|
|
|
|
|
by irjoe
469 days ago
|
|
Using document.addEventListener means it will work even if the DOM is updated without having to add new event listeners. If I'm not expecting the DOM to change I would be more inclined to do something like: document.querySelectorAll('.menu-wrapper')).forEach(menuWrapper => {
const button = menuWrapper.querySelector('.menu-opener');
const content = menuWrapper.querySelector('.menu-content');
if (!content || !button) {
return;
}
button.addEventListener(() => {
button.setAttribute('aria-expanded', 'true');
menu.showPopover();
});
content.addEventListener('toggle', e => {
// reset back to aria-expanded=false on close
if (e.newState == 'closed') {
button.setAttribute('aria-expanded', 'false');
}
});
});
The React example seems a little odd as well, if the "open" callback actually called "showPopover()" instead of only calling "setIsOpen" then the "useEffect" could be entirely redundant. The resulting code would be a lot clearer imo. |
|
Nailed it.
And the sibling comment got at it but the "magic phrase" to Google for this technique is "event delegation." Two more phrases: delegation relies on "event bubbling," bubbling can be interrupted with "event capturing." (You will rarely want to capture events, it's JS's `!important` equivalent)
One decent overview: https://javascript.info/bubbling-and-capturing