让我们假设我有这个标记
<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
}
});
答案 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;
}
答案 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
即使在特殊情况下,此函数也能正常工作:
function isBeforeElement( first_id, second_id ) {
return document.querySelectorAll('#' + first_id + ', #' + second_id)[0] === document.getElementById(first_id);
}
false
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)
仅当元素处于同一级别时,可接受的答案才有效。如果要确定哪个元素优先于哪个级别,一种解决方法是:
答案 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>