JavaScript事件使用指南

事件流
事件流描述的是從頁面中接收事件的順序,IE和Netscape提出來差很少徹底相反的事件流的概念,IE事件流是事件冒泡流,Netscape事件流是事件捕獲流。

事件冒泡
IE的事件流叫作事件冒泡,即事件開始時由最具體的元素(文檔中嵌套最深的那個節點)接收,而後逐級向上(一直到文檔);以下代碼:

<div id = "div">
    <span id="span">
        <a id="aTag">事件測試</a>
    </span>
</div>

JS以下:

document.getElementById("aTag").addEventListener('click',aTag);
document.getElementById("span").addEventListener('click',span);
document.getElementById("div").addEventListener('click',div);
function aTag(e) {
    alert("點擊的是a標籤");
}
function span(e) {
    alert("點擊的是span標籤");
}
function div(e) {
    alert("點擊的是div標籤");
}

當單擊 「事件測試」文字後,那麼click事件會按照以下順序傳播;
1.先打印出:點擊的是a標籤
2.再打印出:點擊的是span標籤
3.最後打印出:點擊的是div標籤
4.最後確定是document文檔。

全部現代瀏覽器都支持事件冒泡。

事件捕獲:
事件捕獲與事件冒泡事件流正好相反的順序,事件捕獲的事件流是最外層逐級向內傳播,也就是先document,而後逐級div標籤 , span標籤 , a標籤;

上面的JS代碼改爲以下:

document.getElementById("div").addEventListener('click',div,true);
document.getElementById("aTag").addEventListener('click',aTag,true);
document.getElementById("span").addEventListener('click',span,true);

第三個參數設置爲true,即爲捕獲事件,默認爲false;不然的話,事件流仍是和上面的同樣,由於不論是在IE仍是標準瀏覽器下,事件冒泡瀏覽器都支持的。

DOM事件流
DOM2級事件規定的事件流包括三個階段,分別是:事件捕獲階段,處於目標階段和事件冒泡階段。示意圖就不畫了,具體的能夠看看書。

DOM0級事件處理程序
以下代碼是DOM0級事件處理程序:

var btn = document.getElementById("btn");
btn.onclick = function(){
     alert("Clicked");
};

使用DOM0級方法指定的事件處理程序被認爲是元素的方法,處理程序是在元素的做用域進行的,程序中this是引用的是當前元素。

<div id="btn">btn</div>
var btn = document.getElementById("btn");
btn.onclick = function(){
    alert(this.id); // 彈出btn
}

單擊元素btn後,經過this.id取得元素的屬性id,還能夠經過this訪問元素的任何屬性和方法,以這種方式添加的事情處理程序在事件流的冒泡階段處理。
也能夠刪除經過DOM0級方法指定的事件處理程序,只要將事件處理程序的屬性值設置爲null便可。
btn.onclick = null; // 刪除事件處理程序;

以下JS代碼改爲以下:

var btn = document.getElementById("btn");
btn.onclick = function(){
    alert(this.id);
}
btn.onclick = null;

再單擊btn後,沒有任何反應;
DOM2級事件處理程序
DOM2級事件定義了2個方法,用於處理指定和刪除事件處理程序的操做;
addEventListener()和removeEventListener()。全部DOM節點都包含這兩個方法,他們包含三個參數,第一個參數爲事件類型;
第二個參數爲事件函數,第三個參數爲布爾值,若是是true的話,說明是事件流是捕獲事件,若是是false的話,那麼事件流是冒泡事件;
好比如上的btn代碼,咱們改爲以下:

var btn = document.getElementById("btn");
btn.addEventListener('click',function(e){
    alert(this.id);
},false);

上面的點擊事件是在冒泡階段被觸發,與DOM0級方法同樣,這裏添加的事件處理程序也是在其依副的元素做用域中運行,
使用DOM2級添加事件處理程序的好處是能夠添加多個事件處理程序,以下代碼:

var btn = document.getElementById("btn");
btn.addEventListener('click',function(e){
    alert(this.id);
},false);
btn.addEventListener('click',function(e){
    alert("我是來測試的");
},false);

上面的代碼被彈出2次對話框,而在DOM0級是不能夠的;它永遠是執行最後一次的。

addEventListener添加的事件只能使用removeEventListener來刪除相對應的事件,那麼如上的JS不能按照上面的方式來編寫哦!須要給定義一個函數;以下:

btn.addEventListener('click',handler,false);
function handler(e){
   alert(this.id);
}

可使用以下方式對click事件刪除;以下代碼:

btn.removeEventListener(‘click’,handler);

上面的是在標準瀏覽器下處理的事件,下面咱們來看看在IE下處理的事件;
IE事件處理的程序
IE實現了與DOM相似的2個方法,分別是attachEvent()和detachEvent(),這兩個方法只接受2個參數,第一個參數是事件名稱,
第二個參數是要處理的函數;因爲IE8及更早版本只支持事件冒泡,因此經過attachEvent()添加的事件處理程序會被添加到冒泡階段;
下面是IE事件處理程序的代碼以下:

btn.attachEvent('onclick',handler);
function handler(e){
    alert(this); // window
}

注意:attachEvent的事件名稱是onclick,而addEventListener的事件名稱是click,且IE中使用的attachEvent()與使用DOM0級方法的的主要區別在於事件處理程序的做用域,
在使用dom0級狀況下,事件處理程序在其所屬元素的做用域內運行,在使用attachEvent()方法的狀況下,事件處理程序在全局做用域下運行,其中的this等於window。

與addEventListener同樣,attachEvent也能夠註冊多個點擊click事件,以下代碼:

btn.attachEvent('onclick',function(e){
    alert("1");
});
btn.attachEvent('onclick',function(e){
    alert("2");
});

可是與Dom方法不一樣的是,這些事件處理程序不是以添加他們的順序執行,而是以相反的順序觸發,好比如上代碼,會先彈出2,而後彈出1對話框;
使用attachEvent註冊的事件只能使用detachEvent()方法來移除;

下面咱們能夠來編寫跨瀏覽器的事件處理程序;代碼以下:

var EventUtil = {
    addHandler: function(element,type,handler) {
        if(element.addEventListener) {
                        element.addEventListener(type,handler,false);
        }else if(element.attachEvent) {
                    element.attachEvent("on"+type,handler);
        }else {
            element["on" +type] = handler;
        }
    },
    removeHandler: function(element,type,handler){
        if(element.removeEventListener) {
                    element.removeEventListener(type,handler,false);
        }else if(element.detachEvent) {
                    element.detachEvent("on"+type,handler);
        }else {
            element["on" +type] = null;
        }
    }
};

下面咱們可使用這個封裝的函數代碼來測試以前的代碼了,代碼改爲以下所示:

function handler(){
    alert(1);
}
EventUtil.addHandler(btn,'click',handler);

在IE或者標準瀏覽器下都會彈出1;若是咱們須要移除click事件的話,咱們可使用以下代碼:

EventUtil.removeHandler(btn,’click’,handler);

而後在標準瀏覽器下或者IE下點擊btn元素都沒有反應;

事件對象:
在觸發DOM上的某個事件時,會產生一個事件對象event,這個對象中包含着全部與事件有關的信息;包括致使事件的元素,
事件的類型以及其餘與特定事件相關的信息。咱們來看看dom0級和dom2級的事件對象Event;

好比以下代碼:

var btn = document.getElementById("btn");
btn.onclick = function(e){
    console.log(e);
}

下面咱們來看看最基本的成員的含義吧;以下:

