/*******************************
 incMenu.js

	Dynamic Javascript drop down menu
	Written by Kelly Sawatski
	08/17/2005
	
	Copyright 2005 Nortia Technologies Inc

*********************************/

/**************************
Usage:

Instantiate: 
	var objMenu = new Menu();
	
Add Items:
	var objItem = objMenu.AddItem(text, url);
	
Add SubMenu:
	objMenu = objItem.AddMenu();

Trigger a menu to open on an existing element
	objMenu.AttachToHtmlObj(elm) where elm is an existing object, or the id of an existing object

public properties
	
Menu:
displaydirection - current valid values are "down" and "right".  Defaults to "down";
dynamicwidth - true to use the same width as the element that triggered it, false to use the css width
css - stylesheet to use for the menu area

Item:
url - the url to the web page to open
label - the text to display in the link
css - stylesheet to use for items
style - style properties to override
*****************************/

var g_arrMenu = new Array();
var g_isIE = navigator.appName.indexOf("Microsoft")>-1;
var g_arrOpen = new Array();
var g_intDisplayed = 0;
var g_MenuDebug = document.location.href.indexOf("menudebug=1")!=-1;
var g_MenuDebugConsole = null;

/* ensure this script is loaded before displaying any menus.  This fixes an IE bug that causes an error if
   the mouse is hovering over the menu as it's loading
*/

if (g_isIE)
	window.attachEvent("onload", EnableMenu);
else
	EnableMenu();

document.onmousemove = CheckCloseAll; 

function EnableMenu() // turn on the menu by setting the flag
{
	g_intDisplayed=1;
}


/* Menu object */
function Menu()
{
	this.id = "Menu_" + g_arrMenu.length;
	this.displaydirection = "down";
	this.dynamicwidth = false;
	this.css = "DDMenu";
	this.items = new Array();
	this.htmlparent = null;
	this.parentmenu = null;
	this.idx = g_arrMenu.length;
	this.isOpen = false;
	this.activeArea = "";
	
	g_arrMenu[g_arrMenu.length] = this;
}

/* Menu Item Object */
function MenuItem(label, url, parentObj)
{
	this.url = url;
	this.label = label.replace(/ /g, "&nbsp;");
	this.css = "DDMenuItem";
	this.submenu = null;
	this.parentObj = parentObj;
	this.style = "";
	this.target = "";
}



/* Adds an item to a menu */	
Menu.prototype.AddItem = function(label, url)
{
	this.items[this.items.length] = new MenuItem(label, url, this);
		
	return this.items[this.items.length-1];
};

/* Adds the mouseover to an html object to trigger the opening of the menu
*  Valid parameters are the object's id or the object itself
*/
Menu.prototype.AttachToHtmlObj = function(o)
{	
	if (typeof(o)=='object')
		this.htmlparent = o;
	else
		this.htmlparent = document.getElementById(o);	
			
	this.htmlparent.onmouseover = doOpenMenu; 
	this.htmlparent.setAttribute("menuid", this.id);
};

/* Determines whether the mouse pointer is over any of the areas that have been associated
*  with the menu to mark it as "open"
*/
Menu.prototype.IsMouseOver = function(e)
{
	var arrArea;
	var arrCoord;
	var bReturn = false;
		
	arrArea = this.activeArea.split("|");
	
	for (var i=0; i<arrArea.length; i++)
	{
		arrCoord = arrArea[i].split(",");
		if (!this.CheckIsMouseOut(e, parseInt(arrCoord[0]), parseInt(arrCoord[2]), parseInt(arrCoord[1]), parseInt(arrCoord[3])))
		{
			bReturn = true;
			break;
		}
	}
	
	/*if (!bReturn)
	{
		var x,y;
		var o = document.getElementById("txtText");
		o.value += this.activeArea + "\n";
	
		if (g_isIE) 
		{ // grab the x-y pos.s if browser is IE
			x = window.event.clientX;
			y = window.event.clientY;
		} else {  // grab the x-y pos.s if browser is NS
			x = e.pageX;
			y = e.pageY;
		}
	
		x+= document.body.scrollLeft;
		y+= document.body.scrollTop;
		
		o.value += x + "," + y + "\n";
	
	}*/
	
	return bReturn;

}

