I have 2 scripts (Extremely simplified examples below) – The first controls the display of a specified nav menu on a page and it us used in several places for different kinds of menus.
const NavMenu = function(selector) {
this.menuItems = document.querySelectorAll(`${selector} li > a`);
let This = this;
This.menuItems.forEach(item => {
item.addEventListener('click', e => {
item.classList.toggle('selected');
});
});
}
const myNavMenu = new NavMenu('.menu-wrap');
The other is used for 1 specific purpose on a specific page containing a menu that is controlled by the 1st script.
(function () {
const menuItems = document.querySelectorAll('.menu-wrap li > a');
menuItems.forEach(item => {
item.addEventListener('click', e => {
const selectedItems = document.querySelectorAll('.menu-wrap li > a.selected');
let str = '';
if(selectedItems.length) {
selectedItems.forEach((item, i) => {
str += `${item.textContent} `;
});
document.querySelector('#results').innerText = `Selected: ${str}`;
}
});
});
})();
As you can see, the 2nd script has a click handler that performs an action based on the state of each menu item (“selected” or not). Since that state is set by the 1st script, this only works if 1st script’s click handler runs BEFORE the 2nd.
I created a version where I force the 2nd script’s click handler to run first(via setTimeout
). Clicking on the items, you can see that the resulting text does not match.
https://codepen.io/daveh0/pen/GROXmrq
Because the 1st script is used in many other places, it needs to run independently of any other script, otherwise I would have just combined the 2.
I think a custom event is the answer here. i implemented one here: https://codepen.io/daveh0/pen/xxPaqzJ from an example I found, but I have no idea if this is the correct way to do it. It works, but that doesn’t mean a ton…
I’d think the event should be somehow tied to the NavMenu
object, but I couldn’t get it to dispatch from anything other than window
or document
or another DOM element. Can anyone point me in the right direction for a way that I can do something like: myMenu.addEventListener('done', e => //do some stuff)
rather than having it attached to window
? Or if I’m way off to even begin with, feel free to let me know as much too.
I know this is kind of built into jQuery, but this needs to stay Vanilla JavaScript – thanks!