JS仿百度搜索自动提示框匹配查询功能
1.添加动态加载css文件不需要引入csscss全部在JS动态生成。
2.不需要额外的标签只需要一个input输入框并且默认指定一个class类名为"inputElem"当然也可以自己配置参数还需要一个当前父级容器增加一个默认类名parentCls(也可以自己配置),因为输入框匹配值后需要一个隐藏域所以需要隐藏域增加一个class"hiddenCls"当然也支持自己配置参数。
如下代码:
<divclass="parentCls">
<divstyle="width:200px;height:26px;border:1pxsolid#ccc;">
<inputtype="text"class="inputElem"style="width:200px;height:26px;line-height:26px;"/>
</div>
<inputtype="hidden"class="hiddenCls"/>
</div>
<divclass="parentCls">
<divstyle="width:200px;height:26px;border:1pxsolid#ccc;">
<inputtype="text"class="inputElem"style="width:200px;height:26px;line-height:26px;"/>
</div>
<inputtype="hidden"class="hiddenCls"/>
</div>
3.支持页面上有多个输入框。
4.支持鼠标点击和键盘上移和下移键操作类似于百度输入框。
页面上所有的标签都是动态的生成的,不需要额外的标签。如上面的只需要input标签其他的div标签不依赖只需要父级元素增加class"parentCls"(当然可以自己配置类名),
及要传给后台开发人员的隐藏域输入框增加一个class"hiddenCls"当然也可以自动配置参数。
我的模糊查询匹配的需求是这样的:
1.每keyup时候点击或者键盘上移下移操作输入框填充用户名/工号隐藏域填充工号发请求服务器返回数据渲染出来。当然隐藏域填充工号值是form表单提交时候后台要拿到提交过来的工号所以需要这么一个隐藏域。
2.当用户直接在输入框输入值时候并没有键盘上移下移或者点击下拉框某一项时候当鼠标失去焦点时候(blur)当前输入框值为空隐藏域值为空,这样做的目的是为了防止上次form提交过后的数据仍然保存在隐藏域里面当用户重新输入的时候用户也并没有操作键盘上下移操作或者点击操作再点击提交按钮时(失去焦点),那么值为空隐藏域值为空这样防止搜索出来不是用户输入的那个东东。
3.当用户点击某一项时候或者上移下移时候输入框动态的生成值且输入框值现在不能重新输入只有当点击输入框x的时候才可以重新输入。
4.已经遗留输入框可以多选的接口目前还未完善输入框多选的操作。
5.禁止ctrl+v或者右键粘贴操作。
下面HTML代码如下:
<divclass="parentCls">
<divstyle="width:200px;height:26px;border:1pxsolid#ccc;">
<inputtype="text"class="inputElem"style="width:200px;height:26px;line-height:26px;"/>
</div>
<inputtype="hidden"class="hiddenCls"/>
</div>
<divclass="parentCls">
<divstyle="width:200px;height:26px;border:1pxsolid#ccc;">
<inputtype="text"class="inputElem"style="width:200px;height:26px;line-height:26px;"/>
</div>
<inputtype="hidden"class="hiddenCls"/>
</div>
<inputtype="button"value="提交"/>
JS代码如下:
functionAutoComplete(options){ this.cache={ //鼠标点击输入框时候 //阻止form表单默认enter键提交 //点击文档 vartagCls=_config.targetCls.replace(/^\./,""); if(attr.length>0||$(target,tagParent).hasClass(tagCls)){ //如果请求成功后返回了数据(根据元素的长度来判断)执行以下操作 varplen=$(".auto-tipsp",targetParent).length, //上移操作 varpCls=$(_config.targetCls,targetParent).closest(_config.parentCls); self._createDiv(targetParent,curAttr); }elseif(keyCode==40){//下移操作 !$(".auto-tips.p-index"+_cache.currentIndex,targetParent).hasClass(_config.hoverBg)&& varpCls=$(_config.targetCls,targetParent).closest(_config.parentCls); //假如返回的数据如下: for(vari=0,ilen=ret.length;i<ilen;i+=1){ _config.renderHTMLCallback&&$.isFunction(_config.renderHTMLCallback)&&_config.renderHTMLCallback(); //出现滚动条计算p的长度*一项p的高度是否大于设置的高度如是的话出现滚动条反之 if(_config.height>0){ //hover !$(_config.targetCls,targetParent).hasClass("hidden")&&$(_config.targetCls,targetParent).addClass("hidden"); //鼠标移上效果 vartargetInput=$(_config.targetCls,targetParent); if(id&&(id=id.replace("#",""))){ //仅添加一次,不重复添加
/**
*JS模糊查询
*@authortugenhua
*@date2013-11-19
*@param1.当前的inputaddtargetCls
*2.隐藏域里面统一增加同类名叫hiddenCls
*3.在各个父级元素上添加类名parentCls
*/
this.config={
targetCls :".inputElem", //输入框目标元素
parentCls :".parentCls", //父级类
hiddenCls :".hiddenCls", //隐藏域input
searchForm :".jqtransformdone", //form表单
hoverBg :"hoverBg", //鼠标移上去的背景
outBg :"outBg", //鼠标移下拉的背景
isSelectHide :true, //点击下拉框是否隐藏
url :"", //url接口
height :0, //默认为0不设置的话那么高度自适应
manySelect :false, //输入框是否多选默认false单选
renderHTMLCallback:null, //keyup时渲染数据后的回调函数
callback :null, //点击某一项提供回调
closedCallback :null //点击输入框某一项x按钮时回调函数
};
currentIndex :-1,
oldIndex :-1,
inputArrs :[] //多选时候输入框值放到数组里面去
};
this.init(options);
}
AutoComplete.prototype={
constructor:AutoComplete,
init:function(options){
this.config=$.extend(this.config,options||{});
varself=this,
_config=self.config,
_cache=self.cache;
$(_config.targetCls).each(function(index,item){
/*
* 禁止ctrl+v和黏贴事件
*/
$(item).unbind("paste");
$(item).bind("paste",function(e){
e.preventDefault();
vartarget=e.target,
targetParent=$(target).closest(_config.parentCls);
$(this).val("");
$(_config.hiddenCls,targetParent)&&$(_config.hiddenCls,targetParent).val("");
});
$(item).keyup(function(e){
_cache.inputArrs=[];
vartargetVal=$.trim($(this).val()),
keyCode=e.keyCode,
elemHeight=$(this).outerHeight(),
elemWidth=$(this).outerWidth();
//如果输入框值为空的话那么隐藏域的value清空掉
if(targetVal==""){
varcurParents=$(this).closest(_config.parentCls);
$(_config.hiddenCls,curParents).val("");
}
vartargetParent=$(this).parent();
$(targetParent).css({"position":"relative"});
if($(".auto-tips",targetParent).length==0){
//初始化时候动态创建下拉框容器
$(targetParent).append($("<divclass="auto-tipshidden"></div>"));
$(".auto-tips",targetParent).css({"position":"absolute","top":elemHeight,"left":"0px","z-index":999,"width":elemWidth,"border":"1pxsolid#ccc"});
}
varcurIndex=self._keyCode(keyCode);
if(curIndex>-1){
self._keyUpAndDown(targetVal,e,targetParent);
}else{
if(targetVal!=""){
self._doPostAction(targetVal,targetParent);
}
}
});
//失去焦点时如果没有点击或者上下移时候直接输入那么当前输入框值情况隐藏域值情况
$(item).blur(function(e){
vartarget=e.target,
targetParent=$(target).closest(_config.parentCls);
if($(this).attr("up")||$(this).attr("down")){
return;
}else{
$(this).val("");
$(_config.hiddenCls,targetParent).val("");
}
});
});
$(_config.searchForm).each(function(index,item){
$(item).keydown(function(e){
varkeyCode=e.keyCode;
if(keyCode==13){
returnfalse;
}
});
});
$(document).click(function(e){
e.stopPropagation();
vartarget=e.target,
tagParent=$(target).parent(),
attr=$(target,tagParent).closest(".auto-tips");
return;
}else{
$(".auto-tips").each(function(index,item){
!$(item,tagParent).hasClass("hidden")&&$(item,tagParent).addClass("hidden");
});
}
});
varstylesheet=".auto-tips{margin:01px;list-style:none;height:auto!important;padding:0px;position:absolute;border:1pxsolid#ccc;top:27px;left:0;z-index:999;width:100%;background:#fff!important;}"+
".auto-tipsp{overflow:hidden;margin:1px0;padding:5px5px;border-bottom:1pxsolid#e7e7e7;color:#666;text-decoration:none;line-height:23px;white-space:nowrap;cursor:pointer;zoom:1;}"+
".auto-tipspimg{vertical-align:middle;float:left;}"+
".create-input{line-height:26px,padding-left:3px;}"+
".create-inputspan{margin-top:1px;height:24px;float:left;}"+
".create-inputspani,.auto-tipsspana{font-style:normal;float:left;cursor:default;}"+
".create-inputspana{padding:08px03px;cursor:pointer;}"+
".auto-tipsp.hoverBg{background-color:#669cb6;color:#fff;cursor:pointer;}"+
".hidden{display:none;}";
this._addStyleSheet(stylesheet);
},
/**
*键盘上下键操作
*/
_keyUpAndDown:function(targetVal,e,targetParent){
varself=this,
_cache=self.cache,
_config=self.config;
if($(".auto-tipsp",targetParent)&&$(".auto-tipsp",targetParent).length>0){
keyCode=e.keyCode;
_cache.oldIndex=_cache.currentIndex;
if(keyCode==38){
if(_cache.currentIndex==-1){
_cache.currentIndex=plen-1;
}else{
_cache.currentIndex=_cache.currentIndex-1;
if(_cache.currentIndex<0){
_cache.currentIndex=plen-1;
}
}
if(_cache.currentIndex!==-1){
!$(".auto-tips.p-index"+_cache.currentIndex,targetParent).hasClass(_config.hoverBg)&&
$(".auto-tips.p-index"+_cache.currentIndex,targetParent).addClass(_config.hoverBg).siblings().removeClass(_config.hoverBg);
varcurAttr=$(".auto-tips.p-index"+_cache.currentIndex,targetParent).attr("data-html"),
embId=$(".auto-tips.p-index"+_cache.currentIndex,targetParent).attr("embId");
//判断是否是多选操作多选操作暂留接口
if(_config.manySelect){
_cache.inputArrs.push(curAttr);
_cache.inputArrs=self._unique(_cache.inputArrs);
self._manySelect(targetParent);
}else{
$(_config.targetCls,targetParent).val(curAttr);
//上移操作增加一个属性当失去焦点时候判断有没有这个属性
if(!$(_config.targetCls,targetParent).attr("up")){
$(_config.targetCls,targetParent).attr("up","true");
}
$(_config.hiddenCls,pCls).val(embId);
self._closed(targetParent);
//hover
self._hover(targetParent);
}
}
if(_cache.currentIndex==plen-1){
_cache.currentIndex=0;
}else{
_cache.currentIndex++;
if(_cache.currentIndex>plen-1){
_cache.currentIndex=0;
}
}
if(_cache.currentIndex!==-1){
$(".auto-tips.p-index"+_cache.currentIndex,targetParent).addClass(_config.hoverBg).siblings().removeClass(_config.hoverBg);
varcurAttr=$(".auto-tips.p-index"+_cache.currentIndex,targetParent).attr("data-html"),
embId=$(".auto-tips.p-index"+_cache.currentIndex,targetParent).attr("embId");
//判断是否是多选操作多选操作暂留接口
if(_config.manySelect){
_cache.inputArrs.push(curAttr);
_cache.inputArrs=self._unique(_cache.inputArrs);
self._manySelect(targetParent);
}else{
$(_config.targetCls,targetParent).val(curAttr);
//下移操作增加一个属性当失去焦点时候判断有没有这个属性
if(!$(_config.targetCls,targetParent).attr("down")){
$(_config.targetCls,targetParent).attr("down","true");
}
$(_config.hiddenCls,pCls).val(embId);
self._createDiv(targetParent,curAttr);
self._closed(targetParent);
//hover
self._hover(targetParent);
}
}
}elseif(keyCode==13){//回车操作
varcurVal=$(".auto-tips.p-index"+_cache.oldIndex,targetParent).attr("data-html");
$(_config.targetCls,targetParent).val(curVal);
if(_config.isSelectHide){
!$(".auto-tips",targetParent).hasClass("hidden")&&$(".auto-tips",targetParent).addClass("hidden");
}
_cache.currentIndex=-1;
_cache.oldIndex=-1;
}
}
},
//键码判断
_keyCode:function(code){
vararrs=["17","18","38","40","37","39","33","34","35","46","36","13","45","44","145","19","20","9"];
for(vari=0,ilen=arrs.length;i<ilen;i++){
if(code==arrs[i]){
returni;
}
}
return-1;
},
_doPostAction:function(targetVal,targetParent){
var self=this,
_cache=self.cache,
_config=self.config,
url=_config.url;
varresults=[{lastName:"tugenhua",emplId:"E0987",image:""},{lastName:"tugenhua",emplId:"E0988",image:""},{lastName:"tugenhua",emplId:"E0989",image:""}];
self._renderHTML(results,targetParent);
self._executeClick(results,targetParent);
/**$.get(url+"?keyword="+targetVal+"×tamp="+newDate().getTime(),function(data){
varret=$.parseJSON(data.content),
results=ret.results;
if(results.length>0){
self._renderHTML(results,targetParent);
self._executeClick(results,targetParent);
}else{
!$(".auto-tips",targetParent).hasClass("hidden")&&$(".auto-tips",targetParent).addClass("hidden");
$(".auto-tips",targetParent).html("");
}
});**/
},
_renderHTML:function(ret,targetParent){
varself=this,
_config=self.config,
_cache=self.cache,
html="";
html+="<p data-html=""+ret[i].lastName+"("+ret[i].emplId+")"embId=""+ret[i].emplId+""class="p-index"+i+"">"+
"<imgsrc=""+ret[i].image+""style="margin-right:5px;"height="25"width="25"title=""alt="">"+
"<span>"+ret[i].lastName+"("+ret[i].emplId+")</span>"+
"</p>";
}
//渲染值到下拉框里面去
$(".auto-tips",targetParent).html(html);
$(".auto-tips",targetParent).hasClass("hidden")&&$(".auto-tips",targetParent).removeClass("hidden");
$(".auto-tipsp:last",targetParent).css({"border-bottom":"none"});
varplen=$(".auto-tipsp",targetParent).length,
pheight=$(".auto-tipsp",targetParent).height();
if(plen*pheight>_config.height){
$(".auto-tips",targetParent).css({"height":_config.height,"overflow":"auto"});
}else{
$(".auto-tips",targetParent).css({"height":"auto","overflow":"auto"});
}
}
},
/**
*当数据相同的时点击对应的项时返回数据
*/
_executeClick:function(ret,targetParent){
varself=this,
_config=self.config,
_cache=self.cache;
$(".auto-tipsp",targetParent).unbind("click");
$(".auto-tipsp",targetParent).bind("click",function(e){
vardataAttr=$(this).attr("data-html"),
embId=$(this).attr("embId");
//判断是否多选
if(_config.manySelect){
_cache.inputArrs.push(dataAttr);
_cache.inputArrs=self._unique(_cache.inputArrs);
self._manySelect(targetParent);
}else{
$(_config.targetCls,targetParent).val(dataAttr);
varparentCls=$(_config.targetCls,targetParent).closest(_config.parentCls),
hiddenCls=$(_config.hiddenCls,parentCls);
$(hiddenCls).val(embId);
self._createDiv(targetParent,dataAttr);
self._hover(targetParent);
}
self._closed(targetParent);
if(_config.isSelectHide){
!$(".auto-tips",targetParent).hasClass("hidden")&&$(".auto-tips",targetParent).addClass("hidden");
}
_config.callback&&$.isFunction(_config.callback)&&_config.callback();
});
$(".auto-tipsp",targetParent).hover(function(e){
!$(this,targetParent).hasClass(_config.hoverBg)&&
$(this,targetParent).addClass(_config.hoverBg).siblings().removeClass(_config.hoverBg);
});
},
_hover:function(targetParent){
$(".create-inputspan",targetParent).hover(function(){
$(this).css({"background":"#ccc","padding-left":"0px"});
},function(){
$(this).css({"background":""});
});
},
//动态的创建div标签遮住input输入框
_createDiv:function(targetParent,dataAttr){
varself=this,
_config=self.config;
variscreate=$(".create-input",targetParent);
//确保只创建一次div
if(iscreate.length>0){
$(".create-input",targetParent).remove();
}
$(targetParent).prepend($("<divclass="create-input"><span><i></i></span></div>"));
$(".create-inputspani",targetParent).html(dataAttr);
$(_config.targetCls,targetParent).val(dataAttr);
$(".create-inputspan",targetParent).append("<aclass="alink">X</a>");
$(".alink",targetParent).css({"float":"left","background":"none"});
},
//X关闭事件
_closed:function(targetParent){
varself=this,
_config=self.config;
/*
*点击X关闭按钮
*判断当前输入框有没有up和down属性有的话删除掉否则什么都不做
*/
$(".alink",targetParent).click(function(){
$(".create-input",targetParent)&&$(".create-input",targetParent).remove();
$(_config.targetCls,targetParent)&&$(_config.targetCls,targetParent).hasClass("hidden")&&
$(_config.targetCls,targetParent).removeClass("hidden");
$(_config.targetCls,targetParent).val("");
//清空隐藏域的值
varcurParent=$(_config.targetCls,targetParent).closest(_config.parentCls);
$(_config.hiddenCls,curParent).val("");
if($(targetInput).attr("up")||$(targetInput).attr("down")){
$(targetInput).attr("up")&&$(targetInput).removeAttr("up");
$(targetInput).attr("down")&&$(targetInput).removeAttr("down");
}
_config.closedCallback&&$.isFunction(_config.closedCallback)&&_config.closedCallback();
});
},
/*
*数组去重复
*/
_unique:function(arrs){
varobj={},
newArrs=[];
for(vari=0,ilen=arrs.length;i<ilen;i++){
if(obj[arrs[i]]!=1){
newArrs.push(arrs[i]);
obj[arrs[i]]=1;
}
}
returnnewArrs;
},
/*
*输入框多选操作
*/
_manySelect:function(targetParent){
varself=this,
_config=self.config,
_cache=self.cache;
if(_cache.inputArrs.length>0){
$(_config.targetCls,targetParent).val(_cache.inputArrs.join(","));
}
},
/*
*判断是否是string
*/
_isString:function(str){
returnObject.prototype.toString.apply(str)==="[objectString]";
},
/*
*JS动态添加css样式
*/
_addStyleSheet:function(refWin,cssText,id){
varself=this;
if(self._isString(refWin)){
id=cssText;
cssText=refWin;
refWin=window;
}
refWin=$(refWin);
vardoc=document;
varelem;
elem=$("#"+id,doc);
}
if(elem){
return;
}
//elem=$("<style></style>");不能这样创建IE8有bug
elem= document.createElement("style");
//先添加到DOM树中,再给cssText赋值,否则csshack会失效
$("head",doc).append(elem);
if(elem.styleSheet){//IE
elem.styleSheet.cssText=cssText;
}else{//W3C
elem.appendChild(doc.createTextNode(cssText));
}
},
/*
*销毁操作释放内存
*/
destory:function(){
varself=this,
_config=self.config,
_cache=self.cache;
_cache.ret =[];
_cache.currentIndex=0;
_cache.oldIndex=0;
_cache.inputArrs=[];
_config.targetCls=null;
}
};
//初始化
$(function(){
varauto=newAutoComplete({
//url:"/rocky/commonservice/user/find.json"
});
});相关文章