Accordéon jQuery UI qui garde plusieurs sections ouvertes?

93

Je suis peut-être un idiot, mais comment garder plusieurs sections ouvertes dans l'accordéon de l'interface utilisateur jQuery? Les démos ont toutes un seul ouvert à la fois ... Je recherche un système de type de menu réductible.

Marcheur
la source
18
Regardez ce jsfiddle.net/DkHyd
supersuphot
Eh bien, votre plugin est tout simplement parfait! Merci beaucoup, mec!
SexyBeast

Réponses:

94

Cela a été discuté à l' origine dans la documentation de l'interface utilisateur jQuery pour Accordion :

REMARQUE: si vous souhaitez ouvrir plusieurs sections à la fois, n'utilisez pas d'accordéon

Un accordéon ne permet pas d'ouvrir plus d'un panneau de contenu en même temps, et cela demande beaucoup d'efforts. Si vous recherchez un widget permettant d'ouvrir plus d'un panneau de contenu, ne l'utilisez pas. Habituellement, il peut être écrit avec quelques lignes de jQuery à la place, quelque chose comme ceci:

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

Ou animé:

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

"Je suis peut-être un idiot" - Vous n'êtes pas un idiot si vous ne lisez pas la documentation, mais si vous rencontrez des problèmes, cela accélère généralement la recherche d'une solution.

MvanGeest
la source
9
Cette solution ne fait aucun des styles d'accordéon.
forresto
12
De plus, ce n'est pas du tout une solution à la question. Le document d'accordéon et la liste d'options, d'événements, etc. sont tout simplement médiocres. Et au lieu de dire à l'utilisateur "si nous n'avons pas les options pour vous - ne l'utilisez pas!" ils devraient dire "désolé qu'il n'y ait pas encore d'option pour cela, mais nous accueillons tous les contributeurs qui ajoutent des fonctionnalités à notre super plugin"
artgrohe
Le texte que j'ai cité a été supprimé de la documentation. J'ai ajouté un lien vers une version archivée.
MvanGeest
1
Gardez à l'esprit que jQuery UI Accordion fait plus que créer l'effet d'accordéon réel. Il ajoute également beaucoup de balisage d'accessibilité pour les lecteurs d'écran.
Brian
2
Cela n'a aucun sens. Un accordéon peut avoir tous les plis ouverts si les bras du musicien sont éloignés, tous les plis fermés si les moitiés de l'instrument sont ensemble, ou quelque chose entre les deux. Si les mots signifient quelque chose, alors le contrôle de l'interface utilisateur du logiciel d'accordéon devrait permettre toute combinaison de panneaux ouverts et fermés.
birdus
119

Assez 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>
2upmédia
la source
1
A très bien fonctionné. J'ai ajouté create: function(event) { $(event.target).accordion( "activate", false ); }pour commencer effondré.
forresto
2
Impressionnant. Heureux que cela ait fonctionné pour vous. :) J'aime garder les choses aussi simples que possible.
2upmedia du
7
dans jquery-ui 1.10, pour commencer réduit, au lieu de create: function(event) { $(event.target).accordion( "activate", false ); }définir l'option:{active: false}
damko
16
(facepalm) accordéon séparé pour chaque bloc.
Paul Annekov
2
Voici le jsFiddle que j'ai utilisé pour le tester jsfiddle.net/txo8rx3q/1 J'ai également ajouté du CSS pour empêcher une section d'accordéon ouverte de sembler sélectionnée lorsqu'elle est développée
Matthew Lock
77

Publié dans un fil similaire, mais j'ai pensé que cela pourrait également être pertinent ici.

Réaliser cela avec une seule instance de jQuery-UI Accordion

Comme d'autres l'ont noté, le Accordion widget n'a pas d'option API pour le faire directement. Cependant, si pour une raison quelconque vous devez utiliser le widget (par exemple, vous maintenez un système existant), il est possible d'y parvenir en utilisant lebeforeActivate option du gestionnaire d'événements pour subvertir et émuler le comportement par défaut du widget.

Par exemple:

$('#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
    }
});

Voir une démo de jsFiddle

