【问题标题】:Move active element loses mouseout event in Internet Explorer移动活动元素在 Internet Explorer 中丢失 mouseout 事件
【发布时间】:2011-04-10 19:28:01
【问题描述】:

在我使用的库中,我的任务是将元素悬停在 dom 的前面。 (我把它放大了,所以我需要看到它,然后在鼠标移开时将它缩小)。

我正在使用的库有一个简洁的解决方案,它在活动元素上使用 appendChildren 将其移动到其父元素的末尾,从而进一步靠近 dom 的末尾并依次位于顶部。

问题是我相信因为你正在移动的元素是你悬停在mouseout事件上的元素丢失了。您的鼠标仍在节点上,但 mouseout 事件没有被触发。

我已删除功能以确认问题。它在 Firefox 中运行良好,但在任何版本的 IE 中都无法运行。我在这里使用 jQuery 来提高速度。解决方案可以是简单的旧 Javascript,这将是一个偏好,因为它可能需要备份。

我不能在这里使用 z-index,因为元素是 vml,库是 Raphael,我正在使用 toFront 调用。使用 ul/li 的示例在一个简单的示例中显示问题

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script src="js/jquery.min.js" type="text/javascript"></script>
<style>
    li
    {
        border:1px solid black;
    }
</style>
</head>
<body>
<ul><li>Test 1</li></ul>
<ul><li>Test 2</li></ul>
<ul><li>Test 3</li></ul>
<ul><li>Test 4</li></ul>
<script>
$(function(){
    $("li").mouseover(function(){
        $(this).css("border-color","red");
        this.parentNode.appendChild(this);
    });

    $("li").mouseout(function(){
        $(this).css("border-color","black");
    });
});
</script>
</body>
</html>

编辑:这是一个 js 粘贴箱的链接,可以查看它的运行情况。 http://jsbin.com/obesa4

**编辑 2:** 在发布更多信息之前,请查看所有答案的所有 cmets。

【问题讨论】:

  • 我无法理解您的帖子。您希望在鼠标仍在元素上方时触发mouseout 事件吗?你的实际问题是什么?
  • 而对于 this.parentNode.appendChild(this);,您要重新添加现有的 LI 元素吗?为什么不直接添加一个 CSS 类而不是使用新的 CSS 添加/删除相同的元素?或者您的原始代码是否涉及从 UL 内部的其他地方添加一个全新的元素来模仿您在开始时提到的“扩展”尺寸效果?
  • Linkol 我正在尝试让示例代码在 ie 中工作,就像在 Firefox 中一样。 mouseout 事件不会触发。我以 li 元素为例。正如我在帖子中所说的,这些元素实际上是 VML 元素。所以像 z-index 或添加类这样的东西是行不通的,除非人们能证明自己与众不同。
  • 哦,问题/问题是帖子的标题!
  • 我正在为这个问题添加赏金。我通过在 Internet Explorer 中监视鼠标的位置并在鼠标移出该区域时重置悬停来解决了这个问题。基本上重新发明了鼠标输入/输出功能。它有效,但我更愿意找到一个更好的例子。

标签: javascript mouseevent raphael jquery-events mouseout


【解决方案1】:

问题在于 IE 处理 mouseover 的方式不同,因为它的行为类似于 mouseentermousemove 组合在一个元素上。在其他浏览器中,它只是mouseenter

所以即使你的鼠标已经进入目标元素并且你改变了它的外观并将它重新附加到它的父元素mouseover 仍然会为鼠标的每次移动而触发,该元素会再次重新附加,这会阻止其他事件处理程序从被调用。

解决方案是模拟正确的mouseover 行为,以便onmouseover 中的操作只执行一次。

$("li").mouseover( function() {
    // make sure these actions are executed only once
    if ( this.style.borderColor != "red" ) {
        this.style.borderColor = "red";
        this.parentNode.appendChild(this);
    }
});

示例

  1. Extented demo of yours
  2. Example 展示了 mouseover 浏览器之间的差异(奖励:原生 javascript)

【讨论】:

  • 太棒了,这正是我设置赏金时所希望的。我的代码现在执行得更好了,我也不必为此破解了。
  • 这是 Raphael 2.0.2 jsfiddle.net/K2bSY/2 中使用 toFront() 遇到相同问题的一个简单示例,显示了使用 Raphael 的 .data() 函数的示例修复
  • 虽然这似乎解决了问题,但我发现如果我使用 IE11 快速移动鼠标(对于较旧的 IE 可能也是如此),即使进行此更改,鼠标移出也可能不会触发.
【解决方案2】:

我能够让它与嵌套的 div 和父级上的 mouseenter 事件一起工作:

<div id="frame">
  <div class='box'></div>
  <div class='box'></div>
  <div class='box'></div>
  <div class='box'></div>
</div>
...
$('#frame').mouseenter(function() {
     $(".box").css("border-color", "black");
});

这是一个使用 Raphael 的工作版本:

http://jsfiddle.net/xDREx/

【讨论】:

  • 完全不能让它工作。当我将鼠标悬停在框上时没有任何反应。
  • 你试过链接了吗?你使用的是什么浏览器?我让它在 IE6、IE7 和 IE8 中工作。
  • 哦 mouseenter 在父级上,这基本上就是您正在做的事情。这会触发重置。好的。然而,它并没有解决事件丢失的核心问题。 (点击事件也是!)Deffo 值 200 分的一半。如果我能在没有输掉比赛的情况下达到顶峰,我会是一个快乐的人。 (JSFiddle 一定已经宕机了,现在工作得很好)
【解决方案3】:

我修改了@galambalazs 的答案,因为我发现如果我很快将鼠标悬停在 li 元素上它会失败,因为某些元素仍会保留mouseover 效果。

我想出了一个解决方案,该解决方案通过在触发mouseover 时将这些元素推入堆栈来消除未能触发mouseover 事件的元素的悬停状态。每当调用 mouseovermouseout 事件时,我都会从该数组中弹出元素并删除放置在其上的样式:

$(function(){

    // Track any hovered elements
    window.hovered = [];

    $("li").mouseover(function() {
        // make sure that these actions happen only once
        if ( $(this).css("border-color") != "red" ) {
            resetHovered ();  // Reset any previous hovered elements
            $(this).css("border-color","red");
            this.parentNode.appendChild(this);
            hovered.push(this);
        }
    });

    $("li").mouseout(function(){
        resetHovered();  // Reset any previous hovered elements
    });

    // Reset any elements on the stack
    function resetHovered () {
        while ( hovered.length > 0 ) {
            var elem = hovered.pop();
            $(elem).css("border-color","black");
        }
    }
});

我已经用 IE 11 测试了这个解决方案。可以找到一个功能示例 here

【讨论】:

    【解决方案4】:

    这很奇怪,而且似乎仅限于 IE(但 VML 也是如此)。如果父元素指定了高度,您可以将 mouseout 处理程序附加到父元素......但听起来这在您的情况下不起作用。您最好的选择是在相邻元素上使用鼠标悬停来隐藏它:

    $(function()
    {
        $("li").mouseover(function()
        {
            $("li").css("border-color", "black");
            $(this).css("border-color", "red");
            this.parentNode.appendChild(this);
        });
    });
    

    或 SVG。您可以在 SVG 中使用 z-index。

    【讨论】:

    • 嗯,替代方案是我认为这里的解决方案。基本上我需要在鼠标悬停的所有其他元素上调用一个重置函数,这将触发收缩动画。它非常笨重,但它可能会起作用。我现在就给这个答案投票,看看其他人是否能想到什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-19
    • 1970-01-01
    • 1970-01-01
    • 2015-02-27
    • 2013-07-25
    • 2016-04-22
    相关资源
    最近更新 更多