/* 
Dynamic Menus for Texas Online rework (to replace current version at texasonline.com)
Author: James Craig (james.craig at-symbol bearingpoint com)
*/

/* a few sniffs to circumvent known browser bugs */
var sUserAgent = navigator.userAgent.toLowerCase();
var isIE=document.all?true:false;
var isNS4=document.layers?true:false;
var isIE5=(isIE && sUserAgent.indexOf('msie 5')!=-1)?true:false;
var isIE6=(isIE && sUserAgent.indexOf('msie 6')!=-1)?true:false;
var isOp=(sUserAgent.indexOf('opera')!=-1)?true:false;
var isMac=(sUserAgent.indexOf('mac')!=-1)?true:false;
var isMoz=(sUserAgent.indexOf('mozilla/5')!=-1&&sUserAgent.indexOf('opera')==-1&&sUserAgent.indexOf('msie')==-1)?true:false;
var isNS6=(sUserAgent.indexOf('netscape6')!=-1&&sUserAgent.indexOf('opera')==-1&&sUserAgent.indexOf('msie')==-1)?true:false;

/* sets time until menus disappear in milliseconds */
var iMenuTimeout=500;

/* A couple style sheet values that I could not keep out of the script */
var iDefaultMenuTop = -1; /* default menu top position (will be reset to this point if needed) */
var iPixFromBottomEdge = ((isMoz||isNS6)?18:4); /* ensure menus are this many pixels from the bottom edge of viewport (18 includes horizontal scrollbar in moz, 4 for everything else) */

var aMenus=new Array;
var oMenuTimeout;
var oQuickLinksTimeout;
var iMainMenusLength=0;

/* the following boolean controls the z-index property if needed */
/* if is only necessary if you have multiple mainMenus in one file that are overlapping */
/* set bSetZIndeces to true (either here or in the HTML) and the main menus will have a z-index set in descending order so that preceding ones can overlap */
/* the integer iStartZIndexAt controls z-index of the first main menu */
var bSetZIndeces=true;
var iStartZIndexAt=1000;
var aMainMenus=new Array;

