实现类似于百度实时搜索将结果在下拉框中显示的功能

本文主要实现一个类似于百度搜索一样,当在输入框中输入内容实时向后台发送请求,并将返回的内容在输入框下面用下拉框的形式显示出来的功能。

由于本人是前端程序员,so,这里只介绍前端实现部分,实现分为HTML,JS两部分(后台对接使用的是PHP):

HTML:

  第一步:封装一个组件用于页面实现

 1 /**
 2      * Print a FilterlistDiv
 3      *
 4      * @param  string $name 表单提交的字段name
 5      * @param  string $value 表单提交的value
 6      * @param  string $searchInputId  输入框id
 7      * @param  string $inputVal  输入框value
 8      * @param  string $filterDivId
 9      * @param  string $class
10      * @param  string $inputPlaceholder
11      * @param  string $searchInputName 需要提交的input的name属性
12      * @access public
13      * @return string
14      */
15      public static function searchFilterInput($name, $value, $searchInputId, $inputVal = '', $class = '', $inputPlaceholder = '', $searchInputName = '')
16      {
17         $html = '';
18         $html .= html::input($name, $value, "class='hidden'");
19         $html .= html::input($searchInputName, $inputVal, "id='{$searchInputId}' placeholder='{$inputPlaceholder}' class='form-control {$class}'");
20         $html .= "<div class='inputFilter'></div>";
21 
22         return $html;
23      }

  第二步:页面调用该组件

1 // 页面调用
2 echo html::searchFilterInput('trader',  '' ,'traderInput', '', '', , );

