/*
 * 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);

