views:

9183

answers:

5

Hi Everyone,

I've set up a number of accordions on a page using the jquery accordion plugin so I can implement expand all and collapse all functionality.

Each ID element is it's own accordion and the code below works to close them all no matter which ones are already open:

$("#contact, #address, #email, #sales, #equipment, #notes, #marketingdata")
    .accordion("activate", -1)
;

My problem is with the expand all. When I have them all expand with this code:

$("#contact, #address, #email, #sales, #equipment, #notes, #marketingdata")
    .accordion("activate", 0)
;

Some will contract and some will expand based on whether or not they are previously open.

My idea to correct this was to collapse them all and then expand them all when the expand all was clicked. This code however won't execute properly:

$("#contact, #address, #email, #sales, #equipment, #notes, #marketingdata")
    .accordion("activate", -1)
;
$("#contact, #address, #email, #sales, #equipment, #notes, #marketingdata")
    .accordion("activate", 0)
;

It will only hit the second command and not close them all first. Any suggestions?

+12  A: 

I'm not exactly sure what you're after, but this is my best guess. Out of all your accordions, you want the "open all" button to open all the accordions which are closed (that is, no section is showing). I'd do that by using filter()

$("#contact, #address, #email, #sales, #equipment, #notes, #marketingdata")
    .filter(":not(:has(.selected))")
    .accordion("activate", 0)
;

Is that what you were after?


Edit to explain that filter function:

The filter function just runs your current selection through a filter, removing anything which doesn't match. It has two different forms: one where you pass a regular jQuery query in, like i did above, and the other where you can define a function to filter. If the function returns false, then that element is removed.

In this case the query removes anything which doesn't (:not) have (:has) a child with class "selected" (.selected). I used the .selected selector here because that's what the accordion adds to the currently-open panel.

If you only had one accordion, or you gave each of your accordions some sort of identifier, such as a class name, then you could greatly reduce the entire script. Let's say that for each element you want to turn into an accordion, you give it the class "accord".

$(".accord:not(:has(.selected))").accordion("activate", 0);

This is much more legible and maintainable, since you can easily add more accordions in the future if you wish and this will handle it.

The documentation for filter is here: http://docs.jquery.com/Traversing/filter

nickf
Wow! That's perfect! Can you explain the .filter line of code to me? It works great, but I'd really like to understand what it's doing for future reference (I'm new to jquery). Thanks for your help!Jon
Jon
Great explanation! That'll be a big help in the future.
Jon
nickf - great explanation! I haven't seen nested filters like that before. Very instructive.
Nathan Long
Very good info... answers like this deserve more rep!
TM
Nice moves nickf, if I could vote you up again I would. You make the web a better place.
Tyler
A: 

I've had the same issue and resolved it with some short code leveraging JQuery's each() function to collapse while setting focus to item [0] so normal navigation can resume.

http://spstring.jeffthink.com/?p=49

A: 

Is the code in the original post meant to be integrated with the accordion plugin from jqueryui.com, and if so, how do you do that?

Tom
A: 

jQuery('#accordion').accordion({
active:-1, });

Sil2