jQuery UI accordion that keeps multiple sections open?
Asked Answered
S

14

100

I may be an idiot, but how do you keep multiple sections in jQuery UI's accordion open? The demos all have only one open at a time... I'm looking for a collapseable menu type system.

Schall answered 13/8, 2010 at 17:52 Comment(2)
Look at this jsfiddle.net/DkHydFlash
Well, your plugin is just perfect! Thanks a lot, dude!Exposure
H
97

This was originally discussed in the jQuery UI documentation for Accordion:

NOTE: If you want multiple sections open at once, don't use an accordion

An accordion doesn't allow more than one content panel to be open at the same time, and it takes a lot of effort to do that. If you are looking for a widget that allows more than one content panel to be open, don't use this. Usually it can be written with a few lines of jQuery instead, something like this:

jQuery(document).ready(function(){
  $('.accordion .head').click(function() {
      $(this).next().toggle();
      return false;
  }).next().hide();
});

Or animated:

jQuery(document).ready(function(){
  $('.accordion .head').click(function() {
      $(this).next().toggle('slow');
      return false;
  }).next().hide();
});

"I may be an idiot" - You're not an idiot if you don't read the documentation, but if you're having problems, it usually speeds up finding a solution.

Hollie answered 13/8, 2010 at 17:55 Comment(7)
This solution doesn't do any of the accordion styling.Dillydally
Furthermore, this is no solution to the question at all. The accordion docu and list of options, events, etc. is just poor. And instead of telling the user "if we dont have the options for you - dont use it!" they should say "sorry that there is no option for that yet, but we welcome any contributors that add functionality to our great plugin"Khotan
The text I quoted has been removed from the documentation. I added a link to an archived version.Hollie
Keep in mind that jQuery UI Accordion does more than create the actual accordion effect. It also adds lots of accessibility markup for screen readers.Butterfingers
This doesn't make any sense. An accordion can have all the pleats open if the musician's arms are far apart, all the pleats closed if the instrument halves are together, or something in between. If words mean anything, then the accordion software UI control should allow any combination of open and closed panels.Freelance
@Hollie can you please help me to fix this issue #50207463Connie
Given the ease and effectiveness of the solution at https://mcmap.net/q/211072/-jquery-ui-accordion-that-keeps-multiple-sections-open, I don't think this is a valid answer.Leash
H
126

Pretty simple:

<script type="text/javascript">
    (function($) {
        $(function() {
            $("#accordion > div").accordion({ header: "h3", collapsible: true });
        })
    })(jQuery);
</script>

<div id="accordion">
    <div>
        <h3><a href="#">First</a></h3>
        <div>Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.</div>
    </div>
    <div>
        <h3><a href="#">Second</a></h3>
        <div>Phasellus mattis tincidunt nibh.</div>
    </div>
    <div>
        <h3><a href="#">Third</a></h3>
        <div>Nam dui erat, auctor a, dignissim quis.</div>
    </div>
</div>
Heinous answered 19/4, 2012 at 22:45 Comment(10)
Worked great. I added create: function(event) { $(event.target).accordion( "activate", false ); } to start collapsed.Dillydally
Awesome. Glad it worked out for you. :) I like to keep things as simple as possible.Heinous
in jquery-ui 1.10, to start collapsed, instead of create: function(event) { $(event.target).accordion( "activate", false ); } you set the option: {active: false}Liner
Just to get this right: The trick is to put every row in its own accordion, right? May this cause any styling related problems or is it just as applicable as any other solution among the answers?Mateya
(facepalm) separate accordion for each block.Maulstick
This worked for me for a while until I needed to implement a nested sub-accordion. Due to that I switched over to MvanGeest's solution.Zannini
Here's the jsFiddle I used to test it jsfiddle.net/txo8rx3q/1 I also added some CSS to stop an opened accordion section looking selected when it's expandedEvangelist
This is simple , yet ingenius, kudos !!Turnbow
doesn't work with nested accordions: jsfiddle.net/jL9afwq1/1Thermodynamic
Thanks it perfectly works! don't forget to add div guys.Kieger
H
97

This was originally discussed in the jQuery UI documentation for Accordion:

NOTE: If you want multiple sections open at once, don't use an accordion

An accordion doesn't allow more than one content panel to be open at the same time, and it takes a lot of effort to do that. If you are looking for a widget that allows more than one content panel to be open, don't use this. Usually it can be written with a few lines of jQuery instead, something like this:

jQuery(document).ready(function(){
  $('.accordion .head').click(function() {
      $(this).next().toggle();
      return false;
  }).next().hide();
});

Or animated:

