/*
 * jdMenu 1.4.1 (2008-03-31)
 * 
 * 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.2.1 (http://jquery.com) This also requires the jQuery
 * dimensions >= 1.2 plugin
 */

// This initializes the menu
$(function() {
	$('ul.jd_menu').jdMenu();
});

(function($) {
	function addEvents(ul) {
		var settings = $.data(
				$(ul).parents().andSelf().filter('ul.jd_menu')[0],
				'jdMenuSettings');
		$('> li', ul).bind('mouseenter.jdmenu mouseleave.jdmenu',
				function(evt) {
					$(this).toggleClass('jdm_hover');
					var ul = $('> ul', this);
					if (ul.length == 1) {
						clearTimeout(this.$jdTimer);
						var enter = (evt.type == 'mouseenter');
						var fn = (enter ? showMenu : hideMenu);
						this.$jdTimer = setTimeout(function() {
							fn(ul[0], settings.onAnimate, settings.isVertical);
						}, enter ? settings.showDelay : settings.hideDelay);
					}
				}).bind('click.jdmenu', function(evt) {
			var ul = $('> ul', this);
			if (ul.length == 1
					&& (settings.disableLinks == true || $(this)
							.hasClass('accessible'))) {
				showMenu(ul, settings.onAnimate, settings.isVertical);
				return false;
			}

			// The user clicked the li and we need to trigger a click for the a
			if (evt.target == this) {
				var link = $('> a', evt.target).not('.accessible');
				if (link.length > 0) {
					var a = link[0];
					if (!a.onclick) {
						window.open(a.href, a.target || '_self');
					} else {
						$(a).trigger('click');
					}
				}
			}
			if (settings.disableLinks
					|| (!settings.disableLinks && !$(this).parent()
							.hasClass('jd_menu'))) {
				$(this).parent().jdMenuHide();
				evt.stopPropagation();
			}
		}).find('> a').bind('focus.jdmenu blur.jdmenu', function(evt) {
			var p = $(this).parents('li:eq(0)');
			if (evt.type == 'focus') {
				p.addClass('jdm_hover');
			} else {
				p.removeClass('jdm_hover');
			}
		}).filter('.accessible').bind('click.jdmenu', function(evt) {
			evt.preventDefault();
		});
	}

	function showMenu(ul, animate, vertical) {
		var ul = $(ul);
		if (ul.is(':visible')) {
			return;
		}
		ul.bgiframe();
		var li = ul.parent();
		ul.trigger('jdMenuShow').positionBy({
			target : li[0],
			targetPos : (vertical === true || !li.parent().hasClass('jd_menu')
					? 1
					: 3),
			elementPos : 0,
			hideAfterPosition : true
		});
		if (!ul.hasClass('jdm_events')) {
			ul.addClass('jdm_events');
			addEvents(ul);
		}
		li.addClass('jdm_active')
				// Hide any adjacent menus
				.siblings('li').find('> ul:eq(0):visible').each(function() {
					hideMenu(this);
				});
		if (animate === undefined) {
			ul.show();
		} else {
			animate.apply(ul[0], [true]);
		}
	}

	function hideMenu(ul, animate) {
		var ul = $(ul);
		$('.bgiframe', ul).remove();
		ul.filter(':not(.jd_menu)').find('> li > ul:eq(0):visible')
				.each(function() {
					hideMenu(this);
				}).end();
		if (animate === undefined) {
			ul.hide()
		} else {
			animate.apply(ul[0], [false]);
		}

		ul.trigger('jdMenuHide').parents('li:eq(0)')
				.removeClass('jdm_active jdm_hover').end().find('> li')
				.removeClass('jdm_active jdm_hover');
	}

	// Public methods
	$.fn.jdMenu = function(settings) {
		// Future settings: activateDelay
		var settings = $.extend({ // Time in ms before menu shows
			showDelay : 200,
			// Time in ms before menu hides
			hideDelay : 500,
			// Should items that contain submenus not
			// respond to clicks
			disableLinks : false
				// This callback allows for you to animate menus
				// onAnimate: null
		}, settings);
		if (!$.isFunction(settings.onAnimate)) {
			settings.onAnimate = undefined;
		}
		return this.filter('ul.jd_menu').each(function() {
			$.data(this, 'jdMenuSettings', $.extend({
				isVertical : $(this).hasClass('jd_menu_vertical')
			}, settings));
			addEvents(this);
		});
	};

	$.fn.jdMenuUnbind = function() {
		$('ul.jdm_events', this).unbind('.jdmenu').find('> a')
				.unbind('.jdmenu');
	};
	$.fn.jdMenuHide = function() {
		return this.filter('ul').each(function() {
			hideMenu(this);
		});
	};

	// Private methods and logic
	$(window)
			// Bind a click event to hide all visible menus when the document is
			// clicked
			.bind('click.jdmenu', function() {
				$('ul.jd_menu ul:visible').jdMenuHide();
			});
})(jQuery);
