/****************************************************************
 ****************************************************************
 **
 ** Menu Handling Routines
 **
 ** Copyright (c) 2004 Nameless-UK
 ** Copyright (c) 2005 Site Intelligence Ltd.
 **
 ****************************************************************
 ****************************************************************
 */


/****************************************************************
 * Timeout Stack and Lock
 ****************************************************************
 */
var menuTimeOutIDs = new Array();
var menuClearingTimeOuts = false;

/****************************************************************
 * Clear All Running Timeouts
 ****************************************************************
 */
function menuClearTimeouts() {
	if(!menuClearingTimeOuts) {
		menuClearingTimeOuts = true;
		while(menuTimeOutIDs.length > 0) {
			self.clearTimeout( menuTimeOutIDs.pop() );
		}
		menuClearingTimeOuts = false;
	}
}

/****************************************************************
 * Menu Hiding Routines
 ****************************************************************
 */
function menuHideAll() {
	// Clear timeouts
	menuClearTimeouts();

	// Hide submenus
	for(var iSubMenuIndex = 0; iSubMenuIndex < self.oMenus.aoSubMenus.length; iSubMenuIndex++) {
		classAdd(self.oMenus.aoSubMenus[ iSubMenuIndex ][0], 'hidden');
	}
}

function menuSlowHide(iDelay) {
	if(!menuClearingTimeOuts) {
		menuTimeOutIDs.push( self.setTimeout('menuHideAll();', iDelay) );
	}
}

/****************************************************************
 * Menu handlers
 ****************************************************************
 */
function menuOver() {
	// Hide everything else
	menuHideAll();

	// Re-position as required.
	var aInfo = self.oMenus.aoSubMenus[ this.oSubMenu.iSubMenuIndex ];
	this.oSubMenu.style.left = aInfo[1].offsetLeft + aInfo[2].offsetLeft - 1 + 'px';
	this.oSubMenu.style.top  = 0 + (document.documentElement.scrollTop + document.body.scrollTop) + 'px';

	// Show my submenu.
	classDel(this.oSubMenu, 'hidden');
}

function menuOut() {
	this.oSubMenu.menuSlowHide(500);
}

/****************************************************************
 * Submenu Handling
 ****************************************************************
 */
function menuSubOver() {
	// Clear timeouts
	menuClearTimeouts();
}

function menuSubOut() {
	this.menuSlowHide(250);
}

function menuSubClick() {
	this.menuSlowHide(250);
}

/****************************************************************
 * Menu Preparation
 * Run in the window with the menus in it
 ****************************************************************
 */
function menuMasterInit(oAllMenus) {
	// Create a container object to store all this
	window.oMenus              = new Object;
	window.oMenus.aoMenus      = new Array();
	window.oMenus.bInitialised = false;

	// Loop through all the top-level items
	for(var oMainMenuItem = oAllMenus.firstChild; oMainMenuItem; oMainMenuItem = oMainMenuItem.nextSibling) {

		// Ensure the item has a tag and is a UL
		if(!oMainMenuItem.tagName ||
		    oMainMenuItem.tagName.toUpperCase() != 'UL') {
			continue;
		}

		var bFirstMenuItem   = true;
		var oLastSubMenuItem = false;

		// Loop through all the second-level items.
		for(var oSubMenuItem = oMainMenuItem.firstChild; oSubMenuItem; oSubMenuItem = oSubMenuItem.nextSibling) {

			// Ensure the item has a tag and is a LI
			if(!oSubMenuItem.tagName ||
			    oSubMenuItem.tagName.toUpperCase() != 'LI') {
				continue;
			}

			// Find and process the first (/only!) A child.
			var oLink = oSubMenuItem.getElementsByTagName('A')[0];
			if(!oLink) {
				continue;
			}

			// Handle the first valid menu item
			if(bFirstMenuItem) {
				bFirstMenuItem = false;
				classAdd(oSubMenuItem, 'first');
				if(classMatch(oLink, 'disabled')) {
					var oImage = document.getElementById('menuShadow');
					if(oImage) {
						oImage.src = oImage.src.replace(/(\.gif)$/, '-disabled$1');
					}
				}
			}

			// Remember this incase it is the last menu item.
			oLastSubMenuItem = oSubMenuItem;

			// Find and process the first (/only!) UL child submenu.
			var oSubMenu = oSubMenuItem.getElementsByTagName('UL')[0];
			if(oSubMenu) {
				// Push the menu onto the stack
				window.oMenus.aoMenus.push(new Array( oLink,
													  oMainMenuItem,
													  oSubMenu ));

			}
			
			// The first time we do this we remember the onclick as we may overwrite it
			if (!oLink.menuInited)
			{
				oLink.menuInited = true;
				oLink.origOnClick = oLink.onclick;
			}
			
			// If this menu is disabled, stop onClick events and don't
			// attach the submenu to it.
			if (classMatch(oLink, 'disabled'))
			{
				// Set the onclick to return false so you can no longer click on the item
				oLink.onclick = function() {return(false);};
				
				// Remove from menu system
				window.oMenus.aoMenus.pop();
			}
			else if (oLink.origOnClick)
			{
				// Reset any original onclick handler
		       oLink.onclick = oLink.origOnClick;
		    }
		    else
		    { 
		   	   // Use a dummy onclick which just returns true so clicks work
			   oLink.onclick = function() {return(true);};
			}
		}

		// Don't forget to set the last child accordingly.
		if(oLastSubMenuItem) {
			classAdd(oLastSubMenuItem, 'last');
		}
	}
	window.oMenus.bInitialised = true;
	if (typeof(menuRenderId) != 'undefined')
	{
		window.oMenus.menuRenderId = menuRenderId;
	}
	else
	{
		window.oMenus.menuRenderId = false;
	}
	
	
}

