I have a navigation with multiple event listeners: click
and hover
. This event listeners can change, e.g. on browser resize. I add the event listeners in my own method which gets called if listeners should be re-initialized. My problem in my following class: removeEventListener
does not work. So re-initialization causes that both click
and hover
fires.
class Navigation {
constructor(element) {
this.element = element;
this.changeButton = this.element.querySelector("button");
this.version = "hover";
this.navItemElements = Array.from(this.element.querySelectorAll(".nav-item"));
this.navItems = this.createNavItems(this.navItemElements);
this.clickHandler = (event) => this.navItemHoverHandler(event);
this.changeButton.addEventListener("click", () => {
this.isHoverVersion = !(this.isHoverVersion);
console.log("Change trigger. Is hover version --> " + this.isHoverVersion);
this.initListeners();
});
this.clickHandler = (event, navItem) => this.navItemClickHandler(event, navItem);
this.hoverHandler = (event, navItem) => this.navItemHoverHandler(event, navItem);
this.initListeners();
}
initListeners() {
console.log("Init listeners");
console.log(this.navItems);
if (this.isHoverVersion) {
this.navItems.forEach((navItem) => {
console.log(navItem);
navItem.link.addEventListener('mouseover', e => this.hoverHandler(e, navItem));
navItem.link.addEventListener('mouseout', e => this.hoverHandler(e, navItem));
navItem.link.removeEventListener('click',this.clickHandler);
})
} else {
this.navItems.forEach((navItem) => {
navItem.link.addEventListener('click', e => this.clickHandler(e, navItem));
navItem.link.removeEventListener('mouseover', this.hoverHandler);
navItem.link.removeEventListener('mouseout', this.hoverHandler);
})
}
}
navItemClickHandler(event, navItem) {
event.preventDefault();
console.log('Click handler executed');
console.log(navItem);
}
navItemHoverHandler(event, navItem) {
event.preventDefault();
console.log('Hover handler executed');
console.log(navItem);
}
createNavItems(navItemElements) {
let navItems = [];
navItemElements.forEach((itemElement) => {
navItems.push(this.createNavItemObject(itemElement));
});
return navItems;
}
createNavItemObject(navItem) {
let container = navItem;
let link = navItem.querySelector("a");
return {
container: container,
link: link,
};
}
}
let navigationElement = document.querySelector(".navigation");
new Navigation(navigationElement);
.navigation {
display: flex;
flex-flow: row nowrap;
width: 100%;
justify-content: space-between;
width: 100%;
max-width: 280px;
}
ul {
display: flex;
flex-flow: row nowrap;
list-style: none;
margin: 0;
padding: 0;
}
li {
margin-right: 20px;
}
<div class="navigation">
<button id="changeButton">Change trigger</button>
<ul>
<li class="nav-item">
<a href="">Link 1</a>
</li>
<li class="nav-item">
<a href="">Link 2</a>
</li>
</ul>
</div>
navItem
is an object, which I created before. navItem.link
is the HTML Anchor Element.
Question:
How can I bind the listener to the specific object?
I need to call the same method, but with its specific navItem
object...
Update:
Added working code example. The navigation gets initialized with click trigger. Clicking the button will toggle click / hover. In this example, after toggling from click to hover, both listeners get executed.