30

我正在使用 jQuery 设置一个非常简单的常见问题解答页面。像这样:

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

那么,如何在不添加divs 和 classes 以及诸如此类的情况下,让我的this.next()例程选择问题-that-was-clicked-on 和下一个问题(H2 标题)之间的所有内容?

4

9 回答 9

27

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

$('h2').click(function(){
    $(this).nextUntil('h2').show();
})
于 2010-02-06T22:49:45.673 回答
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");
    });
  });
});

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

注意:这假设问题是同级的。如果不是,它会变得更加复杂。

于 2009-05-14T13:48:29.003 回答
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 列表在语义上更有意义。

于 2009-05-14T14:27:04.837 回答
5

当然!只需做一个while循环。

$('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 中上升一个级别。

于 2009-05-14T14:11:37.027 回答
1

也许这并不能真正回答您的问题,但您可以将每个常见问题解答项目(即每个问题/答案对)包装在一个DIV元素中。这在语义上是有意义的,维护页面的非程序员只需复制一个完整的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();
});
于 2009-05-14T13:39:16.810 回答
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" />');

    } );
} );
于 2013-10-27T04:58:15.163 回答
0

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

我已经把它放到了一个例子中。

给定 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(); 
  }) 
});
于 2009-05-14T16:24:14.073 回答
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
 });
于 2009-05-14T17:26:45.887 回答
-3

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

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

我认为您应该做的是为他们简化流程,并培训他们使用您的方法,否则它将不起作用

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

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

(jQuery 不会修复 'user' 错误)

于 2009-05-14T14:23:56.140 回答