Vincent.Chan‘s Blog

          常用鏈接

          統計

          積分與排名

          網站

          最新評論

          XML 事件簡介::用較少的腳本編寫動態文檔

          級別: 初級

          Micah Dubinko, 首席顧問, Brain Attic, L.L.C.

          2004 年 12 月 01 日

          一 些標記技術涉及到為文檔的某些部分附加上行為。XML Events 是 W3C 推薦的一種標準,它允許通過聲明為特定的元素附加行為,這種行為可以是 XML 中預先定義的一組動作,也可以是更一般的腳本語言調用。本文將簡要地介紹 XML Events 的由來、用途以及其工作方式。

          現代的網站是高度交互的:動態的導航菜單、圖像切換、表單,甚至還支持拖拉操作。這類網站的一個共同因素是通過某種技術將行為與文檔的特定部分聯系起來。不幸的是,當前的實踐因為嚴重依賴腳本而造成了混亂,特別是那些需要適應多種瀏覽器的代碼。

          兩種類型的事件

          清單 1 列出了一些可能的變體。它定義了兩個事件處理程序,一個用于 load 事件,另一個用于 unload 事件。一個處理程序是用 VBScript 編寫的,通過一種不常見的技術附加到元素上,并用到了 script 元素的額外屬性。另一個則是用 ECMAscript(請參閱 參考資料)編寫的。


          清單 1. 兩種類型的事件
          												
          														
          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
          "http://www.w3.org/TR/html4/loose.dtd">
          <html>
          <head>
          <title>Intrinsic Events</title>
          <script event="onload" for="window" language="vbscript">
          <!--
          alert "hello"
          -->
          </script>
          </head>
          <body onunload="alert('goodbye')">
          </body>
          </html>

          如果使用 Microsoft Internet Explorer 或者其他支持 VBScript 的瀏覽器查看,在加載文檔的時候,就會出現一個顯示“hello”的警告框。基本上所有的瀏覽器在關閉窗口或者導航到其他頁面時都會顯示 “goodbye”。要完整地描述這到底是怎么發生的,就需要了解 DOM Events,該標準目前由 Document Object Model (DOM) Level 2 Events Specification(請參閱 參考資料)授權的 W3C 文檔指定。





          回頁首


          事件的工作原理

          事件到底是什么呢?對于本文而言,最好不要從“事件”一詞的傳統含義上思考,而應將其看作一種數據結構,包含變化的某些事物的詳細信息。比方說,在 mouseover 事件中,我們所關心的事件對象的信息是鼠標指針的坐標、按下了哪個鍵、當前是否按下了修飾鍵如“shift”等等。單個事件對象的存活期非常短,在其消失之前剛夠時間進行即時處理。

          每個事件都有一個 目標,XML 或 HTML 元素和事件的關系最密切。事件 處理程序是對應特定事件的一段可執行代碼或者標記。某些事件和其他處理程序不同,比如單擊一個超鏈接,會引發稱為 默認動作的活動。 清單 1unload 事件的目標是 body 元素,事件處理程序 onunload 屬性中為數不多的那一點腳本。

          事件流

          最簡單、最常用的技術是直接將事件處理程序附加到目標上,過去,瀏覽器只支持這種技術。但是,這樣做常常行不通,比如清單 2 中的例子:


          清單 2. 論證是否需要事件觀測者
          												
          														
          <p>You want to capture all clicks on this paragraph,
          even if the text has <em>special markup</em>.</p>

          清單 2 中,假設對目標為 p 元素的 click 事件有一個處理程序。如果用戶恰好單擊“special markup”這兩個詞,則會創建目標為 em 元素的一個事件。因為目標不是段落,單擊事件處理程序就不會被觸發。解決這個問題的方法是在 p 元素上放一個 observer 事件,它能夠對以該元素自身或者 它的所有子元素為目標的事件作出響應。

          DOM Level 2 Events 描述了如何連接事件處理程序,以解決 清單 2 中所示的問題,盡管由于瀏覽器的歷史原因,這種方法可能有點過于復雜(Internet Explorer 和 Netscape 的早期版本各有自己的特點,其中一些要比正式的 DOM 規范早得多)。事件按照文檔的樹狀結構進行假想的旅行,這個過程稱為 傳播。實際上它的旅行有兩次:第一次旅行稱為 捕獲,從文檔根開始,前進到目標元素。進行常規的目標處理后,第二次旅行稱為 冒泡(bubbling),從目標元素開始,再回到文檔根。每個階段中,路徑中的任何元素都可以注冊為事件觀測者,從而能夠觸發事件處理程序。然后事件將停止傳播,避免后面的觀測者再檢測到發生的事件。圖 1 說明了傳播的過程。

          事件和可訪問性

          無論何時考慮事件,都需要判斷您到底需要哪種事件。比方說,確實關心按鈕是否被鼠標單擊嗎?如果用其他某種方式激活又怎么樣?一些 Web 用戶沒有鼠標,甚至都沒有這樣的圖形用戶界面。更好的辦法是盡量使用設備無關的事件,比如用 DOMActivate 代替按鈕的 click 事件。

          W3C 發布的一些文檔(請參閱 參考資料)描述了增強 Web 內容訪問性的技術。


          圖 1. 事件的傳播
          一個樹狀結構,包括根、 <html>、<body>、<p> 和 <em>。標記為“capture”的箭頭從根開始直到 <em>,后者標記為“target”。從目標回溯到根的箭頭標記為“bubble”。<p> 元素標記為“observer”。

          如果需要設置事件觀測者,應該使用捕獲階段還是冒泡階段呢?下面是一些指導原則:

          • 如果處理單個觀測點 —— 這也是最常見的情況,使用哪個階段都行,兩者沒有實際區別。只有需要從文檔樹中的多個位置觀測一個事件時才會造成區別。
          • 某些事件(如 focus)不參與冒泡階段,因此只能在捕獲階段觀測,或者直接在目標上觀測。
          • 當存在多個觀測者時,如果希望首先觸發最近的觀測者則使用冒泡階段。比如,假設在 圖 1 中, bodyp 上都有觀測者。捕獲的時候 body 上的觀測者將首先被觸發,然后再激活 p 上的觀測者。而冒泡階段,將首先激活 p 上的觀測者,然后才是 body 上的觀測者。
          • 要記住,對于 清單 1onunload 所用的 HTML 4.0 風格的語法,觀測者被注冊到冒泡階段。
          • 無論使用冒泡階段還是捕獲階段,默認動作總是在所有的傳播完成后執行。停止事件傳播本身不會禁止默認動作的執行。一個單獨的 API 特性允許取消默認動作,無論傳播過程中發生什么事。

          DOM Events 規范定義了從腳本中附加事件觀測者的方法,如清單 3 所示。


          清單 3. 附加事件觀測者
          												
          														
          var el = document.getElementById('observer_element_id');
          el.addEventListener("mouseover", highlight_func, true);
          el.addEventListener("mouseout", normal_func, true);

          addEventListener 調用中的第一個參數是事件名,第二個參數是要執行的函數引用,第三個參數是 true(表示在捕獲階段)或者 false(表示在冒泡階段)。DOM Events 規范定義了一些核心事件,以及停止事件傳播和取消關聯的默認動作的 API 方法。

          需要注意的是,這些 API 的不同瀏覽器的實現有很大的不同。具體地說,Internet Explorer 直到 6.0 版還不支持 addEventListener,但它使用了名為 attachEvent 的一個類似函數。





          回頁首


          從事件到 XML Events

          到目前為止,所有和事件有關的一切都和過程性腳本聯系在一起。XML Events 規范在 DOM Level 2 Events 的基礎上,增加了連接事件觀測者的聲明性方法。W3C XForms 規范(請參閱 參考資料)是率先定義兼容 XML Events 的元素庫的標準之一,該元素庫可以通過聲明完成一般性的任務。清單 4 給出了 XForms 中的一個例子。(關于其中使用的完整名稱空間聲明,請參考 清單 5 中的完整例子。)


          清單 4. 聲明性事件處理程序
          												
          														
          <xf:trigger>
          <xf:label>Reset the form</xf:label>
          <xf:reset ev:event="DOMActivate" model="mymodel" />
          </xf:trigger>

          XML Events 被定義成一些屬性。 清單 4 中的 ev:event 屬性規定了要監聽的特定事件,處理程序是 xf:reset 元素,觀測者被默認為父元素 xf:trigger。注意,該清單中根本沒有腳本。

          XML Events 規范主要由可以放置在現有元素中的屬性定義組成,還有一個 listener 元素用來容納這些屬性。每個屬性都映射為 DOM Level 2 事件的一個特性。表 1 列出了所有的 XML Events 屬性。

          表 1. XML Events 屬性

          屬性 功能
          event 清單 4 所示,這個必需的屬性用于命名觸發監聽者的事件
          observer 該屬性指向作為觀測者的元素的惟一 ID
          handler 該屬性指向執行某種動作或處理的元素的 URI,該元素可能在不同的文檔中
          phase capturedefault,該屬性規定使用捕獲階段
          propagate stopcontinue(默認值),該屬性規定事件是否繼續傳播
          defaultAction cancelperform(默認值),該屬性規定傳播后是否激活默認動作
          target 該屬性要求監聽者 對指向特定目標的事件作出響應,并且僅在特殊情況下使用
          id 該屬性為 listener 元素賦予文檔中惟一的標識符

          簡便的默認值

          清單 4 說明了用最少的屬性使用 XML Events 的便捷方法:XML Events 屬性直接附加到處理程序元素上。如果省略 ev:handler 屬性,擁有 XML Events 屬性的元素就被看作是處理程序。觀測者可以通過 ev:observer 屬性指定,或者默認為父元素。在 清單 4 中,觀測者為 xf:trigger

          另一種類型的默認允許將 XML Events 屬性附加到觀測者元素上,這種情況下沒有 ev:observer 屬性,但是出現了 ev:handler 屬性。

          清單 5 重新創建了 清單 1 中的行為,顯示了這兩種默認技術,并使用了腳本和聲明性動作。


          清單 5. 使用 XML Events 的兩種方法
          												
          														
          <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
          <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
          xmlns:ev="http://www.w3.org/2001/xml-events"
          xmlns:xf="http://www.w3.org/2002/xforms">
          <head>
          <title>XML Events</title>
          <script type="text/javascript" ev:event="load" ev:observer="bod_id">
          alert("hello");
          </script>
          <xf:message level="modal" id="hndl_id">goodbye</xf:message>
          </head>
          <body id="bod_id" ev:event="unload" ev:handler="#hndl_id">
          </body>
          </html>

          這里的 script 元素是一個處理程序,被附加到 bod_id 上的一個觀測者( body 元素)。 xf:message 元素本身什么也不做,但觀測者元素(還是 body)又指向了它,注冊了事件處理程序。





          回頁首


          結束語

          腳 本顯然在很多方面都很有用。盡管如此,它仍然難以通過腳本完成某些任務。XML Events 為通過聲明將腳本附加到文檔中提供了統一的語法,甚至能夠定義不依賴于腳本解釋器的行為。現在有越來越多的標記技術開始采用 XML Events,其中包括 XForms、XHTML、SVG 等。在以后的文章中,我將詳細探討如何使用和實現 XML Events。





          回頁首


          參考資料





          回頁首


          關于作者

          Micah Dubinko 的照片

          Micah Dubinko 是 Brain Attic, L.L.C. 的顧問和締造者之一,這是一家專門應對信息過載的軟件供應商和咨詢公司。他為 O'Reilly Media 撰寫了 XForms Essentials 一書,并參加了開發 XForms 1.0 的工作組。他在亞利桑那州菲尼克斯定居和工作,您可以通過 micah@brainattic.info 與他聯系。

          posted on 2006-03-18 21:28 Vincent.Chen 閱讀(358) 評論(0)  編輯  收藏 所屬分類: AJAX

          主站蜘蛛池模板: 鹤岗市| 青河县| 德阳市| 北京市| 突泉县| 溧水县| 玛曲县| 清镇市| 称多县| 永年县| 红原县| 玉林市| 于田县| 祥云县| 南溪县| 东兴市| 广饶县| 正镶白旗| 东方市| 宁德市| 辽源市| 和田县| 邻水| 苏尼特左旗| 读书| 遂平县| 南汇区| 天祝| 万年县| 北辰区| 遂宁市| 科技| 林州市| 惠水县| 迁西县| 东港市| 逊克县| 铜鼓县| 桓台县| 英山县| 宝丰县|