Mouse clicked

I have an absolutely positioned div, and I'm trying to track when the mouse moves around it and when the mouse leaves. Unfortunately, clicking on the text in the field sometimes triggers a mouseleave event.

DEMO: js violin

How can I prevent this?

Js

let tooltip = document.createElement('div');
tooltip.innerHTML = 'HELLO WORLD';
tooltip.setAttribute('class', 'tooltip');
tooltip.style.display = 'none';

tooltip.onclick = evt => {
    console.log('click')
    evt.stopPropagation();
}
tooltip.ondblclick = evt => {
    console.log('double click')
    evt.stopPropagation();
}

tooltip.onmouseenter = () => {
    console.log('tooltip mouse OVER');
}

tooltip.onmouseleave = () => {
    console.log('tooltip mouse OUT')
}

tooltip.style.left = '290px';
tooltip.style.top = '50px';
tooltip.style.display = 'block';
document.body.appendChild(tooltip);

HTML

<div style="width: 300px; height: 300px; background-color: lightblue">

</div>

CSS

.tooltip {
    position: absolute;
    /*display: none;*/
    left: 100;
    top: 100;
    min-width: 80px;
    height: auto;
    background: none repeat scroll 0 0 #ffffff;
    border: 1px solid #6F257F;
    padding: 14px;
    text-align: center;
}
+15
source share
5 answers

This seems to be a mistake (I can play it in Chrome with clicks that have the mouse down and the mouse quickly happens one after another).

I would suggest getting around this problem by checking if the mouse is over the entire element at the time the event fires:

tooltip.onmouseleave = (e) => {
    if (tooltip === document.elementFromPoint(e.clientX, e.clientY)) {
        console.log('false positive');
        return;
    }
    console.log('tooltip mouse OUT')
}

, , . , .

+9

, , mouseleave

mouseleave:

private handleMouseLeave(event: MouseEvent) {
    if(event.relatedTarget || event.toElement){
        // do whatever
    }
    // otherwise ignore
}

Chrome v64 null , mouseleave. relatedTarget

. null, target (, , ..) . , , , .

: Firefox ( 2018), , mouseleave !

+9

. , , div. , <hr>. , mouseleave div. , div.wrapper.

...
  wrapper.addEventListener(
    'mouseleave',
    (e) => {
      logger('mouseleave fired');
      console.log('mouseleave fired', e);
    },
    false
  );
...

jsfiddle demo

gif . ( ), , , mouseleave , , .

Playback example

+4

@Trincot's answer almost worked for me. In my case, I deal with popover. When I click on the button, it launches a pop-up window displayed on top of the start button. Therefore, it document.elementFromPoint(e.clientX, e.clientY)returns a popover element, not a start button. Here is how I solved it:

mouseleave(ev: MouseEvent) {
    const trigger: HTMLElement = document.getElementById('#myTrigger');
    const triggerRect = trigger.getBoundingClientRect();
    const falsePositive = isWithingARect(ev.clientX, ev.clientY, triggerRect);

    if (!falsePositive) {
        // do what needs to be done
    }
}

function isWithingARect(x: number, y: number, rect: ClientRect) {
  const xIsWithin = x > rect.left && x < rect.right;
  const yIsWithin = y > rect.top && y < rect.bottom;
  return xIsWithin && yIsWithin;
}
0
source
var trackmouseup = null;

$('.box').mouseup(function(event){
    if(trackmouseup){
        clearTimeout(trackmouseup);
    }
    trackmouseup = setTimeout(function(){
        trackmouseup = null;
    }, 2); //it must be 2ms or more

});


$('.box').mouseleave(function(event){
    //if this event is triggered by click, there must be a mouse up event triggered 2ms ago
    if(trackmouseup){
        return;
    }

    //to do something
});
-1
source

All Articles