JS部分:

  第一步:通过扩展jQuery的方式将该方法进行封装,主要包含实时请求事件以及键盘操作事件,该方法根据传入的参数来进行不同的处理,主要处理的参数有:1.url:搜索数据的url;2.getAll:用于标示若输入为空时是否显示所有数据(适用于数据列表少的数据,类似于select下拉框);3.canAdd:用于标识当输入的信息搜索不到时是否允许用户将该信息作为新的数据添加进来。在进行实时请求中,使用setTimeout来进行节流,防止向后台请求频率过多。

  1 +function($, window, document, Math)
  2 {
  3     'use strict';
  4 
  5     var searchFilter = function(element, options)
  6     {
  7         this.$            = $(element);
  8         this.options      = this.getOptions(options);
  9         this.$next        = this.$.next();
 10 
 11         this.init();
 12     };
 13 
 14     searchFilter.prototype.getOptions = function (options)
 15     {
 16         options = $.extend({}, searchFilter.DEFAULTS, this.$.data(), options);
 17         return options;
 18     };
 19 
 20     searchFilter.prototype.init = function()
 21     {
 22         //绑定事件
 23         this.bindEvents();
 24     };
 25 
 26     searchFilter.prototype.bindEvents = function()
 27     {
 28         var $this = this.$,
 29             $next = this.$next,
 30             url   = this.options.url,
 31             getAll= this.options.getAll,
 32             cantFindInfo = this.options.cantFindInfo ? this.options.cantFindInfo : '',
 33             canAdd= this.options.canAdd;
 34 
 35         var focus = function(){
 36             if($next.find('ul li').length > 1)
 37             {
 38                 $next.width($this.width()+20);
 39                 $next.show();
 40             }
 41 
 42             // 通过仓库动态加载货位
 43             if($this.attr('id') == 'shelfInput'){
 44                 var store = $this.parents('#selectPosition').find('#store').val();
 45                 url = createLink('store', 'getShelvesBySearch', 'storeId='+store);
 46             }
 47 
 48             $this.unbind('input propertychange');
 49             $this.bind('input propertychange', change);
 50             if(getAll){
 51                 getListByInput($this.val());
 52             }
 53             else if($this.val() !== '' && $next.find("li").length == 0){
 54                 getListByInput($this.val());
 55             }
 56         }
 57 
 58         var blur = function(){
 59             setTimeout(function(){
 60                 $next.hide();
 61                 $this.prev().val('');
 62                 if($this.val() !== '')
 63                 {
 64                     var lis = $next.find("li");
 65                     for(var i = 0; i < lis.length; i++){
 66                         if($this.val() == lis[i].innerText){
 67                             $this.prev().val($(lis[i]).attr('id'));
 68                             break;
 69                         }
 70                     }
 71                     
 72                     if($this.prev().val() == '' && !canAdd){
 73                         $this.val('');
 74                     }
 75                 }
 76             },200);
 77         }
 78 
 79         var change = function(){
 80             if($this.val() != '' || getAll){
 81                 $next.width($this.width()+20);
 82                 $next.show();
 83                 setTimeout(function(){getListByInput($this.val())}, 300);
 84             }
 85         }
 86 
 87         var keydown = function(){
 88             var key       = event.keyCode,
 89                 searchNum = $next.find("li").length, // 搜索到的相关条数
 90                 li        = $next.find("li.active-item"), // 当前通过键盘选中的是第几条li
 91                 index     = $next.find('li').index(li);
 92 
 93             switch(key)
 94             {
 95                 case 13: // 回车键
 96                     event.preventDefault();
 97                     if(li.attr('id')) {
 98                         selectOptionToInput(li.attr('id'), li.text());
 99                     }
100                     $next.hide();
101                     break;
102                 case 38: // 上键
103                     event.stopPropagation();
104                     event.preventDefault();
105                     if(index >= 0)
106                     {
107                         index--;
108                         if (index == -1){
109                             if(canAdd)  $next.find("li").removeClass('active-item');
110                             else        index = 0; //到顶了
111                         }
112 
113                         // 使选中的焦点永远能看到
114                         var $currLi = $next.find("li:eq(" + index + ")"),
115                             $contanier = $currLi.closest('.inputFilter');
116 
117                         if($currLi.position().top <= 20 )
118                         {
119                             $contanier.scrollTop($contanier.scrollTop() - $currLi.height());
120                         }
121                     }
122 
123                     break;
124                 case 40: // 下键
125                     event.stopPropagation();
126                     event.preventDefault();
127                     $next.show();
128                     index++;
129 
130                     if (index == searchNum) index = searchNum - 1; //到底了
131 
132                     // 使选中的焦点永远能看到
133                     var $currLi = $next.find("li:eq(" + index + ")"),
134                         $contanier = $currLi.closest('.inputFilter');
135 
136                     if(($currLi.position().top + $currLi.height() + 20) > $contanier.height())
137                     {
138                         $contanier.scrollTop($contanier.scrollTop() + $currLi.height());
139                     }
140 
141                     break;
142                 default: break;
143             }
144             if(index >= 0){
145                 li = $next.find("li:eq(" + index + ")");
146                 li.addClass("active-item").siblings().removeClass('active-item');
147             }
148         }
149 
150         var getListByInput = function(value)
151         {
152             $.ajax({
153                 type: "POST",
154                 data: {"value": value},
155                 url :  url,
156                 dataType:'json',
157                 success:function(data){
158                   var searchList = "<ul>";
159 
160                   if(!isEmptyObj(data))
161                   {
162                       for(var key in data){
163                           var li = "<li id='" + key + "'>" + data[key] + "<b></b></li>";
164                           searchList += li;
165                       }
166                   } else {
167                       searchList += "<li>" + cantFindInfo + "</li>";
168                   }
169 
170                   searchList += "</ul>";
171 
172                   // 重新加载下拉列表
173                   $next.find('ul').remove();
174                   $next.append(searchList);
175                   $next.find('li').each(function(i,e){
176                       $(e).on('click',function(){
177                           selectOptionToInput($(this).attr('id'), $(this).text());
178                       });
179                   });
180 
181                   // 若没有显示下拉框则显示下拉框
182                   if(getAll && $next.find('ul li').length > 1){
183                     $next.width($this.width()+20);
184                     $next.show();
185                   }
186                   if(!canAdd){
187                     $next.find("li:eq(0)").addClass('active-item');
188                   }
189                 },
190                 error:function(message){
191                 }
192             });
193         }
194 
195         var selectOptionToInput = function(id, name)
196         {
197             var $prev = $this.prev();
198 
199             $this.val(name);
200             $prev.val(id);
201             $prev.change();
202             $next.find('li#'+id).addClass('active-item').siblings().removeClass('active-item');
203         }
204 
205         this.$.on('focus', focus);
206         this.$.on('keydown', keydown);
207         this.$.on('blur', blur);
208         if($this.is(":focus")){
209             $this.bind('input propertychange', change);
210         }
211     }
212 
213     $.fn.searchFilter = function(option)
214     {
215         return this.each(function()
216         {
217             var $this   = $(this);
218             var data    = $this.data('zui.searchFilter');
219             var options = typeof option == 'object' && option;
220 
221             if (!data) $this.data('zui.searchFilter', (data = new searchFilter(this, options)));
222 
223             if (typeof option == 'string') data[option]();
224         })
225     };
226 
227     $.fn.searchFilter.Constructor = searchFilter;
228 }(jQuery,window,document,Math);

  第二步:调用searchFilter方法

1  $('#traderInput').searchFilter({url: getTraderUrl, cantFindInfo: “无法找到该信息”}); 

 

 

  

posted @ 2015-10-12 20:09  Mr.Alex  阅读(2364)  评论(0编辑  收藏  举报