/* Compares the mouse pointer to a set of coordinates to determine if the mouse is in the area */
Menu.prototype.CheckIsMouseOut = function(e, xMin, xMax, yMin, yMax)
{
	var x,y;
	
	if (g_isIE) 
	{ // grab the x-y pos.s if browser is IE
		x = window.event.clientX;
		y = window.event.clientY;
		x+= document.body.scrollLeft;
		y+= document.body.scrollTop;
	} else {  // grab the x-y pos.s if browser is NS
		x = e.pageX;
		y = e.pageY;
	}
	
	
	
	var str;
	
	//if (x<xMin || x>xMax || y<yMin || y>yMax)
	//{
	//	str = x + "," + y + "      " + xMin + "," + yMin + "      " + xMax + "," + yMax;
	//	document.getElementById("txtText").value += str + "\n";
	//}
	
	return (x<xMin || x>xMax || y<yMin || y>yMax);
	
}

/* Sets the areas of the screen that are valid for this menu to display */
Menu.prototype.InitActiveArea = function(objCont)
{
	var x,y,vLeft,vTop,objParent;
	
	// overflow 
	vLeft = objCont.offsetWidth - objCont.scrollWidth;
	vTop = objCont.offsetHeight - objCont.scrollHeight;	
	
	objParent = this.htmlparent;
	
	// set the area used by the menu
	this.activeArea = parseInt(objCont.style.left) - vLeft + ","
	this.activeArea += parseInt(objCont.style.top) - vTop+ ",";
	this.activeArea += parseInt(objCont.style.left) + parseInt(objCont.scrollWidth) + vLeft + ",";
	this.activeArea += parseInt(objCont.style.top) + parseInt(objCont.scrollHeight) + vTop;
				
	x = findPosX(this.htmlparent);
	y = findPosY(this.htmlparent);
	
	if (this.displaydirection=="right")
	{
		if (objParent.id)
		{
			if (objParent.id.indexOf("Sub")!=-1)  objParent = objParent.parentNode;
		}
		
	}
			
	// set the area for the menu's opener
	this.activeArea += "|" + (x-vLeft) + "," + (y-vTop) + ",";
	this.activeArea += (x+ vLeft) + parseInt(objParent.offsetWidth) + ",";
	this.activeArea += (y+vTop) + parseInt(objParent.offsetHeight);

	// add the area to the menu's parent menu, and its parent menus
	objParent = this;
	
	while (objParent = objParent.parentmenu)
	{
		objParent.activeArea += "|" + this.activeArea.slice(0, this.activeArea.indexOf("|"));
	}
}
	
/* Adds a menu to a menu item */
MenuItem.prototype.AddMenu = function()
{
	this.submenu = new Menu();
	this.submenu.parentmenu = this.parentObj;	
	return this.submenu;	
};

/* Closes the html menu */
function doClose(obj)
{
	if (obj) obj.style.display = "none";
}

/* Checks the menu array for a menu that matches the source element, and displays the menu
*  if found
*/
function doOpenMenu(e)
{
	var src = e ? e.currentTarget : event.srcElement;
	var objMenu = null;
	
	for (var i=0; i<g_arrMenu.length; i++)
	{
		if (g_arrMenu[i].htmlparent==src) 
		{	
			objMenu = g_arrMenu[i];
			break;
		}
	}
	if (g_intDisplayed>0) // bad kludge to avoid displaying if the mouse is over the menu when it is first built as the page is loading
		if (objMenu!=null) DisplayMenu(src, objMenu, e);
	
	//g_intDisplayed=1;
}

