
var HistoryManagerX=new Class({Implements:[Options,Events],options:{observeDelay:100,stateSeparator:';',iframeSrc:'blank.html',onStart:Class.empty,onRegister:Class.empty,onUnregister:Class.empty,onStart:Class.empty,onUpdate:Class.empty,onStateChange:Class.empty,onObserverChange:Class.empty},dataOptions:{skipDefaultMatch:true,defaults:[],regexpParams:''},initialize:function(options){if(this.modules)return this;this.setOptions(options);this.modules=$H({});this.count=history.length;this.states=[];this.states[this.count]=this.getHash();this.state=null;this.old_state='#1';return this;},start:function(){this.observe.periodical(this.options.observeDelay,this);this.started=true;this.observe();this.update();this.fireEvent('onStart',[this.state]);return this;},register:function(key,defaults,onMatch,onGenerate,regexp,options){if(!this.modules)this.initialize();var data=$merge(this.dataOptions,options||{},{defaults:defaults,onMatch:onMatch,onGenerate:onGenerate,regexp:regexp});data.regexp=data.regexp||key+'-([\\w_-]*)';if(typeof data.regexp=='string')data.regexp=new RegExp(data.regexp,data.regexpParams);data.onGenerate=data.onGenerate||function(values){return key+'-'+values[0];};data.values=data.defaults.copy();this.modules.set(key,data);this.fireEvent('onUnregister',[key,data]);return{setValues:function(values){return this.setValues(key,values);}.bind(this),setValue:function(index,value){return this.setValue(key,index,value);}.bind(this),getState:function(){return this.state;}.bind(this),getOldState:function(){return this.old_state;}.bind(this),generate:function(values){return this.generate(key,values);}.bind(this),update:function(values){return this.update()}.bind(this),unregister:function(){return this.unregister(key);}.bind(this)};},unregister:function(key){this.fireEvent('onRegister',[key]);this.modules.remove(key);},setValues:function(key,values){var data=this.modules.get(key);if(!data||isSimilar(data.values,values))return this;data.values=values;this.update();return this;},setValue:function(key,index,value){var data=this.modules.get(key);if(!data||data.values[index]==value)return this;data.values[index]=value;this.update();return this;},generate:function(key,values){var data=this.modules.get(key);var current=data.values.copy();data.values=values;var state=this.generateState();data.values=current;return'#'+state;},observe:function(){if(this.timeout)return;var state=this.getState();if(this.state==state)return;if(((Browser.Engine.trident&&(!document.querySelectorAll)))&&(this.state!==null))this.setState(state,true);else this.state=state;this.modules.each(function(data,key){var bits=state.match(data.regexp);if(bits){bits.splice(0,1);bits=complement(bits,data.defaults);if(!isSimilar(bits,data.defaults))data.values=bits;}else data.values=copy(data.defaults);data.onMatch(data.values,data.defaults);});this.fireEvent('onStateChange',[state]).fireEvent('onObserverChange',[state]);},generateState:function(){var state=[];this.modules.each(function(data,key){if(data.skipDefaultMatch&&isSimilar(data.values,data.defaults))return;state.push(data.onGenerate(data.values));});return state.join(this.options.stateSeparator);},update:function(){if(!this.started)return this;var state=this.generateState();if((!this.state&&!state)||(this.state==state))return this;this.setState(state);this.fireEvent('onStateChange',[state]).fireEvent('onUpdate',[state]);return this;},observeTimeout:function(){if(this.timeout)this.timeout=$clear(this.timeout);else this.timeout=this.observeTimeout.delay(200,this);},getHash:function(){var href=top.location.href;var pos=href.indexOf('#')+1;return(pos)?href.substr(pos):'';},getState:function(){var state=this.getHash();if(this.iframe){var doc=this.iframe.contentWindow.document;if(doc&&doc.body.id=='state'){var istate=doc.body.innerText;if(this.state==state)return istate;this.istateOld=true;}else return this.istate;}
return state;},setState:function(state,fix){this.old_state=this.state;state=$pick(state,'');top.location.hash=state||'#';if(Browser.Engine.trident&&(!document.querySelectorAll)&&(!fix||this.istateOld)){if(!this.iframe){this.iframe=new Element('iframe',{src:this.options.iframeSrc,style:'visibility: hidden;height:1px;'}).injectInside(document.body);this.istate=this.state;}
try{var doc=this.iframe.contentWindow.document;doc.open();doc.write('<html><body id="state">'+state+'</body></html>');doc.close();this.istateOld=false;}catch(e){};}
this.state=state;},extend:$extend});function isSimilar(array1,array2){return(array1.toString()==array2.toString());}
function complement(array1,array2){for(var i=0,j=array1.length;i<j;i++)array1[i]=$pick(array1[i],array2[i]||null);return array1;}
function copy(str,start,length){start=start||0;if(start<0)start=str.length+start;length=length||(str.length-start);var newArray=[];for(var i=0;i<length;i++)newArray[i]=str[start++];return newArray;}
Array.implement({isSimilar:function(array){return(this.toString()==array.toString());},complement:function(array){for(var i=0,j=this.length;i<j;i++)this[i]=$pick(this[i],array[i]||null);return this;},copy:function(start,length){start=start||0;if(start<0)start=this.length+start;length=length||(this.length-start);var newArray=[];for(var i=0;i<length;i++)newArray[i]=this[start++];return newArray;}});var HistoryManager;window.addEvent('domready',function(){HistoryManager=new HistoryManagerX();});
