开发者

jQuery UI accordion that keeps multiple sections open?

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


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>


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.


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


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>


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.


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/


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>`


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>


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...


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
  });
});


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


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/


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


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