31
May
09

Saving state with the jQuery Accordion Menu

I have been working on the new True Negative website pretty much non-stop lately and I’m using several differernt things from the jQuery JavaScript library. One of these is the jQuery Accordion Menu, from their User Interface library. It’s a great simple menu that can be implemented with very little javascript code.

One thing that it doesn’t inherently support is saving the state between webpages, which is something I had wanted since I’m using it as a menu, not just for content display. Functionally, I knew what had to be done in order to get it to save state. It was obvious that I needed to use cookies and some quick javascript to save what menu was open. I then came across the jQuery Cookie plugin, which really simplifies working with cookies in jQuery.

Setting a cookie with the plugin is as simple as follows:

$.cookie('cookiename', 'cookiecontents');

The accordion menu has an event change attribute, which can be set to a function or just inline code. Using both this feature and the cookie plugin, it was very simple to write the code that I needed in order to get the result I wanted. Here is the code and I will explain it below:

// accordion menu
$('#menu').accordion({
	header: 'h3',
	navigation: true,
	active: '.selected',
	autoHeight: false,
	clearStyle: true,
	collapsibe: true,
	alwaysOpen: false,
	animated: 'slide',
	change: function(event,ui) {
		var hid = ui.newHeader.children('a').attr('id');
	if (hid === undefined) {
		$.cookie('menustate', null);
	} else {
		$.cookie('menustate', hid, { expires: 2 });
	}
}
});

// check cookie for accordion state
if($.cookie('menustate')) {
	$('#menu').accordion('option', 'animated', false);
	$('#menu').accordion('activate', $('#' + $.cookie('menustate')).parent('h3'));
	$('#menu').accordion('option', 'animated', 'slide');
}

The first section is pretty straightforward. It defines and applies the accordion menu to a div tag with an id of menu. All of the various options are laid out in the Accordion docs and I just set some of the standard ones in order to get the look and feel that I wanted. The important part is the change option:

change: function(event,ui) {
		var hid = ui.newHeader.children('a').attr('id');
	if (hid === undefined) {
		$.cookie('menustate', null);
	} else {
		$.cookie('menustate', hid, { expires: 2 });
	}

Here you can see that I check the value of the menu that is open to see if it is undefined, which would mean the menu is closed. If it is open, it will have a value in there, so I store that in a cookie called “menustate” for use when the page is reloaded.

// check cookie for accordion state
if($.cookie('menustate')) {
         $('#menu').accordion('option', 'animated', false);
         $('#menu').accordion('activate', $('#' + $.cookie('menustate')).parent('h3'));
         $('#menu').accordion('option', 'animated', 'slide');

Upon page reload I have it check the “menustate” cookie to see if it has been set or not. If it is, I first turn off the animation so the visitor does not see it open again, then I call the activate method to open the one with the id that is stored in the cookie. Lastly, I reenable the animation. It works great!

Unfortunately, I have no completed the True Negative site yet, so I do not have an example of this working. As soon as I finish the site, I’ll update this blog post with a link to it. Hope this helps anyone trying to do this in a simple way. Thanks for reading!


13 Responses to “Saving state with the jQuery Accordion Menu”


  1. 1 drewho Jul 3rd, 2009 at 6:41 AM

    cheers for this, saved my bacon

    you just need path: ‘/’ in the part that writes, or you end up with multiple cookies

    $.cookie(‘menustate’, hid, { path: ‘/’, expires: 2 });

  2. 2 mikecentola Jul 3rd, 2009 at 3:09 PM

    Thanks for the correction! :)

  3. 3 Per Jensen Aug 13th, 2009 at 6:21 AM

    Many thanks for sharing.

    The variable ‘hid’ never did get a value in my setup (Ubuntu 9.04 Firefox 3.013, jQuery 1.3.2, ui 1.7.2). I have tried different things. this works for me:

    jQuery(document).ready(function(){
    var drawer = jQuery.cookie(‘accdrawer’);
    if(drawer === undefined) {
    drawer = “0″;
    }

    jQuery(‘#accordion’).accordion({
    header: ‘h3′,
    navigation: false,
    active: parseInt(drawer),
    autoHeight: false,
    clearStyle: true,
    collapsibe: true,
    alwaysOpen: true,
    animated: ‘slide’,
    change: function(event,ui) {
    var index = jQuery(this).find(“h3″).index(ui.newHeader[0]);
    if (index > -1) {
    jQuery.cookie(“accdrawer”, index, {path: “/”});
    }
    }
    }
    );
    });

  4. 4 Roman Aug 18th, 2009 at 6:31 AM

    Example of this working would be really nice, since I just can’t make it work :(

  5. 5 mikecentola Aug 20th, 2009 at 3:32 PM

    I know I know! It’s coming soon. I swear! :)

  6. 6 Taeke Aug 27th, 2009 at 5:09 PM

    Thanks Per Jensen,

    I didn’t get the cookie thing to work but your solution works like a charm

  7. 7 Help Seeker Sep 27th, 2009 at 4:14 PM

    Per Jensesn,
    Thanks for your suggstion. It seems to e working for un-nested accordions, but for nested I’m having trouble as is collapses all as soon as I click on the sub-accordion. Here’s my code:

    jQuery(document).ready(function(){
    var drawer = jQuery.cookie(‘accdrawer’);
    if(drawer == undefined) {
    drawer = “0″;
    }
    jQuery(‘#accordion2′).accordion({
    header: ‘h3′,
    navigation: false,
    active: parseInt(drawer),
    autoHeight: false,
    clearStyle: true,
    collapsible: true,
    alwaysOpen: true,
    animated: ‘slide’,
    change: function(event,ui) {
    var index = jQuery(this).find(“h3″).index(ui.newHeader[0]);
    if (index > -1) {
    jQuery.cookie(“accdrawer”, index, {path: “/”});
    }
    }
    });
    });

    Main

    Search
    Test
    Review

    Database

    Summary

    Dashboard

    Summary

  8. 8 Stuart Oct 29th, 2009 at 6:55 PM

    Hi Mike,
    Thanks for the code.
    Any news on when you might have a working example?

  9. 9 mikecentola Oct 30th, 2009 at 1:06 PM

    Working example is up (unofficially) at http://www.truenegative.com

    Take a look and let me know what you think!

  10. 10 kibi Nov 6th, 2009 at 7:05 AM

    Thanks for article.
    How to store nested list accordions ?
    In you example http://www.truenegative.com you have 1 level accordion with
    Here it is nested list accordion – http://blog.evaria.com/wp-content/themes/blogvaria/jquery/index-multi.php
    Any ideas?

    Thank you for answer :-)

  11. 11 Parker Hillius Nov 18th, 2009 at 6:09 PM

    Setting the navigation attribute to true will let the accordion automatically handle this for you.

    From jQuery Documentation:

    navigation

    Type:Boolean
    Default:false

    If set, looks for the anchor that matches location.href and activates it. Great for href-based state-saving. Use navigationFilter to implement your own matcher.

  12. 12 mikecentola Nov 18th, 2009 at 6:23 PM

    Right, that will work for having the anchor tag in the address bar. Using a cookie circumvents that. I can’t remember why I didn’t want it in the address bar, but it will come to me haha.

  13. 13 Cool Dude Jan 11th, 2010 at 3:34 AM

    Your site was extremely interesting, especially since I was searching for thoughts on this subject last Thursday.

    I’m Out! :)

Leave a Reply




What I'm Doing...

Folding@Home


Folding@Home