jQuery(document).ready(function(){
  $('.accordion .head').click(function() {
      $(this).next().toggle('slow');
      return false;
  }).next().hide();
});

"I may be an idiot" - You're not an idiot if you don't read the documentation, but if you're having problems, it usually speeds up finding a solution.

Hollie answered 13/8, 2010 at 17:55 Comment(7)
This solution doesn't do any of the accordion styling.Dillydally
Furthermore, this is no solution to the question at all. The accordion docu and list of options, events, etc. is just poor. And instead of telling the user "if we dont have the options for you - dont use it!" they should say "sorry that there is no option for that yet, but we welcome any contributors that add functionality to our great plugin"Khotan
The text I quoted has been removed from the documentation. I added a link to an archived version.Hollie
Keep in mind that jQuery UI Accordion does more than create the actual accordion effect. It also adds lots of accessibility markup for screen readers.Butterfingers
This doesn't make any sense. An accordion can have all the pleats open if the musician's arms are far apart, all the pleats closed if the instrument halves are together, or something in between. If words mean anything, then the accordion software UI control should allow any combination of open and closed panels.Freelance
@Hollie can you please help me to fix this issue #50207463Connie
Given the ease and effectiveness of the solution at https://mcmap.net/q/211072/-jquery-ui-accordion-that-keeps-multiple-sections-open, I don't think this is a valid answer.Leash
W
85

Posted this in a similar thread, but thought it might be relevant here as well.

Achieving this with a single instance of jQuery-UI Accordion

As others have noted, the Accordion widget does not have an API option to do this directly. However, if for some reason you must use the widget (e.g. you're maintaining an existing system), 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; // Cancels the default action
    }
});

See a jsFiddle demo

Wondrous answered 30/3, 2013 at 0:29 Comment(11)
Thanks! This is the best solution since you need no change in all your existing environment.Khotan
It requires jQuery UI 1.9.0+ (Drupal 7 is stuck with 1.8.7)Somnus
I believe the active class has changed ui-accordion-header-activeLomond
worked great for me, minimal amount of refactoring :-)Flex
good solution, only issue is this solution won't take icon option :-)Kamerun
Nice solution. I added detection of animate option: var animate = $(this).accordion("option", "animate"); if(selected) animate === false ? currContent.hide() : toString.call(animate) === '[object String]' ? currContent.slideUp({ easing: animate }) : currContent.slideUp(animate); else animate === false ? currContent.show() : toString.call(animate) === '[object String]' ? currContent.slideDown({ easing: animate }) : currContent.slideDown(animate);Tracery
As said by @TimVermaelen, it seems there have been some changes since. Instead of the accordion-content-active class, use ui-accordion-content-active, then the opened sections will get the good aspect. My version of jQuery UI : 1.11.Aulea
I want exactly this, but all collapsed on load. How to achieve that if I do activate:false it shows allCray
Nice solution fot who has already created his jquery ui accordion widget and don't want to re-write all the stuff !Pinder
This is exactly what I was looking for rather than ripping out jQuery UI's accordion. Thank you!Pearlstein
how to handle it if we have more than 1 accordion, because it will open all other accordion when we want to implement it on only 1 accordion ? thanksPeony
T
22

Or even simpler?

<div class="accordion">
    <h3><a href="#">First</a></h3>
    <div>Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.</div>
</div>    
<div class="accordion">
    <h3><a href="#">Second</a></h3>
    <div>Phasellus mattis tincidunt nibh.</div>
</div>         
<div class="accordion">
    <h3><a href="#">Third</a></h3>
    <div>Nam dui erat, auctor a, dignissim quis.</div>
</div>
<script type="text/javascript">
    $(".accordion").accordion({ collapsible: true, active: false });
</script>
Tribal answered 9/11, 2012 at 20:42 Comment(1)
This is nice imho. Easy solution and it solved issues I was having with performance of large sets of accordion items. Surprisingly intialising a large set of accordions performs well. Thanks!Forgo
T
14

I have done a jQuery plugin that has the same look of jQuery UI Accordion and can keep all tabs\sections open

you can find it here

http://anasnakawa.wordpress.com/2011/01/25/jquery-ui-multi-open-accordion/

works with the same markup

<div id="multiOpenAccordion">
        <h3><a href="#">tab 1</a></h3>
        <div>Lorem ipsum dolor sit amet</div>
        <h3><a href="#">tab 2</a></h3>
        <div>Lorem ipsum dolor sit amet</div>
</div>

Javascript code

