var xsltProcessor = new XSLTProcessor();
var menuArray = [];
var DELIMITER = "_";
var subMenuQueue = new Object();
var XHTML_NS = "http://www.w3.org/1999/xhtml";
var timeoutID;
var XML_DIR = "../xml_files/";

subMenuQueue.queue = [];

subMenuQueue.handleStateChange = function()
{
    switch (this.httpReq.readyState)
    {
    case 0: // uninitialized
    case 1: // loading
    case 2: // loaded
    case 3: // interactive
        break;

    case 4: // complete
        var smr = this.queue.shift();
        var menu = document.getElementById(smr.id);

        // Removed "Loading..." text
        for (var i = 0; i < menu.childNodes.length; i++)
        {
            var node = menu.childNodes[i];

            if (node.nodeType == Node.TEXT_NODE)
                menu.removeChild(node);
        }

//		if (this.httpReq.status == 0) // uncomment to test on local harddrive
        if (this.httpReq.status == 200) // comment "  "    "  "     "
        {
            var docFrag = xsltProcessor.transformToFragment(this.httpReq.responseXML, document);
            var menuItems = docFrag.childNodes;

            // set IDs, and get submenu references
            for (var i = 0; i < menuItems.length; i++)
            {
                var id = smr.id + i;
                var menuItem = menuItems[i];
                var subMenuList = menuItem.getElementsByTagNameNS(XHTML_NS, "div");

                menuItem.setAttribute("id", id);

                if (subMenuList.length > 0)
                {
                    var subMenu = subMenuList[0];

                    id += DELIMITER;
                    subMenu.uri = subMenu.getAttribute("id");
                    subMenu.setAttribute("id", id);
                    subMenu.isLaidOut = false;
                }
            }

            menu.style.color = "";

            // Attach menu items
            menu.appendChild(docFrag);

            if (getComputedStyle(menu, null).display == "")
                timeoutID = setTimeout("showMenuTree('" + menu.id.slice(0, -1) + "')", 1);
        }
        else
        {
            var textNode = document.createTextNode(this.httpReq.status + " error:  " +
                    this.httpReq.statusText)
            menu.appendChild(textNode);
        }

        setTimeout('subMenuQueue.processQueue()', 1);
    }
}

subMenuQueue.setHttpReq = function(httpReq)
{
    this.httpReq = httpReq;
};

subMenuQueue.processQueue = function()
{
    if (this.queue.length > 0 &&
        (this.httpReq.readyState == 0 || this.httpReq.readyState == 4))
    {
        this.httpReq.onreadystatechange = function()
        {
            subMenuQueue.handleStateChange();
        };

        this.httpReq.open("GET", XML_DIR + this.queue[0].uri, true);
        this.httpReq.send(null);
    }
}

subMenuQueue.push = function(smr)
{
    this.queue.push(smr);
};

function SubMenuRef(uri, id)
{
    this.uri = uri;
    this.id = id;
}

SubMenuRef.prototype =
{
    uri: null,
    id: null
};

function positionArrow(img)
{
    if (img.offsetParent)
    {
        var style = getComputedStyle(img.offsetParent, null);
        var inset = parseInt(style.borderRightWidth, 10) + parseInt(style.paddingRight, 10);
        <!--img.style.top = ((img.offsetParent.clientHeight - img.offsetHeight) / 2 - img.offsetTop) + "px";
        <!--img.style.left = (img.offsetParent.clientWidth - img.offsetLeft - inset - img.offsetWidth) + "px";
    }
}