/* Creates, or enables the display of a menu and dynamically sets its position on the screen */
function DisplayMenu(objEventSrc, objMenu, e)
{
	var i;
		
	if (objMenu.items.length>0)
	{

		var objMenuParent = objMenu.parentmenu;		
		var objCont = document.getElementById(objMenu.id);
		g_arrOpen[g_arrOpen.length] = objMenu;
		
		if (objCont==null) 
		{
			objCont = document.createElement("div");
			var objItem, objLink;
			var bIsSubMenu = false;
			
			
			// check if there is a sub menu for one of the items in this menu
			for (i=0; i<objMenu.items.length; i++)
			{
				if (objMenu.items[i].submenu)
				{
					bIsSubMenu = true;
					break;
				}
			}
					
			// set the parent attribute for this menu
			if (objMenuParent!=null) objCont.setAttribute("parentmenu", objMenuParent.id);
							
			// create the menu
			if (objMenu.dynamicwidth) objCont.style.width = objEventSrc.scrollWidth + "px";
			objCont.className = objMenu.css;
			objCont.id = objMenu.id;
			
			for (i=0; i<objMenu.items.length; i++)
			{
				objItem = document.createElement("div");
				objItem.className = objMenu.items[i].css;
				
				if (objMenu.items[i].url)
				{
					objLink = document.createElement("a");
					if (objMenu.items[i].target!="") objLink.target = objMenu.items[i].target;
					objLink.className = objItem.className;
					objLink.href = objMenu.items[i].url;
				}
				else
				{
					objLink = document.createElement("span");
					objLink.className = "DDMenuItemSubMenu";
				}
					
				objLink.innerHTML = objMenu.items[i].label; //appendChild(document.createTextNode(objMenu.items[i].label));
				
				if (objMenu.items[i].submenu)
				{
					objLink.id = objMenu.id + "Sub_" + i;
					objMenu.items[i].submenu.AttachToHtmlObj(objLink);
				}
				else if (bIsSubMenu) // add a mouseover to close any other sub menus when hovering over this item
				{
					objLink.setAttribute("menuIdx", objMenu.idx);
					
				}
				
				// add any customized style attributes for the item
				if (objMenu.items[i].style!="") 
				{
					objItem.style.cssText = objMenu.items[i].style; //("style", objMenu.items[i].style);				
				}
				
				objItem.appendChild(objLink);
				objCont.appendChild(objItem);			
			}
						
			document.body.appendChild(objCont);
		}
		else
		{		
			objCont.style.display = "block";
		}
		
		objCont.style.position = "absolute";
		
		if (objMenu.displaydirection=="right")
		{
			objCont.style.top = findPosY(objEventSrc.parentNode) + "px";

			var objP;
			if (objMenu.parentmenu)		
			{
				objP = document.getElementById(objMenu.parentmenu.id);
				objCont.style.left = parseInt(objP.style.left) + objP.offsetWidth + "px";
			}
			else
			{
				objP = objMenu.htmlparent;
				objCont.style.left = findPosX(objP) + objP.offsetWidth + "px";
			}
			
		}
		else
		{
			
			
						
			objCont.style.left = findPosX(objEventSrc) + "px";
			objCont.style.top = (findPosY(objEventSrc) + objEventSrc.scrollHeight + objEventSrc.offsetParent.offsetTop + objEventSrc.offsetTop) +  "px";
			objCont.style.top = findPosY(objEventSrc) + objEventSrc.offsetHeight;
			
			//alert(objEventSrc.scrollHeight + "\n" + objEventSrc.clientHeight + "\n" + objEventSrc.offsetHeight + "\n" + objEventSrc.offsetParent.offsetTop);
			//alert(objEventSrc.offsetHeight - objEventSrc.scrollHeight);
			//if (g_isIE) objCont.style.top = parseInt(objCont.style.top) + 3 + "px";
		}
		
		objMenu.isOpen = true;
		
		
		// map out the space taken by the menu and its parents/children
		objMenu.InitActiveArea(objCont); 
				
		// uncomment this to see the areas mapped out for use with the menu
		if (g_MenuDebug)
		{
			// create the debug console
			if (g_MenuDebugConsole==null)
			{
				g_MenuDebugConsole = document.createElement("DIV");
				g_MenuDebugConsole.style.position = "absolute";
				g_MenuDebugConsole.style.padding = "3px";
				g_MenuDebugConsole.style.fontSize = "12px";
				g_MenuDebugConsole.style.borderStyle = "solid";
				g_MenuDebugConsole.style.borderColor = "#000000";
				g_MenuDebugConsole.style.borderWidth = "1px";
				g_MenuDebugConsole.style.backgroundColor = "#FFFFFF";
				g_MenuDebugConsole.style.right = "0px";
				document.body.appendChild(g_MenuDebugConsole);
			}
						
			g_MenuDebugConsole.innerHTML = "Mouse X: " + ((g_isIE ? window.event.clientX + document.body.scrollLeft : e.pageX)) + "px<br>Mouse Y: " +
				((g_isIE ? window.event.clientY + document.body.scrollTop: e.pageY)) + "px<br>" +  objMenu.activeArea + "<br>ScrollTop: " + document.body.scrollTop +
				"<br>scrollLeft: " + document.body.scrollLeft + "<br>body offset: " + document.body.offsetTop;
			
			
			g_MenuDebugConsole.style.top = (g_isIE ? window.event.clientY : e.pageY) + "px";
		}
		
		/* g_Debug.value = objMenu.id + " " + objMenu.activeArea;*/
		
		
	}
}

