'Trigger problem mouseover/mouseleave javascript
I'm trying to make an effect when the user switches elements on hover but I have an issue.
Here is my code
var oStudyRows = document.querySelectorAll('.study_row');
oStudyRows.forEach(function(oStudyRow) {
oStudyRow.addEventListener('mouseover', function(e) {
console.log('enter')
oStudyRow.classList.add('blub');
})
oStudyRow.addEventListener('mouseleave', function(e) {
oStudyRow.classList.remove('blub');
console.log('out');
})
})
<div class="wrapper_study">
<div class="study_row study">
<div class="study_year">aaaa</div>
<div class="study_name">bbbb</div>
</div>
<div class="study_row work">
<div class="study_year">aaaa</div>
<div class="study_name">bbbbb</div>
</div>
<div class="study_row work">
<div class="study_year">aaaa</div>
<div class="study_name">bbbbbb</div>
</div>
<div class="study_row study">
<div class="study_year">aaaa</div>
<div class="study_name">bbbbb</div>
</div>
<div class="study_row work">
<div class="study_year">aaaaa</div>
<div class="study_name">bbbb</div>
</div>
</div>
When I "enter" in the first row and I "leave" to the top , the enter/out work correctly, I have "enter/out" in the console but when I hover row1 to row2 I have a mutiple console log.
Someone can help me and explain to me why it doesn't work properly, please?
Thanks a lot
Solution 1:[1]
The children divs contained in .study_row
will bubble the event to the parent. So to make only the parent fire the event, I set pointer-events to none for any children of .study_row
.
There are better alternatives on setting the event handler here, but this is the solution taking the less modification to your strategy.
var oStudyRows = document.querySelectorAll('.study_row');
oStudyRows.forEach(function(oStudyRow){
oStudyRow.addEventListener('mouseover', function(e){
console.log('enter')
oStudyRow.classList.add('blub');
})
oStudyRow.addEventListener('mouseleave', function(e){
oStudyRow.classList.remove('blub');
console.log('out');
})
})
.study_row{
border: solid 1px red;
margin-bottom: 25px;
}
.study_row *{
pointer-events: none;
}
<div class="wrapper_study">
<div class="study_row study">
<div class="study_year">aaaa</div>
<div class="study_name">bbbb</div>
</div>
<div class="study_row work">
<div class="study_year">aaaa</div>
<div class="study_name">bbbbb</div>
</div>
<div class="study_row work">
<div class="study_year">aaaa</div>
<div class="study_name">bbbbbb</div>
</div>
<div class="study_row study">
<div class="study_year">aaaa</div>
<div class="study_name">bbbbb</div>
</div>
<div class="study_row work">
<div class="study_year">aaaaa</div>
<div class="study_name">bbbb</div>
</div>
</div>
Here's a strategy using one single function to handle both the mouseover
and mouseout
events firing just on the .wrapper_study
container element (and all of its children through bubbling .. excepts for elements that got pointer-events:none
due to the rule .study_row *
). To pursue this strategy I had to replace mouseleave
with mouseout
because the former one doesn't support bubbling.
You can find more on those topic here:
- https://developer.mozilla.org/en-US/docs/Web/API/Element/mouseleave_event
- https://developer.mozilla.org/en-US/docs/Web/API/Element/mouseout_event
- https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_bubbling_and_capture
//one single event handler
function generalHandler(event){
//element firing the event
const eventTarget = event.target;
//if eventTarget is a .study_row
if(eventTarget.classList.contains('study_row')) {
//if event is mouseover
if (event.type == 'mouseover'){
eventTarget.classList.add('blub');
//console.log('--enter');
}
//if event is mouseout
else if(event.type == 'mouseout'){
eventTarget.classList.remove('blub');
//console.log('--out');
}
}
}
const mainContainer = document.querySelector('.wrapper_study');
mainContainer.addEventListener('mouseover', generalHandler);
mainContainer.addEventListener('mouseout', generalHandler);
.study_row{
border: solid 1px red;
margin-bottom: 25px;
cursor: pointer;
}
.study_row *{
pointer-events: none;
}
.blub{
border-color: blue;
}
<div class="wrapper_study">
<div class="study_row study">
<div class="study_year">aaaa</div>
<div class="study_name">bbbb</div>
</div>
<div class="study_row work">
<div class="study_year">aaaa</div>
<div class="study_name">bbbbb</div>
</div>
<div class="study_row work">
<div class="study_year">aaaa</div>
<div class="study_name">bbbbbb</div>
</div>
</div>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |