Javascript *整个*文档中某个元素后的下一个元素

Javascript *整个*文档中某个元素后的下一个元素,javascript,jquery,html,dom,Javascript,Jquery,Html,Dom,这是一个被问了很多次的问题的变体。给定任何元素,我希望能够在整个文档中找到它之后的任何其他元素。它可以是兄弟,但也可以是随后发生的任何其他元素。例如,给定以下标记 <div> <p>Hello</p> <div> <p>Foo</p> <p class="bar">Bar</p> <p>rawr!</p>

这是一个被问了很多次的问题的变体。给定任何元素,我希望能够在整个文档中找到它之后的任何其他元素。它可以是兄弟,但也可以是随后发生的任何其他元素。例如,给定以下标记

<div>
    <p>Hello</p>
    <div>
        <p>Foo</p>
        <p class="bar">Bar</p>
        <p>rawr!</p>
    </div>
    <p>bop</p>
    <input/>
    <div>
        <p>Another</p>
        <div>
            <span>something</span>
            <p>deep!</p>
        </div>
    </div>
</div>
<p>last</p>
继续下去,它会得到另一个
,然后

最后一个
最后一个

这样的东西存在吗?我不在乎它是选择器还是函数。我只需要功能


EDIT更新了DOM结构,使之成为一个更具挑战性的问题,更清楚地说明我在寻找什么。

这应该行得通。但我不确定它是否有用

;(function ($)
{
    $.fn.nextInDocument = function (s)
    {
        var self = this,
            next;
        do
        {
            next = self.nextAll(s).first();
            self = self.parent();
        }
        while (self.length && !next.length);

        return next;
    };
})(jQuery);
演示:

看看我的代码:

HTML

更改
start+X
,您将获得下一个“p”标记

以下是POJS版本:

function nextInDocument(el, tagName) {
  var node, nodes = document.getElementsByTagName('*');
  var start = false;
  tagName = tagName.toLowerCase();

  for (var i=0, iLen=nodes.length; i<iLen; i++) {
    node = nodes[i];
    if (!start) {
      if (node == el) start = true;
    } else {
      if (node.tagName.toLowerCase() == tagName) {
        return node;
      }
    }
  }
}
函数nextInDocument(el,标记名){
var节点,nodes=document.getElementsByTagName('*');
var start=false;
标记名=标记名.toLowerCase();

对于(var i=0,iLen=nodes.length;i如何?这是一个通用解决方案,它使用DOM方法依次遍历节点,并根据jQuery选择器对每个节点进行测试

jsFiddle:


@Matt Ball它在当前元素之后的子元素中存在一些问题,尽管我不确定他是否使用了这样的功能:谢谢你指出。这是一个明显的缺陷,如果需要的话,它肯定会使事情变得更复杂。需要一个更好的树遍历算法。我不确定这是如何工作的它看起来很有希望。我把它放在一把小提琴里,没有办法匹配选择器。换句话说,
$('.bar')。nextInDocument('p')==$('.bar')。nextInDocument('div')=='rawr!

。我的需求确实需要再次遍历到树下,尽管这可能很不幸be@Jeff我不明白你所说的“
$('.bar')是什么意思.nextInDocument('p')==$('.bar').nextInDocument('div')=='rawr!

“谢谢Boopathi。我不确定是否遗漏了什么。我把它放在一个小提琴中,你的函数为每个调用返回原始元素,例如
$('.bar')。nextInDocument('div'))==rawr

。很抱歉……更正了……检查了……还有一个小错误。我会改进……我从中得到了空值。它仍然不起作用。谢谢。这似乎与我在演示中给出的标记紧密耦合,但我需要一些可以“针对任何元素”并抓取“后面的任何元素”的东西。我不认为这会有那么大的灵活性。我打赌它会:)在不同的DOM上尝试。您所需要的只是将此代码放入JQ函数。顺便说一下,开始元素的标记(按类选择)和您要查找的标记应该是相同的(例如“p”)谢谢。jQuery可以使用更复杂的选择器,虽然这使得一些其他代码片段对我的特定情况更有吸引力。请注意这种方法,如果你使选择器太复杂,你可能会发现性能问题。ND。好点。我想,如果性能变成了一个问题。这已经达到了我迄今为止所做的一切。我想知道它执行得有多好,我想现在我不打算在过大的页面上运行。非常感谢!”杰夫:它可能会被优化:例如,我想象为每一个选择选择器。节点是可能导致性能问题的一个原因。我建议只在它导致瓶颈时才这样做。
(function(jQuery) {
jQuery.fn.extend({
    nextInDocument: function(a) {
        if (jQuery(this).next(a).length === 0) {
            //console.log($(this).parent().nextInDocument('p'));
            jQuery(this).parent().nextInDocument(a);
        }
        else
            return jQuery(this).next(a);
    }
});
})(jQuery);
<div>
    <p>Hello</p>
    <div> 
        <p>Foo</p>
        <p>Fooooo</p>
        <p class="bar">Bar</p>
        <p>rawr!</p>
    </div>
    <p>bop</p>
    <input/>
    <div>
        <p>Another</p>
    </div>
</div>
<p>last</p>

<a class="show" href="#">!!!</a>
$(function() {
    i = 0;
    start = 0;
    $('p').each(function() {
        if ($(this).hasClass('bar')) {
            start = i;
        }
        i++;
    });
    $('a.show').click( function(){
        alert($('p').eq(start+4).text());
    });
});
function nextInDocument(el, tagName) {
  var node, nodes = document.getElementsByTagName('*');
  var start = false;
  tagName = tagName.toLowerCase();

  for (var i=0, iLen=nodes.length; i<iLen; i++) {
    node = nodes[i];
    if (!start) {
      if (node == el) start = true;
    } else {
      if (node.tagName.toLowerCase() == tagName) {
        return node;
      }
    }
  }
}
(function($) {
    function nextNode(node, omitChildren) {
        var sibling, parentNode;
        if (!omitChildren && node.hasChildNodes()) {
            return node.firstChild;
        } else {
            sibling = node.nextSibling;
            if (sibling) {
                return sibling;
            } else {
                parentNode = node.parentNode;
                return parentNode ? nextNode(parentNode, true) : null;
            }
        }
    }

    $.fn.nextInDocument = function(selector) {
        var node = this[0], $node;
        while ( (node = nextNode(node)) ) {
            $node = $(node);
            if ($node.is(selector)) {
                return $node;
            }
        }
        return null;
    }
})(jQuery);