二、在javascript中,為元件的事件建立事件處理函式
在每個事件發生之後即會啟動事件處理函式,接著我們會希望能夠執行一些程式碼來達成一些效果。如何將這些要執行的程式碼與元件的事件處理函式作連結(這稱為「事件處理模式」),其方法有許多種,隨著DOM(document object model,文件物件模式)版本不同而不同,也隨著瀏覽器不同而不同。以下,我們介紹DOM0和DOM2的事件處理模式。
1. DOM0的事件處理模式:
DOM0將事件處理函式當作元件的屬性。上述所有將事件處理函式寫在html標籤中的寫法,就符合DOM0的事件處理模式。所以,以DOM0的事件處理模式而言,要在javascript中為某元件設定事件處理函式,也一樣是要把他當作元件的屬性來設定。語法如下:
(1) 元件.setAttribute("事件處理函式名稱", "執行碼");
其中,執行碼就是該元件在發生該事件後,會執行的程式碼,也就是該事件的「效果」。執行碼的寫法可以是呼叫一個已存在的函式,如:
函式名(參數一, 參數二…);
也可以是單純的javascript程式碼。
範例如下:
<body>
<input type="text" id="text1" />
</body>
<script type="text/javascript">
function get_msg(S)
{ document.write(S); }
document.getElementById("text1").setAttribute("onclick","get_msg('OK!');");
</script>
這是呼叫一個已存在的函式給執行碼,又如:
<body>
<input type="text" id="text1" />
</body>
<script type="text/javascript">
document.getElementById("text1").setAttribute("onclick","document.write('OK!');");
</script>
這是將執行碼直接寫成javascript程式碼。上述這兩種寫法有著相同的效果:若使用者之滑鼠在ID為text1的那個元件上按了一下,螢幕會顯示出OK!的文字。
(2) 要解除該元件的事件處理函式,就像解除該元件的屬性一樣。語法如:
元件.removeAttribute("事件處理函式名稱");
(3) DOM0事件處理模式有個所謂的「事件往上傳遞(英文為 event bubbling)」的特性,即觸發該事件的元件中,如果其祖先元件有為同樣的事件處理函式設定執行碼,則會一併執行其祖先元件的這些執行碼。如下列程式碼:
<body onclick="document.getElementById('test').value+='BODY,';">
<div onclick="document.getElementById('test').value+='DIV,';">
<table id="this_table" >
<tbody ondblclick="document.getElementById('test').value+='TBODY,';">
<tr>
<td><input type="button" onclick="document.getElementById('test').value+='BUTTON,';" value="按我" /></td>
</tr>
</tbody>
</table>
</div>
<input type="text" id="test" size="30"/>
</body>
<script type="text/javascript">
document.getElementById('this_table').setAttribute("onclick","document.getElementById('test').value+='TABLE,';");
</script>
程式執行後、按下「按我」按鈕後,顯示出的是:
雖然我們按下的是button元件,但除了button元件本身的onclick事件處理函式被觸發之外,其祖先元件中的onclick事件處理函式也被觸發了!而且由顯示訊息的先後,還可看出是button元件本身的onclick事件處理函式先被觸發,接著觸發的順序從其輩分低的祖先、到輩份高的祖先,這就是所謂的「事件往上傳遞」。這種設計是考量到在瀏覽視窗中,後代元件的位置通常和祖先元件重疊,當我們在某個元件上用滑鼠觸發事件時,瀏覽器並無法分辨使用者是要觸發祖先元件還是後代元件,所以就從後代元件到祖先元件中搜索,看其是否有相應的事件處理函式,若有就觸發之。
(4) 事件本身:
在事件觸發的時候,瀏覽器會將事件的相關資訊儲存在一個物件上。此物件名為event(event在javascript中是關鍵字),是個環境變數(包含「整個程式之作業環境之訊息」的變數)。而對於不同種類的事件,event物件所存的資訊也是不一樣的。
(4-1) 對所有種類的事件而言:
(4-1-1) event物件常用的成員:
※ event物件.type:該事件的事件名稱。
※ event物件.srcElement:一個元件之指標。乃是觸發此事件的元件之指標。此成員在chrome、firefox等瀏覽器中是法使用的。在IE等瀏覽器中是可用的。
※ event物件.target:和event物件.srcElement相同。不過此成員在IE8及其以下版本的瀏覽器中是無法使用的。在chrome、firefox等瀏覽器中是可用的。
※ 範例如下:
<head>
<script type="text/javascript">
function tt(this_e)
{
var target = this_e.target ? this_e.target : this_e.srcElement;
document.getElementById('test').value=target.id;
} //這樣寫,在IE、chorme、firefox等主要瀏覽器中均有效
</script>
</head>
<body >
<input type="text" id="test" />
<input type="text" id="test2" onkeypress="tt(event);" />
</body>
這樣一來,在id為test2的文字輸入列中按下任意的鍵盤按鍵,則在id為test的文字輸入列中就會顯示test2。
(4-1-2) event物件常用的成員函式:
※ event物件.preventDefault():此成員函式一執行,則可停止此事件再繼續產生任何效果(包括原本的效果)。不過此函式在IE8及其以下版本的瀏覽器中是無法使用的。在chrome、firefox等瀏覽器中是可用的。在IE8及其以下版本的瀏覽器中另有一寫法能達成此函式的作用,語法為:event物件.returnValue=false;。範例如下:
<head>
<script type="text/javascript">
function tt(this_e)
{
var target = this_e.target ? this_e.target : this_e.srcElement;
document.getElementById('test').value=target.id;
if(this_e.preventDefault){ this_e.preventDefault();}
else { this_e.returnValue=false;} //這樣寫,在IE、chorme、firefox等主要瀏覽器中均有效
}
</script>
</head>
<body >
<input type="text" id="test" />
<input type="text" id="test2" onkeypress="tt(event);" />
</body>
執行程式後,若在id為test2的文字輸入框中按了k鍵,則在id為test的文字輸入框中就顯示test2。不過,在id為test的文字輸入框中就不會出現k這個字元了!這告訴我們兩件事:
a. 就算設計者沒有為文字輸入框設定任何事件處理函式,只要在文字輸入框中按下按鍵,就是觸發了內建的鍵盤事件處理函式。「顯示字元」就是這個事件的效果。
b. 若設計者有為文字輸入框設定事件處理函式,「顯示字元」這個效果發生在「自設的事件處理函式的效果(如function tt(event))」之後。所以只要在「自設的事件處理函式的效果」中執行event物件.preventDefault();或是event物件.returnValue=false;來讓此事件失效,則後續所有的效果(包括「顯示字元」)都不會發生了。
※ event物件.stopPropagation():此成員函式一執行,則可停止事件的往上傳遞。不過此函式在IE8及其以下版本的瀏覽器中是無法使用的。在chrome、firefox等瀏覽器中是可用的。在IE8及其以下版本的瀏覽器中另有一寫法能達成此函式的作用,語法為:event物件.cancelBubble=true;。
(4-2) 對於滑鼠事件而言:
(4-2-1) event物件常用的成員:
※ event物件.altKey:一個bool。若為true,表示該事件觸發時按著Alt鍵。若為false則否。
※ event物件.ctrlKey:一個bool。若為true,表示該事件觸發時按著Ctrl鍵。若為false則否。
※ event物件.shiftKey:一個bool。若為true,表示該事件觸發時按著Shift鍵。若為false則否。
※ event物件.clientX:一個整數。表示該事件觸發時,滑鼠的X座標(以網頁文件的左上角為座標零點)。
※ event物件.clientY:一個整數。表示該事件觸發時,滑鼠的Y座標(以網頁文件的左上角為座標零點)。
※ event物件.screenX:一個整數。表示該事件觸發時,滑鼠的X座標(以螢幕的左上角為座標零點)。
※ event物件.screenY:一個整數。表示該事件觸發時,滑鼠的Y座標(以螢幕的左上角為座標零點)。
(4-3) 對於鍵盤事件而言:
(4-3-1) event物件常用的成員:
※ event物件.keyCode:一個整數。代表所按下之鍵盤按鍵的編號。此成員在chrome、firefox等瀏覽器中是法使用的。在IE等瀏覽器中是可用的。
※ event物件.which:和event物件.keyCode相同。不過此成員在IE8及其以下版本的瀏覽器中是無法使用的。在chrome、firefox等瀏覽器中是可用的。
※ 範例如下:
<head>
<script type="text/javascript">
function tt(this_e)
{
var this_key_code = this_e.keyCode ? this_e.keyCode : this_e.which;
document.getElementById('y').value=this_key_code;
} //這樣寫,在IE、chorme、firefox等主要瀏覽器中均有效
</script>
</head>
<body >
<input type="text" id="x" style="position:absolute" onkeydown="tt(event);">
<label style="position:absolute; left:175px;">unicode of key:</label>
<input type="text" id="y" style="position:absolute ; left:280px;" >
</body>
//執行後,在左邊的文字輸入框內按下按鍵,如按下g,顯示:
71就是g這個按鍵的統一編碼。