;(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);