/* load up the submenus */
function loadMenus(){
	if(!document.getElementById || isNS6)return;
	var oMainMenu = document.getElementById('mainMenu');
	/* Remove empty text nodes in mainMenu list. (Mozilla knows these but IE does not.) */
	for(var i=0;i<oMainMenu.childNodes.length;i++){
		if(oMainMenu.childNodes[i].nodeType != 1){ /* if nodeType is not ELEMENT_NODE constant 1 */
			oMainMenu.removeChild(oMainMenu.childNodes[i]);
		}
	}
	/* load submenus into the DOM under existing top-level list items */
	if(oMainMenu.childNodes.length == aSubMenus.length){
		for(var i=0;i<aSubMenus.length;i++){
			loadSubMenusIntoDOM(oMainMenu.childNodes.item(i),aSubMenus[i].aSubMenus);
		}
	}
	var aLists=document.getElementsByTagName('ul');
	for(var i=0;i<aLists.length;i++){
		if(aLists[i].className=='navMenu')aMenus[aMenus.length]=aLists[i];
	}
	var aAnchors=document.getElementsByTagName('a');
	var aItems = new Array;
	for(var i=0;i<aAnchors.length;i++){
		if(aAnchors[i].className=='navItem')aItems[aItems.length] = aAnchors[i];
	}
	var sMenuId=null;
	var oParentMenu=null;
	var aAllElements=document.body.getElementsByTagName("*");
	if(isIE)aAllElements=document.body.all;
	/* loop through navItem and navMenus and dynamically assign their IDs */
	/* each relies on it's parent's ID being set before it */
	for(var i=0;i<aAllElements.length;i++){
		if(aAllElements[i].className.indexOf('mainMenu')!=-1){
			/* load up main menus collection */
			if(bSetZIndeces)aMainMenus[aMainMenus.length]=aAllElements[i];
		}
		if(aAllElements[i].className=='navItem'){
			oParentMenu = aAllElements[i].parentNode.parentNode;
			if(!oParentMenu.childMenus) oParentMenu.childMenus = new Array;
			oParentMenu.childMenus[oParentMenu.childMenus.length]=aAllElements[i];
			if(aAllElements[i].id==''){
				if(oParentMenu.className=='mainMenu'){
					aAllElements[i].id='navItem_'+iMainMenusLength;
					iMainMenusLength++;
				}else{
					aAllElements[i].id=oParentMenu.id.replace('Menu','Item')+'.'+oParentMenu.childMenus.length;
				}
			}
		} else if(aAllElements[i].className=='navMenu'){
			oParentItem = aAllElements[i].parentNode.firstChild;
			/* make sure this is not a whitespace text node */
			while(oParentItem.nodeType!=1){
				oParentItem = oParentItem.nextSibling;
			}
			aAllElements[i].id = oParentItem.id.replace('Item','Menu');
		}
	}
	/* dynamically set z-indeces of main menus so they won't underlap */
	for(var i=aMainMenus.length-1;i>=0;i--){
		aMainMenus[i].style.zIndex=iStartZIndexAt-i;
	}
	/* set menu item properties */
	for(var i=0;i<aItems.length;i++){
		sMenuId=aItems[i].id;
		sMenuId='navMenu_'+sMenuId.substring(8,sMenuId.lastIndexOf('.'));
		/* assign event handlers */
		/* eval() used here to avoid syntax errors for function literals in Netscape 3 */
		eval('aItems[i].onmouseover=function(){modClass(true,this,"activeItem");window.clearTimeout(oMenuTimeout);showMenu("'+sMenuId+'");};');
		eval('aItems[i].onmouseout=function(){modClass(false,this,"activeItem");window.clearTimeout(oMenuTimeout);oMenuTimeout=window.setTimeout("hideMenu(\'all\')",iMenuTimeout);}');
	}
	var sCatId=0;
	var oItem;
	for(var i=0;i<aMenus.length;i++){
		/* assign event handlers */
		/* eval() used here to avoid syntax errors for function literals in Netscape 3 */
		eval('aMenus[i].onmouseover=function(){window.clearTimeout(oMenuTimeout);}');
		eval('aMenus[i].onmouseout=function(){window.clearTimeout(oMenuTimeout);oMenuTimeout=window.setTimeout("hideMenu(\'all\')",iMenuTimeout);}');
		sCatId=aMenus[i].id;
		sCatId=sCatId.substring(8,sCatId.length);
		oItem=document.getElementById('navItem_'+sCatId);
		if(oItem){
			if(!isOp && !(isMac && isIE) && oItem.parentNode)modClass(true,oItem.parentNode,"hasSubMenu");
			else modClass(true,oItem,"hasSubMenu");
			/* assign event handlers */
			eval('oItem.onmouseover=function(){window.clearTimeout(oMenuTimeout);showMenu("navMenu_'+sCatId+'");}');
			eval('oItem.onmouseout=function(){window.clearTimeout(oMenuTimeout);oMenuTimeout=window.clearTimeout(oMenuTimeout);oMenuTimeout=window.setTimeout(\'hideMenu("navMenu_'+sCatId+'")\',iMenuTimeout);}');
		}
	}
}

/* this will append the loadMenus function to any previously assigned window.onload event */
/* if you reassign this onload event, you'll need to include this or execute it after all the menus are loaded */
function newOnload(){
	if(typeof previousOnload=='function')previousOnload();
	loadMenus();
	loadQuickLinks();
}
var previousOnload;
if(window.onload!=null)previousOnload=window.onload;
window.onload=newOnload;

