標籤:style blog http color java 使用 os io
原文:JS子項目oumouseover觸發父元素onmouseout
JavaScript中,父元素包含子項目:
當父級設定onmouseover及onmouseout時,滑鼠從父級移入子級,則觸發父級的onmouseout後又觸發onmouseover;從子級移入父級後再次觸發父級的oumouseout後又觸發onmouseover。而如果onmouseover內又應用了計時器便會存在較大的問題。下面針對此問題給出解決方案。
首先,在給出解決方案之前,必須先弄清楚幾個對象及方法,分別如下:
1、事件對象
2、事件對象相關屬性(只針對onmouseover及onmouseout),即fromElement、toElement、relatedTarget
3、判斷一個元素是否包含另一個元素的方法,即element.contains(Node)與element.compareDocumentPosition(Node)
既然前面已經說了要弄清如上幾個對象及方法,那麼,我們就可以分析一下倒底如何去解決這個問題。
分析:
存在的問題是設定onmouseover時,滑鼠從移入父級內時,沒任何問題,但由父級移入子級時,以及由子級稱出到父級時會出現如上問題,那麼我們可以想辦法設定當滑鼠從父級移入到子級時,或從子級移出到父級時讓觸發對象失效,我們可以通過if語句進行判斷。而事件對象裡面有個屬性可以擷取移入移出時的相關對象,下面就來介紹。
1、事件對象:可以擷取事件對象的一系列屬性,在事件中寫一個參數,即可通過參數擷取,方法如下:
1 wrap.onmouseover = function(e) {2 e = window.event || e; // window.event是為了相容ie下擷取事件對象,而e為標準瀏覽器直接擷取3 }
2、事件對象的相關對象
在觸發onmouseover及onmouseout時,必定會涉及到其它對象,如:onmouseover的相關對象,即為哪個對象進入的。onmouseout的相關對象即為進入到哪個對象。擷取方法如下:
1 wrap.onmouseover = function(e) {2 e = window.event || e;3 var s = e.fromElement || e.relatedTarget; //e.fromElement為IE下onmouseover擷取相關對象方法,relatedTarget為標準瀏覽器下擷取方法4 }5 wrap.onmouseout = function(e) {6 e = window.event || e;7 var s = e.toElement || e.relatedTarget; //e.toElementIE下onmouseout擷取相關對象方法,relatedTarget為標準瀏覽器下擷取方法8 }
3、判斷一個元素是否包含另一個元素
IE下可以使用a.contains(b)判斷a是否包含b
標準瀏覽器下a.compareDocumentPosition(b)有5個值,若為0表示為同一節點,若為2表示a位於b後面,若為4表示a位於b前面,若為10表示a為b的後代,若為20表示a為b的祖級。
先上個即將用到的樣本的HTML及CSS
1 <!doctype html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <style type="text/css"> 6 html,body,div{margin:0;padding:0} 7 .wrapper { 8 overflow: hidden; 9 width: 800px;10 background: black;11 }12 .box {13 height: 200px;14 background: #FF0;15 margin: 80px 0;16 }17 </style>18 </head>19 <body>20 <div class="wrapper" id="wrap">21 <div class="box" id="box"></div>22 </div>23 </body>24 </html>
既然知道了以上的擷取屬性及事件的必備方法,那麼我們就可以想方法解決問題了
當觸發onmouseover時,可能是從對象以外移入的,也有可能是父級移入到子級,以及子級移出到父級,剛才也說過,onmouseover的相關對象是擷取從哪個對象進入的。如果是從外面的對象進入的,我們就執行所需的代碼。如果是從父級移入到子級或是由子級移出到父級時,則直接跳過。
父級移入到子級對象,相關對象為父級。 子級移出到父級對象,相對對象為子級。
代碼如下:
1 wrap.onmouseover = function(e) { 2 e = window.event || e; 3 var s = e.fromElement || e.relatedTarget; 4 if (document.all) { //判斷瀏覽器是否為IE,如果存在document.all則為IE 5 if (!this.contains(s)) { // 判斷調用onmouseover的對象(this)是否包含自身或子級,如果包含,則不執行 6 console.log(‘IE will over‘); 7 } 8 } else { //標準瀏覽器下的方法 9 var reg = this.compareDocumentPosition(s);10 if (!(reg == 20 || reg == 0)) {11 console.log(‘Browser will over‘);12 }13 }14 }
當觸發onmouseout時,可能是從父級移到子級,也可能由子級移到父級,或是移出至父級之外。
父級稱到子級,則相關對象為子級,子級稱到父級,則相關對象為父級。
代碼如下:
1 wrap.onmouseout = function(e) { 2 e = window.event || e; 3 var s = e.toElement || e.relatedTarget; 4 if(document.all) { 5 if (!this.contains(s)) { 6 console.log(‘IE will out‘); 7 } 8 } else { 9 var reg = this.compareDocumentPosition(s);10 if (!(reg == 20 || reg == 0)) {11 console.log(‘Browser will out‘);12 }13 }14 }
問題也就得到瞭解決。
不過你會發現:onmouseover與onmouseout的判斷方法其實是一樣的。於是我們得到:
無論是移入還是移出,只要相關對象是父級以外的就可以執行,否則代碼不執行。
最後,再為大家提供本人自己寫的相容代碼,複製到JS代碼後可直接調用。代碼如下:
1 /* 2 * 功能:滑鼠移入對象觸發事件,相容所有瀏覽器並防止滑鼠在父子物件間移動造成的觸發onmouseover的bug 3 * 參數:第一個參數表示觸發的對象,第二個參數表示觸發的對象的事件對象,第三個對象表示要執行的函數 4 * http://www.cnblogs.com/wuyuchang/ 5 */ 6 function mouseover(a, e, func) { 7 e = e || window.event; 8 var b = e.fromElement || e.relatedTarget; 9 10 mouseoverAndOut(a, b, func);11 }12 /* 13 * 功能:滑鼠移出對象觸發事件,相容所有瀏覽器並防止滑鼠在父子物件間移動造成的onmouseout的bug14 * 參數:第一個參數表示觸發的對象,第二個參數表示觸發的對象的事件對象,第三個對象表示要執行的函數15 * http://www.cnblogs.com/wuyuchang/16 */17 function mouseout(a ,e, func) {18 e = e || window.event;19 var b = e.toElement || e.relatedTarget;20 mouseoverAndOut(a, b, func);21 }22 /* 23 * 功能:滑鼠移入或移出對象觸發事件,相容所有瀏覽器並防止滑鼠在父子物件間移動造成的onmouseover & onmouseout的bug24 * 參數:第一個參數表示觸發的對象,第二個參數表示觸發的對象的事件對象,第三個對象表示要執行的函數25 * http://www.cnblogs.com/wuyuchang/26 */27 function mouseoverOrOut(a, e, func) {28 e = e || window.event;29 var b;30 if (e.type == ‘mouseover‘) {31 b = e.fromElement || e.relatedTarget;32 } else if (e.type == ‘mouseout‘) {33 b = e.toElement || e.relatedTarget;34 }35 mouseoverAndOut(a, e, func);36 }37 /* 38 * 功能:滑鼠移入或移出對象觸發事件,相容所有瀏覽器並防止滑鼠在父子物件間移動造成的onmouseover & onmouseout的bug39 * 參數:第一個參數表示觸發的對象,第二個參數表示觸發的對象的相關對象,第三個對象表示要執行的函數40 * http://www.cnblogs.com/wuyuchang/41 */42 function mouseoverAndOut(a, b, func) {43 if (document.all) {44 if (!(a.contains(b))) {45 func();46 }47 } else {48 var res = a.compareDocumentPosition(b);49 if(!(res == 20 || res == 0)){ 50 func();51 } 52 } 53 }
(如果是onmouseover,調用mouseover(a, e, func)即可;如果是onmouseout,調用mouseout(a, e, func)即可;或不管onmouseover還是onmouseout直接調用mouseoverOrOut(a, e, func)即可。)
以上為個人經驗之談,如有不到之處還請留言指點。