21

I'm trying to create an accordion able to expand multiple panels at once. I have tried to find it in the jQuery UI API, but I haven't yet found the proper way.

Please let me know if there is a way of doing this using jQuery UI accordion.

Simon Adcock
  • 3,554
  • 3
  • 25
  • 41
Tarun
  • 1,888
  • 3
  • 18
  • 30
  • 1
    This might help: http://forum.jquery.com/topic/accordion-multiple-sections-open-at-once – techfoobar Mar 29 '13 at 11:41
  • 1
    It is not possible with jQuery UI accordion by design. – Andrei Mar 29 '13 at 11:42
  • @techfoobar Thanks for reference URL, It's seems they have same problem but don't have any proper solution till now. – Tarun Mar 29 '13 at 11:48
  • @Andrei I also believe there is not any way provided by jQuery, But i'm looking if it's possible to extend it. Because in my application jQuery UI is already implemented for other stuffs and for accessibility of widgets. So i don't want to write code my self from scratch or use any other library. – Tarun Mar 29 '13 at 11:55
  • 2
    check this out http://jsfiddle.net/AR57Y/ – rajesh kakawat Mar 29 '13 at 12:22
  • @Rajesh In this case it'll not work in JAWS and other screen readers with shortcut keys, only reason is to use jQuery UI is accessibility. – Tarun Apr 01 '13 at 03:06
  • I improved http://jsfiddle.net/AR57Y to not scroll to the top of the page if you click on the header but not on the triangle icon: http://jsfiddle.net/HotFusionMan/y3vN5/1 – Al Chou Jun 11 '13 at 21:08
  • 2
    possible duplicate of [jQuery UI accordion that keeps multiple sections open?](http://stackoverflow.com/questions/3479447/jquery-ui-accordion-that-keeps-multiple-sections-open) – Simon East Jun 03 '15 at 03:02

3 Answers3

50

As others have noted, the Accordion widget does not have an API option to do this directly. However, if you must use the widget, it is possible to achieve this by using the beforeActivate event handler option to subvert and emulate the default behavior of the widget.

For example:

$('#accordion').accordion({
    collapsible:true,

    beforeActivate: function(event, ui) {
         // The accordion believes a panel is being opened
        if (ui.newHeader[0]) {
            var currHeader  = ui.newHeader;
            var currContent = currHeader.next('.ui-accordion-content');
         // The accordion believes a panel is being closed
        } else {
            var currHeader  = ui.oldHeader;
            var currContent = currHeader.next('.ui-accordion-content');
        }
         // Since we've changed the default behavior, this detects the actual status
        var isPanelSelected = currHeader.attr('aria-selected') == 'true';

         // Toggle the panel's header
        currHeader.toggleClass('ui-corner-all',isPanelSelected).toggleClass('accordion-header-active ui-state-active ui-corner-top',!isPanelSelected).attr('aria-selected',((!isPanelSelected).toString()));

        // Toggle the panel's icon
        currHeader.children('.ui-icon').toggleClass('ui-icon-triangle-1-e',isPanelSelected).toggleClass('ui-icon-triangle-1-s',!isPanelSelected);

         // Toggle the panel's content
        currContent.toggleClass('accordion-content-active',!isPanelSelected)    
        if (isPanelSelected) { currContent.slideUp(); }  else { currContent.slideDown(); }

        return false; // Cancel the default action
    }
});

See a jsFiddle demo

Boaz
  • 19,892
  • 8
  • 62
  • 70
  • Thanks Boaz, I not try it but as per your script it'll defiantly work with accessibility. – Tarun Apr 01 '13 at 03:10
  • @Boaz hey, I've tried implementing this on my page, and now all my content divs always have the same height. Can't figure out what's going on. http://stackoverflow.com/questions/29327520/custom-accordion-content-divs-all-share-same-size-no-idea-why – Miha Šušteršič Mar 29 '15 at 11:44
  • @MihaŠušteršič [Answered in the OP](http://stackoverflow.com/a/29330118/1889273). Basically, the height of the panels can be set by the accordion's [`styleHeight`](http://api.jqueryui.com/accordion/#option-heightStyle) property, which in your case should probably be `styleHeight:'content'`. – Boaz Mar 29 '15 at 14:32
  • +1 Works perfectly! In the line: currContent.toggleClass('accordion-content-active',!isPanelSelected) you missed a semicolon at the end though ;) – Philipp May 28 '15 at 12:52
  • This works in jQuery UI 1.9.2 (released in 2012) which is used in the example fiddle. While it still works in at least 1.10.4, newer versions of jQuery UI will leave open panels in a halfway state when you call the refresh method on the accordion. (Internally the widget uses an index for the active panel, so it's strongly coded to allow a max of 1 panel open at a time). My current approach will probably have to be noting which are open, closing them all, refreshing, then re-opening the ones that had been open before. Lots of animation, but not sure how else to make it work at present. – jinglesthula Aug 19 '16 at 17:25
8

You could write multiple accordions that are stacked and each accordion have only one panel. This way the panels could be individually toggled.

anssi
  • 729
  • 7
  • 9
6

An accordion is, by definition, a set of expanding elements that toggle in a certain way. You don't want that. You just want a set of expanding elements. It's extremely easy to build that with jQuery. It often needs nothing more than this:

$('.my-heading-class').on('click', function() {
   $(this).next('.my-content-class').slideToggle();
});

<div class="my-heading-class">My Heading</div>
<div class="my-content-class">My Content</div>
isherwood
  • 58,414
  • 16
  • 114
  • 157
  • 2
    jQuery UI accordion is not a simple slide toggle, they handle lots of things in accessibility, keyboard shortcuts, focus etc. – Tarun Sep 05 '13 at 07:11
  • True. I didn't mention jQuery UI Accordion. I mentioned accordion functionality in a generic sense, which is what seemed appropriate for the question above. – isherwood Sep 05 '13 at 14:14