var Autocomplete=function(b,a){this.el=$(b);this.id=this.el.identify();this.el.setAttribute("autocomplete","off");this.suggestions=[];this.data=[];this.badQueries=[];this.selectedIndex=-1;this.currentValue=this.el.value;this.intervalId=0;this.cachedResponse=[];this.instanceId=null;this.onChangeInterval=null;this.ignoreValueChange=false;this.serviceUrl=a.serviceUrl;this.options={autoSubmit:false,minChars:1,maxHeight:300,deferRequestBy:0,width:0,container:null};if(a){Object.extend(this.options,a)}if(Autocomplete.isDomLoaded){this.initialize()}else{Event.observe(document,"dom:loaded",this.initialize.bind(this),false)}};Autocomplete.instances=[];Autocomplete.isDomLoaded=false;Autocomplete.getInstance=function(c){var b=Autocomplete.instances;var a=b.length;while(a--){if(b[a].id===c){return b[a]}}};Autocomplete.highlight=function(b,a){return b.replace(a,function(c){return"<strong>"+c+"</strong>"})};Autocomplete.prototype={killerFn:null,initialize:function(){var a=this;this.killerFn=function(c){if(!$(Event.element(c)).up(".autocomplete")){a.killSuggestions();a.disableKillerFn()}}.bindAsEventListener(this);if(!this.options.width){this.options.width=this.el.getWidth()}var b=new Element("div",{style:"position:absolute;"});b.update('<div class="autocomplete-w1"><div class="autocomplete-w2"><div class="autocomplete" id="Autocomplete_'+this.id+'" style="display:none; width:'+this.options.width+'px;"></div></div></div>');this.options.container=$(this.options.container);if(this.options.container){this.options.container.appendChild(b);this.fixPosition=function(){}}else{document.body.appendChild(b)}this.mainContainerId=b.identify();this.container=$("Autocomplete_"+this.id);this.fixPosition();Event.observe(this.el,window.opera?"keypress":"keydown",this.onKeyPress.bind(this));Event.observe(this.el,"keyup",this.onKeyUp.bind(this));Event.observe(this.el,"blur",this.enableKillerFn.bind(this));Event.observe(this.el,"focus",this.fixPosition.bind(this));this.container.setStyle({maxHeight:this.options.maxHeight+"px"});this.instanceId=Autocomplete.instances.push(this)-1},fixPosition:function(){var a=this.el.cumulativeOffset();$(this.mainContainerId).setStyle({top:(a.top+this.el.getHeight())+"px",left:a.left+"px"})},enableKillerFn:function(){Event.observe(document.body,"click",this.killerFn)},disableKillerFn:function(){Event.stopObserving(document.body,"click",this.killerFn)},killSuggestions:function(){this.stopKillSuggestions();this.intervalId=window.setInterval(function(){this.hide();this.stopKillSuggestions()}.bind(this),300)},stopKillSuggestions:function(){window.clearInterval(this.intervalId)},onKeyPress:function(a){if(!this.enabled){return}switch(a.keyCode){case Event.KEY_ESC:this.el.value=this.currentValue;this.hide();break;case Event.KEY_TAB:case Event.KEY_RETURN:if(this.selectedIndex===-1){this.hide();return}this.select(this.selectedIndex);if(a.keyCode===Event.KEY_TAB){return}break;case Event.KEY_UP:this.moveUp();break;case Event.KEY_DOWN:this.moveDown();break;default:return}Event.stop(a)},onKeyUp:function(a){switch(a.keyCode){case Event.KEY_UP:case Event.KEY_DOWN:return}clearInterval(this.onChangeInterval);if(this.currentValue!==this.el.value){if(this.options.deferRequestBy>0){this.onChangeInterval=setInterval((function(){this.onValueChange()}).bind(this),this.options.deferRequestBy)}else{this.onValueChange()}}},onValueChange:function(){clearInterval(this.onChangeInterval);this.currentValue=this.el.value;this.selectedIndex=-1;if(this.ignoreValueChange){this.ignoreValueChange=false;return}if(this.currentValue===""||this.currentValue.length<this.options.minChars){this.hide()}else{this.getSuggestions()}},getSuggestions:function(){var a=this.cachedResponse[this.currentValue];if(a&&Object.isArray(a.suggestions)){this.suggestions=a.suggestions;this.data=a.data;this.suggest()}else{if(!this.isBadQuery(this.currentValue)){new Ajax.Request(this.serviceUrl,{parameters:{query:this.currentValue},onComplete:this.processResponse.bind(this),method:"get"})}}},isBadQuery:function(b){var a=this.badQueries.length;while(a--){if(b.indexOf(this.badQueries[a])===0){return true}}return false},hide:function(){this.enabled=false;this.selectedIndex=-1;this.container.hide()},suggest:function(){if(this.suggestions.length===0){this.hide();return}var b=[];var a=new RegExp("\\b"+this.currentValue.match(/\w+/g).join("|\\b"),"gi");this.suggestions.each(function(d,c){b.push((this.selectedIndex===c?'<div class="selected"':"<div"),' title="',d,'" onclick="Autocomplete.instances[',this.instanceId,"].select(",c,');" onmouseover="Autocomplete.instances[',this.instanceId,"].activate(",c,');">',Autocomplete.highlight(d,a),"</div>")}.bind(this));this.enabled=true;this.container.update(b.join("")).show()},processResponse:function(c){var a;try{a=c.responseText.evalJSON();if(!Object.isArray(a.data)){a.data=[]}}catch(b){return}this.cachedResponse[a.query]=a;if(a.suggestions.length===0){this.badQueries.push(a.query)}if(a.query===this.currentValue){this.suggestions=a.suggestions;this.data=a.data;this.suggest()}},activate:function(a){var b=this.container.childNodes;var c;if(this.selectedIndex!==-1&&b.length>this.selectedIndex){b[this.selectedIndex].className=""}this.selectedIndex=a;if(this.selectedIndex!==-1&&b.length>this.selectedIndex){c=b[this.selectedIndex];c.className="selected"}return c},deactivate:function(b,a){b.className="";if(this.selectedIndex===a){this.selectedIndex=-1}},select:function(b){var a=this.suggestions[b];if(a){this.el.value=a;if(this.options.autoSubmit&&this.el.form){this.el.form.submit()}this.ignoreValueChange=true;this.hide();this.onSelect(b)}},moveUp:function(){if(this.selectedIndex===-1){return}if(this.selectedIndex===0){this.container.childNodes[0].className="";this.selectedIndex=-1;this.el.value=this.currentValue;return}this.adjustScroll(this.selectedIndex-1)},moveDown:function(){if(this.selectedIndex===(this.suggestions.length-1)){return}this.adjustScroll(this.selectedIndex+1)},adjustScroll:function(b){var a=this.container;var f=this.activate(b);var c=f.offsetTop;var d=a.scrollTop;var e=d+this.options.maxHeight-25;if(c<d){a.scrollTop=c}else{if(c>e){a.scrollTop=c-this.options.maxHeight+25}}this.el.value=this.suggestions[b]},onSelect:function(a){(this.options.onSelect||Prototype.emptyFunction)(this.suggestions[a],this.data[a])}};Event.observe(document,"dom:loaded",function(){Autocomplete.isDomLoaded=true},false);