// Dynamic menu code
// 
// Copyright James G. Ross, 2004
// 

var menus = new Object();

function initMenu(name, root) {
	var menu = new Object();
	menus[name] = menu;
	
	menu.name = name;
	menu.node = root;
	menu.root = root;
	menu.level = 0;
	menu.items = new Array();
	
	menu.root.setAttribute("onmouseout", "");
	
	for (var i = 0; i < menu.root.childNodes.length; i++) {
		var item = menu.root.childNodes[i];
		
		if ((item.nodeType != 1) || (item.className.match(/menu-sep/)))
			continue;
		
		item.setAttribute("menu_id", menu.name);
		item.setAttribute("menu_event_target", "true");
		
		var level = item.className.match(/menu-level-(\d+)/);
		if (level) {
			item.setAttribute("menu_level", level[1]);
			item.className = item.className.replace(/menu-level-\d+/, "");
		}
		
		var link = findLink(item);
		if (link) {
			// Move tooltips from link to containing list item.
			if (link.getAttribute("title")) {
				item.setAttribute("title", link.getAttribute("title"));
				link.removeAttribute("title");
			}
		}
		
		if ("addEventListener" in item) {
			item.addEventListener("mouseover", menu_onenter, false);
			item.addEventListener("mouseout",  menu_onleave, false);
			item.addEventListener("click",     menu_onclick, false);
		} else if ("attachEvent" in item) {
			item.attachEvent("onmouseover", menu_onenter);
			item.attachEvent("onmouseout",  menu_onleave);
			item.attachEvent("onclick",     menu_onclick);
		} else {
			// alert("There is no known way to attach event hooks.");
		}
	}
	
	for (i = 0; i < menu.root.childNodes.length; i++) {
		item = menu.root.childNodes[i];
		
		if (item.nodeType != 1)
			continue;
		
		level = 1 * item.getAttribute("menu_level");
		if (level > 0) {
			var link = findLink(item);
			if (link) {
				if ((link.href == document.location.href) || (link.href+"/" == document.location.href)) {
					item.className = item.className + " menu-current";
				}
				if (link.href == document.location.href.substr(0, link.href.length)) {
					menu_expand2(menu, item);
					continue;
				}
			}
			menu_collapse2(menu, item);
		}
	}
	
	return menu;
}

function findChildItems(menu, node) {
	var list = new Array();
	
	var baselevel = 1 * node.getAttribute("menu_level");
	
	for (var item = node.nextSibling; item; item = item.nextSibling) {
		if (item.nodeType != 1)
			continue;
		
		var level = 1 * item.getAttribute("menu_level");
		if (level < baselevel+1)
			break;
		if (level > baselevel+1)
			continue;
		
		list.push(item);
	}
	
	return list;
}

// Utility function that collects up all the information for an event in a
// standard way.
function getEvent(event) {
	// IE doesn't pass |event| to handlers, instead putting it on the global
	// window object, so we need to fetch it from there.
	if (!event)
		event = window.event;
	
	// event.target is the standard property.
	if (!event.target && event.srcElement) {
		// Map IE's "thing we hit" property onto the standard one.
		event.target = event.srcElement;
	}
	
	if (!event.originalTarget) {
		event.originalTarget = event.target;
	}
	
	// Our own special property - this is the node that has the event handler on it.
	event.hookTarget = event.target;
	
	// IE doesn't support |hasAttribute| so use |getAttribute| here.
	while (!event.hookTarget.getAttribute("menu_event_target")) {
		event.hookTarget = event.hookTarget.parentNode;
	}
	
	return event;
}

function findLink(base) {
	for (var i = 0; i < base.childNodes.length; i++) {
		var item = base.childNodes[i];
		
		if (item.nodeType != 1)
			continue;
		
		if (item.tagName == "A" || item.tagName == "a") {
			// Got it!
			return item;
		} else {
			var link = findLink(item);
			if (link)
				return link;
		}
	}
	return null;
}

function menu_onenter(e) {
	var event = getEvent(e);
	var menu = menus[event.hookTarget.getAttribute("menu_id")];
	
	if (menu.currentItem == event.hookTarget)
		return;
	
	// New item selected.
	if (menu.currentItem) {
		menu.currentItem.className = menu.currentItem.className.replace(/menu-selected/g, "");
	}
	menu.currentItem = event.hookTarget;
	menu.currentItem.className = menu.currentItem.className + " menu-selected";
	var index = -1;
	for (var i = 0; i < menu.root.childNodes.length; i++) {
		if (menu.currentItem == menu.root.childNodes[i]) {
			index = i;
			break;
		}
	}
}

function menu_onleave(e) {
	var event = getEvent(e);
	var menu = menus[event.hookTarget.getAttribute("menu_id")];
	
	if (menu.currentItem) {
		menu.currentItem.className = menu.currentItem.className.replace(/menu-selected/g, "");
	}
	menu.currentItem = null;
}

function menu_onclick(e) {
	var event = getEvent(e);
	var menu = menus[event.hookTarget.getAttribute("menu_id")];
	
	if (event.target.tagName == "A" || event.target.tagName == "a")
		return true;
	
	var list = findChildItems(menu, event.hookTarget);
	if (list.length > 0) {
		menu_toggle2(menu, event.hookTarget);
		if (event.preventDefault)
			event.preventDefault();
		return false;
	}
	
	// Ok, fun. We need to find the A tag...
	var link = findLink(event.hookTarget);
	if (link) {
		document.location.href = link.getAttribute("href");
	}
	return false;
}

function menu_toggle(name, index) {
	var menu = menus[name];
	var item = menu.root.childNodes[index];
	menu_toggle2(menu, item);
}

function menu_expand(name, index) {
	var menu = menus[name];
	var item = menu.root.childNodes[index];
	menu_expand2(menu, item);
}

function menu_collapse(name, index) {
	var menu = menus[name];
	var item = menu.root.childNodes[index];
	menu_collapse2(menu, item);
}

function menu_toggle2(menu, item) {
	if (item.getAttribute("menu_expanded")) {
		menu_collapse2(menu, item);
	} else {
		menu_expand2(menu, item);
	}
}

function menu_expand2(menu, item) {
	var list = findChildItems(menu, item);
	
	if (list.length == 0)
		return;
	
	for (var i = 0; i < list.length; i++) {
		list[i].className = list[i].className.replace(/menu-hidden/g, "");
	}
	var link = findLink(item);
	if (link) {
		link.previousSibling.src = "/images/menu_open.gif";
		link.previousSibling.setAttribute("title", "Close this branch");
	}
	item.setAttribute("menu_expanded", "true");
}

function menu_collapse2(menu, item) {
	var list = findChildItems(menu, item);
	
	if (list.length == 0)
		return;
	
	for (var i = 0; i < list.length; i++) {
		list[i].className = list[i].className + " menu-hidden";
		menu_collapse2(menu, list[i]);
	}
	var link = findLink(item);
	if (link) {
		link.previousSibling.src = "/images/menu_closed.gif";
		link.previousSibling.setAttribute("title", "Open this branch");
	}
	item.removeAttribute("menu_expanded");
}
