/*
Multi Tiered Menu System

ids should follow this format:

menu			- main menu object
menu:0			- first sub menu
menu:0:0		- first sub menu off first child of previous sub menu

*/

var nMenu = {
	
	/*
	setup mouseovers and mouseouts
	*/
	init: function(params)
	{
		this.element_id = "menu";										// identifies the top most menu
		this.childTag = "LI";											// tells us which parent is a child (usually a, td, tr, li);
		this.timers = new Array();										// holds menu closing timers 
		this.timeout = 200;												// how long to display a menu before closing after mouseout
		this.level_orientation = "vertical,horizontal";					// sets how to display a menu
		this.interactions = new Array();								// holds information on whats happening with the menus
		this.interactions_count = 1;									// just gives a visual representation of queue place
		this.interactions_display_id = "";								// the id of the element in the page to place the menu debug info
		
		// overwrite any parameters that have been set
		for (var name in params) {
			eval("this." + name + " = '" + params[name] + "';");
		}

		this.level_orientation = this.level_orientation.split(/,/);

		nMenu.attach_actions(this.element_id);
	},

	/*
	attach actions to an elements children
	*/
	attach_actions: function(id)
	{
		var tobj = document.getElementById(id);
		tobj.menus = new Array();
		if (tobj) {
			var children = tobj.getElementsByTagName(nMenu.childTag);
			for (var e = 0; e < children.length; e ++) {
				// attach actions and object references
				children[e].parentMenu = tobj;
				children[e].firstMenu = (e == 0) ? true : false;
				children[e].lastMenu = (e == (children.length - 1)) ? true : false;
				children[e].menuID = id + ":" + e;
				children[e].parentIndex = e;
				children[e].onmouseover = nMenu.show;
				children[e].onmouseout = nMenu.start_hide;	
				// repeat if there is children for this menu
				if (document.getElementById(id + ":" + e)) {
					tobj.menus.push(children[e]);
					nMenu.attach_actions(id + ":" + e);
				}
			}
		}
	},
	
	/*
	show a submenu
	*/
	show: function(e)
	{
		var obj = nMenu.get_obj(e);
	
		// hide any open menus on this level
		nMenu.hide_this_level(obj);
		var menu_parts = obj.menuID.split(/:/);

		// add to interactions
		nMenu.add_interaction("Menu Show: " + obj.menuID + ", First: " + obj.firstMenu + ", Last: " + obj.lastMenu);
		
		// clear parent timeouts by making a copy of menu parents and stepping upwards
		var mp2 = menu_parts;
		for (var v = mp2.length; v > 1; v --) {
			var cid = mp2.slice(0, v).join(":");
			nMenu.add_interaction("Checking Menu Cancellation State: " + cid);
			if (nMenu.timers[cid]) {
				// add to interactions
				nMenu.add_interaction("Cancelling Menu Close: " + cid);
				clearTimeout(nMenu.timers[cid]);
				nMenu.timers[cid] = null;
			}
		}
		
		// test for existence of child menu and only continue if needed
		var subnav = document.getElementById(obj.menuID);
		if (subnav) {
		
			var index = obj.parentIndex;	
			nMenu.add_interaction("Index: " + index);		
			
			var left = parseInt(nMenu.get_position(obj.firstChild, "Left"));
			var top = parseInt(nMenu.get_position(obj.parentNode, "Top"));
			var width = 0;
			var height = 0;
			
			var pchilds = obj.parentNode.getElementsByTagName(nMenu.childTag);

			// get nearest orientation definition, step up until we get one
			var current_level = menu_parts.length - 2;
			var real_level = current_level;
			while (typeof(nMenu.level_orientation[current_level]) == "undefined" && current_level > 0) {
				current_level --;
			}

			var orientation = nMenu.level_orientation[current_level];
			if (! orientation) {
				orientation = "horizontal";
			}
			
			switch (orientation) {

				case "vertical" : 
					if (real_level == 0) {
						top += parseInt(obj.parentNode.offsetHeight);
						/*for (var x = 0; x < index - 1; x ++) {
							if (pchilds[x].style.display == "block") {
								width += pchilds[x].offsetWidth;
							}
							else {
								width += pchilds[x].firstChild.offsetWidth;
							}
						}*/
					}
				break;

				case "horizontal" :
					width += obj.offsetWidth + 30;
					for (var x = 0; x < index; x ++) {
						if (pchilds[x].style.display == "block") {
							height += pchilds[x].offsetHeight;
						}
						else {
							height += pchilds[x].firstChild.offsetHeight;
						}
					}				
				break;
			}
			
			top += height;
			left += width;
			
			subnav.style.display = "block";	
			subnav.style.left = left + "px";		
			subnav.style.top = top + "px";	
		}
	},
	
	/*
	start hide timer (gives you time to scroll over a child menu)
	*/
	start_hide: function(e, use_obj)
	{
		var obj = nMenu.get_obj(e);;
		var mp = obj.menuID.split(/:/);;
		for (var v = mp.length; v > 1; v --) {
			var cid = mp.slice(0, v).join(":");
			nMenu.add_interaction("Hide timer initiated: " + cid);
			nMenu.timers[cid] = setTimeout("nMenu.hide('" + cid + "')", nMenu.timeout);			
		}
	},

	/*
	hides menus on the same level (steps through children hiding each)
	*/
	hide_this_level: function(obj)
	{
		var kids = obj.parentMenu.menus;
		for (var n = 0; n < kids.length; n ++) {
			if (kids[n] != obj) {
				nMenu.add_interaction("Hiding Level: " + kids[n].menuID);
				var cmenu = document.getElementById(kids[n].menuID);
				cmenu.style.display = "none";
				nMenu.hide_children(cmenu);
			}
		}
	},

	/*
	hides all but the passed menu instantly
	*/
	hide_children: function(obj)
	{
		if (obj) {
			var kids = obj.menus;
			if (kids) {
				for (var n = 0; n < kids.length; n ++) {
					nMenu.add_interaction("Calling Menu Close: " + kids[n].menuID);
					var cmenu = document.getElementById(kids[n].menuID);
					cmenu.style.display = "none";
					nMenu.hide_children(cmenu);
				}
			}
		}
	},
	
	/*
	hides a determined menu
	*/
	hide: function(id)
	{
		if (nMenu.timers[id]) {
			nMenu.add_interaction("Closing Menu: " + id);
			var cmenu = document.getElementById(id);
			if (cmenu) {
				cmenu.style.display = "none";
			}
		}
	},

	/*
	return which object we are using on the page
	*/
	get_obj: function(e)
	{
		if (! e) {
			e = window.event;
		}
		var obj = (e.srcElement) ? e.srcElement : e.currentTarget;
		while (obj.tagName != nMenu.childTag) {
			obj = obj.parentNode;
		}
		return obj;
	},
	
	/*
	adds an action to an array for debugging and then displays that array
	*/
	add_interaction: function(interaction)
	{
		if (nMenu.interactions_display_id != "") {
			nMenu.interactions.push(nMenu.interactions_count + ": " + interaction);
			nMenu.interactions_count ++;
			if (nMenu.interactions.length > 25) {
				nMenu.interactions.shift();
			}
			nMenu.show_interactions();
		}
	},
	
	/*
	shows the interacitons 
	*/
	show_interactions: function()
	{
		var d = document.getElementById("info");
		d.innerHTML = nMenu.interactions.join("<br />");
	},

	// returns the elements position on the document
	get_position: function(obj, type)
	{
		var retval = 0;

		if (type == "Left" && obj.x) {
			return obj.x;
		}
		else if (obj.y) {
			return obj.y;
		}
		else {
			while (obj.offsetParent) {
				if (obj && obj.style && obj.style.position) obj.style.position = "relative";
				retval += eval("obj.offset" + type);
				obj = obj.offsetParent;
			}
			return retval;
		}
	}
}

var func = function() {
	var e = nMenu.init({
		element_id: "menu", 
		childTag: "LI",
		level_orientation: "vertical,horizontal"
	});
};

add_to_onload("func()");