//////////////////////////////////////////////////////////////
// Side (drop down) Menu Functions & Objects
// v1.00 (Budd Wright)
//
// Description:
//////////////////////////////////////////////////////////////
// Contains side menu functions and objects
//////////////////////////////////////////////////////////////
//
// Usage:
//////////////////////////////////////////////////////////////
// <script language="javascript" src="js/menu_side.js"></script>
//////////////////////////////////////////////////////////////
//
// v1.00 Notes
// -----------
//
//
// Known Issues
// ------------
// 
//
// Examples
// --------
//
//
//////////////////////////////////////////////////////////////






/////////////////////////////////////
// Object Constructors
/////////////////////////////////////



function Menu(label, id, frame)
{
	this.id = id;										// id to the variable used to create this menu
	this.label = label;									// label
	this.frame = frame;									// frame to send links into

	this.cellspacing = 0;								// Spacing between top level cells
	this.closeDelay = 1500;								// Delay in ms for menu closing onmouseout
	this.timer = setTimeout(this.id + ".StopTimer()", 1);	// Timer used for this menu closing its MenuItems after mouseout

	this.selectedMenuItem = null;						// index of menuItem currently selected

	this.menuItems = new Array();						// array of MenuItems
	this.menuLayers = new Array();						// array of menu div layers

	this.Initiate = Initiate;
	this.Add = Add;
	this.Click = Click;
	this.Expand = Expand;
	this.ExpandChild = ExpandChild;
	this.CloseAll = CloseAll;
	this.CloseSubmenus = CloseSubmenus;
	this.StartTimer = StartTimer;
	this.StopTimer = StopTimer;
}


function MenuItem(id, label, parentId, urlLink, cellClass)
{
	this.id = id;								// id
	this.label = label;							// UI label
	this.parentId = parentId;					// parent ID
	this.urlLink = urlLink;						// url for link MenuItem
	this.cellClass = cellClass;					// cell class

	this.dropDownClass = "submenuTable";		// class for any child menu of this menuItem
	this.level = 0;								// depth level for this MenuItem

	this.isTopLevel = false;					// Top level MenuItem
	this.hasChildren = false;					// Openable
	this.isOpen = false;						// current open state for parent item
	this.isSelected = false;					// currently highlighted / selected
	this.icon = null;							// standard icon
	this.iconSelected = null;					// selected state icon

	this.menuItems = new Array();				// array of submenu MenuItems


	// Set link status
	if(urlLink != null)
		this.isLink = true;
	else
		this.isLink = false;
}




/* Menu Methods */


/* Menu.Initiate() */
// Initiates and displays the menu
function Initiate()
{
	// Initialize HTML table for menu display
	document.write("<table cellspacing=\"" + this.cellspacing + "\" cellpadding=\"0\" border=\"0\" align=\"left\" class=\"categoryContainer\">");


	// Loop through all MenuItems; Initialize their settings and show level 0 / top level parents
	for(var x = 0; x < this.menuItems.length; x++)
	{
		var menuItem = this.menuItems[x];

	
		// Display top level parents, set top level bool
		if(menuItem.parentId == 0)
		{
			menuItem.isTopLevel = true;

			// Create row
			document.write("<tr>");

			// Write bullet cell
			document.write("<td class=\"categoryBullet\"><img src=\"../images/clear.gif\" border=\"0\" alt=\"\"></td>");


			if(menuItem.isLink)
				document.write("<td class=\"" + menuItem.cellClass + "\" onMouseOut=\"" + this.id + ".StartTimer()\" onMouseOver=\"" + this.id + ".StopTimer()\"><a href=\"" + menuItem.urlLink + "\" onMouseOver=\"" + this.id + ".Expand(" + x + ", this)\" target=\"" + this.frame + "\" class=\"category\">" + menuItem.label + "</a></td>");
			else
				document.write("<td class=\"" + menuItem.cellClass + "\" onMouseOut=\"" + this.id + ".StartTimer()\" onMouseOver=\"" + this.id + ".StopTimer()\"><a href=\"#\" onMouseOver=\"" + this.id + ".Expand(" + x + ", this)\" class=\"category\">" + menuItem.label + "</a></td>");

			// Close row
			document.write("</tr>");
		}


		// Create references to children  (start at index x, since MenuItems are added top-down; saves some time)
		for(var y = x; y < this.menuItems.length; y++)
		{
			// Anything with a parentId of this MenuItem's id is added to the menuItems array
			if(this.menuItems[y].parentId == menuItem.id)
				menuItem.menuItems[ menuItem.menuItems.length ] = this.menuItems[y];
		}

		if(menuItem.menuItems.length > 0)
			menuItem.hasChildren = true;


		// Determine the depth level of this MenuItem by the number of parents it has
		if(menuItem.parentId != 0)
		{
			var nextParentId = menuItem.parentId;

			while(nextParentId != 0)
			{
				// Increment the depth level because another parent exists
				menuItem.level += 1;

				for(var y = 0; y < x; y++)
				{
					if(this.menuItems[y].id == nextParentId)
					{
						// Found the parent, use its parentId as the next parentId to search for
						nextParentId = this.menuItems[y].parentId;
						break;
					}
				}
			}
		}

	}
	//- Loop through all MenuItems; Initialize their settings and show level 0 / top level parents


	// Write end
	document.write("</table>");

}


