本文主要實現一個相似於百度搜索同樣,當在輸入框中輸入內容實時向後臺發送請求,並將返回的內容在輸入框下面用下拉框的形式顯示出來的功能。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