Soru jQuery: “Buradan sonraki H2'ye kadar” nasıl seçilir?


JQuery ile çok basit bir SSS sayfası hazırlıyorum. Öyle:

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

Hepsi çok özel bir div içinde, bu yüzden $('#faq h2'). Basit, değil mi? H2'yi tıklayın ve kullanın this.next() Bir sonraki paragrafı göstermek için.

(Bu sayfadaki uyarı, programcı olmayan birinin bunu sürdürmesidir, bu yüzden dersleri kullanmıyorum: yeni girişlerin doğru sınıflara sahip olmalarının bir garantisi yoktur.)

Yani! Sorun:

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

Peki nasıl eklemeden divs ve sınıflar ve ne yok, benim this.next() rutine tıklandığında sorulan soru ile bir sonraki soru (H2 başlığı) arasındaki her şeyi seçin.


29
2018-05-14 13:29


Menşei


Yani sınıf seçicisi olmadan ikinci h2'nin altındaki tüm "p" leri seçmek istersiniz? - TStamper
İlginç bir soru için +1 ve her yerde sınıflar ve div'lar ekleme isteğine direnmek için. - Dominic Rodger
İdeal olarak H2 # 1 ve H2 # 2 arasındaki her şeyi seçmek istiyorum. Bildiğim kadarıyla, UL'leri ve her türlü şeyi ortaya koyacaktır. - Eileen
Bana gelen bir şey, bir sonraki h2'ye sahip olmayan son h2 hakkında dikkatli olmanız gerektiğidir. - Dominic Rodger
cevabımı buradan kontrol et stackoverflow.com/a/43836549/4251431 - Basheer AL-MOMANI


Cevaplar:


İlginç bir problem. Öncelikle, en iyi stratejinin bütün cevabı div'a dahil etmeyi düşündüğümü söyleyeyim ve sonra problem çözülmesi önem kazanıyor:

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

ile:

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

Ama söylenen, bu olmadan çözülebilir.

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

Son derece zarif değil ama işe yarayacak.

Not: Bu soruların kardeş olduğunu varsayar. Eğer değilse, çok daha karmaşık hale gelir.


21
2018-05-14 13:48



DIV kısmına katılmıyorum. Her soru / cevap çiftini sadece cevaplardan ziyade DIV içinde sarmak daha zarif değil mi? Bu söyleniyor, bu Eileen'in sorusunun doğru cevabı! - Mathias Bynens
Bütün soru / cevapların bir div içinde sarılması makul bir varyasyondur ama (imho) gösterdiğinizde / gizlediğinizde veya vurguladığınızda Cevap, sarması gereken bu. Bir div geçişi, içindeki tüm öğeleri değiştirmekten daha etkilidir. - cletus
Benim düşünceme göre, HTML’nizi yazarken davranışı düşünmemelisiniz. Bu, göze batmayan JavaScript'in bütün noktasıdır: sadece istediğiniz HTML'yi yazın, ardından istediğinizle birlikte yaptığınız JavaScript'i yazın. Bu yüzden her soru / cevap çiftini sarmak için semantik olarak daha cazip olduğunu düşünüyorum. - Mathias Bynens
Bu adil bir nokta ama aynı zamanda keyfi ve öznel. Bana göre, bir cevap, "Soru / Cevap", "Soru" ve "Soru / Cevap eksi Soru" kavramlarına sahip olmak yerine, kendi başına anlamsal olarak anlamlı bir kavramdır. - cletus
+1 Ben nereye gittiğimi, ama her zamanki gibi, biraz daha güzel ve çok daha hızlı. - cgp


Bunun eski bir soru olduğunu anlıyorum ama jQuery 1.4 şimdi nextUntil. Yani böyle bir şey şimdi çalışmalıdır:

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

27
2018-02-06 22:49



Bu kullanışlı özelliği eski bir soruna eklemek için +1. - cletus
+1 de, teşekkürler! - reto
Değişirseniz daha da iyisi .show() için .toggle()Bu şekilde hem gizlemek hem de işlevsellik göstermek. :) - Timothy Aaron


