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,
collapsible: 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!
What I'm Doing
- Welding!! #welding #weld #mikecentola #allstartactical #manstuff #murica #harborfart #fluxcore #bauss instagram.com/p/atZFK-L4rg/ 5 hours ago
- @ExpertDan lol why? in reply to ExpertDan 8 hours ago
- Got personally invited to a reception with #Texas Governor Rick Perry tomorrow in #nyc. What to do what to do 9 hours ago
- Woo hoo down another 2 pounds! 9 hours ago
- Ugh. Sick again. These temperature changes are killing me. That and having two boys who cough in my face all of the time. 10 hours ago
- RT @allstartactical: I’m always losing count. #firearms #guns #gun #shooting #pewpewpew #meme #funny #igguns #igmilitia… http://t.co/APwT48… 10 hours ago
- RT @allstartactical: Three Dee. #3D #print #printing #prototype #3Dprint #firearms #guns #gungeeks #ar15… instagram.com/p/ar8QdPgavk/ 18 hours ago
- Workin my ass off at ridgeway and for what? 1 day ago
- I give up. 1 day ago
- Workin hard! #ryanmatterson #one80shineshop #detail #motorsports #car #bmw #polish #buff instagram.com/p/aqm9ugL4s9/ 1 day ago
Recent Comments
- mehdi on Saving state with the jQuery Accordion Menu
- Gianpiero on Saving state with the jQuery Accordion Menu
- howard on REVIEW: TerraLUX Ministar30M LED Upgrade for Maglite Flashlights
- Marc on Saving state with the jQuery Accordion Menu
- Daniel on Saving state with the jQuery Accordion Menu
Categories
Pages
Business
- Allstar Graphics
- Allstar Tactical
- Elegance by Technotic Media
- Fanboi Clothing
- ihatestickers.com
- Technotic Media Inc.
- True Negative
Social Networking
Archives
- January 2011
- December 2010
- November 2009
- August 2009
- July 2009
- June 2009
- May 2009
- April 2009
- March 2009
- February 2009
- January 2009
- December 2008
- November 2008
- October 2008
- September 2008
- August 2008
- July 2008
- June 2008
- May 2008
- April 2008
- March 2008
- November 2007
- July 2007
- June 2007
- March 2007
July 3rd, 2009 - 06:41
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 });
July 3rd, 2009 - 15:09
Thanks for the correction!
August 13th, 2009 - 06:21
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: “/”});
}
}
}
);
});
August 18th, 2009 - 06:31
Example of this working would be really nice, since I just can’t make it work
August 20th, 2009 - 15:32
I know I know! It’s coming soon. I swear!
August 27th, 2009 - 17:09
Thanks Per Jensen,
I didn’t get the cookie thing to work but your solution works like a charm
September 27th, 2009 - 16:14
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
October 29th, 2009 - 18:55
Hi Mike,
Thanks for the code.
Any news on when you might have a working example?
October 30th, 2009 - 13:06
Working example is up (unofficially) at http://www.truenegative.com
Take a look and let me know what you think!
November 6th, 2009 - 07:05
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
November 18th, 2009 - 18:09
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.
November 18th, 2009 - 18:23
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.
January 11th, 2010 - 03:34
Your site was extremely interesting, especially since I was searching for thoughts on this subject last Thursday.
I’m Out!
September 3rd, 2010 - 11:47
thanks for sharing, just a little bug, pay attention, in the code is written “collapsibe” instead of “collapsible”.
September 23rd, 2010 - 08:09
Thanks, your article saved my day! And another big thanks to HelpSeeker, as it was his posted changes which made it all work.
October 4th, 2010 - 11:20
@maumau Thanks! Fixed the typo
October 17th, 2010 - 15:04
Hi,
thanks for the cue.
I´ve found one bug – when I implemented thi code to my site, it was working fine, but sometimes, the active field collapsed back to “inactive” state. So I was trying to fix it and there is the solution. If you are experiencing the same, set the parameter “Navigation” to false value.
November 27th, 2010 - 02:27
Very useful and thanks very much for sharing.
December 27th, 2010 - 15:10
Any idea on how to have this work per page? If I copy this page into a new page, jq and all, it reads the cookie. If a site uses multiple accordions this is not how it should work.
April 8th, 2011 - 08:50
How can I make this accordion move more smoothly?
It’s ok when it’s opening but when closing a panel it’s not smooth at all.
August 3rd, 2011 - 13:22
Nothing I found here worked for my particular installation. I developed my own way using the index, if anyone finds this useful:
$(document).ready(function() {
$(‘#accordion’).accordion({
autoHeight: false,
collapsible: true,
active: false,
change: function(event,ui) {
var index = ui.options.active;
if (index > -1) {
$.cookie(‘accidx’, index, {expires: 2, path: ‘/’});
}
}
});
if ($.cookie(‘accidx’) > -1) {
var idx = Number($.cookie(‘accidx’));
$(‘#accordion’).accordion(‘option’, ‘animated’, false);
$(‘#accordion’).accordion(‘activate’,idx);
$(‘#accordion’).accordion(‘option’, ‘animated’, ‘slide’);
}
});
September 21st, 2011 - 02:54
Here’s a working example (except for the cookie getter/setter)
jQuery(document).ready(function() {
var selected = readCookie(‘activeMkt’);
var select = -1;
if (selected){
select = parseInt(selected);
}
$( “#accordion” ).accordion({
header: ‘h3′,
autoHeight: false,
navigation: true,
collapsible: true,
alwaysOpen: false,
animated: ‘slide’,
active: select,
change: function(event,ui) {
var sel = ui.newHeader.children(‘a’).attr(‘id’);
if (sel === undefined) {
setCookie(‘activeMkt’,'-1′);
} else {
setCookie(‘activeMkt’,sel);
}
}
});
});
EINS
EIN
ZWEI
ZWE
DREI
DRE
October 1st, 2011 - 10:21
thanks for your sharing,I use accordion menu on my website…
October 2nd, 2011 - 11:14
I am very much new to Jquery. what I want is something very simple. Could anyone please tell me how to achieve this.
I have two menu’s which needs to be ‘remembered’ by the browser.
1. A menu that is hidden initially and shown when clicked on a link
2. I have put ‘help-hints’ allover the site. There is a button to hide the hint icons.
What I want is : Once that main menu is shown, it should stay shown while browsing through the pages. Same with the hint icons. When someone clicks on the link that hides/shows the hint icons, they should get hidden/displayed.
The following is my code :
JQuery :
jQuery(‘.slideout’).click(function() {
jQuery(‘.sf-green’).slideToggle();
jQuery(‘.slideout, .slidein’).toggleClass(‘slidein slideout’);
});
jQuery(‘#infobutton’).click(function(){
jQuery(‘.info_on, .info_off’).toggleClass(‘info_off info_on’);
jQuery(‘.hint, .hintoff’).toggleClass(‘hintoff hint’);
});
HTML
Main Menu
Help »
Any help will be great!
Thank you!
November 23rd, 2011 - 06:32
Thank you so much! you saved my day on implementing this in my website haha love you~
November 25th, 2011 - 08:53
Useful and brilliant thank you for sharing this. save me today this did.
August 3rd, 2012 - 16:02
Just used it today with some edits.
cookie plugin can be found here: https://github.com/carhartl/jquery-cookie
I’ve put it on jsbin for easy cut’n'pasting
It only works in edit mode though,
http://jsbin.com/ekuhap/1/edit
thanks!
August 21st, 2012 - 05:31
Thanks everyone for sharing, I combined a few of these ideas, which let me understand what was is going on.
October 8th, 2012 - 03:16
Simplest solution:
$(function () {
var myact = false;
$( “#myaccordion” ).accordion({
clearStyle: true,
collapsible: true, // allow to close completely
create: function (event, ui) {
//get index in cookie on accordion create event
if (($.cookie(‘saved_index’) != null) && ($.cookie(‘saved_index’) != ‘false’)) {
myact = parseInt($.cookie(‘saved_index’));
}
},
change: function (event, ui) {
//set cookie for current index on change event
myact = ui.options.active;
$.cookie(‘saved_index’, null, { expires: 2, path: ‘/’ }); // session cookie
$.cookie(‘saved_index’, myact, { expires: 2, path: ‘/’ });
},
active: ($.cookie(‘saved_index’) == null) ? 0 : ($.cookie(‘saved_index’) == ‘false’) ? false : parseInt($.cookie(‘saved_index’))
});
});
October 18th, 2012 - 04:18
thanks for your help.if i want do it by myself i have to spend two hour except 5 minutes.
with the best wishes.