2009-07-03 8 views
8

Tworzę stronę FAQ, gdzie odpowiedź jest przełączana przez kliknięcie pytania. Pytanie brzmi: h3, a odpowiedź brzmi: kilka elementów: p. Tak:jQuery nextAll - Kliknij element h, aby przełączyć wszystkie elementy p do następnej h

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

Jak mogę przełączyć wszystkie p -elements należące do pewnego pytanie? Moje JS przełącza wszystko po p -elements na stronie:

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

Nie mogę korzystać div „s lub klasach).

Odpowiedz

16

Najlepszym sposobem na to jest za pomocą każdego i iteracji, aż dojdziesz do następnego elementu, który powinien zatrzymać iteracji. Zwracanie wartości false podczas każdego zatrzymania iteracji. Za pomocą filtra można sprawdzić typ elementu w iteracji i odpowiednio zareagować.

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

Dziękuję bardzo, działa idealnie! – Christoph

+1

Podoba mi się twoje rozwiązanie, ponieważ jest bardziej jQueriesh. – SolutionYogi

+0

Myślę, że to prawdopodobnie ważne, aby pamiętać, że ten kod ukryje tylko tagi akapitów. Jeśli wyślesz tekst bez tagów akapitu lub innych znaczników po tagu h3, to ich nie ukryje. – SolutionYogi

8

chciałbym zrobić to w ten sposób:

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

Wracając fałszywe od siebie() kończy się łańcuch.

Proponowałbym również, jeśli to możliwe, lepsze uporządkowanie danych w celu obsłużenia tego scenariusza. Na przykład:

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

i wtedy problem staje się trywialne rozwiązania:

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

Sprawdzanie zmiennej jest dobry pomysł, nie przyszło mi do głowy. Zgaduję, że utknąłem w trybie jQuery. Możesz również sprawdzić, czy element jest przełączany, jeśli jest coś innego niż akapit, który nie powinien być przełączany. – tvanfosson

+0

Chciałbym poznać powód upadku ... – cletus

+0

cletus - to prawdopodobnie dla twojej literówki z nextall zamiast nextAll i the: zamiast; – ScottE

1

Tutaj jest ciekawym rozwiązaniem, które nie korzysta z .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(); 

}); 

szukam następnego Ps przez indeks. Nie jestem pewien, jak to jest praktyczne, ale było to dobre ćwiczenie.

+0

IMHO, ten kod jest trudniejszy do odczytania. Wolę zaakceptowaną odpowiedź. – SolutionYogi

+0

Według mojego obliczenia, iteracja przez DOM następuje trzykrotnie, aby uniknąć powtarzania elementów akapitu po jednym nagłówku. Głosuję za nieprzystosowaniem. :-) – tvanfosson

+0

Nie ma problemu! Nie sugerowałem, że to było lepsze - byłem ciekawy, czy można to zrobić bez użycia .each(). Dobry punkt powyżej. – ScottE

0

Polecam jQuery nextUntil();

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