為Lotus Connections Home page實現和部署Google小部件

genusBIT發表於2009-10-29

原文連結:http://www.ibm.com/developerworks/cn/lotus/connections-gadgets/index.html?ca=drs-cn-1027

本文介紹由 IBM® 開發並可用於各種 IBM 產品(比如 IBM Lotus® Connections 2.0)的 iWidget 規範。本文通過一個實用的例子描述該規範的各個方面,展示如何實現一個能夠用作 Google 小部件的 iWidget。

注意:本文討論 Lotus Connections 2.0。您可以參考 developerWorks 文章 “Customizing Lotus Connections 2.5 with Lotus Widget Factory and Google Gadgets” 的第二部分,瞭解在 Lotus Connections 2.5 中部署 Google 小部件的步驟。本文的程式設計細節仍然是可用的,並且為希望瞭解 iWidget 規範的開發人員提供一個不錯的起點。

Lotus Connections 2.0 包含一個新的、高度可定製和可擴充套件的 Home page,它使使用者能夠通過一個統一的檢視檢視來源不同的資訊。這個 Home page 特性基於小部件,並允許您輕鬆地擴充套件 Lotus Connections 社交軟體平臺。

Lotus 軟體試用下載

立即下載最新版本的 IBM Lotus 試用軟體,輕鬆體驗產品的最新特性!

Home page 特性允許您實現和新增自己的小部件。iWidget 是 IBM 為小部件定義的新定義。iWidget 規範 定義小部件的結構。iWidget 標準不侷限於 Lotus Connections,它可用於其他產品(比如 IBM Mashup Center 的 Lotus Mashups),因此您只需要編寫小部件一次就可以在不同的產品中執行它。

本文概述了建立和部署基礎的 iWidget 並在 Home page 中執行它涉及到的步驟。本文展示如何將 Google 小部件包裝到 iWidget 中。在閱讀了本文之後,您應該能夠建立可以向使用者顯示任何內容的基礎小部件。

本文的前兩個小節介紹與 iWidget 和 Google 小部件相關的必要理論知識。第 3 小節將逐步指導您實現一個能夠用作基礎的 Google 小部件包裝器的 iWidget。最後,本文將深入討論如何為 Google 小部件包裝器新增改進。

建立和部署基礎小部件的步驟非常簡單。本文假設您熟悉最常見的 Web 開發技術,比如 JavaScript™、Java™ Platform, Enterprise Edition 和 XML。對以上技術有中等程度的瞭解即可,因為對於不常見的領域,比如 JavaScript. Dojo Toolkit 的使用,本文將適時提供相關的介紹。

Home page 小部件和 iWidget 規範概述

本小節概述了 IBM iWidget 規範,併為理解後文的實現部分提供必要的理論知識。本文不會過於深入地研究該規範描述的某些特性。

Home page 小部件剖析

在討論技術細節之前,我們先分析 Home page 小部件。Home page 小部件可以分為兩部分:

  • 頭部(Header)。包含小部件的標題和一些通過圖示表示的操作按鈕(移動、編輯、重新整理、幫助和關閉)。
  • 主體(Body)。圖 1 中紅色矩形包圍的部分,主體是向使用者顯示 iWidget 的地方。


圖 1. Home page 小部件的結構
Home page 小部件的結構

小部件開發人員幾乎能夠完全控制在 Home page 小部件的主體部分顯示的內容。小部件可以顯示任何標準 Web 頁面的內容。唯一的限制是必需遵循在 iWidget 規範中定義的元件模型。

Home page 執行時自動生成頭部欄。您僅能對頭部欄進行有限的定製。您可以定義哪個操作受 iWidget 的支援。Home page 自動隱藏嵌入的 iWidget 不支援的操作圖示。管理員在部署時定義小部件的標題。

iWidget 描述器

描述器是 iWidget 的核心部分,必須從這裡宣告小部件支援的各種功能。可以用兩種不同的風格編寫 iWidget 描述器:microformat 或 XML 語法。因為 Lotus Connections Home page 僅支援 XML 定義風格,所以本文不介紹 microformat 語法。清單 1 顯示了一個示例 Hello World iWidget XML 描述器。


清單 1. Hello World iWidget XML 描述器


   			
   
      
            Hello World! 
]]>

這個小部件顯示字串 “Hello World” 和一個按鈕,如圖 2 所示。


圖 2. Hello World 小部件
Hello World 小部件

例子的中的 XML 描述器的重要部分是:

  • iScope 屬性。這個屬性指定包含 iWidget 的邏輯的類的名稱。它通常是在 XML 描述器中宣告的資源之一中定義的 JavaScript. 類。iWidget 框架為每個 iWidget 例項例項化一個 iScope 物件。
  • iw:resource 標記。這些標記指向 iWidget 需要的不同資源。Home page 支援 JavaScript. 和層疊樣式表(CSS)資源。將獲取和計算在 XML 描述器中宣告的每個資源。名為 “uri”(Uniform. Resource Identifier)的屬性與 XML 描述器的位置有關。在這個例子中,我們僅宣告瞭一個資源,它是應該名為 helloworld.js 的 JavaScript. 檔案,所在的目錄與 XML 描述器 file.iw:content 標記相同。這些標記定義特定模式的標記。標記片段是當 iWidget 顯示特定模式時 Home page 為其呈現的 HTML 程式碼。這個例子中的小部件僅有一個模式 view(檢視),它是預設的模式。

