jQuery Autocomplete自动完成插件


Posted in Javascript onJuly 17, 2010

相对于同类插件,他的特色有3点。
1、可缓存查询结果 (二次查询速度快)
2、非keyup监听方式 (解决某些系统/情况下无法触发keyxxx事件的问题)
3、简洁的参数 (好看?)

插件性能尚好,我的E6500、2G内存,30秒内一共发生了4469次调用,耗时94.65毫秒;百度的是2432次调用,80.24毫秒。

接近1倍的调用是jQuery中的问题,但具体原因我还没弄明白,如果那位兄弟知道的还请不吝赐教。

调用方法

jQuery("#kw").suggest({ 
url:siteConfig.suggestionUrl, 
params:{ 
kw:function(){return jQuery("#kw").val()}, 
n:10 
} 
});

参数url:baseUrl,例如http://www.target.com/search.php
参数params:url的后缀列表,范例中拼合的url为:http://www.target.com/search.php?kw=xxx&n=10&callback=?(默认加入callback)
参数delay:输入间隔时间,主要是为了降低负载,数值越大,负载越低,查询速度越慢。
参数cache:是否实用缓存,默认为true,例如当搜索“test”时,程序会将对应的查询结果缓存,当第二次搜索test时直接从缓存中读取。
参数formId:必须填写,form表单的id
参数callback:是否使用jsonp以便处理跨域问题。
核心代码:
suggest.js
(function($){ 
$.tools = $.tools || {version: '1.0'}; 
$.tools.suggest = {}; 
$.tools.suggest.defaults = { 
url : null, 
params : null, 
delay : 100, 
cache : true, 
formId : '#search_form', 
focus:null, 
callback : true 
} 
$.tools.suggest.borderKey = { 
UP: 38, 
DOWN: 40, 
TAB: 9, 
ESC: 27, 
ENTER:13 
} $.fn.suggest=function(options,fn){ 
var options,key = $.tools.suggest.borderKey; 
if($.isFunction(options)){ 
fn=options; 
options = $.extend({}, $.tools.suggest.defaults, key); 
}else{ 
options = $.extend({}, $.tools.suggest.defaults, key, options); 
} 
return this.each(function(){ 
var 
self = $(this), 
url = options.url, 
params = options.params, 
searchUrl = null, 
searchtimer = 0, 
delay = options.delay, 
cache = options.cache, 
callback = options.callback, 
formobj = $(options.formId), 
focus = options.focus, 
rebox = $('<ul/>').attr("id","suggest"), 
htmlLi = null, 
litop = null, 
lileft = null, 
liwth = null, 
tip = false, 
val = null, 
rlen = null, 
UP = options.UP, 
DOWN = options.DOWN, 
TAB = options.TAB, 
ESC = options.ESC, 
ENTER = options.ENTER, 
index = -1, 
choseKey = null, 
backval = null, 
hidden = false, 
locksuggest = false 

//init 
if(focus){ 
self.focus(); 
searchtimer = setInterval(getKey, delay); 
} 
self.bind("focus",function(){ 
searchtimer = setInterval(getKey, delay); 
// 触发焦点时初始化backval的值 
backval = (backval=$.trim(self.val()))==''?null:backval; 
}) 
.bind("blur",function(){ 
clearInterval(searchtimer); 
searchtimer = 0; 
hideResult(); 
}) 
.bind("keydown",function(e){ 
// 少于10项不使用switch 
if(e.keyCode == UP){ 
clearInterval(searchtimer); 
searchtimer = 0; 
if($('#suggest').css('display') == 'none'){ 
reSet(); 
return false; 
} 
index--; 
if(index<0){ 
index=Math.abs(rlen)-1; 
} 
changeSelect(index); 
e.preventDefault(); 
return false; 
}else if(e.keyCode == DOWN){ 
clearInterval(searchtimer); 
searchtimer = 0; 
if($('#suggest').css('display') == 'none'){ 
reSet(); 
return false; 
} 
index++; 
if(index>=rlen){ 
index=0; 
} 
changeSelect(index); 
e.preventDefault(); 
return false; 
}else if(e.keyCode == TAB){ 
clearInterval(searchtimer); 
searchtimer = 0; 
hideResult(); 
}else if(e.keyCode == ESC){ 
clearInterval(searchtimer); 
searchtimer = 0; 
hideResult(); 
return false; 
}else if(e.keyCode == ENTER){ 
clearInterval(searchtimer); 
searchtimer = 0; 
}else if(searchtimer == 0){ 
searchtimer = setInterval(getKey, delay); 
} 
}); 
// 获取关键词 
function getKey(){ 
val = $.trim(self.val()); 
// 关键词不为空且关键词不重复 
if(!!val && val!=backval){ 
backval = val; 
// 如不需要缓存结果,设cache为false 
if(cache && !!$.tools.suggest[val]){ 
index = -1; 
rlen = $.tools.suggest[val][1]; 
appendSuggest($.tools.suggest[val][0]); 
}else{ 
searchurl = url+'?'+$.param(params); 
getResult(searchurl,function(htmltemp,htmllen){ 
index = -1; 
rlen = htmllen; 
appendSuggest(htmltemp); 
}); 
} 
} 
// 关键词为空 
if(!!!val && !hidden){ 
hideResult(); 
} 
} 
// 获取提示数据 
function getResult(searchurl,fn){ 
if(callback){searchurl = searchurl+'&callback=?';} 
$.getJSON(searchurl,function(data){ 
var htmltemp = '', 
htmllen = 0, 
inputWord = self.val() 
$.each(data.list,function(i,n){ 
if(n.word != inputWord){ 
htmltemp += '<li>'+n.word+'</li>'; 
htmllen++; 
} 
}); 
if(cache && !!!$.tools.suggest[val]){$.tools.suggest[val]=[htmltemp,htmllen];} 
fn.call(document,htmltemp,htmllen) 
}); 
} 
// 插入提示数据 
function appendSuggest(result){ 
locksuggest = hidden = false; 
if(!!result){ 
if(!tip){ 
litop = self.offset().top+self.outerHeight()-1; 
lileft = self.offset().left; 
liwth = self.outerWidth()-2; 
rebox.css({'position':'absolute','top':litop,'left':lileft,'width':liwth}).html(result).appendTo('body').show(); 
tip = true; 
}else{ 
rebox.html(result).show(); 
} 
rebox.find('li').bind('mouseover',function(){ 
// 锁定提示层,保证不因冒泡关闭提示层 
locksuggest = true; 
index = $(this).index(); 
changeSelect(index,false); 
}) 
.bind('click',function(){ 
changeSelect(index); 
searchSubmit(); 
}); 
rebox.bind('mouseout',function(){ 
locksuggest = false; 
}) 
}else{ 
// 如果检索结果为空,清空提示层 
rebox.hide(); 
} 
} 
function changeSelect(index,v){ 
v=v==false?false:true; 
var obj = rebox.find('li').eq(index); 
rebox.find('li.mo').removeClass('mo'); 
obj.addClass("mo"); 
if(v){ 
choseKey = backval = obj.html(); 
self.val(choseKey); 
} 
} 
function reSet(){ 
if(!!self.val()){ 
index = -1; 
$('#suggest').css('display','block'); 
rebox.find('li.mo').removeClass('mo'); 
// 根据html结构重新计算提示结果长度 
rlen = rebox.find('li').size(); 
} 
} 
function hideResult(){ 
if(!locksuggest){ 
choseKey = backval = null; 
hidden = true; 
rebox.hide(); 
} 
} 
function searchSubmit(){ 
self.val(choseKey); 
hideResult(); 
clearInterval(searchtimer); 
formobj.submit(); 
} 
}); 
} 
})(jQuery);

