Based on the MDN event
documentation, the event
object has a method called composedPath which stores:
An array of the objects on which listeners will be invoked. This
does not include nodes in shadow trees if the shadow root was created
with its ShadowRoot.mode closed.
While this seems to work in Chrome, it is not specified in the documentation how other browsers support this method.
Inspecting the event
object further also revealed a event.path
property which also contains the same path array, at least in Chrome, however, I could not find any documentation on event.path
at all.
Having said that, I did see samples suggesting it might be saver to do
var eventPath = event.path || (event.composedPath &&
event.composedPath());
instead of just using var eventPath =
event.composedPath();
Assuming your browser does support it, you can iterate through the path of the clicked element and check if it is a child of the button or the button itself.
The below code demonstrates this and stores the button element reference for further use.
document.getElementById('wrapper').addEventListener('click', function() {
// actual element clicked
console.log(event.target);
var buttonClicked = false;
var button;
var eventPath = event.composedPath();
for (let i = 0; i < eventPath.length; i++) {
if (eventPath[i].tagName && eventPath[i].tagName.toLowerCase() === 'button') {
buttonClicked = true;
button = eventPath[i];
break;
}
}
if (buttonClicked) {
console.log(button);
console.log('button was clicked');
}
})
<div id="wrapper">
<button class="c-config__option c-config__option--button c-config__option--pack" data-index="0">
Item 1
<span>Subtext</span>
</button>
<button class="c-config__option c-config__option--button c-config__option--pack" data-index="1">
Item 2
<span>Subtext</span>
</button>
</div>
As an alternative you can replicate jQuery.closest using the code from this SO post: DOM / pure JavaScript solution to jQuery.closest() implementation?