检查元素是否在jQuery中的另一个元素之前或之后

时间:2011-08-26 17:47:17

标签: jquery dom

让我们假设我有这个标记

<h3 id="first">First</h3>
<p>Hi</p>
<p>Hello</p>
<h3 id="second">Second</h3>
<p>Bye</p>
<p>Goodbye</p>

如何使用jQuery以编程方式检查某个元素(例如p之一)是在h3之后还是在第二个h3之前?

我正在尝试做这样的事情:

$(p).each(function(){
   if($(this).isAfter("#first") && $(this).isBefore("#second")) {
     // do stuff
   }
});

11 个答案:

答案 0 :(得分:51)

如果sel是一个真正的选择器,Rocket的解决方案可以正常工作,如果你传递一个jquery对象,它将不起作用。

如果你想要一个兼容选择器和jquery对象的插件,只需使用我稍微修改过的版本:

(function($) {
    $.fn.isAfter = function(sel){
        return this.prevAll().filter(sel).length !== 0;
    };

    $.fn.isBefore= function(sel){
        return this.nextAll().filter(sel).length !== 0;
    };
})(jQuery);

向Rocket寻求原始解决方案。

答案 1 :(得分:47)

要查看某个元素是否在另一个元素之后,您可以使用prev()prevAll()来获取上一个元素,并查看它是否匹配。

要查看元素是否在另一个元素之前,您可以使用next()nextAll()来获取下一个元素,并查看它是否匹配。

$.fn.isAfter = function(sel){
  return this.prevAll(sel).length !== 0;
}
$.fn.isBefore= function(sel){
  return this.nextAll(sel).length !== 0;
}

DEMO:http://jsfiddle.net/bk4k7/

答案 2 :(得分:25)

您可以使用index()功能:

$('p').each(function(){
   var index = $(this).index();
   if(index > $("#first").index() && index < $("#second").index()) {
     // do stuff
   }
});

答案 3 :(得分:2)

这是fiddle

$('p').each(function() {
    previousH3 = $(this).prevAll('h3');
    nextH3 = $(this).nextAll('h3');

    if (previousH3.length > 0 && nextH3.length > 0) {
        $(this).css('color', 'red')
    }

});

答案 4 :(得分:2)

我实现了一个通用data = Terms.objects.filter(language = language_id).values() for d in data: if d.term is None: d.colour = "#D3D3D3" else: d.colour = termColours[d.term] 函数,它考虑了深度和DOM树,并且可以正确地确定isAfter是否在a之后,即使它们在2个不同的子树中:

b

你可以在my GitHub Repository找到它。非常感谢您对代码的反馈

答案 5 :(得分:1)

答案:

$.fn.isAfter = function(sel){
    return this.prevAll(sel).length !== 0;
}
$.fn.isBefore= function(sel){
    return this.nextAll(sel).length !== 0;
}

选择所有之前的元素或下一个元素而不管选择器(sel),所以我做了以下修改,根据类选择元素:

$.fn.isAfter = function(sel){
    sel = "." + sel.attr("class").replace(/ /g, ".");

    return this.prevAll(sel).length !== 0;
}
$.fn.isBefore= function(sel){
    sel = "." + sel.attr("class").replace(/ /g, ".");

    return this.nextAll(sel).length !== 0;
}

答案 6 :(得分:1)

这种单行检查适用于任何情况

用于此示例的问题中的 ID:

   id      Name correct_id
0   1      Paul          1
1   2      Jean        N/A
2   3    Alicia          3
3   4  Jennifer        N/A

document.getElementById("first") === document.querySelectorAll("#second, #first")[0] 方法中的 ID 顺序无关紧要,在这种情况下,只需使用将选择两个元素的选择器 querySelectorAll

如果你需要多次使用这个可以使用这个功能:

#second, #first

即使在特殊情况下,此函数也能正常工作:

  1. 如果两个元素都没有找到,它将返回function isBeforeElement( first_id, second_id ) { return document.querySelectorAll('#' + first_id + ', #' + second_id)[0] === document.getElementById(first_id); }
  2. 如果 second 元素未找到,它将返回 false
  3. 如果 first 元素未找到,它将返回 true

答案 7 :(得分:0)

记住Rocket的回答我更喜欢使用.index()方法,如下所示:

$.fn.isAfter = function(sel){
    return $(this).index() > $(sel).index();
};
$.fn.isBefore= function(sel){
    return $(this).index() < $(sel).index();
};

阅读/理解似乎更清晰,并且在行选择中完美运行。

答案 8 :(得分:0)

如果相关元素是兄弟姐妹(他们在原始问题中),之前的答案可以正常工作,但更通用的解决方案会考虑以下情况:

<div id="top">    
    <div>
        <div>
           <h3 id="first">First</h3>
           <p>Hi</p>
           <p>Hello</p>
        </div>
    </div>
    <div>
        <h3 id="second">Second</h3>
        <p>Bye</p>
        <p>Goodbye</p>
    </div>
</div>

更通用的解决方案是:

$.extend($.fn, {
    isBefore: function(sel, context) {
        // Get all element within the context.
        var all = $(context || document).find("*");
        return all.index(this[0]) < all.index($(sel));
    },

    isAfter: function(sel, context) {
        return !this.isBefore(sel, context);
    }
});

其中&#34; context&#34;是一个可选参数,仅限制jQuery的搜索区域以提高性能。我还没有进行任何测试,但&#34; context&#34;可能没必要,因为$(&#34; *&#34;)似乎在质量上快速执行。另请注意,index()将返回-1,或者元素不在上下文中。

$("#first").isBefore("#second");  
// Gives the same result as
$("#first").isBefore("#second", "#top");

当然这一切都假设在&#34;之前&#34; &#34;&#34;&#34;&#34;你的意思是他们在文档模型中的顺序。如果您担心它们在显示器上的相对位置,您可能需要检查相对于文档的元素显示坐标为&#34; relative&#34;,&#34; fixed&#34;和&#34;绝对&#34; CSS职位使一切成为可能。

答案 9 :(得分:0)

仅当元素处于同一级别时,可接受的答案才有效。如果要确定哪个元素优先于哪个级别,一种解决方法是:

  1. 为每个具有相同值的元素设置一个临时属性
  2. 使用jquery选择器找到具有该属性值的第一个元素

答案 10 :(得分:0)

此版本适用于任何深度,比较两个元素是否在彼此之前、相等或之后。分别返回 -1、0 和 1。

它的工作原理是获取传递给比较函数的元素的所有索引偏移量。

然后它比较两个偏移量数组并在发现差异时停止迭代。

var topElement = $("span").eq(0);
var bottomElement = $("span").eq(2);

var res = compare(topElement, bottomElement);

console.log("The compare result is: " + res)



function getOffsets(el)
{
  var res = new Array();
  
  while(el.length > 0)
  {
    res.push(el.index());
    el = el.parent();
    }
  
  return res.reverse();
}

function compare(a, b)
{  
  var offA = getOffsets(a);
  var offB = getOffsets(b);
  
  
  for(let i = 0; i < offA.length + 1; i++)
  {
        let delta = (offA[i] || -1) - (offB[i] || -1);
    
    if(delta < 0)
      return -1;
    else if(delta > 0)
      return 1;
  }
  
  return 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div>
    <span>1</span>
</div>
<div>
    <div>
        <span>2</span>
    </div>
</div>
<div>
    <div>
        <div>
            <span>3</span>
        </div>
    </div>
</div>