个人认为是比较完整的自动完成插件(jquery)
最近项目需要,要一个带下拉,又可以自己填写的插件,在网上找了很多,都不太符合使用需求,所以自己学着做了一个,对比了很多自动完成,个人感觉这个算是功能上比较完整的了吧,废话不多说,上代码,供大家参考一下
callback方法可带一个参数,该参数反回了input的dom对象,注意,是dom对象,不是jquery对象
20150129:修改->
1.css中限制了下拉选框的高度,显示纵向滚动条
2.修复了拉下选框的滚动条焦点与IE的兼容性问题(针对以前用户在CSS中自行限制高度并设置滚动条的情况)
js:
1 (function ($) { 2 $.fn.myautocomplete = function (options, callback) { 3 $.each(this, function (index, component) { 4 var defaultVal = { 5 source: null, 6 ajax: null 7 }; 8 var params = $.extend(defaultVal, options) 9 var dictionary = null;//备选集合 10 var $popup = null;//备选列表对象 11 var $input = null; 12 var $popupDiv = null;//解决下IE中拉选单超高,用户鼠标点击滚动条时焦点错误 13 14 init(); 15 16 $.fn.myautocomplete.destory = function () { 17 var $newInput = $input.clone(); 18 var $father = $input.parent(); 19 $father.find("*").remove(); 20 $father.append($newInput); 21 22 } 23 24 function init() { 25 initDictionary(); initInput(); deleteUselessObj(); initDropdownBtn(); initPopup(); 26 } 27 28 function initDictionary() { 29 if (params.source && params.source instanceof Array) 30 dictionary = params.source; 31 else { 32 if (params.ajax) { 33 $.post(params.ajax, {}, function (data) { 34 var json = eval(data); 35 if (json instanceof Array) 36 dictionary = json; 37 }) 38 } 39 } 40 } 41 42 function initInput() { 43 $input = $(component);//input的jquery对象 44 $input.timer = null; 45 $input.oldValue = $input.val(); 46 $input.keydown(function (event) { keydown(event) }); 47 $input.focus(function () { 48 //设置每间隔200ms,检查值是否变化 49 $input.focusValue = $input.val(); 50 if (!$input.timer) 51 $input.timer = setInterval(function () { 52 if ($input.val() != $input.oldValue) { 53 $input.oldValue = $input.val(); 54 setPopup($input.val(), false); 55 } 56 }, 200) 57 }) 58 59 $input.blur(function () { 60 setTimeout(function () { 61 if ($input.timer) { 62 clearInterval($input.timer); 63 $input.timer = null; 64 } 65 if (!isMyAutoCompleteIsOnFocus()) { 66 $popup.close(); 67 } 68 if (callback && !isMyAutoCompleteIsOnFocus() && $input.focusValue != $input.val()) { 69 $input.focusValue = $input.val(); 70 callback($input.get(0)); 71 } 72 }) 73 }) 74 }//initInput结束 75 76 function deleteUselessObj() { 77 $input.parent().find("*").each(function (i, n) { 78 if (n != $input.get(0)) 79 $(n).remove(); 80 }); 81 } 82 83 function initDropdownBtn() { 84 $dropdownBtn = $("<a>").attr("href", "javascript:;").attr("class", "dropdownBtn");//兼容ie7,8 85 $dropdownImg = $("<div class='dropdownImg'>"); 86 $dropdownBtn.append($dropdownImg); 87 $dropdownBtn.insertAfter($input); 88 $dropdownBtn.click(function () { 89 $input.focusValue = $input.val(); 90 if ($popup.visible) 91 $popup.close(); 92 else { 93 setPopup('', true); 94 } 95 }) 96 $dropdownBtn.blur(function () { 97 setTimeout(function () { 98 if (!isMyAutoCompleteIsOnFocus()) { 99 $popup.close(); 100 } 101 }); 102 }); 103 $dropdownImg.blur(function () { $dropdownBtn.blur(); });//IE兼容性 104 $dropdownBtn.keydown(function (event) { keydown(event); }); 105 } 106 107 function initPopup() { 108 if ($input.parent() && $input.parent().find("ul").size() > 0) 109 $input.parent().find("ul").remove(); 110 $popupDiv = $("<div class='popupDiv'></div>") 111 $popup = $("<ul class='popup'>"); 112 $popupDiv.insertAfter($input); 113 $popupDiv.append($popup); 114 $popup.listSize = 0; 115 $popup.hoverIndex = -1; 116 $popupDiv.hide(); 117 $popup.visible = false; 118 $popupDiv.css("top", $input.outerHeight()).css("left", "0");//left("0")兼容ie7 119 $popup.close = function () { 120 if ($popup.visible) { 121 $input.parents().unbind("keydown", unbindBodyScroll); 122 this.listSize = 0; 123 this.hoverIndex = -1; 124 $popup.html(""); 125 $popupDiv.hide(); 126 $popup.visible = false; 127 if (callback && !isMyAutoCompleteIsOnFocus() && $input.focusValue != $input.val()) { 128 $input.focusValue = $input.val(); 129 callback($input.get(0)); 130 } 131 } 132 } 133 $popup.open = function () { 134 $input.parents().bind("keydown", unbindBodyScroll); 135 $popupDiv.show(); 136 $popup.visible = true; 137 } 138 $popupDiv.keydown(function (event) { if (!isPopupItemOnFocus() && document.activeElement != $input.get(0)) keydown(event) }); 139 $popup.keydown(function (event) { keydown(event) }); 140 $popupDiv.blur(function () { 141 if (!isMyAutoCompleteIsOnFocus()) 142 $popup.close(); 143 }) 144 }//initPopup结束 145 //设置下拉框内容 146 function setPopup(val, showPopupIfValIsNull) { 147 $popup.html(""); 148 if (val || (!val && showPopupIfValIsNull)) {//判断是否满足显示被选框的条件 149 var Reg = RegExp("^" + val) 150 if (dictionary) { 151 $(dictionary).each(function (i, n) { 152 if (Reg.exec(n)) { 153 //匹配,添加下拉列表 154 var li = $("<li>"); 155 var a = $("<a>") 156 a.text(n); 157 a.attr("href", "javascript:;"); 158 a.click(function () { 159 $input.val(n); 160 $input.oldValue = n; 161 $input.focus(); 162 $popup.close(); 163 if (callback) 164 callback($input.get(0)); 165 }); 166 a.focus(function () { 167 a.addClass("hover"); 168 }); 169 a.blur(function () { 170 a.removeClass("hover"); 171 setTimeout(function () { 172 if (!isMyAutoCompleteIsOnFocus()) 173 $popup.close(); 174 }) 175 }); 176 li.append(a); 177 $popup.append(li); 178 } 179 });//遍历数组进行匹配 180 $popup.listSize = $popup.find("li").size(); 181 if ($popup.listSize > 0) { 182 $popup.open(); 183 } 184 else { 185 $popup.close(); 186 } 187 188 } 189 } 190 else { 191 if ($popup.visible) 192 $popup.close(); 193 } 194 } 195 //按键事件 196 function keydown(event) { 197 if ($popup.visible) { 198 switch (event.keyCode) { 199 case 13: { 200 //按回车键 201 if ($popup.hoverIndex != -1) { 202 $popup.find("a:eq(" + $popup.hoverIndex + ")").click(); 203 } 204 break; 205 } 206 case 38: { 207 //按↑键 208 $popup.hoverIndex--; 209 if ($popup.hoverIndex < -1) 210 $popup.hoverIndex = $popup.listSize - 1; 211 $popup.find("a").removeClass("hover"); 212 if ($popup.hoverIndex != -1) { 213 $popup.find("a:eq(" + $popup.hoverIndex + ")").focus(); 214 } 215 else 216 $input.focus(); 217 break; 218 } 219 case 40: { 220 //按↓键 221 $popup.hoverIndex++; 222 if ($popup.hoverIndex > $popup.listSize - 1) 223 $popup.hoverIndex = -1; 224 $popup.find("a").removeClass("hover"); 225 if ($popup.hoverIndex != -1) { 226 $popup.find("a:eq(" + $popup.hoverIndex + ")").focus(); 227 } 228 else 229 $input.focus(); 230 break; 231 } 232 } 233 } 234 } 235 //解除键盘的↑和↓键导致input父元素们的滚动条滚动 236 function unbindBodyScroll(event) { 237 event = event ? event : window.event; 238 if (event.keyCode == 38 || event.keyCode == 40) return false; 239 } 240 241 function isMyAutoCompleteIsOnFocus() { 242 return document.activeElement == $input.get(0) || isPopupItemOnFocus() || document.activeElement == $popupDiv.get(0); 243 } 244 245 function isPopupItemOnFocus() { 246 return document.activeElement.parentElement.parentElement == $popup.get(0); 247 } 248 }) 249 } 250 })(jQuery);
css:(注意background-image在实际应用时的url地址)
1 .autoComplete { 2 position: relative; 3 zoom: 1; /*ie7兼容*/ 4 } 5 6 .autoComplete:after { /*ie8及更早的版本需要声明<!DOCTYPE html>*/ 7 clear: both; 8 content: ""; 9 display: block; 10 visibility: hidden; 11 height: 0; 12 } 13 14 .autoComplete input { 15 width: 200px; 16 height: 22px; 17 margin: 0; 18 padding: 0; 19 line-height: 22px; 20 display: block; 21 float: left; 22 } 23 24 .autoComplete input::-ms-clear { 25 display: none; 26 } 27 28 .autoComplete .dropdownBtn { 29 cursor: default; 30 margin-left: -14px; 31 float: left; 32 margin-left: -16px; 33 } 34 35 /*ie7,ie8样式兼容*/ 36 * + .autoComplete .dropdownBtn { 37 margin-left: -16px; 38 } 39 40 .autoComplete .dropdownBtn .dropdownImg { 41 height: 23px; 42 width: 15px; 43 background-image: url(../img/dropdown.png); 44 background-size: 100%; 45 } 46 47 .autoComplete .popupDiv { 48 z-index: 9999999999999; 49 padding: 0px; 50 margin: 0px; 51 position: absolute; 52 } 53 54 .autoComplete .popup { 55 padding: 0px; 56 margin: 0px; 57 min-width: 200px; 58 border: 1px #333 solid; 59 background: white; 60 overflow-y: auto; 61 max-height: 190px; 62 } 63 64 65 .autoComplete .popup li { 66 list-style: none; 67 } 68 69 .autoComplete .popup li a { 70 display: block; 71 color: #000; 72 text-decoration: none; 73 padding: 1px 0 1px 5px; 74 cursor: default; 75 _width: 97%; 76 } 77 78 .autoComplete .popup li a:hover, .autoComplete .popup .hover { 79 color: #000; 80 background: #ccc; 81 border: none; 82 }
还有一个图片,不传了,在压缩包里面都有.完整的例子也有
http://pan.baidu.com/s/1dDvS4Id