/*
	file:	.../menu.js
	
	about:	implements js-functions enabling the column-based menu
*/

/* initialize menu variablees */
var menuRoot;
var menuTop = 0;
var currentMenuOpener = null;
var topMenuOpeners = new Array ();
var defaultSelected;

var menuTimer;

function startMenuTimer() {
	if (defaultSelected == null) {
		menuTimer = setTimeout('hideAllMenus();',5000);
	} else {
		menuTimer = setTimeout('openMenuByMenuLink(defaultSelected);',5000);
	}
}

function endMenuTimer() {
	clearTimeout(menuTimer); 
	menuTimer = null;
}
	
//function dumptxt (x)
//{
//	document.getElementById('foober').value += "----------\n" + x + "\n";
//}

/* hide all menus */
function hideAllMenus () {
	// dumptxt ("!!!!HIDING ALL (NOT)");
	// return;
	for (var i=0; i<topMenuOpeners.length;i++) {
		hideChildMenuRecurse (topMenuOpeners[i]);
	}
}

/* hide the given menu (specified by its menu opener) and any sub-menus
*/
function hideChildMenuRecurse (thisMenuOpener) {
	if (thisMenuOpener.childMenuOpenerList) {
		// hide any sub-menus of the current menu
		for (var i=0; i<thisMenuOpener.childMenuOpenerList.length;i++) {
			hideChildMenuRecurse (thisMenuOpener.childMenuOpenerList[i]);
			// dumptxt (thisMenuOpener.id + " - hide:" + thisMenuOpener.childMenuOpenerList[i].id);
		}
		if (thisMenuOpener.sibMenuContainer) {
			thisMenuOpener.sibMenuContainer.style.visibility = 'hidden';
			// thisMenuOpener.style.fontWeight = 'normal';
			// dumptxt("hiding child menu:" + thisMenuOpener.id);
		}
	}
}

/* compare the parent menus of the current menu opener and the selected
menu opener to find the highest "open" node in the menu to begin cloding
menu items from */
function getTopHidingMenu (thisSelectedMenuOpener) {
	var topHidingMenu;
	var isUnder = false;
	var breakLoop = false;

	/* get the top-level menu opener from the current menu opener's
	parent menu openers, excepting any menu openers shared with the
	selected menu */
	if (thisSelectedMenuOpener.parentMenuOpenerList.length>0) {
		/* compare parents of the new opener with parents of the current opener */
		for (var j=0; j<thisSelectedMenuOpener.parentMenuOpenerList.length; j++) {
			if (currentMenuOpener == thisSelectedMenuOpener.parentMenuOpenerList[j] ) {
				isUnder = true;
				// dumptxt("new opener is UNDER current menu");
				break;
			}
		}
		
		if ( isUnder == false )
		{
			/* compare parents of the new opener with parents of the current opener */
			for (var i=0; i<currentMenuOpener.parentMenuOpenerList.length; i++) {
				for (var j=0; j<thisSelectedMenuOpener.parentMenuOpenerList.length; j++) {
					if (currentMenuOpener.parentMenuOpenerList[i] == thisSelectedMenuOpener.parentMenuOpenerList[j] ) {
						breakLoop = true;
						break;
					}
					// dumptxt("get current menu's parent " + i + ": " + currentMenuOpener.parentMenuOpenerList[i].id);
					topHidingMenu = currentMenuOpener.parentMenuOpenerList[i];
				}
				if (breakLoop) {
					break;
				}
			}
		}
		
		/* if there are no menus to close, but there are also no menu
		conflicts, then close the current menu */
		if (topHidingMenu==null
			&& breakLoop==true) {
			// dumptxt("close current menu" + currentMenuOpener.id + ":" + thisSelectedMenuOpener.id);
			topHidingMenu = currentMenuOpener;
		}

	/* if the selected menu is top-level (i.e. it has no parent menu
	openers) then just use the top-level menu from the current menu */
	} else if (currentMenuOpener.parentMenuOpenerList.length>0) {
		// dumptxt('top level from current - thinks is top-level');
		topHidingMenu = currentMenuOpener.parentMenuOpenerList[(currentMenuOpener.parentMenuOpenerList.length-1)];

	/* if dealing with two top-level menu openers (i.e. neither the
	current nor selected menus have parent menu openers) then close the
	current menu if it is not identical to the select menu */
	} else if (currentMenuOpener != thisSelectedMenuOpener) {
		// dumptxt('top hiding the current MO');
		topHidingMenu = currentMenuOpener;
	// } else {
	//	dumptxt('NO top hiding found!');
	}

	return topHidingMenu;
}

