var AutoComplete=Class.create({selector:null,input:null,_timeout:null,visible:false,drawn:false,_hideTimeout:null,options:null,initialize:function(input,action,options){this.action=action;this.input=$(input);this.input.autocomplete="off";this.options=new AutoComplete.Options(options||{});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(event){this._onSelectorFocus(event)},_onSelectorBlur:function(event){this._onInputBlur(event)},_onInputBlur:function(event){this._hideTimeout=setTimeout(this._checkOnBlur.bind(this),100)},_checkOnBlur:function(){this._hideTimeout=null;this.hide()},_onInputKeyUp:function(event){this._suggest(event)&&Event.stop(event)},_onInputKeyDown:function(event){this._suggest(event)&&Event.stop(event)},_onSelectorFocus:function(event){if(this._hideTimeout){clearTimeout(this._hideTimeout);this._hideTimeout=null}},_onSelectorChange:function(event){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;if(window.Scriptaculous){new Effect.BlindUp(this.selector,{duration:this.options.delay,queue:'end',afterFinish:function(event){Element.setStyle(this.selector,{display:'none'});this.selector.options.length=0;setTimeout(this._restoreFocus.bind(this),50)}.bind(this)})}else{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 trigger=null;if(this.selector.options.length){if(window.Scriptaculous){new Effect.BlindDown(this.selector,{duration:this.options.delay,queue:'end'})}else{Element.setStyle(this.selector,{display:'inline'})}this._reposition();this.visible=true}},_cancelTimeout:function(){if(this._timeout){clearTimeout(this._timeout);this._timeout=null}},_suggest:function(event){this._cancelTimeout();var key=Event.keyPressed(event);var ignoreKeys=[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(ignoreKeys.indexOf(key)>-1)return false;switch(key){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(event);return true;break;default:break}if(this.input.value.length>=this.options.threshold-1){this._timeout=setTimeout(this._sendRequest.bind(this),1000*this.options.delay)}return false},_sendRequest:function(){this._request=new Ajax.Request(this.action+this.input.value+".htm",{onComplete:this._process.bind(this),method:this.options.requestMethod})},_reposition:function(){if(!this.drawn)return;var pos=Position.cumulativeOffset(this.input);pos.push(pos[0]+this.input.offsetWidth);pos.push(pos[1]+this.input.offsetHeight);Element.setStyle(this.selector,{left:pos[0]+'px',top:pos[3]+'px'})},_process:function(objXML,jsonHeader){this.selector.options.length=0;switch(this.options.resultFormat){case AutoComplete.Options.RESULT_FORMAT_XML:this._parseXML(objXML.responseXML);break;case AutoComplete.Options.RESULT_FORMAT_JSON:if(!jsonHeader){jsonHeader=objXML.responseText&&objXML.responseText.isJSON()?objXML.responseText.evalJSON():null}this._parseJSON(jsonHeader);break;case AutoComplete.Options.RESULT_FORMAT_TEXT:this._parseText(objXML.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(xml){var suggestions=null;for(var i=0;i<xml.childNodes.length;i++){if(xml.childNodes[i].tagName){suggestions=xml.childNodes[i].childNodes}}if(!suggestions){alert("Could not parse response XML.");return}for(i=0;i<suggestions.length;i++){suggestion=suggestions.item(i).firstChild.nodeValue;this._addOption(suggestion)}},_parseJSON:function(json){if(!json)json=[];for(i=0;i<json.length;i++)this._addOption(json[i])},_parseText:function(text){var suggestions=(text||"").split(/\n/);for(i=0;i<suggestions.length;i++){if(suggestions[i]!=""){this._addOption(suggestions[i])}}},_addOption:function(suggestion){var opt=new Option(suggestion,suggestion);Prototype.Browser.IE?this.selector.add(opt):this.selector.add(opt,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(event){if(!this.visible)return;var key=Event.keyPressed(event);if(key!=Event.KEY_UP&&key!=Event.KEY_DOWN)return;var mx=this.selector.options.length;if(key==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:1,delay:.2,requestMethod:'GET',resultFormat:'xml',initialize:function(overrides){Object.extend(this,overrides||{})}});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(event){return Prototype.Browser.IE?window.event.keyCode:event.which}});