CSS tarzını kullanmak daha mantıklı olmaz mıydı? DL listesi?

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

Ve sonra kolay seçim kullanarak:

$('+ dd', this); 

bu şu anki dt seçimi.

Ya da her bir cevabı bir div içinde sarın, çünkü bu, anlamsal olarak da anlamlıdır. Ancak bir DL listesinin anlamsal olarak çok daha anlamlı olduğunu düşünüyorum.


7
2018-05-14 14:27



Tamamen katılıyorum. Bu, bence, bir tanım listesinin en iyi kullanımlarından biridir. Soru terimdir, cevap tanımdır. 1! (Yapabilseydim +2 veririm: P) - Erik van Brakel
Etiketin mükemmel bir şekilde kullanılması, ancak editörün içeriğinde kullandığı içeriklerden şüphe duymayacağım. OP'ye gerçekten yardımcı olmamasına rağmen +1, - Samantha Branham
Ooh, bu iyi bir fikir ve eğer bunu sıfırdan yapıyor olsaydım (eski kodun etrafında çalışmak yerine), bu harika bir çözüm. FWIW FCKEditor'ın özelleştirilmesi ve özel kodla (DL'ler, hatta özel klasli / divs / etc gibi) eklenmesi oldukça kolaydır. - Eileen


Emin! Sadece bir süre döngü yapın.

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

Bu, h2'nizden sonra yalnızca p etiketlerinizin olduğunu varsayar. İmg gibi bir şey eklemek istiyorsanız while döngüsüne daha fazla istisna ekleyebilirsiniz.

Veya H2 etiketleri arasında ne olduğunu umursamıyorsanız, H2'ye eşit olmadığını kontrol edebilirsiniz.

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

Bu, H2'in sonraki H2 bulunana kadar tıklandığı ya da dom seviyesine yükseldikten sonra her şeyi gizleyecektir.


5
2018-05-14 14:11





Belki bu soruya gerçekten cevap vermiyor, ancak her bir SSS öğesini (örneğin her soru / cevap çifti) DIV öğesi. Bu, anlamsal bir şekilde mantıklı olacaktır ve sayfanın bakımını yapmayan programcı, tam olarak bir kopyayı kopyalamak zorunda kalacaktır. DIV (derslere gerek yok).

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

1
2018-05-14 13:39



Sorun, denetleyicinin bir WYSIWYG editörü (FCKEditor) kullanmasıdır, bu yüzden H2S soruları yapmak dışında kod ile HERHANGİ bir şeyler yapmasına bağlı kalamam ve editör cevapları p'ye çevirecektir. - Eileen
FCKEditor çevrimiçi bir WYSIWYG editörüdür, bu yüzden bazı türlerde bir içerik yönetim sistemi oluşturduğunuzu farz ediyorum. Neden sadece DIV ve H2 elemanlarını kodlamıyorsunuz? Muhafazakar, daha sonra sadece bir başlığa (bir H2'ye sarılacak) ve bir cevaba (paragraflara ya da herhangi bir şeye sarılacak) girmek zorunda kalacaktı. Gerçekten de, bütün HTML'yi isteyeceğiniz bir durumu hayal bile edemiyorum. sayfa FCKEditor ile düzenlenebilir ... - Mathias Bynens
Eh, bu durumlardan biri - uzun bir hikaye, ama temelde hiç kimse bireysel girişler olarak yeniden giriş yapmak istemeyen mevcut bir verrrrrry uzun sayfa var. - Eileen
@mathias: Sadece FYI, Geçenlerde buna benzer bazı şeyler yazdım. Benim durumumda TinyMCE kullandım ama yaptığım bir CMS değildi. - cletus


Sadece hâlâ bunun için bir cevaba ihtiyacı olan insanlar var ise ... Bu ayrıca gruptaki h2 satırını içerir.

Burada çözümümün çalıştığı örnek html varsa:

<h2> text1 </h2>
<p>asd</p>
<p>asd</p>
<p>asd</p>
<p>asd</p>
<h3>kjdf</h3>
<h2>asdk</h2>
<h3>kjdf</h3>
<p>asd</p>
<p>asd</p>
<p>asd</p>
<p>asd</p>
<h2>aqdsa</h2>

çözüm:

jQuery( function ( $ ) {
//defining groups for wrapping them in custom divs

    $('h2').each( function () {
        var grpForDiv= [];          
        var next = $(this).next();  
        grpForDiv.push(this);
        while ( next.length!==0 && next!== undefined && next[0].nodeName !== 'H2')
            {
            grpForDiv.push(next[0]);
            next = next.next();
            }       
        jQuery(grpForDiv).wrapAll('<div class="Group1" />');

    } );
} );

1
2017-10-27 04:58





Seçilen cevabın iyi olduğuna dikkat edin, ama benzer bir şey yapmaya çalışıyorum, bu yüzden fazla mesai yaptım :)

