基於jquery的自動提示單選框

本文介紹基於jquery 的 自動提示單選組件QuickSelect  ,筆者對該組件進行修改支持dwr的用法。 

1   QuickSelect  :


 


1.1 數據源:
組件的數據來源方式:data,ajax
data: 簡單數據源
 <script>
    $('#ExampleOne_LocalData').quickselect({
      maxItemsToShow:10,
      data:["Aberdeen", "Ada", "Adamsville", ["Addyston", "Addyston", 'closed'], "Adelphi", "Adena", "Adrian", "Akron"]}) // truncated data...
    </script>
  

ajax:ajax數據源
 <script type="text/javascript">
              $(function(){
                $('#zip').quickselect({
                  ajax:'http://www.test.com/aaa.action',    /* call to url with json formatted array of data */
                  match:'substring',
                  autoSelectFirst:false,
                  mustMatch:true,
                  additionalFields:[$('#city'), $('#state')],
                  formatItem:function(data, index, total){return data[0]+", "+data[1]+" "+data[2]}
                });
              });
            </script>
組件在輸入變化的時候,會發出ajax請求:
http://www.test.com/aaa.action?q=輸入框的值

返回的數據作爲下拉提示框的數據源

1.2 返回數據結構

下拉提示框 的數據源格式 使用 json 格式

1.2.1 描述與提交的值一致的

[a,b,c,....]

1.2.1 描述與提交的值不一致的

[{value:'1',label:'中國'},{value:'2',label:'美國'}........] 



1.3  對 quickselect的擴展

1.3.1增加對javascript的支持




 

<script type="text/javascript">


		$(function(){


		 	$("#input").quickselect({ maxItemsToShow:10,


				  finderFunctionStr:'jsfunction',


				  jsfunction:function(q,callback){


					  var ognl="daoHelper.queryForList(\"SELECT HOSTNAME label,HOSTNASID VALUE  FROM t_cfg_host1_info where HOSTNAME like '%"+q+"%'\")";


					  //var ognl="service.query("+q+")";


					  ctx.eval(ognl,callback);


					  /*


					  service.query(q,calback);


					  */


					  /*


					   $.post("demo_ajax_gethint.asp",{suggest:q},callback);


					  */


				  }


			      });


		      });


		  


	 </script>





finderFunctionStr:查詢數據源的的方法 值可以是 data(簡單數據源),ajax( ajax數據源),jsfunction(對外部javascript支持,此接口比較靈活,可以用於ajax,dwr的擴展)
jsfunction:組件onchange事件時會自動調用的方法
參數:
q :輸入框值
callback: jsfunction的回調函數


補充:
 ctx.eval(ognl,callback);
service.query(q,calback);
dwr的調用 
ctx,service 是dwr中定義的服務 。
eval是ctx的方法



2 源碼解讀

2.1  組件構成

$input_element :輸入框

$result_list :下拉選擇提示

$results_mask:遮罩層 ,當輸入變化進行查詢的時候,等待時出現的層

2.2 組件查詢過程解析


當用戶輸入,監聽輸入框的keyup事件 ,並與上次的輸入的字符進行對比,如果發生變法,則確認爲一個change事件

組件監聽change事件,通過 finder找出查詢數據源的方法,並調用該方法。

方法返回後,數據結構如1.2 所描述,然後更新$result_list 對象,彈出該對象 

用戶可以輸入上下鍵選擇,按enter確認選擇,或者用鼠標點擊選擇。




2.2.1 finder 

QuickSelect.finders = {  
    data : function( q,callback){  
      callback(this.options.data);  
    },  
    ajax  : function( q,callback){  
      var url = this.options.ajax + "?q=" + encodeURI(q);  
        for(var i in this.options.ajaxParams){  
          if(this.options.ajaxParams.hasOwnProperty(i)){  
              url += "&" + i + "=" + encodeURI(this.options.ajaxParams[i]);  
            }  
        }  
      $.getJSON(url, callback);  
    },  
      
    dwrexpression:function( ognl,callback){  
        ctx.eval(ognl,callback);  
        //alert("daoHelper.queryForList(\"SELECT HOSTNAME label, HOSTNASID value  FROM t_cfg_host1_info where HOSTNAME like '%"+ognl+"%'\")");  
    },  
    jsfunction:function(q,callback){  
           
        this.options.jsfunction(q,callback);  
        //ctx.eval(ognl,callback);  
        //alert("daoHelper.queryForList(\"SELECT HOSTNAME label, HOSTNASID value  FROM t_cfg_host1_info where HOSTNAME like '%"+ognl+"%'\")");  
    }  
      
  };  
 
  if(options.finderFunctionStr==='dwrexpression'){   
        options.finderFunction = QuickSelect.finders[options.finderFunctionStr];  
    }else if(options.finderFunctionStr==='jsfunction'){  
        options.finderFunction = QuickSelect.finders[options.finderFunctionStr];  
           
    }else{  
         options.finderFunction = options.finderFunction || QuickSelect.finders[!options.data ? 'ajax': 'data'];  
        // console.log(options.finderFunction);  
          if(options.finderFunction==='data' || options.finderFunction==='ajax'  ) options.finderFunction = QuickSelect.finders[options.finderFunction];  
        // console.log(options.finderFunction);  
        // matchMethod: (quicksilver | contains | startsWith | <custom>). Defaults to 'quicksilver' if quicksilver.js is loaded / 'contains' otherwise.  
  
    }  
如果有ajax 或者data屬性,
options.finderFunction = QuickSelect.finders[options.finderFunction]

如果options.finderFunctionStr==='jsfunction' 則 使用 jsfunction
finders是定義數據源查找的js方法 。

2.2.2 matcher

排序,根據輸入的值的匹配程度去排序


3附件:源碼

// Credit to Anders Retteras for adding functionality preventing onblur event to fire on text input when clicking on scrollbars in MSIE / Opera.
// Minified version created at http://jsutility.pjoneil.net/ by running Obfuscation with all options unchecked, and then Compact.
// Packed version created at http://jsutility.pjoneil.net/ by running Compress on the Minified version.
//update by [email protected] ,add the support of the method for javascript and dwr 
 
function object(obj){
  var s = function(){};
  s.prototype = obj;
  return new s();
}

var QuickSelect;

(function($){
  // The job of the QuickSelect object is to encapsulate all the state of a select control and manipulate the DOM and interface events.
  QuickSelect = function( $input_element, options){
    var self = this;
    
   
    $input_element = $($input_element);
    $input_element.attr('autocomplete', 'off');
    self.options = options;

    // Save the state of the control
      // AllItems: hash of "index" -> [items], where index is the query that retrieves or filters the results.
      // clickedLI: just a state variable for IE scrollbars.
      self.AllItems = {};
      var clickedLI = false,
          activeSelection = -1,
          hasFocus = false,
          last_keyCode,
          previous_value,
          timeout,
          ie_stupidity = false,
          $results_list,
          $results_mask;
      if(/MSIE (\d+\.\d+);/.test(navigator.userAgent)){ //test for MSIE x.x;
        if(Number(RegExp.$1) <= 7) ie_stupidity=true;
      }

    // Create the list DOM
      
      $results_list = $('<div class="'+options.resultsClass+'" style="display:block;position:absolute;z-index:9999;"></div>').hide();
      // Supposedly if we position an iframe behind the results list, before we position the results list, it will hide select elements in IE.
      $results_mask = $('<iframe />');
      $results_mask.css({border:'none',position:'absolute'});
    	if(options.width>0){
    	  $results_list.css("width", options.width);
    	  $results_mask.css("width", options.width);
    	}
    	$('body').append($results_list);
    	$results_list.hide(); // in case for some reason it didn't hide before appending it?
      if(ie_stupidity) $('body').append($results_mask);

    // Set up all of the methods
      self.getLabel = function(item){
        return item['label']||item['LABEL']||item.label || (typeof(item)==='string' ? item : item[0]) || ''; // hash:item.label; string:item; array:item[0]
      };
      var getValues = function(item){
        return item['value']||item['VALUE']||item.values || (item.value ? [item.value] : (typeof(item)==='string' ? [item] : item)) || []; // hash:item.values || item.value; string:item; array:item[1..end]
      };
     	var moveSelect = function(step_or_li){
    		var lis = $('li', $results_list);
    		if(!lis) return;

     	  if(typeof(step_or_li)==="number") activeSelection = activeSelection + step_or_li;
     	  else activeSelection = lis.index(step_or_li);

    		if(activeSelection < 0) activeSelection = 0;
  		  else if(activeSelection >= lis.size()) activeSelection = lis.size() - 1;

    		lis.removeClass(options.selectedClass);
    		$(lis[activeSelection]).addClass(options.selectedClass);

        if(options.autoFill && self.last_keyCode != 8){ // autoFill value, if option is set and the last user key pressed wasn't backspace
          // 1. Fill in the value (keep the case the user has typed)
      		$input_element.val(previous_value + $(lis[activeSelection]).text().substring(previous_value.length));
      		// 2. SELECT the portion of the value not typed by the user (so the next character will erase if they continue typing)
            var sel_start = previous_value.length,
                sel_end = $input_element.val().length,
                field = $input_element.get(0);
          	if(field.createTextRange){
          		var selRange = field.createTextRange();
          		selRange.collapse(true);
          		selRange.moveStart("character", sel_start);
          		selRange.moveEnd("character", sel_end);
          		selRange.select();
          	} else if(field.setSelectionRange){
          		field.setSelectionRange(sel_start, sel_end);
          	} else if(field.selectionStart){
        			field.selectionStart = sel_start;
        			field.selectionEnd = sel_end;
        		}
          	field.focus();
      	}
    	};
      var hideResultsNow = function(){
        if(timeout){clearTimeout(timeout);}
    		$input_element.removeClass(options.loadingClass);
    		if($results_list.is(":visible")) $results_list.hide();
    		if($results_mask.is(":visible")) $results_mask.hide();
    		activeSelection = -1;
      };
      self.selectItem = function(li, from_hide_now_function){
    		if(!li){
    			li = document.createElement("li");
    			li.item = '';
    		}
        var label = self.getLabel(li.item),
    		    values = getValues(li.item);
    		$input_element.lastSelected = label;
    		$input_element.val(label); // Set the visible value
    		previous_value = label;
    		$results_list.empty(); // clear the results list
        $(options.additionalFields).each(function(i,input){$(input).val(values[i+1]);}); // set the additional fields' values
        if(!from_hide_now_function)hideResultsNow(); // hide the results when something is selected
    		if(options.onItemSelect)setTimeout(function(){ options.onItemSelect(li); }, 1); // run the user callback, if set
    		return true;
      };
      var selectCurrent = function(){
        var li = $("li."+options.selectedClass, $results_list).get(0);
    		if(li){
    			return self.selectItem(li);
    		} else {
          // No current selection - blank the fields if options.exactMatch and current value isn't valid.
          if(options.exactMatch){
            $input_element.val('');
            $(options.additionalFields).each(function(i,input){$(input).val('');});
          }
          return false;
    		}
      };
      var repopulate_items = function(items){
        // Clear the results to begin:
        $results_list.empty();
        // If the field no longer has focus or if there are no matches, forget it.
 //alert(hasFocus+"--"+items);
        //!hasFocus ||
    		if(  items === null || items.length === 0) return hideResultsNow();
   // 		 alert(hasFocus);
      	var ul = document.createElement("ul"),
      	    total_count = items.length,
        // hover functions
            hf = function(){ moveSelect(this); },
            bf = function(){},
            cf = function(e){ e.preventDefault(); e.stopPropagation(); self.selectItem(this); };
    		$results_list.append(ul);
      	// limited results to a max number
      	if(options.maxVisibleItems > 0 && options.maxVisibleItems < total_count) total_count = options.maxVisibleItems;

        // Add each item:
        for(var i=0; i<total_count; i++){
          var item = items[i],
      		    li = document.createElement("li");
          $results_list.append(li);
    			$(li).text(options.formatItem ? options.formatItem(item, i, total_count) : self.getLabel(item));

          // Save the extra values (if any) to the li
    			li.item = item;
          // Set the class name, if specified
    			if(item.className) li.className = item.className;
      		ul.appendChild(li);
      		$(li).hover(hf, bf).click(cf);
        }

        // Lastly, remove the loading class.
        $input_element.removeClass(options.loadingClass);
        return true;
      };
      var itemList;
      var repopulate = function(q,callback){
    	  var ognl;
    	  if(options.finderFunctionStr==='dwrexpression'){
    		  ognl=options.dwrognl.replace('{value}',q);
        	}else{
        		 ognl=q; 
        	}
    	  queryLabel=q;
        options.finderFunction.apply(self,[ognl,function(data){
        	itemList=data;
        repopulate_items(options.matchMethod.apply(self,[q,data]));
          callback();
        }]);
      };
      
      var repopulate2 = function(q, callback){
    	  repopulate_items(options.matchMethod.apply(self,[q,itemList]));
    	  callback();
      };
      var show_results = function(){
      	// pos: get the position of the input field before showing the results_list (in case the DOM is shifted)
      	// iWidth: either use the specified width, or autocalculate based on form element
      	var pos = $input_element.offset(),
      	    iWidth = (options.width > 0 ? options.width : $input_element.width()),
            $lis = $('li', $results_list);
      	// reposition
      	$results_list.css({
      		width: parseInt(iWidth,10) + "px",
      		top: pos.top + $input_element.height() + 5 + "px",
      		left: pos.left + "px"
      	});
      	if(ie_stupidity){$results_mask.css({
      		width: parseInt(iWidth,10) - 2 + "px",
      		top: pos.top + $input_element.height() + 6 + "px",
      		left: pos.left + 1 + "px",
      		height: $results_list.height() - 2+'px'
      	}).show();}
      	$results_list.show();
        // Option autoSelectFirst, and Option selectSingleMatch (activate the first item if only item)
        if(options.autoSelectFirst || (options.selectSingleMatch && $lis.length == 1)) moveSelect($lis.get(0));
      };
      var onChange = function(){
    		// ignore if non-consequence key is pressed (such as shift, ctrl, alt, escape, caps, pg up/down, home, end, arrows)
    	  if(itemList==null){
    		  return ;
    	  }
    	 // alert("change");
    	   
    		if(last_keyCode >= 9 && last_keyCode <= 45){return;}
        // compare with previous value / store new previous value
    		var q = $input_element.val();
    		if(q == previous_value) return;
    		previous_value = q;
        // if enough characters have been typed, load/populate the list with whatever matches and show the results list.
    		if(q.length >= options.minChars){
    			$input_element.addClass(options.loadingClass);
          // Populate the list, then show the list.
    		 
          repopulate2( q,show_results);
          
    		} else { // if too short, hide the list.
    		  if(q.length === 0 && (options.onBlank ? options.onBlank() : true)) // onBlank callback
    		    $(options.additionalFields).each(function(i,input){input.value='';});
    			$input_element.removeClass(options.loadingClass);
    			$results_list.hide();
    			$results_mask.hide();
    		}
      };
      var queryLabel;
      var onQuery = function(){
    	  //查詢事件
    	  var q = $input_element.val();  
    	   previous_value=q;
  		$input_element.addClass(options.loadingClass);
  		 
  		if(itemList==null){
  			repopulate(q,show_results);
  			//alert("repopulate");
  		}else{
  			if(q.indexOf(queryLabel)>-1){
  				repopulate2(q,show_results);
  			}else{
  				repopulate(q,show_results);
  			}
  			
  			//alert("repopulate2");
  		}
      };
    // Set up the interface events
      // Mark that actual item was clicked if clicked item was NOT a DIV, so the focus doesn't leave the items.
      $results_list.mousedown(function(e){if(e.srcElement)clickedLI=e.srcElement.tagName!='DIV';});
     
      $input_element.keyup(function(e){
    	   
        last_keyCode = e.keyCode;
//        if(e.keyCode==13){
//        	
//        }
       	 
        switch(e.keyCode){
          case 38: // Up arrow - select prev item in the drop-down
            e.preventDefault();
            moveSelect(-1);
            break;
          case 40: // Down arrow - select next item in the drop-down
            e.preventDefault();
            if(!$results_list.is(":visible")){
              show_results();
              moveSelect(0);!$results_list.is(":visible")
            }else{moveSelect(1);}
            break;
          case 13: // Enter/Return - select item and stay in field
        	 // alert($results_list.css('display'));
        	/**var q = $input_element.val();  
      		if(q != previous_value) {
      			onQuery();
      			
      		}else if($results_list.is(":visible")){
      			e.preventDefault();
                $input_element.select();
                var li = $("li."+options.selectedClass, $results_list).get(0);
        		self.selectItem(li);
                $results_list.hide();
      		}
      		
         */
        	  e.preventDefault();
              $input_element.select();
              var li = $("li."+options.selectedClass, $results_list).get(0);
      		self.selectItem(li);
              $results_list.hide();
            break;
          case 9:  // Tab - select the currently selected, let the onblur happen
            // selectCurrent();
            break;
          case 27: // Esc - deselect any active selection, hide the drop-down but stay in the field
            // Reset the active selection IF must be exactMatch and is not an exact match.
            if(activeSelection > -1 && options.exactMatch && $input_element.val()!=$($('li', $results_list).get(activeSelection)).text()){activeSelection = -1;}
        		$('li', $results_list).removeClass(options.selectedClass);
         	  hideResultsNow();
            e.preventDefault();
            break;
          default:
        	  var q = $input_element.val();  
          	if(q != previous_value) {
    			onQuery();
    			
    		}else if($results_list.is(":visible")){
    			e.preventDefault();
              $input_element.select();
              var li = $("li."+options.selectedClass, $results_list).get(0);
      		self.selectItem(li);
              $results_list.hide();
    		}  
          
          //alert(q);
            /**if(timeout){clearTimeout(timeout);}
            timeout = setTimeout(onChange, options.delay);*/
        	  /*if(itemList!=null&& $results_list.is(":visible")){
        		 
           	   	repopulate2(q,show_results);
        	  }*/
            break;
        } 
      }).focus(function(){
    		// track whether the field has focus, we shouldn't process any results if the field no longer has focus
    		hasFocus = true;
    	}).blur(function(e){
        if(activeSelection>-1){selectCurrent();}
    		hasFocus = false;
    		if(timeout){clearTimeout(timeout);}
    		timeout = setTimeout(function(){
    		  hideResultsNow();
          // Select null element, IF options.exactMatch and there is no selection.
          // !! CLEARS THE FIELD IF YOU BLUR AFTER CHOOSING THE ITEM AND RESULTS ARE ALREADY CLOSED!
          if(options.exactMatch && $input_element.val() != $input_element.lastSelected){self.selectItem(null,true);}
    		}, 200);
    	}); 
  };

  QuickSelect.matchers = {
    quicksilver : function(q,data){
			var match_query, match_label, self=this;
      match_query = (self.options.matchCase ? q : q.toLowerCase());
			self.AllItems[match_query] = [];
      for(var i=0;i<data.length;i++){
        match_label = (self.options.matchCase ? self.getLabel(data[i]) : self.getLabel(data[i]).toLowerCase());
        // Filter by match/no-match
        if(match_label.score(match_query)>0){self.AllItems[match_query].push(data[i]);}
			}
      // Sort by match relevance
			return self.AllItems[match_query].sort(function(a,b){
        // Normalize a & b
        a = (self.options.matchCase ? self.getLabel(a) : self.getLabel(a).toLowerCase());
        b = (self.options.matchCase ? self.getLabel(b) : self.getLabel(b).toLowerCase());
        // Score a & b
    	  a = a.score(match_query);
        b = b.score(match_query);
        // Compare a & b by score
        return(a > b ? -1 : (b > a ? 1 : 0));
      });
    },
    contains : function(q,data){
			var match_query, match_label, self=this;
      match_query = (self.options.matchCase ? q : q.toLowerCase());
      self.AllItems[match_query] = [];
      for(var i=0;i<data.length;i++){
        match_label = (self.options.matchCase ? self.getLabel(data[i]) : self.getLabel(data[i]).toLowerCase());
        if(match_label.indexOf(match_query)>-1){self.AllItems[match_query].push(data[i]);}
      }
			return self.AllItems[match_query].sort(function(a,b){
        // Normalize a & b
        a = (self.options.matchCase ? self.getLabel(a) : self.getLabel(a).toLowerCase());
        b = (self.options.matchCase ? self.getLabel(b) : self.getLabel(b).toLowerCase());
        // Get proximities
        var a_proximity = a.indexOf(match_query);
        var b_proximity = b.indexOf(match_query);
        // Compare a & b by match proximity to beginning of label, secondly alphabetically
        return(a_proximity > b_proximity ? -1 : (a_proximity < b_proximity ? 1 : (a > b ? -1 : (b > a ? 1 : 0))));
      });
    },
    startsWith : function(q,data){
			var match_query, match_label, self=this;
      match_query = (self.options.matchCase ? q : q.toLowerCase());
      self.AllItems[match_query] = [];
      for(var i=0;i<data.length;i++){
        match_label = (self.options.matchCase ? self.getLabel(data[i]) : self.getLabel(data[i]).toLowerCase());
        if(match_label.indexOf(match_query)===0){self.AllItems[match_query].push(data[i]);}
      }
			return self.AllItems[match_query].sort(function(a,b){
        // Normalize a & b
        a = (self.options.matchCase ? self.getLabel(a) : self.getLabel(a).toLowerCase());
        b = (self.options.matchCase ? self.getLabel(b) : self.getLabel(b).toLowerCase());
        // Compare a & b alphabetically
        return(a > b ? -1 : (b > a ? 1 : 0));
      });
    }
  };

  QuickSelect.finders = {
    data : function( q,callback){
      callback(this.options.data);
    },
    ajax  : function( q,callback){
      var url = this.options.ajax + "?q=" + encodeURI(q);
    	for(var i in this.options.ajaxParams){
    	  if(this.options.ajaxParams.hasOwnProperty(i)){
    		  url += "&" + i + "=" + encodeURI(this.options.ajaxParams[i]);
    		}
    	}
      $.getJSON(url, callback);
    },
    
    dwrexpression:function( ognl,callback){
    	ctx.eval(ognl,callback);
    	//alert("daoHelper.queryForList(\"SELECT HOSTNAME label, HOSTNASID value  FROM t_cfg_host1_info where HOSTNAME like '%"+ognl+"%'\")");
    },
    jsfunction:function(q,callback){
    	 
    	this.options.jsfunction(q,callback);
    	//ctx.eval(ognl,callback);
    	//alert("daoHelper.queryForList(\"SELECT HOSTNAME label, HOSTNASID value  FROM t_cfg_host1_info where HOSTNAME like '%"+ognl+"%'\")");
    }
    
  };

  $.fn.quickselect = function(options, data){
    if(options == 'instance' && $(this).data('quickselect')) return $(this).data('quickselect');

    // Prepare options and set defaults.
  	options = options || {};
  	options.data          = (typeof(options.data) === "object" && options.data.constructor == Array) ? options.data : undefined;
  	options.ajaxParams    = options.ajaxParams || {};
  	options.delay         = options.delay || 400;
  	if(!options.delay) options.delay = (!options.ajax ? 400 : 10);
  	options.minChars      = options.minChars || 1;
  	options.cssFlavor     = options.cssFlavor || 'quickselect';
  	options.inputClass    = options.inputClass || options.cssFlavor+"_input";
  	options.loadingClass  = options.loadingClass || options.cssFlavor+"_loading";
  	options.resultsClass  = options.resultsClass || options.cssFlavor+"_results";
  	options.selectedClass = options.selectedClass || options.cssFlavor+"_selected";
// wrap entire thing: .ui-widget
// default item:      .ui-state-default
// active / hover:    .ui-state-hover
    // finderFunction: (data | ajax | <custom>)
  	if(options.finderFunctionStr==='dwrexpression'){ 
  		options.finderFunction = QuickSelect.finders[options.finderFunctionStr];
  	}else if(options.finderFunctionStr==='jsfunction'){
  		options.finderFunction = QuickSelect.finders[options.finderFunctionStr];
  		 
  	}else{
  		 options.finderFunction = options.finderFunction || QuickSelect.finders[!options.data ? 'ajax': 'data'];
  	    // console.log(options.finderFunction);
  	      if(options.finderFunction==='data' || options.finderFunction==='ajax'  ) options.finderFunction = QuickSelect.finders[options.finderFunction];
  	    // console.log(options.finderFunction);
  	    // matchMethod: (quicksilver | contains | startsWith | <custom>). Defaults to 'quicksilver' if quicksilver.js is loaded / 'contains' otherwise.

  	}
       options.matchMethod   = options.matchMethod || QuickSelect.matchers[(typeof(''.score) === 'function' && 'l'.score('l') == 1 ? 'quicksilver' : 'contains')];
      if(options.matchMethod==='quicksilver' || options.matchMethod==='contains' || options.matchMethod==='startsWith') options.matchMethod = QuickSelect.matchers[options.matchMethod];
  	if(options.matchCase === undefined) options.matchCase = false;
  	if(options.exactMatch === undefined) options.exactMatch = false;
  	if(options.autoSelectFirst === undefined) options.autoSelectFirst = true;
  	if(options.selectSingleMatch === undefined) options.selectSingleMatch = true;
  	if(options.additionalFields === undefined) options.additionalFields = $('nothing');
  	options.maxVisibleItems = options.maxVisibleItems || -1;
  	if(options.autoFill === undefined || options.matchMethod != 'startsWith'){options.autoFill = false;} // if you're not using the startsWith match, it really doesn't help to autoFill.
  	options.width         = parseInt(options.width, 10) || 0;
    
    // Make quickselects.
  	return this.each(function(){
  		var input = this,
          my_options = object(options);

      if(input.tagName == 'INPUT'){
        // Text input: ready for QuickSelect-ing!
  	    var qs = new QuickSelect( input, my_options);
  	     
  	    $(input).data('quickselect', qs);

  		} else if(input.tagName == 'SELECT'){
        // Select input: transform into Text input, then make QuickSelect.
      	my_options.delay = my_options.delay || 10; // for selects, we know we're not doing ajax, so we might as well speed up
        my_options.finderFunction = 'data';

        // Record the html stuff from the select
        var name = input.name,
            id = input.id,
            className = input.className,
            accesskey = $(input).attr('accesskey'),
            tabindex = $(input).attr('tabindex'),
            selected_option = $("option:selected", input).get(0);

        // Collect the data from the select/options, remove them and create an input box instead.
  		  my_options.data = [];
  		  $('option', input).each(function(i,option){
  		    my_options.data.push({label : $(option).text(), values : [option.value, option.value], className : option.className});
  		  });

        // Create the text input and hidden input
        var text_input = $("<input type='text' class='"+className+"' id='"+id+"_quickselect' accesskey='"+accesskey+"' tabindex='"+tabindex+"' />");
        if(selected_option){text_input.val($(selected_option).text());}
        var hidden_input = $("<input type='hidden' id='"+id+"' name='"+input.name+"' />");
        if(selected_option){hidden_input.val(selected_option.value);}

        // From a select, we need to work off two values, from the label and value of the select options.
        // Record the first (label) in the text input, the second (value) in the hidden input.
        my_options.additionalFields = hidden_input;
        
        // Replace the select with a quickselect text_input
      	$(input).after(text_input).after(hidden_input).remove(); // add text input, hidden input, remove select.
        // console.log(my_options);
      	text_input.quickselect(my_options); // make the text input into a QuickSelect.
      }
    });
  };
})(jQuery);


 


發佈了22 篇原創文章 · 獲贊 1 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章