話說有一個DIV元素,其內部有一個IMG元素和SPAN元素,不用理會這兩個內部元素怎么布局,這不是我要討論的重點。
為了實現一些特殊的效果,我需要利用TD的onmouseover和onmouseout事件,測試時就會發現如下的狀況:
當鼠標移入DIV內部時,onmouseover事件被觸發;接着再鼠標移動到DIV內部的IMG或者SPAN元素之上,我們肯定不會認為這時鼠標已經移到了DIV的外邊,但奇怪的是onmouseout事件觸發了,而且緊接着onmouseover事件也馬上被觸發了。
這可不是我想要的,那么怎么來“屏蔽”內部元素給外層元素帶來的Javascript事件干擾呢?
這里列舉兩種方法:
一. setTimeout
因為在鼠標移動到內部元素之上而觸發了外層元素的onmouseout事件后,外層元素的onmouseover也會馬上觸發,所以我們只需要把外層元素的onmouseout事件需要執行的動作延遲很短的一段時間來運行,然后在onmouseover事件中再執行clearTimeout方法,這樣就可以避免內部元素引起的事件干擾。
具體的執行過程請看下圖(縱向的虛線表示時間):
這是個很巧妙的的方法,因為當onmouseout觸發后,實質性的方法並沒有馬上執行,而是要等待一小段時間。如果在這段時間里馬上又觸發了 onmouseover事件,那么基本上就可以肯定onmouseout事件的觸發是因為內部元素的干擾了,所以在onmouseover事件中使用 clearTimeout來阻止延時的方法執行。
二.contains
在onmouseover時先進行如下判斷,結果為true時再執行方法體:
$("#popFormDiv").mouseover(function () {
var s = event.fromElement || event.relatedTarget;
if (!this.contains(s)) { $(this).show("slow"); }
});
在onmouseout時先進行如下判斷,結果為true時再執行方法體:
$("#popFormDiv").mouseout(function () {
var s = event.toElement || event.relatedTarget;
if (!this.contains(s)) { $(this).hide("slow"); }
});
下面來解釋一下上面兩行代碼的含義:
在IE中,所有的HTML元素都有一個contains方法,它的作用是判斷當前元素內部是否包含指定的元素。我們利用這個方法來判斷外層元素的事件是不是因為內部元素而被觸發,如果內部元素導致了不需要的事件被觸發,那我們就忽略這個事件。
event.fromElement指向觸發onmouseover和onmouseout事件時鼠標離開的元素;event.toElement指向觸發onmouseover和onmouseout事件時鼠標進入的元素。
那么上面兩行代碼的含義就分別是:
○ 當觸發onmouseover事件時,判斷鼠標離開的元素是否是當前元素的內部元素,如果是,忽略此事件;
○ 當觸發onmouseout事件時,判斷鼠標進入的元素是否是當前元素的內部元素,如果是,忽略此事件;
這樣,內部元素就不會干擾外層元素的onmouseover和onmouseout事件了。
但問題又來了,非IE的瀏覽器並不支持contains函數,不過既然我們已經知道了contains函數的作用,就可以自行添加如下的代碼來為非IE瀏覽器增加contains支持:
if (typeof (HTMLElement) != "undefined") {
HTMLElement.prototype.contains = function (obj) {
while (obj != null && typeof (obj.tagName) != "undefined") {
if (obj == this)
return true;
obj = obj.parentNode;
}
return false;
};
}
上面不的方法不兼容火狐:
方案三:
,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));
});
});
完美解決~