之前我介紹過一個 jQuery Cycle Plugin 套件,非常適合用來做跑馬燈或廣告輪播,但是今天我遇到一個跨瀏覽器的問題。我們有做一個網站用到了 jQuery 與 jQuery Cycle Plugin,為了讓 jQuery Cycle 可以在當滑鼠移進廣告看板的範圍時可以先停止輪播,否則使用者可能才剛想要點選廣告時廣告卻換走了的窘境。
如果你的 jQuery Cycle 這樣子宣告:
$('#banners').cycle({
fx: 'fade',
timeout: 600
});
你只要簡單的多加上一個 pause 參數設定即可,如下:
$('#banners').cycle({
fx: 'fade',
timeout: 600,
pause: 1
});
雖然一個看似簡單的設定,在 IE 中可以正常運作,但在 Firefox 中卻永遠無法停止輪播!
我看了 jQuery Cycle Plugin 發現他有一行是負責註冊 jQuery 的 hover 事件 ( 即 onmouseover 與 onmouseout 事件 ) 到放置輪播圖片的 DIV 上,如下:
$cont.hover(function(){this.cyclePause++;},function(){this.cyclePause--;});
但我發現只要滑鼠移進輪播的圖片是會引發 onmouseover 事件,但卻也會立即觸發 onmouseout 事件,我覺得十分詭異,這樣的狀況只有在 Firefox 中會發生。
我原本還以為跟事件觸發順序(Event order)有關,一般來說 W3C 定義兩種事件觸發模式:
- 捕獲模式 ( Event capturing ) : 這是一種由外而內的事件觸發順序
- 冒泡模式 ( Event bubbling ) :這是一種由內而外的事件觸發順序
但我怎麼想都覺得這邏輯不太對,因為這件事根本跟事件觸發「順序」無關,而是 onmouseout 事件提早被觸發了!
研究了好一番功夫才發現原來跟 Image Map 有關,先列出我所使用的 HTML 定義:
<div id="banners">
<div><img src='images/Banners/b1.jpg' usemap='#FPMap1' /></div>
<div><img src='images/Banners/b2.jpg' usemap='#FPMap2' /></div>
<div><img src='images/Banners/b3.jpg' usemap='#FPMap3' /></div>
</div>
<map id="FPMap1" name="FPMap1">
<area coords="0, 210, 359, 227"
href="http://example.com/" shape="rect" />
</map>
<map id="FPMap2" name="FPMap2">
<area coords="0, 210, 359, 227"
href="http://example.com/" shape="rect" />
</map>
<map id="FPMap3" name="FPMap3">
<area coords="0, 210, 359, 227"
href="http://example.com/" shape="rect" />
</map>
你可以看到我的輪播圖片是採用 Image Map 的方式設定連結,而這就是重點中的重點!
我的 <div id="banners"> 定義了 onmouseover 與 onmouseout 事件,但是只要遇到元素內的圖片有使用 Image Map 且剛好滑鼠移到 <map> 定義的連結上時,在 Firefox 中就會立即觸發 <div id="banners"> 定義的 onmouseout 事件,以致於我的 jQuery Cycle 圖片輪播永遠不會停!
我覺得這根本就是個 by design 的 defect,一個小問題耗了我將近兩個小時的時間(包括寫這篇文章),真的很討厭。
以後各位在使用 Image Map 時,一定要特別注意這個差異,否則光除錯就會花你一堆時間。
至於 jQuery Cycle 的 替代方案(Workaround) 就是多加一段程式碼,將事件多註冊一組事件到到所有會用到 <map> 的 <area> 上面,如下程式碼:
$('#banners').parent().find('area').hover(
function() { $('#banners').cycle('pause'); },
function() { $('#banners').cycle('resume'); }
);
原本的 jQuery Cycle 宣告並不需要修改,因為在 IE 下還是可以執行的!