Blog from Saravanan Arumugam

Let us talk about Technologies

Simple jQuery enabled Menu


This paper explains a simple HTML based Menu written with the help of jQuery and CSS.

I have implemented the menu in a MVC 3 application’s default template. However this menu is not specific to MVC 3, its applicable in any Html page.

 

Step 1: Create the Menu and Sub-Menu items

Create the root menu and menu items using <ul> element or with <div> and <table> elements. For simplicity I have made the menu items with hyperlinks pointing to either Home or About page (Home and About pages are created by default with MVC 3)

<nav>
    <ul id="menu">
        <li id="Home">
            @Html.ActionLink("Home", 
                "Index", "Home")
        </li>
        <li id="About">
            @Html.ActionLink("About", 
                "About", "Home")
        </li>
    </ul>
    <ul parentmenu="Home">
        <li>
            @Html.ActionLink("Go to About",
                "About", "Home")
        </li>
        <li>
            @Html.ActionLink("Go to About again",
                "About", "Home")
        </li>
    </ul>
    <ul parentmenu="About">
        <li>
            @Html.ActionLink("Go Home", 
                "Index", "Home")
        </li>
        <li>
            @Html.ActionLink("Go Home Again", 
                "Index", "Home")
        </li>
    </ul>
</nav>

Note that parentmenu attribute is specified on the <ul> element to indicate that it is a sub menu of another menu item. Obviously the <ul> list element not having the parentmenu is the root menu.

In case of MVC 3, this is to be written in Views/Shared/_Layout.cshtml. In Web forms, the code above should be written in the master page.

 

Step 2: Hide the Sub-Menu’s in the default view

We don’t want the submenu to be visible in the default view. To hide it, I used the CSS stylesheet.

ul[parentMenu]
{
    display: none;
    position: fixed;
    z-index: 1;
}

 

Step 3: Set the style for the Menu and Sub-Menus

ul#menu, ul[parentMenu]
{
    clear: left;
    border-bottom: 1px #5C87B2 solid;
    padding: 0 0 0 0;
    position: relative;
    margin: 0;
    text-align: left;
}
 
ul#menu li
{
    display: inline;
    list-style: none;
}
 
ul#menu li#greeting
{
    padding: 10px 20px;
    font-weight: bold;
    text-decoration: none;
    line-height: 2.8em;
    color: #fff;
}
 
ul#menu li a
{
    padding: 10px 20px;
    font-weight: bold;
    text-decoration: none;
    line-height: 2.8em;
    background-color: #666666;
    color: #EFEFEF;
    border-radius: 8px 8px 0 0;
    -webkit-border-radius: 8px 8px 0 0;
    -moz-border-radius: 8px 8px 0 0;
}
 
ul#menu li a:hover
{
    background-color: #9B9B9B;
    text-decoration: none;
}
 
ul#menu li a:active
{
    background-color: #a6e2a6;
    text-decoration: none;
}
 
ul#menu li.selected a
{
    background-color: #fff;
    color: #000;
}
 
ul[parentMenu]
{
    display: none;
    position: fixed;
    z-index: 1;
}
 
ul[parentMenu] li
{
    list-style: none;
    border: 1px solid #e8eef4;
    border-width: thin thin 0 thin;
    background-color: #666666;
    color: #EFEFEF;
    padding: 5px 20px 5px 20px;
}
 
ul[parentMenu] li a
{    
    border-width: thin thin 0 thin;
    background-color: inherit;
    color: #EFEFEF;    
    font-weight: bold;
    text-decoration: none;    
}
 
ul[parentMenu] li:hover
{
    background-color: #9B9B9B;
    text-decoration: none;
}
 
ul[parentMenu] li:active
{
    background-color: #a6e2a6;
    text-decoration: none;
}

 

Step 4: Script to activate the menu

Here’s a full code listing. Code is explained in detail below the listing.

