舊文件

此處文件僅供參考,請自行考量時效性與適用程度,其他庫藏文件請參考文件頁面
我們亟需您的協助,進行共筆系統搬移、及文件整理工作,詳情請查閱參與我們

套件開發指南 - Googlebar Lite

出自 MozTW Wiki

於 2006年3月17日 (五) 15:41 由 Chkuya對話 | 貢獻 所做的修訂

翻譯進度:37.5%

有些句子不知該如何翻譯,排版也有點亂,請幫忙調整!--chkuya 00:14 2006年三月17日 (CST)

原文: Creating a Firefox Toolbar Extension (Firefox 1.5)

前言 (Instruction)

這份指南將說明如何建立 Firefox 的工具列套件(支援 1.5 或更新的版本)。這份文件提供套件如何開發的概要、必要的工具、以及建立工具列的細節。套件開發是不難的,儘管必須具備某些基礎的程式設計知識。

有三種技術是我建議你必須稍微熟悉的:XML、JavaScript、CSS。這三個技術學習起來都不難,而且網路上有許多不錯的教學。

Firefox 1.5 版在套件開發上有很大的改善,這個版本比先前的版本更容易建立套件。 這份指南利用了改善的部份,必要時,我會指出變動的部份。如果你發現錯誤的地方,或是有任何建議,請聯絡作者

第一章:準備開始 (Getting Started)

在我們開始製作第一份工具列套件之前,有一些非常有用的東西是你必須要先知道的。

下載指南 (Tutorial Downloads)

在這份指南的最後,我們將建立一個 Googlebar Lite 的簡化版本。為了幫助過程的學習,你可以下載這個工具列的開發版本。兩份可得到的版本:

  • Example Toolbar XPI : 這是我們將要建立的套件的安裝版本。
  • Example Toolbar Source Code (即將完成): 這份 zip 檔案包含建立工具列的原始碼。

注意到這份 xpi 檔案也包含了原始碼。技術上而言,你只要下載 xpi 的檔案,並用 zip 的解壓縮程式解開 xpi 檔,以及其中的 jar 檔。第二份檔案只是為了方便而已。

有用的參考文獻 (Useful References)

我強烈建議你將下列的網址加入書籤,在我學習套件開發的過程,這些網頁對我非常的有幫助,我相信對你來說也是。(前四項為原作者提供)

必需先學習的 (Learning the Prerequisites)

如我之前所提到的,Firefox 套件開發需要先知道一點關於 XML、JavaScript、及CSS 的技術。這三個主題都是相當容易了解的,我也會提供了一些關於這三項技術的說明。

你將會需要的工具 (Tools You Will Need)

為了設計套件,你需要幾個工具軟體,這些軟體都是免費可取得的。我們要設計的幾個檔案都是標準文字檔。因此,你需要一個不錯的文字編輯器。我強烈反對使用類似 Microsoft Word 的程式。網路上有一些傑出的免費程式設計文字編輯器,這些編輯器對你有非常大的幫助,例如自動縮排、強調語法等等。幾個受歡迎的編輯器包含 Crimson EditorTextPad、及 JCreator

第二個你會用到的工具是 zip 檔的壓縮軟體。雖然有其他需多有用的工具,像是 7-Zip、及 WinRAR,但我個人是使用 WinZip。當封裝套件時,我們會用到這個工具。如果你打算做很多套件的開發,我建議你找有命令列介面的壓縮工具。使用命令列可以輕易地將封裝過程自動化,也省下你大量的時間。

檔案結構佈局 (File Structure Layout)

套件開發需要特定的內部結構,所以我們必須確定這一步是正確的。否則,將不會發生作用。首先,為我們的套件建立最上層的目錄。在這份指南,我們會使用 TutToolbar 當作目錄名稱(避免使用空白文字)。在這個新建立好的 TutToolbar 目錄裡,我們需要再建立第二個目錄。這個目錄命名為 chrome (使用小寫) 。既然我們這麼喜歡建立目錄,那就再來建立第三個吧!這次在 chrome 目錄裡建立一個名稱為 content 的目錄(使用小寫)。這裡是我們的目錄結構看起來的樣子:

+- TutToolbar/
   +- chrome/
      +- content/

或者是

TutToolbar/
TutToolbar/chrome/
TutToolbar/chrome/content/

第二章:建立架構(Creating the Framework)

套件的架構是用來告訴 Firefox 套件是如何被延伸的:檔案的結構、被誰建立、或是套件的全球唯一代號(GUID)。在 Firefox 1.5 這個版本,套件開發在這個部份有很大的變化。原本在 1.0.x 版是很沈重的技巧,在 1.5 版已經變得更整潔、更簡單。

