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,{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++)
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:3,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;}});
