這一節,我們來學習如何向XBL元素中添加事件處理程序。
事件處理程序(Event Handlers)
正如你所期望的,匿名內容裡的元素支持鼠標點擊、鍵盤按下等事件。但你可能會想采用一種特別方式觸發事件和處理程序。如果需要,你可以向匿名內容裡 的元素添加事件處理程序。上一小節的最後一個例子其實已經演示了這點。在那個例子中,幾個按鈕被添加了oncommand事件處理程序。
但你可能想為content標記下的所有元素都添加事件處理程序。這在觸發focus事件和blur事件的時候特別有用。使用handler元素定義一個事件處理程序。每個事件處理程序對應一個動作,如果需要,你可以定義多個事件處理程序。如果一個事件和所有定義的處理程序都不匹配,那就會自動按照正常步驟傳遞到內部內容裡。
事件處理程序的一般語法如下所示:
<binding id="binding-name">
<handlers>
<handler event="event-name" action="script"/>
</handlers>
</binding>
把所有的事件處理程序都置於handlers元素下,每個handler元素對應一個特定事件的動作,具體由event特性來定義。只有那些同時被XUL和JavaScript支持的事件類型才是有效的,比如click事件和focus事件。注意事件名稱前面是沒有“on”的。
最常使用事件處理程序的情況就是需要在事件觸發的時候修改自定義屬性。比如說,當用戶點擊一個自定義的復選框時,要自動修改它的checked屬性:
<handlers>
<handler event="mouseup" action="this.checked=!this.checked"/>
</handlers>
當用戶在復選框上點擊並釋放鼠標鍵後,就會觸發mouseup事件,而該事件對應的處理程序隨之會被調用,結果就是將checked屬性的值進行反 轉。同理,你可能想在一個元素被激活的時候就修改其中一個屬性的值,這樣你就需要添加一個事件處理程序,這樣無論通過鍵盤還是鼠標輸入都可以響應。
對於鼠標相關的事件,你可以通過button特性,設置為只有在特定的情況才被觸發。如果不設置這個特性,你無論按下鼠標哪個鍵,都會觸發事件,但 設置後只有在按下特定鍵時才觸發。把button特性設置為0代表鼠標左鍵,設置為1代表鼠標右鍵,設置為2代表鼠標中間的鍵。
<handlers>
<handler event="click" button="0" action="alert('Left button pressed');"/>
<handler event="mouseup" button="1" action="alert('Middle button pressed')"/>
<handler event="click" button="2" action="alert('Right button pressed');"/>
</handlers>
於鍵盤相關的事件,有很多特性都可以用來限制事件觸發的條件。比如key元素可以限定為特定的按鍵組合。我們可以對上一個例子進行擴展,使復選框的checked屬性在按下空格鍵的時候就會修改。
<handlers>
<handler event="keypress" key=" " action="this.checked=!checked"/>
</handlers>
你還可以使用keycode特性來限定那些非打印字符。針對這點,在這篇文章中進行了詳細的描述。可以通過modifIErs特性設置輔助按鍵,具體可以設置為下面其中的一個值:
alt
用戶必須同時按下Alt鍵。
control
用戶必須同時按下Ctrl鍵。
meta
用戶必須同時按下Meta鍵。
shift
用戶必須同時按下Shift鍵。
accel
用戶必須按下特定的輔助按鍵。這個特性是平台相關的,對應於該平台在定義快捷鍵時最常用的輔助按鍵。(譯者注:在Windows平台下對應於Ctrl)
如果設置了這個特性,那麼處理程序將會被限定只有在輔助按鍵按下的時候才被觸發。你可以同時設置多個輔助按鍵,按鍵之間使用空格分隔。
如果事件處理程序內的代碼很多,可以使用下面的語法替代action特性:
<binding id="binding-name">
<handlers>
<handler event="event-name">
-- handler code goes here --
</handler>
</handlers>
</binding>
實例
在下面的例子中,我們會通過增加幾個鍵盤事件處理程序來實現一個本地剪貼板的原型:
實例 11.6.1:源代碼
<binding id="clipbox">
<content>
<xul:textbox/>
</content>
<implementation>
<fIEld name="clipboard"/>
</implementation>
<handlers>
<handler event="keypress" key="x" modifIErs="control"
action="this.clipboard=document.getAnonymousNodes(this)[0].value; document.getAnonymousNodes(this)[0].value='';"/>
<handler event="keypress" key="c" modifIErs="control"
action="this.clipboard=document.getAnonymousNodes(this)[0].value;"/>
<handler event="keypress" key="v" modifIErs="control"
action="document.getAnonymousNodes(this)[0].value=this.clipboard ? this.clipboard : '';"/>
</handlers>
</binding>
匿名名內容裡面只有一個文本框,而clipboard字段則用來儲存保存在剪貼板裡的內容。這意味著剪貼板的所有操作都將局限在這一個文本框中,但確實每個文本框有自己的緩存,可以保存自己的內容。
在這個例子中添加了三個事件處理程序,一個用於剪切,一個用於復制,另外一個用於粘貼。每一個事件處理程序都對應自己的快捷鍵。第一個事件處理程序 對應於剪切操作,會在Ctrl和x同時按下的時候激活,此時action特性裡面的腳本將會被執行,把文本框的內容刪除,並把原來的內容保存在 clipboard字段中。為簡單起見,這裡操作的是文本框內的全部內容,而不是選中的部分。代碼具體執行的步驟如下所示:
this.clipboard = document.getAnonymousNodes(this)[0].value;
通過textbox元素獲得的匿名內容數組的第一項,也就是匿名元素中的第一項(也是唯一一項),他的value屬性對應於textbox內顯示的內容。這個內容被賦給了clipboard字段,這樣就達到了把文本框的內容復制到特定剪貼板的效果。
document.getAnonymousNodes(this)[0].value = '';
文本框內的文本被設置為空串,等同於清空文本框內的文本。
復制操作和剪切操作類似,但是不會清空文本框內的文本。粘貼操作正好相反,是把clipboard字段裡的值賦給textbox的value。如果我們建立一個完整的剪貼板實現,會使用真實的剪貼板接口,當然也不會一鍋端,而只是處理選擇部分的文本。
在下一節,我們將學習如果擴展已有的XBL定義。