Alvaro
Alvaro

Reputation: 41605

mouseenter delegation using vanilla JavaScript?

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.

Upvotes: 14

Views: 3775

Answers (2)

Luca Rainone
Luca Rainone

Reputation: 16468

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

Upvotes: 24

Amr Noman
Amr Noman

Reputation: 2647

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>

Upvotes: -2

Related Questions