/**
* Global JavaScript Definitions
*
* @author      		Matt Gifford
* @copyright			2006 Timeshifting Interactive Limited
* @version        	1.3.2 // fork
*/


xhtml = new WebPage();
window.onload = new Function("xhtml.init();");


/**
* Creates a new WebPage object with methods used by all pages, can be extended to add page specific methods.
*
* @author      		Matt Gifford
* @copyright			2006 Timeshifting Interactive Limited
* @version        	1.3.2
*/
function WebPage()
	{
	// Step 1. Define Properties

	this.initialized = false;
	this.debug = false;


	// Step 2. Define Public Methods

	/**
	* Sets up the initial page state and event handlers
	*/
	this.init = function()
		{
		this.initAnchors();
		this.initInputButtons();
		this.initMenus();			// Initialize drop down menus (if applicable for this document)

		// Set class as initialized
		this.initialized = true;
		}


	/**
	* Adds standard event handlers to process in-page links and offsite links
	*/
	this.initAnchors = function()
		{
		var links = document.getElementsByTagName('a');
		for(x=0; x<links.length; x++)
			{
			// 1. Hide marquee border for inpage links
			links[x].onfocus = function()
				{
				this.blur();
				}
			
			// 2. Make offsite links open in a new tab/window
			if(/\boffsite\b/.exec(links[x].className))
				{
				links[x].onclick = function()
					{
					window.open(this.href,'_blank');
					return false;
					}
				}
			
			// 3. If we're in debug mode, draw a red border around empty links
			if ( this.debug == true && links[x].href.indexOf('#') == (links[x].href.length-1) )
				{
				links[x].style.border = '2px solid #f00';
				}

			// 4. Disable links to the current page (improves user experience)
			if (links[x].href == window.location.toString() || links[x].href == window.location.toString() + '#')
				{
				links[x].style.cursor = 'default';
				links[x].style.textDecoration = 'none';
				}
			}
		}	



	/**
	* Adds rollover support to input[type=image] elements
	*/
	this.initInputButtons = function()
		{
		var rolloverCache = new Array();
		var inputs = document.getElementsByTagName('input');
		for(x=0; x<inputs.length; x++)
			{
			// Check if it's an image button with a roll over
			if (inputs[x].type == 'image' && inputs[x].className.indexOf('hasRollover') != -1)
				{
				// 1. Add event handlers to swap the images
				inputs[x].onmouseover = function()
					{
					this.src = this.src.replace(/\.(gif|jpg|png)/, '-over.$1');
					}
				inputs[x].onmouseout = function()
					{
					this.src = this.src.replace(/-over\.(gif|jpg|png)/, '.$1');
					}
				
				// 2. Pre-cache the rollover image
				var newImage = new Image();
				newImage.src = inputs[x].src.replace(/\.(gif|jpg|png)/i, '-over.$1');
				rolloverCache[rolloverCache.length] = newImage;
				}
			}

		}



	/**
	* Initializes the drop down menu system for the document (if applicable)
	*
	* (The menu container is specified by using the "dropDownMenu" class)
	*
	*/
	this.initMenus = function()
		{
		// Search the document for a drop down menu container
		var divs = document.getElementsByTagName('div');
		var menuContainer = null;
		for (var x = 0; x < divs.length; x++)
			{
			if (divs[x].className.indexOf('dropDownMenu') != -1)
				{
				menuContainer = divs[x];
				break;
				}
			}

		// Check if we're a menu container, if no return (the document contains no menus)
		if (menuContainer == null)
			{
			return
			}

		// Create menu timeout variable
		this.menuTimeout = null;

		// Add event handlers to menu headings
		this.menuItems = menuContainer.getElementsByTagName('div');
		for (var x = 0; x < this.menuItems.length; x++)
			{
			// Add show menu event handler to heading anchor
			this.menuItems[x].getElementsByTagName('a')[0].onmouseover = function()
				{
				try
					{
					xhtml.hideMenus();
					var parentDiv = findParent(this, 'div');
					parentDiv.className = 'active';
					}
				catch (err)
					{
					}
				}

			// Add hide menu event handler to heading anchor
			this.menuItems[x].getElementsByTagName('a')[0].onmouseout = function()
				{
				try
					{
					clearTimeout(xhtml.menuTimeout);
					xhtml.menuTimeout = setTimeout("xhtml.hideMenus();", 750);
					}
				catch (err)
					{
					}
				}

			// Add event handlers to menu items
			var links = this.menuItems[x].getElementsByTagName('li');
			if ( 0 < links.length )
				{
				for (var y = 0; y < links.length; y++)
					{
					// Clear timed menu hide on mouseover
					links[y].firstChild.onmouseover = function()
						{
						try
							{
							clearTimeout(xhtml.menuTimeout);
							}
						catch (err)
							{
							}
						}

					// Add timed menu hide on mouseout
					links[y].firstChild.onmouseout = function()
						{
						try
							{
							xhtml.menuTimeout = setTimeout("xhtml.hideMenus();", 750);
							}
						catch (err)
							{
							}
						}	
					}
				}
			else
				{
				// If the heading doesn't have a menu below it, make it inactive on mouseout
				this.menuItems[x].getElementsByTagName('a')[0].onmouseout = function()
					{
					try
						{
						xhtml.hideMenus();
						var parentDiv = findParent(this, 'div');
						parentDiv.className = 'inactive';
						}
					catch (err)
						{
						}
					}
				}
			}
		}


	/**
	* Hides all the down drop menus
	*/
	this.hideMenus = function()
		{
		clearTimeout(xhtml.menuTimeout);
		for (var x = 0; x < xhtml.menuItems.length; x++)
			{
			xhtml.menuItems[x].className = 'inactive';
			}
		}



	// Step 3. Define Private Methods

	/**
	* Finds the parent of the element with a node type of parentTagName
	*
	* @param		element					The element object to find the parent of
	* @param		parentTagName		The type of parent element to find
	*
	* @return		The element's parent object of the specified type, or null if no parent of that type could be found
	*/
	function findParent(element, parentTagName)
		{
		if (element == null)
			{
			return null;
			}
		else
			{
			if ( element.nodeType == 1 && element.tagName.toLowerCase() == parentTagName.toLowerCase() )
				{
				return element;
				}
			else
				{
				return findParent(element.parentNode, parentTagName);
				}
			}
		}
	}
