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!
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 });
Thanks for the correction!
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: “/”});
}
}
}
);
});
Example of this working would be really nice, since I just can’t make it work
I know I know! It’s coming soon. I swear!
Thanks Per Jensen,
I didn’t get the cookie thing to work but your solution works like a charm
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
Hi Mike,
Thanks for the code.
Any news on when you might have a working example?
Working example is up (unofficially) at http://www.truenegative.com
Take a look and let me know what you think!
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
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.
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.
Your site was extremely interesting, especially since I was searching for thoughts on this subject last Thursday.
I’m Out!