// Initialization, you can leave this here or move this somewhere else
$(function(){
	$('ul.jd_menu').jdMenu();
	$(document).bind('click', function() {
		$('ul.jd_menu ul:visible').jdMenuHide();
	});
});

/*
 * jdMenu 1.2.1 (2007-02-20)
 *
 * Copyright (c) 2006,2007 Jonathan Sharp (http://jdsharp.us)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://jdsharp.us/
 *
 * Built upon jQuery 1.1.1 (http://jquery.com)
 * This also requires the jQuery dimensions plugin
 */
(function($) {
    // This method can be removed once it shows up in core
    if (!$.fn.ancestorsUntil) {
        $.fn.ancestorsUntil = function(match) {
            var a = [];
            $(this[0]).parents().each(function() {
                a.push(this);
                return !$(this).is(match);
            });
            return this.pushStack(a, arguments);
        };
    }

    // Settings
    var DELAY = 150;
    var IFRAME = $.browser.msie;
    var CSSR = 'jd_menu_flag_root';
    var CSSB = 'jd_menu_hover_toolbar';
    var CSSH = 'jd_menu_hover';
    var index = 0;

    // Public methods
    $.fn.jdMenu = function() {
        return this.each(function() {
            $(this).addClass(CSSR);
            addEvents(this);
        });
    };

    $.fn.jdMenuHide = function() {
        return this.each(function() {
            hide(this);
        });
    };

    // Private methods
    function addEvents(ul) {
        $('> li', ul).hover(hoverOver, hoverOut).bind('click', click);
    };

    function removeEvents(ul) {
        $('> li', ul).unbind('mouseover').unbind('click', click);
    };

    function hoverOver() {
        var c = $(this).parent().is('.' + CSSR) ? CSSB : CSSH;
        $(this).addClass(c).find('> a').addClass(c);

        if (this.$timer) {
            clearTimeout(this.$timer);
        }
        this.$size = $('> ul', this).size();
        if (this.$size > 0) {
            var ul = $('> ul', this)[0];
            if (!$(ul).is(':visible')) {
                this.$timer = setTimeout(function() {
                    if (!$(ul).is(':visible')) {
                        show(ul);
                    }
                }, DELAY);
            }
        }
    };

    function hoverOut() {
        $(this).removeClass(CSSH).removeClass(CSSB)
			.find('> a')
				.removeClass(CSSH).removeClass(CSSB);

        if (this.$timer) {
            clearTimeout(this.$timer);
        }
        if ($(this).is(':visible') && this.$size > 0) {
            var ul = $('> ul', this)[0];
            this.$timer = setTimeout(function() {
                if ($(ul).is(':visible')) {
                    hide(ul);
                }
            }, DELAY);
        }
    };

    function show(ul) {
        // Hide any existing menues at the same level
        $(ul).parent().parent().find('> li > ul:visible').not(ul).each(function() {
            hide(this);
        });
        addEvents(ul);

        var o = $(ul).offset();
        var bt = o.borderTop;
        var bl = o.borderLeft;

        var x = 0, y = 0;
        var li = $(ul).parent();
        if ($(li).ancestorsUntil('ul.' + CSSR).filter('li').size() == 0) {
            x = $(li).offset($(li).parents('ul.' + CSSR)[0]).left;
            y = $(li).outerHeight();
        } else {
            x = $(li).outerWidth() - (3 * bl);
            y = $(li).offset($(li).parent()).top + bt;
        }

        x = 0;
        y = 38;
        $(ul).css({ left: x + 'px', top: y + 'px' }).show();

        //alert("x: " + x + " - y:" + y);

        if (IFRAME && ($(ul).ancestorsUntil('ul.' + CSSR).filter('li').size() > 0)) {
            // TODO Add in the auto declaration?
            var w = $(ul).outerWidth(); // Needs to be before the frame is added
            var h = $(ul).outerHeight();
            if ($('> iframe', ul).size() == 0) {
                $(ul).append('</iframe>').prepend('<iframe style="position: absolute; z-index: -1;">');
            }
            $('> iframe', ul).css({ opacity: '0',
                left: -bl + 'px',
                top: -bt + 'px',
                width: w + 'px',
                height: h + 'px'
            });
            if (!ul.style.width || ul.$auto) {
                ul.$auto = true;
                $(ul).css({ width: w - (bl * 2) + 'px',
                    height: h - (bt * 2) + 'px',
                    zIndex: '100'
                });
            }
        }
    };

    function hide(ul, recurse) {
        $('> li > ul:visible', ul).each(function() {
            hide(this, false);
        });
        if ($(ul).is('.' + CSSR)) {
            return;
        }

        removeEvents(ul);
        $(ul).hide();
        $('> iframe', ul).remove();

        // If true, hide all of our parent menues
        if (recurse == true) {
            $(ul).ancestorsUntil('ul.' + CSSR)
					.removeClass(CSSH).removeClass(CSSB)
				.not('.' + CSSR).filter('ul')
					.each(function() {
					    hide(this, false)
					});
        }
    };

    function click(e) {
        e.stopPropagation();
        if (this.$timer) {
            clearTimeout(this.$timer);
        }
        if (this.$size > 0) {
            var ul = $('> ul', this)[0];
            if (!$(ul).is(':visible')) {
                show(ul);
            }
        } else {
            if ($(e.target).is('li')) {
                var l = $('> a', this).get(0);
                if (l != undefined) {
                    if (!l.onclick) {
                        window.open(l.href, l.target || '_self');
                    } else {
                        $(l).click();
                    }
                }
            }

            var ul = $(this).parent();
            if (!$(ul).is('.' + CSSR)) {
                hide(ul, true);
            }
        }
    };
})(jQuery);
