/*
 * jdMenu 1.4.0 (2008-01-25)
 *
 * 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
 */
$(function() {
	$('ul.jd_menu').jdMenu();
});

(function($){
	$.jdMenu = {
		settings: 	[],
		getSettings: 	function( element ) {
							var t = $(element).parents('ul.jd_menu:eq(0)')[0];
							return this.settings[ t && t.$jdSettings ? t.$jdSettings : 0 ];
						}
	};

	function activateMenu(ul) {
		var ul = $(ul);
		var li = ul.parent();
		ul	.trigger('jdMenuShow')
			.positionBy({ 	target: 	li[0],
							targetPos: 	( li.parent().is('.jd_menu') ? 3 : 1 ),
							elementPos: 0
							});
		li	.addClass('jdm_active')
			// Hide any adjacent menus
			.siblings('li').find('ul:eq(0):visible')
				.each(function(){
					hideMenu( this );
				});
	}

	function hideMenu(ul) {
		$(ul)
			.filter(':not(.jd_menu)')
			.find('> li ul:eq(0):visible')
				.each(function() {
					hideMenu( this );
				})
			.end()
			.hide()
			.trigger('jdMenuHide')
			.parents('li:eq(0)')
				.removeClass('jdm_active jdm_hover')
			.end()
				.find('> li')
				.removeClass('jdm_active jdm_hover');
	}

	function getSettings(element) {
		return $.data( $(element).is('.jd_menu') ? element : $(element).parents('ul.jd_menu')[0], 'jdMenuSettings');;
	}

	// Public methods
	$.fn.jdMenu = function(settings) {
		var settings = $.extend({	activateDelay: 	500,
					showDelay: 		0,
					hideDelay: 		1000
					}, settings);
		return this.filter('ul.jd_menu').each(function() {
			$.data(this, 'jdMenuSettings', settings);
			$('li', this)
				.bind('mouseenter.jdmenu', function() {
					$(this).addClass('jdm_hover');
					var ul = $('ul:eq(0)', this);
					if ( ul.length == 1 ) {
						var me = this;
						clearTimeout( this.$jdTimer );
						this.$jdTimer = setTimeout(function() {
							activateMenu( ul );
						}, getSettings(this).showDelay );
					}
				})
				.bind('mouseleave.jdmenu', function(){
					$(this).removeClass('jdm_hover');
					var ul = $('ul:eq(0)', this);
					if ( ul.length == 1 ) {
						var settings = $.jdMenu.getSettings( this );
						var me = this;
						clearTimeout( this.$jdTimer );
						this.$jdTimer = setTimeout(function() {
							hideMenu( ul );
						}, getSettings(this).hideDelay );
					}
				})
				.bind('click.jdmenu', function(evt) {
					var ul = $('> ul', this);
					if ( ul.length == 1 ) {
						activateMenu( ul );
						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');
							}
						}
					}
					$(this).parent().jdMenuHide();
					evt.stopPropagation();
				})
				.bind('keydown.jdmenu', function(e) {
					if ( e.which == 27 ) {
						if ( !$(this).parent().is('.jd_menu') ) {
							hideMenu( $(this).parent()[0] );
						}
						$(this).parents('li:eq(0)').find('a:eq(0)').trigger('focus');
						return false;
					}
				})
				.find('> a')
					.bind('focus.jdmenu', function() {
						$(this).parents('li:eq(0)').addClass('jdm_hover');
					})
					.bind('blur.jdmenu', function() {
						$(this).parents('li:eq(0)').removeClass('jdm_hover');
					})
					.filter('.accessible')
						.bind('click.jdmenu', function(evt) {
							evt.preventDefault();
						});
		});
	};

	$.fn.jdMenuUnbind = function() {
		$('li', this)
			.unbind('mouseenter.jdmenu mouseleave.jdmenu click.jdmenu keydown.jdmenu')
			.find('> a').unbind('focus.jdmenu blur.jdmenu click.jdmenu');
		return this;
	};

	$.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);
