firefox附加組件開發者指南(三)——XUL簡介(中)

XUL中可用的窗體部件

根元素

XUL文檔使用不同的根元素來實現不同的目的。本節我們將會看到三種典型的根元素:window、page和dialog。
根元素使用windowtype屬性作爲這種類型的窗口的標識符。例如,Firefox使用navigator:browser作爲其瀏覽器窗口的windowtype,使用Browser:Preference作爲其選項窗口的windowtype。使用將會在第四章描述的方法,我們會看到是如何使用這些值來獲取窗口的。
一個窗口在屏幕上的大小和位置可以使用width、height、screenX、screenY(單位都是像素)等屬性來指定。使用前面描述的persist屬性,你可以簡單的存儲一個窗口的尺寸和位置。Firefox也是使用這一方法來存儲其窗口的尺寸和位置的。

常規根元素

window
至今爲止在例子中出現的window元素是用來定義一個普通窗口的。這顯示了用於Firefox瀏覽器窗口、書籤管理器窗口一起很多其他窗口種類相同的窗口。一般的,你可以使用window元素作爲你的根元素。
page
對於側邊欄以及其他在窗口框架內部打開的XUL文檔,使用page元素作爲根元素。除了與window元素的目的不同之外,其功能與window元素沒有任何不同。

用於對話框窗口的根元素

dialog
創建選項對話框、確認對話框等的時候使用dialog元素。這個元素有很多屬性,可以簡單的顯示控件(按鈕,等等)這樣的窗體小部件以及適應於任何所運行的平臺的佈局。
例如,windows將OK按鈕放在左邊而cancel按鈕放在右邊,而Mac OS X的佈局方式卻不一樣。這就是Firefox本身使用在bookmark屬性以及其他對話框中的方式。
對話框中使用的按鈕
一個dialog元素會在其底部顯示很多按鈕,如表1所示,有4種類型的按鈕可以顯示,你可以將你想要顯示的按鈕名稱作爲逗號隔開的列表寫在buttons屬性之後。
表1:對話框窗口中可以顯示的按鈕類型

按鈕名稱

描述

accept

OK按鈕

cancel

Cancel按鈕

help

Help按鈕

disclosure

提示三角或者按鈕。這用來方便用戶切換顯示附加信息

另外,還有兩個特殊的按鈕,extra1和extra2.這兩個按鈕的標籤使用buttonlabelextra1和buttonlabelextra2屬性來進行設置,這些屬性的值是任意的字符串。
當由事件處理器使用按鈕名ondialog<button name>定義了的按鈕中有按鈕按下的時候相應的行爲就會發生。如果這些事件處理器沒有定義,不管點擊accept按鈕還是cancel按鈕都會關閉對話框。清單9中展示了一個簡單的對話框例子,圖5展示了其輸出。
清單9:一個對話框
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="chrome://global/skin/"?>
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="My Dialog" buttons="accept,cancel"
ondialogaccept="saveValues(); window.close();"
ondialogcancel="window.close();">
<checkbox label="My Option"/>
</dialog>

圖5:清單9的輸出

注意:The functions behind the dialog elements discussed here require "XPConnect privileges," which are discussed in Chapter 4, so this example will only run correctly if it can run as Firefox code itself or installed extension code. Please be aware that if you attempt to open this sample directly in Firefox, it will not run correctly.

菜單

具有層次結構的下拉菜單是經常在應用程序或者網絡服務中使用的訪問功能的用戶接口的一部分。在過去,使用聯合HTML和javascript的方式來產生這樣的複雜的UI結構,但是在XUL中,僅僅通過使用標籤就可以實現了。

創建菜單

清單10展示瞭如何將menu元素以及其相關的元素進行聯合。其輸出如圖6所示。
清單10:一個菜單的定義

<menubar>
<menu label="Menu 1">
<menupopup>
<menuitem label="Item 1"/>
<menuitem label="Item 2"/>
<menuseparator/>
<menuitem label="Item 3"/>
<menu label="Submenu">
<menupopup>
<menuitem label="Item 4"/>
<menuitem label="Item 5"/>
</menupopup>
</menu>
</menupopup>
</menu>
</menubar>

圖6:清單10的輸出

菜單中的每個菜單項都是用menuitem標籤來進行標記的。使用menuseparator元素向一組菜單項中插入一個分隔符。menu和menuitem元素都有label屬性以設置它們的標籤。

將menu元素插入到menubar元素中科院創建多個菜單。你可以簡單的通過爲menu元素插入menupopup來創建菜單的層次。
你甚至可以通過添加class="menuitem-iconic"到一個menuitem元素中並將其src屬性設置爲一個圖像的URI來使菜單顯示一個圖標。圖7展示了這樣顯示的例子。
圖7:帶有圖標的菜單項

當選擇菜單項的時候執行命令

與動態HTML非常相似,事件處理器用來在一個菜單項選中的時候執行命令。在HTML中爲對鼠標和鍵盤輸入進行響應,典型的是使用onclick事件處理器來響應鼠標點擊,使用onkeypress事件處理器來對鍵盤輸入進行響應。
XUL也可以使用這些事件處理器,但是XUL還提供了oncommand這個特殊的事件處理器來處理那些具有特定含義的行爲,如:左鍵點擊的選擇(或者系統設置爲習慣左手時的右鍵點擊)或者回車鍵的選擇。清單11顯示了一個oncommand事件處理器的使用例子。除了menuitem元素之外,oncommand也可以用於按鈕或其他輸入控件。
清單11:oncommand事件處理器

<menuitem label="Open project page" oncommand="loadURI(this.value)"
value="http://mozilla.org/"/>

由於gecko引擎實現了2級DOM的事件處理器,你可以像清單12一樣定義動態的事件偵聽器。
清單12:使用動態事件偵聽器的添加與刪除

var item = document.getElementById('menu-item-custom');
function handleCommandEvent(aEvent) {
alert('OK');
item.removeEventListener('command', handleCommandEvent, false);
item.parentNode.removeChild(item);
}

item.addEventListener('command', handleCommandEvent, false);

特殊菜單項

與HTML中的input元素非常相似,menuitem可以通過設置他們的type屬性像單選按鈕和複選按鈕一樣進行操作。
Checkbox
爲menuitem元素添加type="checkbox"會在它被選中的時候顯示選中標記,並在再次選擇的時候顯示未選中。帶有複選框的菜單項的例子可以參考Firefox的view菜單,有菜單項以顯示或者隱藏工具欄和側邊欄。當一個菜單項被選中的時候,會設置屬性checked="true".
radiobutton
爲多個menuitem元素設置type="radio" 並將他們的name屬性設置爲相同則選擇其中的一個就無法選擇其他的了,這與HTML中的單選按鈕非常相似。Firefox中view菜單下的Character Encoding子菜單項就是一個例子。選中的單選按鈕具有屬性selected="true" 。
上下文菜單
屬性context是用來顯示上下文菜單或者說快捷鍵菜單的,即,一個定製的菜單會在右鍵點擊某個元素的時候顯示。
之前我們將menupopup子元素放在一個menu元素內部;這裏,我們在menu元素的外面使用它。menupopup是根元素的一個直接子元素,我們在其他XUL元素中使用其id屬性值作爲context的值來檢索它。當我們右鍵點擊這個XUL元素的時候,就可以通過其id來引用這個menupopup,並在上下文菜單中顯示其內容。清單13展示了一個例子。
清單13:上下文菜單

<button label="Send" oncommand="send();" context="button-context"/>
<menupopup id="button-context">
<menuitem label="Send with new tab" oncommand="sendInNewTab();"/>
</menupopup>

按鈕
用戶可以點擊的按鈕使用button元素來定義,圖8顯示了一個帶有圖標的按鈕,可以通過定義一個圖像的URI作爲其image屬性的值來實現。
使用icon屬性而不使用image屬性一可以顯示帶有系統標準圖標的按鈕。
Icon屬性的可能值在表2中給出。

圖8:一個帶有圖像的按鈕

Icon屬性值

icon屬性值

accept

close

cancel

print

help

add

open

remove

save

refresh

find

go-forward

clear

go-back

yes

properties

no

select-font

apply

select-color

表2:icon屬性的值
工具欄按鈕
toolbarbutton元素是用來定義工具欄按鈕的元素。典型的這是放在一個定義工具欄的toolbar元素內部的,但是也可以放在其他位置。
這幾乎與button元素一樣,但是如清單14所示,你可以通過使用type屬性來改變toolbarbutton元素的行爲。這在圖9中的輸出可以看出來。
清單14:
<toolbar>
<toolbarbutton label="Checkbox Type" type="checkbox" image="firefox.png"/>
<toolbarbutton label="Menu Type" type="menu" popup="button-popup" image="firefox.png"/>
<toolbarbutton label="Menu Button Type" type="menu-button" popup="button-popup" image="firefox.png"/>
<menupopup id="button-popup">
<menuitem label="Item 1"/>
<menuitem label="Item 2"/>
<menuitem label="Item 3"/>
</menupopup>
</toolbar>

