我如何选择包含所有这些元素的一组元素的第一个父元素?
例如:
<body>
<dl>
<dt>Items:</dt>
<dd>
<ul>
<li>Item 1<div class="item-info">...</div></li>
<li>Item 2<div class="item-info">...</div></li>
<li>Item 3<div class="item-info">...</div></li>
</ul>
</dd>
</dl>
</body>
我想要这样的事情:
$('.item-info').commonParent();
它将返回相当于:
[$('ul')]
使用jQuery选择器有一种简单的方法吗?或者我要写一个插件?
答案 0 :(得分:9)
如果您确实在寻找最低共同祖先(See this working in a fiddle):
jQuery.fn.commonAncestor = function() {
var parents = [];
var minlen = Infinity;
$(this).each(function() {
var curparents = $(this).parents();
parents.push(curparents);
minlen = Math.min(minlen, curparents.length);
});
for (var i in parents) {
parents[i] = parents[i].slice(parents[i].length - minlen);
}
// Iterate until equality is found
for (var i = 0; i < parents[0].length; i++) {
var equal = true;
for (var j in parents) {
if (parents[j][i] != parents[0][i]) {
equal = false;
break;
}
}
if (equal) return $(parents[0][i]);
}
return $([]);
}
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script src="jquery.commonancestor.js"></script>
$(function() {
console.log($(".item-info").commonAncestor());
});
</script>
<body>
<dl>
<dt>Items:</dt>
<dd>
<ul>
<li>Item 1<b><div class="item-info">...</div></b></li>
<li>Item 2<u><div class="item-info">...</div></u></li>
<li>Item 3<i><div class="item-info">...</div></i></li>
</ul>
</dd>
</dl>
</body>
这尚未经过严格测试,因此请指出您看到的任何错误。
编辑返回父级而非$(父级)
编辑在IE8中无效
答案 1 :(得分:2)
我认为重点在于.item-info
元素(可能)遍布整个页面。
如果这是正确的,试试这个: http://jsfiddle.net/EJWjf/1/
var $items = $('.item-info'); // Cache all the items in question
var total = $items.length; // Cache the total number
var parent; // Will store the match
$items.first() // Grab the first item (an arbitrary starting point)
.parents() // Get all of its parent elements
.each(function() {
// Iterate over each parent, finding the .info-item elements
// it contains, and see if the quantity matches the total
if($(this).find('.item-info').length == total) {
parent = this; // If so, we found the closest common ancestor so
return false; // store it and break out of the loop
}
});
alert(parent.tagName);
这是一个功能版本:http://jsfiddle.net/EJWjf/2/
function findCommon(selector) {
var $items = $(selector);
var total = $items.length;
var parent;
$items.first()
.parents()
.each(function() {
if($(this).find(selector).length == total) {
parent = this;
return false;
}
});
return $(parent);
}
var result = findCommon('.item-info');
答案 2 :(得分:1)
这是我的版本。它是页面上所有jQuery-plugin类型答案的performs best。它是唯一一个处理空jQuery对象$()
而没有错误的对象。它和Jamie Wong的答案是唯一能够无错误地处理单项jQuery对象的答案。
我建造了a jsfiddle showcasing all the versions' output。您可以单击“预设”按钮以轻松查看不同的测试用例,或者输入您自己的选择器并单击“查找”以查看结果。
jQuery.fn.reverse = function() {
return Array.prototype.reverse.call(this);
};
jQuery.fn.commonAncestor = function() {
var i, l, current,
compare = this.eq(0).parents().reverse(),
pos = compare.length - 1;
for (i = 1, l = this.length; i < l && pos > 0; i += 1) {
current = this.eq(i).parents().reverse();
pos = Math.min(pos, current.length - 1);
while (compare[pos] !== current[pos]) {
pos -= 1;
}
}
return compare.eq(pos);
};
在其中一个元素是另一个元素的祖先的情况下,到目前为止给出的所有答案都返回祖先元素的父元素。上述两个链接都包含我的函数版本,例如,如果页面上有div,$('body, div').commonAncestor()
将返回body
而不是html
注意:此函数假定jQuery集中的所有项都在当前文档中。将两个不同文档中的元素放入同一个jQuery对象中需要特别的,奇怪的努力 - 在这种情况下,我的函数将失败(页面上的所有其他文档也将失败)。这可以从将条件pos > 0
更改为pos >= 0
开始,使while循环句柄达到-1,并可能将return compare.eq(pos)
更改为return $(compare[pos])
(因为eq( )函数使用负索引从末尾向后索引而不是返回空)。
答案 3 :(得分:1)
这个比其他所有人(包括ErikE&#39; s)快得多,特别是对于很多元素:
jQuery.fn.commonAncestor = function() {
if (!this.length)
return null;
var parent = this[0].parentNode;
for (var i = this.length - 1; i >= 1; --i) {
var elt = this[i];
if (elt.contains(parent))
parent = elt.parentNode;
else
while (!parent.contains(elt))
parent = parent.parentNode;
}
return parent;
};
&#13;
答案 4 :(得分:0)
你在寻找这些吗?
$("element").parents() // return all parents until reaches 'html'
$("element").parent() // return the first parent
$("element").closest("parent") // return the closest selected parent
答案 5 :(得分:0)
我相信这就是你要找的东西:
<强>的jQuery 强>
前四行包含实际抓取UL的代码。其余的只是显示匹配的UL的内容。
<script type="text/javascript">
$(document).ready(function() {
// The code that grabs the matching ULs
var ULsWithAll=$("ul").has(".item-info").filter( function(index) { // Grab all ULs that has at least one .item-info
var ChildrenOfUL=$(this).children("li"); // Grab the children
return ChildrenOfUL.length===ChildrenOfUL.has(".item-info").length; // Are all of them .item-info
});
$(ULsWithAll).each(function(){ // Output the ULs that were found
alert($(this).html());
})
});
</script>
<强> HTML 强>
<dl>
<dt>Items 1:</dt>
<dd>
<ul>
<li>Item 1-1<div class="item-info">...</div></li>
<li>Item 1-2<div class="item-info">...</div></li>
<li>Item 1-3<div class="item-info">...</div></li>
</ul>
</dd>
<dt>Items 2:</dt>
<dd>
<ul>
<li>Item 2-1<div class="item-info">...</div></li>
<li>Item 2-2<div class="item-info">...</div></li>
<li>Item 2-3<div class="item-info">...</div></li>
</ul>
</dd>
<dt>Items 3:</dt>
<dd>
<ul>
<li>Item 3-1<div class="item-info">...</div></li>
<li>Item 3-2<div class="item-info">...</div></li>
<li>Item 3-3<div>...</div></li>
</ul>
</dd>
</dl>
上面的jQuery代码将返回第一次和第二次命中的UL(第三次是dud)。请在http://jsfiddle.net/ksTtF/
处查看另一个例子(没有警报):http://jsfiddle.net/vQxGC/
答案 6 :(得分:0)
受到各种其他答案的启发,我创建了一个符合我要求的版本。 http://jsfiddle.net/qDRv5/(请注意,它将找到的父级写入控制台)
jQuery.fn.firstParent=function (f){
//Set the variables for use;
s=$(this);
var i,j;
var p=[];
var pv=true;
//make sure there is something to itterate over
if(s.length>0){
//build a multidimentional array of parents
s.each(function(){p.push($(this).parents());});
//itterate through the parents of the first element starting at the closest
for(i=0;i<p[0].length;i++){
//itterate through all elements after the first
for(j=1;j<s.length;j++){
//look for the current parent of the first element in each array
pv=($.inArray(p[0][i],p[j]) != -1);
//if we are looking at the last element and it matchs, return that parent
if(pv==true && j==s.length-1) return typeof(f)=='string'?$(p[0][i]).find(f):$(p[0][i]);
}
}
}
return false;
}
我首先从root查找元素最少的步骤,因为我确信这个元素不会有一个远离root的共同祖先。 然后我一次从父母退回,从那些元素检查父元素是否具有所有其他元素作为子元素。当我找到一个包含所有元素作为孩子的父元素时,我的任务就完成了。
答案 7 :(得分:0)
$('.item-info').get(0).parentElement
答案 8 :(得分:0)
所以...我知道这是一个旧线程,但我需要这个确切的功能,并且需要它在jQuery的漂亮链中工作;)所以这就是我想出的:
jQuery.fn.firstParent=function (f){
//Set the variables for use;
s=$(this);
var i,j;
var p=[];
var pv=true;
//make sure there is something to itterate over
if(s.length>0){
//build a multidimentional array of parents
s.each(function(){p.push($(this).parents());});
//itterate through the parents of the first element starting at the closest
for(i=0;i<p[0].length;i++){
//itterate through all elements after the first
for(j=1;j<s.length;j++){
//look for the current parent of the first element in each array
pv=($.inArray(p[0][i],p[j]) != -1);
//if we are looking at the last element and it matchs, return that parent
if(pv==true && j==s.length-1) return typeof(f)=='string'?$(p[0][i]).find(f):$(p[0][i]);
}
}
}
return false;
}
还有一个jsfiddle here
答案 9 :(得分:0)
我会这样做:过滤出选择器父项,它包含选择器集中的每个元素。
jQuery.fn.commonParent = function() {
var parent = this.parents();
this.each(function() {
parent = parent.has(this);
});
return parent.first();
};
答案 10 :(得分:0)
8年后,面对同样的问题,我最终来到了这里。这些答案都不是我想要的,所以我最终得到了这个答案。它可能不是绝对最快的,但它很小而直接:
$.fn.commonParents = function () {
var $children = this.toArray();
// reduce the parents to those where
return this.parents().filter(function (i, parent) {
// every child
return $children.every(function (child) {
// is contained by a that parent
return $.contains(parent, child);
});
});
};
获取最接近的信息:
var $closestCommonParent = $elements.commonParents().first();