/* Menu.Add() */
// Adds a new MenuItem into the menu's menuItems array at the next index
function Add(id, label, parentId, urlLink, cellClass)
{
	var index = this.menuItems.length;

	this.menuItems[index] = new MenuItem(id, label, parentId, urlLink, cellClass);

	return this.menuItems[index];
}


/* Menu.Click() */
// Handles mouse clicks on menuItems
function Click()
{
	// Close all menus
	this.CloseAll();
}


/* Menu.Expand() */
// Opens a menuItem and displays its children
function Expand(menuItemId, linkReference)
{
	// Reference to the affected menuItem
	var menuItem = this.menuItems[menuItemId];

	// If the active MenuItem is top level, close all other menus
	if( menuItem.isTopLevel)
		this.CloseAll();

	// Only expand when a MenuItem has a submenu (children)
	if(! menuItem.hasChildren)
		return;





	// Create nodes to contain new menu
	var submenu = document.createElement("div");
	var frameReference = document.getElementById("iFrameBase").cloneNode(false);

	// Set the properties of the new div and frame
	frameReference.className = "iFrame";
	frameReference.id = "baseFrame" + menuItemId;
	frameReference.name = "baseFrame" + menuItemId;
	frameReference.style.display = "inline";

	submenu.className = "menuDiv";
	submenu.id = "submenu" + menuItemId;
	submenu.name = "frameReference" + menuItemId;
	submenu.style.display = "inline";

	// Position the frame and submenu
	frameReference.style.top = (GetTotalOffsetTop(linkReference) + ( linkReference.parentNode.offsetHeight / 2 ) ) + "px";
	submenu.style.top = frameReference.style.top;


	frameReference.style.left = ( GetTotalOffsetLeft(linkReference) + linkReference.parentNode.offsetWidth ) + "px";
	submenu.style.left = frameReference.style.left;


	// Create the inner HTML for the new menu
	var htmlCode = "<table class=\"" + menuItem.dropDownClass + "\">";
	for(var x = 0; x < menuItem.menuItems.length; x++)
	{
		// Class based on MenuItem child state
		if(menuItem.menuItems[x].hasChildren)
			var cellClass = "hasSubmenu";
		else
			var cellClass = "noSubmenu";

		if(menuItem.menuItems[x].isLink)
		{
			if(menuItem.menuItems[x].urlLink.indexOf("open:") == -1)
				// Regular hyperlink
				htmlCode += "<tr><td class=\"" + cellClass + "\"><a href=\"" + menuItem.menuItems[x].urlLink + "\" target=\"" + this.frame + "\" onMouseOver=\"" + this.id + ".ExpandChild(" + menuItem.menuItems[x].id + ", this)\" onClick=\"" + this.id + ".Click()\">" + menuItem.menuItems[x].label + "</a></td></tr>";
			else
				// Open new window
				htmlCode += "<tr><td class=\"" + cellClass + "\"><a href=\"" + menuItem.menuItems[x].urlLink.substring(5) + "\" target=\"_blank\" onMouseOver=\"" + this.id + ".ExpandChild(" + menuItem.menuItems[x].id + ", this)\" onClick=\"" + this.id + ".Click()\">" + menuItem.menuItems[x].label + "</a></td></tr>";
		}
		else
			htmlCode += "<tr><td class=\"" + cellClass + "\"><a href=\"#\" onMouseOver=\"" + this.id + ".ExpandChild(" + menuItem.menuItems[x].id + ", this)\">" + menuItem.menuItems[x].label + "</a></td></tr>";
	}

	htmlCode += "</table>";


	// Display the new submenu
	submenu.innerHTML = htmlCode;


	document.body.appendChild(frameReference);
	document.body.appendChild(submenu);

	// Adjust the iframe's dimensions
	frameReference.style.height = submenu.offsetHeight;
	frameReference.style.width = submenu.offsetWidth;

	// Add an onMouseOut event handler to the submenu
	submenu.setAttribute("menuId", this.id);
	submenu.onmouseout =	function() {	eval( this.getAttribute("menuId") + ".StartTimer()");	};
	submenu.onmouseover =	function() {	eval( this.getAttribute("menuId") + ".StopTimer()");	};

	// Create a permanent reference in the Menu object
	var newMenuLayer = this.menuLayers[ this.menuLayers.length ] = new Array();
	newMenuLayer[0] = submenu;
	newMenuLayer[1] = frameReference;
	newMenuLayer[2] = 1;
}


