//@+leo-ver=4
//@+node:@file menu2.js
//@@language actionscript
//@@encoding utf-8


//@+others
//@+node:plugin
//@+at
// 		menu2 jQuery plugin
// 		usage:
// 		$( ... ).menu2( opt )
// 		select nested (unordered) list and make menu system
// 		options:
// 			panelHandle (string:"ul") = jQuery selector acting as managing container 
// for panel (i.e. ul > li > {panelHandle} > li ...)
// 			itemHandle (string:"li") = jQuery selector acting as managing container 
// for item (i.e. ul > {itemHandle} > ul > li ...)
// 			effect (string:"show") = slide | fade | show
// 			speed (int:350) = show/hide effect speed
// 			delay (int:350) = delay in milliseconds before hiding panel
// 			position (bool:true) = whether to position panels
// 			excludePos (string:"exclude") = css class to be excluded when 
// positioning elements
// 			horizontal (string:"horizontal") = css class of items that are layed out 
// horizontally
// 			active (string:"active") = css class of item that is active
// 		events:
// 			panelHandle triggers events "menu2.open", "menu2.close" and 
// "menu2.position"
// 			itemHandle triggers events "menu2.activate" and "menu2.deactivate"
// 		depends on:
// 			dimensions plugin
// 			jQuery 1.2.6
// 		note:
// 			itemHandles and panelHandles when in active state have css class 
// "active".
//@-at
//@@c
(function($) {

    //@	<< constructor >>
    //@+node:<< constructor >>
    //@+at
    // 		plugin constructor
    // 		each panelHandle and itemHandle is extended with .root property 
    // pointing to menu root
    // 		menu root is extended with .menu2 object
    //@-at
    //@@c
    $.fn.menu2 = function(opt) {

        // support multiple objects in constructor
        if (this.length > 1) {
            this.each(function() { $(this).menu2(opt); });
            return this;
        }


        var $root = this.eq(0),
			root = $root[0];
        var p, i;

        // set defaults
        root.menu2 = opt = $.extend({
            panelHandle: "ul",
            itemHandle: "li",
            effect: "show",
            speed: 350,
            delay: 350,
            position: true,
            excludePos: "exclude",
            horizontal: "horizontal",
            active: "active"
        }, opt);


        /*
        loop through panels
        */
        var $panels = $root.find(opt.panelHandle);
        if (opt.position) {
            // when positioning, ignore panels marked with exclude class and prepare visibility for positioning
            $panels.not("." + opt.excludePos)
				.css({ display: "block", position: "absolute", visibility: "hidden" });
        }
        $panels
			.each(function() {  //this=panelHandle
			    var t = this,
					$t = $(t);
			    t.parentItem = $t.parents(opt.itemHandle)[0];
			    t.parentItem.childPanel = t;
			    t.root = root;

			    t.show = panelShow;
			    t.hide = panelHide;
			    t.hideNow = panelHideNow;

			    // bind hover event handles
			    $t.hover(panelShow, panelHide);

			    // position?
			    if (opt.position && !$t.hasClass(opt.excludePos)) {
			        var off = $(t.parentItem).offset(),
						off1 = $t.offsetParent().offset();
			        off.left -= off1.left;
			        off.top -= off1.top;
			        if ($(t.parentItem).hasClass(opt.horizontal))
			            off.top += $(t.parentItem).height();
			        else
			            off.left += $(t.parentItem).width();
			        $t.css(off).trigger("menu2.position");
			    }


			});
        // now hide panels
        $panels
			.css({ display: "none", visibility: "hidden" });



        /*
        loop through items
        */
        $root.find(opt.itemHandle)
			.each(function() {  //this=itemHandle
			    var t = this,
					$t = $(t);
			    t.root = root;

			    // bind hover event handles
			    $t.hover(itemActivate, itemDeactivate);

			    /*				var $a = $t.find("a").not(opt.panelHandle + " a").get(0);  //only direct children and not from child panels' items
			    if ($a.length)  //get default behavior from nested anchor
			    $t.attr("title", $a.attr("title"))
			    .bind("click", function(evt) { window.location = $a.attr("href"); evt.preventDefault(); });*/
			});

        return this;
    }

    //@-node:<< constructor >>
    //@nl

    //@	<< private members >>
    //@+node:<< private members >>
    //@+at
    // 		private members
    // 		methods that extend panelHandles:
    // 			panelShow
    // 			panelHide
    // 			panelHideNow
    // 		methods that extend itemHandles:
    // 			itemActivate
    // 			itemDeactivate
    // 			itemDeactivateNow
    // 		helpers:
    // 			applyEffect
    // 			clearTimer
    //@-at
    //@@c



    //@+at
    // 		panelHandle extenders
    //@-at
    //@@c

    function panelShow(evt) {
        var m2 = this.root.menu2;
        clearTimer(this);

        $(m2.panelHandle, this.root)
			.filter("." + m2.active)
				.not($(this).parents().andSelf().add($(this).find(m2.panelHandle)))
					.each(panelHideNow);  //hide old panels immediately before showing new one
        applyEffect(
			$(this).filter(":hidden")
				.addClass(m2.active)
				.trigger("menu2.open"),
			m2.effect, true, m2.speed);
        // console.log("panelShow: %o", this);
    }

    function panelHide(evt) {
        var t = this;
        clearTimer(this);
        this.timer = setInterval(function() {
            panelHideNow.call(t);
        }, this.root.menu2.delay);
        // console.log("panelHide: %o", this);
    }

    function panelHideNow() {
        var m2 = this.root.menu2;
        clearTimer(this);
        applyEffect(
			$(this).filter(":visible")
				.removeClass(m2.active)
				.trigger("menu2.close"),
			m2.effect, false, m2.speed);
        // console.log("panelHideNow: %o", this);
    }


    function itemActivate(evt) {
        var m2 = this.root.menu2;
        clearTimer(this);

        $(m2.itemHandle, this.root)
			.filter("." + m2.active)
				.not($(this).parents().andSelf().add($(this).find(m2.itemHandle)))
					.each(itemDeactivateNow);  //deactivate old items immediately before activating new one
        $(this).not("." + m2.active)
			.addClass(m2.active)
			.trigger("menu2.activate");
        if (this.childPanel)
            this.childPanel.show();
        // console.log("itemActivate: %o", this);
    }

    function itemDeactivate(evt) {
        var t = this;
        clearTimer(this);
        this.timer = setInterval(function() {
            itemDeactivateNow.call(t);
        }, this.root.menu2.delay);
        // console.log("itemDeactivate: %o", this);
    }

    function itemDeactivateNow() {
        var m2 = this.root.menu2;
        clearTimer(this);
        $(this).filter("." + m2.active)
			.removeClass(m2.active)
			.trigger("menu2.deactivate");
        if (this.childPanel)
            this.childPanel.hideNow();
        // console.log("itemDeactivateNow: %o", this);
    }



    //@+at
    // 		helpers
    //@-at
    //@@c

    function applyEffect(target, effect, unhide, speed) {
        target.stop();
        switch (effect) {
            case "slide": unhide ? target.slideDown(speed) : target.slideUp(speed);
                break;
            case "fade": unhide ? target.fadeIn(speed) : target.fadeOut(speed);
                break;
            case "show":
            default: unhide ? target.show().css("visibility", "visible") : target.hide().css("visibility", "hidden");
                break;
        }
    }


    function clearTimer(obj) {
        if (obj.timer != null) {
            clearInterval(obj.timer);
            obj.timer = null;
        }
    }



    //@-node:<< private members >>
    //@nl


})(jQuery);
//@-node:plugin
//@-others
//@-node:@file menu2.js
//@-leo





$(function() {
    $("#main-nav ul").menu2();
});