$(function(){
        $('#multiOpenAccordion').multiAccordion();
       // you can use a number or an array with active option to specify which tabs to be opened by default:
       $('#multiOpenAccordion').multiAccordion({ active: 1 });
       // OR
       $('#multiOpenAccordion').multiAccordion({ active: [1, 2, 3] });

       $('#multiOpenAccordion').multiAccordion({ active: false }); // no opened tabs
});

UPDATE: the plugin has been updated to support default active tabs option

UPDATE: This plugin is now deprecated.

Toxoid answered 26/1, 2011 at 5:47 Comment(1)
Great ever solution.Croom
I
7

Simple: active the accordion to a class, and then create divs with this, like multiples instances of accordion.

Like this:

JS

$(function() {
    $( ".accordion" ).accordion({
        collapsible: true,
        clearStyle: true,
        active: false,
    })
});

HTML

<div class="accordion">
    <h3>Title</h3>
    <p>lorem</p>
</div>
<div class="accordion">
    <h3>Title</h3>
    <p>lorem</p>
</div>
<div class="accordion">
    <h3>Title</h3>
    <p>lorem</p>
</div>

https://jsfiddle.net/sparhawk_odin/pm91whz3/

Industrialist answered 19/6, 2015 at 13:27 Comment(2)
I tried all the answers in the thread and this works the best. With latest jquery and jqueryUI there are a lot of styling issues with other solutions now. Here's the 2017 update jsfiddle.net/rambutan2000/eqbbgb7gAeolis
@Aeolis I'm glad that helped.Industrialist
T
6

Actually was searching the internet for a solution to this for a while. And the accepted answer gives the good "by the book" answer. But I didn't want to accept that so I kept searching and found this:

http://jsbin.com/eqape/1601/edit - Live Example

This example pulls in the proper styles and adds the functionality requested at the same time, complete with space to write add your own functionality on each header click. Also allows multiple divs to be in between the "h3"s.

 $("#notaccordion").addClass("ui-accordion ui-accordion-icons ui-widget ui-helper-reset")
  .find("h3")
    .addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-top ui-corner-bottom")
    .hover(function() { $(this).toggleClass("ui-state-hover"); })
    .prepend('<span class="ui-icon ui-icon-triangle-1-e"></span>')
    .click(function() {
      $(this).find("> .ui-icon").toggleClass("ui-icon-triangle-1-e ui-icon-triangle-1-s").end()


        .next().toggleClass("ui-accordion-content-active").slideToggle();
        return false;
    })
    .next()
      .addClass("ui-accordion-content  ui-helper-reset ui-widget-content ui-corner-bottom")
      .hide();

HTML code:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Toggle Panels (not accordion) using ui-accordion  styles</title>

<!-- jQuery UI  |  http://jquery.com/  http://jqueryui.com/  http://jqueryui.com/docs/Theming  -->
<style type="text/css">body{font:62.5% Verdana,Arial,sans-serif}</style>
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.1/themes/base/jquery-ui.css" rel="stylesheet" type="text/css" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.1/jquery-ui.min.js"></script>


</head>
<body>

<h1>Toggle Panels</h1>
<div id="notaccordion">
  <h3><a href="#">Section 1</a></h3>
  <div class="content">
    Mauris mauris  ante, blandit et, ultrices a, suscipit eget, quam. Integer
    ut neque. Vivamus  nisi metus, molestie vel, gravida in, condimentum sit
    amet, nunc. Nam a  nibh. Donec suscipit eros. Nam mi. Proin viverra leo ut
    odio. Curabitur  malesuada. Vestibulum a velit eu ante scelerisque vulputate.
  </div>
  <h3><a href="#">Section 2</a></h3>
  <div>
    Sed non urna. Donec et ante. Phasellus eu ligula.  Vestibulum sit amet
    purus. Vivamus hendrerit, dolor at aliquet laoreet,  mauris turpis porttitor
    velit, faucibus interdum tellus libero ac justo.  Vivamus non quam. In
    suscipit faucibus urna.
  </div>
  <h3><a href="#">Section 3</a></h3>
  <div class="top">
  Top top top top
  </div>
  <div class="content">
    Nam enim risus, molestie et, porta ac, aliquam ac,  risus. Quisque lobortis.
    Phasellus pellentesque purus in massa. Aenean in pede.  Phasellus ac libero
    ac tellus pellentesque semper. Sed ac felis. Sed  commodo, magna quis
    lacinia ornare, quam ante aliquam nisi, eu iaculis leo  purus venenatis dui.
    <ul>
      <li>List item one</li>
      <li>List item two</li>
      <li>List item  three</li>
    </ul>
  </div>
  <div class="bottom">
  Bottom bottom bottom bottom
  </div>
  <h3><a href="#">Section 4</a></h3>
  <div>
    Cras dictum. Pellentesque habitant morbi tristique  senectus et netus
    et malesuada fames ac turpis egestas. Vestibulum ante  ipsum primis in
    faucibus orci luctus et ultrices posuere cubilia Curae;  Aenean lacinia
    mauris vel est.
    Suspendisse eu nisl. Nullam ut libero. Integer  dignissim consequat lectus.
    Class aptent taciti sociosqu ad litora torquent per  conubia nostra, per
    inceptos himenaeos.
  </div>
