js实现的联想输入

本文介绍了一个自定义的JavaScript输入提示插件,该插件支持多种实用功能,包括字符匹配提示、上下方向键选择、循环选项、绑定数组提示等,并提供了完整的代码示例。

  以前也写过一个jQuery的这种插件,但是很多地方根本不用jQuery,这个功能也有很多其它库支持,但是为了用这个功能而加载很多js插件,这样效率明显下降了很多,而且这个东西平时也很常用,所以一决心自己写了个相对比较独立的。

 

完成有以下功能:

  • 输入字符会把以输入字符开头的提示出来。
  • 支持上下方向键选择提示选项,支持循环
  • 支持绑定一个数组提示,支持ajax传递输入框值请求数据。
  • 支持多个选择的dom元素一块绑定数据实现输入提示。各dom元素也可以单独绑定自己的数据实现输入提示,互不影响。
  • 支持中文。

      首先是js的核心部分,其各部分都有较详细的说明,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
;( function (window){
/* 插件开始 */
var  autoComplete= function (o){
     var  handler=( function (){
         var  handler= function (e,o){  return  new  handler.prototype.init(e,o); }; /* 为每个选择的dom都创建一个相对应的对象,这样选择多个dom时可以很方便地使用 */
         handler.prototype={
             e: null , o: null , timer: null , show:0, input: null , popup: null ,
             init: function (e,o){ /* 设置初始对象 */
                 this .e=e,  this .o=o,
                 this .input= this .e.getElementsByTagName( this .o.input)[0],
                 this .popup= this .e.getElementsByTagName( this .o.popup)[0],
                 this .initEvent(); /* 初始化各种事件 */
             },
             match: function (quickExpr,value,source){ /* 生成提示 */
                 var  li =  null ;
                 for ( var  in  source){
                     if ( value.length>0 && quickExpr.exec(source[i])!= null  ){
                         li = document.createElement( 'li' );
                         li.innerHTML =  '<a href="javascript:;">' +source[i]+ '</a>' ;
                         this .popup.appendChild(li);
                     }
                 }
                 if ( this .popup.getElementsByTagName( 'a' ).length)
                     this .popup.style.display= 'block' ;
                 else
                     this .popup.style.display= 'none' ;
             },
             ajax: function (type,url,quickExpr,search){ /* ajax请求远程数据 */
                 var  xhr = window.ActiveXObject ?  new  ActiveXObject( "Microsoft.XMLHTTP" ) :  new  XMLHttpRequest();
                 xhr.open(type,url, true ); /* 同异步在此修改 */
                 xhr.setRequestHeader( "Content-Type" , "application/x-www-form-urlencoded" );
                 var  that= this ;
                 xhr.onreadystatechange =  function (){
                     if (xhr.readyState==4) {
                         if (xhr.status==200) {
                             var  data = eval(xhr.responseText);
                             that.match(quickExpr,search,data); /* 相同于成功的回调函数 */
                         } else {
                             alert( "请求页面异常!" ); /* 请求失败 */
                         }
                     }
                 };
                 xhr.send( null );
             },
             fetch: function (ajax,search,quickExpr){
                 var  that= this ;
                 this .ajax(ajax.type,ajax.url+search,quickExpr,search);
             },
             initEvent: function (){ /* 各事件的集合 */
                 var  that= this ;
                 this .input.onfocus =  function (){
                     if ( this .inputValue)  this .value =  this .inputValue;
                     var  value= this .value, quickExpr=RegExp( '^' +value, 'i' ), self= this ;
                     var  els = that.popup.getElementsByTagName( 'a' );
                     if (els.length>0) that.popup.style.display =  'block' ;
                     that.timer=setInterval( function (){
                         if (value!=self.value){ /* 判断输入内容是否改变,兼容中文 */
                             value=self.value;
                             that.popup.innerHTML= '' ;
                             if (value!= '' ){
                                 quickExpr=RegExp( '^' +value);
                                 if (that.o.source) that.match(quickExpr,value,that.o.source);
                                 else  if (that.o.ajax) that.fetch(that.o.ajax,value,quickExpr);
                             }
                         }
                     },200);
                 };
                 this .input.onblur =  function (){ /*  输入框添加事件 */
                     if ( this .value!= this .defaultValue)  this .inputValue =  this .value;
                     clearInterval(that.timer);
                     var  current=-1; /* 记住当前有焦点的选项 */
                     var  els = that.popup.getElementsByTagName( 'a' );
                     var  len = els.length-1;
                     var  aClick =  function (){
                         that.input.inputValue =  this .firstChild.nodeValue;
                         that.popup.innerHTML= '' ;
                         that.popup.style.display= 'none' ;
                         that.input.focus();
                     };
                     var  aFocus =  function (){
                         for ( var  i=len; i>=0; i--){
                             if ( this .parentNode===that.popup.children[i]){
                                 current = i;
                                 break ;
                             }
                         }
                         //that.input.value = this.firstChild.nodeValue;
                         for ( var  in  that.o.elemCSS.focus){
                             this .style[k] = that.o.elemCSS.focus[k];
                         }
                     };
                     var  aBlur=  function (){
                         for ( var  in  that.o.elemCSS.blur)
                             this .style[k] = that.o.elemCSS.blur[k];
                     };
                     var  aKeydown =  function (event){
                         event = event || window.event; /* 兼容IE */
                         if (current === len && event.keyCode===9){ /* tab键时popup隐藏 */
                             that.popup.style.display =  'none' ;
                         } else  if (event.keyCode==40){ /* 处理上下方向键事件方便选择提示的选项 */
                             current++;
                             if (current<-1) current=len;
                             if (current>len){
                                 current=-1;
                                 that.input.focus();
                             } else {
                                 that.popup.getElementsByTagName( 'a' )[current].focus();
                             }
                         } else  if (event.keyCode==38){
                             current--;
                             if (current==-1){
                                 that.input.focus();
                             } else  if (current<-1){
                                 current = len;
                                 that.popup.getElementsByTagName( 'a' )[current].focus();
                             } else {
                                 that.popup.getElementsByTagName( 'a' )[current].focus();
                             }
                         }
                     };
                     for ( var  i=0; i<els.length; i++){ /* 为每个选项添加事件 */
                         els[i].onclick = aClick;
                         els[i].onfocus = aFocus;
                         els[i].onblur = aBlur;
                         els[i].onkeydown = aKeydown;
                     }
                 };
                 this .input.onkeydown =  function (event){
                     event = event || window.event; /* 兼容IE */
                     var  els = that.popup.getElementsByTagName( 'a' );
                     if (event.keyCode==40){
                         if (els[0]) els[0].focus();
                     } else  if (event.keyCode==38){
                         if (els[els.length-1]) els[els.length-1].focus();
                     } else  if (event.keyCode==9){
                         if (event.shiftKey== true ) that.popup.style.display =  'none' ;
                     }
                 };
                 this .e.onmouseover =  function (){ that.show=1; };
                 this .e.onmouseout =  function (){ that.show=0; };
                 addEvent.call(document, 'click' , function (){
                     if (that.show==0){
                         that.popup.style.display= 'none' ;
                     }
                 }); /* 处理提示框dom元素不支持onblur的情况 */
             }
         };
         handler.prototype.init.prototype=handler.prototype; /* JQuery style,这样我们在处的时候就不用每个dom元素都用new来创建对象了 */
         return  handler; /* 把内部的处理函数传到外部 */
     })();
     if ( this .length){ /* 处理选择多个dom元素 */
         for ( var  a= this .length-1; a>=0; a--){ /* 调用方法为每个选择的dom生成一个处理对象,使它们不互相影响 */
             handler( this [a],o);
         }
     } else { /* 处理选择一个dom元素 */
         handler( this ,o);
     }
     return  this ;
};
return  window.autoComplete = autoComplete; /* 暴露方法给全局对象 */
/* 插件结束 */
})(window);

 

      其中了一些全局的自定义函数,如addEvent和在例子中将要用到的getElementsByClassName函数如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