/* use aSubMenus array to load submenus in the DOM tree */
function loadSubMenusIntoDOM(oDomNode, aSubMenus){
	var oElement = document.createElement('ul');
	oElement.className = 'navMenu';
	var oTextNode;
	if (aSubMenus.length > 0) oDomNode.appendChild(oElement); /* add list */
	for(var i=0;i<aSubMenus.length;i++){
		 /* add list item */
		oElement = document.createElement('li');
		oDomNode.lastChild.appendChild(oElement);
		 /* add anchor */
		oElement = document.createElement('a');
		oElement.className = 'navItem';
		oElement.setAttribute('href',aSubMenus[i].sPath);
		oDomNode.lastChild.lastChild.appendChild(oElement);
		 /* add text to anchor */
		oTextNode = document.createTextNode(aSubMenus[i].sText);
		oDomNode.lastChild.lastChild.lastChild.appendChild(oTextNode);
		  /* if there is a sub menu */
		if(aSubMenus[i].aSubMenus.length != 0){
			/* recursively call this function */
			loadSubMenusIntoDOM(oDomNode.lastChild.lastChild,aSubMenus[i].aSubMenus);
		}
	}
}

/* show menu and hide all others except ancestors of the current menu */
function showMenu(sWhich){
	var oWhich=document.getElementById(sWhich);
	if(oDiv){
		modClass(false,oDiv,'showMenu');
	}
	if(!oWhich){
		hideMenu('all');
		return;
	}
	var aRootMenus=new Array;
	aRootMenus[0]=sWhich
	var sCurrentRoot=sWhich;
	var bHasParentMenu=false;
	if(sCurrentRoot.indexOf('.')!=-1){
		bHasParentMenu=true;
	}
	/* make array of this menu and ancestors so we know which to leave exposed */
	/* ex. from ID string "navMenu_12.3.7.4", extracts menu levels ["12.3.7.4", "12.3.7", "12.3", "12"] */
	while(bHasParentMenu){
		if(sCurrentRoot.indexOf('.')==-1)bHasParentMenu=false;
		aRootMenus[aRootMenus.length]=sCurrentRoot;
		sCurrentRoot=sCurrentRoot.substring(0,sCurrentRoot.lastIndexOf('.'));
	}
	for(var i=0;i<aMenus.length;i++){
		var bIsRoot=false;
		for(var j=0;j<aRootMenus.length;j++){
			var oThisItem=document.getElementById(aMenus[i].id.replace('navMenu_','navItem_'));
			if(aMenus[i].id==aRootMenus[j])bIsRoot=true;
		}
		if(bIsRoot && oThisItem)modClass(true,oThisItem,'hasSubMenuActive');
		else modClass(false,oThisItem,'hasSubMenuActive');
		if(!bIsRoot && aMenus[i].id!=sWhich)modClass(false,aMenus[i],'showMenu');
	}
	modClass(true,oWhich,'showMenu');
	keepInViewport(oWhich);
	var oItem=document.getElementById(sWhich.replace('navMenu_','navItem_'));
	if(oItem)modClass(true,oItem,'hasSubMenuActive');
}

/* move menu into viewport if it is outside the window's viewable area. */
/* or reposition back to default position. */
function keepInViewport(oWhich){
	var iBottom = getBottomEdge(oWhich);
	//var iViewportHeight = (isIE ? document.body.clientHeight : window.innerHeight);
	var iViewportHeight = (document.all ? document.body.clientHeight : window.innerHeight);
	if (document.all && document.documentElement && !isMac && isIE6) iViewportHeight = document.documentElement.clientHeight; 
	//alert(document.body.clientHeight);
	/* if top already reassigned through the script (not just in the CSS) */
	if(oWhich.style.top){
		if(parseInt(oWhich.style.top)!=iDefaultMenuTop && iBottom!=iViewportHeight-iPixFromBottomEdge){
			oWhich.style.top = iDefaultMenuTop+'px';
			/* get new bottom edge */
			iBottom = getBottomEdge(oWhich);
		}
	}
	/* if bottom edge of is lower than the bottom edge of viewport */
	if (iBottom>iViewportHeight-iPixFromBottomEdge){
		/* raise the menu just enough to fit on screen. */
		oWhich.style.top = (oWhich.offsetTop+(iViewportHeight-iBottom)-iPixFromBottomEdge)+'px';
	}
}

