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 相关文章推荐
Javascript this指针
Jul 30 Javascript
js检测用户输入密码强度
Oct 22 Javascript
JS实现浏览器状态栏文字闪烁效果的方法
Oct 27 Javascript
第九章之路径分页标签与徽章组件
Apr 25 Javascript
jQuery侧边栏实现代码
May 06 Javascript
express文件上传中间件Multer详解
Oct 24 Javascript
Bootstrap基本插件学习笔记之折叠(22)
Dec 08 Javascript
js实现登录验证码
Dec 22 Javascript
angularjs实现下拉列表的选中事件示例
Mar 03 Javascript
ztree简介_动力节点Java学院整理
Jul 19 Javascript
vue嵌套路由与404重定向实现方法分析
May 04 Javascript
Angular ElementRef简介及其使用
Oct 01 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 404错误页面实现代码
2009/06/22 PHP
php实现图形显示Ip地址的代码及注释
2014/01/20 PHP
ThinkPHP3.2.2的插件控制器功能简述
2014/07/09 PHP
php常用hash加密函数
2014/11/22 PHP
PHP魔术方法__GET、__SET使用实例
2014/11/25 PHP
PHP安全上传图片的方法
2015/03/21 PHP
使用PHP下载CSS文件中的所有图片【几行代码即可实现】
2016/12/14 PHP
JavaScript方法和技巧大全
2006/12/27 Javascript
Colortip基于jquery的信息提示框插件在IE6下面的显示问题修正方法
2010/12/06 Javascript
Js 回车换行处理的办法及replace方法应用
2013/01/24 Javascript
jQuery创建DOM元素实例解析
2015/01/19 Javascript
详解javascript中的事件处理
2015/11/06 Javascript
总结JavaScript中布尔操作符||与&amp;&amp;的使用技巧
2015/11/17 Javascript
全面解析jQuery $(document).ready()和JavaScript onload事件
2016/06/08 Javascript
js实现一个简单的数字时钟效果
2017/03/29 Javascript
简单谈谈js的数据类型
2017/09/25 Javascript
jquery+css3实现熊猫tv导航代码分享
2018/02/12 jQuery
vue+iview 兼容IE11浏览器的实现方法
2019/01/07 Javascript
[09:13]2014DOTA2国际邀请赛 中国区预选赛coser表演
2014/05/23 DOTA
Python通过PIL获取图片主要颜色并和颜色库进行对比的方法
2015/03/19 Python
Python线性回归实战分析
2018/02/01 Python
详谈套接字中SO_REUSEPORT和SO_REUSEADDR的区别
2018/04/28 Python
Python采集代理ip并判断是否可用和定时更新的方法
2018/05/07 Python
django2+uwsgi+nginx上线部署到服务器Ubuntu16.04
2018/06/26 Python
基于Python打造账号共享浏览器功能
2019/05/30 Python
Python音频操作工具PyAudio上手教程详解
2019/06/26 Python
欧洲顶级的童装奢侈品购物网站:Bambini Fashion(面向全球)
2018/04/24 全球购物
荷兰浴室和卫浴网上商店:Badkamerxxl.nl
2020/10/06 全球购物
体育比赛口号
2014/06/09 职场文书
政风行风整改方案
2014/10/25 职场文书
2016廉洁教育心得体会
2016/01/20 职场文书
三下乡活动心得体会
2016/01/23 职场文书
思想品德课教学反思
2016/02/24 职场文书
导游词之青城山景区
2019/09/27 职场文书
vue实现简单数据双向绑定
2021/04/28 Vue.js
MySQL池化框架学习接池自定义
2022/07/23 MySQL