鼠标移出事件的问题

时间:2020-03-05 18:49:20  来源:igfitidea点击:

我正在使用JavaScript隐藏图像并显示隐藏在其下方的一些文本。但是,如果在滚动时显示文本,则会在容器上触发mouseout事件,然后隐藏该文本并再次显示图像,这只会进入一个怪异的循环。

html看起来像这样:

<div onmouseover="jsHoverIn('1')"
     onmouseout="jsHoverOut('1')">
    <div id="image1" />
    <div id="text1" style="display: none;">
        <p>some content</p>
        <p>some more content</p>
    </div>
</div>

和javascript(它使用脚本):

function jsHoverIn(id) {
  if(!visible[id]) {
    new Effect.Fade ("image" + id, {queue: { position: 'end', scope: id } });
    new Effect.Appear ("text" + id, {queue: { position: 'end', scope: id } });
    visible[id] = true;
  }
}
function jsHoverOut (id) {
  var scope = Effect.Queues.get(id);
  scope.each(function(effect) { effect.cancel(); });

  new Effect.Fade ("text" + id, {queue: { position: 'end', scope: id } });
  new Effect.Appear ("image" + id, {queue: { position: 'end', scope: id } });
  visible[id] = false;
}

这看起来真的很简单,但是我不能把头包住。

解决方案

回答

这可能不是最好的解决方案,但是我们可以设置一个全局布尔变量,这两个方法都可以访问这两个变量,它们仅指定最后一个动作是HoverIn还是HoverOut。我们可以使用此布尔变量确定代码是否应该运行。

if (bWasHoverIn){
   ...
}

回答

onmouseover事件不应该在图像div上,onmouseout事件不应该在文本div上吗?

回答

@Ryan布尔值并没有真正的帮助,只是避免了循环,但是mouseover事件仍然被触发并且文本被隐藏。

@Brian曾经是这种方式,但其行为方式却是相同的。

回答

我给容器div:

position: relative;

并在容器中添加第三个div(应为容器的最后一个子元素),并带有:

position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;

并在此div上捕获mouseover和mouseout事件。

由于它没有子元素,因此不应散布虚假的mouseover和mouseout事件。

编辑:

我相信发生的是,当光标从父元素移动到子元素时,在父元素上发生mouseout事件,在子元素上发生mouseover事件。但是,如果子元素上的mouseover处理程序没有捕获到该事件并停止传播,则父元素也将收到mouseover事件。

回答

我不确定这是否适合其余样式,但是也许我们是否更改了文本div上的css,使其与图像大小相同,或者固定了外部div的大小,则将鼠标悬停触发事件后,外部div的大小变化不会太大,不会引起mouseout事件。

这有意义吗?

回答

听起来我们真正想要的是mouseenter/mouseleave(IE专有事件,但易于模拟):

// Observe mouseEnterLeave on mouseover/mouseout
var mouseEnterLeave = function(e) {
    var rel = e.relatedTarget, cur = e.currentTarget;
    if (rel && rel.nodeType == 3) {
        rel = rel.parentNode;
    }
    if(
        // Outside window
        rel == undefined ||
        // Firefox/other XUL app chrome
        (rel.tagName && rel.tagName.match(/^xul\:/i)) ||
        // Some external element
        (rel && rel != cur && rel.descendantOf && !rel.descendantOf(cur))
    ) {
        e.currentTarget.fire('mouse:' + this, e);
        return;
    }
};
$(yourDiv).observe('mouseover', mouseEnterLeave.bind('enter'));
$(yourDiv).observe('mouseout', mouseEnterLeave.bind('leave'));

// Use mouse:enter and mouse:leave for your events
$(yourDiv).observe(!!Prototype.Browser.IE ? 'mouseenter' : 'mouse:enter', yourObserver);
$(yourDiv).observe(!!Prototype.Browser.IE ? 'mouseleave' : 'mouse:leave', yourObserver);

或者,对prototype.js进行补丁,并放心使用mouseentermouseleave。请注意,我已经扩大了离开窗口或者输入XUL chrome的支票;这似乎为我修复了Firefox中的一些极端情况。