代码之家  ›  专栏  ›  技术社区  ›  Juan

MouseOut事件的问题

  •  6
  • Juan  · 技术社区  · 16 年前

    我使用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(它使用scriptaculous):

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

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

    6 回复  |  直到 8 年前
        1
  •  5
  •   SpoonMeiser    16 年前

    我会把集装箱分类:

    position: relative;
    

    并在容器中添加第三个DIV(应为容器的最后一个子级),其中:

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

    在这个分区中捕捉mouseover和mouseout事件。

    因为它没有子元素,所以不应该得到虚假的mouseover和mouseout事件传播到它。

    编辑:

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

        2
  •  4
  •   eyelidlessness    16 年前

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

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

    或者, patch prototype.js 使用 鼠标器 鼠标器 充满信心。请注意,我已经扩展了对离开窗口或进入xul chrome的检查;这似乎修复了我在firefox中的一些边缘情况。

        3
  •  0
  •   Ryan Lanciaux    16 年前

    这可能不是最好的解决方案,但您可以设置一个全局布尔变量,这两个方法都可以访问该变量,只需指定最后一个操作是hoverin还是hoverout。您可以使用这个布尔变量来确定代码是否应该运行。

    if (bWasHoverIn){
       ...
    }
    
        4
  •  0
  •   Brian Chiasson    16 年前

    OnMouseOver事件不应该在image DIV上,而OnMouseOut事件应该在文本DIV上吗?

        5
  •  0
  •   Juan    16 年前

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

    @布赖恩以前是那样的,但现在也一样。

        6
  •  0
  •   pkaeding    16 年前

    我不确定这是否适合您的其他样式,但也许如果您更改了文本DIV上的CSS,使其与图像大小相同,或者修复了外部DIV的大小,那么当mouseover事件触发时,外部DIV的大小不会更改太多,从而导致mouseout事件。

    这有道理吗?