屬性/方法    類型    含義
bubbles    Boolean    事件是否冒泡
cancelable    Boolean    是否能夠取消事件的默認行爲
currentTarget    Boolean    事件處理程序當前正在處理事件的那個元素
defaultPrevented    Boolean    爲true 表示已經調用了preventDefault()
detail    Integer    與事件相關的細節信息
eventPhase    Integer    調用事件處理程序的階段:1表示捕獲階段,2表示「處於目標」,3表示冒泡階段
preventDefault()    Function    取消事件的默認行爲。若是cancelable是true,則可使用這個方法
stopImmediatePropagation()    Function    取消事件的進一步捕獲或冒泡,同時阻止任何事件處理程序被調用
stopPropagation()    Function    取消事件的進一步捕獲或冒泡。若是bubbles爲true,則可使用這個方法
target    Element    事件的目標
type    String    被觸發的事件的類型
view    AbstractView    與事件關聯的抽象視圖。等同於發生事件的window對象
理解currentTarget與target

在事件處理程序內部,this始終等於currentTarget值,即currentTarget是指當前被觸發或者說正在處理事件的那個元素,
而target是指當前的目標元素;好比以下代碼,對btn按鈕觸發點擊事件,那麼e.currentTraget指向了this,e.target也指向了this;以下代碼:

var btn = document.getElementById("btn");
btn.onclick = function(e){
    console.log(e.currentTarget == this); // true
    console.log(e.target == this);  // true
}
可是若是我對document.body觸發點擊的話,那麼e.currentTarget就指向了document.body了,那麼e.target 指向與 btn那個元素了,以下代碼:

document.body.onclick = function(e){
    console.log(e.currentTarget === document.body); // true
    console.log(document.body === this);  // true
    console.log(e.target === document.getElementById("btn")); //true
};
如今應該能理解currentTarget與target的區別吧!currentTarget就是指被點擊的那個元素,可是target是當前點擊的目標元素,
如上代碼,因爲btn上並無註冊事件,結果click事件就冒泡到了document.body,在那裏事件才獲得了處理。

理解標準瀏覽器下的事件對象與IE下的事件對象
標準瀏覽器下的事件對象是event,好比btn點擊後;以下代碼:

var btn = document.getElementById("btn");
btn.onclick = function(){
    console.log(event); //標準瀏覽器下打印事件對象
    console.log(event.type);//'click'
}
btn.onclick = function(){
    // IE下打印的事件對象window.event
    console.log(window.event);
    console.log(window.event.type); // 'click'
 }
上面的寫法是在DOM0級上註冊事件,若是咱們在Dom2級上註冊事件的話,那麼就會有一個事件對象event做爲參數傳入事件到函數中,以下:

var btn = document.getElementById("btn");
EventUtil.addHandler(btn,'click',function(e){
    console.log(e);
});
理解特定事件的默認行爲事件

在標準瀏覽器下,在阻止特定事件的默認行爲,可使用preventDefault()方法,好比以下,我點擊一個鏈接,按道理是打開一個新鏈接窗口,
可是我使用preventDefault()方法能夠阻止默認行爲,阻止打開新窗口;以下代碼:

HTML:<a href="http://www.baidu.com" id="alink" target="_blank">打開新鏈接</a>
JS以下:
var alink = document.getElementById("alink");
alink.onclick = function(e){
    console.log(e)
    e.preventDefault();
}

就能夠阻止頁面進行跳轉了~ 這是標準瀏覽器下處理方式,下面咱們來看看IE是如何處理默認事件的;
IE下使用returnValue屬性來取消給定事件的默認行爲,只要將returnValue屬性值設置爲false便可,就能夠阻止瀏覽器的默認行爲,以下代碼:

alink.onclick = function(){
    console.log(window.event)
    window.event.returnValue = false;
}

標準瀏覽器下與IE下的事件目標的區別
標準瀏覽器下使用e.target來指定當前被點擊的目標元素,以下代碼所示:

var btn = document.getElementById("btn");
btn.onclick = function(){
    console.log(event); 
    console.log(event.target); // 打印事件目標元素
}

IE下是使用event.srcElement來指定當前的目標元素,以下代碼:

btn.onclick = function(){
    console.log(event); 
    console.log(window.event.srcElement);
}

理解標準瀏覽器與IE下阻止事件傳播的區別
在標準瀏覽器下咱們可使用stopPropagation()方法來中止事件在DOM層次中的傳播,即取消事件中的冒泡或者捕獲。
從而避免觸發註冊在document.body上面的事件處理程序,以下所示:

var btn = document.getElementById("btn");
btn.onclick = function(e){
    alert(1);
    e.stopPropagation();
}
document.body.onclick = function(){
    alert(2);
}

如上代碼,若是我不使用stopPropagation()阻止冒泡事件的話,那麼在頁面中會先彈出1,而後彈出2,若是使用stopPropagation()方法的話,
只會在頁面上彈出1,就不會冒泡到body上面去;

IE下中止冒泡的話,咱們可使用cancelBubble屬性,咱們只要將此屬性設置爲true,便可阻止事件經過冒泡觸發document.body中的註冊事件。
可是IE是不支持捕獲事件的,可是stopPropagation()即支持捕獲事件又支持冒泡事件的。以下代碼:

btn.onclick = function(e){
    alert(1);
    window.event.cancelBubble = true;
}
document.body.onclick = function(){
    alert(2);
}

若是不設置window.event.cancelBubble 爲true的話,就會先彈出1,而後彈出2,若是加上的話,就只會彈出1對話框。
理解了上面的區別後,咱們如今能夠往EventUtil對象裏面添加跨瀏覽器的方法了;

跨瀏覽器的事件對象

var EventUtil = {
    addHandler: function(element,type,handler) {
        if(element.addEventListener) {
            element.addEventListener(type,handler,false);
        }else if(element.attachEvent) {
            element.attachEvent("on"+type,handler);
        }else {
            element["on" +type] = handler;
        }
    },
    removeHandler: function(element,type,handler){
        if(element.removeEventListener) {
            element.removeEventListener(type,handler,false);
        }else if(element.detachEvent) {
            element.detachEvent("on"+type,handler);
        }else {
            element["on" +type] = null;
        }
    },
    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;
        }
    },
    stopPropagation: function(event) {
        if(event.stopPropagation) {
            event.stopPropagation();
        }else {
            event.cancelBubble = true;
        }
    }
};

事件類型:
DOM3級事件規定了如下幾類事件;以下:
UI事件: 當用戶與頁面上的元素交互時觸發;
load事件:當頁面加載完後(包括全部圖像,全部javascript文件,css文件等外部資源),就會觸發window上面的load事件,以下代碼是加載圖片的:
HTML代碼:<img src = 「event.png」 id=」img」/>

JS代碼以下:

var img = document.getElementById("img");
EventUtil.addHandler(img,'load',function(event){
      var event = EventUtil.getEvent(event);
      alert(EventUtil.getTarget(event).src);
});

當圖片加載完後,就會彈出圖片的url地址了;
若是在建立新的img元素時,能夠爲其指定一個事件處理程序,以便圖像加載完成後給出提示,此時,最重要的是在指定src屬性以前先指定事件;以下代碼所示:

 EventUtil.addHandler(window,'load',function(){
    var img = document.createElement("img");
    EventUtil.addHandler(img,'load',function(e){
        e = EventUtil.getEvent(e);
        alert(EventUtil.getTarget(e).src);
    });
    document.body.appendChild(img);
    img.src = "event.png";
});

在圖像加載完成後,會彈出圖片地址了;
一樣的功能,咱們可使用DOM0級的Image對象來實現,在DOM出現以前,開發人員常用Image對象在客戶端預加載圖像,以下代碼:

