var Autocompleter=new Class({Implements:[Options,Events],options:{minLength:1,markQuery:true,width:'inherit',maxChoices:10,injectChoice:null,customChoices:null,emptyChoices:null,visibleChoices:true,className:'autocompleter-choices',zIndex:42,delay:400,observerOptions:{},fxOptions:{},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:false,allowDupes:false,cache:true,relative:false},initialize:function(a,b){this.element=$(a);this.setOptions(b);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 c=this.options.selectMode;this.typeAhead=(c=='type-ahead');this.selectMode=(c===true)?'selection':c;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(a){this.focussed=a;if(!a)this.hideChoices(true);this.fireEvent((a)?'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 a=(e.key=='up');this.choiceOver((this.selected||this.choices)[(this.selected)?((a)?'getPrevious':'getNext'):((a)?'getLast':'getFirst')](this.options.choicesMatch),true)}return false;case'esc':case'tab':this.hideChoices(true);break}}return true},setSelection:function(b){var c=this.selected.inputValue,value=c;var d=this.queryValue.length,end=c.length;if(c.substr(0,d).toLowerCase()!=this.queryValue.toLowerCase())d=0;if(this.options.multiple){var e=this.options.separatorSplit;value=this.element.value;d+=this.queryIndex;end+=this.queryIndex;var f=value.substr(this.queryIndex).split(e,1)[0];value=value.substr(0,this.queryIndex)+c+value.substr(this.queryIndex+f.length);if(b){var g=value.split(this.options.separatorSplit).filter(function(a){return this.test(a)},/[^\s,]+/);if(!this.options.allowDupes)g=[].combine(g);var h=this.options.separator;value=g.join(h)+h;end=value.length}}this.observer.setValue(value);this.opted=value;if(b||this.selectMode=='pick')d=end;this.element.selectRange(d,end);this.fireEvent('onSelection',[this.element,this.selected,value,c])},showChoices:function(){var a=this.options.choicesMatch,first=this.choices.getFirst(a);this.selected=this.selectedValue=null;if(this.fix){var b=this.element.getCoordinates(this.relative),width=this.options.width||'auto';this.choices.setStyles({'left':b.left,'top':b.bottom,'width':(width===true||width=='inherit')?b.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 c=this.choices.getChildren(a),max=this.options.maxChoices;var d={'overflowY':'hidden','height':''};this.overflown=false;if(c.length>max){var e=c[max-1];d.overflowY='scroll';d.height=e.getCoordinates(this.choices).bottom;this.overflown=true};this.choices.setStyles(d);this.fix.show();if(this.options.visibleChoices){var f=document.getScroll(),size=document.getSize(),coords=this.choices.getCoordinates();if(coords.right>f.x+size.x)f.x=coords.right-size.x;if(coords.bottom>f.y+size.y)f.y=coords.bottom-size.y;window.scrollTo(Math.min(f.x,coords.left),Math.min(f.y,coords.top))}},hideChoices:function(a){if(a){var b=this.element.value;if(this.options.forceSelect)b=this.opted;if(this.options.autoTrim){b=b.split(this.options.separatorSplit).filter($arguments(0)).join(this.options.separator)}this.observer.setValue(b)}if(!this.visible)return;this.visible=false;if(this.selected)this.selected.removeClass('autocompleter-selected');this.observer.clear();var c=function(){this.choices.setStyle('display','none');this.fix.hide()}.bind(this);if(this.fx)this.fx.start(0).chain(c);else c();this.fireEvent('onHide',[this.element,this.choices])},prefetch:function(){var a=this.element.value,query=a;if(this.options.multiple){var b=this.options.separatorSplit;var c=a.split(b);var d=this.element.getSelectedRange().start;var e=a.substr(0,d).split(b);var f=e.length-1;d-=e[f].length;query=c[f]}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=d;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(c){this.choices.empty();this.cached=c;var d=c&&$type(c);if(!d||(d=='array'&&!c.length)||(d=='hash'&&!c.getLength())){(this.options.emptyChoices||this.hideChoices).call(this)}else{if(this.options.maxChoices<c.length&&!this.options.overflow)c.length=this.options.maxChoices;c.each(this.options.injectChoice||function(a){var b=new Element('li',{'html':this.markQueryValue(a)});b.inputValue=a;this.addChoiceEvents(b).inject(this.choices)},this);this.showChoices()}},choiceOver:function(a,b){if(!a||a==this.selected)return;if(this.selected)this.selected.removeClass('autocompleter-selected');this.selected=a.addClass('autocompleter-selected');this.fireEvent('onSelect',[this.element,this.selected,b]);if(!this.selectMode)this.opted=this.element.value;if(!b)return;this.selectedValue=this.selected.inputValue;if(this.overflown){var c=this.selected.getCoordinates(this.choices),margin=this.options.overflowMargin,top=this.choices.scrollTop,height=this.choices.offsetHeight,bottom=top+height;if(c.top-margin<top&&top)this.choices.scrollTop=Math.max(c.top-margin,0);else if(c.bottom+margin>bottom)this.choices.scrollTop=Math.min(c.bottom-height+margin,bottom)}if(this.selectMode)this.setSelection()},choiceSelect:function(a){if(a)this.choiceOver(a);this.setSelection(true);this.queryValue=false;this.hideChoices()},filter:function(b){return(b||this.tokens).filter(function(a){return this.test(a)},new RegExp(((this.options.filterSubset)?'':'^')+this.queryValue.escapeRegExp(),(this.options.filterCase)?'':'i'))},markQueryValue:function(a){return(!this.options.markQuery||!this.queryValue)?a:a.replace(new RegExp('('+((this.options.filterSubset)?'':'^')+this.queryValue.escapeRegExp()+')',(this.options.filterCase)?'':'i'),'<span class="autocompleter-queried">$1</span>')},addChoiceEvents:function(a){return a.addEvents({'mouseover':this.choiceOver.bind(this,[a]),'click':this.choiceSelect.bind(this,[a])})}});var OverlayFix=new Class({initialize:function(a){if(Browser.Engine.trident){this.element=$(a);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 a=this.element.getCoordinates(this.relative);delete a.right;delete a.bottom;this.fix.setStyles($extend(a,{'display':'','zIndex':(this.element.getStyle('zIndex')||1)-1}))}return this},hide:function(){if(this.fix)this.fix.setStyle('display','none');return this},destroy:function(){if(this.fix)this.fix=this.fix.destroy()}});Element.implement({getSelectedRange:function(){if(!Browser.Engine.trident)return{start:this.selectionStart,end:this.selectionEnd};var a={start:0,end:0};var b=this.getDocument().selection.createRange();if(!b||b.parentElement()!=this)return a;var c=b.duplicate();if(this.type=='text'){a.start=0-c.moveStart('character',-100000);a.end=a.start+b.text.length}else{var d=this.value;var e=d.length-d.match(/[\n\r]*$/)[0].length;c.moveToElementText(this);c.setEndPoint('StartToEnd',b);a.end=e-c.text.length;c.setEndPoint('StartToStart',b);a.start=e-c.text.length}return a},selectRange:function(a,b){if(Browser.Engine.trident){var c=this.value.substr(a,b-a).replace(/\r/g,'').length;a=this.value.substr(0,a).replace(/\r/g,'').length;var d=this.createTextRange();d.collapse(true);d.moveEnd('character',a+c);d.moveStart('character',a);d.select()}else{this.focus();this.setSelectionRange(a,b)}return this}});Autocompleter.Base=Autocompleter;var Observer=new Class({Implements:[Options,Events],options:{periodical:false,delay:1000},initialize:function(a,b,c){this.element=$(a)||$$(a);this.addEvent('onFired',b);this.setOptions(c);this.bound=this.changed.bind(this);this.resume()},changed:function(){var a=this.element.get('value');if($equals(this.value,a))return;this.clear();this.value=a;this.timeout=this.onFired.delay(this.options.delay,this)},setValue:function(a){this.value=a;this.element.set('value',a);return this.clear()},onFired:function(){this.fireEvent('onFired',[this.value,this.element])},clear:function(){$clear(this.timeout||null);return this},pause:function(){if(this.timer)$clear(this.timer);else this.element.removeEvent('keyup',this.bound);return this.clear()},resume:function(){this.value=this.element.get('value');if(this.options.periodical)this.timer=this.changed.periodical(this.options.periodical,this);else this.element.addEvent('keyup',this.bound);return this}});var $equals=function(a,b){return(a==b||JSON.encode(a)==JSON.encode(b))};Autocompleter.Local=new Class({Extends:Autocompleter,options:{minLength:0,delay:200},initialize:function(a,b,c){this.parent(a,c);this.tokens=b},query:function(){this.update(this.filter())}});Autocompleter.Request=new Class({Extends:Autocompleter,options:{postData:{},ajaxOptions:{},postVar:'value'},query:function(){var a=$unlink(this.options.postData)||{};a[this.options.postVar]=this.queryValue;var b=$(this.options.indicator);if(b)b.setStyle('display','');var c=this.options.indicatorClass;if(c)this.element.addClass(c);this.fireEvent('onRequest',[this.element,this.request,a,this.queryValue]);this.request.send({'data':a})},queryResponse:function(){var a=$(this.options.indicator);if(a)a.setStyle('display','none');var b=this.options.indicatorClass;if(b)this.element.removeClass(b);return this.fireEvent('onComplete',[this.element,this.request])}});Autocompleter.Request.JSON=new Class({Extends:Autocompleter.Request,initialize:function(a,b,c){this.parent(a,c);this.request=new Request.JSON($merge({'url':b,'link':'cancel'},this.options.ajaxOptions)).addEvent('onComplete',this.queryResponse.bind(this))},queryResponse:function(a){this.parent();this.update(a)}});Autocompleter.Request.HTML=new Class({Extends:Autocompleter.Request,initialize:function(a,b,c){this.parent(a,c);this.request=new Request.HTML($merge({'url':b,'link':'cancel','update':this.choices},this.options.ajaxOptions)).addEvent('onComplete',this.queryResponse.bind(this))},queryResponse:function(c,d){this.parent();if(!d||!d.length){this.hideChoices()}else{this.choices.getChildren(this.options.choicesMatch).each(this.options.injectChoice||function(a){var b=a.innerHTML;a.inputValue=b;this.addChoiceEvents(a.set('html',this.markQueryValue(b)))},this);this.showChoices()}}});Autocompleter.Ajax={Base:Autocompleter.Request,Json:Autocompleter.Request.JSON,Xhtml:Autocompleter.Request.HTML};