圖9:清單14的輸出

-複選框類型的工具欄按鈕

指定type=”checkbox”的結果是一個在點擊之後下陷、再次點擊之後彈起的按鈕。按鈕在其下陷狀態具有checked=”true”的屬性。這是用作歷史和書籤按鈕的按鈕,可以用來定製工具欄。
-菜單類型的工具欄按鈕
指定type=”menu”並添加一個menupopup子元素(在firefox3中你也可以使用pannel元素),或者設置popup屬性爲一個位於其他地方的彈出菜單的引用將會在按鈕按下的時候顯示一個彈出菜單。這裏,button-click不是其輸入,而是將command事件在按鈕被選中的時候彈出菜單項。這是用在標籤欄右邊的列出所有標籤的按鈕類型。
-菜單按鈕類型的工具欄按鈕
指定type=”menu-button”的結果是一個特殊的結合了正常工具欄按鈕和具有type=”menu”類型的按鈕特性的按鈕,因此點擊這個按鈕的時候會產生一個command事件。這是後退和前進按鈕的類型;

輸入控件

XUL包含很多與HTML的form相關元素非常相似的輸入控件元素。

標籤

label元素用於獨立的文本標籤,如描述性文字,value屬性的值就是將要顯示的文本。control屬性的值是其他XUL元素的id,有了這個id,點擊那個label或者它獲得焦點的時候就可以將焦點傳遞到那個XUL元素。
這也可以用來顯示一長段文本。如果你想要插入自動換行的長字符串,可以使用flex屬性如清單15所示,這樣就會自動的進行擴展。這種情況下不要使用value屬性來設置文本,而要將這些文字作爲元素的內容。圖10顯示了這個清單的輸出結果。
清單15:label中處理長字符串

<hbox>
<label flex="1">
Proceeding with this action will send your personal information to a server. Are you sure you want to proceed?
</label>
</hbox>

圖10:清單15的輸出

簡潔標籤

在label元素和其他XUL元素的label屬性之間,XUL還有很多使用標籤的元素。一個常用的可以對所有XUL元素設置的屬性是crop屬性。
通過對具有label屬性的元素或者label元素使用crop屬性,標籤的一部分會在文本寬度大於其父元素的寬度時被省略號(…)代替。被裁掉大部分可以通過設置其屬性值爲start、center、或者end來控制。
你可以使用CSS的max-width屬性來設置一個box的最大寬度。

複選框

圖11所示的複選框是使用checkbox元素來標記的,黨其處於選中狀態時,其checked屬性設爲true。
清單16:不同狀態的複選框

<checkbox label="Checkbox checked" checked="true"/>
<checkbox label="Checkbox unchecked" checked="false"/>

圖11:清單16的輸出

單選按鈕

在HTML中的單選按鈕是多個輸入元素通過指定他們都具有相同的name屬性作爲一組。在XUL中,這是結合兩個元素radiogroup和radio來表達的。通過插入多個radio元素到一個radiogroup元素的內容中就可以設置排他的選項,當前選擇的radio元素將會有selected=”true”的設置。
radio元素可以通過設置其value屬性來進行唯一識別。黨那個radio元素被選擇的時候,其value屬性就會複製到radiogroup中,因此你可以簡單的獲取radiogroup元素的value值來檢查選中的單選按鈕。
有時候你可能需要將radio元素放在radiogroup元素的外面。通過結合hbox和vbox可以寫出與清單17相似的代碼,就會出現如圖12所示的輸出。
清單17:一個單選按鈕的複雜佈局

<radiogroup orient="vertical">
<hbox>
<radio label="Top Left"/>
<radio label="Top Right"/>
</hbox>
<hbox>
<radio label="Bottom Left"/>
<radio label="Bottom Right"/>
</hbox>
</radiogroup>

圖12:清單17的輸出

文本框

使用textbox元素來接受文本輸入。在HTML中,有兩個獨立的元素——用於單行文本的input,和用於多行文本的textarea 。但是XUL中這兩種功能都是由textbox來處理的,如清單18所示,其輸出的結果如圖13.
textbox元素使用value屬性來設置其默認的內容;用戶輸入的內容也可以使用value屬性來獲取。聲明maxlength屬性爲一個正整數值可以設置設置最大的字符數。設置type=”password”將會使得textbox變爲一種特殊的密碼輸入框,其中輸入的字符會被隱藏。
每個字符輸入到textbox中都會產生一個input事件。如果你使用oninput事件處理器,你就可以實時的實現與用戶相應的命令。
清單18:文本框例子

