Internet Explorer 和 <select> 标签问题

8
我在Internet Explorer 7/8中遇到了以下问题:
当用户悬停在链接上时,弹出窗口会被触发。弹出窗口是一个简单的<div>,其中包含一些数据。在这个<div>标记内部,有一个带有一些<option><select>标记。我已经将mouseover/mouseout事件附加到<div>上,以便在光标悬停在该位置时,这个弹出窗口将保持打开状态。问题在于,当您单击<select>并将光标移动到任何一个<option>上时,会触发<div>标记的mouseout事件,并相应地关闭它。
如何防止IE关闭弹出窗口?
13个回答

9

您应该能够通过事件的值来检测是否是您想要的情况。虽然有点复杂,但似乎可以工作。

在您外部

的事件处理程序中,可以这样做:

<div onmouseover="if (isReal()) { toggle(); }"
     onmouseout="if (isReal()) { toggle(); }">
</div>

接下来实现 isReal 方法:

function isReal() {
    var evt = window.event;
    if (!evt) {
        return true;
    }

    var el;
    if (evt.type === "mouseout") {
        el = evt.toElement;
    } else if (evt.type === "mouseover") {
        el = evt.fromElement;
    }
    if (!el) {
        return false;
    }
    while (el) {
        if (el === evt.srcElement) {
            return false;
        }
        el = el.parentNode;
    }
    return true;
}

基本上,isReal方法只是检测事件是否来自div内部。如果是,则返回false,避免调用隐藏切换。

这基本上就是我来这里要发布的内容。 这类似于mootools如何实现它们的mouseovermouseout事件,但更加简洁。 可能是最好的解决方案。 - TJ L

2

我的建议是,在选择框获得焦点时设置另一个标志。只要标志已设置,就不要关闭div。


我已经尝试过这个了,但它不起作用,因为我需要使用jQuery的live()函数,而它不支持focus事件。 - dalizard

0

嗯,这种行为的原因是因为mouseover/out事件会冒泡,这意味着当你将鼠标悬停在弹出窗口内的任何元素上时,弹出窗口也会接收到该事件。

你可以在这里阅读更多关于这些事件的信息,以及这里了解事件冒泡。

这里有三种可能的解决方案:

  1. 将事件更改为onmouseenter/leave。你提到这并没有帮助,这听起来很奇怪,因为这些事件不应该冒泡。

  2. 检查事件中的srcElement与from/toElement的关系。

McKAMEY的改进版本检查如下:

function isReal() {
  var evt = window.event;
  if (!evt) {
      return true;
  }

  var el;
  if (evt.type === "mouseout") {
      el = evt.toElement;
  } else if (evt.type === "mouseover") {
      el = evt.fromElement;
  }
  if (!el) {
      return false;
  }
  // this will also return true if el == evt.srcElement
  return evt.srcElement.contains(el);
}

做相同的事情,只是更短。

3. 另一个选项是创建一个透明的、不可见的 div,在你的弹出窗口下方,覆盖下拉选择框所在的区域。我假设它是在弹出窗口的实际区域之外下拉的。

希望这可以帮助到您!


0
你尝试过使用hover代替mouseover/out效果吗?
$(".myDiv").hover(function(){
    $(this).show();
}, function {
    $(this).hide();
});

是的,还是不行 :-) 实际上那就是我最初的写法。 - dalizard

0

这个怎么样:

        <div id="trigger">
            Hover over me!
        </div>

    <div class="container">
        <select>
            <option>Blah</option>
            <option>Blah</option>
        </select>
    </div>


$("#trigger").mouseover(function(){
    $('.container).show();
});

$(".container").mouseleave(function(){
    $(this).hide();
});

基本思路是当你悬停在触发器上时显示容器元素,然后当你离开容器时隐藏容器。你需要定位容器,使其剪裁触发器元素,否则它会立即隐藏。

0

<select> 中,您应该使用 event.stopPropagation() 或者在 <select> 元素本身中使用 cancelBubble()


0

当鼠标通过<options>mouseover事件时,重新显示

怎么样呢?

编辑:选项的mouseover和div的mouseout的执行顺序可能会导致问题。


IE无法将事件监听器附加到<option>元素。 在Gecko / WebKit浏览器中运行,但在IE中不起作用。 - dalizard
1
我认为问题出在IE将<select>标签呈现为DOM中所有其他元素的顶部ActiveX元素。 - dalizard
@dalizard:自IE7起,选择元素是一个无窗口控件并支持z-index属性,这不是事实。然而,选项弹出框的行为就像它不是DOM的一部分一样(尽管它确实是),因此不支持DOM事件。 - Andy E

0
在 div 的 mouseout 事件中,为 div 元素添加一个超时,以便在大约 200 毫秒内隐藏 div。
然后,在 div/select 的 mouseover 事件和 select 的 click 事件中,清除存储在 div 元素中的超时。
这会在隐藏 div 之前产生非常轻微的延迟,允许 mouseover 或 click 事件在执行超时之前清除它。虽然不太美观,但应该可以工作。

那是我能想到的唯一事情。目前它被设置成这样。很遗憾我找不到更好的东西。 - dalizard

0

不要使用mouseout作为关闭div的事件,而是使用mouseleave,这样事件只会在指针离开div边界时触发,而不是在移动到其中其他元素时触发。


0
你可以尝试为选项列表添加另一个鼠标悬停事件。

您不能为选项列表添加任何事件,因为在IE下不会触发。 - dalizard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接