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 相关文章推荐
js之ActiveX控件使用说明 new ActiveXObject()
Mar 03 Javascript
推荐一款jQuery插件模板
Jan 09 Javascript
JavaScript 基本概念
Jan 20 Javascript
jquery解析json格式数据的方法(对象、字符串)
Nov 24 Javascript
简述jQuery ajax的执行顺序
Jan 05 Javascript
APP中javascript+css3实现下拉刷新效果
Jan 27 Javascript
jQuery dataTables与jQuery UI 对话框dialog的使用教程
Sep 02 Javascript
JS实现表单验证功能(验证手机号是否存在,验证码倒计时)
Oct 11 Javascript
JavaScript实现微信红包算法及问题解决方法
Apr 26 Javascript
vue+eslint+vscode配置教程
Aug 09 Javascript
解决Antd Table表头加Icon和气泡提示的坑
Nov 17 Javascript
基于vuex实现购物车功能
Jan 10 Vue.js
一个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和MySQL保存和输出图片
2006/10/09 PHP
PHP has encountered an Access Violation at 7C94BD02解决方法
2009/08/24 PHP
PHP中使用break跳出多重循环代码实例
2015/01/21 PHP
Thinkphp3.2简单解决多文件上传只上传一张的问题
2017/09/26 PHP
对于Laravel 5.5核心架构的深入理解
2018/02/22 PHP
php设计模式之观察者模式实例详解【星际争霸游戏案例】
2020/03/30 PHP
JavaScript 数组详解
2013/10/10 Javascript
引用其它js时如何同时处理多个window.onload事件
2014/09/02 Javascript
jQuery控制网页打印指定区域的方法
2015/04/07 Javascript
JS实现获取键盘按下的按键并显示在页面上的方法
2015/11/04 Javascript
jquery.cookie实现的客户端购物车操作实例
2015/12/24 Javascript
js拼接html字符串的注意事项
2016/10/13 Javascript
weUI应用之JS常用信息提示弹层的封装
2016/11/21 Javascript
canvas实现图像截取功能
2017/02/06 Javascript
Vue axios 中提交表单数据(含上传文件)
2017/07/06 Javascript
JS中正则表达式要注意lastIndex属性
2017/08/08 Javascript
理解nodejs的stream和pipe机制的原理和实现
2017/08/12 NodeJs
使用wxapp-img-loader自定义组件实现微信小程序图片预加载功能
2018/10/18 Javascript
vue+iview动态渲染表格详解
2019/03/19 Javascript
Javascript作用域和作用域链原理解析
2020/03/03 Javascript
在react中使用vue的状态管理的方法示例
2020/05/02 Javascript
uni-app微信小程序登录授权的实现
2020/05/22 Javascript
vue使用video插件vue-video-player详解
2020/10/23 Javascript
[13:38]2015国际邀请赛中国战队出征仪式
2015/05/29 DOTA
python多线程调用exit无法退出的解决方法
2019/02/18 Python
HTML5的结构和语义(5):内嵌媒体
2008/10/17 HTML / CSS
Nike西班牙官方网站:Nike.com (ES)
2017/10/30 全球购物
ETO男装官方网店:ETO Jeans
2019/02/28 全球购物
五好党支部事迹材料
2014/02/06 职场文书
岗位职责说明书
2014/05/07 职场文书
计算机网络专业求职信
2014/06/05 职场文书
小学五年级语文上册教学计划
2015/01/22 职场文书
煤矿安全生产工作总结
2015/08/13 职场文书
Mysql基础之常见函数
2021/04/22 MySQL
python基于opencv批量生成验证码的示例
2021/04/28 Python
如何用JS实现简单的数据监听
2021/05/06 Javascript