var Autocompleter={};Autocompleter.Base=new Class({options:{minLength:1,markQuery:true,width:'inherit',maxChoices:10,injectChoice:null,customChoices:null,className:'autocompleter-choices',zIndex:42,delay:400,observerOptions:{},fxOptions:{},onOver:$empty,onSelect:$empty,onSelection:$empty,onShow:$empty,onHide:$empty,onBlur:$empty,onFocus:$empty,autoSubmit:false,overflow:false,overflowMargin:25,selectFirst:false,filter:null,filterCase:false,filterSubset:false,forceSelect:false,selectMode:true,choicesMatch:null,multiple:false,separator:', ',separatorSplit:/\s*[,;]\s*/,autoTrim:true,allowDupes:false,cache:true,relative:false},initialize:function(element,options){this.element=$(element);this.setOptions(options);this.build();this.observer=new Observer(this.element,this.prefetch.bind(this),$merge({'delay':this.options.delay},this.options.observerOptions));this.queryValue=null;if(this.options.filter)this.filter=this.options.filter.bind(this);var mode=this.options.selectMode;this.typeAhead=(mode=='type-ahead');this.selectMode=(mode===true)?'selection':mode;this.cached=[];},build:function(){if($(this.options.customChoices)){this.choices=this.options.customChoices;}else{this.choices=new Element('ul',{'class':this.options.className,'styles':{'zIndex':this.options.zIndex}}).inject(document.body);this.relative=false;if(this.options.relative){this.choices.inject(this.element,'after');this.relative=this.element.getOffsetParent();}
this.fix=new OverlayFix(this.choices);}
if(!this.options.separator.test(this.options.separatorSplit)){this.options.separatorSplit=this.options.separator;}
this.fx=(!this.options.fxOptions)?null:new Fx.Tween(this.choices,$merge({'property':'opacity','link':'cancel','duration':200},this.options.fxOptions)).addEvent('onStart',Chain.prototype.clearChain).set(0);this.element.setProperty('autocomplete','off').addEvent((Browser.Engine.trident||Browser.Engine.webkit)?'keydown':'keypress',this.onCommand.bind(this)).addEvent('click',this.onCommand.bind(this,[false])).addEvent('focus',this.toggleFocus.create({bind:this,arguments:true,delay:100})).addEvent('blur',this.toggleFocus.create({bind:this,arguments:false,delay:100}));},destroy:function(){if(this.fix)this.fix.destroy();this.choices=this.selected=this.choices.destroy();},toggleFocus:function(state){this.focussed=state;if(!state)this.hideChoices(true);this.fireEvent((state)?'onFocus':'onBlur',[this.element]);},onCommand:function(e){if(!e&&this.focussed)return this.prefetch();if(e&&e.key&&!e.shift){switch(e.key){case'enter':if(this.element.value!=this.opted)return true;if(this.selected&&this.visible){this.choiceSelect(this.selected);return!!(this.options.autoSubmit);}
break;case'up':case'down':if(!this.prefetch()&&this.queryValue!==null){var up=(e.key=='up');this.choiceOver((this.selected||this.choices)[(this.selected)?((up)?'getPrevious':'getNext'):((up)?'getLast':'getFirst')](this.options.choicesMatch),true);}
return false;case'esc':case'tab':this.hideChoices(true);break;}}
return true;},setSelection:function(finish){var input=this.selected.inputValue,value=input;var start=this.queryValue.length,end=input.length;if(input.substr(0,start).toLowerCase()!=this.queryValue.toLowerCase())start=0;if(this.options.multiple){var split=this.options.separatorSplit;value=this.element.value;start+=this.queryIndex;end+=this.queryIndex;var old=value.substr(this.queryIndex).split(split,1)[0];value=value.substr(0,this.queryIndex)+input+value.substr(this.queryIndex+old.length);if(finish){var space=/[^\s,]+/;var tokens=value.split(this.options.separatorSplit).filter(space.test,space);if(!this.options.allowDupes)tokens=[].combine(tokens);var sep=this.options.separator;value=tokens.join(sep)+sep;end=value.length;}}
this.observer.setValue(value);this.opted=value;if(finish||this.selectMode=='pick')start=end;this.element.selectRange(start,end);this.fireEvent('onSelection',[this.element,this.selected,value,input]);},showChoices:function(){var match=this.options.choicesMatch,first=this.choices.getFirst(match);this.selected=this.selectedValue=null;if(this.fix){var pos=this.element.getCoordinates(this.relative),width=this.options.width||'auto';this.choices.setStyles({'left':pos.left,'top':pos.bottom,'width':(width===true||width=='inherit')?pos.width:width});}
if(!first)return;if(!this.visible){this.visible=true;this.choices.setStyle('display','');if(this.fx)this.fx.start(1);this.fireEvent('onShow',[this.element,this.choices]);}
if(this.options.selectFirst||this.typeAhead||first.inputValue==this.queryValue)this.choiceOver(first,this.typeAhead);var items=this.choices.getChildren(match),max=this.options.maxChoices;var styles={'overflowY':'hidden','height':''};this.overflown=false;if(items.length>max){var item=items[max-1];styles.overflowY='scroll';styles.height=item.getCoordinates(this.choices).bottom;this.overflown=true;};this.choices.setStyles(styles);this.fix.show();},hideChoices:function(clear){if(clear){var value=this.element.value;if(this.options.forceSelect)value=this.opted;if(this.options.autoTrim){value=value.split(this.options.separatorSplit).filter($arguments(0)).join(this.options.separator);}
this.observer.setValue(value);}
if(!this.visible)return;this.visible=false;this.observer.clear();var hide=function(){this.choices.setStyle('display','none');this.fix.hide();}.bind(this);if(this.fx)this.fx.start(0).chain(hide);else hide();this.fireEvent('onHide',[this.element,this.choices]);},prefetch:function(){var value=this.element.value,query=value;if(this.options.multiple){var split=this.options.separatorSplit;var values=value.split(split);var index=this.element.getCaretPosition();var toIndex=value.substr(0,index).split(split);var last=toIndex.length-1;index-=toIndex[last].length;query=values[last];}
if(query.length<this.options.minLength){this.hideChoices();}else{if(query===this.queryValue||(this.visible&&query==this.selectedValue)){if(this.visible)return false;this.showChoices();}else{this.queryValue=query;this.queryIndex=index;if(!this.fetchCached())this.query();}}
return true;},fetchCached:function(){return false;if(!this.options.cache||!this.cached||!this.cached.length||this.cached.length>=this.options.maxChoices||this.queryValue)return false;this.update(this.filter(this.cached));return true;},update:function(tokens){this.choices.empty();this.cached=tokens;if(!tokens||!tokens.length){this.hideChoices();}else{if(this.options.maxChoices<tokens.length&&!this.options.overflow)tokens.length=this.options.maxChoices;tokens.each(this.options.injectChoice||function(token){var choice=new Element('li',{'html':this.markQueryValue(token)});choice.inputValue=token;this.addChoiceEvents(choice).inject(this.choices);},this);this.showChoices();}},choiceOver:function(choice,selection){if(!choice||choice==this.selected)return;if(this.selected)this.selected.removeClass('autocompleter-selected');this.selected=choice.addClass('autocompleter-selected');this.fireEvent('onSelect',[this.element,this.selected,selection]);if(!selection)return;this.selectedValue=this.selected.inputValue;if(this.overflown){var coords=this.selected.getCoordinates(this.choices),margin=this.options.overflowMargin,top=this.choices.scrollTop,height=this.choices.offsetHeight,bottom=top+height;if(coords.top-margin<top&&top)this.choices.scrollTop=Math.max(coords.top-margin,0);else if(coords.bottom+margin>bottom)this.choices.scrollTop=Math.min(coords.bottom-height+margin,bottom);}
if(this.selectMode)this.setSelection();},choiceSelect:function(choice){if(choice)this.choiceOver(choice);this.setSelection(true);this.queryValue=false;this.hideChoices();},filter:function(tokens){var regex=new RegExp(((this.options.filterSubset)?'':'^')+this.queryValue.escapeRegExp(),(this.options.filterCase)?'':'i');return(tokens||this.tokens).filter(regex.test,regex);},markQueryValue:function(str){return(!this.options.markQuery||!this.queryValue)?str:str.replace(new RegExp('('+((this.options.filterSubset)?'':'^')+this.queryValue.escapeRegExp()+')',(this.options.filterCase)?'':'i'),'<span class="autocompleter-queried">$1</span>');},addChoiceEvents:function(el){return el.addEvents({'mouseover':this.choiceOver.bind(this,[el]),'click':this.choiceSelect.bind(this,[el])});}});Autocompleter.Base.implement(new Events);Autocompleter.Base.implement(new Options);Autocompleter.Local=new Class({Extends:Autocompleter.Base,options:{minLength:0,delay:200},initialize:function(element,tokens,options){this.parent(element,options);this.tokens=tokens;},query:function(){this.update(this.filter());}});Autocompleter.Ajax={};Autocompleter.Ajax.Base=new Class({Extends:Autocompleter.Base,options:{postVar:'value',postData:{},ajaxOptions:{},onRequest:$empty,onComplete:$empty},initialize:function(element,options){this.parent(element,options);var indicator=$(this.options.indicator);if(indicator){this.addEvents({'onRequest':indicator.show.bind(indicator),'onComplete':indicator.hide.bind(indicator)},true);}},query:function(){var data=$unlink(this.options.postData);data[this.options.postVar]=this.queryValue;this.fireEvent('onRequest',[this.element,this.request,data,this.queryValue]);this.request.send({'data':data});},queryResponse:function(){this.fireEvent('onComplete',[this.element,this.request,this.response]);}});Autocompleter.Ajax.Json=new Class({Extends:Autocompleter.Ajax.Base,initialize:function(el,url,options){this.parent(el,options);this.request=new Request.JSON($merge({'url':url,'link':'cancel'},this.options.ajaxOptions)).addEvent('onComplete',this.queryResponse.bind(this));},queryResponse:function(response){this.parent();this.update(response);}});Autocompleter.Ajax.Xhtml=new Class({Extends:Autocompleter.Ajax.Base,initialize:function(el,url,options){this.parent(el,options);this.request=new Request.HTML($merge({'url':url,'link':'cancel','update':this.choices},this.options.ajaxOptions)).addEvent('onComplete',this.queryResponse.bind(this));},queryResponse:function(tree,elements){this.parent();if(!elements||!elements.length){this.hideChoices();}else{this.choices.getChildren(this.options.choicesMatch).each(this.options.injectChoice||function(choice){var value=choice.innerHTML;choice.inputValue=value;this.addChoiceEvents(choice.set('html',this.markQueryValue(value)));},this);this.showChoices();}}});var OverlayFix=new Class({initialize:function(el){if(Browser.Engine.trident){this.element=$(el);this.relative=this.element.getOffsetParent();this.fix=new Element('iframe',{'frameborder':'0','scrolling':'no','src':'javascript:false;','styles':{'position':'absolute','border':'none','display':'none','filter':'progid:DXImageTransform.Microsoft.Alpha(opacity=0)'}}).inject(this.element,'after');}},show:function(){if(this.fix){var coords=this.element.getCoordinates(this.relative);delete coords.right;delete coords.bottom;this.fix.setStyles($extend(coords,{'display':'','zIndex':(this.element.getStyle('zIndex')||1)-1}));}
return this;},hide:function(){if(this.fix)this.fix.setStyle('display','none');return this;},destroy:function(){this.fix=this.fix.destroy();}});Element.implement({getOffsetParent:function(){var body=this.getDocument().body;if(this==body)return null;if(!Browser.Engine.trident)return $(this.offsetParent);var el=this;while((el=el.parentNode)){if(el==body||Element.getComputedStyle(el,'position')!='static')return $(el);}
return null;},getCaretPosition:function(){if(!Browser.Engine.trident)return this.selectionStart;this.focus();var work=document.selection.createRange();var all=this.createTextRange();work.setEndPoint('StartToStart',all);return work.text.length;},selectRange:function(start,end){if(Browser.Engine.trident){var range=this.createTextRange();range.collapse(true);range.moveEnd('character',end);range.moveStart('character',start);range.select();}else{this.focus();this.setSelectionRange(start,end);}
return this;}});
