Javascript jQuery:如何选择";从这里到下一个H2;?

Javascript jQuery:如何选择";从这里到下一个H2;?,javascript,jquery,dom,jquery-selectors,css-selectors,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> 那么,如何在不添加divs和类之类的情况下,让我的this.next()例程选择单击的问题和下一个问题(H2标题)之间的所有内容呢?也许这并不是真正回答您的问题,但您可以包装每个FAQ项目(即每个问题/答案对)在D

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

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

那么,如何在不添加
div
s和类之类的情况下,让我的
this.next()
例程选择单击的问题和下一个问题(H2标题)之间的所有内容呢?

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

HTML:


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

<h2>Question here</h2>
<div>
<p>Answer here</p>
</div>
</h2>Next Question</h2>
...
但话说回来,没有这个问题是可以解决的

$(function() {
  $("h2").click(function() {
    $(this).nextAll().each(function() {
      if (this.tagName == 'H2') {
        return false; // stop execution
      }
      $(this).toggleClass("highlighted");
    });
  });
});
不是非常优雅,但它会起作用


注意:这假设问题是同级问题。如果他们不是,事情会变得复杂得多。

当然!做一个循环

$('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中升级。

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

但是您最大的问题是您说您不能信任维护人员使用div/span/classes等

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

添加一些您自己的简单标记,并为它们进行解释

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

(jQuery不会修复“用户”bug)

使用css样式的DL列表是否更有意义

<dl class="faq">
    <dt>Question?</dt>
    <dd>
         <p>Answer</p>
         <p>Answer</p>
         <p>Answer</p>
    </dd>
</dl>
这是当前的dt选择


或者把每个答案都写在一个div中,因为它在语义上也是有意义的。然而,我认为DL列表在语义上更有意义。

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

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

您也可以在不编辑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
 });

我意识到这是一个老问题,但jQuery1.4现在已经解决了。这样的方法现在应该可以起作用了:

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

以防万一还有人需要答案。。。 这也包括组中的h2线

如果我的解决方案适用的示例html:
text1
自闭症

自闭症

自闭症

自闭症

kjdf asdk kjdf 自闭症

自闭症

自闭症

自闭症

aqdsa

解决方案:
jQuery(函数($){
//定义用于将其包装到自定义div中的组
$('h2')。每个(函数(){
var grpForDiv=[];
var next=$(this.next();
grpForDiv.推(此);
while(next.length!==0&&next!==undefined&&next[0].nodeName!==H2')
{
grpForDiv.push(下一步[0]);
next=next.next();
}       
jQuery(grpForDiv).wrapAll(“”);
} );
} );

所以你想选择第二个h2下的所有“p”,而不选择类选择器?+1,这是一个有趣的问题,也是为了抵制到处添加类和div的诱惑。理想情况下,我想选择h2#1和h2#2之间的所有内容。据我所知,他将加入ULs和各种各样的东西。我想到的一件事是,你需要小心最后一个h2,它没有下一个h2。检查我的答案这里的问题是,维护者将使用WYSIWYG编辑器(FCKEditor),所以我不能指望他对代码做任何事情,除了提出问题,编辑会将答案输入到p’s中。FCKEditor是一个在线所见即所得编辑器,所以我假设你正在构建某种内容管理系统。为什么不直接硬编码DIV和H2元素呢?然后,维护人员只需输入一个标题(将被包装在H2中)和一个答案(将被包装在段落中,或其他任何形式)。我真的无法想象您希望整个HTML页面通过FCKEditor进行编辑的情况……嗯,这是其中一种情况——说来话长,但是基本上有一个很长的页面,没有人想把它作为单独的条目重新输入。@mathias:仅供参考,我最近写了一些类似的东西。在我的例子中,我使用了TinyMCE,但它不是我正在做的CMS。在DIV部分,我不同意你的观点。将每个问题/答案对封装在一个DIV中,而不仅仅是答案,不是更优雅吗?尽管如此,这才是艾琳问题的真正答案!将整个问题/答案包装在div中是一种合理的变化,但是(imho)当你显示/隐藏或突出显示答案时,这就是你应该包装的内容。切换一个div比切换它中的所有元素更有效率。在我看来,在编写HTML时,不应该考虑行为。这就是不引人注目的JavaScript的全部要点:只需编写您想要的HTML,然后编写您想要的JavaScript即可。这就是为什么我认为从语义上来说,把每一对问题/答案都包装起来更可取的原因。这是一个公平的观点,但也是武断和主观的。对我来说,答案本身就是一个语义上有意义的概念,而不是“问题/答案”、“问题”和“问题/答案减去问题”的概念。在我看来,这是定义列表的最佳用途之一。问题是术语,答案是定义
$('+ dd', this); 
<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(); 
  }) 
});
(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
 });
$('h2').click(function(){
    $(this).nextUntil('h2').show();
})
<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" />');

    } );
} );