window.dhtmlHistory={initialize:function()
{
	if(this.isInternetExplorer()==false)
	{return}
	if(historyStorage.hasKey("DhtmlHistory_pageLoaded")==false)
	{
		this.fireOnNewListener=false;
		this.firstLoad=true;
		historyStorage.put("DhtmlHistory_pageLoaded",true)
	}
	else
	{
		this.fireOnNewListener=true;this.firstLoad=false
	}
}
,addListener:function(callback)
{
	this.listener=callback;
	if(this.fireOnNewListener==true)
	    {
		this.fireHistoryEvent(this.currentLocation);
		this.fireOnNewListener=false
		}
},add:function(newLocation,historyData)
		
		{
			
				
			var self=this;var addImpl=function()
			{	
			
			if(self.currentWaitTime>0)self.currentWaitTime=self.currentWaitTime-self.WAIT_TIME;newLocation=self.removeHash(newLocation);
				var idCheck=document.getElementById(newLocation);
				
				if(idCheck!=undefined||idCheck!=null)
				{
					
					var message="Exception: History locations can not have "+"the same value as _any_ id's "+"that might be in the document, "+"due to a bug in Internet "+"Explorer; please ask the "+"developer to choose a history "+"location that does not match "+"any HTML id's in this "+"document. The following ID "+"is already taken and can not "+"be a location: "+newLocation;
					throw message;
					}
					historyStorage.put(newLocation,historyData);
					self.ignoreLocationChange=true;
					this.ieAtomicLocationChange=true;
					self.currentLocation=newLocation;
					window.location.hash=newLocation;
					if(self.isInternetExplorer())self.iframe.src="blank.html?"+newLocation;
					this.ieAtomicLocationChange=false};
					
					window.setTimeout(addImpl,this.currentWaitTime);
					this.currentWaitTime=this.currentWaitTime+this.WAIT_TIME
					},isFirstLoad:function()
				{ 
					if(this.firstLoad==true)
					{
						
						return true
						}
						else
						{
							return false
							}
							},isInternational:function()
							{
								
								return false
								},getVersion:function()
								{
									return"0.05"
									},
									getCurrentLocation:function()
									{
										var currentLocation=this.removeHash(window.location.hash);
										return currentLocation
										},currentLocation:null,listener:null,iframe:null,ignoreLocationChange:null,WAIT_TIME:200,currentWaitTime:0,fireOnNewListener:null,firstLoad:null,ieAtomicLocationChange:null,create:function()
										{
											
											var initialHash=this.getCurrentLocation();this.currentLocation=initialHash;if(this.isInternetExplorer())
											{
												
												document.write("<iframe style='border: 0px; width: 1px; "+"height: 1px; position: absolute; bottom: 0px; "+"right: 0px; visibility: visible;' "+"name='DhtmlHistoryFrame' id='DhtmlHistoryFrame' "+"src='blank.html?"+initialHash+"'>"+"</iframe>");
												this.WAIT_TIME=400
												}
												var self=this;window.onunload=function()
												{self.firstLoad=null
												};
												if(this.isInternetExplorer()==false)
												{
													if(historyStorage.hasKey("DhtmlHistory_pageLoaded")==false)
													{
														this.ignoreLocationChange=true;
														this.firstLoad=true;
														historyStorage.put("DhtmlHistory_pageLoaded",true)
														}
														else
														{
															this.ignoreLocationChange=false;
															this.fireOnNewListener=true;
															}
															}
															else
															{
																this.ignoreLocationChange=true
																}
																if(this.isInternetExplorer())
																{
																	this.iframe=document.getElementById("DhtmlHistoryFrame")
																	}
																	var self=this;
																	var locationHandler=function()
																	{
																		self.checkLocation()
																		};
																		setInterval(locationHandler,100)
																		},fireHistoryEvent:function(newHash)
																		{
																			var historyData=historyStorage.get(newHash);
																			this.listener.call(null,newHash,historyData)
																			},checkLocation:function()
																			{
																				if(this.isInternetExplorer()==false&&this.ignoreLocationChange==true)
																				{
																					
																					this.ignoreLocationChange=false;return
																					}
																					if(this.isInternetExplorer()==false&&this.ieAtomicLocationChange==true)
																					{
																						return
																						}
																						var hash=this.getCurrentLocation();
																						if(hash==this.currentLocation)return;
																						this.ieAtomicLocationChange=true;
																						if(this.isInternetExplorer()&&this.getIFrameHash()!=hash)
																						{
																							this.iframe.src="blank.html?"+hash
																							}
																							else if(this.isInternetExplorer())
																							{
																								return
																								}
																								this.currentLocation=hash;
																								this.ieAtomicLocationChange=false;this.fireHistoryEvent(hash)
																								},getIFrameHash:function()
																								{
																									var historyFrame=document.getElementById("DhtmlHistoryFrame");
																									var doc=historyFrame.contentWindow.document;var hash=new String(doc.location.search);
																									if(hash.length==1&&hash.charAt(0)=="?")hash="";
																									else if(hash.length>=2&&hash.charAt(0)=="?")hash=hash.substring(1);
																									return hash
																									},removeHash:function(hashValue)
																									{
																										
																										if(hashValue==null||hashValue==undefined)return null;
																										else if(hashValue=="")return"";
																										else if(hashValue.length==1&&hashValue.charAt(0)=="#")return"";
																										else if(hashValue.length>1&&hashValue.charAt(0)=="#")return hashValue.substring(1);
																										else return hashValue},iframeLoaded:function(newLocation)
																										{
																											if(this.ignoreLocationChange==true)
																											{
																												this.ignoreLocationChange=false;return}var hash=new String(newLocation.search);
																												if(hash.length==1&&hash.charAt(0)=="?")hash="";
																												else if(hash.length>=2&&hash.charAt(0)=="?")hash=hash.substring(1);
																												if(this.pageLoadEvent!=true)
																												{
																													window.location.hash=hash
																													}
																													this.fireHistoryEvent(hash)
																													},isInternetExplorer:function()
																													{
																														var userAgent=navigator.userAgent.toLowerCase();
																														if(document.all&&userAgent.indexOf('msie')!=-1)
																														{
																															return true
																															}
																															else
																															{
																																return false
																																}
																																}
																																};
																																window.historyStorage={debugging:false,storageHash:new Object(),hashLoaded:false,put:function(key,value){this.assertValidKey(key);
																																if(this.hasKey(key))
																																{
																																	this.remove(key)
																																	}
																																	this.storageHash[key]=value;this.saveHashTable()
																																	},get:function(key){this.assertValidKey(key);
																																	this.loadHashTable();
																																	var value=this.storageHash[key];
																																	if(value==undefined)return null;else return value},remove:function(key)
																																	{
																																		this.assertValidKey(key);
																																		this.loadHashTable();
																																		delete this.storageHash[key];
																																		this.saveHashTable()},reset:function()
																																		{
																																			this.storageField.value="";
																																			this.storageHash=new Object()
																																			},hasKey:function(key)
																																			{
																																				this.assertValidKey(key);
																																				this.loadHashTable();if(typeof this.storageHash[key]=="undefined")return false;
																																				else return true},isValidKey:function(key){if(typeof key!="string")key=key.toString();
																																				var matcher=/^[a-zA-Z0-9_ \!\@\#\$\%\^\&\*\(\)\+\=\:\;\,\.\/\?\|\\\~\{\}\[\]]*$/;
																																				return matcher.test(key)
																																				},storageField:null,init:function()
																																				{
																																					var styleValue="position: absolute; top: -1000px; left: -1000px;";
																																					if(this.debugging==true)
																																					{
																																						styleValue="width: 30em; height: 30em;"
																																						}var newContent="<form id='historyStorageForm' "+"method='GET' "+"style='"+styleValue+"'>"+"<textarea id='historyStorageField' "+"style='"+styleValue+"'"+"left: -1000px;' "+"name='historyStorageField'></textarea>"+"</form>";
																																						document.write(newContent);
																																						this.storageField=document.getElementById("historyStorageField")
																																						},assertValidKey:function(key)
																																						{if(this.isValidKey(key)==false)
																																						{
																																							throw"Please provide a valid key for "+"window.historyStorage, key= "+key;
																																							}
																																							},loadHashTable:function()
																																							{
																																								if(this.hashLoaded==false)
																																								{
																																									var serializedHashTable=this.storageField.value;
																																									if(serializedHashTable!=""&&serializedHashTable!=null)
																																									{this.storageHash=eval('('+serializedHashTable+')')
																																									}this.hashLoaded=true}},saveHashTable:function()
																																									{
																																										this.loadHashTable();
																																									var serializedHashTable=JSON.stringify(this.storageHash);
																																									this.storageField.value=serializedHashTable
																																									}
																																									};
																																									Array.prototype.______array='______array';var JSON={org:'http://www.JSON.org',copyright:'(c)2005 JSON.org',license:'http://www.crockford.com/JSON/license.html',stringify:function(arg)
																																									{
																																										var c,i,l,s='',v;switch(typeof arg)
																																										{
																																											case'object':if(arg)
																																											{
																																												if(arg.______array=='______array')
																																												{
																																													for(i=0;i<arg.length;++i)
																																													{
																																														v=this.stringify(arg[i]);if(s)
																																														{s+=','}s+=v}return'['+s+']'}
																																														else if(typeof arg.toString!='undefined')
																																														{for(i in arg){v=arg[i];if(typeof v!='undefined'&&typeof v!='function')
																																														{v=this.stringify(v);if(s){s+=','}s+=this.stringify(i)+':'+v}}return'{'+s+'}'}
																																														}return'null';case'number':return isFinite(arg)?String(arg):'null';case'string':l=arg.length;s='"';
																																														for(i=0;i<l;i+=1){c=arg.charAt(i);if(c>=' ')
																																														{
																																															if(c=='\\'||c=='"'){s+='\\'}s+=c}
																																															else{switch(c)
																																															{
																																																case'\b':s+='\\b';
																																																break;
																																																case'\f':s+='\\f';
																																																break;
																																																case'\n':s+='\\n';
																																																break;
																																																case'\r':s+='\\r';
																																																break;
																																																case'\t':s+='\\t';
																																																break;
																																																default:c=c.charCodeAt();
																																																s+='\\u00'+Math.floor(c/16).toString(16)+(c%16).toString(16)}}}return s+'"';
																																																case'boolean':return String(arg);
																																																default:return'null'}},parse:function(text){var at=0;
																																																var ch=' ';
																																																function error(m){throw{name:'JSONError',message:m,at:at-1,text:text}}
																																																function next(){ch=text.charAt(at);at+=1;
																																																return ch}function white(){while(ch!=''&&ch<=' '){next()}}function str(){var i,s='',t,u;
																																																if(ch=='"'){outer:while(next()){if(ch=='"'){next();
																																																return s}
																																																else if(ch=='\\'){switch(next()){case'b':s+='\b';break;case'f':s+='\f';
																																																break;
																																																case'n':s+='\n';
																																																break;
																																																case'r':s+='\r';
																																																break;case't':s+='\t';
																																																break;case'u':u=0;
																																																for(i=0;i<4;i+=1)
																																																{t=parseInt(next(),16);
																																																if(!isFinite(t)){break outer}u=u*16+t}s+=String.fromCharCode(u);
																																																break;
																																																default:s+=ch}
																																																}
																																																else{s+=ch}}}
																																																error("Bad string")}
																																																function arr(){var a=[];if(ch=='[')
																																																								 {next();white();if(ch==']'){next();
																																																return a}while(ch){a.push(val());
																																																white();
																																																if(ch==']'){next();
																																																return a}
																																																else if(ch!=',')
																																																{
																																																	break
																																																	}next();
																																																	white()}}error("Bad array")}function obj(){var k,o={};if(ch=='{'){next();
																																																	white();
																																																	if(ch=='}'){next();return o}while(ch){k=str();
																																																	white();
																																																	if(ch!=':'){break}next();
																																																	o[k]=val();white();
																																																	if(ch=='}'){next();
																																																	return o}else if(ch!=','){break}next();
																																																	white()}}error("Bad object")}function num(){var n='',v;
																																																	if(ch=='-'){n='-';
																																																	next()}while(ch>='0'&&ch<='9'){n+=ch;next()}if(ch=='.'){n+='.';
																																																	while(next()&&ch>='0'&&ch<='9'){n+=ch}}if(ch=='e'||ch=='E'){n+='e';next();
																																																	if(ch=='-'||ch=='+'){n+=ch;next()}while(ch>='0'&&ch<='9'){n+=ch;
																																																	next()}}v=+n;
																																																	if(!isFinite(v)){error("Bad number")}else{return v}}function word(){switch(ch){case't':if(next()=='r'&&next()=='u'&&next()=='e'){next();
																																																	return true}break;
																																																	case'f':if(next()=='a'&&next()=='l'&&next()=='s'&&next()=='e'){next();
																																																	return false}break;
																																																	case'n':if(next()=='u'&&next()=='l'&&next()=='l'){next();
																																																	return null}break}error("Syntax error")}function val(){white();switch(ch){case'{':return obj();case'[':return arr();
																																																																													  case'"':return str();case'-':return num();default:return ch>='0'&&ch<='9'?num():word()}}return val()}};