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/
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.
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.
Resetting through addClass/removeClass/attr will make your accordion looks good visually but it requires 2 clicks to activate previous selected tab.
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
A lot of these seem to be overcomplicated. I achieved what I wanted with just the following:
$(".ui-accordion-content").show();
JSFiddle
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With