LOGO: 深埋在最最狂野的季节
WWW.VGOT.NET
My heart is like an open highway, Like franke said I did it my way.
科技创造力量,网络成就梦想。凝聚天下,开阔眼界

onmouseout 经过内部元素时被触发的解决方法

发布时间:2010/04/10 20:58 分类:Web前端 作者:pader 点击:73564
Web前端

我们在使用 JavaScript 的 onmouseout 或 onmouseover 事件时,如果鼠标经过事件绑定的元素内部的元素时,都会触上以上两个事件,这个问题想必您即然来看此文章,必然是知道了。
在 IE 下有一个 onmouseleave 和 onmouseenter 事件,Look:

<div onmouseleave="alert('Out');" onmouseout="alert('In');";>
    <div>我是内部元素</div>
    这是鼠标经过的主元素
</div>

可是这个事件除了 IE 以外,别的浏览器就没有了,不知道是标准重要,还是实用的人性化重要。W3C 横行的今天,标准是统一了,可是尽增加各种麻烦。(我都不知道这个JS事件跟W3C 有什么关系?)
以前写过一个函数,看:

/*
  鼠标 onmouseleave 修复事件,兼容IE和FF
  参数e 是对象传递的触发事件 FF下想访问event对象必须传递event参数
  参数o 是目标DIV对象
  onmouseout="leaveFix(event,this,function(){alert('leave')})";
*/
function leaveFix(e,o,funcCallBack) {
  // FF 下判断鼠标是否离开
  if(window.navigator.userAgent.indexOf("MSIE") == "-1") {
    var reltg = e.relatedTarget ? e.relatedTarget : e.type == 'mouseout' ? e.toElement : e.fromElement;
    while (reltg && reltg != o)
      reltg = reltg.parentNode;
    if(reltg != o) {
      funcCallBack();
    }
  } else {
    // IE
    if(o.contains(event.toElement ) == false) funcCallBack();
  }
}

这个事件写在元素标签内部用来解决 onmouseout 在经过内部元素也被触发的问题,上面例子的写法用上这个函数这样写:
<div onmouseout="leaveFix(event,this,function(){ alert('In'); });";>
    <div>我是内部元素</div>
    这是鼠标经过的主元素
</div>

OK,这个问题解决了,各个浏览器下通行。
那么下面,我想要使用监听的方式,哎呀,这就麻烦了,传递 event 经常就是一件麻烦事。
下面的代码就解决了此问题
/*
  由于ff 不支持 onmouseenter 和 onmouseleave。
  下面这个方法 就是为了解决 ff 下的这个问题。
  用法:
  mousel.addEvent(Object, 'mouseenter', function(){
    //do something here
  });

*/
var mousel = {
  evtHash: [],

  ieGetUniqueID: function(_elem) {
    if(_elem === window) { return 'theWindow'; }
    else if(_elem === document) { return 'theDocument'; }
    else { return _elem.uniqueID; }
  },

  addEvent: function(_elem, _evtName, _fn) {
    var _useCapture = false;
    if(typeof _elem.addEventListener != 'undefined') {
      if(_evtName == 'mouseenter') { _elem.addEventListener('mouseover', mousel.mouseEnter(_fn), _useCapture); }
      else if(_evtName == 'mouseleave') { _elem.addEventListener('mouseout', mousel.mouseEnter(_fn), _useCapture); } 
      else { _elem.addEventListener(_evtName, _fn, _useCapture); }
    } else if(typeof _elem.attachEvent != 'undefined') {
      var key = '{FNKEY::obj_' + mousel.ieGetUniqueID(_elem) + '::evt_' + _evtName + '::fn_' + _fn + '}';
      var f = mousel.evtHash[key];
      if(typeof f != 'undefined') { return; }
      
      f = function() { _fn.call(_elem); };
    
      mousel.evtHash[key] = f;
      _elem.attachEvent('on' + _evtName, f);
  
      // attach unload event to the window to clean up possibly IE memory leaks
      window.attachEvent('onunload', function() {
        _elem.detachEvent('on' + _evtName, f);
      });
    
      key = null;
      //f = null; /* DON'T null this out, or we won't be able to detach it */
    } else { _elem['on' + _evtName] = _fn; }
  },  

  removeEvent: function(_elem, _evtName, _fn, _useCapture) {
    if(typeof _elem.removeEventListener != 'undefined') { _elem.removeEventListener(_evtName, _fn, _useCapture); }
    else if (typeof _elem.detachEvent != 'undefined') {
      var key = '{FNKEY::obj_' + mousel.ieGetUniqueID(_elem) + '::evt' + _evtName + '::fn_' + _fn + '}';
      var f = mousel.evtHash[key];
      if(typeof f != 'undefined') {
        _elem.detachEvent('on' + _evtName, f);
        delete mousel.evtHash[key];
      }
      key = null;
      //f = null; /* DON'T null this out, or we won't be able to detach it */
    }
  },
  
  mouseEnter: function(_pFn) {
    return function(_evt) {
      var relTarget = _evt.relatedTarget;        
      if(this == relTarget || mousel.isAChildOf(this, relTarget)) { return; }
      _pFn.call(this, _evt);
    }
  },
  
  isAChildOf: function(_parent, _child) {
    if (_parent == _child) { return false };
    while(_child && _child != _parent) { _child = _child.parentNode; }
    return _child == _parent;
  }  
};

用法的简单演示:
var myObject = document.getElementById("chop");
mousel.addEvent(myObject, 'mouseenter', function(){
  alert("Mouse enter!");
});

第一个参数传递对象,第二个是 "mouseenter" 或 "mouseleave",第三个就是要执行的函数了。
jQuery 同样提供和这个一个的绑定事件,但是我们同样有必要了解此代码的运行机制,实现的原理都是当 onmouseout 的时候判断鼠标所在当前元素是不是其子元素,如果是,则认为鼠标仍然没有移出。

本文内容由 VGOT Design 原创,转载请保留原文链接:http://www.vgot.net/?A66.htm

网友评论
  • 评论正在加载...
发表评论
名字: 主页: 邮箱:
© Copyrights VGOT.NET 2008-2009 皖ICP备17000202号-1
Processed in 0.0059741 second(s), 4 Queries, Memory 572.76 KB.