1 /**
  2  *
  3  * autocomplete.js
  4  *
  5  * @fileOverView 自动完成组件
  6  * @author  <a href="mailto:chenzheng.carl@snda.com">CarlChen</a>
  7  * @date    2012-10-31
  8  */
  9 define(["core"], function() {
 10 
 11     var _ContainerHtml = [
 12         '<div class="we_option_box" style="display: none;" attr="inner:root"></div>'
 13     ].join('');
 14 
 15     var _DropDownHtml = [
 16     '<span class="we_cell_select_bt" attr="inner:dropDownBtn">',
 17             '<b class="we_cell_select_arrow"></b>',
 18     '</span>',
 19     ].join('');
 20 
 21     var _Html = [
 22         '<div class="we_option_list" style="height: 150px;overflow-y: auto;">',
 23         '<p class="we_option_txt" attr="inner:title">$title$</p>',
 24         '<ul class="we_list" attr="inner:datasource"></ul>',
 25         '</div>'
 26     ].join('');
 27 
 28     /**
 29      * 自动完成组件
 30      *
 31      * @lends $we.widget.Autocomplete
 32      */
 33     $we.widget.reg("Autocomplete", {
 34         /**
 35          * 自动完成组件接口
 36          *
 37          * @memberOf $we.widget.Autocomplete-
 38          */
 39         interfaces:{
 40             /**
 41              * 渲染数据
 42              */
 43             renderData:function ()
 44             {
 45                 var t = this;
 46                 var config = this.config;
 47                 var ds = config['ds'];
 48 
 49 
 50                 var dataSource = $(this.node['datasource']);
 51                 dataSource.empty();
 52 
 53                 var searchParse = config['search_parse'];
 54                 if (typeof ds == 'object') {
 55                     $.each(ds, function (i, d)
 56                     {
 57                         var showStr = d;
 58                         if (searchParse) {
 59                             showStr = searchParse.call(t.target,d);
 60                         }
 61                         if(showStr){
 62                             var dataHtml = [];
 63                             dataHtml.push('<li class="ac_datasource" ds="' + d + '" ss="' + showStr + '">');
 64                             dataHtml.push('<a href="javascript:void(0);">' + showStr + '</a>');
 65                             dataHtml.push('</li>');
 66                             dataSource.append(dataHtml.join(''));
 67                         }
 68                     });
 69 
 70                     $(".ac_datasource").each(function (i, li)
 71                     {
 72                         li = $(li);
 73                         li.click(function ()
 74                         {
 75                             var ss = li.attr('ss');
 76                             t.setVal(ss);
 77                             $we.utils.validForm(t.target);
 78                         });
 79                     });
 80                 }
 81             },
 82 
 83             /**
 84              * 给AutoComplete设置值
 85              */
 86             setVal:function(ss){
 87                 var t = this;
 88                 t.target.val(ss);
 89                 t.hide();
 90 
 91                 var config = t.config;
 92                 if(config['onAfterSet']){
 93                     config['onAfterSet'](ss);
 94                 }
 95             },
 96 
 97             /**
 98              * 是否处于显示状态
 99              * @return {Boolean} [description]
100              */
101             isShow:function(){
102                 var display = $(this.node['root']).css("display");
103                 return !(display == 'none');
104             },
105             /**
106              * 显示
107              */
108             show:function ()
109             {
110                 $(this.node['root']).show();
111                 this.renderData();
112             },
113 
114             /**
115              * 隐藏
116              */
117             hide:function (event)
118             {
119                 $(this.node['root']).hide();
120             }
121         },
122 
123         /**
124          * 事件
125          *
126          * @memberOf $we.widget.Autocomplete-
127          */
128         events:{
129         },
130 
131         /**
132          *  Config配置说明 <br/>
133          *  title:标题
134          *  ds:数据源
135          *  search_parse: 搜索解析器
136          *  commit:回车提交函数
137          *  dropDown:false 是否有下拉按钮
138          *  onAfterSet: 在设置完值后触发事件
139          *
140          * @param config
141          * @constructs
142          */
143         init:function (target, config)
144         {
145             var t = this;
146 
147             config = config || {};
148             this.config = config;
149             this.target = target;
150 
151             target.attr('autocomplete','off');
152 
153             var title = config['title'];
154             this.after(target, _ContainerHtml);
155             this.append(this.node['root'], _Html, {title:title||''});
156 
157             var dropDown = config['dropDown'];
158             if(dropDown){
159                 this.after(target,_DropDownHtml);
160                 $(this.node['dropDownBtn']).click(function(){
161                     if(t.isShow()){
162                         t.hide();
163                     }else{
164                         t.show();
165                     }
166                 });
167             }
168 
169             if(!title){
170                 $(this.node['title']).hide();
171             }
172 
173             //监控输入
174             target.keyup(function (event)
175             {
176                 if (event.keyCode == 13) {
177                     //回车
178                     var target = $(t.node['datasource']).find(".we_cur");
179                     if (target && target.length > 0) {
180                         var ss = target.attr('ss');
181                         t.setVal(ss);
182                         target.removeClass('we_cur');
183                     }else{
184                         if(config['commit']){
185                             config['commit']();
186                         }
187                     }
188                 }
189                 else if (event.keyCode == 38) {
190                     //向上箭头
191                     var prevTarget = null;
192                     $(".ac_datasource").each(function (i, li)
193                     {
194                         li = $(li);
195                         if (li.hasClass('we_cur')) {
196                             prevTarget = li.prev();
197                             li.removeClass('we_cur');
198                         }
199                     });
200                     if (!prevTarget) {
201                         prevTarget = $(".ac_datasource:last");
202                     }
203                     prevTarget.addClass('we_cur');
204                 }
205                 else if (event.keyCode == 40) {
206                     //向下箭头
207                     var nextTarget = null;
208                     $(".ac_datasource").each(function (i, li)
209                     {
210                         li = $(li);
211                         if (li.hasClass('we_cur')) {
212                             nextTarget = li.next();
213                             li.removeClass('we_cur');
214                         }
215                     });
216                     if (!nextTarget) {
217                         nextTarget = $(".ac_datasource:first");
218                     }
219                     nextTarget.addClass('we_cur');
220                 }
221                 else if (event.keyCode == 27) {
222                     //取消
223                     t.hide();
224                 }
225                 else {
226                     t.show();
227                 }
228             });
229 
230             //监控Focus
231             target.focus(t.show);
232 
233             //监控Blur
234             var blur = function(){
235                 t.hide();
236                 $we.utils.validForm(t.target);
237             };
238             target.blur(blur);
239 
240             $(this.node['root']).mouseenter(function ()
241             {
242                 target.off('blur', blur);
243             }).mouseleave(function ()
244                     {
245                         target.on('blur', blur);
246                     });
247         }
248     });
249 
250     return $we.widget.amd("Autocomplete");
251 });