安裝清單 (Installer Manifest)

這份清單是用來提供 Firefox 關於套件的細節。有一些重要的項目放置在這個檔案,所以我們必須確定這部份是正確的。在你的最上層目錄裡,建立一個檔案 install.rdf 。當你建立好這個檔案,你會看到這樣的結構:

+- TutToolbar/
   +- install.rdf
   +- chrome/
      +- content/

在我們開工前,讓我們看看這個範例。所有我們必須編輯的部份已經被突顯出來了,沒有被突顯的部份是不可以修改的。接著,我們來看這份檔案的內容,我將會解釋每個部份的細節,而且可以開始編輯屬於自己的套件。

<?xml version="1.0"?>

<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">

<Description about="urn:mozilla:install-manifest">

<!-- Required Items -->
<em:id>yourextension@yoursite.com</em:id>
<em:name>Your Extension's Name</em:name>
<em:version>1.0</em:version>

<em:targetApplication>
    <Description>
        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
        <em:minVersion>1.5</em:minVersion>
        <em:maxVersion>1.5.0.*</em:maxVersion>
    </Description>
</em:targetApplication>

<!-- Optional Items -->
<em:creator>Your Name</em:creator>
<em:description>A description of the extension</em:description>
<em:homepageURL>http://www.yoursite.com/</em:homepageURL>

</Description>
</RDF>

在最上面第一行表示這是一份 XML 格式的檔案。第二行,以 <RDF> 開頭的,是這份文件的基本元素(root element)。它的責任是辨別這部份是 RDF (Resource Description Framework) 格式。下一個標籤(Tag) <Description> 同樣地是用來辨別為安裝清單。現在,乏味的東西都結束了,讓我們看看第一部份必須要編輯的:

<em:id>yourextension@yoursite.com</em:id>
<em:name>Your Extension's Name</em:name>
<em:version>1.0</em:version>

第一個我們需要擔心的是套件的識別號碼。在 Firefox 1.5 之前的版本,必須使用全球唯一代號(globally unique identifier),即 GUID。儘管 GUID 還是被支援的,新的格式卻更容易使用。僅僅需要使用你的套件名稱,@ 符號,再加上你的網站的最上層網址。在這份指南中,我們為這個工具列使用這個值 tuttoolbar@borngeek.com

接著是套件的名稱(這會顯示在套件管理員裡)。在我們的範例裡,使用 Toolbar Tutorial 為這個套件的名稱。確定這個名稱不包含版本編號,因為版本編號有它自己專屬的標籤。我們要編輯的這個標籤就在下一行。既然這是我們試圖要做的第一個工具列套件,讓這個值為 1.0 。要注意到,在真實的情況裡,當你發表新版本的套件時,必須更新這個值,描述解譯程式(Scripter)在自動更新過程才不會發生問題。在我的套件裡,我利用了描述語法 (以 Perl 寫成)。在這份指南的第七章,我將會告訴你我如何使用。

下一個區塊也是這個安裝清單重要的一部分,接著來看看這部份:

<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>1.5</em:minVersion>
<em:maxVersion>1.5.0.*</em:maxVersion>
</Description>
</em:targetApplication>

這個區塊是用來指示套件要用在哪個程式。在這個例子,我們要開發 Firefox 的套件。因此,<em:id> 這個元素指定了 Firefox 的 GUID 。你不應該改變這個值,否則,會讓你的套件無法被正確地安裝。

唯一兩個我們需要變動的,是這兩個元素:<em:minVersion><em:maxVersion> 。這兩個元素指明套件適合用在 Firefox 的哪個版本 ( minVersion 是最低支援版本,而 maxVersion 是最高支援版本) 。 在我們的範例,我們會使用 1.5 (minVersion) 與 1.5.0.* (maxVersion)。因為我們利用 Firefox 1.5 的開發環境,所以不可以把 minVersion 設定的比 1.5 還小。

注意到,你所使用的版本編號必須遵守標準協定。舉個例子,「1.5 Release Candidate 1」是不行的。目前 Firefox 的版本結構是相當嚴謹的,在 Mozilla Developer Center 的文章 Toolkit Version Format 有詳細的描述。我建議你讀這篇文章,以了解怎樣的字串是被允許的。

在安裝清單的最後,是用來描述套件的資料定義,或稱中繼資料(meta-data):

<!-- Optional Items -->
<em:creator>Your Name</em:creator>
<em:description>A description of the extension</em:description>
<em:homepageURL>http://www.yoursite.com/</em:homepageURL>

就如註釋一樣,這些元素是非必要的。<em:creator> 允許套件作者指明自己的名字,這樣別人就知道是誰製作這個套件。下一個,<em:description> 允許我們對我們的套件做一些說明,這個說明會顯示在套件管理員中的套件名稱底下。最後,<em:homepageURL> 允許我們指明別人可以在哪裡找到我們的套件。

