[Google] Google Gadget 開發初體驗

昨天被 assign 一個任務,說要在 iGoogle 上開發一個 Gadget 讀取 RSS 來展現系統的最新資料,之前我自己是有寫過 Gadget 的經驗,也當過 Google Gadget 小工具開發競賽的論壇專板板主角色,但那個比賽結束後,我就沒有再接觸 Gadget Development 這一塊了,這次等於是複習 Gadget Development 的工作。

昨天被 assign 一個任務,說要在 iGoogle 上開發一個 Gadget 讀取 RSS 來展現系統的最新資料,之前我自己是有寫過 Gadget 的經驗,也當過 Google Gadget 小工具開發競賽的論壇專板板主角色,但那個比賽結束後,我就沒有再接觸 Gadget Development 這一塊了,這次等於是複習 Gadget Development 的工作。

Gadget 是一個可掛在 iGoogle 介面上的一個 Mashup Application,每個 Gadget 均提供特定的介面與功能供使用者自由在自己的 iGoogle 首頁上安裝,等於是把 Google 當成是一個入口網站般,使用者可以自由的運用在 iGoogle 中提供的各式 Gadgets,組裝出自己的入口頁面。

image

每個 Gadget 其實都是一個 XML 的定義檔案,有一個固定的格式,例如:

<?xml version="1.0" encoding="UTF-8" ?>
<Module>
  <ModulePrefs title="Hello World!" />
  <Content type="html">
    <![CDATA[
      Hello, world!
    ]]>
  </Content>
</Module>​

 

一個 Gadget 可以設定多個 Content 的內容區,以及可在 ModulePrefs 之後加上自己的設定,而且有些特殊的功能設定,也要在 ModulePrefs 中設定,例如:

<module>
  <ModulePrefs title="RSS Testing Tool">
    <Preload href=http://www.mydomain.com.tw
/>
    <Require feature="tabs"/>
    <Require feature="dynamic-height"/>

  </ModulePrefs>
  <UserPref name="FeedUrl0" default_value="
http://udn.com/udnrss/BREAKINGNEWS1.xml" datatype="string" />
  <UserPref name="FeedUrl1" default_value="
http://mag.udn.com/udnrss/campus_rss.xml" datatype="string" />
  <UserPref name="FeedUrl2" default_value="
http://udn.com/udnrss/local_ksptisland.xml" datatype="string" />
  <UserPref name="TabCaption0" default_value="Breaking News" datatype="string" />
  <UserPref name="TabCaption1" default_value="Campus News" datatype="string" />
  <UserPref name="TabCaption2" default_value="K,P,Islands News" datatype="string" />
  <UserPref name="TabTooltip0" default_value="Breaking News" datatype="string" />
  <UserPref name="TabTooltip1" default_value="Campus News" datatype="string" />
  <UserPref name="TabTooltip2" default_value="K,P,Islands News" datatype="string" />
  <Content>
  …
  </Content>
</module>

 

如果有自己想要放的設定,也可以放在 Gadget 中,自己的設定稱為 User Preference (UserPref),例如:

<module>
  <ModulePrefs title="RSS Testing Tool">
    <Preload href="http://www.mydomain.com.tw"
/>
    <Require feature="tabs"/>
    <Require feature="dynamic-height"/>
  </ModulePrefs>
  <UserPref name="FeedUrl0" default_value="
http://udn.com/udnrss/BREAKINGNEWS1.xml" datatype="string" />
  <UserPref name="FeedUrl1" default_value="
http://mag.udn.com/udnrss/campus_rss.xml" datatype="string" />
  <UserPref name="FeedUrl2" default_value="
http://udn.com/udnrss/local_ksptisland.xml" datatype="string" />
  <UserPref name="TabCaption0" default_value="Breaking News" datatype="string" />
  <UserPref name="TabCaption1" default_value="Campus News" datatype="string" />
  <UserPref name="TabCaption2" default_value="K,P,Islands News" datatype="string" />
  <UserPref name="TabTooltip0" default_value="Breaking News" datatype="string" />
  <UserPref name="TabTooltip1" default_value="Campus News" datatype="string" />
  <UserPref name="TabTooltip2" default_value="K,P,Islands News" datatype="string" />

  <Content>
   …
  </Content>
</module>

 

