I am wondering if there is a way to select a specific element way up the DOM only using vanilla JS while not having to use parentNode
multiple times. I understand you can do this with jQuery and modifying Element.prototype
, but are there any other pretty ways to write this.
const deleteButtons = document.querySelectorAll('.delete-button');
for (var i = 0; i < deleteButtons.length; i++) {
deleteButtons[i].addEventListener('click', (e) => {
e.preventDefault();
//This is the crazy amount of parentNode usage
bookDatabase.child(e.target.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.getAttribute("id")).remove();
});
}
There is really only one other way, which is to use the DOM API element.closest()
, but it does require that you provide a selector that can uniquely identify the particular element you need (or the first element that matches that selector from the descendant's point of view). Without that, multiple uses of the .parent()
method would be required and you'd need to know how many levels up you want to go.
// Starting from the inner most level
var start = document.getElementById("source");
// Let's say you wanted to reference the first ancestor
// that has the "something3" class
start.closest(".something3").classList.add("red");
// Or, the second closest
var firstMatch = start.closest(".something2");
firstMatch.classList.add("yellow");
// Or, even higher
firstMatch.closest(".something1").classList.add("aqua");
// And, of course, you can skip levels
start.closest(".something1").classList.add("dropCap");
#source {background-color:orange; }
.red { background-color:red; }
.yellow { background-color:yellow; font-size:1rem; }
.aqua { background-color:aqua; }
.dropCap { font-size:3em; }
<div class="something1">Level 1
<div class="something2">Level 2
<div class="something3">Level 3
<div id="source">Level 4</div>
</div>
</div>
</div>
Here is the simplest way to get a parent node of a needed hierarchical level:
function getParentNode(element, level = 1) { // 1 - default value (if no 'level' parameter is passed to the function)
while (level-- > 0) {
element = element.parentNode;
if (!element) return null; // to avoid a possible "TypeError: Cannot read property 'parentNode' of null" if the requested level is higher than document
}
return element;
}
With this function, instead of:
e.target.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode
you can use this:
getParentNode(e.target, 6)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With