Bunu bir örnek haline getirdim.

HTML verildiğinde:

<h2>Question 1</h2> 
<p>Answer 1</p> 
<p>Answer 1</p> 
<p>Answer 1</p> 
<h2>Question 2</h2> 
<p>Answer 2</p> 
<p>Answer 2</p> 
<p>Answer 2</p> 
<h2>Question 3</h2> 
<p>Answer 3</p> 
<p>Answer 3</p> 
<p>Answer 3</p> 

Aşağıdakileri yapın ve cevabınızı alacaksınız. ben düşünmek şimdi verilen tüm çözümlerin en zarif hali ama diğerlerine bu konuda biraz değer veriyorum.

jQuery.fn.nextUntilMatch = function(selector) { 
  var result = [];   
  for(var n=this.next();(n.length && (n.filter(selector).length == 0));n=n.next())  
      result.push(n[0]);   
  return $(result); 
} 

$(function() { 
  $('h2~p').hide(); 
  $('h2').click(function() { 
    $(this).nextUntilMatch(':not(p)').toggle(); 
  }) 
});

0
2018-05-14 16:24



Sizin yönteminiz Cletus 'yönteminden yaklaşık% 32.1 daha yavaştır. Sağladığınız HTML'yi göz önünde bulundurarak, hem Cletus'u hem de çözümlerinizi ve Cletus'un çözümünü 10 denemede her bir koşuda yaklaşık 2.28 ms sürdüm. Verilmiş ... burada 1 ms'lik farktan bahsediyoruz ... ama, eğer garip bir durumda milyonlarca elemanın ayrıştırılması gereken elemanlar varsa, Cletus'un çözümü daha çabuk bitecek gibi görünüyor. Onun bir sprinter daha olduğu uzun mesafe koşucu). Gerçi cesur bir çaba. - KyleFarris
Kyle, performansı nasıl ölçersin? - Thomas Stock
İlginç. Muhtemelen n.filter ile gelmek yerine filtrelemek için iç jQuery işlevini kullanmanız gerekir .... - cgp


Bunu, HTML'yi düzenlemeden de yapabilirsiniz. Bu sadece bu özel amaç için yazdığım bir eklentidir:

(function($){
    $.fn.nextUntill = function(expr){
        var helpFunction = function($obj, expr){
            var $siblings = $obj.nextAll();
            var end = $siblings.index( $siblings.filter(expr) );
            if(end===-1) return $([]);
            return $siblings.slice(0, end);
        }
        var retObject = new Array();
        this.each(function(){
            $.merge(retObject, helpFunction($(this), expr));
        });
        return $(retObject);
    }
})(jQuery);

Bunu şu şekilde kullanabilirsiniz:

 $('h2').click(function(){
    $(this).nextUntill('h2').show(); //this will show all P tags between the clicked h2 and the next h2 assuiming the p and h2 tags are siblings
 });

0
2018-05-14 17:26



Bu ilginç. 'Rec' değişkeni ne için?
Oops, bunu kaldırmayı unutma, hiçbir şey yapmaz. - Pim Jager