/****************************************************************************
* Menu.js
*
* Copyright 2005, Winterborne Electronics Limited.
* Last update: 24 Mar 05.
*
* Multi-level drop-down table-based menus.
*
*****************************************************************************/

//------------------
//	Global Variables
//------------------

now = new Date();
function year() {
	document.write(now.getFullYear());
}

var VERTICAL	= true;
var HORIZONTAL	= false;

var topLevelMenuId;

var timeout	= 1;
var clockValue	= 0;
var clockTick;

var isIE = navigator.appName.indexOf("Microsoft") != -1;


//---------------------------------------------
//	Menu Item Object
//	The individual elements that comprise a menu.
//	Objects of type Item are used to create cells
//	of a table when the page is first loaded.
//	Thereafter, it is the tables and cells themselves
//	that are operated upon.
//---------------------------------------------
function Item(parent, index, childMenu, link, caption)
{
	//-----------------------------------------
	//	Attributes
	//-----------------------------------------
	this.parent	= parent;
	this.childMenu	= childMenu;
	this.itemId	= parent.menuId + index;
	this.link	= link;
	this.caption	= caption;
	this.cell	= new Object();
	
	//-----------------------------------------
	//	Methods
	//-----------------------------------------
	//	InsertItem method
	//	Creates the Item as a cell in a table
	//	and sets its attributes using the object's
	//	attributes.
	Item.prototype.InsertItem = function(parentTable)
	{
		var cell		= document.createElement("TD");
		cell.outStyle		= this.parent.outStyle;
		cell.overStyle		= this.parent.overStyle;
		cell.parentMenu		= parentTable;
		cell.childMenu		= null;
		cell.className		= this.parent.outStyle;
		cell.id			= this.itemId;
		cell.link		= this.link;
		cell.onmouseover	= showMenu;
		cell.onmouseout		= hideMenu;
		cell.onclick		= loadPage;
		cell.appendChild(document.createTextNode(this.caption));
		this.cell		= cell;
		return this.cell;
	}
	
	//-----------------------------------------
	//	AddSubMenu method
	//	Adds a reference to the table cell to identify
	//	the table element containing the childMenu,
	//	if any.
	Item.prototype.AddSubMenu = function()
	{
		if (null != this.childMenu)
		{
			var childMenuTable = document.getElementById(this.childMenu.menuId);
			if (null != childMenuTable)
			{
				this.cell.childMenu = childMenuTable;
				var parentMenuTable = document.getElementById(this.cell.parentMenu.id);
				parentMenuTable.childMenu.push(childMenuTable);
			}
		}
	}
}


//---------------------------------------------
//	Menu Object
//	The container for the menu items
//	Objects of type Menu are used to create tables
//	holding the menus when the page is first loaded.
//	Thereafter, it is the tables and cells themselves
//	that are operated upon.
//---------------------------------------------
function Menu(menuId, parentMenu, layout, visibility, menuStyle, outStyle, overStyle)
{
	//	Attributes
	this.menuId	= menuId;
	this.parentMenu	= parentMenu;
	this.layout	= layout;
	this.visibility	= visibility;
	this.menuStyle	= menuStyle;
	this.outStyle	= outStyle;
	this.overStyle	= overStyle;
	this.items	= new Array();
	
	//-----------------------------------------
	//	Methods
	//-----------------------------------------
	//	InsertMenu method
	//	Create the table to display the menu and its items
	//	and append it to the supplied element.
	Menu.prototype.InsertMenu = function(element)
	{
		var table = document.createElement("TABLE");
		var tbody = document.createElement("TBODY");
		var row = document.createElement("TR");
		table.className		= this.menuStyle;
		table.id		= this.menuId;
		table.layout		= this.layout;
		table.childMenu		= new Array();
		table.parentMenu	= null;
		if (null != this.parentMenu)
		{
			var parentTable	= document.getElementById(this.parentMenu.menuId)
			if (null != parentTable)
				table.parentMenu = parentTable;
		}
		if (isIE)
			table.style.setAttribute('display', this.visibility);
		else
			table.style.display = "" + this.visibility;
		for (var i = 0; i < this.items.length; i++)
		{
			if ((VERTICAL == this.layout)	&& (i > 0))
				row = document.createElement("TR");
			row.appendChild(this.items[i].InsertItem(table));
			if (VERTICAL == this.layout)
				tbody.appendChild(row);
		}
		if (HORIZONTAL == this.layout)
			tbody.appendChild(row);
		table.appendChild(tbody);
		element.appendChild(table);
	}
}


