2012-07-02

在 Firefox 裡消失的 mouseup

在實做 drag and drop 時發現 Firefox 有個奇怪的行為。

若只是單選沒有移動滑鼠,也就是 mousedown 與 mouseup,沒有 mousemove,那 Firefox、IE 與 Chrome 都正常。

但是當拖拉時,IE 與 Chrome 正常,Firefox 怪了,只有 mousedown 與 mousemove,沒有觸發 mouseup。


測試:
$('.a').mousedown(function(){
    mousemoving = false;
    $('.msg').append('a.mousedown<br/>');
});
$('.a').click(function(){
    $('.msg').append('a.click<br/>');
});
$('.a').mouseup(function(){
    mousemoving = false;
    $('.msg').append('a.mouseup<br/>');
});
var mousemoving = false; // 防止一堆 mousemove 訊息
$('.a').mousemove(function(){
    if (mousemoving) {
        return;
    }
    mousemoving = true;
    $('.msg').append('a.mousemove<br/>');
});
輸出訊息為:
// 單點沒問題
a.mousedown
a.mouseup
a.click
// 拖拉就不行了
a.mousedown
a.mousemove
 最後沒有觸發 mouseup 與 click。

修正方法:
$('.a').mousedown(function(){
    mousemoving = false;
    $('.msg').append('a.mousedown<br/>');
    return false;
});
在 mousedown 最後回傳 false,表示 mousedown 不繼續往下傳,也就是 Firefox 不會收到 mousedown。

一般事件傳導路徑
div -> ... -> body -> document -> browser
範例:
$('.a').mousedown(function(){
    $('.msg').append('a.mousedown<br/>');
});
$('.a').mouseup(function(){
    $('.msg').append('a.mouseup<br/>');
});
$('.a').click(function(){
    $('.msg').append('a.click<br/>');
});

$('body').mousedown(function(){
    $('.msg').append('body.mousedown<br/>');
});
$('body').mouseup(function(){
    $('.msg').append('body.mouseup<br/>');
});
$('body').click(function(){
    $('.msg').append('body.click<br/>');
});

$(document).mousedown(function(){
    $('.msg').append('document.mousedown<br/>');
});
$(document).mouseup(function(){
    $('.msg').append('document.mouseup<br/>');
});
$(document).click(function(){
    $('.msg').append('document.click<br/>');
});
得到的訊息為:
a.mousedown
body.mousedown
document.mousedown
a.mouseup
body.mouseup
document.mouseup
a.click
body.click
document.click
一層一層往外傳,當然要有註冊該 Event type 才會 Catch 到,所以可以在任一層 return false,該層以後就不會得到該 Event,以上面範例為例,若在 a.mousedown 回傳 false,得到的訊息就變成:
a.mousedown
a.mouseup
body.mouseup
document.mouseup
a.click
body.click
document.click
回到最前面的問題,為防止 Firefox 奇怪的行為,得在有註冊的最外層物件 reture false,一定要在最外層,不然外層的收不到 Event。

沒有留言:

張貼留言