<vbox align="start">
<textbox/>
<textbox multiline="true" rows="5" cols="15"/>
</vbox>

圖13:清單18的輸出

自動完成

爲textbox元素添加type=”autocomplete”可以爲這個文本框啓用一個自動完成的功能。
注意要實際的使用這個功能,你必須同時爲自動完成文本要使用的autocompletesearch屬性指定一個搜索目標。如果你想要使用地址欄的歷史,可以將這個值設爲history;如果你想要使用搜索欄的歷史,則可以設爲search-history;如果你想要設置爲其他表格的輸入歷史,使用form-history;這個屬性可以有一個值,也可以用空格將多個值隔開以接受多個值
同樣的,爲了能夠實際的讀取一個歷史記錄用來進行自動完成,你需要XPConnect權限,這會在第四章中描述。

菜單列表

使用menulist元素來創建一個從下拉列表中做出選擇的控件,如清單19所示,這是通過聯合menupopup元素來實現的,其產生的結果如圖14所示。
點擊就會出現下拉列表;黨一個項被選擇的時候,那一項的label和value屬性就會複製到menulist的label和value屬性。默認選擇的是第一個菜單項,但是任何菜單都可以通過添加selected=”true”來設置爲默認選中。
清單19:菜單列表示例

<menulist>
<menupopup>
<menuitem label="Item 1" value="1"/>
<menuitem label="Item 2" value="2"/>
<menuitem label="Item 3" value="3"/>
</menupopup>
</menulist>

圖14:清單19的輸出

通過添加editable=”true”到menulist中,可以接受任意的文本輸入來輔助進行列表選擇,就像文本處理器中經常使用的用來選擇字體的菜單一樣。

特殊元素

嵌入圖像

除了直接在javascript代碼中寫事件處理器之外,XUL還支持使用script元素將腳本嵌入到XUL文檔中,就像HTML一樣;這樣就可以讀取外部腳本文件也可以直接將代碼放在script元素內容中。
如果你在一個頁面中嵌入腳本,你需要將你的代碼括在一個CDATA段中,如清單20所示;這樣可以避免由讀取&加其他字符開頭的實體引用時出現錯誤。
清單20:在XUL代碼中嵌入腳本

<script type="application/javascript"><![CDATA[
var nodes = gBrowser.mTabContainer.childNodes;
for (var i = 0; i < nodes.length; i++)
alert(nodes[i].label);
]]></script>

注意:儘管嵌入javascript是可以的,但一般還是推薦將javascript代碼寫到一個獨立的外部文件中。

Browser 和 tabbrowser

XUL允許使用內聯幀(frame)。你可以將一個iframe元素的src屬性設置爲另外一個XUL文件或者網頁的URI,就會顯示在那裏。但是在實際中iframe基本上很少用於XUL中,經常使用的是browser元素。
browser元素是一個更強大的內聯幀,具有網頁瀏覽器的所有基本功能。與iframe不同,一個browser元素有前進後退的功能也包含有阻止嵌入在frame內部的腳本訪問frame之外的位置的能力。對於構建與外部網頁有關的應用程序,browser是一個更加安全和方便的途徑。
tabbrowser元素比browser元素能力更加強大,因爲它包含了Firefox中標籤處理特性的基本內容。要使用它需要XPConnect權限,與自動完成相同。這會在第四章中描述。
打開一個頁面
如果你爲browser元素的src屬性指定一個URI值,就會默認打開這個URI。改變c屬性的值,就可以動態的打開不同的網頁或者XUL文檔。
後退、前進、重新載入等功能都可以通過調用goBack、goForward和reload方法來實現。使用stop方法可以停止加載當前正在加載的頁面。
訪問限制
使用HTML的frame和iframe元素定義的幀,可以通過子幀用window對象的parent和top屬性訪問其父幀以及其祖先幀。對於可以打開任意網頁的應用程序,這會傳遞給網頁一個腳本來訪問XUL文檔的幀,也可能會創建危險的可能導致個人信息泄露的頁面。
爲安全性考慮,你可以通過在browser元素上聲明type=”content”來設置訪問限制。如果你這樣做了,任何打開的網頁都會將其視爲最頂層的幀。如果你開發的是一個具有打開網頁接口的應用程序,我推薦你使用這個聲明以限制網頁訪問父幀。
在某些環境中,你可能會聲明type=”content-primary”。一個具有這種聲明的browser元素會被認爲是與其他XUL文檔不同的特殊瀏覽器,這樣窗口對象就可以通過使用window.content屬性來訪問其網頁並進行顯示。在Firefox中,被當做其內容區的活動標籤就是使用type=”content-primary”聲明瞭的browser元素。

