2015年5月12日 20:16:48 星期二

效果: 

自动补全多标签输入, 适合新闻标签/商品标签

原理:

1. 建立"单字"索引(倒排索引): 将汉字拆分成单个字, 作为redis hash 的一个键, 将所有包含该字的id作为hash的值

2. 每次输入一个字, 就去redis里将该字的所有id取出来, 输入第二个字的时候, 取出第二个字的所有id与第一个字的id求交集

  求得同时包含这两个字的所有id, 再进一步获取id对应的信息并返回

 

另外:

1. 文中还建立了两个全词索引(redis hash), 一个是 {"完整汉字词语" : "id", .....} 另一个是 {"id" : "完整汉字词语" ,.......} 方便后续程序使用, 与这个自动补全关系不大

2. 小细节, 每次点选词语的时候, js自动补上"," 而且ajax请求数据的时候, 只把最后一个","后边的用户输入词语发送给服务端

 

话不多说, 上代码:

js+css

  1 <script type="text/javascript">
  2 var ac_domain = 'http://'+document.domain+'/';
  3 initAutoComplete();
  4 function initAutoComplete()
  5 {
  6     var ac_input = document.getElementById('auto_complete_input');
  7     if (!ac_input) {return false;}
  8     var ac_rebuildindex = document.getElementById('rebuild_autocomplete_index');
  9 
 10     if (document.attachEvent) {
 11         ac_input.attachEvent('oninput', input_autocomplete); //输入时进行自动补全
 12         // ac_input.attachEvent('onblur', hide_autocomplete); //鼠标点击其它地方隐藏div, 屏蔽 因为onblur 和 onclick 冲突
 13         ac_input.attachEvent('onfocus', input_autocomplete); //输入框重新获取焦点时显示自动补全结果
 14         ac_input.attachEvent('onkeydown', input_autocomplete_keydown); //处理按键信息
 15         ac_rebuildindex.attachEvent('onclick', rebuild_autocomplete_index);
 16     } else {
 17         ac_input.addEventListener('input', input_autocomplete); //输入时进行自动补全
 18         // ac_input.addEventListener('blur', hide_autocomplete); //鼠标点击其它地方隐藏div, 屏蔽 因为onblur 和 onclick 冲突
 19         ac_input.addEventListener('focus', input_autocomplete); //输入框重新获取焦点时显示自动补全结果
 20         ac_input.addEventListener('keydown', input_autocomplete_keydown); //处理按键信息
 21         ac_rebuildindex.addEventListener('click', rebuild_autocomplete_index);
 22     }
 23 
 24     $(document).bind("click",function(e){
 25         var target  = $(e.target);//表示当前对象,切记,如果没有e这个参数,即表示整个BODY对象
 26         if(target.closest(".form-input-autocomplete,#auto_complete_input").length == 0){
 27            hide_autocomplete();
 28         }
 29      })
 30 }
 31 
 32 function input_autocomplete()
 33 {
 34     var ac_input = document.getElementById('auto_complete_input');
 35     var userinput = ac_input.value;
 36     if (!userinput) {return false;}
 37     var arr_new_word = userinput.split(/,\s*/);
 38     var new_word = arr_new_word.pop();
 39 
 40     var url = ac_domain+'getAutoComplete?word='+new_word;
 41     $.get(url, 
 42         function(data) {
 43             if (!data) {return false;};
 44             var objGame = eval('('+data+')');
 45             html = '<ul>';
 46             for (var i in objGame) {
 47                 html += '<li class="auto_complete_li" data->;
 48             }
 49             html += '</ul>';
 50             var ac_div = $("#auto_complete_div");
 51             ac_div.show();
 52             ac_div.html(html);
 53             click_autocomplete_li(); //注册点击事件
 54         }
 55     );
 56 }
 57 
 58 function hide_autocomplete()
 59 {
 60     var ac_div = document.getElementById('auto_complete_div');
 61     ac_div.style.display = 'none';
 62 }
 63 
 64 function click_autocomplete_li()
 65 {
 66     var arr_ac_li = getElementsByClassName('auto_complete_li', 'ul');
 67     for (var i = 0; i < arr_ac_li.length; i++) {
 68         arr_ac_li[i].addEventListener('click', function () {
 69             //获取列表li上的数据, 并组装
 70             var data_id = this.getAttribute('data-id');
 71             var data_name = this.getAttribute('data-name');
 72             var data_info = data_id+'|'+data_name;
 73 
 74             ///////向输入框写数据
 75             var already_input = document.getElementById('auto_complete_input');
 76 
 77             //去掉用户的输入, 换做用户点击的li里的name
 78             var arr_already_input = already_input.value.split(/,\s*/);
 79             arr_already_input.pop(); 
 80             arr_already_input.push(data_name);
 81 
 82             //去重
 83             var hash_already_input = {};
 84             for (var i in arr_already_input) {
 85                 hash_already_input[arr_already_input[i]] = arr_already_input[i];
 86             }
 87             arr_already_input = [];
 88             for (key in hash_already_input) {
 89                 arr_already_input.push(key);
 90             }
 91 
 92             //回写入表单
 93             var str_already_input = arr_already_input.join(", ");
 94             document.getElementById('auto_complete_input').value = str_already_input+", ";
 95 
 96             //如果只有一条匹配, 点击后就消失, 多条的话点击后不消失, 可以多次点选
 97             if (arr_ac_li.length == 1) {
 98                 hide_autocomplete();
 99             };
100         })
101     };
102 }
103 
104 function rebuild_autocomplete_index()
105 {
106     var nodeParent = this.parentNode;
107     var url = ac_domain+'buildTeamAutoComplete';
108     $.get(url, 
109         function(data) {
110             nodeParent.innerHTML = '已经重建索引,再点击输入框试试';
111         }
112     );
113 }
114 
115 function input_autocomplete_keydown(e)
116 {
117     switch(e.keyCode){
118         case '8':
119         //按下删除键
120         input_autocomplete();
121         break;
122     };
123 }
124 
125 function getElementsByClassName(className, tagName)
126 {
127     var t = typeof(document.getElementsByClassName);
128 
129     if (t == 'function') {
130         return document.getElementsByClassName(className);
131     }
132 
133     var tags, matchedTags;
134     if (tagName) {
135         tags = document.getElementsByTagName(tagName);
136     } else {
137         tags = document.getElementsByTagName('*');
138     }
139 
140     matchedTags = [];
141     for (var i = 0; i < tags.length; i++) {
142         if (tags[i].className.indexOf(className) != -1) {
143             matchedTags.push(tags[i]);
144         }
145     }
146 
147     return matchedTags;
148 }
149 </script>
150 
151 <style type="text/css">
152     /*自动补全*/
153     .form-input-autocomplete {padding: 0px; width: 200px; border: 1px solid #aaa; display: none; z-index: 99; position: absolute; background-color: #fff; filter: alpha(opacity=100); opacity: 1;}
154     .form-input-autocomplete ul {margin: 0px;padding: 0px; text-align: left; list-style: none; font:15px;}
155     .form-input-autocomplete ul li{margin: 3px;}
156     .form-input-autocomplete ul li:hover{background-color: #eee; cursor:hand;}
157 </style>
View Code

相关文章: