jQuery.autocomplete=function(input,options){var me=this;var $input=$(input).attr("autocomplete","off");if(options.inputClass){$input.addClass(options.inputClass);} var results=document.createElement("div");var $results=$(results).hide().addClass(options.resultsClass).css("position","absolute");if(options.width>0){$results.css("width",options.width);} $("body").append(results);input.autocompleter=me;var timeout=null;var prev="";var active=-1;var cache={};var keyb=false;var hasFocus=false;var lastKeyPressCode=null;var mouseDownOnSelect=false;var hidingResults=false;function flushCache(){cache={};cache.data={};cache.length=0;};flushCache();if(options.data!=null){var sFirstChar="",stMatchSets={},row=[];if(typeof options.url!="string"){options.cacheLength=1;} for(var i=0;i0){sFirstChar=row[0].substring(0,1).toLowerCase();if(!stMatchSets[sFirstChar])stMatchSets[sFirstChar]=[];stMatchSets[sFirstChar].push(row);}} for(var k in stMatchSets){options.cacheLength++;addToCache(k,stMatchSets[k]);}} $input .keydown(function(e){lastKeyPressCode=e.keyCode;switch(e.keyCode){case 38:e.preventDefault();moveSelect(-1);break;case 40:e.preventDefault();moveSelect(1);break;case 9:case 13:if(selectCurrent()){$input.get(0).blur();e.preventDefault();} break;default:active=-1;if(timeout)clearTimeout(timeout);timeout=setTimeout(function(){onChange();},options.delay);break;}}) .focus(function(){hasFocus=true;}) .blur(function(){hasFocus=false;if(!mouseDownOnSelect){hideResults();}});hideResultsNow();function onChange(){if(lastKeyPressCode==46||(lastKeyPressCode>8&&lastKeyPressCode<32))return $results.hide();var v=$input.val();if(v==prev)return;prev=v;if(v.length>=options.minChars){$input.addClass(options.loadingClass);requestData(v);}else{$input.removeClass(options.loadingClass);$results.hide();}};function moveSelect(step){var lis=$("li",results);if(!lis)return;active+=step;if(active<0){active=0;}else if(active>=lis.size()){active=lis.size()-1;} lis.removeClass("ac_over");$(lis[active]).addClass("ac_over");};function selectCurrent(){var li=$("li.ac_over",results)[0];if(!li){var $li=$("li",results);if(options.selectOnly){if($li.length==1)li=$li[0];}else if(options.selectFirst){li=$li[0];}} if(li){selectItem(li);return true;}else{return false;}};function selectItem(li){if(!li){li=document.createElement("li");li.extra=[];li.selectValue="";} var v=$.trim(li.selectValue?li.selectValue:li.innerHTML);input.lastSelected=v;prev=v;$results.html("");$input.val(v);hideResultsNow();if(options.onItemSelect){setTimeout(function(){options.onItemSelect(li)},1);}};function createSelection(start,end){var field=$input.get(0);if(field.createTextRange){var selRange=field.createTextRange();selRange.collapse(true);selRange.moveStart("character",start);selRange.moveEnd("character",end);selRange.select();}else if(field.setSelectionRange){field.setSelectionRange(start,end);}else{if(field.selectionStart){field.selectionStart=start;field.selectionEnd=end;}} field.focus();};function autoFill(sValue){if(lastKeyPressCode!=8){$input.val($input.val()+sValue.substring(prev.length));createSelection(prev.length,sValue.length);}};function showResults(){var pos=findPos(input);var iWidth=(options.width>0)?options.width:$input.width();$results.css({width:parseInt(iWidth)+"px",top:(pos.y+input.offsetHeight)+"px",left:pos.x+"px"}).show();};function hideResults(){if(timeout)clearTimeout(timeout);timeout=setTimeout(hideResultsNow,200);};function hideResultsNow(){if(hidingResults){return;} hidingResults=true;if(timeout){clearTimeout(timeout);} var v=$input.removeClass(options.loadingClass).val();if($results.is(":visible")){$results.hide();} if(options.mustMatch){if(!input.lastSelected||input.lastSelected!=v){selectItem(null);}} hidingResults=false;};function receiveData(q,data){if(data){$input.removeClass(options.loadingClass);results.innerHTML="";if(!hasFocus||data.length==0)return hideResultsNow();if($.browser.msie){$results.append(document.createElement('iframe'));} results.appendChild(dataToDom(data));if(options.autoFill&&($input.val().toLowerCase()==q.toLowerCase()))autoFill(data[0][0]);showResults();}else{hideResultsNow();}};function parseData(data){if(!data)return null;var parsed=[];var rows=data.data.split(options.lineSeparator);for(var i=0;i0)&&(options.maxItemsToShow/g,'>').replace(/"/g,'"').replace(/'/g,''');li.innerHTML=autoResult;li.selectValue=row[0];} var extra=null;if(row.length>1){extra=[];for(var j=1;j0)){$.get(makeUrl(q),function(data){data=parseData(data);addToCache(q,data);receiveData(q,data);},null,'json');}else{$input.removeClass(options.loadingClass);}};function makeUrl(q){var sep=options.url.indexOf('?')==-1?'?':'&';var url=options.url+sep+"q="+encodeURI(q);for(var i in options.extraParams){url+="&"+i+"="+encodeURI(options.extraParams[i]);} return url;};function loadFromCache(q){if(!q)return null;if(cache.data[q])return cache.data[q];if(options.matchSubset){for(var i=q.length-1;i>=options.minChars;i--){var qs=q.substr(0,i);var c=cache.data[qs];if(c){var csub=[];for(var j=0;j0)){$.get(makeUrl(q),function(data){data=parseData(data) addToCache(q,data);findValueCallback(q,data);},null,'json');}else{findValueCallback(q,null);}} function findValueCallback(q,data){if(data)$input.removeClass(options.loadingClass);var num=(data)?data.length:0;var li=null;for(var i=0;i1){extra=[];for(var j=1;joptions.cacheLength){flushCache();cache.length++;}else if(!cache[q]){cache.length++;} cache.data[q]=data;};function findPos(obj){var curleft=obj.offsetLeft||0;var curtop=obj.offsetTop||0;while(obj=obj.offsetParent){curleft+=obj.offsetLeft curtop+=obj.offsetTop} return{x:curleft,y:curtop};}} jQuery.fn.autocomplete=function(url,options,data){options=options||{};options.url=url;options.data=((typeof data=="object")&&(data.constructor==Array))?data:null;options=$.extend({inputClass:"ac_input",resultsClass:"ac_results",lineSeparator:"\n",cellSeparator:"|",minChars:1,delay:400,matchCase:0,matchSubset:1,matchContains:0,cacheLength:1,mustMatch:0,extraParams:{},loadingClass:"ac_loading",selectFirst:false,selectOnly:false,maxItemsToShow:-1,autoFill:false,width:0},options);options.width=parseInt(options.width,10);this.each(function(){var input=this;new jQuery.autocomplete(input,options);});return this;} jQuery.fn.autocompleteArray=function(data,options){return this.autocomplete(null,options,data);} jQuery.fn.indexOf=function(e){for(var i=0;i