
/*
	Script which contains all functions needed to generate an interactive 
	menu that can be embedded into a web site. 

	The only thing you need to know about is the Node class constructor.
	Building a menu requires 1) that a set of nodes (i.e. menu items) is instantiated 
	appropriately and 2) that the "writeMenuAsHTML" function is called from within
	the HTML page.

	Written by Johannes Horstmann (jhorstma at cochrane.de) in June 2005
*/


// the global variable containing all the menu nodes ... it wil be filled with 
// instances of the Node class (see constructor below) later, when the buildMenu.js
// script is loaded 
var existingMenuNodes = new Array();

// for simplicity, I store all the top level items of the menu in this array
var topLevelNodes = new Array();

// choose the internal id of the root node of the menu here. 
// It'll be the prefix of all the other menu nodes, so if the rootID is "menu",
// the ID of the first sub menu will be menu_0, whose third sub item will be
// "menu_0_2" etc. 
var rootID = "menu";

var borderOnColor = "1px solid #dddddd";
// this line controls the color for the rollover on root level menu items.    
// For the Flyout, see ".tableExt" in /assets/css/memuStyles.css. 
var activeBackgroundColor = "#fafafa";

// this is a global variable too, whose default is the root node's ID.
// If the "keywords" meta tag of the current HTML page contains the index
// of the active menu node, e.g. "menu_0", then this variable will be set 
// accordingly
var activeNodeID = rootID;

// this function sets the 'activeNodeID' variable appropriately
readActiveNode();

// this variable could be used to influence the internal representation of
// sub menu items, so if you change this to "item", the menu IDs will be 
// "menu_itemX_itemY" instead of "menu_X_Y" ... but it MUST NOT contain the
// "_" character!
var itemAbbrev = "";

// the constructor of a node instance
// it is passed a list of already existing nodes, so as to
// find its parent, as well as a link (optionally) and an
// arbitrary parent ID (is transformed into an internal ID).

function Node(usersGivenID, usersParentID, name, link) {
	//alert("Node constructor with args "+usersGivenID+" "+usersParentID+" "+name+" "+link);

	this.children = new Array();
	this.name = name;
	this.link = link;	
	this.usersGivenID = usersGivenID;

	if (existingMenuNodes) {
		existingMenuNodes[existingMenuNodes.length] = this;
	} else {
		existingMenuNodes[0] = this;
	}

	if (!usersParentID && usersParentID != 0) {
		this.id = rootID;
		return;
	}

	var parent = findNode(usersParentID, false);
	if (!parent) alert("Parent is null!");
	this.parent = parent;

	if (parent.children.length) {
		this.id = parent.id+"_"+itemAbbrev+(parent.children.length);
		parent.children[parent.children.length] = this;
	} else {
		this.id = parent.id+"_"+itemAbbrev+"0";
		parent.children[0] = this;
	}

	if (this.parent.id == "menu") {
		topLevelNodes[topLevelNodes.length] = this;
	}

}

function readActiveNode() {
	//alert("Read active node!");
	// find the active node in the 'keywords' meta tag
	if (document.getElementsByTagName("meta")) {
		var metaTags = document.getElementsByTagName("meta");
		if (metaTags) {
			for (var i = 0; i < metaTags.length; i++) {
				if (metaTags[i].getAttribute("name") == "Keywords") {
					var content = metaTags[i].getAttribute("content");
					var keywords = (content.indexOf(",") > -1) ? content.split(",") : content.split(" ");

					for (var j = 0; j<keywords.length; j++) {
						//alert("found "+keywords[j]);
						if (keywords[j].indexOf("menu") > -1) {
							activeNodeID = keywords[j].replace(/^\s+/,'').replace(/\s+$/,'');
							//alert("Thats it: '"+activeNodeID+"'");
						}
					}
				}
			}
		}
	}
}

//pass the user defined ID
function writeMenuAsHTML(usersNodeID) {

	if (is_nav && !is_nav7up) {
		var menutext = inactiveMenu();
		document.write(menutext);
	} else {

		var node = findNode(usersNodeID, false);
		if (!node) {
			var error = "Menu below node with ID "+usersNodeID+" cannot be found!";
			error += "\n\r(Check this page's path to buildMenu.js)";
			alert (error);	

			return "NO MENU";
		}

		menuText = "<div class='rootMenu'>\n";
		menuText += writeNodeContent(node);
		menuText += "\n</div>";

	        document.write(menuText);
	}
}