注意到,這些不是唯一的資料定義,同時也有許多其他可選用的項目。舉個例子,有個元素可以在套件管理員中使用我們自己的圖示(icon)。 另一個元素允許我們指定自訂選項的位置或是「關於」的對話視窗。全部可用的元素(也叫做屬性 properties ),可以看看在Mozilla Developer Center 中的文章 Installer Manifests 。最後一點要注意的,所有的元素是不需要按照順序的。也就是說,你可以將它們放在檔案中任何地方,僅僅要注意的是,將它們放置在 <Description></Description> 之間。

現在,我們了解了安裝清單,讓我們來看看最後的樣子,這個版本將被使用在這份指南中。你可以直接將下面的部份,複製在 install.rdf 中。

<?xml version="1.0"?>

<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">

<Description about="urn:mozilla:install-manifest">

 <!-- Required Items -->
 <em:id>tuttoolbar@borngeek.com</em:id>
 <em:name>Tutorial Toolbar</em:name>
 <em:version>1.0</em:version>

 <em:targetApplication>
     <Description>
         <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
         <em:minVersion>1.5</em:minVersion>
         <em:maxVersion>1.5.0.*</em:maxVersion>
     </Description>
 </em:targetApplication>

 <!-- Optional Items -->
 <em:creator>Jonah Bishop</em:creator>
 <em:description>An example toolbar extension.</em:description>
 <em:homepageURL>http://www.borngeek.com/firefox/</em:homepageURL>

</Description>
</RDF>

Chrome 清單 (Chrome Manifest)

Chrome 清單是 Firefox 1.5 才開始有的。在之前,所有的資料被設定在兩個地方:安裝清單(installer manifest)、及 contents.rdf 。而現在,新的格式顯得更簡單。再次在最上層目錄建立另外一個檔案 chrome.manifest 。下面是檔案結構看起來的樣子:

+- TutToolbar/
   +- install.rdf
   +- chrome.manifest
   +- chrome/
      +- content/

與早先使用的 contents.rdf (通常超過20行) 比較,現在的方式變得非常簡單!第一行使用你指定的封裝名稱來登錄,並指明放置在 content 目錄。這將允許 chrome 資源識別字串(Uniform Resource Identifier,簡稱 URI) ,如 chrome://myextension/content/,在我們的套件層級中指向適當的地方。

注意到,content 目錄的位置是相對於套件的根目錄。在這份指南,我們使用 tuttoolbar 當作封裝名稱。

第二行登錄 chrome://browser/content/browser.xul 的覆載(overlay),這允許你新增或修改 Firefox 主視窗的使用者介面(user interface)。

在上面的範例,chrome://myextension/content/overlay.xul 指定了覆載(overlay)的XUL 檔案。

換句話說,位於套件中 content 目錄的 overlay.xul 檔案,是我們將要新增的使用者介面(工具列)。在這個部份,我們要使用的值為 chrome://tuttoolbar/content/tuttoolbar.xul 。 下一行說明地區化如何建立(how a locale can be created)。在這份指南中,我們不設計地區化(雖然過程很簡單),這將在未來再做討論。

最後一行設定了面板(skin),我們將使用這個技巧來美化我們的工具列。現在,先略過它,我們將在第五章再回來討論這點。 一切都很簡單,不是嘛?下面是我們將會使用的 chrome 清單,這只是半成品,之後我們將會加入面板的資訊。再一次,將下面的程式碼複製到我們剛剛建立的 chrome.manifest

content tuttoolbar chrome/content/
overlay chrome://browser/content/browser.xul chrome://tuttoolbar/content/tuttoolbar.xul

現在架構已經可以了,接著讓我們來做些有趣的事吧!

第三章:建構工具列 (Structuring the Toolbar)

Firefox 套件的使用者介面部份是使用 XUL 技術 (音:zool),這是一種用來設計使用者介面的標示語言。XUL 可以想成是一種 XML 的調味料(意旨有附加功能的), 它不過是使用預設元素的 XML (也叫做 widgets)。使用 XUL 的好處,是因為它使用了動態覆載(dynamic overlays)的技術。動態覆載技術可以讓開發者不需要改變原本介面的程式碼的情況下,去修改視窗的使用者介面。在不需更動原始程式碼的情況下,可以讓我們專注於設計我們的套件,而不用擔心需要重複開發的問題。在這個章節,我們要來看看設計工具列的 XUL 必要標示。記住,XUL 僅僅是用來建構工具列而已。為了讓工具列可以運作,我們必須使用 JavaScript ,這部份將在第六章提到。

