mouseenter delegation using vanilla JavaScript?
Asked Answered
A

2

13

How do I implement event delegation for the mouseenter event?

I'm looking for the equivalent to this jQuery code, but didn't manage to understand how jQuery does it internally:

$(document).on('mouseenter', '.demo', foo);

I've seen this other question about it, but no proper solution was provided.

I've also read Mozilla docs regarding mouseenter and delegation, and besides saying it's not compatible with any browser, the example they provided throws error on the JS console and doesn't work.

I've also checked this codepen, which doesn't work on Chrome either (didn't try other browsers).

Any idea?

This is what I'm trying so far, but the target element seems to always bubble up:

document.addEventListener('mouseenter', function(e) {
    console.log('==============================');
    console.log(e.currentTarget); //document
    console.log(e.target); //document 
    console.log(e.relatedTarget); //nothing
    console.log(e.handleObj); //nothing
});

You can play with it in this jsfiddle.

Afterdamp answered 4/5, 2018 at 14:30 Comment(5)
They might not exist on load. They can be dynamically added and I have no control over when and how.Afterdamp
Oh, right, I forgot that was a thingBrueghel
We opted for going for mouseover and a variable to store the last element hovered over. That way event.target will actually contain the element hovered over and you can check its class to see if it should do something. Next hover, you can check if the next element hovered over is a child or not of the previous one.Pagandom
@Pagandom but how do you get the target element? I'm always getting document when trying to use delegation. e.target doesn't give me the actual element.Afterdamp
@LucaRainone can't seem to easily extract what I need from jquasiAfterdamp
N
23

You have to add the event listener on capturing phase, passing true as third argument:

document.body.addEventListener("mouseenter", function(e) {
    if(e.target.className === "demo") {
        console.log("catched");
    }
},true); // capturing phase

You can do something of more elaborated in order to catch the selector. But that's the key.

Demo here https://codepen.io/anon/pen/Xqaxwd

Ninepins answered 4/5, 2018 at 15:14 Comment(1)
That's the issue! I forgot the true on the last parameter!! :DAfterdamp
R
-2

Maybe you can use mousemove and keep track of the current element (keeping in mind parents) like this:

let lastTarget = null;

document.addEventListener('mousemove', function(e) {
 const target = checkWithParents(e.target);
 if (target && target != lastTarget) {
   alert('mouseenter');
 }
 lastTarget = target;
})

function checkWithParents(el) {
  while (el) {
    if (el && el.classList && el.classList.contains('demo')) {
      return el;
    }
    el = el.parentNode;
  }
  return null;
}
.demo {
  background-color: tomato;
  height: 300px;
  width: 300px;
  margin: 50px;
}
<div class="demo"><div class="inner"></div></div>
<div class="demo"><div class="inner"></div></div>
Retinitis answered 4/5, 2018 at 14:55 Comment(3)
Nop. Need mouse enter. The mouse might not move :)Afterdamp
@Afterdamp I think even jquery doesn't work like how you want, check this fiddle, put your mouse to the right of the div and when the div moves over your mouse nothing will happen (unless you move the mouse).Retinitis
I can scroll up and down without moving the mouse (only using wheel effect of the trackpad) and the alert keeps firing.Afterdamp

© 2022 - 2024 — McMap. All rights reserved.