//---------------------------------------------
//	Table Cell Event Handlers
//---------------------------------------------
//	onmouseover event handler
//	Changes the style of the table cell that
//	invoked this handler to the cell's overStyle
//	and displays the cell's childMenu, if any.
function showMenu()
{
	StopFader();
	CloseMenus(this.parentMenu);

	//	Change the style of the cell
	this.className = this.overStyle;
	
	//	Display the child menu, if any
	if (null != this.childMenu)
	{
		//	Make the child menu visible
		//	and specify that its position is absolute
		this.childMenu.style.display = 'block';
		this.childMenu.style.position = 'absolute';

		if (VERTICAL == this.parentMenu.layout)
		{
			//	Set the child menu's left and top attributes
			//	according to the parent menu's offsets
			this.childMenu.style.left = GetAscendingLefts(this.parentMenu) + this.parentMenu.offsetWidth;
			this.childMenu.style.top  = GetAscendingTops(this) - document.getElementById(topLevelMenuId + "0").offsetTop;
		}
		else
		{
			//	Set the child menu's left and top attributes
			//	according to the parent menu's offsets
			this.childMenu.style.left = GetAscendingLefts(this) - document.getElementById(topLevelMenuId + "0").offsetLeft;
			this.childMenu.style.top  = GetAscendingTops(this.parentMenu) + this.parentMenu.offsetHeight;
			if (this.childMenu.offsetWidth < this.offsetWidth)
				this.childMenu.style.width = this.offsetWidth;
		}
	}

	if (this.link != null)
		this.style.cursor = 'pointer';
	else
		this.style.cursor = 'arrow';
}
	
//-----------------------------------------
//	onmouseout event handler
//	Changes the style of the table cell that
//	invoked this handler to the cell's outStyle
//	and starts the timer to hide the menu.
function hideMenu()
{
	this.className = this.outStyle;
	StartFader();
}
	
//-----------------------------------------
//	onclick event handler
//	Loads the page referenced by the cell's
//	link attribute, if any.
function loadPage()
{
	if (null != this.link)
	{
		var pattern = /htm/i
		if (!pattern.test(this.link))
		{
			var newWin = window.open();
			newWin.location.href = this.link;
		}
		else
			location.href = this.link;
		StopFader();
		CloseMenus(this.parentMenu);
	}
}


//---------------------------------------------
//	Table Cell Utility Functions
//---------------------------------------------
//	CloseMenus function
//	Close a displayed menu hierarchy for all submenus
//	of the supplied menu element.
function CloseMenus(element)
{
	for (var i = 0; i < element.childMenu.length; i++)
	{
		element.childMenu[i].style.display = 'none';
		CloseMenus(element.childMenu[i]);
	}
}

//---------------------------------------------
//	GetAscendingLefts function
//	Positioning for the left edge of a menu.
function GetAscendingLefts(element)
{
	if (element == null)
		return 0;
	return element.offsetLeft + GetAscendingLefts(element.offsetParent);
}

//---------------------------------------------
//	GetAscendingTops function
//	Positioning for the top edge of a menu.
function GetAscendingTops(element)
{
	if (element == null)
		return 0;
	return element.offsetTop + GetAscendingTops(element.offsetParent);
}


//---------------------------------------------
//	Fader Functions
//---------------------------------------------
//	StartFader function
//	Controls the delayed closure of a menu
//	once the mouse has moved off all menus.
function StartFader()
{
	if (clockValue >= timeout)
	{
		StopFader();
		CloseMenus(document.getElementById(topLevelMenuId));
	}
	else
	{
		clockValue++;
		clockTick = setTimeout("StartFader();", 1000);
	}
}

//---------------------------------------------
//	StopFader function
//	Cancels any fader in efect.
function StopFader()
{
	clockValue = 0;
	clearTimeout(clockTick);
}


//---------------------------------------------
//	Global Functions
//---------------------------------------------
//	insertMenus function
//	Creates the menu tables and cells from the
//	supplied menus and inserts them as children
//	of the element identified by the supplied
//	elementID, then creates a parent/child
//	hierarchy for the menu tables.
function insertMenus(menus, elementID)
{
	topLevelMenuId = menus[0].menuId;
	var container = document.getElementById(elementID);
	for (var i = 0; i < menus.length; i++)
	{
		menus[i].InsertMenu(container);
	}
	for (var i = 0; i < menus.length; i++)
	{
		for (var j = 0; j < menus[i].items.length; j++)
		{
			menus[i].items[j].AddSubMenu();
		}
	}
}