清單 2 顯示了來自 helloworld.js 檔案的程式碼,這些程式碼定義 iScope 類 HelloWorldWidgetClass。這個類僅定義一個方法 onClickButton,該方法是與在清單 1 中定義的按鈕的 onclick 事件相關聯的處理函式。當使用者單擊按鈕時,一個視窗將顯示字串 “Button clicked”。

Dojo 語法

JavaScript. 是基於原型的語言。為了給習慣物件導向程式設計的開發人員提供便利,Dojo Toolkit 提供了一些物件導向的類幫助程式(helper)。這個例子在宣告沒有繼承任何父類(null)並有一個方法(onClickButton)的 HelloWorldWidgetClass 時使用了 dojo.declare 方法。


清單 2. helloworld.js 的內容
dojo.provide("HelloWorldWidgetClass");

dojo.declare(
   /* class name */                                            
   "HelloWorldWidgetClass",  
   /* parent class */ 
    null,
   /* methods and variables */ 
   {	
      onClickButton: function(){
         alert("Button clicked");
      }
   }
}

使用 iWidget 框架提供的服務

iContext 物件是用於與 iWidget 框架提供的服務互動的中心點。iWidget 框架自動將一個名為 iContext 的物件插入到您的小部件的 iScope 類,並將其作為一個成員 (this.iContext)。您可以通過 iContext 物件利用 iWidget 框架的功能。

另外,可以在小部件的 HTML 標記中使用 iContext 物件來以封裝的方式呼叫 iScope 類的相關例項的方法。清單 1 的例子使用這種技術呼叫 onClickButton 方法。

封裝和 iContext

封裝是 iWidget 規範的重要部分。每個 iWidget 都需要進行封裝,以避免同時在相同的頁面上開啟的幾個小部件宣告的資源之間發生衝突。iWidget 框架幫助您封裝小部件,但您也需要完成一些工作。iWidget 開發人員尤其需要:

  • 正確宣告 iWidget 類 (iScope) 的作用域,如本文的 “iWidget 描述器” 小節所述。iWidget 要使用的任何方法或變數都必須在 iScope 中宣告。
  • 要避免在 iWidget 資源中使用全域性 JavaScript. 函式和變數,因為您不能保證該頁面上的其他小部件沒有宣告同名的物件,如果存在同名物件將導致衝突。
  • 通過 iContext 物件與 iWidget 框架互動以獲取作用域合適的物件。在 Hello World 例子中,您通過 iContext.iScope() 語句來實現該目的。

ItemSets

ItemSet 是一組由 iWidget 框架管理的名-值對。它們通常用於儲存 iWidget 的屬性。ItemSet 通過 iScope 類中的方法進行操作,比如 getItemValue 和 getAllNames(要了解更多資訊,請參考 iWidget 規範)。ItemSet 可以在 XML 描述器中宣告,如清單 3 所示。


清單 3. ItemSet 宣告


   
   


本文的最後一個小節 “進一步改進小部件包裝器” 提供了一個具體的例子,闡述如何使用 ItemSet 儲存您在本文中實現的 Google 小部件包裝器的首選項。

iWidget 框架提供的其他服務

