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

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

js实现的联想输入的更多相关文章

  1. JS实现联想输入(二)

    JS实现联想输入(一)是主要针对单列结构的JSON格式的数据的,如果想满足多列结构的JSON格式的数据,也是非常容易的,其解决方案有至少有三种选择: 1:在后台Action方法中将多列的值拼成单列结构 ...

  2. JS实现联想输入(一)

    这里是我们的项目中的一个使用JS实现联想输入的功能代码,在此做个小的记录并且将它分享给大家希望对园中的朋友有用! 我将分享三段都非常简单的代码,仅仅作为个人的一点小小的积累而已! 1:后台的Actio ...

  3. autocomplete实现联想输入,自动补全

    jQuery.AutoComplete是一个基于jQuery的自动补全插件.借助于jQuery优秀的跨浏览器特性,可以兼容Chrome/IE/Firefox/Opera/Safari等多种浏览器. 特 ...

  4. bigautocomplete实现联想输入,自动补全

    bigautocomplete是一款Jquery插件.用它实现仿搜索引擎文本框自动补全插件功能很实用,使用也很简单,引入了插件之后写几行代码就可以实现,可以灵活设置. 先看效果图: 上图是通过ajax ...

  5. javascript 实现类似百度联想输入,自动补全功能

    js  实现类似百度联想输入,自动补全功能 方案一: search是搜索框id="search" //点击页面隐藏自动补全提示框 document.onclick = functi ...

  6. Vue.js 和 MVVM 小细节

    MVVM 是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式,其核心是提供对View 和 ViewModel 的双向数据绑定,这使得ViewModel 的状态改变可以自 ...

  7. js学习笔记:操作iframe

    iframe可以说是比较老得话题了,而且网上也基本上在说少用iframe,其原因大致为:堵塞页面加载.安全问题.兼容性问题.搜索引擎抓取不到等等,不过相对于这些缺点,iframe的优点更牛,跨域请求. ...

  8. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  9. JS调用Android、Ios原生控件

    在上一篇博客中已经和大家聊了,关于JS与Android.Ios原生控件之间相互通信的详细代码实现,今天我们一起聊一下JS调用Android.Ios通信的相同点和不同点,以便帮助我们在进行混合式开发时, ...

随机推荐

  1. 感知机学习算法(PLA)

    Perception Learning Algorithm, PLA 1.感知机 感知机是一种线性分类模型,属于判别模型. 感知机模型给出了由输入空间到输出空间的映射: f(X) = sign(WTX ...

  2. Gitlab自动触发Jenkins构建项目

    Gitlab自动触发Jenkins构建项目 一.前提 Gitlab已安装配置好. Jenkins已安装Gitlab plugin. 二.配置jenkins中Job 1.勾选触发器下的gitlab触发器 ...

  3. 并查集——poj1308(并查集延伸)

    题目链接:Is It A Tree? 题意:给你一系列形如u v的点对(u v代表一条由u指向v的有向边),请问由给你的点构成的图是不是一棵树? 树的特征:①每个节点(除了根结点)只有一个入度:②只有 ...

  4. java课程设计 学生管理系统

    学生成绩管理系统 可实现功能 学生管理系统 查询学生信息:姓名.学号.性别.出生年月日.(学号自动生成且唯一) 查询学生成绩:每个人都有数学.Java与体育与选修课 查询学生课程 进行公选课选课 教师 ...

  5. 《学习OpenCV》课后习题解答8

    题目:(P126) 本章完整讲述了基本的输入/输出编程以及OpenCV的数据结构.下面的练习是基于前面的知识做一些应用,为后面大程序的实现提供帮助. a.创建一个程序实现以下功能:(1)从视频文件中读 ...

  6. springmvc项目搭建五-postgresql+easyui的数据显示

    上一篇虽然完成了页面的显示,但是是假数据,本篇添加了postgresql的数据库,将登陆的校验和数据的显示都通过数据库来完成. 我是在本地搭建了一个postgre的数据库,就先新建两张表吧,一个用于用 ...

  7. 201621123033 《Java程序设计》第13周学习总结

    1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 为你的系统增加网络功能(购物车.图书馆管理.斗地主等)-分组完成 为了让你的系统可以被多个用户通过网 ...

  8. Bootstrap中轮播图

    Bootstrap中轮播图插件叫作Carousel,为了清晰的表明每个标签在这里是什么意思,我把解释写在了下面的代码中. <!-- 以下容器就是整个轮播图组件的整体, 注意该盒子必须加上 cla ...

  9. Intellij IDEA 系统路径配置

    在使用IDEA启动Tomcat的时候,会读取系统路径,默认路径可能不是我们想要的,可以修改 C:\MyPrograms\IntelliJ IDEA 14.0.1\bin\idea.properties ...

  10. ElasticSearch1.7.1拼音插件elasticsearch-analysis-pinyin-1.3.3使用介绍

    ElasticSearch拼音插件elasticsearch-analysis-pinyin使用介绍 https://my.oschina.net/xiaohui249/blog/214505 摘要: ...