var  getElementsByClassName =  function  (searchClass, node, tag) { /* 兼容各浏览器的选择class的方法;(写法参考了博客园:http://www.cnblogs.com/rubylouvre/archive/2009/07/24/1529640.html,想了解更多请看这个地址) */
     node = node || document, tag = tag ? tag.toUpperCase() :  "*" ;
     if (document.getElementsByClassName){ /* 支持getElementsByClassName的浏览器 */
         var  temp = node.getElementsByClassName(searchClass);
         if (tag== "*" ){
             return  temp;
         else  {
             var  ret =  new  Array();
             for ( var  i=0; i<temp.length; i++)
                 if (temp[i].nodeName==tag)
                     ret.push(temp[i]);
             return  ret;
         }
     } else { /* 不支持getElementsByClassName的浏览器 */
         var  classes = searchClass.split( " " ),
             elements = (tag ===  "*"  && node.all)? node.all : node.getElementsByTagName(tag),
             patterns = [], returnElements = [], current, match;
         var  i = classes.length;
         while (--i >= 0)
             patterns.push( new  RegExp( "(^|\\s)"  + classes[i] +  "(\\s|$)" ));
         var  j = elements.length;
         while (--j >= 0){
             current = elements[j], match =  false ;
             for ( var  k=0, kl=patterns.length; k<kl; k++){
                 match = patterns[k].test(current.className);
                 if (!match)  break ;
             }
             if (match) returnElements.push(current);
         }
         return  returnElements;
     }
};
var  addEvent=( function (){ /* 用此函数添加事件防止事件覆盖 */
     if (document.addEventListener){
         return  function (type, fn){  this .addEventListener(type, fn,  false ); };
     } else  if (document.attachEvent){
         return  function (type,fn){
             this .attachEvent( 'on' +type,  function  () {
                 return  fn.call( this , window.event); /* 兼容IE */
             });
         };
     }
})();

 

 原文地址: http://www.cnblogs.com/jaiho/archive/2011/02/28/js_autocomplete.html

如果忘记,在自己的语言精髓文件夹里

转载于:https://www.cnblogs.com/yangheng/p/6015586.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值