</div>

</body>
</html>`
Tedman answered 6/9, 2013 at 18:25 Comment(0)
S
5

I found a tricky solution. Lets call the same function twice but with different id.

JQuery Code

$(function() {
    $( "#accordion1" ).accordion({
        collapsible: true, active: false, heightStyle: "content"
    });
    $( "#accordion2" ).accordion({
        collapsible: true, active: false, heightStyle: "content"
    });
});

HTML Code

<div id="accordion1">
    <h3>Section 1</h3>
    <div>Section one Text</div>
</div>
<div id="accordion2">   
    <h3>Section 2</h3>
    <div>Section two Text</div>
</div>
Swing answered 19/11, 2012 at 12:46 Comment(1)
You are better off going with a single selector based on the class as suggested by others, this then means you don't repeat yourself (DRY)Fishing
H
4

Simple, create multiple accordian div each representating one anchor tag like:

<div>
<div class="accordion">
<a href = "#">First heading</a>
</div>
<div class="accordion">
<a href = "#">First heading</a>
</div>
</div>

It adds up some markup. But works like a pro...

Hindoo answered 30/8, 2014 at 11:35 Comment(0)
S
2

Just call each section of the accordion as its own accordion. active: n will be 0 for the first one( so it will display) and 1, 2, 3, 4, etc for the rest. Since each one is it's own accordion, they will all have only 1 section, and the rest will be collapsed to start.

$('.accordian').each(function(n, el) {
  $(el).accordion({
    heightStyle: 'content',
    collapsible: true,
    active: n
  });
});
Sextuple answered 1/4, 2013 at 15:21 Comment(1)
Note this has already been suggested in 2upmedia's answer belowWondrous
Q
2

Even simpler, have it labeled in each li tag's class attribute and have jquery to loop through each li to initialize the accordion.

Quartz answered 20/8, 2013 at 16:14 Comment(0)
D
2

Without jQuery-UI accordion, one can simply do this:

<div class="section">
  <div class="section-title">
    Section 1
  </div>
  <div class="section-content">
    Section 1 Content: Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.
  </div>
</div>

<div class="section">
  <div class="section-title">
    Section 2
  </div>
  <div class="section-content">
    Section 2 Content: Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.
  </div>
</div>

And js

$( ".section-title" ).click(function() {
    $(this).parent().find( ".section-content" ).slideToggle();
});

https://jsfiddle.net/gayan_dasanayake/6ogxL7nm/

Distinguished answered 12/5, 2017 at 3:20 Comment(0)
B
0

open jquery-ui-*.js

find $.widget( "ui.accordion", {

find _eventHandler: function( event ) { inside

change

var options = this.options,             active = this.active,           clicked = $( event.currentTarget ),             clickedIsActive = clicked[ 0 ] === active[ 0 ],             collapsing = clickedIsActive && options.collapsible,            toShow = collapsing ? $() : clicked.next(),             toHide = active.next(),             eventData = {
                oldHeader: active,
                oldPanel: toHide,
                newHeader: collapsing ? $() : clicked,
                newPanel: toShow            };

to

var options = this.options,
    clicked = $( event.currentTarget),
    clickedIsActive = clicked.next().attr('aria-expanded') == 'true',
    collapsing = clickedIsActive && options.collapsible;

    if (clickedIsActive == true) {
        var toShow = $();
        var toHide = clicked.next();
    } else {
        var toShow = clicked.next();
        var toHide = $();

    }
    eventData = {
        oldHeader: $(),
        oldPanel: toHide,
        newHeader: clicked,
        newPanel: toShow
    };

before active.removeClass( "ui-accordion-header-active ui-state-active" );

add if (typeof(active) !== 'undefined') { and closing }

enjoy

Ben answered 2/12, 2014 at 9:40 Comment(0)
T
0

I know this question specifically asks for jQuery UI.

I always find myself exploring jQuery UI Accordion and then remembering that I can just use the native DETAILS and SUMMARY elements (except for IE11) to implement essentially the same type of feature: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details

Just a reminder in case you forget as often as I do.

Trove answered 20/3, 2021 at 4:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.