Content 區域則是可供開發人員放置 HTML 內容的地方,這裡也可以使用 JavaScript 來操作網頁,而這也是 Gadget 最重要的地方,因為有些 Gadget Service 是透過 JavaScript 來提供的,包括對外的存取,以及控制 Gadget 中的控制項等,都會需要使用到 JavaScript。而這次需要的功能是,在 Gadget 中加入頁籤,並且能夠讓不同的頁籤讀取不同的 RSS Feeds,而我又比較熟悉 jQuery,因此我在 Content 區中引入 jQuery 的 Library,還好 Google 本身就有提供 jQuery 的 CDN:

<Content type="html">
  <![CDATA[
   
<script type='text/javascript'
            src='
http://ajax.googleapis.com/ajax/libs/jquery/1.6/jquery.min.js'></script>
]]>
</Content>

 

接著為了要加入頁籤,我在 <ModulePrefs> 中加入 <Require feature="tabs" /> 的宣告 (沒有這個宣告的話,gadgets.tabs 會失效),以及 <Requires feature="dynamic-height" /> 的宣告 (後面會用到),然後使用 JavaScript 將頁籤加入:

$(function () {
    // initialize tab.
   
tabs = new gadgets.TabSet(__MODULE_ID__);
    tabs.addTab(prefs.getString("TabCaption0"), {
        contentContainer: document.getElementById("gadget_Tab1"),
        callback: loadRSS,
        tooltip: prefs.getString("TabTooltip0"),
        index: 0
    });
    tabs.addTab(prefs.getString("TabCaption1"), {
        contentContainer: document.getElementById("gadget_Tab2"),
        callback: loadRSS,
        tooltip: prefs.getString("TabTooltip1"),
        index: 1
    });
    tabs.addTab(prefs.getString("TabCaption2"), {
        contentContainer: document.getElementById("gadget_Tab3"),
        callback: loadRSS,
        tooltip: prefs.getString("TabTooltip2"),
        index: 2
    });
});

 

這會產生這樣的效果:

image

 

接著,要設定每個頁籤使用的內容,只要使用 div 作為容器即可,所以我在 Content 中再加入頁籤的內容 (因為內容要動態產生,所以內容可以不用加):

<div id="gadget_Tab1" style="display:none"></div>
<div id="gadget_Tab2" style="display:none"></div>
<div id="gadget_Tab3" style="display:none"></div>

 

然後,我們要處理由 RSS Feed 的網站下載 RSS 的資料,需要使用 HTTP Request 來讀取,不過考慮到跨網域的問題 (jQuery.get() 會被擋),所以我們只有 gadgets.io.makeRequest() 可以使用,所以我撰寫了下面的程式碼:

function loadRSS()
{
    var contentContainer = $(tabs.getSelectedTab().getContentContainer());
    contentContainer.html(""); // clean previous result.
    gadgets.io.makeRequest(
        prefs.getString("FeedUrl" + tabs.getSelectedTab().getIndex()), function (response) {
          currentRssContainer = $($.parseXML(response.text));
          currentRssContainer.find("rss > channel > item").each(function (i, o) {
              contentContainer.html(
          contentContainer.html() +
          "<div><a href='" + $(o).find("link").text() + "'>" + $(o).find("title").text() + "</a></div>");
              if (i == (currentRssContainer.find("rss > channel > item").size() - 1))
                  gadgets.window.adjustHeight();
          });
      });
}

 

此時,Gadget 已基本完成,透過 Google 的 Gadget Developer Tool,我們可以將寫好的 Gadget XML 儲存在 Google 的主機上,並且直接測試:

image

image

然後就可以在 iGoogle 中直接測試:

image

 

另外還有一個需要注意的,若你想要開發 Gadget 的話,建議在自己的 iGoogle 空間中加入 My Gadgets 這個 Gadget,它可以允許你設定哪些 Gadget 要快取,哪些要設 Inline,這對開發人員是有很大幫助的,因為在修改 Gadget XML 的時候,如果原先的 Gadget 是被 Cached 的,你就必須要等個十幾分鐘,再重新加入才會生效,透過 My Gadgets 取消快取,可以讓你馬上就得到修改過的結果。然而很弔詭的是,這個工具在 IE 上有用,在本家的 Google Chrome 卻沒有作用…。

image

 

更多的 Gadget 開發資訊,請參考 Google Code: Gadget Development。

Reference:

Google Gadget Development: http://code.google.com/intl/zh-TW/apis/gadgets/docs/overview.html