/* Menu.ExpandChild() */
// Opens a sub menuItem and displays its children -- same as Expand except menu is displayed to the right instead of below
function ExpandChild(menuItemId, linkReference)
{
	// Reference to the affected menuItem
	var menuItem = null;

	for(var x = 0; x < this.menuItems.length; x++)
	{
		if(this.menuItems[x].id == menuItemId)
		{
			menuItem = this.menuItems[x];
			break;
		}
	}


	// Close everything under this menuItem's depth level
	this.CloseSubmenus(menuItem.level);

	// Only expand when a MenuItem has a submenu (children)
	if(! menuItem.hasChildren)
		return;





	// Create nodes to contain new menu
	var submenu = document.createElement("div");
	var frameReference = document.getElementById("iFrameBase").cloneNode(false);

	// Set the properties of the new div and frame
	frameReference.className = "iFrame";
	frameReference.id = "baseFrame" + menuItemId;
	frameReference.name = "baseFrame" + menuItemId;
	frameReference.style.display = "inline";

	submenu.className = "menuDiv";
	submenu.id = "submenu" + menuItemId;
	submenu.name = "frameReference" + menuItemId;
	submenu.style.display = "inline";

	// Position the frame and submenu
	frameReference.style.top = (GetTotalOffsetTop(linkReference)) + "px";
	submenu.style.top = frameReference.style.top;


	frameReference.style.left = (GetTotalOffsetLeft(linkReference) + linkReference.parentNode.offsetWidth - 5) + "px";
	submenu.style.left = frameReference.style.left;


	// Create the inner HTML for the new menu
	var htmlCode = "<table class=\"" + menuItem.dropDownClass + "\">";
	for(var x = 0; x < menuItem.menuItems.length; x++)
	{
		// Class based on MenuItem child state
		if(menuItem.menuItems[x].hasChildren)
			var cellClass = "hasSubmenu";
		else
			var cellClass = "noSubmenu";

		if(menuItem.menuItems[x].isLink)
		{
			if(menuItem.menuItems[x].urlLink.indexOf("open:") == -1)
				// Regular hyperlink
				htmlCode += "<tr><td class=\"" + cellClass + "\"><a href=\"" + menuItem.menuItems[x].urlLink + "\" target=\"" + this.frame + "\" onMouseOver=\"" + this.id + ".ExpandChild(" + menuItem.menuItems[x].id + ", this)\" onClick=\"" + this.id + ".Click()\">" + menuItem.menuItems[x].label + "</a></td></tr>";
			else
				// Open new window
				htmlCode += "<tr><td class=\"" + cellClass + "\"><a href=\"" + menuItem.menuItems[x].urlLink.substring(5) + "\" target=\"_blank\" onMouseOver=\"" + this.id + ".ExpandChild(" + menuItem.menuItems[x].id + ", this)\" onClick=\"" + this.id + ".Click()\">" + menuItem.menuItems[x].label + "</a></td></tr>";
		}
		else
			htmlCode += "<tr><td class=\"" + cellClass + "\"><a href=\"#\" onMouseOver=\"" + this.id + ".ExpandChild(" + menuItem.menuItems[x].id + ", this)\">" + menuItem.menuItems[x].label + "</a></td></tr>";
	}

	htmlCode += "</table>";


	// Display the new submenu
	submenu.innerHTML = htmlCode;


	document.body.appendChild(frameReference);
	document.body.appendChild(submenu);

	// Adjust the iframe's dimensions
	frameReference.style.height = submenu.offsetHeight;
	frameReference.style.width = submenu.offsetWidth;

	// Add an onMouseOut event handler to the submenu
	submenu.setAttribute("menuId", this.id);
	submenu.onmouseout =	function() {	eval( this.getAttribute("menuId") + ".StartTimer()");	};
	submenu.onmouseover =	function() {	eval( this.getAttribute("menuId") + ".StopTimer()");	};



	// Create a permanent reference in the Menu object
	var newMenuLayer = this.menuLayers[ this.menuLayers.length ] = new Array();
	newMenuLayer[0] = submenu;
	newMenuLayer[1] = frameReference;
	newMenuLayer[2] = menuItem.level + 1;
}



