您的位置:知识库 » Web前端

用js实现输入提示(自动完成)

作者: JaiHo  来源: 博客园  发布时间: 2011-03-06 21:39  阅读: 2111 次  推荐: 0   原文链接   [收藏]  

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

  完成有以下功能:

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

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

1
;(function(window){<br>/* 插件开始 */<br>var autoComplete=function(o){<br>    var handler=(function(){<br>        var handler=function(e,o){ return new handler.prototype.init(e,o); };/* 为每个选择的dom都创建一个相对应的对象,这样选择多个dom时可以很方便地使用 */<br>        handler.prototype={<br>            e:null, o:null, timer:null, show:0, input:null, popup:null,<br>            init:function(e,o){/* 设置初始对象 */<br>                this.e=e, this.o=o,<br>                this.input=this.e.getElementsByTagName(this.o.input)[0],<br>                this.popup=this.e.getElementsByTagName(this.o.popup)[0],<br>                this.initEvent();/* 初始化各种事件 */<br>            },<br>            match:function(quickExpr,value,source){/* 生成提示 */<br>                var li = null;<br>                for(var i in source){<br>                    if( value.length>0 && quickExpr.exec(source[i])!=null ){<br>                        li = document.createElement('li');<br>                        li.innerHTML = '<a href="javascript:;">'+source[i]+'</a>';<br>                        this.popup.appendChild(li);<br>                    }<br>                }<br>                if(this.popup.getElementsByTagName('a').length)<br>                    this.popup.style.display='block';<br>                else<br>                    this.popup.style.display='none';<br>            },<br>            ajax:function(type,url,quickExpr,search){/* ajax请求远程数据 */<br>                var xhr = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();<br>                xhr.open(type,url,true);/* 同异步在此修改 */<br>                xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");<br>                var that=this;<br>                xhr.onreadystatechange = function(){<br>                    if(xhr.readyState==4) {<br>                        if(xhr.status==200) {<br>                            var data = eval(xhr.responseText);<br>                            that.match(quickExpr,search,data);/* 相同于成功的回调函数 */<br>                        }else{<br>                            alert("请求页面异常!");/* 请求失败 */<br>                        }<br>                    }<br>                };<br>                xhr.send(null);<br>            },<br>            fetch:function(ajax,search,quickExpr){<br>                var that=this;<br>                this.ajax(ajax.type,ajax.url+search,quickExpr,search);<br>            },<br>            initEvent:function(){/* 各事件的集合 */<br>                var that=this;<br>                this.input.onfocus = function(){<br>                    var value=this.value, quickExpr=RegExp('^'+value,'i'), self=this;<br>                    that.timer=setInterval(function(){<br>                        if(value!=self.value){/* 判断输入内容是否改变,兼容中文 */<br>                            value=self.value;<br>                            that.popup.innerHTML='';<br>                            if(value!=''){<br>                                quickExpr=RegExp('^'+value);<br>                                if(that.o.source) that.match(quickExpr,value,that.o.source);<br>                                else if(that.o.ajax) that.fetch(that.o.ajax,value,quickExpr);<br>                            }<br>                        }<br>                    },200);<br>                };<br>                this.input.onblur = function(){/*  输入框添加事件 */<br>                    clearInterval(that.timer);<br>                    var current=-1;/* 记住当前有焦点的选项 */<br>                    var els = that.popup.getElementsByTagName('a');<br>                    var len = els.length-1;<br>                    var aClick = function(){<br>                        that.input.value=this.firstChild.nodeValue;<br>                        that.popup.innerHTML='';<br>                        that.popup.style.display='none';<br>                    };<br>                    var aFocus = function(){<br>                        for(var i=len; i>=0; i--){<br>                            if(this.parentNode===that.popup.children[i]){<br>                                current = i;<br>                                break;<br>                            }<br>                        }<br>                        for(var k in that.o.elemCSS.focus)<br>                            this.style[k] = that.o.elemCSS.focus[k];<br>                    };<br>                    var aBlur= function(){<br>                        for(var k in that.o.elemCSS.blur)<br>                            this.style[k] = that.o.elemCSS.blur[k];<br>                    };<br>                    var aKeydown = function(event){<br>                        event = event || window.event;/* 兼容IE */<br>                        if(event.keyCode==40){/* 处理上下方向键事件方便选择提示的选项 */<br>                            current++;<br>                            if(current<0) current=len;/* 处理循环 */<br>                            if(current>len) current=0;<br>                            that.popup.getElementsByTagName('a')[current].focus();<br>                        }else if(event.keyCode==38){<br>                            current--;<br>                            if(current>len) current=0;<br>                            if(current<0) current=len;<br>                            that.popup.getElementsByTagName('a')[current].focus();<br>                        }<br>                    };<br>                    for(var i=0; i<els.length; i++){/* 为每个选项添加事件 */<br>                        els[i].onclick = aClick;<br>                        els[i].onfocus = aFocus;<br>                        els[i].onblur = aBlur;<br>                        els[i].onkeydown = aKeydown;<br>                    }<br>                };<br>                this.input.onkeydown = function(event){<br>                    event = event || window.event;/* 兼容IE */<br>                    if(event.keyCode==40){<br>                        that.popup.blur();<br>                        if(that.popup.getElementsByTagName('a')[0])<br>                            that.popup.getElementsByTagName('a')[0].focus();<br>                    }<br>                };<br>                this.e.onmouseover = function(){ that.show=1; };<br>                this.e.onmouseout = function(){ that.show=0; };<br>                addEvent.call(document,'click',function(){ if(that.show==0) that.popup.style.display='none'; });/* 处理提示框dom元素不支持onblur的情况 */<br>            }<br>        };<br>        handler.prototype.init.prototype=handler.prototype;/* JQuery style,这样我们在处的时候就不用每个dom元素都用new来创建对象了 */<br>        return handler;/* 把内部的处理函数传到外部 */<br>    })();<br>    if(this.length){/* 处理选择多个dom元素 */<br>        for(var a=this.length-1; a>=0; a--){/* 调用方法为每个选择的dom生成一个处理对象,使它们不互相影响 */<br>            handler(this[a],o);<br>        }<br>    }else{/* 处理选择一个dom元素 */<br>        handler(this,o);<br>    }<br>    return this;<br>};<br>return window.autoComplete = autoComplete;/* 暴露方法给全局对象 */<br>/* 插件结束 */<br>})(window);<br>

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

1
var getElementsByClassName = function (searchClass, node, tag) {/* 兼容各浏览器的选择class的方法;(写法参考了博客园:http://www.cnblogs.com/rubylouvre/archive/2009/07/24/1529640.html,想了解更多请看这个地址) */<br>    node = node || document, tag = tag ? tag.toUpperCase() : "*";<br>    if(document.getElementsByClassName){/* 支持getElementsByClassName的浏览器 */<br>        var temp = node.getElementsByClassName(searchClass);<br>        if(tag=="*"){<br>            return temp;<br>        } else {<br>            var ret = new Array();<br>            for(var i=0; i<temp.length; i++)<br>                if(temp[i].nodeName==tag)<br>                    ret.push(temp[i]);<br>            return ret;<br>        }<br>    }else{/* 不支持getElementsByClassName的浏览器 */<br>        var classes = searchClass.split(" "),<br>            elements = (tag === "*" && node.all)? node.all : node.getElementsByTagName(tag),<br>            patterns = [], returnElements = [], current, match;<br>        var i = classes.length;<br>        while(--i >= 0)<br>            patterns.push(new RegExp("(^|\\s)" + classes[i] + "(\\s|$)"));<br>        var j = elements.length;<br>        while(--j >= 0){<br>            current = elements[j], match = false;<br>            for(var k=0, kl=patterns.length; k<kl; k++){<br>                match = patterns[k].test(current.className);<br>                if(!match) break;<br>            }<br>            if(match) returnElements.push(current);<br>        }<br>        return returnElements;<br>    }<br>};<br>var addEvent=(function(){/* 用此函数添加事件防止事件覆盖 */<br>    if(document.addEventListener){<br>        return function(type, fn){ this.addEventListener(type, fn, false); };<br>    }else if(document.attachEvent){<br>        return function(type,fn){<br>            this.attachEvent('on'+type, function () {<br>                return fn.call(this, window.event);/* 兼容IE */<br>            });<br>        };<br>    }<br>})();<br>

      最后是调用的部分,调用和每个参数的部分都有说明和注意事项,再说一个其中source和ajax参数是二选一,如果二者都写只有source是有用的,调用代码如下:

1
addEvent.call(null,'load',function(){<br>    autoComplete.call( getElementsByClassName('autoComplete'), {/* 使用call或apply调用此方法 */<br>            source:['0123','023',123,1234,212,214,'033333','0352342',1987,17563,20932],/* 提示时在此数组中搜索 */<br>            //ajax:{ type:'post',url:'./php/fetch.php?search=' },/* 如果使用ajax则返回的数据格式要与source相同,如为字符串"[111,222,333,444]"等形式。*/<br>            elemCSS:{ focus:{'color':'#00ff00','background':'red'}, blur:{'color':'#ff0000','background':'transparent'} },/* 些对象中的key要js对象中的style属性支持 */<br>            input:'input',/* 输入框使用input元素 */<br>            popup:'ul'/* 提示框使用ul元素 */<br>    });<br>});<br>

  代码比较多,但是测试的比较完整,基本没有什么大毛病了,如果有什么毛病请大家指正,谢谢!

0
2

Web前端热门文章

    Web前端最新文章

      最新新闻

        热门新闻