//@+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).outerHeight();
					else
						off.left += $(t.parentItem).outerWidth();
					$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() {
	$("#top-navigation").menu2();
});