var AutoComplete=Class.create({selector:null,input:null,_timeout:null,visible:false,drawn:false,_hideTimeout:null,options:null,initialize:function(a,b,c){this.action=b;this.input=$(a);this.input.autocomplete="off";this.options=new AutoComplete.Options(c||{});if(!this.input)alert("No input field/binding field given or found");if(!this.action)alert("No action url specified");this.selector=document.createElement("select");Event.observe(this.input,"focus",this._onInputFocus.bindAsEventListener(this));Event.observe(this.input,"keydown",this._onInputKeyDown.bindAsEventListener(this));Event.observe(this.input,"blur",this._onInputBlur.bindAsEventListener(this));Event.observe(this.selector,"blur",this._onSelectorBlur.bindAsEventListener(this));Event.observe(this.selector,"focus",this._onSelectorFocus.bindAsEventListener(this));Event.observe(this.selector,"change",this._onSelectorChange.bindAsEventListener(this));Event.observe(window,"resize",this._reposition.bind(this));Event.observe(window,"scroll",this._reposition.bind(this))},_onInputFocus:function(a){this._onSelectorFocus(a)},_onSelectorBlur:function(a){this._onInputBlur(a)},_onInputBlur:function(a){this._hideTimeout=setTimeout(this._checkOnBlur.bind(this),100)},_checkOnBlur:function(){this._hideTimeout=null;this.hide()},_onInputKeyUp:function(a){this._suggest(a)&&Event.stop(a)},_onInputKeyDown:function(a){this._suggest(a)&&Event.stop(a)},_onSelectorFocus:function(a){if(this._hideTimeout){clearTimeout(this._hideTimeout);this._hideTimeout=null}},_onSelectorChange:function(a){this.select()},draw:function(){if(this.drawn)return;if(this.options.cssClass)this.selector.className=this.options.cssClass;Element.setStyle(this.selector,{display:"none",position:"absolute",width:this.input.offsetWidth+"px"});this.selector.size=this.options.size;document.body.appendChild(this.selector);this.input.autocomplete="off";this.drawn=true},hide:function(){if(!this.drawn||!this.visible)return;this.visible=false;Element.setStyle(this.selector,{display:"none"});this.selector.options.length=0;setTimeout(this._restoreFocus.bind(this),50)},_restoreFocus:function(){this.input.focus()},show:function(){if(!this.drawn)this.draw();var a=null;if(this.selector.options.length){Element.setStyle(this.selector,{display:"inline"});this._reposition();this.visible=true}},_cancelTimeout:function(){if(this._timeout){clearTimeout(this._timeout);this._timeout=null}},_suggest:function(a){this._cancelTimeout();var b=Event.keyPressed(a);var c=[20,16,17,91,121,122,123,124,125,126,127,128,129,130,131,132,45,36,35,33,34,144,145,44,19,93];if(c.indexOf(b)>-1)return false;switch(b){case Event.KEY_LEFT:case Event.KEY_RIGHT:return false;break;case Event.KEY_TAB:case Event.KEY_BACKSPACE:case 46:this.cancel();return false;break;case Event.KEY_RETURN:if(this.visible){this.select();return true}return false;break;case Event.KEY_ESC:this.cancel();return true;break;case Event.KEY_UP:case Event.KEY_DOWN:this._interact(a);return true;break;default:break}if(this.input.value.length>=this.options.threshold-1){this._timeout=setTimeout(this._sendRequest.bind(this),1e3*this.options.delay)}return false},_sendRequest:function(){this._request=new Ajax.Request(this.action+this.input.value,{onComplete:this._process.bind(this),method:this.options.requestMethod})},_reposition:function(){if(!this.drawn)return;var a=Position.cumulativeOffset(this.input);a.push(a[0]+this.input.offsetWidth);a.push(a[1]+this.input.offsetHeight);Element.setStyle(this.selector,{left:a[0]+"px",top:a[3]+"px"})},_process:function(a,b){this.selector.options.length=0;switch(this.options.resultFormat){case AutoComplete.Options.RESULT_FORMAT_XML:this._parseXML(a.responseXML);break;case AutoComplete.Options.RESULT_FORMAT_JSON:if(!b){b=a.responseText&&a.responseText.isJSON()?a.responseText.evalJSON():null}this._parseJSON(b);break;case AutoComplete.Options.RESULT_FORMAT_TEXT:this._parseText(a.responseText);break;default:alert("Unable to parse result type. Make sure you've set the resultFormat option correctly");break}if(this.selector.options.length>this.options.size)this.selector.size=this.options.size;else this.selector.size=this.selector.options.length>1?this.selector.options.length:2;if(this.selector.options.length){this.selector.selectedIndex=-1;this.show()}else this.cancel()},_parseXML:function(a){var b=null;for(var c=0;c<a.childNodes.length;c++){if(a.childNodes[c].tagName){b=a.childNodes[c].childNodes}}if(!b){alert("Could not parse response XML.");return}for(c=0;c<b.length;c++){suggestion=b.item(c).firstChild.nodeValue;this._addOption(suggestion)}},_parseJSON:function(a){if(!a)a=[];for(i=0;i<a.length;i++)this._addOption(a[i])},_parseText:function(a){var b=(a||"").split(/\n/);for(i=0;i<b.length;i++)this._addOption(b[i])},_addOption:function(a){var b=new Option(a,a);Prototype.Browser.IE?this.selector.add(b):this.selector.add(b,null)},cancel:function(){this.hide()},select:function(){if(this.selector.options.length)this.input.value=this.selector.options[this.selector.selectedIndex].value;this.cancel();if(typeof this.options.onSelect=="function"){this.options["onSelect"](this.input)}},_interact:function(a){if(!this.visible)return;var b=Event.keyPressed(a);if(b!=Event.KEY_UP&&b!=Event.KEY_DOWN)return;var c=this.selector.options.length;if(b==Event.KEY_UP){if(this.selector.selectedIndex==0)this.selector.selectedIndex=this.selector.options.length-1;else this.selector.selectedIndex--}else{if(this.selector.selectedIndex==this.selector.options.length-1)this.selector.selectedIndex=0;else this.selector.selectedIndex++}}});AutoComplete.Options=Class.create({size:10,cssClass:null,onSelect:null,threshold:3,delay:.2,requestMethod:"GET",resultFormat:"xml",initialize:function(a){Object.extend(this,a||{})}});Object.extend(AutoComplete.Options,{RESULT_FORMAT_XML:"xml",RESULT_FORMAT_JSON:"json",RESULT_FORMAT_TEXT:"text"});Object.extend(Event,{KEY_BACKSPACE:8,KEY_TAB:9,KEY_RETURN:13,KEY_ESC:27,KEY_LEFT:37,KEY_UP:38,KEY_RIGHT:39,KEY_DOWN:40,KEY_DELETE:46,KEY_SHIFT:16,KEY_CONTROL:17,KEY_CAPSLOCK:20,KEY_SPACE:32,keyPressed:function(a){return Prototype.Browser.IE?window.event.keyCode:a.which}})
