
/* create own convenience DOM JavaScript object */

DOM = {
    getNode: function (str, obj) {
        return cssQuery(str, obj);
    },
    getPosition: function (obj) {
        var pos = YAHOO.util.Dom.getXY(obj);
        return { x: pos[0], y: pos[1] };
    },
    setPosition: function (obj, pos) {
        YAHOO.util.Dom.setXY(obj, [ pos.x, pos.y ], true);
    },
    getStyle: function (obj, name) {
        return YAHOO.util.Dom.getStyle(obj, name);
    },
    setStyle: function (obj, name, value) {
        YAHOO.util.Dom.setStyle(obj, name, value);
    },
    getViewport: function () {
        return { x: YAHOO.util.Dom.getClientWidth(), y: YAHOO.util.Dom.getClientHeight() };
    },
    setEvent: function (obj, name, cb, ctx, override) {
        YAHOO.util.Event.addListener(obj, name, cb, ctx, override);
    }
};

/* smart deferred execution */

var defer_scheduled = Array();
var defer_handle    = Array();

function defer_schedule (id, cmd, delay) {
    if (defer_scheduled[id])
        clearTimeout(defer_handle[id]);
    defer_scheduled[id] = 1;
    defer_handle[id] = setTimeout("defer_scheduled[\""+id+"\"] = 0; " + cmd, delay);
    return;
}

function defer_cancel (id) {
    if (defer_scheduled[id])
        clearTimeout(defer_handle[id]);
    defer_scheduled[id] = 0;
    return;
}

/*
 *  <div> content switching
 */

/*  INTERNAL: the switchdiv run-time information */
var switchdiv = new Array();

/* INTERNAL: on mouse over events */
function switchdiv_over(event) {
    var id = this;
    switchdiv[id]["suspend"] = 1;
    return;
}

/* INTERNAL: on mouse out events */
function switchdiv_out(event) {
    var id = this;
    switchdiv[id]["suspend"] = 0;
    return;
}

/*  INTERNAL: update the switchdiv effect on a DOM node */
function switchdiv_update (id) {
    /*  check for suspend mode first */
    if (switchdiv[id]["suspend"] == 1) {
        /*  reschedule after 1s */
        defer_schedule("switchdiv_update_"+id, "switchdiv_update('"+id+"')", 1000);
        return;
    }

    /*  determine message nodes */
    var divs = switchdiv[id]["divs"];
    var div  = divs[switchdiv[id]["current"]];

    /*  switching to next message */
    div.style.display = "none";
    switchdiv[id]["current"] = ((switchdiv[id]["current"] + 1) % divs.length);
    div = divs[switchdiv[id]["current"]];
    div.style.display = "block";
    t = switchdiv[id]["keep"];

    /*  re-schedule switchdiv rendering */
    defer_schedule("switchdiv_update_"+id, "switchdiv_update('"+id+"')", t);

    return;
}

/*  EXTERNAL: apply a switchdiv effect to a DOM node */
function switchdiv_apply (id, root_select, div_select, keep) {
    /*  determine DOM root node */
    var root = DOM.getNode(root_select);

    /*  initially do not display any message */
    var divs = DOM.getNode(div_select, root);
    if (divs.length < 2) {
        alert("switchdiv <div> '"+id+"' does not contain at least 2 message <div> elements!");
        return;
    }
    for (var i = 0; i < divs.length; i++)
        divs[i].style.display = "none";

    /*  remember switchdiv run-time information */
    switchdiv[id] = new Array();
    switchdiv[id]["divs"]     = divs;
    switchdiv[id]["current"]  = divs.length-1;
    switchdiv[id]["keep"]     = keep;
    switchdiv[id]["suspend"]  = 0;

    /* grab mouse over/out events */
    DOM.setEvent(root, "mouseover", switchdiv_over, id, true);
    DOM.setEvent(root, "mouseout",  switchdiv_out,  id, true);

    /*  schedule switchdiv rendering */
    defer_schedule("switchdiv_update_"+id, "switchdiv_update('"+id+"')", 1000);

    return;
}

/* INTERNAL: toggle classes */
function toggleclass_update (id, nodes_selector, class1, class2, delay) {
    var nodes = DOM.getNode(nodes_selector);
    for (var i = 0; i < nodes.length; i++) {
        if (nodes[i].className == class1)
            nodes[i].className = class2;
        else if (nodes[i].className == class2)
            nodes[i].className = class1;
    }
    defer_schedule("toggleclass_update_"+id, "toggleclass_update('"+id+"', '"+nodes_selector+"', '"+class1+"', '"+class2+"', '"+delay+"')", delay);
    return;
}

