5.1 DOM and JavaScript Event

 介紹DOM : Document Object Model 文件物件模型

            就網頁上 javascript 使用 DOM 而言,它可以讓設計人員除了一般的瀏覽器物件(例如 window, document)以外,還能將每個HTML標籤也視為物件來管理,是網頁與 javascript 語言溝通的橋樑。DOM解決了NetscapedJavascriptMicrosoftJscript之間的衝突,給予web設計師和開發者一個標準的方法,讓他們來訪問他們站點中的數據、腳本和表現層對像

DOM 是全球資訊網協會(World Wide Web ConsortiumW3C建立的標準,稱之為「W3C DOM」。是給 HTML XML 使用的一種像java API的模板。但是 DOM 本身是設計為一種獨立的程式語言,以一致的 API 存取文件的結構表述。DOM 其實可以與任何程式語言共同運作。

 

DOM的目的

第一、W3C當初在制定這個標準時,主要為考量web設計師寫的程式,能讓各瀏覽器得到最大的支援
            是它的目的。

第二、相信所有的web設計師,都有相同的希望和目標,那就是讓所有瀏覽器使用者都能看到同樣的
            網頁效果。

第三、因此有了W3C這樣的機構出現,更何況它是非營利事業組織,得到眾多瀏覽器的支援並不能讓
            它獲利,他的出發點大
多是為web設計師、甚或是更廣大的網頁設計人設想。 

  

大致來說 DOM Event 的註冊方式可以分成下面三種︰ 

·     傳統式

·     W3C DOM 標準式

·     IE

 

下面我就一一介紹這三種方式,在介紹之前我先寫一些 sample code 供下面介紹使用︰ 

<div id="div1">

  <a id="link" href="http://xuite.net/" >Link</a>

</div>

<script>

  var oLink = document.getElementById('link');

 

  function handler() {

    alert(this.nodeName);

  }

</script>   

  

  

傳統式

 

  

顧名思義是最早的註冊方式,所有的瀏覽器都支援。

  

oLink.onclick = handler;  

 要取消註冊的時候︰

oLink.onclick = null; 

 

 

在網頁點下 oLink 的時候會跳 A ,因為 handler 裡的 this 會是 oLink

我們平常 inline 寫在 HTML 裡的註冊方式,也算是傳統式的一種。

<a onclick="..." > " " 裡面當成 handler 這個函式裡面就對了,

 

也就是 <a onclick="alert(this.nodeName)" > 和上面寫的 oLink.onclick = handler; 效果是一樣的。 

 

 

傳統式的問題很明顯,如果我要在 oLink onclick 上面註冊兩個函式怎麼辦?也許我們可以在 handler 裡面動手腳,改成下面這樣︰ 

  function handler() {

    func1();

    func2();

  } 

 

 

 

但如果我要把其中的 func1 取消註冊呢?因為這些問題所以才有後面的 W3C DOM 標準式 IE

 

W3C DOM 標準式

顧名思義就是 W3C 為了改善傳統式而訂定出來的標準方式,除了 IE ,各種瀏覽器都支援。註冊方法如下︰ 

         oLink.addEventListener('click', handler, false); 

 

取消註冊的方法︰ 

 

         oLink.removeEventListener('click', handler, false);

  

在網頁點下 oLink 的時候會跳 A ,因為 handler 裡的 this 會是 oLink  

很顯然傳統式的問題解決了。 W3C DOM 標準式要在 oLink 上註冊多個函式,或是移除其中任何一個都沒有問題。addEventListener removeEventListener 的第三個參數叫 useCapture ,和 Event 的傳遞順序有關

 

 

請看上面的 sample code <a> <div> 包住,那如果 <a> <div> onclick 都有被註冊函式,是 <a> 的函式該先被執行,還是 <div> 的該先被執行呢? 

按照 W3C DOM 標準是這樣的, Event 的傳遞分成兩階段,

 

  

第一階段是由上到下,叫 Capture

 

 第二階段是由下到上,叫 Bubble

  

  

由剛剛 <a> <div> 的例子,第一階段 Capture 由上到下就是由 <a> <div> ;第二階段 Bubble 由下到上就是由 <div> <a> ,所以整個 Event 的傳遞順序就是 <a> → <div> → <div> → <a>  

 

你可以用 addEventListener 的第三個參數來決定函式要在 Capture 的階段執行,還是 Bubble 的階段執行。 true 就是 Capture 階段, false 則是 Bubble 階段。你也可以把同一個函式註冊在 Capture 階段,又註冊在 Bubble 階段,寫兩行 addEventListener 便是。 removeEventListener 的第三個參數就是用來指明你要取消註冊的是 Capture 階段的函式,還是 Bubble 階段的函式。 

 

 

1. Regsitering Event Handlers

 用來處理事件的function稱之為Event Handlers
在一開始只有inline model一種
後來Nascape開發了traditional model以後Internet Explorer也增加了這個規格
W3C接著建造出有更多功能的W3C model,但因為Internet Explorer 7不支援這種形式,所以目前還是以traditional model為主
// inline mode例子:
script裡
function handleEvent()
{
alert("訊息")
}

// traditional mode例子:
function registerEvent()
{
var traditional = ducument.getElementById("traditional")
traditional.onclick = handleEvent;
}
body裡
<body onload = "registerEvent()">
<div id = "inline" onclick = "handleEvent()" >inline mode</div>

<div id = "traditional">traditional mode</div>
</body>

雖然到最後都是呼叫同一個,不過traditional明顯看的出來多次使用function的時候,只要寫標籤就好,不需要加上onclick之類的參數

2. onload

當頁面的元素讀取好的時候onload後面加的function就會啟動
<body onload = "function()">
</body>

3. onmousemove, event Object, this

onmousemove是用來偵測滑鼠移動而產生物件
用物件的onmousemove來宣告事件
var cell = ducument.createElement("td");
cell.onmousemove = processMouse;

function processMouse(e) //e代表的就是event Object
{
if(!e)
var e = window.event; //因為IE不支援所以要這樣轉換
if(e.ctrlKey)
this.style.backgroundColor = "black";
}

使用this可以代表當前觸發的該物件
ex:
this.style.backgroundColor = "black";

4. onmouseover, onmouseout

類似的滑鼠事件還有
onmouseover 偵測滑鼠移到該物件上(沒有點擊)而產生物件
onmouseout  偵測滑鼠移開該物件而產生物件
都是一樣用document.onmouseover(或是onmouseout) = function名稱; 來宣告

5. onfucus, onblur

onfucus 該物件被選中的時候產生物件 比如說像是TextArea就是指游標在框內的狀態
onblur 該物件取消選中狀態的時候產生物件

6. Form Processing: onsubmit, onreset

當文件送出或清除的時候觸發事件
ex:
ducument.getElementById("Form").onsubmit = function()
{
return confirm("確定要傳送此訊息?")
}
按下OK傳回的是True 按下Cancel則是false

7. Event Bubbling

當有parent的物件發生事件的時候,會像泡沫一樣往上層浮,直到Event能夠被Catch到並處理
但有時候會產生不同層都處理到的情形,為了避免如此,可以使用下列表示來只讓child處理事件
function noBubbel(e)
{
alert("事件不會上浮");
e.cancelBubble = true; //加了這行後,就算parent可以處理,也只會讓child處理了
}

8. More events

以下是常使用的事件(Internet Explorer及 Firefox都支援的)

 

 

 

 

 Event  Description(觸發事件的時機)
 onabort  載入圖片被使用者中斷
 onchange  新選項選中或輸入文字改變
 onclick  用滑鼠點擊
 ondbclick  用滑鼠雙擊
 onfocus  物件被選中
 onkeydown  按鍵按下
 onkeypress  按鍵按下並鬆開
 onkeyup  按鍵鬆開
 onload  當元素和他的全部子元素被載入時
 onmousedown  滑鼠按下
 onmousemove  滑鼠移動
 onmouseout  滑鼠離開元素
 onmouseover  滑鼠在該元素上
 onmouseup  滑鼠按鍵鬆開
 onreset  表格的reser按鈕按下重設
 onresize  物件大小改變(如改變視窗大小)
 onselect  文字被選擇(textarea或input)
 onsubmit  表格的onsubmit按鈕按下送出
 onunload  離開目前網頁

 

9.JavaScript幾乎都用來處理DOM,但並不表示 JavaScript=DOM。瀏覽器把所有的元件以物件型式來看待,再透過JavaScript來進行存取或者是控制,也就是說JavaScript所控制的種種效果,需要透過DOM才能達成,我們在瀏覽器所看到的一切元素,其實就是DOM解析後的成果。所以JavaScript與DOM本來就是息息相關的,而DOM可以使用JavaScript來控制,但當離開了DOM,JavaScript就沒有用處了。