简体   繁体   English

通过点击触发鼠标离开

[英]Mouseleave triggered by click

I have an absolutely-positioned div, and I'm trying to keep track of when the mouse moves over it, and when the mouse leaves.我有一个绝对定位的 div,我试图跟踪鼠标何时移过它以及鼠标何时离开。 Unfortunately clicking on the text in the box occasionally triggers the mouseleave event.不幸的是,单击框中的文本偶尔会触发 mouseleave 事件。

DEMO: js fiddle演示: js 小提琴

How can I prevent this?我怎样才能防止这种情况?

JS 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 HTML

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

</div>

CSS 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;
}

This seems to be a bug (I could reproduce it in Chrome with clicks that have the mouse down and mouse up happening rapidly after each other).这似乎是一个错误(我可以通过点击在 Chrome 中重现它,使鼠标向下和鼠标快速发生在彼此之后)。

I would suggest to work around this issue by checking whether the mouse is still over the element at the moment the event is fired:我建议通过检查在触发事件时鼠标是否仍在元素上来解决此问题:

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

The downside is that when the browser window loses focus, that is also considered a false positive.缺点是当浏览器窗口失去焦点时,这也被认为是误报。 If that is an issue for you, then check this answer .如果这对您来说是个问题,请查看此答案

I had previously looked at the answers and comments here, but recently found a way to check if the mouseleave event was triggered erroneously我之前看过这里的答案和评论,但最近找到了一种检查mouseleave事件是否被错误触发的方法

I added a check in my mouseleave handler:我在我的mouseleave处理程序中添加了一个检查:

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

From my testing on Chrome v64, both of these values will be null whenever fast clicking causes the mouseleave event to be triggered.根据我在 Chrome v64 上的测试,只要快速点击导致mouseleave事件被触发,这两个值都将为null The relatedTarget is for older browser compatibility relatedTarget用于旧浏览器兼容性

Note: both of these values will also be null if the mouse leaves the target element and enteres the Browser (eg the tabs, menus etc), or leaves the browser window.注意:如果鼠标离开target元素并进入浏览器(例如选项卡、菜单等)或离开浏览器窗口,这两个值也将为null For my purposes that was not a problem, as it is a sliding menu I am working with, and leaving the Browser window should not close the menu in my particular case.出于我的目的,这不是问题,因为它是我正在使用的滑动菜单,在我的特定情况下,离开浏览器窗口不应关闭菜单。

Note : latest Firefox release (Feb 2018) seems to trigger mouseleave on every click of my menu!注意:最新的 Firefox 版本(2018 年 2 月)似乎在每次单击菜单时都会触发mouseleave Will have to look into it将不得不调查它

I also ran into this bug.我也遇到了这个bug。 In my case, I added label wrapped checkboxes into a list, and wrapped the list in a div.就我而言,我将标签包装的复选框添加到列表中,并将列表包装在 div 中。 I also used some list items that were <hr> tags.我还使用了一些<hr>标签的列表项。 If you click around the checkboxes and labels quickly you will occasionally trigger a mouseleave event on the wrapping div.如果您快速点击复选框和标签,您偶尔会在包装 div 上触发mouseleave事件。 This shouldn't occur as all clicked elements are children of the div.wrapper .这不应该发生,因为所有点击的元素都是div.wrapper子元素。

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

jsfiddle demo jsfiddle 演示

Here's a gif of the reproduction.这是复制品的 gif。 Click within the clue area (granted with some intensity and movement), click events from the label and input boxes are firing and then you see two mouseleave events fire in error, and then a third when the mouse truly leaves the blue area.在线索区域内单击(具有一定的强度和移动性),来自标签和输入框的单击事件正在触发,然后您会看到两个mouseleave事件错误触发,然后当鼠标真正离开蓝色区域时触发了第三个。

样品复制

The answer by @trincot almost worked for me. @trincot 的回答几乎对我有用。 In my case I'm dealing with popovers.就我而言,我正在处理弹出窗口。 When I click on a button, it triggers a popover showing up on top of the triggering button.当我点击一个按钮时,它会触发一个弹出窗口,显示在触发按钮的顶部。 So document.elementFromPoint(e.clientX, e.clientY) returns the popover element rather than the triggering button.所以document.elementFromPoint(e.clientX, e.clientY)返回的是document.elementFromPoint(e.clientX, e.clientY)元素而不是触发按钮。 Here's how I solved this:这是我解决这个问题的方法:

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;
}
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
});

Check if the primary button is pressed with MouseEvent.buttons .检查是否使用MouseEvent.buttons按下了主按钮。

tooltip.onmouseleave = (e) => {
  if (e.buttons !== 1) {
    console.log('tooltip mouse OUT')
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM