I have a forEach
loop that gets the attribute of any element that has the specified attribute on my page. It looks something like this:
const cursorActionElements = document.querySelectorAll("[data-cursor]");
cursorActionElements.forEach((el) => {
const elAttr = el.getAttribute("data-cursor");
el.addEventListener('mouseover', () => {
console.log(elAttr)
});
});
It all works fine. It goes through and gets all elements that have the data-cursor
attribute and stores its value in the elAttr
variable. However, for some reason, If the parent of the target happens to ALSO have a data-cursor
attribute, it returns both the target’s data-cursor
value, AND its parent’s data-cursor
value.
I’m really not sure how to solve this issue. I’ve thought of retrieving the data-cursor
value on mouseover
but, that just means I need to use yet another event listner and it seems to slow my site down a bit.
Please help.
2
Answers
The issue is because the event is propagating up the DOM from the child to the parent, so the event handler fires once per element. To fix this you can call
stopPropagation()
on the event passed to the event handler.Also note that it would be a better idea to read the
data
attribute from the Event object as well, to avoid any scope/closure issues which may arise when relying on the variable set in a loop within an event handler.Here’s a working example with the above changes made:
This is because the
mouseover
event bubbles up the DOM tree, which means it triggers on the parent element when you hover over a child element. To solve this issue, you can use themouseenter
event instead ofmouseover
.Now, when you hover over an element with the
data-cursor
attribute, it will only log the value of that attribute, not the value of any parent elements.