// this is the essential method for writing a node's content into the page. it is 
// initially called by the above method, applying to the root node, which then recursively
// writes out the whole menu. 
function writeNodeContent(node) {
	var text = "\n";
	var children = node.children;

	for (var i = 0; i<children.length; i++) {
		var c = children[i];

		// check whether this is the home item (1st menu item)
		if (c.id == "menu_0" && (activeNodeID == "menu_0" || activeNodeID == rootID)) {
			continue;
		}	

		var itemsImage = "";
		// check whether we got a visible 2nd level item
		if (c.parent) {
			
			if (c.parent.id != rootID && activeNodeID.indexOf(c.parent.id) > -1) {

				var sign = "";

				if (c.id.split("_").length <= 3) {
					sign = "&gt;";
				} else {
					//alert("Got "+c.id+" with len "+c.id.split("_").length);
				}

				itemsImage = "<span class='sign'>"+sign+"&nbsp;</span>";
			} 
		}

		if (c.parent.id == rootID) {
			if (activeNodeID.indexOf(c.id) < 0) {
				itemsImage = "<img border=0 src='/assets/images/arrows_right1.gif'/>&nbsp;";
			} else {
				itemsImage = "<img border=0 src='/assets/images/arrows_down1.gif'/>&nbsp;";
			}
		} 

		var isLinkAndInactive = c.link && c.id != activeNodeID;

		// every item is within a container div
		text += "\n<div class='container' id='"+c.id+"' onmouseover='setActivation(\""+c.id+"\", 1)' onmouseout='setActivation(\""+c.id+"\", 0)'>";

		// write the menu row
		text += "\n<div class='menuRow' id='row_"+c.id+"'>";

		// draw image (might be empty string)
		text += itemsImage;

		// make the row a link?
		if (isLinkAndInactive) text += "<a href='"+c.link+"'>";

		// highlight active node according to our style sheet
		if (c.id == activeNodeID) {
			//alert("ACTIVE: "+c.id);
			text += "<span class='activeItem'>"+c.name+"</span>";
		} else {
			text += c.name;
		}

		// close the link tag, if existing
		if (isLinkAndInactive) text += "</a>";

		// close the menu row div
		text += "</div>";
						
		// write submenu, if existing
		if (c.children.length > 0) {

			var internalMenu = ((activeNodeID+"_").indexOf(c.id+"_") > -1);
			//var internalMenu = (activeNodeID == c.id);

			if (internalMenu) {
				// close container div, open separate submenu div
				text += "</div><div class='submenu'>";
				text += "<div class='tableInt' id='below"+c.id+"'>"+writeNodeContent(c)+"</div>";
			} else if (!is_nav6up) {
				text += "<div class='submenu'>";
				text += "<div class='tableExt' id='sub"+c.id+"'>"+writeNodeContent(c)+"</div>";
				text += "</div>";
			}
		} 

		// close last open div, either container div (in case of external menu) or submenu div (internal menu)
		text += "</div>";
	}	

	return "\n"+text;
}

function setActivation(id, is_active) {
	// do the item highlighting (all commented out ... my fancy 
	// features weren't required anymore)

	//var divs = document.getElementsByTagName("div");

	//var div = document.getElementById("row_"+id);
	//var div = document.getElementById(id);

	//var itemColor = (id.length > 7) ? subItemColor : superItemColor;

	//div.style.color = is_active ? itemHoverColor : itemColor;
	//div.style.background = is_active ? backgroundHoverColor : defaultBackgroundColor;

	// expand or collapse submenu



	var subdiv = document.getElementById("sub"+id);
	if (subdiv) subdiv.style.visibility = (is_active ? "visible" : "hidden");
		
	var rowelem = document.getElementById("row_"+id);
	if (rowelem && id.split("_").length < 3) {
		if (is_active) {
			rowelem.style.border = borderOnColor;
			rowelem.style.background = activeBackgroundColor;
		} else {
			rowelem.style.border = "1px solid #ffffff";
			rowelem.style.background = "#ffffff";
		}
	}
}



function collapseAll() {
	if (!document.getElementsByTagName("div")) return;
	var divs = document.getElementsByTagName("div");

	for (var i = 0; i < divs.length; i++) {
		if (divs[i].id) {
			if (divs[i].id.indexOf("menu") > -1) {
				setActivation(divs[i].id, 0);
			}
		}
	}	
}

function findNode(searchID, internal) {
	if (!existingMenuNodes) {
		alert("No menu nodes provided! Has buildMenu.js been called yet?");
		return;
	}

	for (var i = 0; i < existingMenuNodes.length; i++) {
		if (existingMenuNodes[i].usersGivenID == searchID && !internal) return existingMenuNodes[i];
		if (existingMenuNodes[i].id == searchID && internal) return existingMenuNodes[i];
	}
}

function writeBreadCrumbs() {

	var text = "";
	var activenode = findNode(activeNodeID, true);

	if (!activenode)	{
		return;
	}

	if (activenode.id == "menu") {
		return;
	}

	var breadcrumbStr = "<a href='" + activenode.link + "'>" + activenode.name + "</a>";
	var parent = activenode.parent;

	if (!parent) {
		return;
	}	

	while (parent.name) {
		breadcrumbStr = "<a href='" + parent.link + "'>" + parent.name + "</a> &gt; " + breadcrumbStr;
		parent = parent.parent;
	}

	text += breadcrumbStr;
	document.write(text);
}


// this function writes HTML code representing the menu with selectable
// parent nodes for each node, but without any rollover effects ... this 
// is a solution for somewhat crappy (i.e. either old and/or IE) browsers.

function writeDynamicMenu() {
	
	var outputHTML = "<form>";
	var parentID = "null";	

	for (var i = 0; i < existingMenuNodes.length; i++) {

		if (existingMenuNodes[i].parent) {
			parentID = existingMenuNodes[i].parent.id;
		}

		outputHTML += "<p>Node "+i+" is " + existingMenuNodes[i].name +", parent id is "+parentID+": ";	
		outputHTML += "<select>";

		for (var j = 0; j < topLevelNodes.length; j++) {
			var selectAttribute;

			if (topLevelNodes[j].id == parentID) {
				selectAttribute = "selected='selected'";
				//alert("Matched for " + existingMenuNodes[i].id+" where parent node is " + existingMenuNodes[i].parent.id+" and topLevelNode id is "+ topLevelNodes[j].id);
			} else {
				selectAttribute = "";
			}

			outputHTML += "\n<option value='"+ topLevelNodes[j].id + "' "+selectAttribute+">" + topLevelNodes[j].name;
		}
		
		outputHTML += "</select>";
	}

	outputHTML += "</form>";

	document.write(outputHTML);
}


function inactiveMenu() {
	var text = "<ul>";

	for (var i = 0; i < topLevelNodes.length; i++) {
		text += "<li><a href='"+ topLevelNodes[i].link +"'>";
		text += topLevelNodes[i].name +"</a></li>";
	}

	text += "</ul>";

	return text;
}