代码打包下载
Javascript 相关文章推荐
静态图片的十一种滤镜效果--不支持Ie7及非IE浏览器。
Mar 06 Javascript
javascript Firefox与IE 替换节点的方法
Feb 24 Javascript
javascript XMLHttpRequest对象全面剖析
Apr 24 Javascript
js实现的跟随鼠标移动的时钟效果(中英文日期显示)
Jan 17 Javascript
IE6下focus与blur错乱的解决方案
Jul 31 Javascript
Javascript中拼接大量字符串的方法
Feb 05 Javascript
JS判断页面是否出现滚动条的方法
Jul 17 Javascript
Vue.js表单标签中的单选按钮、复选按钮和下拉列表的取值问题
Nov 22 Javascript
React中常见的动画实现的几种方式
Jan 10 Javascript
js 图片转base64的方式(两种)
Apr 24 Javascript
Vue CLI3搭建的项目中路径相关问题的解决
Sep 17 Javascript
JS 图片压缩原理与实现方法详解
Apr 29 Javascript
一个js拖拽的效果类和dom-drag.js浅析
Jul 17 #Javascript
JavaScript 浏览器验证代码(来自discuz)
Jul 17 #Javascript
IE6,IE7下js动态加载图片不显示错误
Jul 17 #Javascript
js模拟类继承小例子
Jul 17 #Javascript
javascript 循环读取JSON数据的代码
Jul 17 #Javascript
一个可绑定数据源的jQuery数据表格插件
Jul 17 #Javascript
js跨域问题之跨域iframe自适应大小实现代码
Jul 17 #Javascript
You might like
支付宝接口开发集成支付环境小结
2015/03/17 PHP
discuz图片顺序混乱解决方案
2015/07/29 PHP
Iframe thickbox2.0使用的方法
2009/03/05 Javascript
JQuery 入门实例1
2009/06/25 Javascript
jQueryUI写一个调整分类的拖放效果实现代码
2012/05/10 Javascript
javascript测试题练习代码
2012/10/10 Javascript
JS测试显示屏分辨率以及屏幕尺寸的方法
2013/11/22 Javascript
JQuery的$和其它JS发生冲突的快速解决方法
2014/01/24 Javascript
Javascript学习笔记之 函数篇(二) : this 的工作机制
2014/06/24 Javascript
实例详解jQuery结合GridView控件的使用方法
2016/01/04 Javascript
Bootstrap4一次重大更新 几乎涉及每行代码
2016/05/16 Javascript
基于CSS3和jQuery实现跟随鼠标方位的Hover特效
2016/07/25 Javascript
jQuery之动画ajax事件(实例讲解)
2017/07/18 jQuery
以BootStrap Tab为例写一个前端组件
2017/07/25 Javascript
jq源码解析之绑在$,jQuery上面的方法(实例讲解)
2017/10/13 jQuery
微信小程序HTTP接口请求封装代码实例
2019/09/05 Javascript
前端深入理解Typescript泛型概念
2020/03/09 Javascript
将图片文件嵌入到wxpython代码中的实现方法
2014/08/11 Python
python3.x实现发送邮件功能
2018/05/22 Python
python统计多维数组的行数和列数实例
2018/06/23 Python
Python2与Python3的区别实例总结
2019/04/17 Python
Python SELENIUM上传文件或图片实现过程
2019/10/28 Python
Python绘制三角函数图(sin\cos\tan)并标注特定范围的例子
2019/12/04 Python
python实现高斯投影正反算方式
2020/01/17 Python
Python流程控制常用工具详解
2020/02/24 Python
python GUI库图形界面开发之PyQt5窗口类QMainWindow详细使用方法
2020/02/26 Python
Python实现一个简单的毕业生信息管理系统的示例代码
2020/06/08 Python
python爬取代理IP并进行有效的IP测试实现
2020/10/09 Python
如何用python爬取微博热搜数据并保存
2021/02/20 Python
HTML5之SVG 2D入门8—文档结构及相关元素总结
2013/01/30 HTML / CSS
Wolford法国官网:奥地利奢侈内衣品牌
2020/08/11 全球购物
考察现实表现材料
2014/05/19 职场文书
计划生育证明格式范本
2014/09/12 职场文书
幼儿园校车安全责任书
2015/05/08 职场文书
关于分班的感言
2015/08/04 职场文书
openstack中的rpc远程调用的方法
2021/07/09 Python