27 votes

jQuery: Comment sélectionner "d'ici au prochain H2"?

Je suis la mise en place très simple FAQ de la page avec jQuery. Comme suit:

<h2>What happens when you click on this question?</h2>
<p>This answer will appear!</p>

C'est tout à l'intérieur d'un très spécifique de la div, donc je vais être la sélection de l'en-tête d' $('#faq h2'). Simple, non? Cliquez sur le H2, et utiliser this.next() pour rendre le paragraphe suivant s'afficher.

(L'inconvénient avec cette page, c'est qu'un non-programmeur sera de le maintenir, c'est pourquoi je ne suis pas à l'aide de classes: il n'y a aucune garantie que les nouvelles entrées aurait le droit classes en eux.)

Afin de! Le problème:

<h2>What happens when you click on the next question?</h2>
<p>That is an interesting conundrum.</p>
<p>Because the maintainer is kind of long-winded</p>
<p>and many answers will span a few paragraphs.</p>

Alors, comment, sans l'ajout en divs et les classes et autres joyeusetés, je peux avoir mon this.next() de routine sélectionnez tout ce qui est entre la question-qui-a-été cliqué et la question suivante (H2-tête)?

21voto

John McCollum Points 3270

Je me rends compte que c'est une vieille question, mais jQuery 1.4 a maintenant nextUntil . Donc, quelque chose comme ça devrait maintenant fonctionner:

 $('h2').click(function(){
    $(this).nextUntil('h2').show();
})
 

19voto

cletus Points 276888

Problème intéressant. Tout d'abord, permettez-moi de dire que je pense que la meilleure stratégie consiste à enfermer toute la réponse dans une div, puis le problème devient trivial à résoudre:

 <h2>Question here</h2>
<div>
<p>Answer here</p>
</div>
</h2>Next Question</h2>
...
 

avec:

 $(function() {
  $("h2").click(function() {
    $(this).next().toggleClass("highlighted");
  });
});
 

Mais cela étant dit, il est résoluble sans cela.

 $(function() {
  $("h2").click(function() {
    $(this).nextAll().each(function() {
      if (this.tagName == 'H2') {
        return false; // stop execution
      }
      $(this).toggleClass("highlighted");
    });
  });
});
 

Pas suprêmement élégant mais ça marchera.

Remarque: Cela suppose que les questions sont des frères et sœurs. S'ils ne le sont pas, cela devient beaucoup plus compliqué.

7voto

Dmitri Farkov Points 3743

ne serait-il pas plus judicieux d'utiliser une liste DL de style CSS?

 <dl class="faq">
    <dt>Question?</dt>
    <dd>
         <p>Answer</p>
         <p>Answer</p>
         <p>Answer</p>
    </dd>
</dl>
 

Et puis sélection facile en utilisant:

 $('+ dd', this);
 

ceci étant la sélection dt actuelle.

Ou simplement envelopper chaque réponse dans un div, car cela a également un sens sémantique. Cependant, je pense qu'une liste DL a beaucoup plus de sens sémantiquement.

4voto

gradbot Points 9219

Sûr! Faites juste une boucle de temps.

 $('h2').click(function() {
    var next = $(this).next();
    while (next.length != 0 && next[0].nodeName == 'P')
    {
        next.toggle();
        next = next.next();
    }
});
 

Cela suppose que vous n'avez que les balises p après votre h2. Vous pouvez ajouter plus d'exceptions à la boucle while si vous souhaitez ajouter quelque chose comme img.

Ou si vous ne vous souciez pas de ce qui se trouve entre les balises H2, vous pouvez vérifier qu'il n'est pas égal à H2.

 $('h2').click(function() {
    var next = $(this).next();
    while (next.length != 0 && next[0].nodeName != 'H2')
    {
        next.toggle();
        next = next.next();
    }
});
 

Cela masquera tout après le H2 sur lequel vous avez cliqué jusqu'à ce que le prochain H2 soit trouvé ou que vous montiez d'un niveau dans le dom.

1voto

Mathias Bynens Points 41065

Peut-être que cela ne répond pas vraiment à votre question, mais vous pouvez envelopper chaque élément de la FAQ (c'est-à-dire chaque paire question / réponse) dans un élément DIV . Cela aurait un sens sémantique, et le non-programmeur qui maintient la page devrait simplement copier un DIV complet (pas besoin de classes).

HTML:

 <div id="faq">
 <!-- start FAQ item -->
 <div>
  <h2>Question goes here</h2>
  <p>Answer goes here.</p>
  <p>And here.</p>
  <ul>
   <li>Really, use any HTML element you want here.</li>
   <li>It will work.</li>
  </ul>
 </div>
 <!-- end FAQ item -->
 <!-- start FAQ item -->
 <div>
  <h2>Second question goes here</h2>
  <p>Answer to question two.</p>
 </div>
 <!-- end FAQ item -->
</div>
 

JavaScript (jQuery):

 $('#faq div h2').click(function() {
 $(this).parent().find(':not(h2)').show();
});
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X