Menu
02/06 2010

jQuery page recognition menu & accordian

If you are a Front End Developer who gets frustrated, working with back end system where you can never seem to have fine control over the menu design. With the following technique, you should now have an extra option if you can't explain what is required to a back end developer.

There have been a few occasions over the last few years where I wanted to produce a really functional, usable navigation system that just works. What I want is a left aligned vertical navigation list that contains a nested list of links (so it is accessible). It lent itself to being an accordian style of functionality, for which there are 10's of scripts. I've included the simple accordian script in this article but that isn't the main point of it.

That's only the half of it

The real functionality that I want to show you in this article, is the page recognition and how you can use this to make your menu much more usable. Firstly, the following script shows the snippet of html that will structure our menu:

  


As you can see, it is a fairly standard nested list of links with a div around it with an id to make it unique.

Once this was in place and styled, you can see that full nested list. If you want to test this between different pages, you can save the same menu as 'about-us.html' and 'who-we-are.html'. When you navigate between them, there is currently no active class. Of course there isn't, nothing is telling to. This is the bit that should be generated dynamically. You can also achieve this using the jQuery below:

  
$(document).ready(function () {
  var loc = window.location.toString().split("/")
  loc = loc[loc.length - 1]
  $('a[href="' + loc + '"]').addClass('active');
  accordianMenu();
  nestCheck();
});

Ignore the two commented functions for now, these will be added next. Basically, what is happening here, is that we are assigning the current page location via javascripts built in window.location function and splitting it at the '/'. This creates an array of path locations, then discards all but the last one and applies an active class to any links that match this location. Go on, try it!

One step beyond

For usability and style, I wanted to add an accordian to the whole thing, closing up the nested list to hide all child elements and leave only the uppermost list. The top level sections if you like. I have to admit to finding a great slimline script after much hunting around and trying out plugins that just didn't quite do what I wanted.

  
function accordianMenu() {
  $('#primarylinks ul').hide();
  $('#primarylinks ul:first').show();
  $('#primarylinks ul li a').hover(
    function () {
      var checkElement = $(this).next();
      if ((checkElement.is('ul')) && (checkElement.is(':visible'))) {
        return false;
      }
      if ((checkElement.is('ul')) && (!checkElement.is(':visible'))) {
        $('#primarylinks ul ul:visible').slideUp('normal');
        //hug();
        checkElement.slideDown('normal');
        return false;
      }
    }, function () {
      //$('.hug').remove();
    }
  );
}

With a feeling of utter chuffedness, I then realised that in an ideal world, the menus with child elements should remain open if the user was either on the parent page or the child page of a section with a second list below it.

With a mixture of logic, my understanding of iterating through the DOM, the script I made prior to this and pure godlike Intellect 🙂 I came up with the following function to find the current active class, iterate through the parent or child elements and make sure that the current page elements are left open.

  
function nestCheck() {
  var numUlBelow = $('a.active').siblings('ul').size();
  var numUlAbove = $('a.active').parents('ul').size();
  if (numUlBelow >= 1) {
    $('a.active').parent().find('ul').show();
    return false;
  }
  else if (numUlAbove >= 2) {
    $('a.active').parent().parent().parent().find('ul').show();
    return false;
    //alert(numUlAbove);
  }
}

I did have a few headaches getting the function to work in conjunction with the others. The order is very important and once I included the accordian followed by this nestcheck function, I got the effect I was after.

Leave a Reply

Your email address will not be published. Required fields are marked *

This article is in the jquery category. Here are some other related articles also in this category.