【问题标题】:onmouseout not fired when element goes away元素消失时未触发 onmouseout
【发布时间】:2012-05-22 22:25:00
【问题描述】:

我有一个触发工具提示的鼠标悬停事件;我希望这个工具提示在鼠标被移除时消失。 onmouseout 效果很好,除了当元素消失时。

这是一个使用背景更改而不是工具提示的提炼示例(因此您可以轻松运行它):

<div id="bar">
  <div onmouseover="document.bgColor='gray'" onmouseout="document.bgColor='white'" style="border:1px solid black;">
   <span onclick="document.getElementById('bar').innerHTML = ''">Remove me</span>
  </div>
</div>

问题是这样的:当我单击“删除我”时,我的鼠标不再“在”div 上,但是 onmouseout 没有触发,因为它已经消失了。当我单击“删除我”时,我希望此示例恢复为白色背景。

有一个明显的解决方案,我想避免。我不希望删除元素的 onclick 处理程序手动“修复”文档。这是因为可能有任意多个处理程序可以使用 onmouseout 删除 div。通常,所有的 mouseout 和删除处理程序都可能是动态生成的,并且需要相互了解。更复杂的是,我可能会遇到可移动元素相互嵌套的情况,并且它们中的任何一个都可以被删除。 (我也许可以移除这个限制,但需要做一些工作。)


这是一个可行的解决方案示例:鼠标悬停时,将模式对话注册为“活动”;然后每当删除元素时,遍历所有模态对话并查找不再在文档中的那些。但这需要我保持全局的对话存储,并且需要时间 O(n*m),其中 n 是活动对话的数量,m 是对话在 DOM 中的嵌套深度。此外,每当我删除元素时,我都需要运行此操作,即使很明显没有任何影响。

这是另一个可行的解决方案:如果您可以实现 onremovedfromdocument 事件,那么我们只需将 onmouseout 处理程序复制为 onremovedfromdocument 事件,该示例也将正常工作。 (我听说 jQuery 可能支持这个,但我需要与非 jQuery 代码互操作。)

这里还有另一种可能的解决方案:让每个模态对话重复轮询以查看其父级是否在文档中。如果不是,让它提交 seppuku。但是民意调查真的很丑。 (如果没有更好的办法,我想我愿意这样做!)

这里还有一个思路:使用事件捕获让onmouseout元素先捕获点击元素,并设置一个定时器来检测点击完成后是否还在文档中。


作为参考,这是我真正想做的事情:我有一个构建复杂树结构的 JS 小部件。对小部件的许多编辑涉及单击树中的某个按钮,然后从树中添加或删除(可能会自行删除。)但是,某些节点需要更复杂的编辑过程,所以我想提出一个工具提示当用户将鼠标悬停在它们上时,带有说明和可能的更多按钮,或者如果用户单击它们,甚至可以保持对话。但是用户可能会改变主意并决定删除节点或节点的任何父节点,在这种情况下对话应该消失。您可以查看我目前拥有的here 的实现,其中对话是手动创建的。我想开始使用一个不错的工具提示库,但它们都有我上面描述的错误。

【问题讨论】:

  • 当你没有相应的开始标签时,你有一个结束&lt;/a&gt;标签的原因吗?您的跨度也是无效的 html。你需要一个结束跨度。
  • 您的跨度仍然是无效的 html。 不存在。

标签: javascript javascript-events


【解决方案1】:

在现代浏览器上,有DOMNodeRemoved 事件。所以:

var div = document.getElementsByTagName('div')[0];
div.addEventListener('DOMNodeRemoved', function(e){
    document.bgColor='white';
});​

http://jsfiddle.net/HX88L/

不好的是,那个事件已经是deprecated。所谓的mutation events 的替代品看起来还没有准备好使用。 MDN 文档页面仍然只是一个stub

【讨论】:

  • 不错!你知道浏览器必须有多现代吗?编辑:重新,弃用,太糟糕了!
  • 我读到它适用于 IE9、Chrome 和 Firefox - 请参阅 stackoverflow.com/a/6987471/825789
  • 奇怪的是,无论出于何种原因,在完整示例中这不起作用。我不知道为什么。
【解决方案2】:

尝试:

    <script>
    var liveToolTip = new Array();
    function addLiveToolTip(elName){
        if(elName in liveToolTip){
        }else{
            liveToolTip[elName]=1;}
    }
    function removeLiveToolTip(elName){
        if(elName in liveToolTip){
            delete liveToolTip[elName];
        }
    }
    function runOnMouseOuts() {
        for(mouseOut in liveToolTip) {
            document.getElementById(mouseOut).onmouseout();
        }
    }
</script>
<div id="bar">
  <div onmouseover="addLiveToolTip(this.id);document.bgColor='gray'" 
        onmouseout="removeLiveToolTip(this.id);document.bgColor='white'" style="border:1px solid black;" id="foo">
      <span onclick="document.getElementById('bar').innerHTML = '';runOnMouseOuts()">
      Remove me</span>
  </div>

【讨论】:

  • 此解决方案未通过模块化测试。如果 bar 内有多个 onmouseout 处理程序怎么办?
  • 我认为 onmouseoutevent 被调用是希望。您也可以直接更改背景颜色。我已经对其进行了编辑。
  • 考虑到 文档 的背景已更改,您的编辑无济于事;不是div 的内容。
  • 这是期望的行为吗?
  • 你没有抓住重点。关键是在 任何 活动工具提示中执行 onmouseout 中的任何操作,而无需对其中一个进行硬编码。
猜你喜欢
  • 2014-01-08
  • 2021-06-16
  • 2023-03-25
  • 2013-02-14
  • 1970-01-01
  • 2022-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多