
var HistoryManager={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;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){key=key.split('%');key=key[1];regexp=regexp.split('%');regexp=regexp[1];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),generate:function(values){return this.generate(key,values);}.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||data.values.isSimilar(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((window.ie||window.webkit419)&&(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(data.defaults);if(!bits.isSimilar(data.defaults))data.values=bits;}else data.values=data.defaults.copy();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&&data.values.isSimilar(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;}
if(window.webkit419&&history.length!=this.count){this.count=history.length;return $pick(this.states[this.count-1],state);}
return state;},setState:function(state,fix){state=$pick(state,'');if(window.webkit419){if(!this.form)this.form=new Element('form',{method:'get'}).injectInside(document.body);this.count=history.length;this.states[this.count]=state;this.observeTimeout();this.form.setProperty('action','#'+state).submit();}else top.location.hash=state||'#';if(window.ie&&(!fix||this.istateOld)){if(!this.iframe){this.iframe=new Element('iframe',{src:this.options.iframeSrc,styles:'visibility: hidden;'}).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};HistoryManager.extend(Events.prototype);HistoryManager.extend(Options.prototype);Array.extend({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;}});