EventUtil.addHandler(window,'load',function(){
    var img = new Image();
    EventUtil.addHandler(img,'load',function(e){
        alert(1);
    });
    img.src ="event.png";
});

Script元素也支持load事件,可是IE8及如下不支持,在IE9+,Firefox,Opera,chrome及Safari3+都支持,以便開發開發人員肯定動態加載的javascript文件是否加載完畢;好比咱們動態建立script標籤後,經過load事件判斷動態建立的script標籤是否加載完畢,代碼以下:

EventUtil.addHandler(window,'load',function(){
    var script = document.createElement("script");
    EventUtil.addHandler(script,'load',function(e){
        alert(1);
    });
    script.src = "a.js";
    document.body.appendChild(script);
});

焦點事件:當元素得到或失去焦點時觸發;
有:blur:在元素失去焦點時觸發,這個事件不會冒泡,全部瀏覽器都支持。
foucs:在元素得到焦點時觸發,這個事件不會冒泡,全部瀏覽器都支持。
鼠標事件:當用戶經過鼠標在頁面操做時觸發;

click事件:在用戶單擊鼠標按鈕或者按下回車鍵觸發;
dblclick事件:在用戶雙擊鼠標按鈕時被觸發;
mousedown事件:在用戶按下了任意鼠標按鈕時被觸發,不能經過鍵盤觸發這個事件。
mouseenter事件:在鼠標光標從元素外部移動到元素範圍以內被觸發;這個事件不冒泡;
mousemove事件:當鼠標指針在元素內部移動時重複地觸發。
mouseout事件:用戶將其移入另外一個元素內被觸發。
mouseover事件:鼠標指針在元素外部,用戶將移入另外一個元素的邊界時觸發,感受和mouseenter事件相似;
mouseup事件:用戶釋放鼠標按鈕時觸發;
頁面上全部的元素都支持鼠標事件,除了mouseenter和mouseleave,全部鼠標事件都會冒泡,也能夠被取消,而取消鼠標事件將會影響瀏覽器的默認行爲。

理解客戶區座標位置
含義是:鼠標指針在可視區中的水平clientX和垂直clientY座標;
代碼以下:

EventUtil.addHandler(btn,'click',function(e){
    e = EventUtil.getEvent(e);
    console.log("可視區X軸座標爲:"+e.clientX + " "+ "可視區Y軸座標爲:"+e.clientY);
});

注意:客戶區座標位置不包含滾動條滾動的位置,所以這個位置不表明鼠標在頁面上的位置;

理解頁面座標位置pageX和pageY:
pageX與pageY是指頁面座標的位置,與clientX和clientY的區別是:它包含頁面滾動條的位置

代碼以下:

EventUtil.addHandler(btn,'click',function(e){
    e = EventUtil.getEvent(e);
    console.log("頁面X軸座標爲:"+e.pageX + " "+ "頁面Y軸座標爲:"+e.pageY);
});

在頁面沒有滾動條的狀況下,pageX與clientX相等,同理pageY與clientY相等。

可是IE8及更早的版本不支持pageX與pageY,不過咱們可使用客戶區座標(client,clientY)和滾動座標計算出來;
所以咱們須要用到document.body(混雜模式下)或 document.documentElement(標準模式下)中的scrollLeft和scrollTop屬性;

對此咱們能夠封裝代碼以下:

EventUtil.addHandler(btn,'click',function(e){
    e = EventUtil.getEvent(e);
    var pageX = e.pageX,
          pageY = e.pageY;
    if(!pageX) {
    pageX = e.clientX + (document.body.scrollLeft || document.documentElement.scrollLeft);
    }
    if(!pageY) {
    pageY = e.clientY + (document.body.scrollTop || document.documentElement.scrollTop);
    }
    console.log("頁面X軸座標爲:"+pageX + " "+ "頁面Y軸座標爲:"+pageY);
});

理解屏幕座標的位置
屏幕橫座標screenX和垂直座標screenY屬性是相對於整個屏幕的

以下代碼測試:

EventUtil.addHandler(btn,'click',function(e){
    e = EventUtil.getEvent(e);
    console.log("屏幕X軸的座標爲:"+e.screenX + " "+"屏幕Y軸的座標爲:"+e.screenY);
});

理解鼠標滾輪事件:

IE6首先實現了mousewheel事件,此後opera,chrome和safari也都實現了這個事件,當用戶經過鼠標滾輪與頁面交互,
在垂直方向上滾動頁面時(不管向上仍是向下),就會觸發mousewheel事件,這個事件能夠在任何元素上觸發,
最終會冒泡到document(IE8)或window(IE9,Opera,Chrome,Safari)對象,與mousewheel事件對應的event對象外,
還有一個屬性wheelDelta屬性,當用戶向前滾動鼠標滾輪時,wheelDelta是120的倍數,當用戶向後滾動鼠標滾輪時,wheelDelta是-120的倍數。

將mousewheel事件給頁面任何元素或document對象,便可處理鼠標滾輪操做;以下代碼:

EventUtil.addHandler(btn,'mousewheel',function(e){
    e = EventUtil.getEvent(e);
    alert(e.wheelDelta);
});

如上代碼,我不是在document對象或者window對象上,而是在頁面btn元素上觸發的;可是咱們要注意,
在Opera9.5以前的版本中,wheelDelta值的正負號是顛倒的,若是咱們要支持Opera9.5版本以前的話,那麼咱們須要瀏覽器檢測技術來檢測下;以下代碼

EventUtil.addHandler(document, "mousewheel", function(event){
    event = EventUtil.getEvent(event);
    // var delta = (client.engine.opera && client.engine.opera < 9.5 ? -event.wheelDelta : event.wheelDelta);
       var delta = event.wheelDelta;
    alert(delta);
});

可是client.engine.opera 這句代碼運行下會報錯,由於目前尚未封裝這個方法,因此等下一個博客我會研究代理檢測封裝下這個方法;
因此先不考慮opera9.5,先註釋掉這句代碼;

可是FireFox支持一個爲DOMMouseScroll的事件,也是在鼠標滾輪滾動時觸發,與mousewheel事件同樣,可是他的有關鼠標滾輪信息保存在detail屬性中,
當鼠標向前滾動時,這個屬性值是-3的倍數,當鼠標滾輪向後滾動時,這個屬性值是3的倍數;也能夠給DOMMouseScroll事件使用在任何元素上,
且這個事件會冒泡到window對象上,所以咱們能夠這樣添加滾輪信息的代碼以下:

EventUtil.addHandler(document, "DOMMouseScroll", function(event){
    event = EventUtil.getEvent(event);
    alert(event.detail);
});

咱們如今能夠給跨瀏覽器下的滾輪事件;代碼以下:

function getWheelDelta (event) {
    if(event.wheelDelta) {
    // return (client.engine.opera && client.engine.opera < 9.5 ? -event.wheelDelta : event.wheelDelta);
         return  event.wheelDelta;
    }else {
        return -event.detail * 40
    }
}
getWheelDelta方法首先檢測了事件對象是否包含了wheelDelta屬性,若是包含則返回屬性值,若是不包含,那麼咱們就看成是firefox瀏覽器,
那麼假設相應的值保存在detail屬性中,有了上面的方法後,咱們如今能夠將相同的事件指定給mousewheel事件和DOMMouseScroll事件了;

EventUtil.addHandler(document, "DOMMouseScroll", handleMouseWheel);
EventUtil.addHandler(document, "mousewheel", handleMouseWheel);
function handleMouseWheel(event) {
    event = EventUtil.getEvent(event);
    var delta = EventUtil.getWheelDelta(event);
    alert(delta);
}

