Reputation: 2616
In my app, I would like to find out if the element (or element's parent, or grand parents, or grand grand parents) I'm clicking on has a certain type (such as button
), in order to trigger a side effect if it hasn't the type I'm looking for.
For example, if I click on an element svg
that is embedded in a span
, which is embedded in a button
, the checker function would return "true", since an ancestor of the svg
element is of type button
.
So far, I have the following check in the isParentFocusable
function:
private isFocusable(el: HTMLElement) {
if (!el) {
return false;
}
if (el.getAttribute('focusable')) {
return true;
}
let types = ['input', 'textarea', 'button', 'select', 'a', 'menuitem'];
return (
this.verifyRoleOrTagName(el, types) ||
this.isParentFocusable(el, types)
);
}
private verifyRoleOrTagName = (element: HTMLElement, types: string[]) => {
return (
types.includes(element.tagName.toLocaleLowerCase()) ||
types.includes(element.getAttribute('role') || '')
);
};
private isParentFocusable(el: HTMLElement, types: string[]) {
let currentElement: HTMLElement | null | undefined = el;
// The upmost level to check for the parent is set to 3;
// we don't want to check all the parents up to the body tag
const MAX_PARENT_LEVEL = 3;
for (let i = 0; i < MAX_PARENT_LEVEL && currentElement; i++) {
currentElement = currentElement.parentElement;
if (currentElement && this.verifyRoleOrTagName(currentElement, types)) {
return true;
}
}
return false;
}
Is there an elegant way or a known method to check for the clicked element to be embedded in a tag of a certain type? (Here, the types are listed in the types
array).
Upvotes: 1
Views: 440
Reputation: 1075309
You can use the closest
method to do that. It finds the closest element that matches a CSS selector, starting with the element you call it on, then going to the parent, etc.
const button = theElement.closest("button");
Here's an example:
function clickHandler(event) {
const button = event.target.closest("button");
console.log(`Found button? ${button ? "Yes" : "No"}`);
}
for (const span of document.querySelectorAll("span")) {
span.addEventListener("click", clickHandler);
}
<button type="button">
<span>Click me</span>
</button>
<div>
<span>And click me</span>
</div>
Upvotes: 2