栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > Web开发 > JavaScript

基于jquery实现智能提示控件intellSeach.js

JavaScript 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

基于jquery实现智能提示控件intellSeach.js

一、需求

  我们经常会遇到【站内搜索】的需求,为了提高用户体验,我们希望能做到像百度那样的即时智能提示。例如:某公司人事管理系统,想搜索李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代码


;(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:{
 
 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)
     
    
    window.intellObj = window.intellObj || {}; 
    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 > 0){
     jCurItem.click();
   }else{
     setIntellObj(null);    
     if(_event.enterKeydown){
_event.enterKeydown({"jthis":jthis,"event":e});
     }
   }
   jthis.blur();
 }else if(jItems.length > 0){
   if(code === 38){
     if(jCurItem.length <= 0){
jCurItem = jItems.last();
jCurItem.addClass("cur");
keyword = jCurItem.text();
     }else{
var index = jCurItem.index();
jCurItem.removeClass("cur");
if(index <= 0){
  keyword = value;
}else{
  jCurItem = jItems.eq(index-1);
  jCurItem.addClass("cur");
  keyword = jCurItem.text();
}
     }
     jthis.val(keyword);
   }else{
     if(jCurItem.length <= 0){
jCurItem = jItems.first();
jCurItem.addClass("cur");
keyword = jCurItem.text();
     }else{
var index = jCurItem.index();
jCurItem.removeClass("cur");
if(index + 1 >= jItems.length){
  keyword = value;
}else{
  jCurItem = jItems.eq(index+1);
  jCurItem.addClass("cur");
  keyword = jCurItem.text();
}
     }
     jthis.val(keyword);
   }
 }
      }
    }
    
    $.fn.unintell = function(){
      remove();
    }
    $(document).unbind({click:window.intelldocumentClick,keydown:window.intelldocumentKeydown})
   .bind({click:window.intelldocumentClick,keydown:window.intelldocumentKeydown});
    jthis.focus(function(){
      _focusCount++;
      if(_focusCount > 1){
 return;
      }
      if(window.intellObj.jthis && jthis !== window.intellObj.jthis){
 setIntellObj(null);
      }
      var keyword = attrValue();
      if(keyword === _dftOpts.defaultValue){
 keyword = "";
 attrValue(keyword);
      }
      if(keyword || _dftOpts.isEmptyRequest){
 sendRequest();
      }
    })
    jthis.blur(function(){      
      _focusCount = 0;
      if(!attrValue()){
 attrValue(_dftOpts.defaultValue);
      }      
    })
    jthis.keyup(function(e){
      if(e.keyCode === 38 || e.keyCode === 40){
 return;
      }
      var keyword = attrValue();
      if(!keyword){
 remove();
 window.intellObj.value = _value = "";
 return;
      }
      if(keyword !== _value){
 window.intellObj.value = _value = keyword;
 sendRequest();
      }
    });
     
    return initBox();
     
    
    function initBox(){
      attrValue(_dftOpts.defaultValue);
      return jthis;
    }    
    function initIntell(){      
      generate();
      register();
      setIntellObj({jthis:jthis,jResult:jResult});
    }
    function generate(){
      var offset = _dftOpts.aligner.offset();
      var width = _dftOpts.width ? _dftOpts.width : _dftOpts.aligner.width();
      jResult = $("
    ",{"class":"intellResult"}); jResult.width(width).css({"position":"absolute","left":offset.left,"top":offset.top + jthis.outerHeight()}); $("body").append(jResult); if(_dftOpts.maxHeight > 0){ jResult.height(_dftOpts.maxHeight).css("overflowY","scroll"); } } function remove(){ if(jResult){ jResult.remove(); jResult = null; } } function register(){ jResult.on("click","li",function(){ var jItem = $(this); var index = jItem.index(); var keyword = jItem.text(); attrValue(keyword); _value = keyword; if(_event.itemClick){ _event.itemClick({"jthis":jthis,"jItem":jItem,"item":_cache[index]}); } }).on("mouseenter","li",function(){ $(this).siblings("li").removeClass("cur").end().addClass("cur"); }).on("mouseleave","li",function(){ $(this).removeClass("cur"); }); } function setIntellObj(obj){ if(!obj){ if(window.intellObj.jResult){ window.intellObj.jResult.remove(); } window.intellObj.jthis = null; window.intellObj.jResult = null; }else{ window.intellObj.jthis = obj.jthis; window.intellObj.jResult = obj.jResult; } } function sendRequest(){ var data; if(_event.setData){ data = _event.setData({"jthis":jthis}); } $.ajax({ url:_dftOpts.url, data:data, cache:_ajax.cache, timeout:_ajax.timeout, beforeSend:function(xhr){ if(_event.beforeSend){ _event.beforeSend(xhr); } }, success:function(data){ remove(); showData(data); }, error:null }); } function showData(data){ data = $.trim(data) ? $.parseJSON(data) : data; if(_event.beforeRender){ var rs = _event.beforeRender({"jthis":jthis,"data":data}); if(rs === false){ return; } if(rs !== undefined){ data = rs; } } if(!data){ return; } var jItem,jA,jSpan,hasProp,item,text,otherTexts,isRender,index; var list = $.isArray(data) ? data: [data]; var length = list.length; length = length > _dftOpts.itemNumber ? _dftOpts.itemNumber : list.length; if(length <= 0){ return; } initIntell(); _cache.length = 0; hasProp = list[0][_dftOpts.property]; for(var i=0;i",{"class":"intellResult_item"}); jA = $("",{"title":text}).appendTo(jItem); jSpan = $("").appendTo(jA); index = text.toLowerCase().indexOf(_value.toLowerCase()); otherTexts = splitText(text,_value,index); if(otherTexts){ jSpan.text(text.substr(index,_value.length)); if(otherTexts.length > 1){ $("",{"text":otherTexts[0]}).insertBefore(jSpan); $("",{"text":otherTexts[1]}).insertAfter(jSpan); }else{ if(index === 0){ $("",{"text":otherTexts[0]}).insertAfter(jSpan); }else{ $("",{"text":otherTexts[0]}).insertBefore(jSpan); } } }else{ jSpan.text(text); } isRender = true; if(_event.itemBeforeRender){ isRender = _event.itemBeforeRender({"jthis":jthis,"jItem":jItem,"item":item}); } if(isRender !== false){ jResult.append(jItem); if(_event.itemAfterRender){ _event.itemAfterRender({"jthis":jthis,"jItem":jItem,"item":item}); } } _cache.push(item); } if(_event.endRender){ _event.endRender({"jthis":jthis}); } jResult.show(); } function attrValue(value){ if(!value && value != ""){ return $.trim(jthis.val()); } jthis.val(value); } function splitText(text,value,index){ var tlength = text.length; var vlength = value.length; if(index === -1){ return null; } if(index === 0){ if(index + vlength >= tlength){ return null; } return [text.substr(index + vlength)]; } if(index + vlength >= tlength){ return [text.substr(0,index)]; } return [text.substr(0,index),text.substr(index + vlength)]; } } })(window,jQuery);

样式

.intellResult{margin:0;padding:0;background:#fff;border:1px solid #b6b6b6;clear:both;z-index:999;display:none;}
.intellResult li{margin:0;padding:0;padding:5px 15px;height:20px;line-height:20px;overflow:hidden;text-overflow:ellipsis;cursor:pointer;white-space:nowrap;}
.intellResult li.cur{background:#E5E0E0;}

以上就是本文的全部内容,希望对大家的学习有所帮助。

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号