Simple Menu is a quick jQuery plugin which aims to be simple, minimally invasive, and provide non complicated, rudimentary functionality without bells and whistles. It is the very script used in this site to provide multilevel drop down menus.

Simple the options are the bare minimum necessary to adapt to the simplicity of needs, you may specify what type of trigger is used (click or hover) and specify callbacks to fire when displaying a menu or hiding a menu. That’s it. The rest of the styling is left up to you, however you decide to do it.

To activate it you’ll need specify the menu to call it upon and the script will handle the positioning:

$(function(){
    $("ul#navigation").mainNav();
});

Refer to the tutorial in the Academy for more information on how it all works and what options are available. It will automatically find second level ul’s inside the children li’s of the top level ul#navigation and position them accordingly. Note that it expects and may even force some elements to relative positioning. Additionally it expects the top level navigation to be horizontal. Works well with my WordPress navigation menus.

The plugin script is as follows:

/**
 * Protect namespace, etc
 */
(function ( $ ) {
    /**
     * create plugin for main nav stuff
     */
    $.fn.mainNav = function( options ) {
        
        // handle settings, if i had any
        var settings = $.extend({
            activator: 'hover',
            callbackIn: null,
            callbackout: null
        }, options );
        
        var showCMD = 'mouseover';
        var hideCMD = 'mouseout';
        
        if( settings.activator != 'hover' ){
            showCMD = settings.activator;
        }
        
        // identify the nav item
        var self = $(this);
        
        // first hide children ul
        self.find("ul").css("visibility","hidden");
        
        
        // get all first level lis
        var lis = self.find("li");
        var tier = lis.find("li");
        var top = self.children("li");
        
        // fire first round positioning
        var pos = function( self, sub, w, sw, h ) {
            
            // do some edge detection
            var ww = $(window).width();
            
            
            // check for second tier
            if( top.filter(self).length == 0  ) {
                
                // detect edge collision and apply
                if( ww < $(self).offset().left + w + sw ) {
                    w=-sw;
                }
                
                // standard tier correction to h
                h = -h
                
            // otherwise first tier
            } else {
                
                
                // edge detect
                if( ww < $(self).offset().left + sw ){
                
                    // aligne right
                    w = w - sw;
                    
                } else {
                
                    w = 0;
                }
                
                // already at appropriate h
                h = 0;
            }
            
            sub.css("marginLeft",w);
            sub.css("marginTop",h);
        };
        
        // execute first round positioning
        lis.each(function(){
            var sub = $(this).children("ul");
        
            // gather dimensions
            var w = $(this).outerWidth();
            var sw = sub.outerWidth();
            var h = $(this).outerHeight();
            
            // fire positioning on this object
            pos( this, sub, w, sw, h );
        });
        
        // show child ul for hovering
        lis.on(showCMD, function(){
            var sub = $(this).children("ul");
            
            sub.css("visibility","");
        
            // gather dimensions
            var w = $(this).outerWidth();
            var sw = sub.outerWidth();
            var h = $(this).outerHeight();
            
            // fire positioning on this object
            pos( this, sub, w, sw, h );
        
            // execute callback in 
            if( settings.callbackIn !== null ){
                settings.callbackIn(this);
            }
        
        }); // end of show function
        
        
        // if not using click, use whatever is already specified
        if( settings.activator != 'click' ){
            lis.on(hideCMD,function(){
            
                $(this).children("ul").css("visibility","hidden");
                
                
                // execute callback out 
                if( settings.callbackOut !== null ){
                    settings.callbackOut(this);
                }
            });
            
        // otherwise handle click out
        } else {
        
            $(document).click(function(e){
                
                if( lis.has("ul:visible").has(e.target).length === 0 ){
                    lis.find("ul").css("visibility","hidden");
                    
                    var tgt = lis.has("ul:visible");
                    
                    // execute callback out 
                    if( settings.callbackOut !== null ){
                        settings.callbackOut(tgt[0]);
                    }
                }
            });
        }
        
        
    };

})(jQuery);

CSS styling is up to you but I will provide what I put together for mine here. To be honest, it’s pretty straight forward.

#mainMenu ul, #mainMenu ul>li {
    display: inline-block;
    margin: 0;
    padding: 0;
    position: relative;
}
#mainMenu ul li a, #mainMenu ul li a:visited, #mainMenu ul li a:active
{
    padding: 15px 10px;
    display: block;
    color: inherit;
}
#mainMenu ul li a:hover, #mainMenu ul li:hover {
    background: beige;
    color: #333;
    text-decoration: none;
}

/** Second tier **/
#mainMenu ul li ul {
    z-index: 99;
    background: beige;
    color: #333;
    position: absolute;
    /*right: 0;*/
}
#mainMenu ul li ul, #mainMenu ul li ul li {
    display: block;
}
#mainMenu ul li ul li {
    position: relative;
}

#mainMenu ul li ul li a {
    display: block;
}
#mainMenu ul li ul li a:hover {
    background: #FFC219;
    border-radius: inherit;
}