/**
* Ajax back/forward fixer
*/

function isArray(obj)
{
   if (obj.constructor.toString().indexOf("Array") == -1)
      return false;
   else
      return true;
};

function AUpdate( container, url, params, loader )
{
	this.url = url;
	this.params = params;
	this.container = container;
	if( loader != 'undefined' )
		this.loader = document.getElementById( loader );
	else
		this.loader = false;
	var oldComplete = false;
	
	// Try to show the loader
	if( this.loader )
		this.loader.style.visibility = 'visible';
	
	if( params.onComplete )
		oldComplete = this.params.onComplete;
	
	this.params.onComplete = function( transporter, jason )
	{
		var c_container = container;
		var c_url = url;
		var c_Complete = oldComplete;
		var c_loader = loader;
		document.ajaxfixer.onSuccess( c_container, transporter.responseText, c_url, c_loader );
		
		/*
		// update the title after the container is loaded
		if (jason && jason.title){
		  document.title = jason.title;
		}
		*/
		
		///////// evaluation of javascripts
		//alert(transporter.responseText.extractScripts())
		setTimeout(function() {transporter.responseText.evalScripts()}, 10);
		
		if( c_Complete )
			c_Complete( transporter, jason );
	};
	
	new Ajax.Request( this.url, this.params );
}

function AjaxFixer( window )
{
	this.current_hash = 'base-level';
	this.first_load = false;
	this.history = new History();
	this.history.addEventListener( "historyChange", this.onHistoryChange );
	
	this.data = new Array();
	document.ajaxfixer = this;
};

AjaxFixer.prototype.Update = function( container, url, params )
{
	return new AUpdate( container, url, params );
}

AjaxFixer.prototype.Save = function ( hash, container, data )
{
	if( !this.data[hash] )
		this.data[hash] = new Array();

	for( i=0; i<this.data[hash].length; i++ )
	{
		if( this.data[hash][i][0] == container )
		{
			this.data[hash][i][1] = data;
			return;
		}
	}
	
	this.data[hash].push( new Array( container, data ) );
};

AjaxFixer.prototype.onHistoryChange = function ( hash )
{
	if( !hash )
		hash = 'base-level';
	else
		hash = unescape( hash );
	if( document.ajaxfixer.current_hash != hash)
		document.ajaxfixer.Load( hash );
}

AjaxFixer.prototype.FirstLoad = function ()
{
	hash = this.history.getCurrent();
	if( !hash )
		return;
	// Break to container and URL
	var container = hash.slice( 0, hash.indexOf( '^' ) );
	var url = hash.slice( hash.indexOf( '^' ) + 1, hash.length );
	if (url.indexOf( '^' ) > -1){
    url = url.slice( 0, url.indexOf( '^' ) );
  }
	// check for remote load hacks
	var reg = new RegExp("^http", "i");
	if (reg.test(url)) return false;
	
	this.first_load = true;
	
	new AUpdate( container, unescape( url ), {},  container + 'Loader');
}

AjaxFixer.prototype.Load = function ( hash )
{
	if( !this.data[hash] )
		return;
	
	this.current_hash = hash;
	
	for( i=0; i<this.data[hash].length; i++ )
	{
		var el = document.getElementById( this.data[hash][i][0] );
		el.innerHTML = this.data[hash][i][1];

		///////// evaluation of javascripts
		setTimeout(function() {el.innerHTML.evalScripts()}, 10);

	}
};

AjaxFixer.prototype.onSuccess = function ( container, data, url, loader )
{
	
	var loader = document.getElementById( loader );
	el = document.getElementById( container );
	if( el )
	{
		var ohash = this.history.getCurrent();
		if(	!ohash )
			ohash = 'base-level';
		else
			ohash = unescape( ohash );
		if( this.first_load == false )
			this.Save( ohash, container, el.innerHTML );
		else
			this.first_load = false;
		hash = container + "^" + escape( url ) + "^" + Math.round(Math.random() * 10000);
		el.innerHTML = data;
		if( loader )
			loader.style.visibility = 'hidden';
		this.history.addHistory( hash );
		this.current_hash = unescape( hash );
		this.Save( unescape( hash ), container, data );
	}
	else
		alert( "Unable to connect to container" );
};

EventManager = function(arg)
{
	this._listeners = {};
	for (var i = 0; i < arguments.length; i++)
		this._listeners[arguments[i]] = [];
};

EventManager.prototype.addEventListener = function($type, $listener)
{
	for (var i = 0; i < this._listeners[$type].length; i++)
		if (this._listeners[$type][i] == $listener) return;
	this._listeners[$type].push($listener);
};

EventManager.prototype.removeEventListener = function($type, $listener)
{
	for (var i = 0; i < this._listeners[$type].length; i++)
	{
		if (this._listeners[$type][i] == $listener) 
		{
			this._listeners.splice(i,1);
			return;
		}
	}
};

EventManager.prototype.notifyListeners = function($type, $data)
{
	for (var i = 0; i < this._listeners[$type].length; i++)
		this._listeners[$type][i]($data);
};

QuickLoader = function()
{
	var _eventMgr = new EventManager("_quickLoad", "_quickLoadPriority");
	
	function _quickLoad()
	{
		if (document.removeEventListener)
			document.removeEventListener("load", _load, false);
		else
			if (window.detachEvent)
				window.detachEvent("onload", _load);

		_load();
	}
	function _load(e)
	{
		_eventMgr.notifyListeners("_quickLoadPriority");
		_eventMgr.notifyListeners("_quickLoad");
	}
	
	if (document.addEventListener)
	{
		document.addEventListener("DOMContentLoaded", _quickLoad, false);
		document.addEventListener("load", _load, false);
	} 
	else 
		if (window.attachEvent)
			window.attachEvent("onload", _load);
	
	if (window.ActiveXObject && window.print && !window.opera)
	{
		document.write("<script id=__"+"ie_onload defer src=javascript:void(0)><\/script>");
		var _script = document.getElementById("__"+"ie_onload");
		_script.onreadystatechange = function()
		{
			if (this.readyState == "complete")
				_quickLoad();
		};
	}
	
	var _QuickLoader = {
		addListener: function($method, $priority)
		{
			var $type = (!$priority)?"_quickLoad":"_quickLoadPriority";
			_eventMgr.addEventListener($type, $method);
		},
		removeListener: function($method, $priority)
		{
			var $type = (!$priority)?"_quickLoad":"_quickLoadPriority";
			_eventMgr.removeEventListener($type, $method);
		}
	};
	return _QuickLoader;
};