鍵盤快捷鍵

要在基於DHTML的接口中實現鍵盤快捷鍵(按住修飾鍵如ctrl或者shift的時候按某個鍵),你需要一個攔截鍵盤輸入的腳本。
在XUL中,你可以很簡單的通過使用key元素來定義鍵盤快捷鍵,如清單21所示。
清單21:定義鍵盤快捷鍵

<key id="key-save" key="s" modifiers="accel,shift" oncommand="save();"/>
<key id="key-scroll-up" keycode="VK_PAGE_UP" oncommand="advanceFocus(-1);"/>

要讓字母、數字、符號或空格鍵作爲觸發器,就可以將那個字符聲明爲key屬性的值。你既可以使用大寫字母也可以使用小寫字母,都會進行同樣的處理。
對於那些特殊鍵作爲觸發器的可以使用keycode屬性,併爲其賦予合適的鍵值作爲其值。通常,你可以對任何鍵使用鍵值;最常使用的一些鍵值如表3所示。
表3:典型的鍵值名稱

Key

Keycode name

Return

VK_RETURN

Enter

VK_ENTER

Backspace

VK_BACK_SPACE

Delete

VK_DELETE

Escape

VK_ESCAPE

VK_UP

VK_DOWN

VK_LEFT

VK_RIGHT

使用修飾鍵
使用modifiers屬性,將下面的一個或者多個值用逗號隔開作爲modifiers屬性的值:"control", "alt", "shift", 以及"meta"這樣就可以限制鍵盤快捷鍵只在這些修飾鍵同時按下的時候才起作用。Windows和linux系統的標準修飾鍵是ctrl鍵;在Mac OS上是command鍵。一個簡單的自動使用這個修飾鍵的方法是將修飾鍵設置爲”accel”,這在windows和linux系統上對應爲control鍵,在Mac OS上對應爲command鍵。
Note: The "meta" key is the Command key on Mac OS X (the one with the cloverleaf design on it).
key元素本身從來不會顯示在屏幕上。爲了顯示定義了的鍵盤快捷鍵如圖15所示,可以將這個key元素的id對應到menu或者menuitem元素的key屬性上。
圖15:原文缺少該圖

與box佈局相關的元素

XUL包含很多用來嚴格組織屏幕小部件佈局的元素。

spacer

如果你想要開啓按鈕之間的空白可以使用spacer元素。你可以使用flex屬性或者style屬性來使空白擴張或者設置爲某一個值。

grid

與table元素在HTML中對內容進行佈局一樣,你可以在XUL中使用grid元素,如清單22所示,首先聲明列數,然後定義每一行的內容。這個例子的輸出如圖16所示。你也可以先聲明行,然後通過列來定義內容。
HTML中table可以使用的rowspan和colspan屬性在XUL中不可用。
清單22:使用grid進行佈局

<grid>
<columns>
<column/>
<column flex="1"/>
</columns>
<rows>
<row align="center">
<label value="User ID"/>
<textbox/>
</row>
<row align="center">
<label value="Name"/>
<textbox/>
</row>
</rows>
</grid>

圖16:清單22的輸出

stack

使用stack元素可以將多個部件疊加起來。與通常的box元素不同,stack元素中的所有元素都是一個堆在另外一個上面的,從最下面開始向上疊加。清單23展示了一個溫度計類型的進度條的例子,其輸出如圖17所示。
清單23:用stack進行重疊

<stack>
<progressmeter mode="normal" value="50"/>
<hbox align="center">
<label value="In progress…"/>
</hbox>
</stack>

圖17:清單23的輸出

tab

使用tab元素可以將多個頁面分開,就像屬性頁對話框中使用的那樣;使用tabbox元素裏對相關的元素進行分組。清單24舉例說明,圖18是其輸出。
清單24:使用tab

<tabbox>
<tabs>
<tab label="tab1"/>
<tab label="tab2" selected="true"/>
</tabs>
<tabpanels>
<tabpanel>
<checkbox label="check1"/>
</tabpanel>
<tabpanel orient="vertical">
<checkbox label="check2"/>
<checkbox label="check3"/>
</tabpanel>
</tabpanels>
</tabbox>

圖18:清單24的輸出



發佈了32 篇原創文章 · 獲贊 83 · 訪問量 29萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章