Question

I'm creating an FAQ page where the answer is toggled by clicking on the question. The question is h3 and the answer is several p-elements. Like this:

<h3>The First Question</h3>
<p>Answer Paragraph</p>
<p>Answer Paragraph</p>
<p>Answer Paragraph</p>

<h3>The Second Question</h3>
<p>Answer Paragraph</p>
<p>Answer Paragraph</p>

How can I toggle all p-elements belonging to a certain question? My JS toggles all following p-elements on the page:

$(document).ready(function(){
    $("p").hide();
    $("h3").click(function(){
        $(this).nextAll("p").toggle();
    });
});

I cannot use div's or classes).

Was it helpful?

Solution

The best way to do this is using each and iterating until you get to the next element that should stop the iteration. Returning false during an each stops the iteration. Using filter allows you to check the type of the element in the iteration and respond appropriately.

$(function() {
   $("p").hide();
   $("h3").click(function() {
       $(this).nextAll().each( function() {
           if ($(this).filter('h3').length) {
              return false;
           }
           $(this).filter('p').toggle();
       });
   });
});

OTHER TIPS

I would do it this way:

$(function() {
  $("p").hide();
  $("h3").click(function() {
    $(this).nextAll().each(function() {
      if ($(this).is('h3')) {
        return false;
      }
      $(this).toggle();
    });
  });
});

Returning false from each() ends the chain.

I would also suggest, if possible, structuring your data better to handle this scenario. For example:

<h3 class="question">Why is there no soup for me?</h3>
<div class="answer">
<p>...</p>
<p>...</p>
<p>...</p>
</div>

and then the problem becomes trivial to solve:

$(function() {
  $("div.answer").hide();
  $("h3.question").click(function() {
    $(this).next().toggle();
  });
});

Here is an interesting solution that doesn't use .each()

$("h3").click(function() {

    var idx = $("h3,p").index(this);
    var nextIdx = ($("h3,p").index($(this).nextAll("h3")));
    var nextPs = (nextIdx == -1) ? $("h3,p").length - idx : nextIdx - idx;
    $(this).nextAll("p:lt(" + (nextPs - 1) + ")").toggle();

});

I'm looking for the next Ps by index. Not sure how practical this is, but it was a good exercise.

I would recommend jQuery nextUntil();

$(document).ready(function(){
    $("p").hide();
    $("h3").click(function(){
        $("h3").nextUntil("h3").toggle();
    });
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top