Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery UI Accordion Expand/Collapse All

I'm using the jQuery UI Accordion (which does not allow more than one item open at a time) on a project. Using accordion is appropriate since I usually do only want one panel open at a time.

However, I need to offer an "Expand All" link which switches to "Collapse All" when clicked. I don't want to custom write near-identical accordion functionality around this one requirement, so I'd like some JS that will achieve this whilst keeping the Accordion component in use.

Question: What JavaScript/jQuery is required to achieve this whilst still using the jQuery UI "Accordion" component to power the standard functionality?

Here's a fiddle: http://jsfiddle.net/alecrust/a6Cu7/

like image 580
AlecRust Avatar asked Oct 11 '12 15:10

AlecRust


People also ask

How do you expand all accordions?

If you want to expand a specified item of Accordion, you need to set the isExpand parameter to true and specify the index of the corresponding accordion pane in index parameter. The index of the HTML 5 Accordion items is starting from 0.

How can we make accordion dynamically using jQuery?

Your append string needs to be terminated with single quotes since you are using double quotes with it. Also you need to include Jquery library. If you are using the jquery accordion you also need to include the Jquery UI library. Also your html is a bit off, here is a working example.

How do you reset an accordion?

Resetting through addClass/removeClass/attr will make your accordion looks good visually but it requires 2 clicks to activate previous selected tab.


2 Answers

As discussed in the jQuery UI forums, you should not use accordions for this.

If you want something that looks and acts like an accordion, that is fine. Use their classes to style them, and implement whatever functionality you need. Then adding a button to open or close them all is pretty straightforward. Example

HTML

By using the jquery-ui classes, we keep our accordions looking just like the "real" accordions.

<div id="accordion" class="ui-accordion ui-widget ui-helper-reset">     <h3 class="accordion-header ui-accordion-header ui-helper-reset ui-state-default ui-accordion-icons ui-corner-all">         <span class="ui-accordion-header-icon ui-icon ui-icon-triangle-1-e"></span>         Section 1     </h3>     <div class="ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom">         Content 1     </div> </div>​ 

Roll your own accordions

Mostly we just want accordion headers to toggle the state of the following sibling, which is it's content area. We have also added two custom events "show" and "hide" which we will hook into later.

var headers = $('#accordion .accordion-header'); var contentAreas = $('#accordion .ui-accordion-content ').hide(); var expandLink = $('.accordion-expand-all');  headers.click(function() {     var panel = $(this).next();     var isOpen = panel.is(':visible');      // open or close as necessary     panel[isOpen? 'slideUp': 'slideDown']()         // trigger the correct custom event         .trigger(isOpen? 'hide': 'show');      // stop the link from causing a pagescroll     return false; }); 

Expand/Collapse All

We use a boolean isAllOpen flag to mark when the button has been changed, this could just as easily have been a class, or a state variable on a larger plugin framework.

expandLink.click(function(){     var isAllOpen = $(this).data('isAllOpen');      contentAreas[isAllOpen? 'hide': 'show']()         .trigger(isAllOpen? 'hide': 'show'); }); 

Swap the button when "all open"

Thanks to our custom "show" and "hide" events, we have something to listen for when panels are changing. The only special case is "are they all open", if yes the button should be a "Collapse all", if not it should be "Expand all".

contentAreas.on({     // whenever we open a panel, check to see if they're all open     // if all open, swap the button to collapser     show: function(){         var isAllOpen = !contentAreas.is(':hidden');            if(isAllOpen){             expandLink.text('Collapse All')                 .data('isAllOpen', true);         }     },     // whenever we close a panel, check to see if they're all open     // if not all open, swap the button to expander     hide: function(){         var isAllOpen = !contentAreas.is(':hidden');         if(!isAllOpen){             expandLink.text('Expand all')             .data('isAllOpen', false);         }      } });​ 

Edit for comment: Maintaining "1 panel open only" unless you hit the "Expand all" button is actually much easier. Example

like image 72
Sinetheta Avatar answered Oct 03 '22 13:10

Sinetheta


A lot of these seem to be overcomplicated. I achieved what I wanted with just the following:

$(".ui-accordion-content").show(); 

JSFiddle

like image 35
Charles Clayton Avatar answered Oct 03 '22 12:10

Charles Clayton