// activate a menu specified by its menu opener
function openMenu (thisMenuOpener) {

	// dumptxt("selecting menuopener:" + thisMenuOpener.id);
	
	/* hide the current menu, it's sub-menus, and any parent menus,
	excepting where this would overlap with the newly selected menu */
	if (currentMenuOpener!=null) {
		var hidingMenu = getTopHidingMenu (thisMenuOpener);
		if (hidingMenu!=null) {
			// dumptxt("planning to hide:" + hidingMenu.id);
			hideChildMenuRecurse (hidingMenu);
		}
	}
	
	/* re-assign current menu based on the current opener */
	currentMenuOpener = thisMenuOpener;
		
	/* make the selected menu visible and position it to the right of
	its parent menu */
	var visibleParent = thisMenuOpener.parentNode.parentNode;
	var menuLeft = visibleParent.offsetLeft + visibleParent.offsetWidth;
	// thisMenuOpener.style.fontWeight = 'bold';
	thisMenuOpener.sibMenuContainer.style.visibility = 'visible';
	thisMenuOpener.sibMenuContainer.style.left = menuLeft + "px";
	thisMenuOpener.sibMenuContainer.style.top = menuTop + "px";

	/*
	dumptxt("set position of:" + thisMenuOpener.sibMenuContainer.id + " based on:" + visibleParent.id
		+ " > " + visibleParent.offsetLeft + "+" + visibleParent.offsetWidth + "=" + menuLeft
		+ ";" + thisMenuOpener.sibMenuContainer.style.left + "," + thisMenuOpener.sibMenuContainer.style.top + "..." + thisMenuOpener.sibMenuContainer.style.visibility);
	*/
}

// activate a menu specified by its menu opener
function openMenuByMenuLink (thisMenuLink,hideFirst) {
	// dumptxt('menulink:' + thisMenuLink.id + ":" + thisMenuLink.href);
	
	/* optionally hide the current menu selection before selecting new
	menus */
	if (hideFirst) {
		hideAllMenus();
	}

	/* get the menu link's menu opener (if any) and use that to display
	the new items bit-by-bit; also, apply styling to the pre-selected
	menu openers and the menu link */
	if (thisMenuLink.parentMenuOpener!=null) {
		var thisMenuOpener = thisMenuLink.parentMenuOpener;
	
		if (thisMenuOpener.parentMenuOpenerList.length>0) {
			for (var i=(thisMenuOpener.parentMenuOpenerList.length-1); i>=0;i--) {
				openMenu(thisMenuOpener.parentMenuOpenerList[i]);
				thisMenuOpener.parentMenuOpenerList[i].style.fontWeight = 'bold';
			}
		}
		openMenu(thisMenuOpener);
		thisMenuOpener.style.fontWeight = 'bold';
	}
	
	// apply stylization to the menu item
	thisMenuLink.style.fontWeight = 'bold';
}

/* recurse through the given menu nodes, performing special
initialization on menu elements (openers, containers, and links) as
appropriate */
function initMenuNodes (thisElement,parentMenuOpener) {
	var thisNodeName;
	var thisNodeClassName;
	if (thisElement.childNodes
		&& thisElement.childNodes.length>0) {
		for (var i=0;i<thisElement.childNodes.length;i++) {
			var thisNode = thisElement.childNodes[i];
			if (thisNode.nodeType==1) {
				thisNodeName = thisNode.nodeName.toUpperCase();
				thisNodeClassName = thisNode.className.toUpperCase();
		
				/* initialize HREF-based menu items */
				/*  initialize menu LINKS */
				if (thisNodeName == 'A' && thisNodeClassName == 'MENULINK') {
					initMenuLink (thisNode,parentMenuOpener);
				/*  initialize menu OPENERS */
				} else if (thisNodeName == 'A' && thisNodeClassName == 'MENUOPENER') {
					initMenuOpener (thisNode,parentMenuOpener);
					// dumptxt("opener:" + thisNode.id);
				/*  initialize menu OPENERS */
				} else if (thisNodeName == 'DIV' && thisNodeClassName == 'MENUCONTAINER') {
					// dumptxt("container:" + thisNode.id);
					initMenuContainer (thisNode,parentMenuOpener);
				} else {
					initMenuNodes (thisNode,parentMenuOpener);
				}
			}
		}
	}
}

