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 相关文章推荐
Mootools 1.2教程 同时进行多个形变动画
Sep 15 Javascript
几个有趣的Javascript Hack
Jul 24 Javascript
js 判断一个元素是否在页面中存在
Dec 27 Javascript
javascript打印输出json实例
Nov 11 Javascript
按Enter键触发事件的jquery方法实现代码
Feb 17 Javascript
JavaScript利用正则表达式去除日期中的“-”
Jul 01 Javascript
深入学习JavaScript中的Rest参数和参数默认值
Jul 28 Javascript
深入理解事件冒泡(Bubble)和事件捕捉(capture)
May 28 Javascript
浅谈JS读取DOM对象(标签)的自定义属性
Nov 21 Javascript
JavaScript设计模式之工厂模式和抽象工厂模式定义与用法分析
Jul 26 Javascript
Vue props 单向数据流的实现
Nov 06 Javascript
vue中的mescroll搜索运用及各种填坑处理
Oct 30 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之第五天
2006/10/09 PHP
PHP+DBM的同学录程序(4)
2006/10/09 PHP
joomla jce editor 解决上传中文名文件失败问题
2013/06/09 PHP
根据ip调用新浪api获取城市名并转成拼音
2014/03/07 PHP
php单一接口的实现方法
2015/06/20 PHP
SESSION存放在数据库用法实例
2015/08/08 PHP
PHP中快速生成随机密码的几种方式
2017/04/17 PHP
Thinkphp5.0 框架视图view的比较标签用法分析
2019/10/12 PHP
JQuery 学习笔记 选择器之六
2009/07/23 Javascript
Javascript技巧之不要用for in语句对数组进行遍历
2010/10/20 Javascript
jWiard 基于JQuery的强大的向导控件介绍
2011/10/28 Javascript
js实现图片轮换效果代码
2013/04/16 Javascript
ExtJs设置GridPanel表格文本垂直居中示例
2013/07/15 Javascript
Javascript中各种trim的实现详细解析
2013/12/10 Javascript
分享12个非常实用的JavaScript小技巧
2016/05/11 Javascript
Vue封装一个简单轻量的上传文件组件的示例
2018/03/21 Javascript
Mint UI实现A-Z字母排序的城市选择列表
2018/12/28 Javascript
详解如何用webpack4从零开始构建react开发环境
2019/01/27 Javascript
Python类的动态修改的实例方法
2017/03/24 Python
python中requests小技巧
2017/05/10 Python
python在非root权限下的安装方法
2018/01/23 Python
Python测试人员需要掌握的知识
2018/02/08 Python
OpenCV模板匹配matchTemplate的实现
2019/10/18 Python
Python 日期的转换及计算的具体使用详解
2020/01/16 Python
python 操作mysql数据中fetchone()和fetchall()方式
2020/05/15 Python
意大利简约的休闲品牌:Aspesi
2018/02/08 全球购物
一道Delphi面试题
2016/10/28 面试题
汽车专业求职信
2014/06/05 职场文书
幼儿园门卫岗位职责范本
2014/07/02 职场文书
财政局党的群众路线教育实践活动剖析材料
2014/10/13 职场文书
党员检讨书
2014/10/13 职场文书
物业接待员岗位职责
2015/04/15 职场文书
2016年幼儿园教师政治学习心得体会
2016/01/23 职场文书
个人自我鉴定怎么写?
2019/07/01 职场文书
Spark SQL 2.4.8 操作 Dataframe的两种方式
2021/10/16 SQL Server
python opencv将多个图放在一个窗口的实例详解
2022/02/28 Python