var TAG_MENU = "UL", TAG_MENU_ITEM = "LI";
//var TAG_MENU = "TABLE", TAG_MENU_ITEM = "TD";

function findParentMenu (obj)
{
	var tmp = obj;
	while (tmp != null)
	{
		if (tmp.tagName == TAG_MENU)
			return tmp;
		tmp = (tmp.parentElement) ? tmp.parentElement : tmp.parentNode;
	}
	return null;
}

function findParentMenuItem (obj)
{
	var tmp = obj;
	while (tmp != null)
	{
		if (tmp.tagName == TAG_MENU)
			return null;
		if (tmp.tagName == TAG_MENU_ITEM)
			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 == TAG_MENU)
			return null;
		if (tmp.tagName == TAG_MENU_ITEM)
			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 == TAG_MENU)  
			return ch.item(i);
	}
	return null;
}

function getMenu (item)
{
	var tmp = (item.parentElement) ? item.parentElement : item.parentNode;
	while (tmp != null)
	{
		if (tmp.tagName == TAG_MENU)
			return tmp;
		if (tmp.tagName == TAG_MENU_ITEM)
			return null;
		tmp = (tmp.parentElement) ? tmp.parentElement : tmp.parentNode;
	}
	return null;
}

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);
		}
		
	}
}