History = function()
{
	function Keeper() 
	{
		var _this = this,
			_pollInterval = 200, _intervalID,
			_currentHash;

		var _getHash = function()
		{
			return location.hash.substring(1);
		};

		_currentHash = _getHash();
		
		var _setHash = function($newHash)
		{
			window.location.hash = $newHash;
		}
		
		function _watchHash()
		{
			var $newHash = _getHash();
			if (_currentHash != $newHash)
			{
				_currentHash = $newHash;
				_this.notifyListeners("historyChange", $newHash);
			}
		}
		
		if (setInterval) _intervalID = setInterval(_watchHash, _pollInterval);
		
		function _createAnchor($newHash)
		{
			if (!_checkAnchorExists($newHash))
			{
				var $anchor = document.createElement("a");
				$anchor.setAttribute("name", $newHash);
				if (/MSIE/.test(navigator.userAgent) && !window.opera)
					$anchor = document.createElement('<a name="'+$newHash+'">'+$newHash+"</a>");
				with ($anchor.style)
				{
					position = "absolute";
					display = "block";
					top = getScrollY()+"px";
					left = getScrollX()+"px";
				}
				
				document.body.insertBefore($anchor,document.body.firstChild);
			}
		}

		function _checkAnchorExists($name)
		{
			if (document.getElementsByName($name).length > 0)
				return true;
		}

		if (typeof self.pageYOffset == "number")
		{
			function getScrollY()
			{
				return self.pageYOffset;
			}
		}
		else
			if (document.documentElement && document.documentElement.scrollTop)
			{
				function getScrollY()
				{
				return document.documentElement.scrollTop;
				}
			}
			else
				if (document.body)
				{
					function getScrollY()
					{
						return document.body.scrollTop;
					}
				}
		
		eval(String(getScrollY).toString().replace(/Top/g,"Left").replace(/Y/g,"X"));
		

		_this.getCurrent = function()
		{
			return _currentHash;
		};
		
		_this.addHistory = function($newHash)
		{ 

			_createAnchor(_currentHash);

			_this.addHistory = function($newHash)
			{
				if (_currentHash != $newHash)
				{
					_createAnchor($newHash);
					_currentHash = $newHash;
					_setHash($newHash);
					_this.notifyListeners("historyChange",$newHash);
				}
				return true;
			};

			return _this.addHistory($newHash);

		};

		if (  
		      ((/Chrome/.test(navigator.appVersion) || /Safari/.test(navigator.appVersion)) && (parseFloat(navigator.appVersion) < 5))
		){

			var _unFocusHistoryLength = history.length,
				_historyStates = {}, _form,
				_recentlyAdded = false;
			
			function _createSafariSetHashForm()
			{
				_form = document.createElement("form");
				_form.id = "unFocusHistoryForm";
				_form.method = "get";
				document.body.insertBefore(_form,document.body.firstChild);
			}
			
			_setHash = function($newHash)
			{
				_historyStates[_unFocusHistoryLength] = $newHash;
				_form.action = "#" + _getHash();
				_form.submit();
			}
			
			_getHash = function()
			{
				return _historyStates[_unFocusHistoryLength];
			};
			
			_historyStates[_unFocusHistoryLength] = _currentHash;
			
			_this.addHistory = function($newHash)
			{

				_createAnchor(_currentHash);

				_createSafariSetHashForm();

				_this.addHistory = function($newHash)
				{
					if (_currentHash != $newHash)
					{
						_createAnchor($newHash);
						_currentHash = $newHash;
						_unFocusHistoryLength = history.length+1;
						_recentlyAdded = true;
						_setHash($newHash);
						_this.notifyListeners("historyChange",$newHash);
						_recentlyAdded = false;
					}
					return true;
				};

				return _this.addHistory($newHash);
			};
			function _watchHistoryLength()
			{
				if (!_recentlyAdded)
				{
					var _historyLength = history.length;
					if (_historyLength != _unFocusHistoryLength)
					{
						_unFocusHistoryLength = _historyLength;
						
						var $newHash = _getHash();
						if (_currentHash != $newHash)
						{
							_currentHash = $newHash;
							_this.notifyListeners("historyChange", $newHash);
						}
					}
				}
			};
			
			clearInterval(_intervalID);

			_intervalID = setInterval(_watchHistoryLength, _pollInterval);
			
		}
		else 
			if (typeof ActiveXObject != "undefined" && window.print && 
				   !window.opera && navigator.userAgent.match(/MSIE (\d\.\d)/)[1] >= 5.5)
			{

			   var _historyFrameObj, _historyFrameRef;
			
				function _createHistoryFrame()
				{
					var $historyFrameName = "unFocusHistoryFrame";
					_historyFrameObj = document.createElement("iframe");
					_historyFrameObj.setAttribute("name", $historyFrameName);
					_historyFrameObj.setAttribute("id", $historyFrameName);

					_historyFrameObj.setAttribute("src", 'javascript:;');
					_historyFrameObj.style.position = "absolute";
					_historyFrameObj.style.top = "-900px";
					document.body.insertBefore(_historyFrameObj,document.body.firstChild);

					_historyFrameRef = frames[$historyFrameName];
					
					_createHistoryHTML(_currentHash, true);
				}
			
				function _createHistoryHTML($newHash)
				{
					with (_historyFrameRef.document)
					{
						open("text/html");
						write("<html><head></head><body onl",
							'oad="parent.ajaxfixer.history._updateFromHistory(\''+$newHash+'\');">',
							$newHash+"</body></html>");
						close();
					}
				}
			
				_this._updateFromHistory = function()
				{
					_this._updateFromHistory = function($hash)
					{
						_currentHash = $hash;
						_this.notifyListeners("historyChange", $hash);
					};
				};
			
				_this.addHistory = function($newHash)
				{
					
					_createHistoryFrame();
				
					_this.addHistory = function($newHash) 
					{
						if (_currentHash != $newHash)
						{
							_currentHash = $newHash;
							_createHistoryHTML($newHash);
						}
						return true;
					};

				return _this.addHistory($newHash);
				};

				_this.addEventListener("historyChange", function($hash) { _setHash($hash) });
			}
	}

	Keeper.prototype = new EventManager("historyChange");


	return new Keeper();
};

function addEvent(obj, evType, fn)
{
	 if (obj.addEventListener) {
		 obj.addEventListener(evType, fn, true);
		 return true;
	 } else if (obj.attachEvent) {
		 var r = obj.attachEvent("on"+evType, fn);
		return r;
	 } else {
		return false;
	 }
}

function LoadContainer()
{
	document.ajaxfixer.FirstLoad();
}

ajaxfixer = new AjaxFixer( window );