Boaz
la source
6
Merci! C'est la meilleure solution puisque vous n'avez besoin d'aucun changement dans tout votre environnement existant.
artgrohe
Il nécessite jQuery UI 1.9.0+ (Drupal 7 est bloqué avec 1.8.7)
Capi Etheriel
1
Je crois que la classe active a changéui-accordion-header-active
Tim Vermaelen
a très bien fonctionné pour moi, une quantité minimale de refactoring :-)
Darkloki
bonne solution, le seul problème est que cette solution ne prendra pas l'option icône :-)
Tachyons
20

Ou encore plus simple?

<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>
Roman Gudkov
la source
C'est gentil à mon humble avis. Solution facile et elle a résolu les problèmes que j'avais avec les performances de grands ensembles d'articles d'accordéon. Étonnamment, l'initiation d'un grand ensemble d'accordéons fonctionne bien. Merci!
Code Noviciate
14

J'ai fait un plugin jQuery qui a le même look que jQuery UI Accordion et peut garder tous les onglets \ sections ouverts

Vous pouvez le trouver ici

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

fonctionne avec le même balisage

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

Code Javascript

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

MISE À JOUR: le plugin a été mis à jour pour prendre en charge l'option des onglets actifs par défaut

MISE À JOUR: Ce plugin est désormais obsolète.

Anas Nakawa
la source
Excellente solution jamais.
Solution logicielle Trimantra
6

En fait, je cherchais sur Internet une solution à ce problème pendant un certain temps. Et la réponse acceptée donne la bonne réponse «par le livre». Mais je ne voulais pas accepter cela, alors j'ai continué à chercher et j'ai trouvé ceci:

http://jsbin.com/eqape/1601/edit - Exemple en direct

Cet exemple extrait les styles appropriés et ajoute la fonctionnalité demandée en même temps, avec un espace pour écrire, ajoutez votre propre fonctionnalité à chaque clic d'en-tête. Permet également à plusieurs div d'être entre les "h3".

 $("#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();

Code HTML:

<!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>`
Donovan
la source
5

J'ai trouvé une solution délicate. Permet d'appeler la même fonction deux fois mais avec un identifiant différent.

Code JQuery

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

Code HTML

<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>
SpritsDracula
la source
2
Vous feriez mieux d' utiliser un seul sélecteur basé sur le classcomme suggéré par d'autres, cela signifie que vous ne vous répétez pas ( DRY )
Scotty.NET
4

Simple, créez plusieurs div d'accordéon représentant chacun une balise d'ancrage comme:

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

Cela ajoute du balisage. Mais fonctionne comme un pro ...

Azeem
la source
4

Simple: active l'accordéon sur une classe, puis crée des divs avec ceci, comme plusieurs instances d'accordéon.

Comme ça:

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/

Giovan Cruz
la source
1
J'ai essayé toutes les réponses dans le fil et cela fonctionne le mieux. Avec les derniers jquery et jqueryUI, il y a maintenant beaucoup de problèmes de style avec d'autres solutions. Voici la mise à jour 2017 jsfiddle.net/rambutan2000/eqbbgb7g
Geordie
@Geordie Je suis heureux que cela ait aidé.
Giovan Cruz
2

Appelez simplement chaque section de l'accordéon comme son propre accordéon. active: n sera 0 pour le premier (donc il s'affichera) et 1, 2, 3, 4, etc. pour le reste. Puisque chacun est son propre accordéon, ils n'auront tous qu'une seule section, et le reste sera réduit pour commencer.

$('.accordian').each(function(n, el) {
  $(el).accordion({
    heightStyle: 'content',
    collapsible: true,
    active: n
  });
});
Funkodebat
la source
Notez que cela a déjà été suggéré dans la réponse de 2upmedia ci
Boaz
2

Encore plus simple, faites-le étiqueter dans l'attribut de classe de chaque balise li et demandez à jquery de parcourir chaque li pour initialiser l'accordéon.

Mikey
la source
1

Sans l'accordéon jQuery-UI, on peut simplement faire ceci:

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

Et js

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

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

Gayan Dasanayake
la source
0

ouvrez jquery-ui - *. js

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

trouver à l' _eventHandler: function( event ) {intérieur

changement

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

à

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

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

ajouter if (typeof(active) !== 'undefined') {et fermer}

prendre plaisir

Alex
la source
-1

Vous utilisez simplement la fonction jquery each ();

$(function() {
    $( ".selector_class_name" ).each(function(){
        $( this ).accordion({
          collapsible: true, 
          active:false,
          heightStyle: "content"
        });
    });
});
Black Mamba
la source