﻿var Class = {
    create: function ()
    {
        return function ()
        {
            this.initialize.apply(this, arguments);
        }
    }
}

/** 一些实用的方法 */
var MenuUtilClass = Class.create();
MenuUtilClass.prototype =
{
    initialize: function ()
    {
    },

    $: function (id)
    {
        return document.getElementById(id);
    },

    $A: function (iterable)
    {
        if (!iterable)
        {
            return [];
        }
        if (iterable.toArray)
        {
            return iterable.toArray();
        } else
        {
            var results = [];
            for (var i = 0; i < iterable.length; i++)
            {
                results.push(iterable[i]);
            }
            return results;
        }
    },

    bind: function (obj, method)
    {
        return function (e)
        {
            return method.apply(obj, [e]);
        }
    },

    getHeight: function (element)
    {
        return element.offsetHeight;
    },

    setStyle: function (element, key, value)
    {
        element.style[key] = value;
    },

    getStyle: function (element, key)
    {
        return element.style[key];
    },

    cleanWhitespace: function (list)
    {
        var node = list.firstChild;
        while (node)
        {
            var nextNode = node.nextSibling;
            if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
            {
                list.removeChild(node);
            }
            node = nextNode;
        }
        return list;
    },

    cumulativeOffset: function (element)
    {
        var valueT = 0, valueL = 0;
        do
        {
            valueT += element.offsetTop || 0;
            valueL += element.offsetLeft || 0;
            element = element.offsetParent;
        } while (element);
        return [valueL, valueT];
    },

    getWidth: function (element)
    {
        return element.offsetWidth;
    },

    currentOffset: function (element)
    {
        var valueT = element.offsetTop || 0;
        var valueL = element.offsetLeft || 0;
        return [valueL, valueT];
    },

    getChildElementAt: function (node, index)
    {
        for (var i = 0; i < node.childNodes.length; i++)
        {
            var childNode = node.childNodes[i];
            if (childNode.nodeType != 1)
                continue;

            if (index == 0)
                return childNode;

            index--;
        }
    },

    cancelBubble: function (e)
    {
        if (!e)
            e = window.event;
        e.cancelBubble = true;
        if (e && e.stopPropagation)
            e.stopPropagation();
    }
}

var MenuUtils = new MenuUtilClass();

var MenuStack = new Array();

MenuStack.indexOf = function (subMenu)
{
    for (var i = 0; i < this.length; i++)
    {
        if (this[i] == subMenu)
            return i;
    }
    return -1;
}

MenuStack.deactivateFrom = function (index)
{
    for (var i = index; i < this.length; i++)
    {
        MenuUtils.setStyle(this[i], 'visibility', 'hidden');
    }

    this.length = index;
}

MenuStack.keepActive = function()
{
    if (this.deactivateTimerId)
    {
        window.clearTimeout(this.deactivateTimerId);
        this.deactivateTimerId = null;
    }
}

MenuStack.activated = function (parent, child)
{
    this.keepActive();

    var index = this.indexOf(child);
    if (index >= 0)
    {
        this.deactivateFrom(index + 1);
        return;
    }
    index = this.indexOf(parent);    
    this.deactivateFrom(index + 1);
    this[this.length] = child;
}

MenuStack.deactivateAll = function ()
{
    if (this.deactivateTimerId)
    {
        this.deactivateFrom(0);
        this.deactivateTimerId = null;
    }
}

MenuStack.deactivate = function (child)
{
    if (this.deactivateTimerId)
        return;

    var pThis = this;
    this.deactivateTimerId = window.setTimeout(
        function ()
        {
            pThis.deactivateAll();
        }, 200);
}

/** 菜单列表 */
var MenuBar = Class.create();
MenuBar.prototype = {

    /**
    * 构造方法
    * id: 菜单列表
    */
    initialize: function (id)
    {
        // Get the root object
        this.obj = document.getElementById(id);
        if (!this.obj) { return; }

        // Get all sub menus
        this.initSubMenus(null, this.obj, 0);
    },

    initSubMenus: function (parent, node, level)
    {
        for (var i = 0; i < node.childNodes.length; i++)
        {
            var childNode = node.childNodes[i];
            if (childNode.nodeType != 1)
                continue;
            if (childNode.className != "sub_menu")
                this.initSubMenus(parent, childNode, level);
            else
            {
                var subMenu = new SubMenu(parent, childNode.parentNode, level);
                this.initSubMenus(subMenu, childNode, level + 1);
            }
        }
    }
}

/** 菜单 */
var SubMenu = Class.create();
SubMenu.prototype = {

    /**
    * 构造方法
    * target: 目标菜单
    * sub: 是否为子菜单 (1 为肯定, -1 为否定) [multi 2009/06/11 ADD]
    */
    initialize: function (parent, target, level)
    {
        this.parent = parent;

        // 获取目标菜单 (没多余元素)
        this.obj = MenuUtils.cleanWhitespace(target);

        // 是否为子菜单
        this.level = level;

        // 菜单标题和菜单体
        this.title = MenuUtils.getChildElementAt(this.obj, 0);
        this.body = MenuUtils.getChildElementAt(this.obj, 1);

        // 定义初始样式
        MenuUtils.setStyle(this.body, 'visibility', 'hidden');
        MenuUtils.setStyle(this.body, 'position', 'absolute');
        MenuUtils.setStyle(this.body, 'display', 'block');

        // 添加监听器
        this.addListener(this.title, 'mouseover', MenuUtils.bind(this, this.activate), false);
        this.addListener(this.obj, 'mouseover', MenuUtils.bind(this, this.keepActive), false);
        this.addListener(this.obj, 'mouseout', MenuUtils.bind(this, this.deactivate), false);
    },

    /**
    * 激活方法
    * 当鼠标移动到菜单标题是激活
    */
    activate: function (e)
    {
        // 获取当前菜单体的位置 (子菜单)
        if (this.level > 0)
        {
            var pos = MenuUtils.currentOffset(this.title);
            var left = MenuUtils.getWidth(this.parent.body) - 4;
            var top = pos[1] - 4;

            // 获取当前菜单体的位置 (菜单)
        } else
        {
            var pos = MenuUtils.cumulativeOffset(this.title);
            var left = pos[0];
            var top = pos[1] + MenuUtils.getHeight(this.title);
        }

        // 定义激活时样式
        MenuUtils.setStyle(this.body, 'left', left + 'px');
        MenuUtils.setStyle(this.body, 'top', top + 'px');
        MenuUtils.setStyle(this.body, 'visibility', 'visible');

        var parent = null;
        if (this.parent)
            parent = this.parent.body;

        MenuStack.activated(parent, this.body);

        MenuUtils.cancelBubble(e);
    },

    keepActive: function (e)
    {
        MenuStack.keepActive();
    },

    /**
    * 解除方法
    * 当鼠标移动出菜单标题是激活
    */
    deactivate: function (e)
    {
        MenuStack.deactivate();
    },

    /**
    * 监听方法
    * element: 监听对象
    * name: 监听方法
    * observer: 执行的方法
    * useCapture: 浏览器调用事件的方式 (true 为 Capture 方式, false 为 Bubbling 方式)
    */
    addListener: function (element, name, observer, useCapture)
    {
        if (element.addEventListener)
        {
            element.addEventListener(name, observer, useCapture);
        } else if (element.attachEvent)
        {
            element.attachEvent('on' + name, observer);
        }
    }
}

/** 添加到页面加载事件 */
window.onload = function (e)
{
    new MenuBar('menu');
}

