/*
 * GLOBALS
 */
// id of the topmenu currently on
var topmenuOnId = null;
// id of the submenu currently on
var submenuOnId = null;
// css class name for topmenu on state, including space
var TOPMENU_ON_CLASSNAME = " onstate";
// Holds widths for submenus.
var submenuWidths = new Array();
// The standard interval for menu actions.
var MENU_TIMEOUT_INTERVAL = 250;
// Timer for hiding a submenu.
var menuOffTimer;


/*
 * Called onmouseover of a top menu button. Turn top and submenus
 * on and off as appropriate.
 *
 * Args:
 *  - topmenu_link_id: id of the topmenu link element moused over.
 *  - submenu_id: id of the corresponding submenu
 */
function topmenuOver(topmenu_link_id, submenu_id) {
    handleMenuAlreadyOn(topmenu_link_id, submenu_id);
    turnTopmenuOn(topmenu_link_id);
    if (submenuWidths[submenu_id] == null) {
        setSubmenuWidth(submenu_id);
    }
    turnSubmenuOn(submenu_id);
}


/*
 * Checks to see if any menu items are already in the on state, and
 * handles them.
 *
 * Args:
 *  - topmenu_link_id: id of the topmenu link element that was most
 *                     recently moused over.
 *  - submenu_id: id of the corresponding submenu
 */
function handleMenuAlreadyOn(topmenu_link_id, submenu_id) {
    // If any menu items were previously on during this page view
    if (topmenuOnId != null && submenuOnId != null) {
        if (topmenuOnId == topmenu_link_id && submenuOnId == submenu_id) {
            // We're mousing back into the menu that's already on
            clearTimeout(menuOffTimer);
        } else {
            // Turn the previously on menu items off immediately
            turnOffMenuItems(topmenuOnId, submenuOnId)
        }
    }
}


/*
 * Set a topmenu item to the on state.
 *
 * Args:
 *  - topmenu_link_id: id of the topmenu link element to turn on
 */
function turnTopmenuOn(topmenu_link_id) {
    topmenuOnId = topmenu_link_id;
    // Add onstate class to topmenu item, unless it already has it
    if (document.getElementById(topmenuOnId).className.indexOf(TOPMENU_ON_CLASSNAME) == -1) {
        document.getElementById(topmenuOnId).className += TOPMENU_ON_CLASSNAME;
    }
}


/*
 * Set a submenu item to the on state.
 *
 * Args:
 *  - submenu_id: id of the submenu link element to turn on
 */
function turnSubmenuOn(submenu_id) {
    submenuOnId = submenu_id;
    document.getElementById(submenu_id).style.visibility = 'visible';
}


/*
 * Sets the width of all links in a submenu to the widest link. Also updates
 * the global submenuWidths array.
 *
 * Args:
 *  - submenu_id: id of the submenu to show.
 */
function setSubmenuWidth(submenu_id) {
    submenuLinkNodes = getSubmenuLinkNodes(submenu_id);
    submenuWidth = getSubmenuWidth(submenuLinkNodes);
    for (var i = 0; i < submenuLinkNodes.length; i++) {
        submenuLinkNodes[i].style.width = submenuWidth + 'px';
    }
    // Set global array of submenu widths.
    submenuWidths[submenu_id] = submenuWidth;
}


/*
 * Returns an Array of <a> element nodes within a submenu.
 *
 * Args:
 *  - submenu_id: id of the submenu to get element nodes from.
 */
function getSubmenuLinkNodes(submenu_id) {
    submenu = document.getElementById(submenu_id);
    submenuNodes = submenu.childNodes;
    submenuLinkNodes = new Array();
    for (var i = 0; i < submenuNodes.length; i++) {
        if (submenuNodes[i].nodeType == 1 &&
            submenuNodes[i].tagName.toLowerCase() == "a") {
            submenuLinkNodes.push(submenuNodes[i]);
        }
    }
    return submenuLinkNodes;
}


/*
 * Return the width of the widest link in the nodes arg.
 *
 * Args:
 *  - submenuLinkNodes: An Array of <a> element nodes.
 */
function getSubmenuWidth(submenuLinkNodes) {
    var widest = 0;
    for (var i = 0; i < submenuLinkNodes.length; i++) {
        if (submenuLinkNodes[i].scrollWidth > widest) {
            widest = submenuLinkNodes[i].scrollWidth
        }
    }
    return widest;
}


/*
 * Called onmouseout of a topmenu item. Kicks off the timer that turns
 * menu items off. 
 *
 * Args:
 *  - topmenu_link_id: id of the topmenu item to turn off.
 *  - submenu_id: id of the submenu to turn off.
 */
function topmenuOut(topmenu_link_id, submenu_id) {
    // A timer will be kicked off here.
    startMenuOffTimer(topmenu_link_id, submenu_id);
}


/*
 * Flip the topmenu item back to non-over state and hide the submenu.
 *
 * Args:
 *  - topmenu_link_id: id of the topmenu item to turn off.
 *  - submenu_id: id of the submenu to turn off.
 */
function turnOffMenuItems(topmenu_link_id, submenu_id) {
    turnTopmenuOff(topmenu_link_id);
    turnSubmenuOff(submenu_id);
}


/*
 * Turn topmenu item off by removing the onstate class.
 *
 * Args:
 *  - topmenu_link_id: id of the topmenu item to turn off.
 */
function turnTopmenuOff(topmenu_link_id) {
    document.getElementById(topmenu_link_id).className =
            document.getElementById(topmenu_link_id).className.replace(TOPMENU_ON_CLASSNAME, "");
}


/*
 * Turn the submenu off by setting its visibility to hidden.
 *
 * Args:
 *  - submenu_id: id of the submenu to turn off.
 */
function turnSubmenuOff(submenu_id) {
    document.getElementById(submenu_id).style.visibility = 'hidden';
}


/*
 * Starts timer that ultimately calls code to turn off menu items.
 *
 * Args:
 *  - topmenu_link_id: id of the topmenu item to turn off.
 *  - submenu_id: id of the submenu to turn off.
 */
function startMenuOffTimer(topmenu_link_id, submenu_id) {
    var code_string = "turnOffMenuItems('" + topmenu_link_id + "', '" + submenu_id + "')";
    menuOffTimer = setTimeout(code_string, MENU_TIMEOUT_INTERVAL);
}


/*
 * Called onmouseover of submenu. Cancels the timer for turning menu items off, which
 * is triggered on the mouseout event of the topmenu link.
 */
function submenuOver() {
    clearTimeout(menuOffTimer);
}


/*
 * Called onmouseout of submenu. Starts the timer for turning the submenu off.
 *
 * Args:
 *  - topmenu_link_id: id of the topmenu item to turn off.
 *  - submenu_id: id of the submenu to turn off.
 */
function submenuOut(topmenu_link_id, submenu_id) {
    startMenuOffTimer(topmenu_link_id, submenu_id);
}
