JavaScriptのブラウザを越えたイベント処理を詳しく解読する.

7456 ワード

一.イベントオブジェクトの取得について
FFは少し強情で、argments[0]だけを支持して、window.eventを支持しません.今回は本当にIEを責めませんでした.イベントを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;//        
}
特別な説明が必要です.HTMLのDOM 0級方式+参型イベントプロセッサは、以下の通りです.

function handler(event){
  //do something
}


上のような方式はフルブラウザ対応ですが、HTMLに依存しているDOM 0レベルの欠点が明らかで、前の2つのような主流方法にはなりませんでした.

function handler(event){
  //do something
}
btn.onclick = handler;//JS DOM0   
//btn.onclick = function(event){/*do something*/}//      ,    
この方式はフルブラウザ対応ではなく、「IE 8-」はサポートされていません.IE 9+未知、FF、Chromeはサポートされています.HTMLのDOM 0級事件処理はJSのDOM 0級事件処理と等価だとずっと思っていましたが、今多くの実験をしてやっと両者の違いが分かりました.
二.イベントソースの取得について
event.srcelementは「IE 8-」唯一の方式であり、IE 9+未知であり、他のブラウザは標準のevent.target方式をサポートしている.
三.イベントの阻止に関するデフォルトの行為
event.prevent Default()は標準的な方法ですが、[IE 8-]はサポートしていません.IE自身の方式はevent.return Value=falseです.
四.停止事件の伝播について
event.stopPropagation()は標準的な方法で、IEはまた意見があって、彼はこのように遊びます:event.ccel Bubble=true;ここでは特に注意が必要です.cancelは属性であり、方法ではないので、標準とはかなり違っています.覚え間違えやすいです.
五.イベントプロセッサの追加と削除について
DOM 0レベル方式
ele.onclick=handler;ele.onclick=null最古の方式
特典:全ブラウザ対応
短所:同じイベントは一つのイベントプロセッサだけをバインド/解除することができます.
DOM 2レベル方式

ele.add/removeEventListener(eventType, handler, catch);

とIE方式:ele.atach/detachEvent(‘on’+eventType,handler);
利点:複数のイベントプロセッサのバインディング/解除をサポートします.
短所:互換性の判断が必要です.注意する必要があるのは、標準的な方法の最後のパラメータは、イベントキャプチャ段階でのバインディング/解除の有無を示し、IEはイベントキャプチャをサポートしないため、第3のパラメータがないことである.
注意:IE方式は方法名が標準と異なるだけではなく、パラメータにイベントタイプがオンでなければなりません.そうでなければ、バインディングは無効ですが、エラーが発生しません.
六.ブラウザをまたぐイベント処理

//              
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;
    }
  }
};

総合例
プロジェクトにjQueryなどのライブラリが使われていない場合、どのようにして要素結合イベントを便利にし、各種ブラウザと互換させますか?以下のこの簡単なUtilityは考えられます.

var eventUtility = {
  addEvent : function(el, type, fn) {
    if(typeof addEventListener !== "undefined") {
      el.addEventListener(type, fn, false);
    } else if(typeof attachEvent !== "undefined") {
      el.attachEvent("on" + type, fn);
    } else {
      el["on" + type] = fn;
    }
  },

  removeEvent : function(el, type, fn) {
    if(typeof removeEventListener !== "undefined") {
      el.removeEventListener(type, fn, false);
    } else if(typeof detachEvent !== "undefined") {
      el.detachEvent("on" + type, fn);
    } else {
      el["on" + type] = null;
    }
  },

  getTarget : function(event) {
    if(typeof event.target !== "undefined") {
      return event.target;
    } else {
      return event.srcElement;
    }
  },

  preventDefault : function(event) {
    if(typeof event.preventDefault !== "undefined") {
      event.preventDefault();
    } else {
      event.returnValue = false;
    }
  }
};

使用方法の例:

var eventHandler = function(evt) {
  var target = eventUtility.getTarget(evt),
    tagName = target.tagName;

  if(evt.type === "click") {
    if(tagName === "A" || tagName === "BUTTON") {
      alert("You clicked on an A element, and the innerHTML is " + target.innerHTML + "!");
      eventUtility.preventDefault(evt);
    }
  } else if(evt.type === "mouseover" && tagName === "A") {
    alert("mouseovered " + target.innerHTML);
  }

};

eventUtility.addEvent(document, "click", eventHandler);
eventUtility.addEvent(document, "mouseover", eventHandler);

eventUtility.removeEvent(document, "mouseover", eventHandler);