$(document).ready(function () {
    $("ul#menu li").hover(
        function () {
            //1. Slide up any existing menu
            if ($("ul[parentmenu]:visible").length > 0 &&
                $("ul[parentmenu]:visible:first")
                    .attr("parentmenu") != this.id) 
            {
                
                $("ul[parentmenu]:visible").slideUp(200);
            }
 
            //2. Show the Menu
            var subMenu = $("ul[parentmenu='" 
                + this.id + "']");
            subMenu.slideDown(200);
 
            //3. Position the sub menu
            var currentMenuPosition = $(this).offset();
 
            if (currentMenuPosition) {
                subMenu.offset({
                    left: currentMenuPosition.left,
                    top: $("ul#menu").offset().top + $("ul#menu").height()
                });
            }
        },
    //Don't do anything on the hover out
    function () { }
    );
});
 
$(document).click(function () {
    $("ul[parentmenu]").slideUp(200);
});
 
$(document).scroll(function () {
    $("ul[parentmenu]").hide();
});

 

Step 4.1: Handle the hover event for the menu items

$(document).ready(function () {
    $("ul#menu li").hover(
        function () {

$(document).ready() registers a handler to document’s load event.

Next thing to do is to handle hoverin and hoverout of menu list items. $(“ul#menu li”) selects the list items within the <ul> with the name “menu”. hover() method helps handle both the hover in and hover out events. In our case we do nothing in the hover out.

 

Step 4.2: Hide any other visible menu

//1. Slide up any existing menu
if ($("ul[parentmenu]:visible").length > 0 &&
    $("ul[parentmenu]:visible:first")
        .attr("parentmenu") != this.id) 
{
                
    $("ul[parentmenu]:visible").slideUp(200);
}

When the mouse is hovered over the menu name, first thing we do is hide any other menu that is actively visible at the moment. $(“ul[parentmenu]:visible”) selects the visible sub menu (we identify the submenu by searching for a <ul> element with the parentmenu attribute).

 

Step 4.3: Identify and display the menu

//2. Show the Menu
var subMenu = $("ul[parentmenu='" 
    + this.id + "']");
subMenu.slideDown(200);

slideDown() displays the subMenu by sliding it down. 200 is the milliseconds, which indicates the speed of the slide transition.

 

Step 4.4: Position the menu at its place

//3. Position the sub menu
var currentMenuPosition = $(this).offset();
 
if (currentMenuPosition) {
    subMenu.offset({
        left: currentMenuPosition.left,
        top: $("ul#menu").offset().top + $("ul#menu").height()
    });
}

$(this).offset() provides the current position of the menu’s list item. Based on its placement, position the submenu dynamically by setting the submenu’s offset value.

 

Step 4.5: Hide the menu if any click or scroll happens on the page

$(document).click(function () {
    $("ul[parentmenu]").slideUp(200);
});
 
$(document).scroll(function () {
    $("ul[parentmenu]").hide();
});

 

Output

image

Advertisements

3 responses to “Simple jQuery enabled Menu

  1. Carnage January 11, 2013 at 7:38 am

    Hi,
    where is “parentmenu” defined in the “ul” definition above? I get “Warning 3 Validation (XHTML 1.0 Transitional): Attribute ‘parentmenu’ is not a valid attribute of element ‘ul'”
    also, should the script to activate the menu be defined in the master page?
    Thanks very much

    • Saravanan Arumugam January 11, 2013 at 7:47 am

      Please ignore the warning, since its a custom attribute we defined for our purpose.
      Please include the script in a js file and include it in the master page/ shared layout page in case of MVC.

  2. Anil May 24, 2013 at 2:07 pm

    Menu displays at top corner before hover. Fixed issue with this code change in JS
    //2. Show the Menu
    var subMenu = $(“ul[parentmenu='”
    + this.id + “‘]”);

    //3. Position the sub menu
    var currentMenuPosition = $(this).offset();
    subMenu.offset({
    left: currentMenuPosition.left,
    top: $(“ul#menu”).offset().top
    });
    subMenu.slideDown(200);

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: