/*
 * menuDropdown.js - implements an dropdown menu based on a HTML list
 * Author: Dave Lindquist (http://www.gazingus.org)
 */


// Returns a copy of a string with leading and trailing whitespace removed.
String.prototype.trim = function() {
    return this.replace(/^\s+/, "").replace(/\s+$/, "");
}

if (typeof document.createElementNS == "function") {
	var template = document.createElementNS("http://www.w3.org/1999/xhtml", "a");
} else {
	var template = document.createElement("a");
}
template.appendChild(document.createTextNode(" "));

// Walks the DOM tree starting at a given root element. Returns an
// array of nodes of the specified type and conforming to the criteria
// of the given filter function. The filter should return a boolean.
function getNodesByType(root, type, filter) {
    var node = root;
    var nodes = [];
    var next;

    while (node != null) {
        if (node.hasChildNodes())
            node = node.firstChild;
        else if (node != root && null != (next = node.nextSibling))
            node = next;
        else {
            next = null;
            for ( ; node != root; node = node.parentNode) {
                next = node.nextSibling;
                if (next != null) break;
            }
            node = next;
        }
        if (node != null && node.nodeType == type && filter(node))
            nodes.push(node);
    }
    return nodes;
}

// Simulates the innerText property of IE and other browsers.
// Mozilla/Firefox need this.
function getInnerText(node) {
    if (node == null || node.nodeType != 1)
        return;
    var text = "";
    var textnodes = getNodesByType(node, 3, function() { return true; });
    for (var i = 0; i < textnodes.length; i++)
        text += textnodes[i].data;
    return text;
}

var currentMenu = null;

function initDropdown(menuId, actuatorId, main) {
	var menu = document.getElementById(menuId);
	var actuator = document.getElementById(actuatorId);
	if (menu == null || actuator == null) return;
 
 	actuator.onmouseover = function() {
		var x = this.offsetLeft;
		var y = this.offsetParent.offsetTop + this.offsetTop;
		if(document.all) {
			x += ((document.body.clientWidth/2) - (this.offsetParent.offsetLeft/2)) + 105;
			y += this.offsetParent.offsetHeight;
		} else {
			x += this.offsetParent.offsetLeft;
			y += this.offsetHeight;
		}
		menu.style.left = x + "px";
		menu.style.top = y + "px";
		menu.style.visibility = "visible";
		currentMenu = menu;
		return false;
	}
			
	actuator.onmouseout = function() {
		currentMenu.style.visibility = "hidden";
		currentMenu = null;
	}
}

switchNode = function(id) {
	var node = document.getElementById(id);
    if (node && /^switch /.test(node.className)) node.onclick();
}

var currentList = null;

function initExpand(uid, text, listitem) {
	var sublist = listitem.getElementsByTagName("ul")[0] || listitem.getElementsByTagName("ol")[0];
	var symbol;
	switch (sublist.style.display) {
		case "none" : symbol = "+"; break;
		case "block": symbol = "-"; break;
		default:
			var display = "none";
                if (sublist.currentStyle) {
                    display = sublist.currentStyle.display;
                } else if (document.defaultView && document.defaultView.getComputedStyle && document.defaultView.getComputedStyle(sublist, "")) {
                    var view = document.defaultView;
                    var computed = view.getComputedStyle(sublist, "");
                    display = computed.getPropertyValue("display");
                }
                symbol = (display == "none") ? "+" : "-";
                // Explicitly set the display style to make sure it is
                // set for the next read. If it is somehow the empty
                // string, use the default value from the (X)HTML DTD.
                sublist.style.display = display || "block";
                break;
		}
	
	var actuator = template.cloneNode(true);
    actuator.id = uid;
    actuator.href = "javascript:switchNode('" + uid + "')";
	if(symbol == "+") {
		actuator.className = "switch off";
		actuator.title = "Expand List: " + text;
		listitem.firstChild.className = "exmi closed";
	} else {
    	actuator.className = "switch on";
		actuator.title = "Collapse List: " + text;
		listitem.firstChild.className = "exmi open";
	}
	
    actuator.firstChild.data = symbol;
    listitem.insertBefore(actuator, listitem.firstChild);

	actuator.onclick = function() {
        var sublist = this.parentNode.getElementsByTagName("ul")[0] ||
                      this.parentNode.getElementsByTagName("ol")[0];
		if(sublist == null) sublist = this.parentNode.firstChild.getElementsByTagName("ul")[0];
		
		if (sublist.style.display == "block") {
            sublist.style.display = "none";
            this.firstChild.data = "+";
            this.className = "switch off";
            this.title = this.title.replace("Collapse", "Expand");
			this.nextSibling.className = "exmi closed";
			currentList = null;
        } else {
			if(currentList) {
				var currentAct = currentList.parentNode.firstChild;
				currentAct.title = currentAct.title.replace("Collapse", "Expand");
				currentAct.className = "switch off";
				currentAct.firstChild.data = "+";
				currentAct.nextSibling.className = "exmi closed";
				currentList.style.display = "none";
			}
            sublist.style.display = "block";
            this.firstChild.data = "-";
            this.className = "switch on";
            this.title = this.title.replace("Expand", "Collapse");
			this.nextSibling.className = "exmi open";
			currentList = sublist;
        }
        return false;
    }
}
	
function initMenus() {
	
	var list, i = 0, j = 0;
    var ptn1 = new RegExp("(^| )" + "dropdown" + "( |$)");
    var ptn2 = new RegExp("(^| )" + "expandable" + "( |$)");
 
 	while ((list = document.getElementsByTagName("ul")[i++]) || (list = document.getElementsByTagName("ol")[j++]))
    {
        // Only lists with the given class name are processed.
        if (ptn1.test(list.className)) {
			var type = 0;
		} else if(ptn2.test(list.className)) {
			var type = 1;
		} else {
			continue;
		}

        var listitem, k = 0;
        while ((listitem = list.getElementsByTagName("li")[k++])) {
            var sublist = listitem.getElementsByTagName("ul")[0] || listitem.getElementsByTagName("ol")[0];

			if(sublist == null) continue;

			var child = listitem.firstChild;
            var text = "";
            while (child) {
                if (child.nodeType == 3 && "" != child.data.trim()) {
                    text = child.data;
                    break;
                } else if (child.nodeType == 1 &&
                           !/^[ou]l$/i.test(child.tagName))
                {
                    text = child.innerText || getInnerText(child);
                    break;
                }
                child = child.nextSibling;
            }
			text = text.trim();            
			var uid = "switch" + i + "-" + j + "-" + k;
			switch(type) {
				case 0 :
					listitem.id = uid;
					var mid = "menu" + i + "-" + j + "-" + k;
					sublist.id = mid;
					initDropdown(mid, uid);
					break;
				case 1 :
					initExpand(uid, text, listitem);
					break;
				default:
					break;
			}
		}
	}
}




// Props to Simon Willison:
// http://simon.incutio.com/archive/2004/05/26/addLoadEvent
var oldhandler = window.onload;
window.onload = (typeof oldhandler == "function") ? function() { oldhandler(); initMenus(); } : initMenus;


