XUL ファイルと XUL オーバーレイ
オーバーレイは、UI に追加するコンテントを記述するために使用する XUL ファイルです。 オーバーレイは、UI 要素を定義して、なんらかの更新や拡張を行うのと同じ効果を加えるためによく利用されますが、 それ以外にもたくさんの用途に利用することが可能です。 オーバーレイでは、以下のような汎用のメカニズムを提供しています。
- 追加コンポーネントの UI を追加 (既述)
- UI の全体を再供給することなしに、XUL ファイルの小さな断片をオーバーライド
- UI の特定部分の再利用
XUL ファイルとオーバーレイは、単一のマスター文書を既述するために一緒に動作することになります。 しかしながら、どのような種類の XUL コンテントを「ベースの」XUL ファイルに置き、どのような種類の XUL コンテントはオーバーレイに置くべきであるかについての正式な規定はありません。 XUL オーバーレイでは、基本版の UI では表示しない、追加のコンポーネントようなものを汎用的に定義することになります。 つまり、プラグインや、ブラウザの拡張機能、または他のアプリケーションからブラウザに供給される新しい UI 要素といった要素が、オーバーレイファイルの中で定義されることになるはずです。 例えば、メディアプレイヤーのプラグインのインストール時には、下記のように多数の新しいアイコンやメニュー項目がインターフェイスに追加されることになります。
navigatorOverlay.xul
ファイルか、分離した navigatorSSPOverlay.xul
ファイル (ナビゲータパッケージの基本的な UI は navigator.xul
で定義されています) では、これらの新しいプラグイン要素は、下記のように要素の集まりやサブツリーとして定義されることになります。
<menuitem name="Super Stream Player"/> <menupopup name="SS Favorites"> <menuitem name="Wave" src="mavericks.ssp"/> <menuitem name="Soccer" src="brazil_soccer.ssp"/> </menupopup> <titledbutton id="SSP" crop="right" flex="1" value="&SSButton.label;" onclick="FireSSP()"/>
オーバーレイと ID 属性
レイアウトエンジンでは ID 属性を使用して、オーバーレイファイル中の要素をマージ (併合) する場所を決定します。
基本となる XUL ファイルと XUL オーバーレイでは、同じ ID を両方に使用します。
そうしなければ、新規の要素はまったく表示されません。
このため、ベースのファイルで、オーバーレイの要素の親ノードになるものに対して ID が設定されていないものがあれば、付けておく必要があります。
例えば、以下に示す XUL のサブツリー中の <menu
> 要素は、Super Stream Player のメニュー項目の親になるべきものであるため、「file_menu」という ID が設定されています。
<menu id="file_menu"> <menuitem name="New"/> <menuitem name="Open"/> <menuitem name="Save"/> <menuitem name="Close"/> </menu>
オーバーレイファイルでは、新規の項目をオーバーレイファイルと同じ ID を持ったタグの子要素になるように作成することで「同期させる」ことが可能です。
レイアウトエンジンは、
タグ直下の ID 付きの要素を取り出し、ベースの XUL ファイルの関連するノードに対してマージを行います。
以下に、上記の例に Super Stream Player のメニュー項目を 1 つ加えるための XUL オーバーレイファイルの完全な例を示します。
overlay
<?xml version="1.0"?> <overlay id="singleItemEx" xmlns:html="https://www.w3.org/1999/xhtml" xmlns="https://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <menu id="file_menu"> <menuitem name="Super Stream Player"/> </menu> </overlay>
ベースのファイルにある
と、オーバーレイファイルの menu
以下にあるサブツリーは、同等のものとして処理されるということを補足しておきます。
つまり、マージされた項目では自由にサブツリーの入れ子を構成することが可能であるため、
新規に追加するポップアップメニューから、別のサブメニューをポップアップさせるようにしたり、
既存のツールバーをオーバーレイするだけでなく、
Netscape Communicator が個人用ツールバーをロケーションバーなどの下に置くように、
既存のツールバーの下に追加のツールバー置いたりすることが可能です。
オーバーレイでは、オーバーレイファイルの overlay
タグの下の要素の ID と、ベースのファイル中で同じ ID を持つタグについて、
任意の適切なサブツリーのマージをサポートしています。
overlay
このとき、ID の無い要素をオーバーレイすることはできないため、
load
ハンドラの中で必要な要素を調整するために
DOM メソッドを利用する必要があります。
オーバーレイをロードする
オーバーレイは、明示的または、動的にロードすることが可能です。 オーバーレイを明示的にロードするということは、ベースのファイルがロードされる場合には、いつもオーバーレイが有効になるようにしたいという意図があることを意味しています。 オーバーレイの主な利用目的は、基本的なパッケージに追加要素やコンポーネントのための UI を提供することであるため、 明示的なロードを行う場合に、そのオーバーレイで付加的な UI 要素を定義すると、何らかの問題が発生する可能性があります。
オーバーレイを明示的にロードする
マスター文書にオーバーレイファイルを明示的にロードするためには、処理命令を使用します。 以下の処理命令を、ベースとなるファイルの DOCTYPE 宣言の前に挿入することにより、レイアウトエンジンにその名前のオーバーレイファイルをロードすることを指示します。
<?xul-overlay href="chrome://component/content/componentOverlay.xul"?>
ここで、component は、オーバーレイされるパッケージの名前になります。
(例: chrome://navigator/content/navigatorOverlay.xul
)
レイアウトエンジンは、任意のオーバーレイファイルをロードしてから、結果の XUL ドキュメントを処理するため、 メニューやボックス、テーブルやフォームを逐次挿入していくことに関連する問題は回避されます。 また、マスター文書には、任意の数のオーバーレイをロードすることができ、オーバーレイが他のオーバーレイをロードすることも可能です。 オーバーレイは、マスター文書に重ね合わせられるために、 スクリプトのスタイルシートのスコープに関する曖昧性は存在しません。 オーバーレイによってロードされたスタイルシートとスクリプトは、単純にマスター文書全体に適用されます。
オーバーレイを動的にロードする
chrome レジストリによって、XUL オーバーレイを (必要な場合にだけ) 動的にロードすることが可能になります。 chrome レジストリとは、利用者に固有の情報を永続化して格納するための特殊な RDF データソースで、 ブラウザとともにインストールされたコンポーネントや追加パッケージについての情報が含まれています。 上記の例で示した「Super Stream Player」のようなコンポーネントはここに登録されて、 コンポーネントに結びつけられたオーバーレイは自動的にロードされることになります。 コンポーネントが表示されない場合は、ベースとなるファイルだけがロードされます。
オーバーレイを実行時にロードする
Firefox 1.5 などの Gecko 1.8 ベースのアプリケーションでは、document.loadOverlay 関数を利用することで、オーバーレイを実行中にロードする方法もサポートしています。
TODO: elaborate
オーバーレイとスキン
ベースファイルとは異なり、オーバーレイからは、そのパッケージのマスタースキンファイルのロードは行わせるべきではありません。
例えば navigatorOverlay.xul
では、navigator パッケージのマスタースキンを定義する navigator.css
をロードしていませんし、絶対にロードするべきではありません。
これは、オーバーレイの目的が、あるパッケージのための新規の UI 要素を、そのパッケージのスキンの文脈の範囲で定義することにあり、
オーバーレイでは構造は追加しても新しいスタイルは追加するべきではないからです。
オーバーレイによってロードされた任意のスキンは、ベースファイルのマスタースキンを破壊的に置き換えるため、パッケージのスキンの基本的な見栄えを不幸な方向に変更する可能性があります。
bookmarks.css
という名称で、skin/default サブディレクトリに置かれることになります。属性のオーバーレイ
新規の要素やサブツリーに加えて、既存の要素の属性についてもオーバーレイすることが可能です。 以下の例のように、XUL では属性は画像のソースといった、スキンの重要な箇所を制御するのに使用されているため、 オーバーレイによりベースとなるファイルの画像のソースを置き換えることで、取り替えるように上書きすることが可能です。 以下のベースファイルでは、 HTML の画像要素は、Netscape の GIF アイコンを指していますが、
<html:img id="foo" src="netscapeImage.gif"/>
オーバーレイでは、同じ ID の要素の属性として別の画像を指定しているため、 その画像の指定は、マージ処理の一環で、元の Netscape の画像の指定の上に重ねられます。
<html:img id="foo" src="mozillaImage.gif"/>
ベースファイルが、上記の HTML 画像要素を含んだオーバーレイを参照すると、 新しい src 属性が元のものに重ねられるため、 Mozilla アイコンが Netscape アイコンを置き換えることになります。
オーバーレイする位置
また、XUL オーバーレイでは、ノードの位置指定もサポートしています。
オーバーレイ中のノードに position
属性を指定することで、マスター文書に挿入する際のヒントを提供することが可能です。
以下の例では、最後のメニュー項目である「Example Four」は、他のもののようにメニューの末尾に追加されるのではなく、「New」のメニュー項目の直後に置かれることになります。
<overlay id="main-overlay" xmlns:html="https://www.w3.org/1999/xhtml" xmlns:rdf="https://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="https://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <menu id="file_menu"> <menuitem name="Example One"/> <menuitem name="Example Two"/> <menuitem name="Example Three"/> <menuitem name="Example Four" position="1"/> </menu> </overlay>
position
属性を持ったノード自体は、メニューの先頭に並べられます。
また position
を、複数のオーバーレイファイルのノードに指定することで、
ベースファイルの類似する項目のグループの中に並べさせることも可能です。
例えば、上記の最後のメニュー項目だけがオーバーレイにあり、
それ以外の項目はベースファイルで定義されていたとしても、
オーバーレイされたメニュー項目は、依然として親のメニューの先頭に表示されることになります。
オーバーレイによる UI の再利用
オーバーレイを使用することによる最も大きな利点の 1 つは、 UI の中で頻繁に表示される一連の要素を再利用可能にできることです。 オーバーレイのメカニズムでは要素を既存のサブツリーにマージできますが、 それを利用して共通の UI 要素をオーバーレイファイルに格納し、 それを利用する任意のベースファイルにマージさせることも可能になります。 具体的には、ベースファイルの必要な任意の場所に ID 属性以外は空のノードを置くことで オーバーレイファイルで定義したサブツリー参照してマージさせることができます。
例えば、共通ダイアログの下部に表示される OK と Cancel ボタンは、UI の中のたくさんの場所で使用されています。
これらのボタンは、特定のダイアログで必要になるたびに再定義するのではなく、
ベースの XUL ファイルからそれらのボタンが定義された dialogOverlay.xul
という XUL ファイルをオーバーレイするようになっています。
(実際の実装はこれよりもう 1 段階複雑になっています。
ベースファイルは、グローバルのコンポーネントディレクトリから、dialogOverlay.xul
をオーバーレイし、さらにその中から platformDialogOverlay.xul
のようなプラットフォーム固有の XUL ファイルがオーバーレイされます。
しかしながら、メカニズムは同じです)
これらのボタンをオーバーレイしたい任意のダイアログでは、先頭でオーバーレイの宣言を行い、
<?xul-overlay href="chrome://global/content/dialogOverlay.xul"?>
空のボックス (box
) に、その UI に対応する okCancelButtons
ID を付加したものを含めるようにします。
<box align="horizontal" id="bx1" flex="100%" style="margin-bottom: 1em; width: 100%;"> <html:input type="checkbox" id="dialog.newWindow"/> <html:label for="dialog.newWindow">&openWin.label;</html:label> <spring flex="100%"/> </box> <box id="okCancelButtons"/>
詳細については、上記から参照しているグローバルコンポーネントファイル platformDialogOverlay.xul
中の OK と Cancel ボタンの定義を見てください。
このように、ツールバー、サブメニュー、ボックスや、その他複数の場所で表示されるサブツリーは、オーバーレイファイルで定義して必要となる任意の場所で再利用のために参照することが可能です。