/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +--------------------------------------------------------------------------+
// | JAVASRCRIPT                                                              |
// +--------------------------------------------------------------------------+
// | DROPDOWN.JS (v 0.00)                                                     |
// +--------------------------------------------------------------------------+
// | Created:       05-12-2005                                                |
// | Last Modified: DD-MM-YYYY                                                |
// +--------------------------------------------------------------------------+
//
// $Id: Dropdown.js,v 0.00 2005/MM/DD 00:00:00 dscott Exp $


//----------------------------------------------------------------------------
// Code for handling the menu bar and active pad.
//----------------------------------------------------------------------------

var timerID = null;
var timerOn = false;
var pause = 500;

var activePad = null;

/**
 * padMouseover(event, menuId)
 *
 * @access public
 */
function padOver(event, menuId)
{
    var pad;

    // Determine calling pad element.
    pad = getEventSourceElement(event)

    stopTimer();
    resetMenus();

    if (!pad.initialised) {

        // Blur focus from the link to remove that annoying outline.
        pad.onclick = 'blur();'

        // Set mouseout event handler for pad.
        pad.onmouseout = startTimer;

        // Determine if calling pad element has associated menu.
        if (!pad.menu && menuId) {

            // Associate the named menu to this pad if not already done.
            pad.menu = document.getElementById(menuId);

            // Set mouseover and mouseout event handlers for menu.
            pad.menu.onmouseover = menuOver;
            pad.menu.onmouseout = padOrMenuMouseout;

            var x, y;

            // Position the associated drop down menu under the pad and show it.
            x = getPageOffsetLeft(pad);
            y = getPageOffsetTop(pad) + pad.offsetHeight;

            // For IE, adjust position.
            if (browser.isIE) {
                x += pad.offsetParent.clientLeft;
                y += pad.offsetParent.clientTop;
            }

            pad.menu.style.left = x + "px";
            pad.menu.style.top  = y + "px";

            //document.getElementById('menu4Left').innerHTML = x;
            //document.getElementById('menu4Top').innerHTML = y;
            
            // Mark menu as initialized.
            pad.menu.initialised = true;
        
        } else {

            // Set mouseout event handler for pad.
            pad.onmouseout = resetMenus;

            pad.menu = null;
        }

        pad.initialised = true;
    }

    // Activate pad element
    // Update the pad's style class to make it look like it's depressed.
    pad.className += " padActive";

    if (pad.menu) {
        pad.menu.style.visibility = "visible";
    }

    activePad = pad;

    return false;
}

/**
 *
 *
 * @access private
 */
function resetMenus()
{
    if (!activePad) {
        return;
    }

    // Restore the pad's style class.
    removeClassName(activePad, "padActive");

    // Hide the pad's menu, first closing any sub menus.
    if (activePad.menu) {
        closeSubMenu(activePad.menu);
        activePad.menu.style.visibility = "hidden";
    }

    activePad = null;
}

//----------------------------------------------------------------------------
// Code to handle the menus and sub menus.
//----------------------------------------------------------------------------

/**
 *
 *
 * @access public
 */
function menuOver(event)
{
    //alert('menuOver(event) triggered');
    
    stopTimer();

    var menu;

    // Find the target menu element.
    if (browser.isIE) {
        menu = getContainerWith(window.event.srcElement, "DIV", "menu");
    } else {
        menu = event.currentTarget;
    }

    // Close any active sub menu.
    if (menu.activeItem != null)
        closeSubMenu(menu);
}

/**
 *
 *
 * @access public
 */
function menuItemOver(event, menuId)
{
    stopTimer();

    var item, menu;
    
    // Find the target item element and its parent menu element.
    //if (browser.isIE) {
    if (window.event) {
        item = getContainerWith(window.event.srcElement, 'A', 'menuItem');
    } else {
        item = event.currentTarget;
    }

    menu = getContainerWith(item, 'DIV', 'menu');

    // Close any active sub menu and mark this one as active.
    if (menu.activeItem) {
        closeSubMenu(menu);
    }
    menu.activeItem = item;

    // Highlight the item element.
    item.className += ' menuItemHighlight';

    // Initialise submenu.
    if (!item.subMenu) {

        item.subMenu = document.getElementById(menuId);
        //if (item.subMenu.isInitialized == null)
            //menuInit(item.subMenu);

        // Set mouseover and mouseout event handlers for submenu.
        item.subMenu.onmouseover = menuOver;
        item.subMenu.onmouseout = padOrMenuMouseout;

        var x, y;

        // Get position for submenu based on the menu item.
        x = getPageOffsetLeft(item) + item.offsetWidth;
        y = getPageOffsetTop(item);

        // Adjust position to fit in view.
        var maxX, maxY;

        if (browser.isIE) {
            maxX = Math.max(document.documentElement.scrollLeft,
                document.body.scrollLeft) +
                (document.documentElement.clientWidth != 0 ?
                document.documentElement.clientWidth :
                document.body.clientWidth);
            maxY = Math.max(document.documentElement.scrollTop,
                document.body.scrollTop) +
                (document.documentElement.clientHeight != 0 ?
                document.documentElement.clientHeight :
                document.body.clientHeight);
        }
    
        if (browser.isOP) {
            maxX = document.documentElement.scrollLeft + window.innerWidth;
            maxY = document.documentElement.scrollTop  + window.innerHeight;
        }
    
        if (browser.isNS) {
            maxX = window.scrollX + window.innerWidth;
            maxY = window.scrollY + window.innerHeight;
        }
    
        maxX -= item.subMenu.offsetWidth;
        maxY -= item.subMenu.offsetHeight;

        if (x > maxX) {
            x = Math.max(0, x - item.offsetWidth - item.subMenu.offsetWidth
                + (menu.offsetWidth - item.offsetWidth));
        }
    
        y = Math.max(0, Math.min(y, maxY));

        // Position and show the sub menu.
        item.subMenu.style.left = x + "px";
        item.subMenu.style.top  = y + "px";

    }

    item.subMenu.style.visibility = "visible";

    // Stop the event from bubbling.
    //if (browser.isIE) {
    if (window.event) {
        window.event.cancelBubble = true;
    } else {
        event.stopPropagation();
    }
}