/* find and return distance from top edge of viewport to bottom edge of menu */
function getBottomEdge(oWhich){
	if (!isMac && oWhich.getBoundingClientRect){
		iBottom = oWhich.getBoundingClientRect().bottom;
	} else if (isIE && isMac){
		var oElement = oWhich;
		iBottom = oElement.offsetTop;
		while(oElement.parentElement){
			oElement = oElement.parentElement;
			iBottom += oElement.offsetTop;
		}
		iBottom += oWhich.offsetHeight;
		iBottom -= document.body.scrollTop;
	} else {
		var oElement = oWhich;
		iBottom = oElement.offsetTop;
		while(oElement.offsetParent){
			oElement = oElement.offsetParent;
			iBottom += oElement.offsetTop;
		}
		iBottom += oWhich.offsetHeight;
		iBottom -= window.scrollY;
	}
	return iBottom;	
}

function hideMenu(sWhich){
	if(sWhich=='all'){
		/* loop backwards b/c WinIE6 has a bug with hiding display of an element when it's parentElement is already hidden */
		for(var i=aMenus.length-1;i>=0;i--){
			var oThisItem=document.getElementById(aMenus[i].id.replace('navMenu_','navItem_'));
			if(oThisItem)modClass(false,oThisItem,'hasSubMenuActive');
			modClass(false,aMenus[i],'showMenu');
		}
	}else{
		var oWhich=document.getElementById(sWhich);
		if(oWhich)modClass(false,oWhich,'showMenu');
		var oThisItem=document.getElementById(sWhich.replace('navMenu_','navItem_'));
		if(oThisItem)modClass(false,oThisItem,'hasSubMenuActive');
	}
}

/* add or remove element className */
function modClass(bAdd,oElement,sClassName){
	if(bAdd){/* add class */
		if(oElement.className.indexOf(sClassName)==-1)oElement.className+=' '+sClassName;
	}else{/* remove class */
		if(oElement.className.indexOf(sClassName)!=-1){
			if(oElement.className.indexOf(' '+sClassName)!=-1)oElement.className=oElement.className.replace(' '+sClassName,'');
			else oElement.className=oElement.className.replace(sClassName,'');
		}
	}
	return oElement.className; /* return new className */
}

/* These need to be gloabl variables or the Timeout causes an error. */
var oLink;
var oDiv;
function loadQuickLinks(){
	if(!document.getElementById)return;
	oLink = document.getElementById('quicklink');
	oDiv = document.getElementById('quicklinks');
	if(!oLink || !oDiv) return;
	setQuickLinksEvents(oLink);
	setQuickLinksEvents(oDiv);
}

function setQuickLinksEvents(oItem){
	if(!oItem) return;
	eval('oItem.onmouseover=function(){window.clearTimeout(oQuickLinksTimeout);oQuickLinksTimeout=window.setTimeout("showQuickLinks()",iMenuTimeout/2);};');
	eval('oItem.onmouseout=function(){window.clearTimeout(oQuickLinksTimeout);oQuickLinksTimeout=window.setTimeout("hideQuickLinks()",iMenuTimeout);};');
}
function showQuickLinks(){
	hideMenu('all');
	modClass(true,oDiv,'showMenu');
}
function hideQuickLinks(){
	modClass(false,oDiv,'showMenu');
}


/* Output any object's prop:values in new console window (for debugging purposes only) */
function getObjProps(oObj){
	var oConsole = window.open('','console','width=500,height=500,scrollbars,resizable');
	oConsole.document.open("text/plain");
	oConsole.focus();
	var aProps = new Array();
	for(prop in oObj) aProps[aProps.length] = prop + ': ' + oObj[prop];
	aProps.sort();
	for(var i=0;i<aProps.length;i++){
		oConsole.document.writeln(aProps[i]);
		// moz doesn't recognize new doc as plaintext so add html line breaks
		if(isMoz || (isMac && isIE)) oConsole.document.write('<br>');
	}
	oConsole.document.close();
}