滾輪向上滾動是正數120,向下滾動是負數-120,因此根據是否大於0,能夠判斷是向下滾動仍是向上滾動;

理解字符編碼charCode

IE9+,firefox,chrome和safari的event對象都支持一個charCode屬性,這個屬性只有在發生keypress事件時才包含值,
並且這個值是按下的那個鍵所表明字符的ASCLL編碼,可是IE8及以前或者opera不支持這個屬性,
可是咱們可使用keyCode這個屬性代替.在取得了字符編碼以後,就可使用String.fromCharCode()將其轉換成實際的字符。

以下代碼:

getCharCode: function(event) {
    if(typeof event.charCode == 'number') {
        return event.charCode;
    }else {
        return event.keyCode;
    }
}

咱們如今能夠給EventUtil添加事件了,以下代碼:

var EventUtil = {
    addHandler: function(element,type,handler) {
        if(element.addEventListener) {
            element.addEventListener(type,handler,false);
        }else if(element.attachEvent) {
            element.attachEvent("on"+type,handler);
        }else {
            element["on" +type] = handler;
        }
    },
    removeHandler: function(element,type,handler){
        if(element.removeEventListener) {
            element.removeEventListener(type,handler,false);
        }else if(element.detachEvent) {
            element.detachEvent("on"+type,handler);
        }else {
            element["on" +type] = null;
        }
    },
    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;
        }
    },
    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){
            return event.toElement;
        } else if (event.fromElement){
            return event.fromElement;
        } else {
            return null;
        }
    },
    getWheelDelta: function(event) {
        if(event.wheelDelta) {
            return event.wheelDelta;
        }else {
            return -event.detail * 40
        }
    },
    getCharCode: function(event) {
        if(typeof event.charCode == 'number') {
            return event.charCode;
        }else {
            return event.keyCode;
        }
    }
};

咱們如今能夠作一個demo以下:

