这是我尝试查询的标记。所以给出了标记:
<table class="non-unique-identifier table">
<tr><td><div id="unique-identifier"></div></td></tr>
</table>
我查询#unique-identifier:
var myDiv = document.getElementById('#unique-identifier');
然后我尝试选择表格。问题是我想让代码不易碎,所以我不需要这样做:
var myDiv = document.getElementById('#unique-identifier'),
myTable = myDiv.parentNode.parentNode.parentNode.parentNode;
我的问题
目前是否有jQuery的DOM实现等价于$()。nearest()?最好的是没有嵌套for循环的高效实现。
限制
我需要不对此特定问题使用jQuery或sizzle或引入任何新库。代码也很老了。因此,这就是这种限制和<tables>
的存在的原因。
答案 0 :(得分:33)
如果没有循环,你就无法做到这一点:
function closest (el, predicate) {
do if (predicate(el)) return el;
while (el = el && el.parentNode);
}
嗯,实际上你可以使用递归(一个伪装的循环):
function closest(el, predicate) {
return predicate(el) ? el : (
el && closest(el.parentNode, predicate)
);
}
演示(使用Sizzle进行DOM查询):
// s = selectors
// n = number of selectors
// get closest s[i+1] from s[i]
// where 0 <= i < n and i % 2 = 0
function main (s) {
var i, el, from;
var n = s.length;
for (i = 0; i < n; i += 2) {
from = Sizzle(s[i])[0];
el = closest(from, function (el) {
return !!el && el !== document && (
Sizzle.matchesSelector(el, s[i + 1])
);
});
console.log(el);
}
}
function closest (el, predicate) {
do if (predicate(el)) return el;
while (el = el && el.parentNode);
}
main([
"#winner" , "b",
"#winner" , "p",
"#winner" , "div",
"#winner" , "div:not(#trump)",
"#winner" , "#clinton",
"#looser" , "html"
]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/sizzle/1.10.18/sizzle.min.js"></script>
<div id="main">
<div id="trump">
<p>Donald <b id="winner">Trump</b></p>
</div>
<div id="clinton">
<p>Hillary <b>Clinton</b></p>
</div>
</div>
答案 1 :(得分:5)
要添加更新的答案,现在可以Element.closest(<query_selector>)
。
https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
IE不支持此功能,但该mozilla doc页面包含IE8和IE9 +的polyfill代码。
答案 2 :(得分:3)
简洁快捷(使用Benchmark.js 进行测试)以便通过任何css选择器搜索最接近的元素:
var ep = Element.prototype;
ep.matches = ep.matches || ep.webkitMatchesSelector || ep.msMatchesSelector || ep.mozMatchesSelector;
function getClosest( elem, selector ) {
while (elem !== document.body) {
elem = elem.parentElement;
if (elem.matches(selector)) return elem;
}
}
支持IE9 +以及您可能关心的其他浏览器。
答案 3 :(得分:2)
function closestById(el, id) {
while (el.id != id) {
el = el.parentNode;
if (!el) {
return null;
}
}
return el;
}
// Use it like:
yourTarget = closestById(document.getElementById('unique-identifier'),'targetId')
alert(yourTarget.id);
<div id="targetId">
Finish
<div>
<div id="unique-identifier">
Start
</div>
</div>
</div>
向上搜索,直到找到某个ID。您还可以更改代码以查找某些类。
答案 4 :(得分:2)
替代方案是递归函数。当我搜索孩子时,这与最近的略有不同,我不确定他是否最接近。
function closest(elem) {
if( elem.className.indexOf("non-unique-identifier") ) {
return elem;
}
var parent = elem.parentNode;
for(var i = 0; i< parent.children.length; i++ ) {
if( parent.children[i].className.indexOf("non-unique-identifier")!=-1) {
return parent.children[i];
}
}
return closest(parent);
}
var elem = document.getElementById('unique-identifier');
var cl = closest(elem);
console.log(cl);
非儿童搜索示例(更像是最近的):
function closest(elem) {
if( elem.className.indexOf("non-unique-identifier") ) {
return elem;
}
var parent = elem.parentNode;
if( parent.className.indexOf("non-unique-identifier")!=-1) {
return parent;
}
return closest(parent);
}
var elem = document.getElementById('unique-identifier');
var cl = closest(elem);
console.log(cl);
答案 5 :(得分:2)
savelogs(a, dtdate.Value.ToShortDateString, cmbstatus.Text, dttime.Value.ToShortTimeString, dtdate.Value.ToShortDateString);
答案 6 :(得分:1)
我在我的一个TypeScript项目中编写了这个简单的函数,所以我在parentNode上使用了querySelector,因此你可以传递给函数class
,id
,tag name
等
findParentNode(el, selector:string):Element | null {
let found = null;
let child = el;
let childSelector = guessSelector(child);
while(child !== document && found === null) {
child = child.parentNode;
childSelector = guessSelector(child);
found = childSelector ? child.parentNode.querySelector(`${childSelector} > ${selector}`) : null;
}
return found;
function guessSelector(child:any):string {
childSelector = child.className ? `.${child.className.replace(' ', '.')}` : null;
if (typeof child.getAttribute === 'function') {
childSelector = !childSelector ?
(child.getAttribute('id') ? `#${child.getAttribute('id')}` : null) : childSelector;
childSelector = !childSelector ?
child.tagName.toLowerCase() : childSelector;
}
return childSelector;
}
}
示例:强>
如果您想找到target
类.param-input
的最近父母,您可以这样做:
document.body.addEventListener('click', (e) => {
console.log(findParentNode(e.target, '.param-input'));
});
答案 7 :(得分:0)
在这种情况下,请使用JavaScript的最近的()
示例:
var el = document.getElementById('div-03');
var r1 = el.closest("#div-02");
// returns the element with the id=div-02
var r2 = el.closest("div div");
// returns the closest ancestor which is a div in div, here is div-03 itself
var r3 = el.closest("article > div");
// returns the closest ancestor which is a div and has a parent article, here is div-01
var r4 = el.closest(":not(div)");
// returns the closest ancestor which is not a div, here is the outmost article
<article>
<div id="div-01">Here is div-01
<div id="div-02">Here is div-02
<div id="div-03">Here is div-03</div>
</div>
</div>
</article>
您可以在MDN Web文档by clicking here
上找到更多信息。