jQuery:如何选择“从这里到下一个H2”?

时间:2009-05-14 13:29:14

标签: javascript jquery dom jquery-selectors css-selectors

我正在使用jQuery设置一个非常简单的FAQ页面。像这样:

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

这都在一个非常具体的div中,所以我将选择带有$('#faq h2')的标题。简单吧?单击H2,然后使用this.next()显示下一段。

(这个页面的警告是非程序员将维护它,这就是我不使用类的原因:不能保证任何新条目都有正确的类。)

原来如此!问题:

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

那么,如果不添加div和类以及诸如此类的东西,我可以让我的this.next()例程选择点击问题和下一个问题之间的所有内容(H2标题) )?

9 个答案:

答案 0 :(得分:27)

我意识到这是一个老问题,但jQuery 1.4现在有nextUntil。所以这样的事情现在应该有效:

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

答案 1 :(得分:21)

有趣的问题。首先让我说,我认为最好的策略是将整个答案都包含在一个div中,然后问题就变得微不足道了:

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

使用:

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

但话虽如此,没有它,它是可以解决的。

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

不是非常优雅,但它会起作用。

注意:这假设问题是兄弟姐妹。如果它们不是它会变得更复杂。

答案 2 :(得分:7)

使用css样式的 DL列表会不会更有意义?

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

然后使用:

轻松选择
$('+ dd', this); 

这是当前的 dt 选择。

或者只是将每个答案包装在一个div中,因为它在语义上也是有意义的。但是我认为DL列表在语义上更有意义。

答案 3 :(得分:5)

当然!只需做一个循环。

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

这假设您的h2之后只有p标签。如果要添加类似img的内容,可以向while循环添加更多异常。

或者,如果你不关心H2标签之间的什么,你可以检查不等于H2。

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

这将隐藏点击H2之后的所有内容,直到找到下一个H2或者你在dom中达到一个级别。

答案 4 :(得分:1)

也许这并没有真正回答你的问题,但你可以在DIV元素中包装每个FAQ项目(即每个问题/答案对)。这在语义上是有意义的,维护页面的非程序员只需要复制一个完整的DIV(不需要类)。

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

答案 5 :(得分:1)

以防万一仍有人需要答案...... 这也包括该组中的h2行。

这里是我的解决方案适用的示例html:

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

溶液:

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" />');

    } );
} );

答案 6 :(得分:0)

请注意,所选的答案很好,但我正在考虑做类似的事情,所以我加班加点:)

I've put this into an example.

给定HTML:

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

执行以下操作,您将获得答案。我认为它现在是所有解决方案中最优雅的,但我会非常重视其他人的输入。

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

答案 7 :(得分:0)

您也可以在不编辑HTML的情况下执行此操作。这是我刚为此特定目的编写的插件:

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

你可以像这样使用它:

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

答案 8 :(得分:-3)

我不认为你解决问题的策略是正确的你有6个答案可以部分解决你的问题......

但是你最大的问题是你说你不能相信维护者使用div / span / classes等。

我认为你应该做的是简化他们的流程,并训练他们使用你的方法,或 不会 工作。

添加一些你自己的简单标记并为它们解释。

[Q] What happens when you click this link?[/Q]
[A] This marvellous answer appears [/A]

(jQuery不会修复'用户'错误)