##一.イベントオブジェクトの取得について##
FF は少し頑固で、arguments[0] のみをサポートし、window.event をサポートしません。今回は本当に IE を責められません。event を window のプロパティとするのは規格に合致しませんが、誰もがすでにこの小さな問題を黙認しており、FF だけが这么多年経っても特立独行です。したがって、クロスブラウザのイベントオブジェクト取得には以下の 2 種類の方法があります:
-
パラメータあり:
getEvent : function(event){ return event ? event : window.event; //return event || window.event;//またはより簡単な方法 } -
パラメータなし:
function getEvent() { return arguments[0] ? arguments[0] : window.event; //return arguments[0] || window.event;//またはより簡単な方法 }
特に説明が必要な方式が 1 つあります:HTML の DOM0 級方式 + パラメータ付きイベントハンドラ、以下の通り:
function handler(event){
//do something
}
<!-- HTML の DOM0 級方式 -->
<button id="btn" onclick="handler(event);">ボタン</button>
上記の方式は全ブラウザ互換ですが、HTML の DOM0 級方式に依存する欠点が明らかであるため、前 2 つのような主流方法にはなりませんでした。一方、JS の DOM0 級方式 + パラメータ付きイベントハンドラは以下の通り:
function handler(event){
//do something
}
btn.onclick = handler;//JS の DOM0 級方式
//btn.onclick = function(event){/*do something*/}//または無名関数、効果は同上
この方式は全ブラウザ互換ではありません、[IE8-] はサポートせず、IE9+ は不明、FF、Chrome はサポートします。ずっと HTML の DOM0 級イベント処理と JS の DOM0 級イベント処理は等価だと思っていましたが、多くの実験をして初めて両者に違いがあることに気づきました
##二.イベントソースの取得について##
event.srcElement は [IE8-] 独自の方式で、IE9+ は不明、他のブラウザはすべて標準の event.target 方式をサポートします
##三.イベントのデフォルト動作を阻止することについて##
event.preventDefault() は標準メソッドですが、[IE8-] はサポートせず、IE 独自の方式は event.returnValue = false; です
##四.イベント伝播を停止することについて##
event.stopPropagation() は標準メソッドですが、IE はまた意見があり、こうプレイします:event.cancelBubble = true;ここで特に注意が必要です、cancel はメソッドではなくプロパティであるため、標準とは大きく異なり、覚え間違いやすいです
##五.イベントハンドラの追加と削除について##
- DOM0 級方式
ele.onclick = handler;ele.onclick=null;最も古い方式
利点:全ブラウザ互換
欠点:同一イベントに 1 つのイベントハンドラのみバインド/アンバインド可能
- DOM2 級方式
ele.add/removeEventListener(eventType, handler, catch);
と IE 方式:ele.attach/detachEvent('on'+eventType, handler);
利点:複数のイベントハンドラのバインド/アンバインドをサポート
欠点:互換性判断が必要。注意すべき点は:標準方式では最後のパラメータはイベントキャプチャ段階でバインド/アンバインドするかどうかを示し、IE はイベントキャプチャをサポートしないため、3 番目のパラメータもありません
注意:IE 方式はメソッド名が標準と異なるだけでなく、パラメータ中のイベントタイプにも on を追加する必要があります、そうでないとバインドは無効ですがエラーは出ません
##六.クロスブラウザのイベント処理##
//クロスブラウザのイベントハンドラ追加方式
var EventUtil = {
addHandler : function(elem, type, handler){
if(elem.addEventListener){
elem.addEventListener(type, handler, false);
}
else if(elem.attachEvent){
elem.attachEvent("on" + type, handler);//複数の同一タイプの handler を追加する場合、IE 方式のルールは最後に追加したものが最初にトリガーされる
}
else{
if(typeof elem["on" + type] === 'function'){
var oldHandler = elem["on" + type];
elem["on" + type] = function(){
oldHandler();
handler();
}
}
else{
elem["on" + type] = handler;//複数のイベントハンドラの追加をサポート
}
}
},
getEvent : function(event){
return event ? event : window.event;
},
getTarget : function(event){
return event.target || event.srcElement;
},
preventDefault : function(event){
if(event.preventDefault){
event.preventDefault();
}
else{
event.returnValue = false;
}
},
removeHandler : function(elem, type, handler){
if(elem.removeEventListener){
elem.removeEventListener(type, handler, false);
}
else if(elem.detachEvent){
elem.detachEvent("on" + type, handler);
}
else{
elem["on" + type] = null;//単一のイベントハンドラの削除をサポートせず、すべて削除するのみ
}
},
stopPropagation : function(event){
if(event.stopPropagation){
event.stopPropagation();
}
else{
event.cancelBubble = true;
}
},
getRelatedTarget : function(event){
if(event.relatedTarget){
return event.relatedTarget;
}
else if(event.toElement && event.type == "mouseout"){
return event.toElement;
}
else if(event.fromElement && event.type == "mouseover"){
return event.fromElement;
}
else{
return null;
}
},
/*IE8 は左ボタンと中ボタンをクリックしてもどちらも 0;FF は中ボタンを識別不可;Chrome は正常*/
getButton : function(event){//0,1,2 を返す - 左、中、右
if(document.implementation.hasFeature("MouseEvents", "2.0")){
return event.button;
}
else{
switch(event.button){
case 0:case 1:case 3:case 5:case 7:
return 0;
break;
case 2:case 6:
return 2;
break;
case 4:
return 1;
break;
default:
break;
}
}
},
/*keypress イベントのみ検出可能、戻り値は表示される文字コードに等しい*/
/*IE と Chrome は表示可能な文字キーのみトリガー、FF は他のキーもトリガー可能、戻り値は 0*/
getCharCode : function(event){
if(typeof event.charCode == "number"){
return event.charCode;
}
else{
return event.keyCode;
}
}
};
上記のコードは『JavaScript 高級程序设计』中文版から整理したもので、书中の getRelatedTarget に少し問題があります(P373)、本文ですでに修正済みです
书中の addHandler は DOM0 級方式で複数のイベントハンドラを追加することをサポートしていません、修正後はサポート可能ですが、単一のイベントハンドラの削除をサポートしないため、コードは依然として不完全です。DOM0 級イベントハンドラの追加/削除操作をサポートしたい場合、手動でイベントハンドラキューを維持できますが、この方式を実現することに大きな意味がないため、ここでは展開しません
###参考資料###
コメントはまだありません