function Menu(container_id)
{
    var Menu = this;

    if (arguments[1]) {
        this.parent = arguments[1];
        this.parent.child = this;
    } else {
        this.parent = null;
    }
    this.currItem = null;

    this.showTimeout = 100;
    this.hideTimeout = 500;

    this.obj = document.getElementById(container_id);
if (!this.obj) { alert("Invalid object id: " + container_id); }
    this.timer = null;

    this.isActive = false;

    this.onMouseOver = function(e)
    {
        Menu.stopTimer();
        if (Menu.parent) {
            Menu.parent.onMouseOver(e);
            if (Menu.parent.container) {
                Menu.parent.container.onMouseOver();
            }
        }
    }

    this.onMouseOut = function(e)
    {
        Menu.stopTimer();

        if (Menu.parent && Menu.parent.container) {
            Menu.parent.container.onMouseOut();
        }

        Menu.runTimer(false);
    }

    this.runTimer = function(mode)
    {
        Menu.stopTimer();
        var timeout;
        if (arguments[1]) {
            timeout = arguments[1];
        } else {
            timeout = mode ? Menu.showTimeout : Menu.hideTimeout;
        }
        Menu.timer = window.setTimeout(function() { Menu.setVisibility(mode); }, timeout);
    }

    this.stopTimer = function()
    {
        if (Menu.timer) {
            window.clearTimeout(Menu.timer);
            Menu.timer = null;
        }
    }

    this.setVisibility = function(mode)
    {
        Menu.stopTimer();
        if (mode) {
            if (Menu.parent) {
                Menu.obj.style.top = Menu.parent.getChildY() + 'px';
                Menu.obj.style.left = Menu.parent.getChildX() + 'px';
            }
            Menu.obj.style.visibility = 'visible';
        } else {
            if (Menu.currItem) {
                Menu.currItem.obj.className = Menu.currItem.normalClass;
                if (Menu.currItem.child) {
                    Menu.currItem.child.visibility = false;
                    Menu.currItem.child.setVisibility(false);
                }
            }
            if (Menu.parent) {
                Menu.parent.obj.className = Menu.parent.normalClass;
            }
            //do not hide parentless (root) container
            if (Menu.parent) {
                Menu.obj.style.visibility = 'hidden';
            }
        }
    }


    this.obj.onmouseover = this.onMouseOver;
    this.obj.onmouseout = this.onMouseOut;
}

function MenuItem(id, container)
{
    var MenuItem = this;

    this.container = container;
    if (arguments[2]) {
        this.child = arguments[2];
        this.child.parent = this;
    } else {
        this.child = null;
    }
    this.childPos = {h:'left', v:'bottom', x:0, y:0};

    this.activeClass = 'activeItem';
    this.normalClass = 'item';

    this.obj = document.getElementById(id);
    if (!this.obj) { alert("Invalid object id: " + id); }

    this.onMouseOver = function(e)
    {
        var prev = (MenuItem.container.currItem) ? MenuItem.container.currItem : null;
        MenuItem.container.currItem = MenuItem;

        MenuItem.obj.className = MenuItem.activeClass;

        if (prev && prev != MenuItem) {
            prev.obj.className = prev.normalClass;
            if (prev.child) {
                prev.child.runTimer(false, MenuItem.child ? MenuItem.child.showTimeout : null);
            }
        }
        if (MenuItem.child) {
            MenuItem.child.runTimer(true);
        }
    }

    this.getChildX = function()
    {
        if (!MenuItem.childPos.h) {
            MenuItem.childPos.h = 'right';
        }
        if (!MenuItem.childPos.x) {
            MenuItem.childPos.x = 0;
        }
        return MenuItem[MenuItem.childPos.h]() + MenuItem.childPos.x;
    }

    this.getChildY = function()
    {
        if (!MenuItem.childPos.v) {
            MenuItem.childPos.v = 'top';
        }
        if (!MenuItem.childPos.y) {
            MenuItem.childPos.y = 0;
        }

        return MenuItem[MenuItem.childPos.v]() + MenuItem.childPos.y;
    }

    this.getCoords = function()
    {
        var obj = MenuItem.obj;
        var c = {x:0, y:0, w:obj.offsetWidth, h:obj.offsetHeight};
        while (obj) {
            c.x += obj.offsetLeft;
            c.y += obj.offsetTop;
            obj = obj.offsetParent;
        }
        return c;
    }

    this.left = function()
    {
        var c = MenuItem.getCoords();
        return (c.x);
    }

    this.center = function()
    {
        var c = MenuItem.getCoords();
        return (c.x + c.w/2);
    }

    this.right = function()
    {
        var c = MenuItem.getCoords();
        return (c.x + c.w);
    }

    this.top = function()
    {
        var c = MenuItem.getCoords();
        return (c.y);
    }

    this.middle = function()
    {
        var c = MenuItem.getCoords();
        return (c.y + c.h/2);
    }

    this.bottom = function()
    {
        var c = MenuItem.getCoords();
        return (c.y + c.h);
    }

    this.obj.onmouseover = this.onMouseOver;
}


function createItem(def, container)
{
    var i = new MenuItem(def.id, container);
    if (def.aclass) {
        i.activeClass = def.aclass;
    }
    if (def.nclass) {
        i.normalClass = def.nclass;
    }
    if (def.child) {
        createContainer(def.child, i);
        if (def.child.pos) {
            i.childPos = def.child.pos;
        }
    }

    return i;
}

function createContainer(def, parent)
{
    var c = new Menu(def.id, parent);
    if (def.items) {
        for (var i=0; i<def.items.length; i++) {
            createItem(def.items[i], c);
        }
    }
    return c;
}