content 目錄裡,建立一個檔名為 tuttoolbar.xul 的檔案。在你建立好之後,目錄的結構會是這樣:

+- TutToolbar/
   +- install.rdf
   +- chrome.manifest
   +- chrome/
      +- content/
         +- tuttoolbar.xul

現在,我們已經建立好這個檔案,可以逐行地開始討論內容。隨著進行的腳步,我會將檔案的所有內容,一步一步地介紹。這會讓過程看起來更簡單,在這章節的最後,這個檔案會相當健全。

因為 XUL 只是一種 XML 的調味料,所以第一行必須是使用 XML 的宣告:

<?xml version="1.0"?>

現在,宣告這是一個 XML 的檔案之後,我們就可以開始藉由 overlay 元素設計覆載了。這個元素將會是這整份文件的根元素。換句話說,所有其他的元素必須在 <overlay> 與 </overlay> 之間。這是 overlay 看起來的樣子:

<overlay id="TutTB-Overlay"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
</overlay>

這個元素有兩個屬性:idxmlns 。這跟 HTML 類似,id 的值必須是唯一的。更重要的是,這也必須是整個瀏覽器唯一的值。這裡有一個可以讓你確定所使用的 ID 是唯一的方法。例如,上面的範例。你可以注意到我使用了 TutTB 開頭的字眼來定義 id 屬性的值。使用符合你的套件名稱開頭的字眼,這會使 ID 是唯一的可能性提高。並且注意到,實際的值是不需要包含 overlay 的字眼,我這麼做是方便我追蹤所使用的名稱是做什麼用的。

第二個屬性:xmlns,用來指定使用於覆載的命名空間。既然這是 XUL 文件,我們必須定義 XUL 的命名空間,這是你會一直用到的值。

工具箱與工具列 (The Toolbox and Toolbar)

所有的工具列應該被集中在工具箱中。我們使用 toolbox 元素來指定一個工具箱(記住,這個元素必須被放置在 overlay 之間。):

<toolbox id="navigator-toolbox">
</toolbox>

注意到,這個 id 屬性有一個預設值:navigator-toolbox 。 這個特定的值表示為 Firefox 視窗中主要的工具箱元素,跟瀏覽工具列、選單列、網址列,或是其他類似的控制選項一樣。藉由指定這個特別的工具列,我們可以確定這個工具列會與其他的工具列靠攏在一起。我建議你總是讓你的工具列放在這個特定的工具箱中,這不只讓你有看起來一致的工具列,也可以讓你在 「檢視>工具列」 中,快速地將你的工具列隱藏或是顯示。

讓我們將注意力放回到 toolbar 元素,我們會將這個元素放在 toolbox 之中。看看這個範例:

<toolbar id="TutTB-Toolbar" toolbarname="Tutorial Toolbar" accesskey="T"
         class="chromeclass-toolbar" context="toolbar-context-menu" 
         hidden="false" persist="hidden">
</toolbar>

讓我們來看看這個元素的屬性:

  • toolbarname - 這個元素指定套件的名稱(這會是你在「檢視>工具列」看到的文字)。
  • accesskey - 給這個工具列指定字母,用來當作快速鍵使用。在這個工具列指南中,我們使用大寫的 T 。雖然這是非必要的屬性,還是強烈建議你使用它,這能讓使用者只要用快速鍵就能開啟或關閉你的工具列。
  • class - 為工具列指定特定的樣式類別。預設值 chromeclass-toolbar 是用來規範工具列顯示模式的類別,同樣地,這是建議使用的非必要屬性。
  • context - 指定當在工具列上按右鍵時,所顯示的工具列選單(context menu)。You can provide the ID of your own menu here, or you can provide the value for the standard View » Toolbars menu, which is shown in the example above (toolbar-context-menu).
  • hidden - 指定工具列是否隱藏。預設的情況下,我們要讓使用者看見我們的工具列,所以設定這個值為 false (相反為 ture )。
  • persist - This attribute is a space separated list of attributes that should persist across browser sessions. 在上面的範例,我使用 hidden ,用來告訴 Firefox 在 sessions 記住工具列的隱藏狀態。注意到,如果你的工具列沒有使用 id 屬性,則 persist 屬性不會發生作用!所以要確定你有為你的工具列指定 id 元素。

你可以在 XUL Planet toolbar element's attributes 看到完整的參考文獻。

現在,讓我們來看看建立好的覆載檔案[1]

<?xml version="1.0"?>
<overlay id="TutTB-Overlay"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

    <toolbox id="navigator-toolbox">

        <toolbar id="TutTB-Toolbar" toolbarname="Tutorial Toolbar" accesskey="T"
                 class="chromeclass-toolbar" context="toolbar-context-menu"
                 hidden="false" persist="hidden">
        </toolbar>

    </toolbox>