/****************************************************************
 * Menu Creation
 * Run in the window displaying the menus
 ****************************************************************
 */
var menuContainer = null;
function menuFindContainer(bReCache) {
	// Look for the frame that will contain the menus
	if(!menuContainer || bReCache) {
		menuContainer = null;
		for(var oWindow = self; true; oWindow = oWindow.parent) {
			menuContainer = oWindow.frames['menuframe'];
			if(menuContainer || oWindow == self.top) {
				break;
			}
		}
	}
	// Return whatever's been found, or not.
	return(menuContainer);
}


function menuReset() {
	var oMenuContainer = menuFindContainer();
	if(oMenuContainer &&
	   oMenuContainer.oMenus) {
	
	   // Reset the initialised flag to ensure we don't get a race between the reload and the slave init
	   oMenuContainer.oMenus.bInitialised = false; 
	   
	   // Reload the menu frame so that enablers etc. fire
	   var href = oMenuContainer.location.href;
	   oMenuContainer.location.href = href;
	   
	   // Slave our menus off the menu frame - we we've cleared the initialised flag 
	   // this will wait for the menu frame to finish loading
	   menuSlaveInit();	   
	}
}


function menuSlaveInit() {
	// Try grabbing the tree container...
	var oMenuContainer = menuFindContainer();

	if(oMenuContainer &&
	   oMenuContainer.oMenus &&
	   oMenuContainer.oMenus.bInitialised &&
	   (typeof(menuRenderId) == 'undefined' || !oMenuContainer.oMenus.menuRenderId || oMenuContainer.oMenus.menuRenderId >= menuRenderId)) {

		self.oMenus = new Object;
		self.oMenus.aoSubMenus = new Array;

		// Loop through each submenu
		for(var iMenuIndex = 0; iMenuIndex < oMenuContainer.oMenus.aoMenus.length; iMenuIndex++) {
			// Shortcut link
			var aMenu = oMenuContainer.oMenus.aoMenus[ iMenuIndex ];

			// Clone the submenu
			var oSubMenuClone = document.createElement( aMenu[2].tagName );
			oSubMenuClone.outerHTML = aMenu[2].outerHTML;
			oSubMenuClone.innerHTML = aMenu[2].innerHTML;

			// Hide it, make it a submenu then add it to the document.
			classAdd(oSubMenuClone, 'hidden');
			classAdd(oSubMenuClone, 'submenu');
			document.body.appendChild(oSubMenuClone);

			// Set the x/y-position and minumum width (Moz only)
			oSubMenuClone.style.top  = '0';
			oSubMenuClone.style.left = aMenu[0].offsetLeft + aMenu[1].offsetLeft - 1 +'px';
			oSubMenuClone.style.minWidth = aMenu[0].offsetWidth +'px';

			// Find and disable all disabled items
			var aoDisabledItems = getElementsByClassName('disabled', oSubMenuClone);
			while(aoDisabledItems.length) {
				aoDisabledItems.pop().onclick = function() {return(false);};
			}

			// Determine this submenu's index and add it.
			oSubMenuClone.iSubMenuIndex = aMenu[0].iSubMenuIndex = self.oMenus.aoSubMenus.length;
			self.oMenus.aoSubMenus.push(new Array( oSubMenuClone, aMenu[0], aMenu[1] ));

			// Set the menu's over/out event handlers and a shortcut to the submenu.
			aMenu[0].onmouseover = menuOver;
			aMenu[0].onmouseout  = menuOut;
			aMenu[0].oSubMenu = self.oMenus.aoSubMenus[ oSubMenuClone.iSubMenuIndex ][0];

			// Set the submenu's over/out event handlers.
			aMenu[0].oSubMenu.onmouseover  = menuSubOver;
			aMenu[0].oSubMenu.onmouseout   = menuSubOut;
			aMenu[0].oSubMenu.onclick      = menuSubClick;
			aMenu[0].oSubMenu.menuSlowHide = menuSlowHide;
		}
		
		return;
	}


	// Not complete: schedule another try
	self.setTimeout(menuSlaveInit, 500);
}

/****************************************************************
 * OnLoad Initialisation
 ****************************************************************
 */
function menuOnLoad() {
	// Determine whether this is the menu-containing or menu-using frame
	var oAllMenus = document.getElementById('menus');
	if(oAllMenus) {
		menuMasterInit(oAllMenus);
	} else {
		menuSlaveInit();
	}
}

addToOnLoadChain(window, menuOnLoad);

