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(a){if(this.modules){return this}this.setOptions(a);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(b,g,c,f,e,a){if(!this.modules){this.initialize()}var d=$merge(this.dataOptions,a||{},{defaults:g,onMatch:c,onGenerate:f,regexp:e});d.regexp=d.regexp||b+"-([\\w_-]*)";if(typeof d.regexp=="string"){d.regexp=new RegExp(d.regexp,d.regexpParams)}d.onGenerate=d.onGenerate||function(h){return b+"-"+h[0]};d.values=d.defaults.copy();this.modules.set(b,d);this.fireEvent("onUnregister",[b,d]);return{setValues:function(h){return this.setValues(b,h)}.bind(this),setValue:function(h,i){return this.setValue(b,h,i)}.bind(this),generate:function(h){return this.generate(b,h)}.bind(this),unregister:function(){return this.unregister(b)}.bind(this)}},unregister:function(a){this.fireEvent("onRegister",[a]);this.modules.remove(a)},setValues:function(b,a){var c=this.modules.get(b);if(!c||c.values.isSimilar(a)){return this}c.values=a;this.update();return this},setValue:function(b,a,d){var c=this.modules.get(b);if(!c||c.values[a]==d){return this}c.values[a]=d;this.update();return this},generate:function(b,a){var d=this.modules.get(b);var e=d.values.copy();d.values=a;var c=this.generateState();d.values=e;return"#"+c},observe:function(){if(this.timeout){return}var a=this.getState();if(this.state==a){return}if((window.ie||window.webkit419)&&(this.state!==null)){this.setState(a,true)}else{this.state=a}this.modules.each(function(d,b){var c=a.match(d.regexp);if(c){c.splice(0,1);c.complement(d.defaults);if(!c.isSimilar(d.defaults)){d.values=c}}else{d.values=d.defaults.copy()}d.onMatch(d.values,d.defaults)});this.fireEvent("onStateChange",[a]).fireEvent("onObserverChange",[a])},generateState:function(){var a=[];this.modules.each(function(c,b){if(c.skipDefaultMatch&&c.values.isSimilar(c.defaults)){return}a.push(c.onGenerate(c.values))});return a.join(this.options.stateSeparator)},update:function(){if(!this.started){return this}var a=this.generateState();if((!this.state&&!a)||(this.state==a)){return this}this.setState(a);this.fireEvent("onStateChange",[a]).fireEvent("onUpdate",[a]);return this},observeTimeout:function(){if(this.timeout){this.timeout=$clear(this.timeout)}else{this.timeout=this.observeTimeout.delay(200,this)}},getHash:function(){var a=top.location.href;var b=a.indexOf("#")+1;return(b)?a.substr(b):""},getState:function(){var b=this.getHash();if(this.iframe){var c=this.iframe.contentWindow.document;if(c&&c.body.id=="state"){var a=c.body.innerText;if(this.state==b){return a}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],b)}return b},setState:function(b,a){b=$pick(b,"");if(window.webkit419){if(!this.form){this.form=new Element("form",{method:"get"}).injectInside(document.body)}this.count=history.length;this.states[this.count]=b;this.observeTimeout();this.form.setProperty("action","#"+b).submit()}else{top.location.hash=b||"#"}if(window.ie&&(!a||this.istateOld)){if(!this.iframe){this.iframe=new Element("iframe",{src:this.options.iframeSrc,styles:"visibility: hidden; height:0px; z-index:-90"}).injectInside(document.body);this.istate=this.state}try{var d=this.iframe.contentWindow.document;d.open();d.write('<html><body id="state" style="height:0px; z-index:-90">'+b+"</body></html>");d.close();this.istateOld=false}catch(c){}}this.state=b},extend:$extend};HistoryManager.extend(Events.prototype);HistoryManager.extend(Options.prototype);Array.extend({isSimilar:function(a){return(this.toString()==a.toString())},complement:function(c){for(var b=0,a=this.length;b<a;b++){this[b]=$pick(this[b],c[b]||null)}return this}});