</overlay>

工具列按鈕 (Toolbar Buttons)

在 Firefox 中,工具列按鈕有三種:一般、選單、按鈕選單。這些都是用 toolbarbutton 來建立的,讓我們來分別看看。記住,這些元素必須放在 toolbar 元素之中。

一般按鈕 (Normal Buttons)

這是用來建立一般的按鈕:

<toolbarbutton id="TutTB-Web-Button" tooltiptext="Search the Web"
               label="Web Search" oncommand="TutTB_Search(event, 'web')" />

完成之後,來看看這個元素的屬性:

  • tooltiptext - 當滑鼠移動到按鈕上時出現的說明。
  • label - 工具列按鈕顯示的文字。
  • oncommand - 當 oncommand 事件觸發時(按下按鈕),你所指定的程式碼。在這個範例,使用 TutTB_Search()函式,我們將在第六章詳細說明。

你可以在 XUL Planet toolbarbutton element's attributes 找到完整的參考文獻。

選單按鈕 (Menu Buttons)

當點擊按鈕選單時,會出現下拉式選單。 Although the markup for this button is similar to the normal button's markup,我們必須加入 menupopup 元素,讓選單以我們想要的樣子出現。為了簡潔點,下面的範例只包含兩個選單項目。

<toolbarbutton id="TutTB-MainMenu" type="menu"
               tooltiptext="Tutorial Toolbar Main Menu">
  <menupopup>
    <menuitem label="Google Home Page" accesskey="G"
              tooltiptext="Navigate to Google"
              oncommand="TutTB_LoadURL('http://www.google.com/')" />

    <menuseparator />

    <menuitem label="Born Geek Website" accesskey="B"
              tooltiptext="Navigate to Born Geek"
              oncommand="TutTB_LoadURL('http://www.borngeek.com/')" />
  </menupopup>
</toolbarbutton>

toolbarbutton 有兩個要注意的變化。第一,type 屬性指定了 menu 的值,說明了這是個選單按鈕,而不是一般按鈕。第二,你會注意到這裡面沒有 oncommand 屬性。因為選單按鈕的唯一目的是為了顯示跳出式選單,並不需要執行任何程式碼,而顯示選單的動作會由 Firefox 自動完成。

也請注意到 menupopupmenuitemmenuseparator 這三個元素。menupopup 所有選單項目的容器,用來建立與顯示選單。在這個範例裡,這個元素沒有屬性。同樣地,menuseparator 也很簡單,在下拉式選單中放置水平分隔線,用來分隔不同的選單。

