jQuery Plugin: Multi-level Drop Down Menu

March 26, 2009 | Demo | Docs | Download | Github

Introduction

Multi-ddm applies mouseover/mouseouts to a preformatted multi-level list. Like the Single Drop Down Menu, Multi-ddm has Metadata support, so each main list can have it's own special features without multiple function calls, and closes on a timer so mouses going awry won't lose the menu.

Basic Usage

While no parameters are required, it's recommended you add some mouse over CSS classes to the parent and child MO like so:

$(function(){
	$('#multi-ddm').dropDownMenu({timer: 1500, parentMO: 'parent-hover', childMO: 'child-hover1'});
});

The above options will activate the following menu like this:




Dropped IE6 Support

Multi-ddm does function properly in IE6, the javascript itself works. It's a css problem that is causing this project to drop support for IE6. I am very open to suggestions on how to fix this, but it seems that I am at a cross roads, and a new version might bring more eyes to this problem.

Source
/*
 * Multi-level Drop Down Menu 3.0
 * April 17, 2010
 * Corey Hart @ http://www.codenothing.com
 */ 
(function( $, window, undefined ){
	// Needed for IE Compatibility (Closing menus must be done backwards in IE)
	// Ensure that no complications arise from other libraries modifying the 
	// array functionality (and hope that they store the old reverse function into _reverse)
	var el, a = Array.prototype, Reverse = a._reverse || a.reverse;

	// bgiframe is needed to fix z-index problem for IE6 users.
	// For applications that don't have bgiframe plugin installed, create a useless 
	// function that doesn't break the chain
	function emptyfn(){
		return this;
	}

	// Cache common event functions so they aren't instantiated with each event
	function clearSiblings(){
		$( el = this ).children('a').removeClass( $.data( el.parentNode , 'multi-ddm-classname' ) );
	}
	function oldMenus(){
		$( el = this ).hide().siblings('a').removeClass( $.data( el.parentNode.parentNode , 'multi-ddm-classname' ) );
	}

	
	// Expose the drop down menu
	$.fn.dropDownMenu = function( options ) {
		return this.each(function(){
			// Defaults with metadata support
			var $main = $(this), i = 0, $menu, timeout,
				settings = $.extend({
					timer: 500,
					parentMO: undefined,
					childMO: undefined,
					bgiframe: undefined,
					levels: []
				}, options || {}, $.metadata ? $main.metadata() : {}),

				// Check on every initiation, so bgiframe can be loaded after this plugin
				bgiframe = $.fn.bgiframe || $.fn.bgIframe || emptyfn;

			// Loop through each level, attach the bgiframe and store it's classname
			$menu = $main.data( 'multi-ddm-classname', settings.levels[ 0 ] || settings.parentMO || settings.childMO || '' );
			while ( $menu.length > 0 ) {
				$menu = bgiframe.call(
					$menu.find('> li > ul').data( 'multi-ddm-classname', settings.levels[ ++i ] || settings.childMO || '' ),
					settings.bgiframe
				);
			}

			// Use event delegation to track mouse movement across the menu
			$main.delegate( 'li', 'mouseenter.multi-ddm', function(){
				var self = $( el = this );

				if ( timeout ) {
					clearTimeout( timeout );
				}

				// Close old menus and remove hover of non-menus
				Reverse.call( self.siblings('li').find('ul:visible') ).each( oldMenus ).end().each( clearSiblings );

				// Open new menu and remove any lingering hover elements
				self.children('a').addClass( $.data( el.parentNode, 'multi-ddm-classname' ) ).siblings('ul').show()
					.children('li').each( clearSiblings );
			})
			.bind( 'mouseleave.multi-ddm', function(){
				timeout = setTimeout( closemenu, settings.timer );
			});
	
			// Closes all open menus
			function closemenu(){
				// Clear mouseovers
				$main.find('li').each( clearSiblings );

				// Close Menus backwards for IE Compatibility
				Reverse.call( $main.find('ul:visible') ).hide();

				if ( timeout ) {
					clearTimeout( timeout );
				}
			}
			
			// Allows user option to close menus by clicking outside the menu on the body
			$( window.document ).bind( 'click.multi-ddm', closemenu );
		});
	};
})( jQuery, window || this );

Download

Latest: multi-ddm-3.0.zip
Released: April 17, 2010
-Switched to event delegation for smaller footprint and smoother feel
-Removed bgiframe and reverse namespace creation, only taking dropDownMenu namespace
-Removed dependency on numberOfLevels setting, intelligently finds all levels of the tree

Past Release's:
October 1, 2009: multi-ddm-2.1.zip
August 22, 2009: multi-ddm-2.0.zip
March 26, 2009: multi-ddm-1.0.2.zip