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 相关文章推荐
一段多浏览器的&quot;复制到剪贴板&quot;javascript代码
Mar 27 Javascript
JS解密入门 最终变量劫持
Jun 25 Javascript
flash 得到自身url参数的代码
Nov 15 Javascript
JavaScript写的一个自定义弹出式对话框代码
Jan 17 Javascript
Node.js中安全调用系统命令的方法(避免注入安全漏洞)
Dec 05 Javascript
node.js中的http.createClient方法使用说明
Dec 15 Javascript
Javascript访问器属性实例分析
Dec 30 Javascript
JS数字抽奖游戏实现方法
May 04 Javascript
微信小程序上传文件到阿里OSS教程
May 20 Javascript
详解wepy开发小程序踩过的坑(小结)
May 22 Javascript
JS/CSS实现字符串单词首字母大写功能
Sep 03 Javascript
vue+element导航栏高亮显示的解决方式
Nov 12 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
PHP如何通过传引用的思想实现无限分类(代码简单)
2015/10/13 PHP
PHP翻页跳转功能实现方法
2020/11/30 PHP
PHP递归遍历指定文件夹内的文件实现方法
2016/11/15 PHP
JS获取后台Cookies值的小例子
2013/03/04 Javascript
js实现无需数据库的县级以上联动行政区域下拉控件
2013/08/14 Javascript
javascript无刷新评论实现方法
2015/05/13 Javascript
浅谈javascript的Touch事件
2015/09/27 Javascript
AngularJS中的Directive实现延迟加载
2016/01/25 Javascript
Vue如何实现组件的源码解析
2017/06/08 Javascript
简单谈谈React中的路由系统
2017/07/25 Javascript
AngularJS实现表单元素值绑定操作示例
2017/10/11 Javascript
微信小程序图片轮播组件gallery slider使用方法详解
2018/01/31 Javascript
vue实现评价星星功能
2020/06/30 Javascript
Python中__init__.py文件的作用详解
2016/09/18 Python
浅谈Python 列表字典赋值的陷阱
2019/01/20 Python
Pytorch实现GoogLeNet的方法
2019/08/18 Python
python如果快速判断数字奇数偶数
2019/11/13 Python
Python数据分析pandas模块用法实例详解
2019/11/20 Python
python操作yaml说明
2020/04/08 Python
python实现数字炸弹游戏
2020/07/17 Python
python BeautifulSoup库的安装与使用
2020/12/17 Python
如何利用Python matplotlib绘制雷达图
2020/12/21 Python
一款纯css3实现的颜色渐变按钮的代码教程
2014/11/12 HTML / CSS
英超联赛的首选足球:Mitre足球
2019/05/06 全球购物
网络通讯中,端口有什么含义,端口的取值范围
2012/11/23 面试题
幼师自我鉴定范文
2013/10/01 职场文书
夜大自我鉴定
2013/10/31 职场文书
国贸类专业毕业生的求职信分享
2013/12/08 职场文书
农村结婚典礼司仪主持词
2014/03/14 职场文书
反邪教标语
2014/06/23 职场文书
计划生育证明格式及范本
2014/10/09 职场文书
教师批评与自我批评范文
2014/10/15 职场文书
2015年学校团委工作总结
2015/05/26 职场文书
优质服务心得体会(共4篇)
2016/01/22 职场文书
二年级数学教学反思
2016/02/16 职场文书
vue项目如何打包之项目打包优化(让打包的js文件变小)
2022/04/30 Vue.js