js实现的联想输入

  以前也写过一个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