11549 sujets

JavaScript, DOM et API Web HTML5

Bonjour,

Je cherche à créer un script accordéon fonctionnant avec tous les éléments disposant de la classe .accordion. Jusque là, tout va bien.

Ensuite, j'ai tenté de rendre indépendant les accordéons les uns des autres, tout en utilisant le même code, mais j'ai échoué pour l'instant.

Voici le cœur du code :
$('[class^="accordion"] > a').click(function(e) {
$('[class^="accordion"] > *:nth-child(even)').slideUp();
if(!$(this).next().is(':visible')) {
	$(this).next().slideDown();
}
	e.preventDefault();
});

Voici une page d'exemple pour tester : Accordion
Modifié par Olivier C (11 Mar 2015 - 12:27)
Modérateur
Le mieux serait d'instancier un objet par accordéon.

En créant un objet en JS directement ou au travers de la création de plugin jQuery.

Il faudrait aussi repenser la structure. Même si ce n'est pas impossible avec cete structure, c'est passablement d'ennuis auxquels tu t'exposes.

Exemple (sans regard envers l'accessibilité de la chose):


<ul class="accordion">
  <li class="accordion-item">
    <h3 class="accordion-title">Blah</h3>
    <div class="accordion-content">
      Blah blah blah
    </div>
  </li>
  <li class="accordion-item">
    <h3 class="accordion-title">Blah</h3>
    <div class="accordion-content">
      Blah blah blah
    </div>
  </li>
  <li class="accordion-item">
    <h3 class="accordion-title">Blah</h3>
    <div class="accordion-content">
      Blah blah blah
    </div>
  </li>
</ul>



function Accordion(element){
  this.$el = $(element);
  var self = this;
  this.$el.on('click', '.accordion-title', function(e){
    e.preventDefault();
    self.click(this);
  });
}
Accordion.prototype = {
  click: function(el){
    var $accordionContent = $(el).parents('.accordion-item');
    if ($accordionContent.hasClass('active')){
      $accordionContent.removeClass('active');
    }
    else {
      this.$el.find('.accordion-item.active').removeClass('active');
      $accordionContent.addClass('active')
    } 
  }
};

$('.accordion').each(function(){
  new Accordion(this);
});



.accordion-content {
  display: none;
}
.accordion-item.active .accordion-content {
  display: block;
}


Et un pen d'exemple : http://codepen.io/anon/pen/jEeMeJ
kustolovic a écrit :
Le mieux serait d'instancier un objet par accordéon.
En créant un objet en JS directement ou au travers de la création de plugin jQuery.

Ouf ! Oui certainement, mais j'ai du mal à suivre. Quand à ton code js : celui-ci fonctionne parfaitement, mais j'ai beaucoup de mal à le comprendre...

Bon, je vais essayer de comprendre tant bien que mal son fonctionnement et tenter de partir de celui-ci pour l'adapter selon mes besoins... Merci.
Bon, finalement - et sans remettre en cause tout mon code - j'ai trouvé la solution.

Au lieu de cette sélection généraliste qui posait problème :
$('[class^="accordion"] > *:nth-child(even)').slideUp();

Je l'ai inclu dans la méthode .siblings() :
$(this).siblings('[class^="accordion"] > *:nth-child(even)').slideUp();