Hoe kan ik de voorouder van een element vinden die zich het dichtst bij de boom met een bepaalde klasse bevindt, in puur JavaScript? Bijvoorbeeld in een boom als volgt:
<div class="far ancestor">
<div class="near ancestor">
<p>Where am I?</p>
</div>
</div>
Dan wil ik div.near.ancestor
als ik dit probeer op de p
en zoek naar ancestor
.
Antwoord 1, autoriteit 100%
Update: nu ondersteund in de meeste grote browsers
document.querySelector("p").closest(".near.ancestor")
Merk op dat dit kan overeenkomen met selectors, niet alleen klassen
https://developer.mozilla.org/en- VS/docs/Web/API/Element.closest
Voor oudere browsers die closest()
niet ondersteunen maar wel matches()
hebben, kan men selector-matching bouwen die lijkt op de class matching van @rvighne:
function findAncestor (el, sel) {
while ((el = el.parentElement) && !((el.matches || el.matchesSelector).call(el,sel)));
return el;
}
Antwoord 2, autoriteit 43%
Dit doet de truc:
function findAncestor (el, cls) {
while ((el = el.parentElement) && !el.classList.contains(cls));
return el;
}
De while-lus wacht totdat el
de gewenste klasse heeft, en zet el
bij elke iteratie op de ouder van el
, dus uiteindelijk , je hebt de voorouder met die klasse of null
.
Hier is een viool, als iemand het wil verbeteren. Het werkt niet in oude browsers (d.w.z. IE); zie deze compatibiliteitstabel voor classList. parentElement
wordt hier gebruikt omdat parentNode
meer werk zou vergen om ervoor te zorgen dat de node een element is.
Antwoord 3, autoriteit 11%
Gebruik element.closest()
https://developer.mozilla.org/en- VS/docs/Web/API/Element/dichtstbijzijnde
Zie dit voorbeeld DOM:
<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>
Zo zou je element.closest gebruiken:
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
Antwoord 4, autoriteit 4%
Op basis van het de8472-antwoorden https://developer.mozilla.org/en-US/docs/Web/API/Element/matcheshier is cross-platform 2017 oplossing:
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;
}