本文主要实现一个相似于百度搜索同样,当在输入框中输入内容实时向后台发送请求,并将返回的内容在输入框下面用下拉框的形式显示出来的功能。html
因为本人是前端程序员,so,这里只介绍前端实现部分,实现分为HTML,JS两部分(后台对接使用的是PHP):前端
HTML:程序员
第一步:封装一个组件用于页面实现ajax
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 }
第二步:页面调用该组件json
1 // 页面调用 2 echo html::searchFilterInput('trader', '' ,'traderInput', '', '', , );
JS部分:app
第一步:经过扩展jQuery的方式将该方法进行封装,主要包含实时请求事件以及键盘操做事件,该方法根据传入的参数来进行不一样的处理,主要处理的参数有:1.url:搜索数据的url;2.getAll:用于标示若输入为空时是否显示全部数据(适用于数据列表少的数据,相似于select下拉框);3.canAdd:用于标识当输入的信息搜索不到时是否容许用户将该信息做为新的数据添加进来。在进行实时请求中,使用setTimeout来进行节流,防止向后台请求频率过多。ide
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方法ui
1 $('#traderInput').searchFilter({url: getTraderUrl, cantFindInfo: “没法找到该信息”}); this