/* Gets the starting x Coordinate of an html object */
function findPosX(obj)
{
	var curleft = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curleft += obj.offsetLeft
			obj = obj.offsetParent;
		}
	}
	else if (obj.x)
		curleft += obj.x;
	return curleft;
}

/* Gets the starting y Coordinate of an html object */
function findPosY(obj)
{
	var curtop = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curtop += obj.offsetTop
			obj = obj.offsetParent;
		}
	}
	else if (obj.y)
		curtop += obj.y;
	return curtop;
}

/* Loops through all the menus marked as "open" and determines whether they should close */
function CheckCloseAll(e)
{
	var i;
	var objMenu;
	
	for (i=0; i<g_arrMenu.length; i++)
	{
		objMenu = g_arrMenu[i];
		if (objMenu.isOpen)
		{
			if (!objMenu.IsMouseOver(e))
			{
				doClose(document.getElementById(objMenu.id));
				objMenu.isOpen = false;
			}
		}
	}
	
	/*var x,y;
		
		if (g_isIE) 
	{ // grab the x-y pos.s if browser is IE
		x = window.event.clientX;
		y = window.event.clientY;
	} else {  // grab the x-y pos.s if browser is NS
		x = e.pageX;
		y = e.pageY;
	}
	
	x+= document.body.scrollLeft;
	y+= document.body.scrollTop;	
	
	g_MousePos.value = x + "," + y;*/
	
}

/* draws the areas that are valid for the menu - for debugging */
function DrawArea(id, x1, y1, x2, y2, col)
{
	var obj = document.getElementById(id);
	if (!obj)
	{
		obj = document.createElement("DIV");
		obj.style.borderStyle = "dotted";
		obj.style.borderWidth = "2px";
		obj.style.borderColor = col;
		obj.id = id;
		document.body.appendChild(obj);
	}
	obj.style.zIndex = 100;
	obj.style.position = "absolute";
	obj.style.left = x1 + "px";
	obj.style.top = y1 + "px";
	obj.style.width = x2-x1 + "px";
	obj.style.height = y2-y1 + "px";
	
	obj.style.display = "block";
}