;(function ($) { $.fn.autoFillTextBox = function (options) { var defaults = { nShow: 5, //显示条数 nLen:10, //结果显示字数 url: "/handler/DataRequestHandler.ashx", //请求数据的url inputCss: 'autofillbox_input', //输入框的样式 containerCss:'autofillbox_container', //外层容器的样式 selectCss:'autofillbox_select', //下拉列表的样式 delay:500, //延时查询的间隔 onSelected:function($container){}, //选择后触发的事件,供外部调用 action:'type', //请求的操做关键字 action_name:'SearchResource', //请求的操做 name_field:'Name', //查询的名字(数据库中的名字字段) py_field:'pinyin', //查询的拼音(数据库中的拼音字段) other_cond:{}, //其余查询条件 enable_fetch_more:true, //是否启用查找更多 do_fetch_more:function(token){}, //查找更多 container_width:0, //输入框长度 enable_blur:true, //是否容许文本框失去焦点的事件 }; var settings = $.extend(defaults, options); var token = 0; var mode = ''; /* * 据配置项中的nLen来获取显示结果的缩写 */ function _getShortName(name){ if (name == null) return ""; if (name.length>settings.nLen) return name.substr(0, settings.nLen)+"..."; else return name; } /* * 显示查询的结果 */ function _showResult($container, response) { $container.children('ul').remove(); if ((response == null || response.length == 0) && !settings.enable_fetch_more) return; var $ul = $("<ul></ul>").addClass(settings.selectCss); $.each(response, function(ii, item) { $ul.append("<li id='"+item.id+"' title='"+item.name+"' data-fullname='"+item.name+"'><a style='text-decoration:none'>" + _getShortName(item.name) + "</a></li>"); }) if (settings.enable_fetch_more){ $ul.append("<a class='fetch_more' style='text-decoration:none;cursor:pointer'><<<查找更多数据>>></a>") } $container.append($ul); $ul.slideDown('slow'); $ul.on('click', 'li', function(){//TODO 此处为啥用delegate没效果 var $container = $(this).parent().parent(); _readMode($(this)); settings.onSelected($container); }); $ul.on('click', '.fetch_more', function(){ settings.do_fetch_more(token); mode = 'fetch_more'; }) }; /* * 编辑模式 */ function _editMode($img){ var $container = $img.parent(); _initInput($container); } /* * 只读模式 */ function _readMode($li){ var $container = $li.parent().parent(); var val = $li.attr('data-fullname'); var id = $li.attr('id'); _initLabel($container, id, val); } /* * 撤销编辑 */ function _redo($img){ var $container = $img.parent().parent(); _initLabel($container); } /* * 执行查询 */ function _doSearch() { var val = $(this).val(); if (val == '') return; var $container = $(this).parent(); var condition = { nameField:settings['name_field'], pyField:settings['py_field'], key:val, maxItem:settings.nShow }; condition[settings['action']] = settings['action_name']; $.extend(condition, settings.other_cond); $.getJSON(settings.url, condition) .done(function (response) { _showResult($container, _formatResponse(response)) }) .fail(function (response) { console.log(response);//ToDo 此处应该显示错误信息,并在1s后自动消失 }) }; /* 规范化response,由于有的是返回model数组,有的是返回dataset */ var _formatResponse = function(response){ if ($.isArray(response)) { return response; }else if (response.hasOwnProperty('ds')){ return response.ds; }else{ return []; } } /* * 延时查询 * 基本思路是,每次用户触发查询时,会重置定时器。若在定时器触发以前用户无再输入,则执行查询 */ var _delayCall = (function() { var timer = null; return function (fn, delay, $input) { clearTimeout(timer); timer = setTimeout(function () { fn.call($input);//使用call能够将input带入给_search函数 }, delay); }; })(); /* * 初始化显示结果的标签 */ function _initLabel($container, id, val){ mode = 'read'; if (id == undefined && val == undefined){ id = $container.attr('data-id'); val = $container.attr('data-val'); }else{ $container.attr({'data-id':id, 'data-val':val}); } $container.children().remove(); $container.append("<span title='"+val+"' style='width:85%'>"+_getShortName(val)+"</span><img title='编辑' src='/Images/icons/page_white_edit.png'/>"); $container.undelegate('img', 'click'); $container.delegate('img', 'click', function () { _editMode($(this)); }); } /* * 显示撤销按钮 */ function _showReDo($container){ if ($container.find('img').length>0) return; $container.children('input').after("<a class='autofillbox_button'><img title='撤销' src='/Images/icons/back.gif' /></a>"); $container.undelegate('img', 'click'); $container.delegate('img', 'click', function () { _redo($(this)); }); } /* * 初始化输入的文本框 */ function _initInput($container) {//初始化输入框 mode = 'write'; $container.children().remove(); if ($container.children().length == 0) { var $input = $('<input type="text" class="' + settings.inputCss + '" id="autofilltextbox_x"/>'); var val = $container.attr('data-val'); $input.val(val); $container.append($input); } $container.undelegate('input', 'keyup'); $container.delegate('input', 'keyup', function () { _delayCall(_doSearch, settings.delay, this); }); $container.undelegate('input', 'click'); $container.delegate('input', 'click', function () { _doSearch.call(this); }); if (settings.enable_blur){ $container.undelegate('input', 'blur'); $container.delegate('input', 'blur', function () { var val = $(this).val(); setTimeout(function () { _setValue($container, '', val); }, 250); }); } _showReDo($container); return $container; } /* * 初始化容器 */ function _initContainer($container) {//初始化外框CSS// $container.css({'position':'relative'}).addClass(settings.containerCss); $container.addClass(settings.containerCss); $container.attr({'data-id':'', 'data-val':''}); if (settings.container_width > 0){ $container.width(settings.container_width); } var t = new Date(); token = t.getTime(); $container.attr('data-token', token);//生成控件的惟一标识 return $container; } function _setValue($container, id, val){ if (mode != 'write') return; $container.attr({'data-id':id, 'data-val':val}); _initLabel($container, id, val); } /* * 初始化控件 */ this.each(function () { var _this = $(this); _this = _initContainer(_this);//初始化外框CSS _this = _initInput(_this);//初始化输入框 }); //-------------------------------------------公有方法---------------------------------------------------- /* * 获取控件的token(惟一标识) */ this.getToken = function(){// return $(this).attr('data-token'); return token; }; /* * 设置其余查询条件 */ this.setOptions =function(options){ $.extend(true, settings, options);//$.extend的第一个参数决定了是否深度拷贝,不然other_cond就会被新的options覆盖 }; /* * 清理选择结果 */ this.clear = function(){ var $container = $(this); $container.attr({'data-id':'', 'data-val':''}); _initInput($container); }; this.setValue = function(id, val, triggerSelect){ var $container = $(this); //$container.attr({'data-id':id, 'data-val':val}); //_initLabel($container, id, val); _setValue($container, id, val); if (triggerSelect){ settings.onSelected($container); } }; this.getSettings = function(){ return settings; }; return this; }})(jQuery);