【问题标题】:jQuery: Select elements and iterate over them until certain element appearsjQuery:选择元素并遍历它们直到出现某个元素
【发布时间】:2011-12-21 23:51:17
【问题描述】:

我有一个这样的 HTML:

<h2>H2 A</h2>
<h3>H3 A</h3>
<h3>H3 B</h3>
<h2>H2 B</h2>
<h3>H3 C</h3>
<h3>H3 D</h3>

我正在尝试迭代(例如:)一组 H2:找到所有 H3 UNDER H2;然后转到下一个 H2 并执行相同的操作。但我想(可能)递归地做到这一点,并且一般适用于所有标题(即 H+level 和 H+level+1;h3 和 h4、h4 和 h5,等等)。但是到现在我还没有成功。

我的代码如下,我认为使用 nextUntil 可以完成这项工作,但它会使 each 迭代所有元素:

function renderHeadingStructure(level, parent)
{
    $('h'+level)/*.nextUntil('h'+level).*/each(function(i,el){  
        // Copy item name to parent in list - now it is missing creating of an UL :- /
        li = document.createElement('li');
        li.innerHTML = el.innerHTML;
        parent.appendChild(li);

        // Here would be handy something like:
        // -> If crossed over H+level-1 (while going trough H+level)
        // -> then create an ul, recurse and then break

        if(level<6)
          renderHeadingStructure(level+1,li);  
    });
}

结果结构应该是这样的:

<ul>
  <li><a>H2 A</a>
    <ul>
      <li><a>H3 A</a></li>
      <li><a>H3 B</a></li>
    </ul>
  </li>
  <li><a>H2 B</a>
    <ul>
      <li><a>H3 C</a></li>
      <li><a>H3 D</a></li>
    </ul>
  </li>
</ul>

上面代码的结果是:第一个 H2 和所有四个 H3,然后是第二个 H2 和所有四个 H3 - 都在相等的 li。

有人可以给我建议或帮助解决问题吗? 谢谢你

【问题讨论】:

  • 这将是一个很好的面试问题

标签: jquery dom


【解决方案1】:

我在几周前完全做到了这一点。递归并使用 nextUntil()。该插件用于根据“article”中的 hX:s 生成文档大纲,并将列表附加到“body”,如下所示:

$('article').generateDocumentOutline('body');

此处代码:http://code.google.com/p/sleek-php/source/browse/trunk/Sites/SleekBase/Modules/Base/JS/jQuery.generateDocumentOutline.js

编辑:无论您的最高和最低标题是什么,它都有效(因此不限于 h2s 和 h3s)。

Edit2:您可以在此处查看它的使用情况:http://sleekphp.com/docs/(右侧的“跳转到部分”位)。

【讨论】:

  • 就是这样!非常感谢。 (现在我必须弄清楚它是如何工作的 :-)
  • NP :) 好吧,它从文档中的最高标题开始 (doc.find(doc.find(':header')[0].nodeName)) - 假设最高标题首先出现(我相信它总是应该))。然后在循环内部检查当前标题是否有任何比它低 1 的标题 (var nextHeadings = heading.nextUntil('h' + currLevel, 'h' + (parseInt(currLevel, 10) + 1)); ) 如果是这样,则在它们上运行相同的功能,然后将它们运行在低于​​该值的一个,然后低于该值的一个,依此类推,直到没有更低的标题。
  • 我从 H2 开始(H1 只是列表上方的一个),使用:doc.find(doc.find('h2:header')[0].nodeName)parseInt(currLevel, 10) 中的 radix 参数也不是必须的,是吗?
  • 如果您知道您将始终从 h2 开始,您可以删除所有这些:doc.find('h2:header')[0].nodeName 并将其替换为它将始终返回的内容 (h2)。不,不是,但我相信包含它是最佳实践:)(至少根据 JSLint)。编辑:但我认为最好不要修改插件,而是在不包含您不想包含在列表中的标题的容器上运行它。就像在这个页面上一样:sleekphp.com/docs 还有一个 h1,但由于我在 #docs 上运行插件,它只会根据该元素中的标题生成一个列表。
【解决方案2】:

试试这个。这将在 h2 之后拉出所有 h3。我刚刚看到你的评论,但似乎它可能只是做这项工作。

JMax

var $parent = null;
var $parentLI = null;

var $ul = $("<ul/>");

$elements = $("h2, h3");

$elements.each(function() {
   var $self = $(this);
    if ($self.get(0).tagName == "H2"){
        $parent = $self;
        $parentLI = $ul.append("<li> > " + $self.text() + "<ul></ul></li>");
    }
    else if ($self.get(0).tagName == "H3"){
        if ($parent) {
            $parentLI.find("ul").append("<li> &nbsp;&nbsp; > " + $self.text() + "</li>");
        }
    }
});

$parent.parent().append($ul);

$elements.remove();

【讨论】:

  • 感谢您的回答。这段代码创建了以下内容: H2 A:H3 A、H3 B、H3 C、H3 D; H2 B:H3 C、H3 D;而且我不知道如何编辑它以达到我需要的目的。
【解决方案3】:

使用 jQuery 选择 h2 元素并检查下一个元素是否为 h3。将其设为函数并在其内部调用该函数以继续检查即将出现的 h3 元素。

【讨论】:

  • 我应该说的,但上面的代码只是一个例子。所有标题之间实际上有很多元素。谢谢回答
【解决方案4】:

这是我的解决方案:http://jsfiddle.net/RYWwU/4/

var ul = "<ul></ul>";
var li = "<li></li>";
var result = $("#result");

$("h2").each(function()
{
    var heading = $(li).html("<a>" + $(this).text() + "</a>");

    var children = $(this).nextUntil("h2").filter("#container h3");

    heading.append($(ul));
    var sub = heading.find("ul");

    children.each(function()
    {
        sub.append($(li).html("<a>" + $(this).text() + "</a>"));
    });

    heading.appendTo(result);
});

【讨论】:

  • 感谢您的回复。它适用于 H2 和 H3,但不适用于 H4。我试图扩展它 - pastebin.com/98WikaPL 但我再次遇到了我在原始帖子中描述的问题 - 它遍历了所有标题。
猜你喜欢
  • 2011-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-06
  • 2014-03-24
  • 2021-11-10
  • 1970-01-01
相关资源
最近更新 更多