/*  EXTERNAL: apply a class toggling effect to DOM nodes */
function toggleclass_apply (id, nodes_selector, class1, class2, delay) {
    var nodes = DOM.getNode(nodes_selector);
    if (nodes.length < 1) {
        alert("no elements found via '"+nodes_selector+"' for class toggling!");
        return;
    }
    defer_schedule("toggleclass_update_"+id, "toggleclass_update('"+id+"', '"+nodes_selector+"', '"+class1+"', '"+class2+"', '"+delay+"')", delay);
    return;
}



/* define tab background update function */
function nav_tab_update (e) {
    /* determine outer canvas box and active navigation tab */
    var box = DOM.getNode("div#canvas")[0];
    var tab = DOM.getNode("ul.navtab li.active")[0];

    /* determine viewport-relative positions of the two elements */
    var box_pos = DOM.getPosition(box);
    var tab_pos = DOM.getPosition(tab);

    /* determine effective width of box and its background image */
    var box_width = 800; // $(box).width() + 0;
    // var box_width = DOM.getStyle(box, "width") || "0px"; YUI returns "auto", JQuery is able to determine width
    // box_width = box_width.replace(/px/, "") - 0;
    var img_width = 720; /* FIXME: hard-coded width of background image */

    /* re-calculate and set new position of tab background image */
    var x = box_pos.x + box_width - img_width - tab_pos.x;
    var y = box_pos.y - tab_pos.y;
    DOM.setStyle(tab, "backgroundPosition", x+'px '+y+'px');
}

/* activate tab background update function */
DOM.setEvent(window, "resize", nav_tab_update);
DOM.setEvent(window, "load",   nav_tab_update);


/* dynamic navigation bar item expading/collapsing */

var navbar_default = "navbar.corporation.management.thl";
var navbar_active = navbar_default;

function navbar_over(event) {
    window.status = this.a.href;
    navbar_active = this.id;
    defer_cancel("navbar_out");
    defer_schedule("navbar_over", "navbar_toggle();", 600);
}

function navbar_out(event) {
    window.status = "";
    defer_schedule("navbar_out", "navbar_out_stage2('"+this.id+"');", 600);
}

function navbar_out_stage2(id) {
    if (navbar_active != id)
        return;
    navbar_active = navbar_default;
    navbar_cleanup();
}

function navbar_toggle() {
    var root = document.getElementById(navbar_active);
    var li = DOM.getNode("> ul > li", root);
    for (var i = 0; i < li.length; i++) {
        var display = (li[i].style.display != "none" ? "none" : "block");
        li[i].style.display = display;
    }
    return;
}

function navbar_cleanup() {
    var li = document.getElementsByTagName("li");
    var active_a = navbar_active.split(".");
    active_a.pop();
    var active_prefix = active_a.join(".");
    var li = document.getElementsByTagName("li");
    for (var i = 0; i < li.length; i++) {
        var id_s = li[i].id;
        var id_a = id_s.split(".");
        if (id_a[0] != "navbar")
            continue;
        id_a.pop();
        var id_prefix = id_a.join(".");
        if (   active_prefix.indexOf(id_prefix) == 0 /* siblings */
            || id_prefix == navbar_active)           /* childs   */
            display = 'block';
        else
            display = 'none';
        if (li[i].style.display != display)
            li[i].style.display = display;
    }
    return;
}

/* DOM event activation */

function nav_bar_setevents(e) {
    var nodes = DOM.getNode("div.navbar li");
    for (var i = 0; i < nodes.length; i++) {
        var anchor = DOM.getNode("a", nodes[i])[0];
        var obj = { id: nodes[i].id, li: nodes[i], a: anchor };
        DOM.setEvent(anchor, "mouseover", navbar_over, obj, true);
        DOM.setEvent(anchor, "mouseout",  navbar_out,  obj, true);
    }
}

DOM.setEvent(window, "load", nav_bar_setevents);



/*
 * Derived from jquery.jdMenu.js, version 1.3 (2007-02-22)
 * Copyright (c) 2006-2007 Jonathan Sharp (http://jdsharp.us)
 * Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
 * Code cleaned up by Ralf S. Engelschall
 */

