实现类似于百度实时搜索将结果在下拉框中显示的功能
本文主要实现一个类似于百度搜索一样,当在输入框中输入内容实时向后台发送请求,并将返回的内容在输入框下面用下拉框的形式显示出来的功能。
由于本人是前端程序员,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: “无法找到该信息”});