/**
 *
 *
 * @access private
 */
function closeSubMenu(menu)
{
    if (!menu || !menu.activeItem) {
        return;
    }

    // Recursively close any sub menus.
    if (menu.activeItem.subMenu) {
        closeSubMenu(menu.activeItem.subMenu);
        menu.activeItem.subMenu.style.visibility = "hidden";
        menu.activeItem.subMenu = null;
    }
    
    removeClassName(menu.activeItem, "menuItemHighlight");
    
    menu.activeItem = null;
}

/**
 * Handler for mouseout event on pads and menus.
 *
 * @access private
 * @access public
 */
function padOrMenuMouseout(event)
{
    // If there is no active pad, exit.
    if (!activePad) {
        return;
    }

    var element;

    // Find the element the mouse is moving to.
    //if (browser.isIE)
    if (window.event) {
        element = window.event.toElement;
    } else if (event.relatedTarget) {
        element = (event.relatedTarget.tagName ? event.relatedTarget :
            event.relatedTarget.parentNode);
    }

    // If the element is not part of a menu, reset the active pad.
    if (!getContainerWith(element, "DIV", "menu")) {
        startTimer();
    }
}

//----------------------------------------------------------------------------
// Code to initialize menus.
//----------------------------------------------------------------------------

/**
 *
 *
 * @access public
 */
function menuInit(menu)
{
    // Mark menu as initialized.
    menu.isInitialized = true;
}

//----------------------------------------------------------------------------
// General utility functions.
//----------------------------------------------------------------------------

/**
 *
 *
 * @access private
 */
function getContainerWith(node, tagName, className)
{
    // Starting with the given node, find the nearest containing element
    // with the specified tag name and style class.
    while (node != null) {
        if (node.tagName != null && node.tagName == tagName &&
            hasClassName(node, className))
            return node;
        node = node.parentNode;
    }

    return node;
}

/**
 *
 *
 * @access private
 */
function hasClassName(el, name)
{
    var i, list;

    // Return true if the given element currently has the given class name.
    list = el.className.split(" ");
    for (i = 0; i < list.length; i++)
        if (list[i] == name)
            return true;

    return false;
}

/**
 *
 *
 * @access private
 * @access public
 */
function removeClassName(el, name)
{
    var i, curList, newList;

    if (el.className == null)
        return;

    // Remove the given class name from the element's className property.
    newList = new Array();
    curList = el.className.split(" ");
    for (i = 0; i < curList.length; i++)
        if (curList[i] != name)
            newList.push(curList[i]);
    el.className = newList.join(" ");
}

/**
 *
 *
 * @access private
 */
function getPageOffsetLeft(el)
{
    var x;

    // Return the x coordinate of an element relative to the page.
    x = el.offsetLeft;
    if (el.offsetParent != null)
        x += getPageOffsetLeft(el.offsetParent);

    return x;
}

/**
 *
 *
 * @access private
 */
function getPageOffsetTop(el)
{
    var y;

    // Return the y coordinate of an element relative to the page.
    y = el.offsetTop;
    if (el.offsetParent != null) {
        y += getPageOffsetTop(el.offsetParent);
    }

    return y;
}

/**
 * getEventSourceElement(event)
 *
 * @access private
 */
function getEventSourceElement(event)
{
    if (window.event) {
        return window.event.srcElement;
    } else {
        return event.currentTarget;
    }
}

function startTimer()
{
    if (timerOn) {
        return;
    }

    timerID = setTimeout("resetMenus()", pause);
    timerOn = true;

}

function stopTimer()
{
    if (!timerOn) {
        return;
    }

    clearTimeout(timerID);
    timerID = null;
    timerOn = false;

}