(function($){
    /* determine parent nodes until a particular parent node is found */
    $.fn.parentsUntil = function(match) {
        var a = [];
        $(this[0]).parents().each(function() {
            a.push(this);
            return !$(this).is(match);
        });
        return this.pushStack(a, arguments);
    };
    
    /* returns settings object for this menu */
    function getSettings(el) {
        return $(el).parents('ul.jq_menu_root')[0].$settings;
    }

    /* unbind any events and then rebind them */
    function addEvents(ul) {
        removeEvents(ul);
        $('> li', ul)
            .hover(hoverOver, hoverOut)
            .bind('click', itemClick)
            .find('> a.accessible')
            .bind('click', accessibleClick);
    };
    
    /* unbind all events we may have attached */
    function removeEvents(ul) {
        $('> li', ul)
            .unbind('mouseover')
            .unbind('mouseout')
            .unbind('click')
            .find('> a.accessible').unbind('click');
    };

    /* passed in an <li> */
    function addHoverClass(li) {
        var c = 'jq_menu_hover' + ($(li).parent().is('.jq_menu_root') ? '_toolbar' : '');
        $(li).addClass(c).find('> a').addClass(c);
    }
    
    /* triggered when hovering over a list item */
    function hoverOver() {
        addHoverClass(this);
        if (this.$timer)
            clearTimeout(this.$timer);
        /* do we have a sub menu? */
        if ($('> ul', this).size() > 0) {
            var settings = getSettings(this);
            /* which delay to use, the longer activate one or the shorter show delay if a menu is already visible */
            var delay = ($(this).parents('ul.jq_menu_root').find('ul:visible').size() == 0) 
                        ? settings.activateDelay : settings.showDelay;
            var t = this;
            this.$timer = setTimeout(function() {
                showMenu.apply(t);
            }, delay);
        }
    };
    
    /* triggered when hovering out of a list item */
    function hoverOut() {
        $(this)
            .removeClass('jq_menu_hover')
            .removeClass('jq_menu_hover_toolbar')
            .find('> a')
            .removeClass('jq_menu_hover')
            .removeClass('jq_menu_hover_toolbar');
        if (this.$timer)
            clearTimeout(this.$timer);
        /* if we have a visible menu, hide it */
        if ($(this).is(':visible') && $('> ul', this).size() > 0) {
            var settings = getSettings(this);
            var ul = $('> ul', this)[0];
            this.$timer = setTimeout(function() {
                hideMenu.apply(ul);
            }, settings.hideDelay);
        }
    };
    
    /* "this" is a reference to the LI element that contains the UL that will be shown */
    function showMenu() {
        var ul = $('> ul', this).get(0);
        /* We are already visible, just return */
        if ($(ul).is(':visible'))
            return;

        /* add hover classes, needed for accessible functionality */
        addHoverClass(this);

        /* hide any existing menus at the same level */
        $(this).parent().find('> li > ul:visible').not(ul).each(function() {
            hideMenu.apply(this);
        });

        /* get our settings object */
        var settings = getSettings(this);

        /* clear our timer if it exists */
        if (this.$timer)
            clearTimeout(this.$timer);

        /* call our callback */
        settings.onShow.apply(this);
        addEvents(ul);

        /* "show" our menu so we can calculate its width, set left and
           top so that it does not accidentally go offscreen and trigger
           browser scroll bars */
        $(ul).css({visibility: 'hidden', left: 0, top: 0}).show();

        /* border width */
        var bw = parseInt($(this).parent().css('borderRightWidth'));
        var offset  = bw * settings.offset;

        /* window width */
        var ww = $(window).width();

        /* outer width of UL element */
        var ow = $(ul).outerWidth();

        /* offset and position */
        var liOffset = $(this).offset({border: true});
        var x = 0, y = 0;

        if ($(this).parentsUntil('ul.jq_menu_root').filter('li').size() == 0) {
            /* we are the top-level drop down menu */
            x = liOffset.left - $(this).parent().offset().left;
            y = liOffset.top  - $(this).parent().offset().top + $(this).outerHeight();
            if (ww < (x + ow)) {
                x = ww - ow;
                if (x < 0)
                    x = 0;
            }
        } else {
            /* we are a sub menu */
            y = liOffset.top - $(this).parent().offset().top;
            if ((ww < (liOffset.left + $(this).outerWidth() + ow))) {
                x = (-ow) + offset;
                if ((liOffset.left + x) < 0) {
                    x = offset;
                    y += $(this).outerHeight() - offset;
                }
            } else
                x = $(this).outerWidth() - offset;
        }

        /* iframe hack */
        if (settings.iframe)
            $(ul).bgiframe();

        /* show menu */
        if (settings.onAnimate) {
            $(ul).hide().css({left: x, top: y, visibility: 'visible'});
            settings.onAnimate.apply(ul);
        } else {
            $(ul).css({left: x, top: y, visibility: 'visible'});
        }
    }

    /* "this" is a reference to a UL menu to be hidden */
    function hideMenu(recurse) {
        if (!$(this).is(':visible'))
            return;
        $('> li > ul:visible', this).each(function() {
            hideMenu.apply(this, [false]);
        });
        if ($(this).is('.jq_menu_root'))
            return;
        var elms = $('> li', this).add($(this).parent());
        elms.removeClass('jq_menu_hover')
            .removeClass('jq_menu_hover_toolbar')
            .find('> a')
            .removeClass('jq_menu_hover')
            .removeClass('jq_menu_hover_toolbar');
        removeEvents(this);
        $(this).hide().find('> .bgiframe').remove();
        var settings = getSettings(this);
        settings.onHide.apply(this);
        /* Recursively hide our parent menus */
        if (recurse == true) {
            $(this).parentsUntil('ul.jq_menu_root')
                   .removeClass('jq_menu_hover').removeClass('jq_menu_hover_toolbar')
                   .not('.jq_menu_root').filter('ul')
                   .each(function() {
                       hideMenu.apply(this, [false]);
                   });
        }
    }

    /* prevent the default (usually following a link) */
    function accessibleClick(e) {
        if ($(this).is('.accessible')) {
            /* Stop the browser from the default link action allowing the 
               click event to propagate to propagate to our LI (itemClick function) */
            e.preventDefault();
        }
    }

    /* trigger a menu click */
    function itemClick(e) {
        e.stopPropagation();
        if ($('> ul', this).size() > 0)
            showMenu.apply(this);
        else {
            if ($(e.target).is('li')) {
                if ($('> a', e.target).not('.accessible').size() > 0) {
                    var lnk = $('> a', e.target).not('.accessible').get(0);
                    if (!lnk.onclick)
                        window.open(lnk.href, lnk.target || '_self');
                    else
                        $(lnk).click();
                }
            }
            hideMenu.apply($(this).parent(), [true]);
        }
    }

    /* -------------------------------------------------------------------- */

    /* public jQuery object method: activate menu */
    $.fn.Menu = function (inSettings) {
        var settings = $.extend({}, arguments.callee.defaults, inSettings);
        return this.each(function() {
            $(this).addClass('jq_menu');
            $(this).addClass('jq_menu_root');
            $(this).css({ display: "block" });
            this.$settings = settings;
            addEvents(this);
            var self = this;
            $(document).bind('click', function() {
                $(self).MenuHide();
            });
            $('li li[ul]', this).append('<span class="rarrow"><img src="/meta/global-image.d/rarrow.gif" alt=""/></span>');
            $('> li[li]', this).prepend('<span class="darrow"><img src="/meta/global-image.d/darrow.gif" alt=""/></span>')
            $('> li', this).not( $('> li:last', this) ).after('<li class="sep">|</li>');
        });
    };
    /* public jQuery object method defaults */
    $.fn.Menu.defaults = {
        activateDelay:   750,
        showDelay:       150,
        hideDelay:       550,
        onShow:          function() { return true; },
        onHide:          function() { return true; },
        onAnimate:       null,
        offset:          2,
        iframe:          $.browser.msie
    };

    /* public jQuery object method: hide menu */
    $.fn.MenuHide = function() {
        return this.each(function() {
            hideMenu.apply(this);
        });
    };

    /* public jQuery object method: show menu */
    $.fn.MenuShow = function() {
        return this.each(function() {
            showMenu.apply(this);
        });
    };
})(jQuery);

$(document).ready(function () {
    $('div#canvas_menu > ul').Menu({
        activateDelay: 0,
        showDelay:     0,
        hideDelay:     550,
        offset:        0,
        onAnimate:     null
    });
});