這個小節描述 iWidget 規範定義的其他服務。我們的 Google 小部件包裝器僅使用了這些服務的一部分。iWidget 規範提供的功能包括:

  • 事件系統。這個系統允許 iWidget 觸發和捕捉事件。在 Home page 中,這個機制用於在使用者選擇頭部欄的操作(比如編輯和重新整理)時對 iWidget 觸發事件。
  • IO 模組。由於 JavaScript. 實施同源安全策略(要了解細節,請訪問 http://www.mozilla.org/projects/security/components/same-origin.html),所以不能對預設的 Home page 之外的其他域觸發 Ajax 請求。為了提供將請求傳送到其他域的能力,Home page 附帶了一個 Ajax 代理。可以使用指定的 IO 模組重寫任何 URL,從而通過內建的 Home page Ajax 代理重新路由 Ajax 請求。此外,還可以用它查詢與 XML 描述器的位置相關的資源。
  • 連線系統。使用者可以配置兩個以上的小部件,並使用剛才提到的事件系統在它們之間交換資料。注意,這個特性在 Lotus Connections Home page 中不可用,但在 Lotus Mashups 中可用。

    Google 小部件概述

    Google 小部件是由 XML、HTML 和 JavaScript. 組成的輕量級應用程式。可以將 Google 小部件新增到 Gadget 容器,比如 iGoogle(Google 的可定製主頁)、Orkut/Google Maps 或 Google Desktop。任何人都可以開發小部件。Google 提供一個 公共目錄,您可以通過它釋出您的小部件。

    就像 iWidget 一樣,Google 小部件的核心部分包含在它的 XML 定義檔案中。您可以在 開發人員的官方指南 的 “編寫自己的小部件” 小節找到關於小部件 XML 描述器的細節。總而言之,小部件的 XML 定義指定兩個主要方面:小部件的標記(HTML 程式碼)和一組首選項。

    注意,目前有兩個不同的 Google 小部件 API。本文使用 Google 支援聯合小部件的遺留 API。

    向任意 Web 站點新增 Google 小部件

    Google 提供在任意 Web 站點上執行小部件的功能,這種功能稱為聯合(syndication)。您可以利用該功能建立允許您在 Lotus Connections Home page 中顯示 Google 小部件的包裝器。

    • 為了讓您能夠在小部件容器之外執行小部件,Google 提供這樣一個 Web 服務:它返回由 JavaScript. 和 HTML(負責發起並呈現小部件的依賴項)組成的格式化輸出。該服務包含幾個請求屬性,尤其是:指向 Google 小部件 XML 定義檔案的 URL。
    • 在小部件的 XML 描述器中定義的使用者首選項(可以通過傳遞首選項的名稱分配一個值)前面有一個 _up,作為服務的請求引數。傳遞的使用者首選項值覆蓋在 Google 小部件的 XML 定義中指定的預設值。
    • 顯示首選項,比如標題、寬度、高度和邊框樣式。

    Google 服務的基 URL 為字串 http://www.gmodule.com/ig/ifr。現在提供一個完整的 URL 例子,它包含為 Date Time Google 小部件返回 JavaScript. 程式碼的 Google 服務的請求屬性:

    http://www.gmodules.com/ig/ifr?url=http://www.google.com/ig/modules/
    datetime.xml&up_color=blue&up_firstDay=0&
    w=320&h=136&output=js

    在該例子中,注意以下引數:

    • 提供諮詢 Date Time 小部件的 XML 描述器的 URL:字串 http://www.google.com/ig/modules/datetime.xml。
    • Color 和 firstDay 使用者首選項(特定於該小部件)被設定為 blue 和 0(Sunday)。
    • Width (w) 和 height (h) 顯示引數被設定為 320 px 和 136 px。

    儘管您可以為 Web 服務手動建立 URL 以包含所需的請求引數,但使用 Google 提供的 Page Creator 工具是一項最佳實踐。這個工具能以可視的方式快速構造 URL。該工具允許您為小部件的首選項指定值以及為服務生成 URL,包括在小部件的 XML 定義中定義的不同首選項的正確請求引數。要使用 Page Creator 工具,請遵循以下步驟:

    1. 訪問 Google 小部件庫
    2. 選擇一個小部件,然後選擇 Add to your webpage 選項。定製該小部件的設定和使用者首選項的值。頁面顯示使用新值的小部件的預覽圖。
    3. 完成這些設定之後,選擇 Get the code 選項。
    4. 該頁面顯示需要包含的程式碼。指向 Web 服務的 URL 為指令碼標記的 src 屬性中的字串。

    注意:您可能已經發現,Page Creator 返回的 URL 對一些特殊字元進行了強制型別轉義。例如和號 (&) 字元被轉義成 &。因為 URL 將儲存在 HTML 或 XML 文件中,必須對特殊字元進行轉義以確保文件有效。

    在 iWidget 描述器中包裝 Google 小部件

    現在,您已經準備好為 Date Time Google 小部件編寫包裝器。圖 3 顯示了在 Home page 部署該小部件之後的結果。


    圖 3. 在 Home page 中部署的 Google Date Time 小部件
    在 Home page 中部署的 Google Date Time 小部件

    在這個小節中公開的方法適用於任何其他 Google 小部件,僅需一行幫助指向適當小部件的程式碼。

    作為第一種方法,您的包裝器非常基礎:它的唯一目的是在 Home page 中呈現小部件。本文的最後小節主要關注向該包裝器新增功能,比如使用者可以通過它修改小部件首選項值的編輯檢視。

    呈現小部件和 XML 描述器的方法

    IFRAME

    IFRAME. 是一個包含另一個文件的內聯框架。它是一個標準的 HTML 元素,並且與 iWidget 規範沒有特定的關係。IFRAME. 的 src 屬性指向將載入的文件的 URL。

    要在 Home page 中呈現 Google 小部件,使用適當的請求引數呼叫在 “向任意 Web 站點新增 Google 小部件” 小節討論的 Google Web 服務。呼叫的響應(包含 HTML 和 JavaScript)插入在一個指令碼元素中。Script. 元素位於 iWidget 的 IFRAME. 部分的 HTML 文件中。

    清單 4 顯示了 iWidget 的 XML 描述器的程式碼骨架。清單 5 包含 JSP 文件 (gadgetWrapper.jsp) 的一部分,其中的指令碼元素指向 Google 服務。


    清單 4. 針對 Google 小部件的 iWidget 包裝器定義

    
       
       ">
          
       ]]> 
            
    
    


    清單 5. gadgetWrapper.jsp
    
    
    

    如您所見,iWidget 呈現指向 gadgetWrapper JSP 頁面的 IFRAME. HTML 元素。JSP 頁面負責以下任務:

    • 獲取 URL 的查詢字串部分。即 URL 中字元 ? 之後的子字串。在這個例子中,/gadgetWrapper/gadgetWrapper.jsp?url= 的查詢字串部分為 url=
    • 通過將查詢字串附加到 gmodule.com 上的服務的上下文根構建指向 Google 服務的 URL。
    • 將指令碼元素的 src 屬性設定為指向包含來自查詢字串的適當小部件引數的 Google 服務。

    如果您不使用 Java,那麼可以根據您選擇的語言(比如 PHP 或 .NET)調整 JSP 頁面的行為。最重要的部分就是使用指向 Google 服務的 URL 設定指令碼元素。

    在這點上,要注意 3 個方面:

    • 我們本來可以將指令碼元素直接插入到 iWidget 程式碼的 XML 定義中。但是,Google 服務返回的 JavaScript. 程式碼之間的衝突迫使我們選擇將指令碼標記隔離在 IFRAME. 元素中。
    • Google 服務的輸出請求引數接受 html 值(而不是 js)。這導致可以將生成的 HTML 程式碼直接插入到 IFRAME. 中(見清單 4),而不需要使用 JSP 解決方案。但是,這個解決方案沒有在 Google 小部件下方包含 “gadget powered by Google” 和 “+Google” 按鈕,這違反了 Google 小部件服務條款
    • 這個 iWidget 沒有任何支援邏輯。因此,XML 定義不包含任何到 iScope 或 JavaScript. 資源的引用。在本文的最後小節,您將為 iWidget 新增一些邏輯。

    Google Date Time 小部件

    清單 6 顯示了針對包裝瞭如圖 3 所示的 Date Time Google 小部件的 iWidget 的 XML 描述器程式碼。IFRAME. 元素的 src 屬性指向這個位於 http://www.google.com/ig/modules/datetime.xml 的小部件的 XML 描述器的 URL。它還設定了特定於該小部件的使用者引數,比如背景顏色(橙色)和每週的第一天(0 表示 Sunday)。如前所述,您可以通過檢查小部件的 XML 定義找到哪些使用者引數可用於特定的小部件,或者使用 Google Page Creator 工具完成該任務。


    清單 6. 針對 Google Date Time 小部件的 iWidget 包裝器定義

    
       
       
            ]]> 
         
    
    

    要將您選擇的 Google 小部件的 URL 插入到 IFRAME. 的 src 屬性(source),請遵循 “向任意 Web 站點新增 Google 小部件” 小節描述的步驟。在這點上,您將使用者首選項硬編碼為 URL 請求字串的一部分。在本文最後一個小節中,您將修改該程式碼以讓使用者能夠更改首選項。

    注意:在清單 6 中,我們還將兩個顯示引數(title 和 border)設定為空值。該設定允許您呈現沒有標題和任何邊框樣式的 Google 小部件。

    在 Home page 中部署 Google 小部件

    將 iWidget 部署到 Home page 有兩個主要步驟:

    1. 將 XML 描述器和 iWidget 的所有資源部署到 Web 伺服器。
    2. 在 Home page 目錄中註冊小部件,具體操作是指向已部署的 iWidget XML 描述器的 URL。

    部署 iWidget

    將 iWidget 部署到 Web 伺服器的方式非常靈活,因為您不侷限於特定的伺服器技術。例如,您的 iWidget 可以是一個部署到 PHP 伺服器的 PHP 專案。您還可以將小部件實現為 Java Platform, Enterprise Edition 專案,並將其部署到 servlet/Java Platform, Enterprise Edition 容器中,比如 WebSphere® Application Server 或 Tomcat。您可以自行選擇。注意,如果您沒有使用 Java Platform, Enterprise Edition 容器,那麼必須調整在 “呈現小部件和 XML 描述器” 小節中描述的 JSP 頁面。

    下面的步驟詳細闡述了在 Eclipse 中將 iWidget 建立為一個 Web 專案並將其作為 EAR 檔案匯出的流程。然後可以將 EAR 檔案部署到 Java Platform, Enterprise Edition 容器。

    注意:您必須安裝 Web 工具外掛才能在 Eclipse 中建立 Web 專案。您可以從 http://download.eclipse.org/webtools/downloads/ 下載該外掛。Java Platform, Enterprise Edition 版本的 Eclipse 包含該外掛。

    讓我們建立專案並準備部署 EAR 檔案。在 Eclipse 中,首先建立一個專案:

    1. 轉到 File - New - Project。
    2. 在視窗中選擇 Web - Dynamic Web Project,然後單擊 Next。
    3. 輸入任意的專案名,比如 gadgetWrapper。如果您想要直接從 Eclipse 部署專案,那麼選擇一個目標執行時;否則,選擇 None。
    4. 選擇 Add Project to an EAR 選項告訴 Eclipse 為這個 Web Project 建立一個 EAR 專案,並將它們關聯起來。
    5. 選擇 Next 獲得最新的視窗。不要修改任何預設設定。單擊 Finish 建立 Web 專案。

    至此,您已經準備好處理該專案。

    接下來,將 iWidget XML 描述器新增到專案中:

    1. 在 WebContent 下,通過右鍵單擊目錄名並選擇 New - File 建立一個新的 XML 檔案。輸入 gadgetWrapper.xml 作為檔名。
    2. 在 Eclipse 中雙擊該檔案開啟它,然後將清單 6 中的程式碼複製貼上到其中。如果您不能編輯該檔案,那麼檢查是否選擇了 source 選項卡。見圖 4。
    3. 儲存檔案。


    圖 4. 在 Eclipse 中編輯的 gadgetWrapper.xml 檔案
    在 Eclipse 中編輯的 gadgetWrapper.xml 檔案

    要將在清單 5 中定義的 JSP 新增到專案,重複新增 XML 描述器的步驟。您可以在本文的下載小節中的 gadgetWrapper.ear 中找到該檔案的完整本版。

    接下來,生成部署到 Java Platform, Enterprise Edition 容器(比如 WebSphere Application Server)的 EAR 檔案:

    1. 選擇與先前建立的 Web 專案相關聯的 EAR 專案。
    2. 右鍵單擊並選擇 Export - EAR file。
    3. 在磁碟上選擇一個目標位置。

    就這麼簡單!包含 iWidget 資源和 XML 檔案的 EAR 檔案已經就緒,可以將其部署到任何 Java Platform, Enterprise Edition 容器中了。

    至此,您可以將 EAR 檔案部署到 Java Platform, Enterprise Edition 容器中,就像部署其他 EAR 檔案一樣。

    注意:清單 6 中顯示的 IFRAME. 有一個對上下文根設定為 /gadgetWrapper 的 JSP 頁面(見清單 5)的引用。您必須根據 EAR 檔案部署到的實際上下文根調整該設定。在本文的最後一個小節中,我們將展示如何使用 iWidget IO 模組解決該限制。

    在 Home page 目錄中註冊小部件

    Home page 提供一個管理使用者介面,用於向目錄資料庫新增新的小部件。注意,只有具有管理員特權的使用者能夠向 Home page 目錄新增小部件。

    遵循以下步驟,使用 Home page Web 管理使用者介面新增我們的 iWidget:

    1. 使用管理員帳戶登入 Home page。
    2. 在 Home page 中選擇 Administration 選項卡,如圖 5 所示。

      圖 5. Administration 選項卡
      Administration 選項卡

    3. 在頁面的右下角選擇 Add another widget 選項。
    4. 將顯示如圖 6 所示的表單。輸入標題名和 iWidget 的 XML 描述器的位置。

      圖 6. Administrators Home page
      Administrators Home page

    5. 輸入小部件的標題。您輸入的標題將顯示在小部件的標題欄中;例如,標題可以是 Google Date Time。
    6. 輸入 XML 描述器的位置。這個欄位取決於您在 “部署 iWidget” 小節中部署小部件的位置。
    7. 其他文字欄位是可選的,可以留空。例如,您可以指向一個圖示。當小部件關閉之後,該圖示將顯示在側欄中。
    8. 不要勾選任何核取方塊。僅當小部件與其他 Lotus Connections 特性互動時才使用它們。包裝 Google 小部件的 iWidget 不需要使用這些選項。
    9. 單擊 Save。

    您可以在 Lotus Connections v2 Information Center 中更多地瞭解管理小部件的管理選項。

    進一步改進小部件包裝器

    這個小節描述如何為基礎的 iWidget 新增更多功能。尤其是,您可以新增這樣一個功能,讓使用者可以修改在 Google 小部件定義中宣告的一部分首選項。注意,使用者首選項由 Google 小部件本身處理,因為它們在 Google 小部件的 XML 定義中被宣告為 元素。我們的目標是讓使用者為這些首選項選擇值,並將它們傳遞到 Google 服務。

    要讓使用者能夠定製已包裝的 Google 小部件,需要:

    1. 為小部件實現一個編輯檢視,使用者可以通過該檢視定製在 Google 小部件定義中宣告的首選項值。
    2. 將輸入的值傳遞到 Google 服務,該服務是在前面的 “向任意 Web 站點新增 Google 小部件” 小節中引入的。為此,將新的首選項值作為 URL 的一部分傳遞給 Google 服務。

    通過這些步驟,您還可以看到使用本文介紹的幾個概念的實用例子,比如 ItemSet、iWidget 框架提供的封裝機制和事件系統。

    Date Time 小部件首選項

    在這個小節,我們將通過修改現有的 iWidget 以讓使用者為 Google Date Time 小部件設定首選項。注意,以下的步驟對所有 Google 小部件都是一樣的;所以,很容易調整這裡的概念並應用到 Home page 的其他小部件的定製過程中。

    通常,可以通過兩種方式獲取 Google 小部件的使用者首選項列表:

    • 可以檢視小部件的 XML 描述器,並找到 元素。
    • 可以使用 Page Creator 工具。首選項列出在 Gadget 設定部分下面。

    通過檢視 Date Time 小部件的 XML 定義,您可以看到有兩個使用者首選項:

    • 背景顏色
    • 日曆中的每週的第一天

    這兩個引數有一個以列舉方式定義的允許值列表。清單 7 顯示了來自使用者顏色首選項的小部件 XML 定義的列舉程式碼片段。用於每週的第一天的首選項也使用相同型別的列舉。在本小節的剩餘部分,我們將實現讓使用者為這兩個首選項之一挑選列舉列出的值。


    清單 7. 來自 Date Time 小部件顯示顏色首選項列舉的 XML 定義

    
       
       
       
       
       
       
       
    
    

    為 iWidget 新增邏輯

    先前展示的 iWidget 是一個基礎的小部件,它僅包含一些標記,而沒有包含任何 JavaScript. 邏輯。在這個基礎的小部件中,指向 Google 服務的 URL 直接硬編碼到 iWidget 的標記 (iw:content) 部分。現在,您想要根據使用者輸入的值動態地構建 URL。為了完成該步驟,您需要編寫一些為生成的 URL 字串實現邏輯的支援程式碼。現在的第一個目標是將 Google 服務 URL 的位置從 iWidget 的 HTML 標記移動到支援程式碼,涉及的步驟為:

    1. 通過在 iWidget XML 定義中將 src 屬性從 IFRAME. 刪除來從標記中刪除 URL。現在,內容部分如清單 8 所示。



      清單 8. iWidget 包裝器檢視的標記
      						
      
         
         ]]> 
      
      

    2. 建立包含支援邏輯的 JavaScript. 檔案。如前所述,在稱為 iScope 的 JavaScript. 類中實現邏輯。在 Eclipse 中,建立和新增 JavaScript. 檔案的步驟與向專案新增 XML 檔案的步驟一樣,見前面的 “部署 iWidget” 小節。將該 JavaScript. 檔案命名為 googleGadgetWrapper.js。清單 9 顯示了新增到該檔案的程式碼。



      清單 9. 初步的 googleGadgetWrapper.js
      						
      dojo.provide("GoogleGadgetWrapper");
      
      dojo.declare("GoogleGadgetWrapper", null, {	
      
         onLoad: function(){
         },
      	
         onview: function(){
         // get the frame. DOM object declared in the widget markup
         var frame. = this.iContext.getElementById("frame");	
      
         // get the URL to the JSP page location without having to hard-code
         // the context root in the code. For instance, if the context root  
         // after deployment is /gadgetWrapper/, jspLocation is set to
         // /gadgetWrapper/gadgetWrapper.jsp
         var jspLocation = this.iContext.io.rewriteURI("gadgetWrapper.jsp");
      	
         // set the src attribute of the iframe. frame.src = jspLocation + "?url=http://www.google.com/ig/modules/datetime.xml&
         title=&border=&output=js&w=400";
         }
      }
      

    我們仔細研究一下清單 9 中的程式碼:

    1. iWidget 框架向小部件傳送一個名為 Load 的 iEvent。我們不打算詳細瞭解事件處理機制,但您需要知道它將導致在 iWidget 的 iScope 上呼叫一個名為 on + 的方法。在這個例子中,這個機制導致呼叫 onLoad 方法。
    2. iWidget 框架載入小部件的預設模式 (view)。通過兩個步驟載入模式:
      • 向使用者顯示與模式對應的標記(XML 描述器中的內容元素)。注意,在清單 7 中,您在該模式的內部宣告瞭小部件的標記(mode="view" 屬性)。
      • 帶有模式的名稱的 iEvent 被髮送給小部件。在這個例子中,將導致呼叫方法 onview。

    結果是當把小部件放到頁面上之後,框架將自動呼叫 onLoad 和 onview 方法。

    另外還要注意,我們使用來自 iWidget 框架(通過 iContext 物件)提供的 IO 模組的 rewriteURI 方法。這種方式允許您獲得 JSP 檔案的真實位置,而且不需要在程式碼中包含專案的上下文根。您不能確定在開發期間 iWidget 在其下部署的上下文根是什麼,因為管理員可以在部署期間更改該值。

    後臺邏輯必須連線到 iWidget 的 XML 定義。通過兩個步驟完成該連線:

    1. 新增一個資源元素標記,以指向剛才新增到專案的 JavaScript. 檔案:
    2. 在 iWidget XML 描述器的 iw:widget 標記元素中設定 iScope 屬性,使其指向在 googleGadgetWrapper.js 中定義的 JavaScript. 類。因為您的 JavaScript. 類的名稱為 GoogleGadgetWrapper,所以 iw:widget 標記應該類似於:
      xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget" iScope="GoogleGadgetWrapper">

    就這麼簡單!現在,將在小部件初始化時動態地設定 IFRAME. 的 src 屬性。至此,小部件出現給使用者的行為已經沒有區別。您現在可以為指向 Google 服務的 URL 生成查詢部分了。

    儲存引數並生成指向 Google 服務的 URL

    在設定指向 IFRAME. 的 URL 之前,您已經看到了一種生成和修改指向 Google 服務的 URL 的簡便方法。在這個小節中,您將通過修改 URL 以加入使用者首選項的值,這包括 3 個步驟:

    1. 將 Google 小部件的使用者首選項值儲存在您的 iWidget 的 ItemSet 中。使用 ItemSet 儲存首選項的理由是:
      • 它提供一致的資料儲存,您可以在程式碼的不同部分使用它來設定和獲取使用者選擇的值。
      • 它允許您在 Home page 伺服器的各個會話中保留首選項。這點在本文後面的 “持久化使用者首選項” 小節實現。

      為此,讓我們修改 iWidget 的 XML 定義以宣告 ItemSet,並將其命名為 userPrefs。清單 10 顯示了您隨後要在編輯檢視中使用的兩個使用者首選項的程式碼片段。



      清單 10. 為 Date Time 小部件儲存使用者首選項的 ItemSet
      						
      
         
         
      
      

      注意,您還為每個使用者首選項指定了預設值(green 和表示 Sunday 的 0)。

    2. 您需要實現一個從儲存在 ItemSet 中的值動態地生成指向 Google 服務的 URL 的機制。為此,在 iWidget 的 iScope 類中新增另一個名為 getQueryString 的方法。清單 11 顯示了該方法的程式碼。


      清單 11. 從首選項 ItemSet 返回查詢字串的方法
      						
      getQueryString: function(){
         // get the ItemSet object
         var userPrefs = this.iContext.getItemSet("userPrefs");
      		
         // get the names ("id") of the items as an array		
         var prefNames = userPrefs.getAllNames();
      		
         // initialize an empty JavaScript. object used as a map		
         var params = {};
      		
         // populate the params map with the user parameters
         dojo.forEach(prefNames, function(name) { 
            // we need to prefix the name with "up_" to pass it to the Google Service 
            as discussed in “Google gadget overview” part
            var upName = "up_" + name;
      	params[upName] = userPrefs.getItemValue(name);		
         });
      		
        // generate the string from the params map
        return dojo.objectToQuery(params);		
      }
      

      這個方法返回包含使用者首選項的值的方法。例如,對於 Date Time 小部件,它返回字串 up_color=green&up_firstDay=0。這個字串可直接用於構建指向 Google 服務的 URL,Google 服務將為 Google 小部件返回對應的標記。

    3. 您必須修改清單 8 中的 onview 方法,以在將指向 Google 服務的 URL 設定為 IFRAME. 的 src 屬性之前呼叫 getQueryString 來構建它。清單 12 顯示了修改後的 onview。


      清單 12. 修改後的 onview,包含使用者首選項值的 URL 字串是動態生成的
      						
      
      onview: function(){   
         var frame. = this.iContext.getElementById("frame");	
      	
         var query = this.getQueryString();
      
         var jspLocation = this.iContext.io.rewriteURI("gadgetWrapper.jsp");
      			
         frame.src = jspLocation + "?url=http://www.google.com/ig/modules/datetime.xml&
         title=&border=&output=js&w=400&" + query;
      }
      

    實現編輯檢視

    至此,您已經實現了儲存使用者首選項並生成包含首選項值的 Google 服務 URL 的機制。在這個小節中,您將使用使用者輸入的值填充 ItemSet。完成該任務需要 3 個步驟:

    1. 實現一個允許使用者為首選項選擇值的圖形介面。為此,您必須實現編輯(edit)檢視的標記。在啟用編輯檢視的情況下,該實現將是使用者與之互動的檢視。在 Date Time Google 小部件中,您希望允許使用者定製背景顏色和每週的第一天。因此,您僅需將編輯檢視實現為包含兩個下拉選單的表單,下拉選單包含兩個使用者首選項可以選擇的值。

      圖 7 顯示了包裝 Date Time 小部件的 iWidget 編輯檢視。



      圖 7. iWidget 包裝器的編輯檢視
      iWidget 包裝器的編輯檢視

      清單 13 顯示的標記程式碼是 iWidget 的 XML 描述器的一部分。



      清單 13. 小部件 的編輯檢視程式碼
      —-- same principle as for the color drop-down list here --&gt
      						
         
         
      Color:

      ]]>

      在清單中,需要注意以下方面:

      • 標記放置在 mode 屬性設定為 edit 的 iw:content 元素中。
      • 使用 iContext.iScope() 方法確保封裝正確。
      • 該標記是一個 HTML 表,它包含兩個帶有兩個按鈕(Save 和 Cancel)的下拉選單。
    2. 向 iWidget 的支援邏輯新增方法,以通過使用者輸入填充 ItemSet。為此,您必須為按鈕(onSave() 和 onCancel() 方法)實現支援邏輯。清單 14 顯示了單擊 Save 按鈕時呼叫的 onSave() 方法的程式碼。


      清單 14. onSave() 方法的程式碼
      						
      onSave: function(){
         // get ItemSet object
         var userPrefs = this.iContext.getItemSet("userPrefs"); 
      
         // set the item values from the drop-down list selections
         userPrefs.setItemValue("color", 
         this.iContext.getElementById("color").value);
         userPrefs.setItemValue("firstDay", 
         this.iContext.getElementById("firstDay").value);
      		
         // switch back to the view mode (widget normal view with the gadget)		
         this.iContext.iEvents.fireEvent("onModeChanged", 
         null, "{newMode: 'view'}");		
      }
      

      onSave() 方法通過使用者輸入為 ItemSet 的兩個首選項設定新值。onSave() 方法的最後一行用於返回到小部件的檢視模式。為此,您需要對小部件發出一個 onModeChanged 事件。iWidget 框架將該事件解釋為將小部件的當前模式從編輯(edit)切換到檢視(view)的請求。在該步驟中,將呼叫在 “為 iWidget 新增邏輯” 中描述的模式處理機制。

      Cancel 按鈕的目標是返回到檢視模式,並且不儲存 ItemSet 中的首選項。因此,onCancel() 只是觸發 onModeChanged 事件的 onSave() 的最後一行。

    3. 在 iWidget 的 XML 描述器中註冊編輯模式。為此,向 XML 描述器的 iw:iwidget 元素新增 supportedMode 屬性,如下所示:
      xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget"
      iScope="GoogleGadgetWrapper" supportedModes="edit view">

      完成更改並重新部署小部件之後,使用者將在 Home page 的小部件的頭部欄上看到編輯圖示,如圖 8 所示。


    圖 8. iWidget 的頭部欄的編輯圖示
    iWidget 的頭部欄的編輯圖示

    當使用者單擊 Edit 時,Home page 執行時將對嵌入的 iWidget 觸發 onModeChanged 事件。該事件導致框架呈現編輯檢視並在 iWidget 的 iScope 中呼叫一個稱為 onedit 的方法。為了完成該任務,清單 15 顯示瞭如何在 onedit 方法中新增一些邏輯,以使用儲存在 ItemSet 中的值設定編輯檢視中的兩個下拉選單。


    清單 15. 使用儲存值在編輯檢視中設定下拉選單的 onedit 方法

    onedit: function(){
       var userPrefs = this.iContext.getItemSet("userPrefs"); 
       this.iContext.getElementById("color").value = userPrefs.getItemValue("color");
       this.iContext.getElementById("firstDay").value = userPrefs.getItemValue("firstDay");
    }
    

    持久化使用者首選項

    更新:根據 iWidget 規範,現在的 Lotus Connections 2.5 支援使用者首選項持久化。儘管 Lotus Connections 2.5 的向後相容性使得本小節中的程式碼仍然有效,但我們建議您使用標準 iWidget。參考文章 “Customizing Lotus Connections 2.5 with Lotus Widget Factory and Google Gadgets” 的 “Lotus Connections 2.5 中的 iWidget 規範 v1.0” 瞭解更多細節。

    對 iWidget 包裝器的最後一個改進是持久化儲存在 ItemSet 中的使用者首選項。當您執行該任務時,使用者所做的定製不會丟失。Home page 執行時為持久化 ItemSet 伺服器提供兩個方法(_save 和 _load)。

    注意:這個實現是針對特定於 Home page 的 iWidget 框架的擴充套件;它不能用於其它 iWidget 容器,比如 Lotus Mashups。

    _save 和 _load 方法接受 URI 作為引數,URI 是持久化 ItemSet 的位置。本文不討論這些方法用於編碼和解碼 ItemSet 的系列化。您僅需要知道 Home page 提供一個接受並返回位於 handleUP?Act=XXX&FId=XXX 的系列化字串的服務 (Servlet),其中 Act 以 SaveCustomization 和 LoadCustomization 作為值,FId 是 iWidget ID。

    注意:在 Home page 中,您可以從 iContext (iContext.widgetId) 獲得小部件 ID。這個變數專屬於 Home page,不是 iWidget 規範的一部分。

    清單 16 顯示了 onLoad 方法的程式碼(在小部件放到頁面上之後才呼叫),該方法負責使用來自持久化層的值填充 userPrefs ItemSet。注意,如果沒有持久化任何值(即使用者沒有為該小部件編輯和儲存首選項),那麼預設值就是在 iWidget 的 XML 描述器中定義的值(見清單 9)。


    清單 16. 從 Home page 持久化層載入使用者首選項

    onLoad: function(){
       var userPrefs = this.iContext.getItemSet("userPrefs");
       userPrefs._load("handleUP?Act=LoadCustomization&FId=" + this.iContext.widgetId);
    }
    

    最後,您需要儲存 ItemSet 的值。當使用者在編輯檢視中單擊 Save 按鈕時,您必須完成該步驟。因此,您必須在觸發 onModeChanged 事件之前呼叫 onSave 方法的 userPrefs 物件上的 _save 方法。您可以在本文下載小節的 EAR 檔案中找到原始碼。

    結束語

    本文討論了實現一個包裝 Google 小部件的基礎 iWidget 並將其部署到 Lotus Connections Home page 所需的各個步驟。除了包裝器本身的實現之外,本文還通過具體的例子展示 iWidget 框架提供的一部分特性。在閱讀完本文之後,您應該瞭解了為 Home page 編寫基礎小部件所需掌握的概念,比如 XML 描述器、ItemSet、模式和事件。另外,您還可以繼續改進 Google 包裝器,例如允許使用者在 iWidget 的編輯檢視中輸入小部件描述器的位置。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/14751907/viewspace-617668/,如需轉載,請註明出處,否則將追究法律責任。

相關文章