以下代碼:
var inputDiv = document.getElementById("inputDiv");
EventUtil.addHandler(inputDiv,'keypress',function(event){
    event = EventUtil.getEvent(event);
    var code = EventUtil.getCharCode(event);
    alert(EventUtil.getCharCode(event)); // 彈出字符編碼
    alert(String.fromCharCode(code));  // 彈出字符
});
HTML5事件
1.contextmenu事件 contextmenu事件在windows操做系統下,咱們是使用右鍵就能夠自定義右鍵彈出菜單,可是咱們使用右鍵的時候會有默認的菜單, 所以咱們須要使用阻止默認事件這個方法來阻止掉;此事件也是屬於鼠標事件,所以此事件包含與光標位置中全部的屬性 HTML代碼以下: <div id="myDiv">Right click or Ctrl+click me to get a custom context menu.Click anywhere else to get the default context menu. </div> <ul id="myMenu" style="position:absolute;visibility:hidden;background-color: silver"> <li><a href="http://www.nczonline.net">Nicholas’ site</a></li> <li><a href="http://www.wrox.com">Wrox site</a></li> <li><a href="http://www.yahoo.com">Yahoo!</a></li> </ul> JS代碼以下: var div = document.getElementById("myDiv"); EventUtil.addHandler(div, "contextmenu", function(event){ event = EventUtil.getEvent(event); EventUtil.preventDefault(event); var menu = document.getElementById("myMenu"); menu.style.left = event.clientX + "px"; menu.style.top = event.clientY + "px"; menu.style.visibility = "visible"; }); EventUtil.addHandler(document, "click", function(event){ document.getElementById("myMenu").style.visibility = "hidden"; }); 如上,咱們是經過右鍵的clientX和clientY來肯定菜單的位置;當我點擊文檔document的時候 就隱藏該菜單; 瀏覽器支持有:IE,Firefox,Safari,chrome和Opera11+ beforeunload事件 此事件是給頁面在卸載以前,給用戶一個提示,是否須要卸載頁面提示給用戶,爲了顯示這個對話框,對IE和firefox而言, 必須將event.returnValue的值設置爲要顯示給用戶的字符串;可是對於safari和chrome而言,能夠返回此字符串便可; 以下代碼: EventUtil.addHandler(window, "beforeunload",function(event){ event = EventUtil.getEvent(event); var message = "I'm really going to miss you if you go."; event.returnValue = message; return message; }); 當用戶關閉遊覽器的時候,會彈出以下窗口給用戶提示 點擊離開此頁按鈕 即關閉窗口,點擊留在此頁按鈕 即留在當前頁面,可是當我按F5刷新頁面的時候,一樣會彈出窗口提示 瀏覽器支持:IE,firefox,chrome和safari都支持,可是Opera11及以前的版本不支持; 理解hashchange事件 HTML5中新增長了hashchange事件,以便在URL的參數列表(url中的#號後面的全部參數發生改變時通知開發人員),在Ajax應用中, 開發人員常用url參數列表保存狀態或導航信息; 咱們必須把hashchange事件添加到window對象中,而後當url參數列表只要發生變化就會調用此事件,此事件對象event包含2個屬性, oldURL和newURL,這兩個屬性分別保存着URL變化先後的完整URL; 支持的瀏覽器有:IE8+,firefox3.6+,safari5+,chrome和opera10.6+ 在這些瀏覽器中,只有firefox3.6+,chrome和opera支持oldURL和newURL屬性; 以下代碼: EventUtil.addHandler(window, "hashchange", function(event){ alert("Old URL: " + event.oldURL + "\nNew URL: " + event.newURL); }); 當我第一次#號參數後面是aa,如今改爲aaaa,就會觸發此事件 有些瀏覽器並不支持oldURL和newURL,所以咱們可使用location.hash來保存當前的參數列表,以下代碼: EventUtil.addHandler(window, "hashchange", function(event){ alert(location.hash); }); 當#號後面我改爲bbb參數時候 可使用以下代碼來檢測瀏覽器是否支持hashchange事件; var isSupported = ("onhashchange" in window); alert(isSupported); 若是IE8 是在IE7 文檔模式下運行,即便功能無效它也會返回true。爲解決這個問題,可使用 如下這個更穩妥的檢測方式: var isSupported = ("onhashchange" in window) && (document.documentMode === undefined || document.documentMode > 7); 設備事件中的—orientationchange事件 蘋果公司爲移動safari添加的orientationchange事件是能讓用戶肯定什麼時候將設備由橫向查看模式切換到縱向模式觸發的事件; 此屬性中包含三個值,0表示肖像模式;90表示向左旋轉的橫向模式(主屏幕按鈕在右側),-90表示向右旋轉的橫向模式(主屏幕按鈕在左側) 只要用戶改變了設備的查看模式,就會觸發orientationchange事件, 使用IOS設備便可演示效果:代碼以下: EventUtil.addHandler(window, "load", function(event){ var div = document.getElementById("myDiv"); div.innerHTML = "Current orientation is " + window.orientation; EventUtil.addHandler(window, "orientationchange", function(event){ div.innerHTML = "Current orientation is " + window.orientation; }); }); 理解移動端的事件—觸摸與手勢事件 有如下幾個觸摸事件: touchstart: 當手指觸摸屏幕時觸發,即便是一個手指放在屏幕上也會觸發。 touchmove:當手指在屏幕上滑動時連續地觸發,這個事件發生期間,咱們可使用preventDefault()事件能夠阻止滾動。 touchend: 當手指從屏幕上移開時觸發。 touchcancel: 當系統中止跟蹤觸摸時觸發。 上面幾個事件都屬於冒泡事件,咱們能夠對此進行取消事件,每一個觸摸的event對象都提供了在鼠標中常見的屬性; bubbles, cancelable,view,clientX, clientY ,screenX, screenY,detail, altKey, shiftKey, ctrlKey, metaKey, 除了常見的DoM屬性外,觸摸事件還包含下列三個用於跟蹤觸摸的屬性; touches: 表示當前跟蹤的觸摸操做的Touch對象數組; targetTouches: 特定與事件目標的Touch對象數組; changeTouches: 表示自上次觸摸以來發生了什麼改變的Touch對象數組;

 

事件流事件流描述的是從頁面中接收事件的順序,IE和Netscape提出來差很少徹底相反的事件流的概念,IE事件流是事件冒泡流,Netscape事件流是事件捕獲流。
事件冒泡IE的事件流叫作事件冒泡,即事件開始時由最具體的元素(文檔中嵌套最深的那個節點)接收,而後逐級向上(一直到文檔);以下代碼:
<div id = "div">    <span id="span">        <a id="aTag">事件測試</a>    </span></div>
JS以下:
document.getElementById("aTag").addEventListener('click',aTag);document.getElementById("span").addEventListener('click',span);document.getElementById("div").addEventListener('click',div);function aTag(e) {    alert("點擊的是a標籤");}function span(e) {    alert("點擊的是span標籤");}function div(e) {    alert("點擊的是div標籤");}
當單擊 「事件測試」文字後,那麼click事件會按照以下順序傳播;1.先打印出:點擊的是a標籤2.再打印出:點擊的是span標籤3.最後打印出:點擊的是div標籤4.最後確定是document文檔。
全部現代瀏覽器都支持事件冒泡。
事件捕獲:事件捕獲與事件冒泡事件流正好相反的順序,事件捕獲的事件流是最外層逐級向內傳播,也就是先document,而後逐級div標籤 , span標籤 , a標籤;
上面的JS代碼改爲以下:
document.getElementById("div").addEventListener('click',div,true);document.getElementById("aTag").addEventListener('click',aTag,true);document.getElementById("span").addEventListener('click',span,true);
第三個參數設置爲true,即爲捕獲事件,默認爲false;不然的話,事件流仍是和上面的同樣,由於不論是在IE仍是標準瀏覽器下,事件冒泡瀏覽器都支持的。
DOM事件流DOM2級事件規定的事件流包括三個階段,分別是:事件捕獲階段,處於目標階段和事件冒泡階段。示意圖就不畫了,具體的能夠看看書。
DOM0級事件處理程序以下代碼是DOM0級事件處理程序:
var btn = document.getElementById("btn");btn.onclick = function(){     alert("Clicked");};
使用DOM0級方法指定的事件處理程序被認爲是元素的方法,處理程序是在元素的做用域進行的,程序中this是引用的是當前元素。
<div id="btn">btn</div>var btn = document.getElementById("btn");btn.onclick = function(){    alert(this.id); // 彈出btn}
單擊元素btn後,經過this.id取得元素的屬性id,還能夠經過this訪問元素的任何屬性和方法,以這種方式添加的事情處理程序在事件流的冒泡階段處理。也能夠刪除經過DOM0級方法指定的事件處理程序,只要將事件處理程序的屬性值設置爲null便可。btn.onclick = null; // 刪除事件處理程序;
以下JS代碼改爲以下:
var btn = document.getElementById("btn");btn.onclick = function(){    alert(this.id);}btn.onclick = null;
再單擊btn後,沒有任何反應;DOM2級事件處理程序DOM2級事件定義了2個方法,用於處理指定和刪除事件處理程序的操做;addEventListener()和removeEventListener()。全部DOM節點都包含這兩個方法,他們包含三個參數,第一個參數爲事件類型;第二個參數爲事件函數,第三個參數爲布爾值,若是是true的話,說明是事件流是捕獲事件,若是是false的話,那麼事件流是冒泡事件;好比如上的btn代碼,咱們改爲以下:
var btn = document.getElementById("btn");btn.addEventListener('click',function(e){    alert(this.id);},false);
上面的點擊事件是在冒泡階段被觸發,與DOM0級方法同樣,這裏添加的事件處理程序也是在其依副的元素做用域中運行,使用DOM2級添加事件處理程序的好處是能夠添加多個事件處理程序,以下代碼:
var btn = document.getElementById("btn");btn.addEventListener('click',function(e){    alert(this.id);},false);btn.addEventListener('click',function(e){    alert("我是來測試的");},false);
上面的代碼被彈出2次對話框,而在DOM0級是不能夠的;它永遠是執行最後一次的。
addEventListener添加的事件只能使用removeEventListener來刪除相對應的事件,那麼如上的JS不能按照上面的方式來編寫哦!須要給定義一個函數;以下:
btn.addEventListener('click',handler,false);function handler(e){   alert(this.id);}
可使用以下方式對click事件刪除;以下代碼:
btn.removeEventListener(‘click’,handler);
上面的是在標準瀏覽器下處理的事件,下面咱們來看看在IE下處理的事件;IE事件處理的程序IE實現了與DOM相似的2個方法,分別是attachEvent()和detachEvent(),這兩個方法只接受2個參數,第一個參數是事件名稱,第二個參數是要處理的函數;因爲IE8及更早版本只支持事件冒泡,因此經過attachEvent()添加的事件處理程序會被添加到冒泡階段;下面是IE事件處理程序的代碼以下:
btn.attachEvent('onclick',handler);function handler(e){    alert(this); // window}
注意:attachEvent的事件名稱是onclick,而addEventListener的事件名稱是click,且IE中使用的attachEvent()與使用DOM0級方法的的主要區別在於事件處理程序的做用域,在使用dom0級狀況下,事件處理程序在其所屬元素的做用域內運行,在使用attachEvent()方法的狀況下,事件處理程序在全局做用域下運行,其中的this等於window。
與addEventListener同樣,attachEvent也能夠註冊多個點擊click事件,以下代碼:
btn.attachEvent('onclick',function(e){    alert("1");});btn.attachEvent('onclick',function(e){    alert("2");});
可是與Dom方法不一樣的是,這些事件處理程序不是以添加他們的順序執行,而是以相反的順序觸發,好比如上代碼,會先彈出2,而後彈出1對話框;使用attachEvent註冊的事件只能使用detachEvent()方法來移除;
下面咱們能夠來編寫跨瀏覽器的事件處理程序;代碼以下:
var EventUtil = {    addHandler: function(element,type,handler) {        if(element.addEventListener) {                        element.addEventListener(type,handler,false);        }else if(element.attachEvent) {                    element.attachEvent("on"+type,handler);        }else {            element["on" +type] = handler;        }    },    removeHandler: function(element,type,handler){        if(element.removeEventListener) {                    element.removeEventListener(type,handler,false);        }else if(element.detachEvent) {                    element.detachEvent("on"+type,handler);        }else {            element["on" +type] = null;        }    }};
下面咱們可使用這個封裝的函數代碼來測試以前的代碼了,代碼改爲以下所示:
function handler(){    alert(1);}EventUtil.addHandler(btn,'click',handler);
在IE或者標準瀏覽器下都會彈出1;若是咱們須要移除click事件的話,咱們可使用以下代碼:
EventUtil.removeHandler(btn,’click’,handler);
而後在標準瀏覽器下或者IE下點擊btn元素都沒有反應;
事件對象:在觸發DOM上的某個事件時,會產生一個事件對象event,這個對象中包含着全部與事件有關的信息;包括致使事件的元素,事件的類型以及其餘與特定事件相關的信息。咱們來看看dom0級和dom2級的事件對象Event;
好比以下代碼:
var btn = document.getElementById("btn");btn.onclick = function(e){    console.log(e);}
下面咱們來看看最基本的成員的含義吧;以下:
屬性/方法類型含義bubblesBoolean事件是否冒泡cancelableBoolean是否能夠取消事件的默認行爲currentTargetBoolean事件處理程序當前正在處理事件的那個元素defaultPreventedBoolean爲true 表示已經調用了preventDefault()detailInteger與事件相關的細節信息eventPhaseInteger調用事件處理程序的階段:1表示捕獲階段,2表示「處於目標」,3表示冒泡階段preventDefault()Function取消事件的默認行爲。若是cancelable是true,則可使用這個方法stopImmediatePropagation()Function取消事件的進一步捕獲或冒泡,同時阻止任何事件處理程序被調用stopPropagation()Function取消事件的進一步捕獲或冒泡。若是bubbles爲true,則可使用這個方法targetElement事件的目標typeString被觸發的事件的類型viewAbstractView與事件關聯的抽象視圖。等同於發生事件的window對象理解currentTarget與target
在事件處理程序內部,this始終等於currentTarget值,即currentTarget是指當前被觸發或者說正在處理事件的那個元素,而target是指當前的目標元素;好比以下代碼,對btn按鈕觸發點擊事件,那麼e.currentTraget指向了this,e.target也指向了this;以下代碼:
var btn = document.getElementById("btn");btn.onclick = function(e){    console.log(e.currentTarget == this); // true    console.log(e.target == this);  // true}可是若是我對document.body觸發點擊的話,那麼e.currentTarget就指向了document.body了,那麼e.target 指向與 btn那個元素了,以下代碼:
document.body.onclick = function(e){    console.log(e.currentTarget === document.body); // true    console.log(document.body === this);  // true    console.log(e.target === document.getElementById("btn")); //true};如今應該能理解currentTarget與target的區別吧!currentTarget就是指被點擊的那個元素,可是target是當前點擊的目標元素,如上代碼,因爲btn上並無註冊事件,結果click事件就冒泡到了document.body,在那裏事件才獲得了處理。
理解標準瀏覽器下的事件對象與IE下的事件對象標準瀏覽器下的事件對象是event,好比btn點擊後;以下代碼:
var btn = document.getElementById("btn");btn.onclick = function(){    console.log(event); //標準瀏覽器下打印事件對象    console.log(event.type);//'click'}btn.onclick = function(){    // IE下打印的事件對象window.event    console.log(window.event);    console.log(window.event.type); // 'click' }上面的寫法是在DOM0級上註冊事件,若是咱們在Dom2級上註冊事件的話,那麼就會有一個事件對象event做爲參數傳入事件到函數中,以下:
var btn = document.getElementById("btn");EventUtil.addHandler(btn,'click',function(e){    console.log(e);});理解特定事件的默認行爲事件
在標準瀏覽器下,在阻止特定事件的默認行爲,可使用preventDefault()方法,好比以下,我點擊一個鏈接,按道理是打開一個新鏈接窗口,可是我使用preventDefault()方法能夠阻止默認行爲,阻止打開新窗口;以下代碼:
HTML:<a href="http://www.baidu.com" id="alink" target="_blank">打開新鏈接</a>JS以下:var alink = document.getElementById("alink");alink.onclick = function(e){    console.log(e)    e.preventDefault();}
就能夠阻止頁面進行跳轉了~ 這是標準瀏覽器下處理方式,下面咱們來看看IE是如何處理默認事件的;IE下使用returnValue屬性來取消給定事件的默認行爲,只要將returnValue屬性值設置爲false便可,就能夠阻止瀏覽器的默認行爲,以下代碼:
alink.onclick = function(){    console.log(window.event)    window.event.returnValue = false;}
標準瀏覽器下與IE下的事件目標的區別標準瀏覽器下使用e.target來指定當前被點擊的目標元素,以下代碼所示:
var btn = document.getElementById("btn");btn.onclick = function(){    console.log(event);     console.log(event.target); // 打印事件目標元素}
IE下是使用event.srcElement來指定當前的目標元素,以下代碼:
btn.onclick = function(){    console.log(event);     console.log(window.event.srcElement);}
理解標準瀏覽器與IE下阻止事件傳播的區別在標準瀏覽器下咱們可使用stopPropagation()方法來中止事件在DOM層次中的傳播,即取消事件中的冒泡或者捕獲。從而避免觸發註冊在document.body上面的事件處理程序,以下所示:
var btn = document.getElementById("btn");btn.onclick = function(e){    alert(1);    e.stopPropagation();}document.body.onclick = function(){    alert(2);}
如上代碼,若是我不使用stopPropagation()阻止冒泡事件的話,那麼在頁面中會先彈出1,而後彈出2,若是使用stopPropagation()方法的話,只會在頁面上彈出1,就不會冒泡到body上面去;
IE下中止冒泡的話,咱們可使用cancelBubble屬性,咱們只要將此屬性設置爲true,便可阻止事件經過冒泡觸發document.body中的註冊事件。可是IE是不支持捕獲事件的,可是stopPropagation()即支持捕獲事件又支持冒泡事件的。以下代碼:
btn.onclick = function(e){    alert(1);    window.event.cancelBubble = true;}document.body.onclick = function(){    alert(2);}
若是不設置window.event.cancelBubble 爲true的話,就會先彈出1,而後彈出2,若是加上的話,就只會彈出1對話框。理解了上面的區別後,咱們如今能夠往EventUtil對象裏面添加跨瀏覽器的方法了;
跨瀏覽器的事件對象
var EventUtil = {    addHandler: function(element,type,handler) {        if(element.addEventListener) {            element.addEventListener(type,handler,false);        }else if(element.attachEvent) {            element.attachEvent("on"+type,handler);        }else {            element["on" +type] = handler;        }    },    removeHandler: function(element,type,handler){        if(element.removeEventListener) {            element.removeEventListener(type,handler,false);        }else if(element.detachEvent) {            element.detachEvent("on"+type,handler);        }else {            element["on" +type] = null;        }    },    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;        }    },    stopPropagation: function(event) {        if(event.stopPropagation) {            event.stopPropagation();        }else {            event.cancelBubble = true;        }    }};
事件類型:DOM3級事件規定了如下幾類事件;以下:UI事件: 當用戶與頁面上的元素交互時觸發;load事件:當頁面加載完後(包括全部圖像,全部javascript文件,css文件等外部資源),就會觸發window上面的load事件,以下代碼是加載圖片的:HTML代碼:<img src = 「event.png」 id=」img」/>
JS代碼以下:
var img = document.getElementById("img");EventUtil.addHandler(img,'load',function(event){      var event = EventUtil.getEvent(event);      alert(EventUtil.getTarget(event).src);});
當圖片加載完後,就會彈出圖片的url地址了;若是在建立新的img元素時,能夠爲其指定一個事件處理程序,以便圖像加載完成後給出提示,此時,最重要的是在指定src屬性以前先指定事件;以下代碼所示:
 EventUtil.addHandler(window,'load',function(){    var img = document.createElement("img");    EventUtil.addHandler(img,'load',function(e){        e = EventUtil.getEvent(e);        alert(EventUtil.getTarget(e).src);    });    document.body.appendChild(img);    img.src = "event.png";});
在圖像加載完成後,會彈出圖片地址了;一樣的功能,咱們可使用DOM0級的Image對象來實現,在DOM出現以前,開發人員常用Image對象在客戶端預加載圖像,以下代碼:
EventUtil.addHandler(window,'load',function(){    var img = new Image();    EventUtil.addHandler(img,'load',function(e){        alert(1);    });    img.src ="event.png";});
Script元素也支持load事件,可是IE8及如下不支持,在IE9+,Firefox,Opera,chrome及Safari3+都支持,以便開發開發人員肯定動態加載的javascript文件是否加載完畢;好比咱們動態建立script標籤後,經過load事件判斷動態建立的script標籤是否加載完畢,代碼以下:
EventUtil.addHandler(window,'load',function(){    var script = document.createElement("script");    EventUtil.addHandler(script,'load',function(e){        alert(1);    });    script.src = "a.js";    document.body.appendChild(script);});
焦點事件:當元素得到或失去焦點時觸發;有:blur:在元素失去焦點時觸發,這個事件不會冒泡,全部瀏覽器都支持。foucs:在元素得到焦點時觸發,這個事件不會冒泡,全部瀏覽器都支持。鼠標事件:當用戶經過鼠標在頁面操做時觸發;
click事件:在用戶單擊鼠標按鈕或者按下回車鍵觸發;dblclick事件:在用戶雙擊鼠標按鈕時被觸發;mousedown事件:在用戶按下了任意鼠標按鈕時被觸發,不能經過鍵盤觸發這個事件。mouseenter事件:在鼠標光標從元素外部移動到元素範圍以內被觸發;這個事件不冒泡;mousemove事件:當鼠標指針在元素內部移動時重複地觸發。mouseout事件:用戶將其移入另外一個元素內被觸發。mouseover事件:鼠標指針在元素外部,用戶將移入另外一個元素的邊界時觸發,感受和mouseenter事件相似;mouseup事件:用戶釋放鼠標按鈕時觸發;頁面上全部的元素都支持鼠標事件,除了mouseenter和mouseleave,全部鼠標事件都會冒泡,也能夠被取消,而取消鼠標事件將會影響瀏覽器的默認行爲。
理解客戶區座標位置含義是:鼠標指針在可視區中的水平clientX和垂直clientY座標;代碼以下:
EventUtil.addHandler(btn,'click',function(e){    e = EventUtil.getEvent(e);    console.log("可視區X軸座標爲:"+e.clientX + " "+ "可視區Y軸座標爲:"+e.clientY);});
注意:客戶區座標位置不包含滾動條滾動的位置,所以這個位置不表明鼠標在頁面上的位置;
理解頁面座標位置pageX和pageY:pageX與pageY是指頁面座標的位置,與clientX和clientY的區別是:它包含頁面滾動條的位置
代碼以下:
EventUtil.addHandler(btn,'click',function(e){    e = EventUtil.getEvent(e);    console.log("頁面X軸座標爲:"+e.pageX + " "+ "頁面Y軸座標爲:"+e.pageY);});
在頁面沒有滾動條的狀況下,pageX與clientX相等,同理pageY與clientY相等。
可是IE8及更早的版本不支持pageX與pageY,不過咱們可使用客戶區座標(client,clientY)和滾動座標計算出來;所以咱們須要用到document.body(混雜模式下)或 document.documentElement(標準模式下)中的scrollLeft和scrollTop屬性;
對此咱們能夠封裝代碼以下:
EventUtil.addHandler(btn,'click',function(e){    e = EventUtil.getEvent(e);    var pageX = e.pageX,          pageY = e.pageY;    if(!pageX) {    pageX = e.clientX + (document.body.scrollLeft || document.documentElement.scrollLeft);    }    if(!pageY) {    pageY = e.clientY + (document.body.scrollTop || document.documentElement.scrollTop);    }    console.log("頁面X軸座標爲:"+pageX + " "+ "頁面Y軸座標爲:"+pageY);});
理解屏幕座標的位置屏幕橫座標screenX和垂直座標screenY屬性是相對於整個屏幕的
以下代碼測試:
EventUtil.addHandler(btn,'click',function(e){    e = EventUtil.getEvent(e);    console.log("屏幕X軸的座標爲:"+e.screenX + " "+"屏幕Y軸的座標爲:"+e.screenY);});
理解鼠標滾輪事件:
IE6首先實現了mousewheel事件,此後opera,chrome和safari也都實現了這個事件,當用戶經過鼠標滾輪與頁面交互,在垂直方向上滾動頁面時(不管向上仍是向下),就會觸發mousewheel事件,這個事件能夠在任何元素上觸發,最終會冒泡到document(IE8)或window(IE9,Opera,Chrome,Safari)對象,與mousewheel事件對應的event對象外,還有一個屬性wheelDelta屬性,當用戶向前滾動鼠標滾輪時,wheelDelta是120的倍數,當用戶向後滾動鼠標滾輪時,wheelDelta是-120的倍數。
將mousewheel事件給頁面任何元素或document對象,便可處理鼠標滾輪操做;以下代碼:
EventUtil.addHandler(btn,'mousewheel',function(e){    e = EventUtil.getEvent(e);    alert(e.wheelDelta);});
如上代碼,我不是在document對象或者window對象上,而是在頁面btn元素上觸發的;可是咱們要注意,在Opera9.5以前的版本中,wheelDelta值的正負號是顛倒的,若是咱們要支持Opera9.5版本以前的話,那麼咱們須要瀏覽器檢測技術來檢測下;以下代碼
EventUtil.addHandler(document, "mousewheel", function(event){    event = EventUtil.getEvent(event);    // var delta = (client.engine.opera && client.engine.opera < 9.5 ? -event.wheelDelta : event.wheelDelta);       var delta = event.wheelDelta;    alert(delta);});
可是client.engine.opera 這句代碼運行下會報錯,由於目前尚未封裝這個方法,因此等下一個博客我會研究代理檢測封裝下這個方法;因此先不考慮opera9.5,先註釋掉這句代碼;
可是FireFox支持一個爲DOMMouseScroll的事件,也是在鼠標滾輪滾動時觸發,與mousewheel事件同樣,可是他的有關鼠標滾輪信息保存在detail屬性中,當鼠標向前滾動時,這個屬性值是-3的倍數,當鼠標滾輪向後滾動時,這個屬性值是3的倍數;也能夠給DOMMouseScroll事件使用在任何元素上,且這個事件會冒泡到window對象上,所以咱們能夠這樣添加滾輪信息的代碼以下:
EventUtil.addHandler(document, "DOMMouseScroll", function(event){    event = EventUtil.getEvent(event);    alert(event.detail);});
咱們如今能夠給跨瀏覽器下的滾輪事件;代碼以下:
function getWheelDelta (event) {    if(event.wheelDelta) {    // return (client.engine.opera && client.engine.opera < 9.5 ? -event.wheelDelta : event.wheelDelta);         return  event.wheelDelta;    }else {        return -event.detail * 40    }}getWheelDelta方法首先檢測了事件對象是否包含了wheelDelta屬性,若是包含則返回屬性值,若是不包含,那麼咱們就看成是firefox瀏覽器,那麼假設相應的值保存在detail屬性中,有了上面的方法後,咱們如今能夠將相同的事件指定給mousewheel事件和DOMMouseScroll事件了;
EventUtil.addHandler(document, "DOMMouseScroll", handleMouseWheel);EventUtil.addHandler(document, "mousewheel", handleMouseWheel);function handleMouseWheel(event) {    event = EventUtil.getEvent(event);    var delta = EventUtil.getWheelDelta(event);    alert(delta);}
滾輪向上滾動是正數120,向下滾動是負數-120,因此根據是否大於0,能夠判斷是向下滾動仍是向上滾動;
理解字符編碼charCode
IE9+,firefox,chrome和safari的event對象都支持一個charCode屬性,這個屬性只有在發生keypress事件時才包含值,並且這個值是按下的那個鍵所表明字符的ASCLL編碼,可是IE8及以前或者opera不支持這個屬性,可是咱們可使用keyCode這個屬性代替.在取得了字符編碼以後,就可使用String.fromCharCode()將其轉換成實際的字符。
以下代碼:
getCharCode: function(event) {    if(typeof event.charCode == 'number') {        return event.charCode;    }else {        return event.keyCode;    }}
咱們如今能夠給EventUtil添加事件了,以下代碼:
var EventUtil = {    addHandler: function(element,type,handler) {        if(element.addEventListener) {            element.addEventListener(type,handler,false);        }else if(element.attachEvent) {            element.attachEvent("on"+type,handler);        }else {            element["on" +type] = handler;        }    },    removeHandler: function(element,type,handler){        if(element.removeEventListener) {            element.removeEventListener(type,handler,false);        }else if(element.detachEvent) {            element.detachEvent("on"+type,handler);        }else {            element["on" +type] = null;        }    },    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;        }    },    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){            return event.toElement;        } else if (event.fromElement){            return event.fromElement;        } else {            return null;        }    },    getWheelDelta: function(event) {        if(event.wheelDelta) {            return event.wheelDelta;        }else {            return -event.detail * 40        }    },    getCharCode: function(event) {        if(typeof event.charCode == 'number') {            return event.charCode;        }else {            return event.keyCode;        }    }};
咱們如今能夠作一個demo以下:
以下代碼:var inputDiv = document.getElementById("inputDiv");EventUtil.addHandler(inputDiv,'keypress',function(event){    event = EventUtil.getEvent(event);    var code = EventUtil.getCharCode(event);    alert(EventUtil.getCharCode(event)); // 彈出字符編碼    alert(String.fromCharCode(code));  // 彈出字符});HTML5事件
1.contextmenu事件contextmenu事件在windows操做系統下,咱們是使用右鍵就能夠自定義右鍵彈出菜單,可是咱們使用右鍵的時候會有默認的菜單,所以咱們須要使用阻止默認事件這個方法來阻止掉;此事件也是屬於鼠標事件,所以此事件包含與光標位置中全部的屬性
HTML代碼以下:<div id="myDiv">Right click or Ctrl+click me to get a custom context menu.Click anywhere else to get the default context menu.</div><ul id="myMenu" style="position:absolute;visibility:hidden;background-color:    silver"><li><a href="http://www.nczonline.net">Nicholas’ site</a></li><li><a href="http://www.wrox.com">Wrox site</a></li><li><a href="http://www.yahoo.com">Yahoo!</a></li></ul>
JS代碼以下:var div = document.getElementById("myDiv");EventUtil.addHandler(div, "contextmenu", function(event){    event = EventUtil.getEvent(event);    EventUtil.preventDefault(event);    var menu = document.getElementById("myMenu");    menu.style.left = event.clientX + "px";    menu.style.top = event.clientY + "px";    menu.style.visibility = "visible";});EventUtil.addHandler(document, "click", function(event){    document.getElementById("myMenu").style.visibility = "hidden";});
如上,咱們是經過右鍵的clientX和clientY來肯定菜單的位置;當我點擊文檔document的時候 就隱藏該菜單;
瀏覽器支持有:IE,Firefox,Safari,chrome和Opera11+
beforeunload事件
此事件是給頁面在卸載以前,給用戶一個提示,是否須要卸載頁面提示給用戶,爲了顯示這個對話框,對IE和firefox而言,必須將event.returnValue的值設置爲要顯示給用戶的字符串;可是對於safari和chrome而言,能夠返回此字符串便可;
以下代碼:
EventUtil.addHandler(window, "beforeunload",function(event){    event = EventUtil.getEvent(event);    var message = "I'm really going to miss you if you go.";    event.returnValue = message;    return message;});
當用戶關閉遊覽器的時候,會彈出以下窗口給用戶提示點擊離開此頁按鈕 即關閉窗口,點擊留在此頁按鈕 即留在當前頁面,可是當我按F5刷新頁面的時候,一樣會彈出窗口提示
瀏覽器支持:IE,firefox,chrome和safari都支持,可是Opera11及以前的版本不支持;
理解hashchange事件
HTML5中新增長了hashchange事件,以便在URL的參數列表(url中的#號後面的全部參數發生改變時通知開發人員),在Ajax應用中,開發人員常用url參數列表保存狀態或導航信息;咱們必須把hashchange事件添加到window對象中,而後當url參數列表只要發生變化就會調用此事件,此事件對象event包含2個屬性,oldURL和newURL,這兩個屬性分別保存着URL變化先後的完整URL;
支持的瀏覽器有:IE8+,firefox3.6+,safari5+,chrome和opera10.6+在這些瀏覽器中,只有firefox3.6+,chrome和opera支持oldURL和newURL屬性;
以下代碼:
EventUtil.addHandler(window, "hashchange", function(event){     alert("Old URL: " + event.oldURL + "\nNew URL: " + event.newURL);});
當我第一次#號參數後面是aa,如今改爲aaaa,就會觸發此事件有些瀏覽器並不支持oldURL和newURL,所以咱們可使用location.hash來保存當前的參數列表,以下代碼:
EventUtil.addHandler(window, "hashchange", function(event){
      alert(location.hash);
});
當#號後面我改爲bbb參數時候可使用以下代碼來檢測瀏覽器是否支持hashchange事件;
var isSupported = ("onhashchange" in window);alert(isSupported);
若是IE8 是在IE7 文檔模式下運行,即便功能無效它也會返回true。爲解決這個問題,可使用如下這個更穩妥的檢測方式:
var isSupported = ("onhashchange" in window) && (document.documentMode === undefined || document.documentMode > 7);設備事件中的—orientationchange事件
蘋果公司爲移動safari添加的orientationchange事件是能讓用戶肯定什麼時候將設備由橫向查看模式切換到縱向模式觸發的事件;此屬性中包含三個值,0表示肖像模式;90表示向左旋轉的橫向模式(主屏幕按鈕在右側),-90表示向右旋轉的橫向模式(主屏幕按鈕在左側)
只要用戶改變了設備的查看模式,就會觸發orientationchange事件,使用IOS設備便可演示效果:代碼以下:
EventUtil.addHandler(window, "load", function(event){    var div = document.getElementById("myDiv");    div.innerHTML = "Current orientation is " + window.orientation;    EventUtil.addHandler(window, "orientationchange", function(event){        div.innerHTML = "Current orientation is " + window.orientation;    });});
理解移動端的事件—觸摸與手勢事件有如下幾個觸摸事件:
touchstart: 當手指觸摸屏幕時觸發,即便是一個手指放在屏幕上也會觸發。touchmove:當手指在屏幕上滑動時連續地觸發,這個事件發生期間,咱們可使用preventDefault()事件能夠阻止滾動。touchend: 當手指從屏幕上移開時觸發。touchcancel: 當系統中止跟蹤觸摸時觸發。上面幾個事件都屬於冒泡事件,咱們能夠對此進行取消事件,每一個觸摸的event對象都提供了在鼠標中常見的屬性;
bubbles, cancelable,view,clientX, clientY ,screenX, screenY,detail, altKey, shiftKey, ctrlKey, metaKey,除了常見的DoM屬性外,觸摸事件還包含下列三個用於跟蹤觸摸的屬性;touches: 表示當前跟蹤的觸摸操做的Touch對象數組;targetTouches: 特定與事件目標的Touch對象數組;changeTouches: 表示自上次觸摸以來發生了什麼改變的Touch對象數組;javascript

相關文章
相關標籤/搜索