/**
 * Vertical Expansion Menu.
 * Version: 2.0
 *
 * The use of this script is strictly forbidden without prior written
 * consent. You must obtain permission before copying, modifying, 
 * redistributing, deriving or selling any part of this program.
 *
 * Copyright (c) 2008 HYPERZOID
 * All Rights Reserved
 */


// The Menu object.
var menu = null;


/**
 * Initializes this program.
 */
function initMenu() {
    menu = new Menu();
}


/**
 * The constructor.
 */
function Menu() {
    // Get cookie values.
    var item        = this.getCookie('item');
    var submenu     = this.getCookie('submenu');
    var submenuItem = this.getCookie('submenuItem');

    // Select the current menu item and submenu item.
    var items = this.getElementsByClass(document.getElementById('menu'), 'item');
    for (var i = 0; i < items.length; i++) {
        if (items[i].id != null && item != null && items[i].id == item) {
            items[i].className = 'item current selected';
        }
        if (items[i].id != null && submenuItem != null && items[i].id == submenuItem) {
            items[i].className = 'item current selected';
        }
    }

    // Open the current submenu.
    var submenus = this.getElementsByClass(document.getElementById('menu'), 'submenu');
    for (var i = 0; i < submenus.length; i++) {
        if (submenus[i].id != null && submenu != null && submenus[i].id == submenu) {
            submenus[i].className = 'submenu current open';
        }
    }
}


/**
 * Clears the current item, submenu and submenu item.
 */
Menu.prototype.clear = function() {
    this.deleteCookie('item');
    this.deleteCookie('submenu');
    this.deleteCookie('submenuItem');
}


/**
 * Handles onclick events for menu items.
 * @param item The menu item that fired the onclick event.
 * @param id   The submenu's DOM ID.
 */
Menu.prototype.clickMenuItem = function(item, id) {
    // Get the submenu element.
    var submenu = document.getElementById(id);

    // Ignore the click if the item is current. 
    if (item.className.indexOf('current') != -1) {
        return false;
    }

    // Deselect the clicked item and close its submenu if it is already opened.
    if (submenu.className.indexOf('open') != -1) {
        item.className    = 'item';
        submenu.className = 'submenu close';
        return false;
    }

    // Close all non-current submenus.
    var submenus = this.getElementsByClass(document.getElementById('menu'), 'submenu');
    for (var i = 0; i < submenus.length; i++) {
        if (submenus[i].className.indexOf('current') != -1) {
            continue;
        }
        submenus[i].className = 'submenu close';
    }

    // Deselect all non-current items.
    var items = this.getElementsByClass(document.getElementById('menu'), 'item');
    for (var i = 0; i < items.length; i++) {
        if (items[i].className.indexOf('current') != -1) {
            continue;
        }
        items[i].className = 'item';
    }

    // Select the clicked item and open its submenu.
    item.className    = 'item selected';
    submenu.className = 'submenu open';

    return false;
}


/**
 * Handles onclick events for submenu items.
 * @param item        The menu item that contains the submenu that contains the submenu item.
 * @param submenu     The submenu that contains the submenu item.
 * @param submenuItem The submenu item that fired the onclick event.
 */
Menu.prototype.clickSubmenuItem = function(item, submenu, submenuItem) {
    this.setCookie('item', item);
    this.setCookie('submenu', submenu);
    if (submenuItem != null) {
        this.setCookie('submenuItem', submenuItem);
    }
}


/**
 * Returns all descendents of node n in CSS class c.
 */
Menu.prototype.getElementsByClass = function(n, c) {
    var descendents = this.getDescendents(n);
    var matches     = new Array();
    var index       = 0;
    for (var i = 0; i < descendents.length; i++) {
        if (descendents[i].className != null &&
            descendents[i].className.indexOf(c) != -1) {
            matches[index] = descendents[i];
            index++;
        }
    }
    return matches;
}


/**
 * Returns all descendents of node n.
 */
Menu.prototype.getDescendents = function(n) {
    var descendents = new Array();
    descendents[0] = n;

    if (n.childNodes.length == 0) {
        return descendents;
    }

    var children = n.childNodes;
    for (var i = 0; i < children.length; i++) {
        descendents = descendents.concat(this.getDescendents(children[i]));
    }
    
    return descendents;
}


/**
 * Deletes a cookie.
 * @param name  The name of the cookie.
 */
Menu.prototype.deleteCookie = function(name) {
    document.cookie = name + "=; path=/; expires=Thu, 01-Jan-70 00:00:01 GMT";
} 


/**
 * Returns the value of a cookie or NULL if it doesn't exist.
 * @param name  The name of the cookie.
 */
Menu.prototype.getCookie = function(name) {
    // Get an array of key/value pairs.
    var cookies = document.cookie.split(';');

    for (var i = 0; i < cookies.length; i++ ) {
        var cookie = cookies[i].split('=');
        
        // Trim leading and trailing spaces.
        cookie[0] = cookie[0].replace(/^\s+|\s+$/g, '');

        if (cookie[0] == name) {
            if (cookie.length > 1) {
                return unescape(cookie[1].replace(/^\s+|\s+$/g, ''));
            } else {
                return '';
            }
        }
    }

    return null; 
}


/**
 * Sets a cookie.
 * @param name  The name of the cookie.
 * @param value The value of the cookie.
 */
Menu.prototype.setCookie = function(name, value) {
    // Make cookie expire in 1 minute.
    var expires = (new Date((new Date()).getTime() + 60000)).toGMTString();

    document.cookie = name + '=' + escape(value) + '; path=/; expires=' + expires;
}


// Initialize this program upon the onload event.
addOnLoad(initMenu);