function init()
{
    // get xmlHttpReq object
    var possibleTransports = [];
    var xmlHttpReq;

    possibleTransports.push(function(){return new ActiveXObject('Msxml2.XMLHTTP')});
    possibleTransports.push(function(){return new ActiveXObject('Microsoft.XMLHTTP')});
    possibleTransports.push(function(){return new XMLHttpRequest()});

    for (var i = 0; i < possibleTransports.length; i++)
    {
        try
        {
            xmlHttpReq = possibleTransports[i]();
            break;
        }
        catch(e)
        {}
    }

    if (typeof xmlHttpReq == "undefined")
    {
        document.getElementById("nav").innerHTML = "Cannot load menu:<br/>Unable to get XMLHttpRequest";
        return;
    }

    // Download .xsl
    xmlHttpReq.open("GET", XML_DIR + "menu.xsl", false);
    xmlHttpReq.send(null);
    xsltProcessor.importStylesheet(xmlHttpReq.responseXML);

    // download menu.xml
    xmlHttpReq.open("GET", XML_DIR + "mainMenu.xml", false);
    xmlHttpReq.send(null);

    // create menu items
    var docFrag = xsltProcessor.transformToFragment(xmlHttpReq.responseXML, document);
    var menuItems = docFrag.childNodes;
    var menuParent = document.getElementById("nav");
	var mainMenu = document.createElementNS(XHTML_NS, "div");

    mainMenu.setAttribute("id", DELIMITER);
	menuParent.appendChild(mainMenu);

    subMenuQueue.setHttpReq(xmlHttpReq);

    // set IDs, add event listeners, and get submenu references
    for (var i = 0; i < menuItems.length; i++)
    {
        var id = DELIMITER + i;
        var menuItem = menuItems[i];
        var subMenuList = menuItem.getElementsByTagNameNS(XHTML_NS, "div");

        menuItem.setAttribute("id", id);

        if (subMenuList.length > 0)
        {
            var subMenu = subMenuList[0];

            id += DELIMITER;
            subMenuQueue.push(new SubMenuRef(subMenu.getAttribute("id"), id));
            subMenu.setAttribute("id", id);
            subMenu.isLaidOut = false;
            document.body.appendChild(subMenu);
        }
    }

    // Attach menu items
    mainMenu.appendChild(docFrag);

    // start downloading submenus
    subMenuQueue.processQueue();
}

function positionSubMenu(id)
{
    var subMenu = document.getElementById(id);
    var menuItem = document.getElementById(id.slice(0, -1));
    var style = getComputedStyle(menuItem, null);
    var x = menuItem.offsetWidth - parseInt(style.borderRightWidth), y = parseInt(style.borderTopWidth);

    for (var obj = menuItem; obj != null; obj = obj.offsetParent)
    {
        x += obj.offsetLeft;
        y += obj.offsetTop;
    }

    subMenu.style.left = x + "px";
    subMenu.style.top = y + "px";
}

function layoutMenu(subMenu)
{
    positionSubMenu(subMenu.id);

    var menuItemList = subMenu.getElementsByTagNameNS(XHTML_NS, "div");

    for (var i = 0; i < menuItemList.length; i++)
    {
        var menuItem = menuItemList[i];
        var imgList = menuItem.getElementsByTagNameNS(XHTML_NS, "img");

        for (var j = 0; j < imgList.length; j++)
            if (imgList[j].className == "arrow")
        {
            positionArrow(imgList[j]);
            break;
        }

        var subMenuList = menuItem.getElementsByTagNameNS(XHTML_NS, "div");

        if (subMenuList.length > 0)
        {
            subMenuQueue.push(new SubMenuRef(subMenuList[0].uri, subMenuList[0].id));
            delete subMenuList[0].uri;
            document.body.appendChild(subMenuList[0]);
        }
    }

    subMenuQueue.processQueue();
}

function delayShowMenuTree(id)
{
	// clear time out
    clearTimeout(timeoutID);
	timeoutID = setTimeout("showMenuTree('" + id + "')", 400);
}

function showMenuTree(id)
{
	// hide the parts of the existing menu tree that aren't a part of the tree to be displayed
    var newMenuArray = id == null? new Array(""): id.split(DELIMITER);
//alert("id: " + id + "\narray len: " + newMenuArray.length);

    for (var i = 0;
         i < newMenuArray.length &&
         i < menuArray.length &&
         newMenuArray[i] == menuArray[i];
         i++);

    for (var j = i + 1; j <= menuArray.length; j++)
    {
        var subMenu = document.getElementById(menuArray.slice(0, j).join(DELIMITER) + DELIMITER);

        if (j < menuArray.length || subMenu != null)
            subMenu.style.display = "none";
    }

	// set menuArray to tree to be displayed
    if (i != newMenuArray.length)
        menuArray = newMenuArray;

	// display menu tree
    var subMenu = document.getElementById(id + DELIMITER);

    if (subMenu != null)
    {
        subMenu.style.display = "";

		// layout the submenu if it needs it
        if (subMenu.hasOwnProperty("isLaidOut"))
        {
            layoutMenu(subMenu);
            delete subMenu.isLaidOut;
        }
    }
}
