如何找到與具有特定類別的樹木最接近的元素的祖先,純JavaScript中的?例如,像這樣一棵樹:查找具有特定類別的最接近的祖先元素
<div class="far ancestor">
<div class="near ancestor">
<p>Where am I?</p>
</div>
</div>
然後我想div.near.ancestor
如果我嘗試這對p
和搜索ancestor
。
如何找到與具有特定類別的樹木最接近的元素的祖先,純JavaScript中的?例如,像這樣一棵樹:查找具有特定類別的最接近的祖先元素
<div class="far ancestor">
<div class="near ancestor">
<p>Where am I?</p>
</div>
</div>
然後我想div.near.ancestor
如果我嘗試這對p
和搜索ancestor
。
該做的伎倆:
function findAncestor (el, cls) {
while ((el = el.parentElement) && !el.classList.contains(cls));
return el;
}
while循環等待,直到el
具有所需的類,並將其設置el
到el
的父母每次迭代所以在最後,你有這個類的祖先或null
。
Here's a fiddle,如果有人想改善它。它不適用於舊瀏覽器(即IE);看到這個compatibility table for classList。 parentElement
在這裏使用,因爲parentNode
將涉及更多的工作,以確保該節點是一個元素。
有關'.classList'的替代方法,請參閱http://stackoverflow.com/q/5898656/218196。 –
我修正了代碼,但如果沒有這樣的類名的祖先,它仍會拋出錯誤。 –
@FelixKling:你能解釋爲什麼'parentElement'錯了嗎? – rvighne
更新:現在支持in most major browsers
document.querySelector("p").closest(".near.ancestor")
注意,這可以匹配選擇,而不僅僅是類
https://developer.mozilla.org/en-US/docs/Web/API/Element.closest
對於不支持closest()
但有matches()
一個傳統的瀏覽器可以構建類似於@ rvighne的類匹配的選擇器匹配:
function findAncestor (el, sel) {
while ((el = el.parentElement) && !((el.matches || el.matchesSelector).call(el,sel)));
return el;
}
謝謝,隨着瀏覽器追上,這將是幾個月內的最佳答案。 – rvighne
當前版本的Internet Explorer,Edge和Opera Mini仍然不支持。 – kleinfreund
@kleinfreund - 在IE,Edge或Opera mini中仍然不支持。 http://caniuse.com/#search=closest – evolutionxbox
基礎上the8472 answer和https://developer.mozilla.org/pl/docs/Web/API/Element/matches這裏是跨平臺的解決方案2017年:
if (!Element.prototype.matches) {
Element.prototype.matches =
Element.prototype.matchesSelector ||
Element.prototype.mozMatchesSelector ||
Element.prototype.msMatchesSelector ||
Element.prototype.oMatchesSelector ||
Element.prototype.webkitMatchesSelector ||
function(s) {
var matches = (this.document || this.ownerDocument).querySelectorAll(s),
i = matches.length;
while (--i >= 0 && matches.item(i) !== this) {}
return i > -1;
};
}
function findAncestor(el, sel) {
if (typeof el.closest === 'function') {
return el.closest(sel) || null;
}
while (el) {
if (el.matches(sel)) {
return el;
}
el = el.parentElement;
}
return null;
}
簡單而美麗 – Michael
@rvighne液效果很好,但在意見中指明ParentElement
和ClassList
都有兼容性問題。爲了使它更兼容,我用:
function findAncestor (el, cls) {
while ((el = el.parentNode) && el.className.indexOf(cls) < 0);
return el;
}
parentNode
屬性,而不是在className
屬性,而不是對classList
屬性contains
方法parentElement
財產indexOf
方法。當然,indexOf只是查找該字符串的存在,它並不關心它是否是整個字符串。所以,如果你有另一個類'祖先類型'的元素,它仍然會返回找到'祖先',如果這對你來說是一個問題,也許你可以使用正則表達式來找到一個完全匹配。
請注意,外部div不是父親,它是'p'元素的*祖先*。如果你實際上只想獲得父節點,你可以執行'ele.parentNode'。 –
@FelixKling:不知道那個術語;我會改變它。 – rvighne
它實際上與我們人類使用的一樣:)您父親(父母)的父親(父母)不是您的父親(父母),而是您的祖父(祖父母),或者更一般地說,您的祖先。 –