function findParentMenu (obj)
{
        var tmp = obj;
        while (tmp != null)
        {
                if (tmp.tagName == "UL")
                        return tmp;
                tmp = (tmp.parentElement) ? tmp.parentElement : tmp.parentNode;
        }
        return null;
}

function findParentMenuItem (obj)
{
        var tmp = obj;
        while (tmp != null)
        {
                if (tmp.tagName == "UL")
                        return null;
                if (tmp.tagName == "LI")
                        return tmp;
                tmp = (tmp.parentElement) ? tmp.parentElement : tmp.parentNode;
        }
        return null;
}

function getParentMenuItem (menu)
{
        if (menu == null)
                return null;
                
        var tmp = (menu.parentElement) ? menu.parentElement : menu.parentNode;
        while (tmp != null)
        {
                if (tmp.tagName == "UL")
                        return null;
                if (tmp.tagName == "LI")
                        return tmp;
                tmp = (tmp.parentElement) ? tmp.parentElement : tmp.parentNode;
        }
        return null;
}

function getChildMenu (item)
{
        if ((item == null) || (item.childNodes == null))
                return null;
        var ch = item.childNodes;
        for (var i=0; i<ch.length; i++)
        {
                if (ch[i].nodeName == "UL")  
                        return ch.item(i);
        }
        return null;
}

function getMenu (item)
{
        return (item.parentElement) ? item.parentElement : item.parentNode;
}

function isParent (p, c)
{
        if ((p == null) || (c == null))
                return false;
                
        var tmp = c;
        do 
        {
                if (tmp == p)
                        return true;
                tmp = (tmp.parentElement) ? tmp.parentElement : tmp.parentNode;
        }       
        while (tmp != null);
        return false;
}

/* basic menu functions */
function menu_Show (menu)
{
        if (!menu || !menu.style)
                return; 

        menu.style.visibility = "visible";
}

function menu_Hide (menu)
{
        if (!menu || !menu.style)
                return; 

        menu.style.visibility = "hidden";
}

function menu_clearHideTimer ()
{
        if (menu_hidetimeout != null)
        {
                window.clearTimeout (menu_hidetimeout);
                menu_hidetimeout = null;
        }
}

function menu_clearShowTimer ()
{
        if (menu_timeout != null)
        {
                window.clearTimeout (menu_timeout);
                menu_timeout = null;
        }
}

function menu_setHideTimer (timeout)
{
        menu_clearHideTimer (); 
        menu_hidetimeout = window.setTimeout (menu_HideAll, timeout);
}

function menu_setShowTimer (timeout, pos)
{
        menu_clearShowTimer (); 
        menu_timeout = window.setTimeout ('menu_ShowMenu (\'' + pos + '\')', timeout);
}


/* menu handling */
var menu_item = null, menu_toshow = null, menu_timeout = null, menu_hidetimeout = null, menu_items = new Array (), menu_level = 0;

function menu_GetLeastCommonMenu (item)
{
        var menu = getMenu (item);
        if (menu == menu_toshow)
        {
                return menu_level;
        }

        for (var i=0; i<menu_level; i++)
        {
                if (getMenu (menu_items[i]) == menu)
                {
                        return (menu_items[i] != item) ? i : menu_level;
                }
        }
        return 0;
}

function menu_ShowMenu (pos)
{
        var item = menu_item;
        if (item == null)
                return;

        var levelOld = menu_level;

        menu_HideChildMenus (menu_GetLeastCommonMenu (item));
        
        /* show menu */
        if ((levelOld > menu_level) || (getMenu (item) == menu_toshow) || (menu_level == 0))
        {
                menu_items [menu_level++] = item;
                var menu = getChildMenu (item);
                if (menu != null)
                {
                        menu_toshow = menu;
                        // reposition
                        if ((pos != null) && (pos != ''))
                                eval (pos + " (menu_level, menu, item);");
                        // show menu
                        menu_Show (menu_toshow);
                }
                else
                {
                        menu_toshow = null;
                }
        }
}

function menu_HideAll ()
{
        menu_clearShowTimer ();

        if (menu_toshow != null)
                menu_Hide (menu_toshow);

        for (var i=menu_level-1; i>0; i--)
                menu_Hide (getMenu (menu_items[i]));

        menu_toshow = null;
        menu_level = 0;
        menu_hidetimeout = null;
}

function menu_HideChildMenus (from)
{
        if (menu_level <= from)
                return;
        else if (menu_level > from)
                if (menu_toshow != null)
                {
                        menu_Hide (menu_toshow);
                        menu_toshow = null;
                }

        for (var i=menu_level-1; i>from; i--)
                menu_Hide (getMenu (menu_items[i]));
                
        menu_level = from;
}

/* event handlers */
function mout (e, timeout)
{
        e = (e == null) ? event : e;
        
        var from = e.fromElement ? e.fromElement : e.target;
        var to   = e.toElement ? e.toElement : e.relatedTarget;
        var menu = findParentMenu (from);

        if (!(from && to && menu))
                return;

        if (isParent (menu, from) && !isParent (menu, to) && (to != menu)
                /* not hide if moving mouse into a parent submenu */
                && (((menu_level > 0) && !isParent (getMenu (menu_items[0]), to)) || (menu_level == 0))
        )
        {
                menu_clearShowTimer ();
                menu_setHideTimer (timeout);
        }

}

function mover (e, timeout, pos)
{
        e = (e == null) ? event : e;
        
        var from = e.fromElement ? e.fromElement : e.relatedTarget;
        var to   = e.toElement ? e.toElement : e.target;
        var menu = findParentMenu (to);
        var item = findParentMenuItem (to);

        if ((from && to && menu) && isParent (menu, to) && !isParent (menu, from) && (from != menu))
                /* cancelling hiding - focus on menu */
                menu_clearHideTimer ();

        if ((from && to && item) && isParent (item, to) && !isParent (item, from) && (from != item))
        {
                menu_item = item;
                if (timeout == 0)
                {
                        menu_ShowMenu (pos);
                }
                else
                {
                        menu_setShowTimer (timeout, pos);
                }
                
        }
}



