
var Observer=new Class({options:{periodical:false,delay:1000},initialize:function(el,onFired,options){this.setOptions(options);this.addEvent('onFired',onFired);this.element=$(el);this.listener=this.fired.bind(this);this.value=this.element.getValue();if(this.options.periodical)this.timer=this.listener.periodical(this.options.periodical);else this.element.addEvent('keyup',this.listener);},fired:function(){var value=this.element.getValue();if(this.value==value)return;this.clear();this.value=value;this.timeout=this.fireEvent.delay(this.options.delay,this,['onFired',[value]]);},clear:function(){$clear(this.timeout);return this;}});Observer.implement(new Options);Observer.implement(new Events);var Autocompleter={};Autocompleter.Base=new Class({options:{minLength:1,useSelection:true,markQuery:true,inheritWidth:true,maxChoices:10,injectChoice:null,onSelect:Class.empty,onShow:Class.empty,onHide:Class.empty,customTarget:null,className:'autocompleter-choices',zIndex:42,observerOptions:{},fxOptions:{},overflown:[]},initialize:function(el,options){this.setOptions(options);this.element=$(el);this.build();this.observer=new Observer(this.element,this.prefetch.bind(this),$merge({delay:400},this.options.observerOptions));this.value=this.observer.value;this.queryValue=null;},build:function(){if($(this.options.customTarget))this.choices=this.options.customTarget;else{this.choices=new Element('ul',{'class':this.options.className,styles:{zIndex:this.options.zIndex}}).injectInside(document.body);this.fix=new OverlayFix(this.choices);}
this.fx=this.choices.effect('opacity',$merge({wait:false,duration:200},this.options.fxOptions)).addEvent('onStart',function(){if(this.fx.now)return;this.choices.setStyle('display','');this.fix.show();}.bind(this)).addEvent('onComplete',function(){if(this.fx.now)return;this.choices.setStyle('display','none');this.fix.hide();}.bind(this)).set(0);this.element.setProperty('autocomplete','off').addEvent(window.ie?'keydown':'keypress',this.onCommand.bindWithEvent(this)).addEvent('mousedown',this.onCommand.bindWithEvent(this,[true])).addEvent('focus',this.toggleFocus.bind(this,[true])).addEvent('blur',this.toggleFocus.bind(this,[false])).addEvent('trash',this.destroy.bind(this));},destroy:function(){this.choices.remove();},toggleFocus:function(state){this.focussed=state;if(!state)this.hideChoices();},onCommand:function(e,mouse){if(mouse&&this.focussed)this.prefetch();if(e.key&&!e.shift)switch(e.key){case'enter':if(this.selected&&this.visible){this.choiceSelect(this.selected);e.stop();}return;case'up':case'down':if(this.observer.value!=(this.value||this.queryValue))this.prefetch();else if(this.queryValue===null)break;else if(!this.visible)this.showChoices();else{this.choiceOver((e.key=='up')?(this.selected?(this.selected.getPrevious()||this.choices.getLast()):this.choices.getLast()):(this.selected?(this.selected.getNext()||this.choices.getFirst()):this.choices.getFirst()));this.setSelection();}
e.stop();return;case'esc':this.hideChoices();return;}
this.value=false;},setSelection:function(){if(!this.options.useSelection)return;var startLength=this.queryValue.length;if(this.element.value.indexOf(this.queryValue)!=0)return;var insert=this.selected.inputValue.substr(startLength);if(document.getSelection){this.element.value=this.queryValue+insert;this.element.selectionStart=startLength;this.element.selectionEnd=this.element.value.length;}else if(document.selection){var sel=document.selection.createRange();sel.text=insert;sel.move("character",-insert.length);sel.findText(insert);sel.select();}
this.value=this.observer.value=this.element.value;},hideChoices:function(){if(!this.visible)return;this.visible=this.value=false;this.observer.clear();this.fx.start(0);this.fireEvent('onHide',[this.element,this.choices]);},showChoices:function(){if(this.visible||!this.choices.getFirst())return;this.visible=true;var pos=this.element.getCoordinates(this.options.overflown);this.choices.setStyles({left:pos.left,top:pos.bottom});if(this.options.inheritWidth)this.choices.setStyle('width',pos.width);this.fx.start(1);this.fireEvent('onShow',[this.element,this.choices]);},prefetch:function(){if(this.element.value.length<this.options.minLength)this.hideChoices();else if(this.element.value==this.queryValue)this.showChoices();else this.query();},updateChoices:function(choices){this.choices.empty();this.selected=null;if(!choices||!choices.length)return;if(this.options.maxChoices<choices.length)choices.length=this.options.maxChoices;choices.each(this.options.injectChoice||function(choice,i){var el=new Element('li').setHTML(this.markQueryValue(choice));el.inputValue=choice;this.addChoiceEvents(el).injectInside(this.choices);},this);this.showChoices();},choiceOver:function(el){if(this.selected)this.selected.removeClass('autocompleter-selected');this.selected=el.addClass('autocompleter-selected');},choiceSelect:function(el){this.observer.value=this.element.value=el.inputValue;this.hideChoices();this.fireEvent('onSelect',[this.element],20);},markQueryValue:function(txt){return(this.options.markQuery&&this.queryValue)?txt.replace(new RegExp('^('+this.queryValue.escapeRegExp()+')','i'),'<span class="autocompleter-queried">$1</span>'):txt;},addChoiceEvents:function(el){return el.addEvents({mouseover:this.choiceOver.bind(this,[el]),mousedown:this.choiceSelect.bind(this,[el])});}});Autocompleter.Base.implement(new Events);Autocompleter.Base.implement(new Options);Autocompleter.Local=Autocompleter.Base.extend({options:{minLength:0,filterTokens:null},initialize:function(el,tokens,options){this.parent(el,options);this.tokens=tokens;if(this.options.filterTokens)this.filterTokens=this.options.filterTokens.bind(this);},query:function(){this.hideChoices();this.queryValue=this.element.value;this.updateChoices(this.filterTokens());},filterTokens:function(token){var regex=new RegExp('^'+this.queryValue.escapeRegExp(),'i');return this.tokens.filter(function(token){return regex.test(token);});}});Autocompleter.Ajax={};Autocompleter.Ajax.Base=Autocompleter.Base.extend({options:{postVar:'value',postData:{},ajaxOptions:{},onRequest:Class.empty,onComplete:Class.empty},initialize:function(el,url,options){this.parent(el,options);this.ajax=new Ajax(url,$merge({autoCancel:true},this.options.ajaxOptions));this.ajax.addEvent('onComplete',this.queryResponse.bind(this));this.ajax.addEvent('onFailure',this.queryResponse.bind(this,[false]));},query:function(){var data=$extend({},this.options.postData);data[this.options.postVar]=this.element.value;this.fireEvent('onRequest',[this.element,this.ajax]);this.ajax.request(data);},queryResponse:function(resp){this.value=this.queryValue=this.element.value;this.selected=false;this.hideChoices();this.fireEvent(resp?'onComplete':'onFailure',[this.element,this.ajax],20);}});Autocompleter.Ajax.Json=Autocompleter.Ajax.Base.extend({queryResponse:function(resp){this.parent(resp);var choices=Json.evaluate(resp||false);if(!choices||!choices.length)return;this.updateChoices(choices);}});Autocompleter.Ajax.Xhtml=Autocompleter.Ajax.Base.extend({options:{parseChoices:null},queryResponse:function(resp){this.parent(resp);if(!resp)return;this.choices.setHTML(resp).getChildren().each(this.options.parseChoices||this.parseChoices,this);this.showChoices();},parseChoices:function(el){var value=el.innerHTML;el.inputValue=value;el.setHTML(this.markQueryValue(value));}});var OverlayFix=new Class({initialize:function(el){this.element=$(el);if(window.ie){this.element.addEvent('trash',this.destroy.bind(this));this.fix=new Element('iframe',{properties:{frameborder:'0',scrolling:'no',src:'javascript:false;'},styles:{position:'absolute',border:'none',display:'none',filter:'progid:DXImageTransform.Microsoft.Alpha(opacity=0)'}}).injectAfter(this.element);}},show:function(){if(this.fix)this.fix.setStyles($extend(this.element.getCoordinates(),{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.remove();}});
