
一、需求
我们经常会遇到【站内搜索】的需求,为了提高用户体验,我们希望能做到像百度那样的即时智能提示。例如:某公司人事管理系统,想搜索李XX,只要输入“李”,系统自然会提示一些姓李的员工,这样方便用户使用。说白了,就是用户边输入,系统会提示相关的结果;或者,当用户点击搜索框时,就推荐一些内容,如360、百度都会提示今天的主要新闻或搜索量大的内容。
jquery 已经有一个这样的插件了,叫 autocomplete, 但我觉得不好用。关于autocomplete的介绍也很多,有兴趣的朋友可以去试试。
看标题就知道,这里只是分享一个插件,不会讨论后台搜索的相关算法和过程,也就是说,后台返回特定格式的数据,控件负责渲染结果呈现。ok,先看一下效果图:
样式与控件无关,只需要一个 input text 就可以了。
二、参数说明
控件以json格式作为传输格式。参数比较多,大部分都有默认值(具体看源码),有些可能不常用,保持默认即可。如下:
url: 请求地址。如:Handler.ashx, 后台获取数据的地址
property: 要显示的json对象的属性。如果我们直接返回[“tom”,”tom cat”,”tom2″] 这样的形式,那么该属性可以不用设置;但有时候我们会返回[{“Name”:”tom”,”ID”:”001″},{“Name”:”tom cat”,”ID”:”002″},{“Name”:”tom2″,”ID”:”003″}] 这样的形式,显示的是Name,那么设置该属性为”Name”即可。至于我们想在点击的时候获得点击的项的ID,通过点击事件即可。
itemNumber: 显示的项数目。
isEmptyRequest: focus时,空白是否发起请求。就像前面说的,如果点击搜索框时(此时没有内容),想要推荐一些内容,设置该属性为true,即会发起请求。
defaultValue: 默认值。通常会是:“请输入关键词…” 这类的提示。
width: 下拉列表宽度。
aligner: 要对齐的元素。
maxHeight: 最大高度。如果设置该高度,超过时就会出现滚动条。
ajax
:{
timeout: 超时时间
cache: 是否缓存
},
event
:{
setData: 发送请求前触发。用于设置参数
itemClick: 点击项触发
enterKeydown: 按下enter键触发
beforeRender: 所有项呈现前触发
endRender: 所有项呈现后触发
itemBeforeRender: 项呈现前触发
itemAfterRender: 项呈现后触发
beforeSend: 发送请求前触发。用户设置请求头部参数等,相当于jquery ajax 的 beforeSend。
}
event 里的方法都会在适当的时候触发,需要注意的是,所有方法都接收一个参数,该参数是一个对象,有4个属性,某些情况如果没有该属性的,则为空。包括如下属性:
jthis: input 的 jQuery 对象。
jItem: 项的 jQuery 对象。
data: 返回的 json 字符串。如果在前台需要对返回 json 再进行处理,那么可以通过 data 属性获得,处理完成后,需要将 json 字符串 return。
event: 事件对象,如按下 enter 时的事件对象。
三、例子
使用例子:
$(“#search”).intellSearch({
url:”Handler.ashx”,
property:”Name”,
itemNumber:5,
isEmptyRequest:false,
defaultValue:”请输入关键字…”,
width:$(“#search”).width() 2,
maxHeight:-1,
event:{
itemClick:function(obj){
alert(obj.item.ID);
},
enterKeydown:function(obj){
if(obj.item){
alert(“有当前项”);
}else{
alert(“没有当前项”);
}
}
}
});
四、总结
如果你还有自己的逻辑需要处理,也支持链式调用,大可以这样写 $(“#search”).intellSearch({参数…}).focus(function(){你的处理…});
分享该插件希望能帮助到有需要的朋友,主要用于学习。由于是v1.0,可能还有一些bug,有发现的朋友也可以告诉我,我会及时修正。
附源代码
js代码
/*搜索智能提示 v1.0
date:2015.09.08
*/
;(function(w,$){
$.fn.intellSearch = function(options){
var jthis = this;
var _dftOpts = {
url:””,//请求地址或数组
property:””,//要显示的json对象的属性
itemNumber:5,//显示的条数
isEmptyRequest:false,//focus空白是否发起请求
defaultValue:””,//默认值
width:0,//列表宽度
aligner:jthis,//要对齐的元素
maxHeight:-1,//最大高度
ajax:{
timeout:3000,//超时时间
cache:true//是否缓存
},
event:{
/*参数说明:parameter:{jthis:”jq input”,jItem:”jq item”,data:”json result”,event:”event”}*/
setData:null,//设置参数
itemClick:null,//点击项触发
enterKeydown:null,//按下enter键触发
beforeRender:null,//所有项呈现前触发
endRender:null,//所有项呈现后触发
itemBeforeRender:null,//项呈现前触发
itemAfterRender:null,//项呈现后触发
beforeSend:null//发送请求前触发
}
};
$.extend(_dftOpts,options);
if(!_dftOpts.url){
throw Error(“url不能为空!”);
}
var jResult;
var _value = “”;
var _ajax = _dftOpts.ajax;
var _event = _dftOpts.event;
var _cache = [];
var _focusCount = 0;//防止focus触发多次(sogou)
/*on window*/
window.intellObj = window.intellObj || {}; /*for global event*/
window.intellDocumentClick = window.intellDocumentClick || function(e){
if(!window.intellObj.jthis){
return;
}
if(e.target !== window.intellObj.jthis[0]){
setIntellObj(null);
}
}
window.intellDocumentKeydown = window.intellDocumentKeydown || function(e){
var jthis = window.intellObj.jthis;
if(!jthis){
return;
}
var code = e.keyCode;
var value = window.intellObj.value;
var jResult,jCurItem,keyword;
if(code === 13 || code === 38 || code === 40){
jResult = window.intellObj.jResult;
jItems = jResult.find(“li”);
jCurItem = jResult.find(“li.cur”);
if(code === 13){
if(jCurItem.length