Javascript中onmouseout与onmouseleave

在IE下解决问题很简单,用onMouseEnter、onMouseLeave来代替onMouseOver、onMouseOut就行了,他们的作用基本相同,前者不会发生冒泡。但是firefox下没有这两个事件,如果用 jQuery的event事件,只要bind mouseleave和mouseenter即可。如果是纯js实现,只能这么做:
 
通过判断触发onMouseOut事件后鼠标到达的元素是不是包含在父元素(信息栏Div)内,如果是就表示鼠标还在信息栏上,则不隐藏,如果否就表示鼠标真的移出了信息栏,那么信息栏隐藏,思路有了,那么就一步步来解决问题
 
首先来获取触发onMouseOut事件的元素,IE下event的属性toElement来获得,在firefox下变成了relatedTarget(很是折腾!)
IE:event.toElement    Firefox:event.relatedTarget(注意Firefox下event须要调用函数时传入)
 
接下来就是判断获取的元素是否是子元素,IE下通过元素的contains(Element)方法可以判断,同样的firefox下没有这个方法!!,不过可以给firefox下的元素定义contains()方法来解决问题,代码如下:
 
if(typeof(HTMLElement)!="undefined")    //给firefox定义contains()方法,ie下不起作用
{  
      HTMLElement.prototype.contains=function(obj)  
      {  
          while(obj!=null&&typeof(obj.tagName)!="undefind"){ //通过循环对比来判断是不是obj的父元素
       if(obj==this) return true;  
       obj=obj.parentNode;
     }  
          return false;  
      };  
}  

获取和判断搞定后,我们就可以通过判断IE和Firefox来针对处理了,通过navigator.userAgent来判断浏览器:
    if(navigator.userAgent.indexOf("MSIE")>0) {
         return "MSIE";
   }
   if(navigator.userAgent.indexOf("Firefox")>0){
        return "Firefox";
   }

到此为止所有要解决的问题都得到了解决,当触发onMouseOut事件时我们针对不同的浏览器先获取鼠标到达的元素,然后通过判断该元素是否在信息栏(div)内,如果元素是子元素,那么不执行onMouseOut事件,反之则执行事件,隐藏信息栏,完成后的代码如下:
function hideMsgBox(theEvent){ //theEvent用来传入事件,Firefox的方式
         if (theEvent){
               var browser=navigator.userAgent;   //取得浏览器属性
               if (browser.indexOf("Firefox")>0){ //如果是Firefox
                    if (document.getElementById('MsgBox').contains(theEvent.relatedTarget)) { //如果是子元素
                        return;   //结束函式
                         }
                }
                  if (browser.indexOf("MSIE")>0){ //如果是IE
                           if (document.getElementById('MsgBox').contains(event.toElement)) { //如果是子元素
                                 return; //结束函式
                            }
                  }
             }
            /*要执行的操作*/
}

在信息栏(Div)上设置onMouseOut=hideMsgBox(event)来调用,解决冒泡问题。
通过设置
window.event.cancelBubble = true (IE) event.stopPropagation() event.preventDefault() (Firefox)
也可以解决问题,但是需要遍历所有子元素,影响效率,所以还是在触发onMouseOut事件时再进行上述判断分别处理比较合适。
 
================其他方法===========================
 
方案一:
 
希望实现 当鼠标离开一个DIV的时候触发一个事件处理函数 于是用onmouseout 结果却发现它的触发是不是也太敏感了 原因现在也没有弄清楚 IE下好像是因为区分mouseout时的fromElement还是toElement ,IE 5.5以上的onmouseleave事件就比较好用 偏FF又不支持这个事件 只有自己想办法手工判断了。

<SCRIPT>
/***
 * 参数e 是对象传递的触发事件 FF下想访问event对象必须传递event参数
* 参数o 是目标DIV对象
*/  
function fun(e,o) {
         /* FF 下判断鼠标是否离开DIV */
         if(window.navigator.userAgent.indexOf("Firefox")>=1) {
             var x = e.clientX + document.body.scrollLeft;
             var y = e.clientY + document.body.scrollTop ;
             var left = o.offsetLeft;
             var top = o.offsetTop;
             var w = o.offsetWidth;
             var h = o.offsetHeight;
            
             if(y < top || y > (h + top) || x > left + w || x<left ) {
                 alert("mouseout");
             }
         }
 
        /* IE */
         if(o.contains(event.toElement ) == false    )
 alert("mouseout");
        
     }
< /SCRIPT>
 
< DIV onmouseout=fun(event,this)>content</DIV>

需要注意 在取鼠标的值的时候 一定要加上滚动条已经拖动过的内容e.clientY + document.body.scrollTop 如果只是e.clientY得到是个错误的值 当然如果高宽都很小 是看不出来问题。 取一个对象的高和宽 也可以使用 clientHeight clientWidth 属性 以后遇到FF IE不兼容的时候要多看看FF的开发手册http://developer.mozilla.org/en/docs/DOM:element.offsetLeft
  
方案二:(与一相似)
 
js的onmouseout有很奇怪的一个问题。例如
 
<div onmouseout="alert(123)">
 
< a href="#">test</a>
 
< /div>
 
我们预期只有当鼠标从div中移开的时候才会触发onmouseout事件,可是,事实上,当我们移到div中的元素时,例如本例中的a标签时,就 会触发onmousout事件。也就是说,移到对象的子对象上,也算onmouseout了。这往往会让我们预期的效果达不到。今天的工作就遇到了这个问 题。在blueidea上搜了一下,找了解决办法。兼容IE和FF。

< !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>test</title>
< /head>
 
< body>
< script type="text/javascript">
function test(obj, e) {
if (e.currentTarget) {
 if (e.relatedTarget != obj) {
if (obj != e.relatedTarget.parentNode) {
alert(1);
 }
}
} else {
if (e.toElement != obj) {
 if (obj != e.toElement.parentNode) {
alert(1);
}
}
 }
}
 < /script>
< div onmouseout="test(this, event)" style="width:100px;height:100px;border:1px #666 solid">
 < span style="margin:5px;width:100%;height:100%;border:1px #ff0000 solid">faddsf</span>
< /div>
< /body>
 < /html>
 
今天发现JQ中关于这个问题,已经有了一个好的解决办法了.呵呵,jquery中定义了一种事件叫做"mouseleave",用这个事件做事件句柄的话,就可以解决这个问题了.越来越发现jquery是个好东西了.
 
方案三:
  
jQuery V1.2.2推荐用bind("mouseleave",function(){})来代替以前的mouseover方法用bind("mouseenter",function(){})来代替mouseout,同样也针对以前的hover方法,要看详细的说明点这个地址:http://docs.jquery.com/Release:jQuery_1.2.2
 
$(document).ready(function() {
    $("#a1").bind("mouseleave", function(){
    $('<div style="color:red;">out</div>')
    .insertAfter($(this));
});
});

 

你可能感兴趣的:(js,onmouseout,onmouseover,onmouseleave,onmouseenter)