/* recursively builds an array of parent menu openers, in order from the
closest to the highest parent menu opener */
function initParentMenuOpenerList (thisMenuOpener,parentList) {
	if (thisMenuOpener.parentMenuOpener!=null) {
		parentList[parentList.length] = thisMenuOpener.parentMenuOpener;
		parentList = initParentMenuOpenerList (thisMenuOpener.parentMenuOpener,parentList);
	}

	return parentList;
}

function initMenuOpener (thisMenuOpener,parentMenuOpener) {
	/* assign the parent menu opener of this menu opener; this is used
	for searching upwards through containing menus */
	thisMenuOpener.parentMenuOpener = parentMenuOpener;

	/* retrieve a list of parent menu openers */
	thisMenuOpener.parentMenuOpenerList = initParentMenuOpenerList (thisMenuOpener,new Array());

	/* create an empty list of child menu openers */
	thisMenuOpener.childMenuOpenerList = new Array();

	/* add self to the list of child menus OPENERS for the parent menu
	OPENER; this is useful for closing child menus */
	if (parentMenuOpener!=null) {
		parentMenuOpener.childMenuOpenerList[parentMenuOpener.childMenuOpenerList.length] = thisMenuOpener;
	/* if there are no parent menu openers for this menu opener, add it
	to the array of top-level menu openers */
	} else {
		topMenuOpeners[topMenuOpeners.length] = thisMenuOpener;
	}

	/* add event handlers to clicking, pressing when a corresponding
	menu CONTAINER is available */
	thisMenuOpener.onclick = function () {
			openMenu (thisMenuOpener);
			return false;
		}
	// thisMenuOpener.onkeypress = thisMenuOpener.onclick;
}

function initMenuLink (thisMenuLink,parentMenuOpener) {
	/* assign the parent menu opener of this menu link; this will be
	used for automatically opening the menu to a given menu link */
	thisMenuLink.parentMenuOpener = parentMenuOpener;

	/*
	thisMenuLink.onclick = function () {
		alert(thisMenuLink.href);
		return false;
	}
	*/
	// thisMenuLink.onkeypress = thisMenuLink.onclick;
}

/* intialize a menu CONTAINER by notifying the corresponding menu OPENER
link of its existence */
function initMenuContainer (menuContainer,parentMenuOpener) {
	menuContainer.parentMenuOpener = parentMenuOpener;

	if (menuContainer.parentNode) {
		/* the menu OPENER link is the first A HREF w/ the "MENUOPENER"
		classname in the same node that containing the menu CONTAINER */
		var thisMenuContainerOpener = null;
	
		if (menuContainer.parentNode.childNodes
			&& menuContainer.parentNode.childNodes.length>0) {
	
			for (var i=0; i<menuContainer.parentNode.childNodes.length; i++ ) {
				if (menuContainer.parentNode.childNodes[i].nodeName.toUpperCase() == 'A'
					&& menuContainer.parentNode.childNodes[i].className.toUpperCase() == 'MENUOPENER') {
					thisMenuContainerOpener = menuContainer.parentNode.childNodes[i];
					break;
				}
			}
			
			if (thisMenuContainerOpener!=null) {
				thisMenuContainerOpener.sibMenuContainer = menuContainer;
			}
		}
	}

	/* continue menu initialization, recognizing the new menu OPENER */
	initMenuNodes (menuContainer,thisMenuContainerOpener);
}

function menuStart (thisMenuRootID,thisMenuLinkID) {
	menuRoot = document.getElementById(thisMenuRootID);
	menuTop = menuRoot.offsetTop;
	initMenuNodes(menuRoot,null,null);
	if (thisMenuLinkID!=null) {
		defaultSelected = document.getElementById(thisMenuLinkID);
		openMenuByMenuLink (defaultSelected);
	}
}