menuitem 稍微有點複雜。在上面的範例,我們指定的屬性:

  • label - 指定選單項目的文字。
  • tooltiptext - 這個屬性就像是我們在 toolbarbutton 看到的,但是有一點要警告的。由於 Firefox 的 bug (bug #147670),這個屬性是必要的。如果你決定從 menuitem 中刪掉這個屬性,當使用者將滑鼠移動到選單項目時,會看不到提示說明。Because menus do not traditionally have tooltips, this is an unpleasant 'feature'.

你可以在 XUL Planet menuitem element's attributes 找到完整的參考文獻。

按鈕選單 (Button-Menu Buttons)

第三也是最後的按鈕選單是三種之中最複雜的。實際上,結合了前兩種按鈕,提供可點擊按鈕的下拉式選單。

「上一頁」與「下一頁」瀏覽選單是這個按鈕選單的範例,這是需要建立的標記:

<toolbarbutton id="TutTB-Combined-Button" label="Search"
               type="menu-button" tooltiptext="Combined Search"
               oncommand="TutTB_Search(event, 'web')">
  <menupopup>
    <menuitem id="TutTB-Combined-Web" label="Web Search"
              class="menuitem-iconic" tooltiptext="Search the Web"
              oncommand="TutTB_Search(event, 'web'); event.preventBubble();" />

    <menuitem id="TutTB-Combined-Image" label="Image Search"
              class="menuitem-iconic" tooltiptext="Search Images"
              oncommand="TutTB_Search(event, 'image'); event.preventBubble();" />
  </menupopup>
</toolbarbutton>

有兩個值得注意的變化:在 toolbarbuttontype 屬性指定了值 menu-button ,而且有另外一行程式碼 oncommand ,我會在第六章解釋這額外的程式碼。接著注意到,這裡有跟「一般按鈕」一樣的 toolbarbuttononcommand 屬性,以及在「選單按鈕」裡的巢狀元素 menupopupmenuitem

現在,我們討論完不同的按鈕,來看看程式碼的樣子[2]

<?xml version="1.0"?>  
<overlay id="TutTB-Overlay"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
                 
    <toolbox id="navigator-toolbox">

        <toolbar id="TutTB-Toolbar" toolbarname="Tutorial Toolbar" accesskey="T"
                 class="chromeclass-toolbar" context="toolbar-context-menu"
                 hidden="false" persist="hidden">
                                 
            <toolbarbutton id="TutTB-MainMenu" type="menu"
                           tooltiptext="Tutorial Toolbar Main Menu">
                  <menupopup>
                      <menuitem label="Google Home Page" accesskey="G"
                                tooltiptext="Navigate to Google"
                                oncommand="TutTB_LoadURL('http://www.google.com/')" />

                      <menuseparator />

                      <menuitem label="Born Geek Website" accesskey="B"
                                tooltiptext="Navigate to Born Geek"
                                oncommand="TutTB_LoadURL('http://www.borngeek.com/')" />
                  </menupopup>
            </toolbarbutton>

            <toolbarbutton id="TutTB-Combined-Button" label="Search"
                           type="menu-button" tooltiptext="Combined Search"
                           oncommand="TutTB_Search(event, 'web')">
                  <menupopup>
                      <menuitem id="TutTB-Combined-Web" label="Web Search"
                                class="menuitem-iconic" tooltiptext="Search the Web"
                                oncommand="TutTB_Search(event, 'web'); event.preventBubble();" />

                      <menuitem id="TutTB-Combined-Image" label="Image Search"
                                class="menuitem-iconic" tooltiptext="Search Images"
                                oncommand="TutTB_Search(event, 'image'); event.preventBubble();" />
                  </menupopup>
              </toolbarbutton>

              <toolbarbutton id="TutTB-Web-Button" tooltiptext="Search the Web"
                             label="Web Search" oncommand="TutTB_Search(event, 'web')" />
        </toolbar>
    </toolbox>
</overlay>

下拉式編輯列 (Drop-Down Edit Box)

下一個我們要在工具列加入的是下拉式編輯列。這是用 menulist 來建立的,讓我們來看看程式碼:

<toolbaritem id="TutTB-SearchTerms-TBItem" persist="width">
    <menulist id="TutTB-SearchTerms" editable="true" flex="1"
              minwidth="100" width="250"
              onkeypress="TutTB_KeyHandler(event);">
        <menupopup id="TutTB-SearchTermsMenu" onpopupshowing="TutTB_Populate()" />
    </menulist>
</toolbaritem>

注意到,我們把 menulist 放在 toolbaritem 之中。任何一個在 toolbar 的項目都不是工具列按鈕,在 toolbaritem 裡頭的才是。也請注意到,我們為 toolbaritem 指定了 id ,且設定了寬度(藉由利用了 persist 屬性)。

menulist 才是真正用來建立下拉式編輯列的。有幾個在這個元素出現的新屬性:

  • editable - 當設定為 true 時,使用者可以在編輯列中打字。
  • flex - 使這個元素是可變動的。The value is an integer specifying the relative "flexibility" of the element in relation to other toolbar elements. 設定值 2 代表著設定值 1 的兩倍寬,0 則是不能變動的固定寬度。
  • minwidth - 最小寬度,單位為像素。
  • width - 初始寬度,單位為像素。
  • onkeypress - 當使用者輸入文字時,用來執行的程式碼。

你可以在 XUL Planet menulist element's attributes 看到完整的參考文獻。

跟我們之前看到的「選單按鈕」一樣,在 menulist 裡的 menupopup 包含了 menuitem 元素。The onpopupshowing event is fired right before the drop-down box is shown to the user. The code snippet shown is a function that we will write to dynamically populate the menu with items, 這部份我們會稍後提及。如果你樂意的話,你可以加入靜態的選單,這個過程跟「選單按鈕」是一樣的。

現在,這個套件已經變得更具體一點了,讓我們來看看程式碼[3]

<?xml version="1.0"?>
<overlay id="TutTB-Overlay"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
         
    <toolbox id="navigator-toolbox">
    
        <toolbar id="TutTB-Toolbar" toolbarname="Tutorial Toolbar" accesskey="T"
                 class="chromeclass-toolbar" context="toolbar-context-menu" 
                 hidden="false" persist="hidden">
                 
            <toolbarbutton id="TutTB-MainMenu" type="menu"
                           tooltiptext="Tutorial Toolbar Main Menu">
                <menupopup>
                    <menuitem label="Google Home Page" accesskey="G"
                              tooltiptext="Navigate to Google"
                              oncommand="TutTB_LoadURL('http://www.google.com/')" />
                    
                    <menuseparator />
                    
                    <menuitem label="Born Geek Website" accesskey="B"
                              tooltiptext="Navigate to Born Geek"
                              oncommand="TutTB_LoadURL('http://www.borngeek.com/')" />
                </menupopup>
            </toolbarbutton>
            
            <toolbaritem id="TutTB-SearchTerms-TBItem" persist="width">
                <menulist id="TutTB-SearchTerms" editable="true" flex="1"
                          minwidth="100" width="250"
                          onkeypress="TutTB_KeyHandler(event);">
                    <menupopup id="TutTB-SearchTermsMenu" onpopupshowing="TutTB_Populate()" />
                </menulist>
            </toolbaritem>
            
            <toolbarbutton id="TutTB-Combined-Button" label="Search"
                           type="menu-button" tooltiptext="Combined Search"
                           oncommand="TutTB_Search(event, 'web')">
                <menupopup>
                    <menuitem id="TutTB-Combined-Web" label="Web Search"
                              class="menuitem-iconic" tooltiptext="Search the Web"
                              oncommand="TutTB_Search(event, 'web'); event.preventBubble();" />
                
                    <menuitem id="TutTB-Combined-Image" label="Image Search"
                              class="menuitem-iconic" tooltiptext="Search Images"
                              oncommand="TutTB_Search(event, 'image'); event.preventBubble();" />
                </menupopup>
            </toolbarbutton>
            
            <toolbarbutton id="TutTB-Web-Button" tooltiptext="Search the Web"
                           label="Web Search" oncommand="TutTB_Search(event, 'web')" />
        </toolbar>
    </toolbox>
</overlay>

Resizing Gripper

還記得之前包含在 menulisttoolbaritem 元素所提到的 persist 屬性嗎?設定這個屬性以讓我們在瀏覽器使用期間,可以儲存搜尋列的寬度。為了讓使用者可以改變寬度,我們要提供 resizing gripper 。用來做這件事的元素是 splitter ,讓我們來看看程式碼:

<splitter id="TutTB-ResizeSplitter" state="open" collapse="none"
          resizebefore="closest" resizeafter="farthest"
          tooltiptext="Resize the Search Box">
    <vbox id="TutTB-ResizeBar" />
</splitter>

這是 splitter 的屬性:

  • state - 指定 splitter 是否摺疊(隱藏)內容。A value of "open" indicates that the content either before or after the splitter (in our case both), is visible.
  • collapse - 決定哪邊的 splitter 被隱藏。我們使用 none ,不讓任何一邊的 splitter 被隱藏。
  • resizebefore - 當 splitter 改變時,指定 splitter 左邊的哪個元素必須被重新調整。當 splitter 移動時,使用 closest 來重新調整最靠近 splitter 左邊的編輯列。
  • resizeafter - 當 splitter 改變時,指定 splitter 右邊的哪個元素必須被重新調整。在這個範例裡,我們使用 farthest 來重新調整最右邊的彈性空間。

vbox 是用來設定樣式的,我們會在第五章討論面板時,提到這點。 你可以在 XUL Planet splitter element's attributes 看到更完整的參考文獻。

讓我們來看看包含 splittertoolbaritem 的覆載程式碼[4]

<?xml version="1.0"?>
<overlay id="TutTB-Overlay"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
         
    <toolbox id="navigator-toolbox">
    
        <toolbar id="TutTB-Toolbar" toolbarname="Tutorial Toolbar" accesskey="T"
                 class="chromeclass-toolbar" context="toolbar-context-menu" 
                 hidden="false" persist="hidden">
                 
            <toolbarbutton id="TutTB-MainMenu" type="menu"
                           tooltiptext="Tutorial Toolbar Main Menu">
                <menupopup>
                    <menuitem label="Google Home Page" accesskey="G"
                              tooltiptext="Navigate to Google"
                              oncommand="TutTB_LoadURL('http://www.google.com/')" />
                    
                    <menuseparator />
                    
                    <menuitem label="Born Geek Website" accesskey="B"
                              tooltiptext="Navigate to Born Geek"
                              oncommand="TutTB_LoadURL('http://www.borngeek.com/')" />
                </menupopup>
            </toolbarbutton>
            
            <toolbaritem id="TutTB-SearchTerms-TBItem" persist="width">
                <menulist id="TutTB-SearchTerms" editable="true" flex="1"
                          minwidth="100" width="250"
                          onkeypress="TutTB_KeyHandler(event);">
                    <menupopup id="TutTB-SearchTermsMenu" onpopupshowing="TutTB_Populate()" />
                </menulist>
            </toolbaritem>
            
            <splitter id="TutTB-ResizeSplitter" state="open" collapse="none"
                      resizebefore="closest" resizeafter="farthest"
                      tooltiptext="Resize the Search Box">
                <vbox id="TutTB-ResizeBar" />
            </splitter>
            
            <toolbaritem flex="0">
            
                <toolbarbutton id="TutTB-Combined-Button" label="Search"
                               type="menu-button" tooltiptext="Combined Search"
                               oncommand="TutTB_Search(event, 'web')">
                    <menupopup>
                        <menuitem id="TutTB-Combined-Web" label="Web Search"
                                  class="menuitem-iconic" tooltiptext="Search the Web"
                                  oncommand="TutTB_Search(event, 'web'); event.preventBubble();" />
                    
                        <menuitem id="TutTB-Combined-Image" label="Image Search"
                                  class="menuitem-iconic" tooltiptext="Search Images"
                                  oncommand="TutTB_Search(event, 'image'); event.preventBubble();" />
                    </menupopup>
                </toolbarbutton>
                
                <toolbarbutton id="TutTB-Web-Button" tooltiptext="Search the Web"
                               label="Web Search" oncommand="TutTB_Search(event, 'web')" />
            </toolbaritem>
        </toolbar>
    </toolbox>
</overlay>

In order to prevent a slightly annoying cosmetic problem with the resizing gripper, 我們還需要建立額外的 toolbaritem ,這與我們剛剛在「選單按鈕」中的搜尋按鈕所做的一樣。 再一次確定 flex 屬性的值為 0 。This will prevent our menu button from being pushed off the left side of the toolbar when the gripper is dragged all the way to the left.

接著,讓我們再來增加兩個項目。首先,將 toolbarseparator 放置在最後兩個按鈕中,目的是為了裝飾。再來,將 toolbarspring 放置在最後的 toolbaritem 元素之後。This spring will allow us to drag the resizer all the way to the right, so that we can see the full resizing effect in action. 這兩個標示是很簡單的,像是這樣:

<toolbarseparator />

<toolbarspring />

讓我們來看看完整的覆載範例[5]

<?xml version="1.0"?>
<overlay id="TutTB-Overlay"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

    <toolbox id="navigator-toolbox">

        <toolbar id="TutTB-Toolbar" toolbarname="Tutorial Toolbar" accesskey="T"
                 class="chromeclass-toolbar" context="toolbar-context-menu"
                 hidden="false" persist="hidden">

            <toolbaritem flex="0">
                <toolbarbutton id="TutTB-MainMenu" type="menu"
                               tooltiptext="Tutorial Toolbar Main Menu">
                    <menupopup>
                        <menuitem label="Google Home Page" accesskey="G"
                                  tooltiptext="Navigate to Google"
                                  oncommand="TutTB_LoadURL('http://www.google.com/')" />

                        <menuseparator />

                        <menuitem label="Born Geek Website" accesskey="B"
                                  tooltiptext="Navigate to Born Geek"
                                  oncommand="TutTB_LoadURL('http://www.borngeek.com/')" />
                    </menupopup>
                </toolbarbutton>
			</toolbaritem>

			<toolbaritem id="TutTB-SearchTerms-TBItem" persist="width">
				<menulist id="TutTB-SearchTerms" editable="true" flex="1"
                          minwidth="100" width="250"
                          onkeypress="TutTB_KeyHandler(event);">
					   <menupopup id="TutTB-SearchTermsMenu" onpopupshowing="TutTB_Populate()" />
				</menulist>
			</toolbaritem>

			<splitter id="TutTB-ResizeSplitter" state="open" collapse="none"
                      resizebefore="closest" resizeafter="farthest"
                      tooltiptext="Resize the Search Box">
				<vbox id="TutTB-ResizeBar" />
			</splitter>

			   <toolbaritem flex="0">

			<toolbarbutton id="TutTB-Combined-Button" label="Search"
                           type="menu-button" tooltiptext="Combined Search"
                           oncommand="TutTB_Search(event, 'web')">
				<menupopup>
					<menuitem id="TutTB-Combined-Web" label="Web Search"
                              class="menuitem-iconic" tooltiptext="Search the Web"
                              oncommand="TutTB_Search(event, 'web'); event.preventBubble();" />

					   <menuitem id="TutTB-Combined-Image" label="Image Search"
                              class="menuitem-iconic" tooltiptext="Search Images"
                              oncommand="TutTB_Search(event, 'image'); event.preventBubble();" />
				</menupopup>
			</toolbarbutton>

			<toolbarseparator />

			<toolbarbutton id="TutTB-Web-Button" tooltiptext="Search the Web"
                           label="Web Search" oncommand="TutTB_Search(event, 'web')" />
			</toolbaritem>
		
		 <toolbarspring />

		</toolbar>
	</toolbox>
</overlay>  
個人工具