/* Menu.CloseAll() */
// Closes all menus
function CloseAll()
{
	// Stop any timers
	this.StopTimer();

	for(var x = 0; x < this.menuLayers.length; x++)
	{
		document.body.removeChild(this.menuLayers[x][0]);
		document.body.removeChild(this.menuLayers[x][1]);
	}

	// Clear the array by recreating it
	this.menuLayers = new Array();
}


/* Menu.CloseSubmenus() */
// Closes all menus under a specified depth level
function CloseSubmenus(depthLevel)
{
	// Stop any timers
	this.StopTimer();

	// The menu's menuLayers array will be rebuilt
	var menuLayers = new Array();

	for(var x = 0; x < this.menuLayers.length; x++)
	{
		if( this.menuLayers[x][2] > depthLevel)
		{
			document.body.removeChild(this.menuLayers[x][0]);
			document.body.removeChild(this.menuLayers[x][1]);
		}
		else
		{
			// This menu layer stays open
			var y = menuLayers.length;
			menuLayers[y] = new Array();
			menuLayers[y][0] = this.menuLayers[x][0];
			menuLayers[y][1] = this.menuLayers[x][1];
			menuLayers[y][2] = this.menuLayers[x][2];
		}
	}

	// Set the menu object's menuLayers array to the new array
	this.menuLayers = menuLayers;
}


/* Menu.StartTimer() */
// Starts the CloseAll() timer
function StartTimer()
{
	this.timer = setTimeout(this.id + ".CloseAll()", this.closeDelay);
}


/* Menu.StopTimer() */
// Stops the CloseAll() timer
function StopTimer()
{
	clearTimeout(this.timer);
}








/* GetTotalOffsetLeft() */
// Calculates the width between the object and the left edge of the browser
function GetTotalOffsetLeft(objectReference)
{
	var totalLeft = 0;

	// Start with the anchor's table cell (td) tag
	var parent = objectReference.parentNode;

	while(parent != document.body)
	{
		totalLeft += parseInt(parent.offsetLeft, 10);
		
		parent = parent.parentNode;
	}

	return totalLeft;
}


/* GetTotalOffsetTop() */
// Calculates the height between the object and the top edge of the browser
function GetTotalOffsetTop(objectReference)
{
	var totalTop = 0;

	// Instead of starting with the anchor tag, start with the table row the link is in
	// (Otherwise a proportionate amount is unnecessarily added to each additional link / row)
	var parent = objectReference.parentNode.parentNode;

	while(parent != document.body)
	{
		if(parent.tagName != "TD")
		{
			totalTop += parseInt(parent.offsetTop, 10);
		}
		
		parent = parent.parentNode;
	}

	return totalTop;
}