mozilla

匿名コンテント

このセクションでは、XBL によりコンテントを生成する方法を見ていきます。

XBL とコンテント

XBL を使用すれば、要素の中に要素のセットを自動的に追加できます。 つまり、XUL ファイルでは外枠の要素を指定するだけで、 XBL に記述されている内側の要素を自動的に追加するように指定することが可能です。 これにより、複数のウィジェットから、単一のウィジェットを組み上げることができます。 こうして作成されたウィジェットは、単一のウィジェットとしてのみ参照することが可能です。 このため、XUL で外枠の要素に設定された特定の属性を、XBL から生成された内側の要素に対して追加するメカニズムが提供されています (詳細は、次のセクションで説明します)。

スクロールバーを宣言する例

以下の例は、スクロールバーを宣言するための方法を示しています (実際のものより若干単純化されています)。

<bindings xmlns="http://www.mozilla.org/xbl"
          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  <binding id="scrollbarBinding">
    <content>
      <xul:scrollbarbutton type="decrement"/>
      <xul:slider flex="1">
        <xul:thumb/>
      </xul:slider>
      <xul:scrollbarbutton type="increment"/>
    </content>
  </binding>
</bindings>

このファイルに含まれている binding 要素で宣言されたバインディングは 1 つだけですが、 CSS の -moz-binding プロパティから参照することを可能にするために、 バインディングの識別子として id 属性を設定しておく必要があります。

例中の content タグは、スクロールバーに追加される匿名コンテントを宣言するのに使われています。 content タグ中にあるすべての要素は、バインディングが結び付けられる要素の中に追加されることになります。 なお、このバインディングはスクロールバーにバインドすることを想定していますが、 それ以外にバインドすることが禁止されているわけではありません。 CSS の -moz-binding プロパティに、このバインディングの URI が設定されたすべての要素がこのバインディングを使用することになります。

上記のバインディングの結果、以下の XUL の行は、その下に示すように展開されます。 (scrollbar 要素には、CSS で上記の XBL がバインドされているものとします)

<scrollbar>

展開後:

<scrollbar>
  <xul:scrollbarbutton type="decrement"/>
    <xul:slider flex="1"/>
      <xul:thumb/>
    </xul:slider>
  <xul:scrollbarbutton type="increment"/>
</scrollbar>

content タグの中に置かれたコンテントは、スクロールバーに匿名で追加されます。 この匿名コンテントは画面上には表示されますが、通常の方法ではスクリプトから取得することはできません。 これは、実際には多数の要素から構成されていたとしても、XUL からは 1 つの単独の要素だけが存在するようにしか見えないことに起因しています。

上記の XBL に記述されている「矢印ボタン」「スライダー」「スライダーにあるサム」「終端にある 2 つめの矢印ボタン」の各要素は、Mozilla ウィンドウのスクロールバーを構成する部品のための要素です。 また、他のバインディングが、内部に置く XUL 要素としてスクロールバーを利用すると、これらの要素は、それらのバインディングにもバインドされることになります。

なお、XBL にコンテントの要素を記述するときには、 それらの要素は、デフォルトの XBL の要素としては正しくなく、XUL の要素として扱う必要があることを示すために、 XUL 名前空間の指定 (xul: の接頭辞) が必要であることに注意して下さい。 (この名前空間は、bindings タグで宣言されています)。 もしも、XUL 要素に名前空間を明示しない場合は、Mozilla は要素が XBL であると想定するため、 正しい要素であるとは認識されず、正常な動作は行われません。

ファイル名入力欄の例

別の例を示します。 今度は、ファイル名の入力欄のためのものです。

<binding id="fileentry">
  <content>
    <textbox/>
    <button label="Browse..."/>
  </content>
</binding>

このバインディングを要素に設定することによって、その要素はテキストの入力欄と、その後ろの Browse ボタンを持つことになります。 これらの内側のコンテントは、匿名で作成されるため、DOM を使って見ることはできません。

XBL から与えた要素を上書きする

匿名コンテントは、バインディングが要素に設定された場合は常に自動的に生成されます。 ただし、XUL 側でその要素に子要素を置いた場合、バインディングから与えた要素を上書きします。 以下に、例として XUL コードの一部を抜き出したものを示します。 (scrollbar には、前出の XBL がバインドされていると想定しています)

<scrollbar/>

<scrollbar>
  <button label="Overridden"/>
</scrollbar>

最初のスクロールバーは、それ自身ではコンテントを持たないため、XBL ファイルで宣言されたバインディング定義から生成されたコンテントを持つことになります。 2 番目のスクロールバーは、それ自身がコンテントを持っているため、そちらが使われることになり、XBL の方のコンテントは使用されません。 その結果、ほとんどスクロールバーとはいえないものが表示されることになります。 なお、実際にはスクロールバーなどの組み込み要素は、XBL を toolkit パッケージの bindings ディレクトリに置かれたファイルから取得することを補足しておきます。

この上書きの挙動は、content タグによる要素の定義だけに適用されます。 プロパティやメソッドなど、XBL で定義するそれ以外の振る舞いについては、コンテントが XBL のものか、XUL 自身のもので上書きされたのかによらず有効です。

children 要素を使用する

XBL で定義したコンテントと XUL ファイル自身のコンテントの両方を表示させたい場合も、しばしばあると思います。 これは、XBL の children 要素を使用することで可能です。 XUL の方で追加された子要素は、children 要素の場所に追加されることになります。 これを利用すれば、カスタムメニューウィジェットを手軽に作成することが可能です。 例えば、以下のようにすれば、編集可能な menulist 要素の簡易版を作成することが可能です。

XUL:

<menu class="dropbox">
  <menupopup>
    <menuitem label="1000"/>
    <menuitem label="2000"/>
  </menupopup>
</menu>

CSS:

menu.dropbox {
    -moz-binding:  url('chrome://example/skin/example.xml#dropbox');
}

XBL:

<binding id="dropbox">
  <content>
    <children/>
    <xul:textbox flex="1"/>
    <xul:button src="chrome://global/skin/images/dropbox.jpg"/>
  </content>
</binding>

この例は、入力欄とその横にボタンを作ります。 menupopup は、XBL に置かれたコンテントの children 要素で示す位置に追加されることになります。 DOM 関数からアクセスすると、コンテントは XUL ファイルに置かれたとおりに見えることになるため、menupopupmenu の子要素になっていることに注意してください。 XBL から展開されたコンテントは完全に隠されているため、XUL 開発者はそこに存在することすら意識する必要はありません。

その結果、出力されるコンテントは、以下のものと同等になります。

<menu class="dropbox">
  <menupopup>
    <menuitem label="1000"/>
    <menuitem label="2000"/>
  </menupopup>
  <textbox flex="1"/>
  <button src="chrome://global/skin/images/dropbox.jpg"/>
</menu>

includes 属性

場合によって、子要素には特定の種類のコンテントだけを選択的に置けるようにしたいことや、 複数の箇所に子要素を設定して、それぞれ異なる種類のコンテントを置けるようにしたいこともあると思います。 includes 属性を利用すれば、コンテント中に表示する要素を、指定の要素のみに制限することが可能です。 この属性の値には、単一のタグ名か、タグ名のリストを、(OR 演算を意味する)「|」記号で区切って指定する必要があります。

<children includes="button"/>

この行によって、 結び付けられた要素の子要素として含まれている、すべての button を、 children タグのある場所に追加します。 それ以外の要素は、このタグにはマッチしませんが、 バインディングに複数の children 要素を置けば、別の場所にそれ以外のコンテントを追加させることが可能です。 なお、XUL 側で設定した子要素が、どの children 要素にもマッチしなかった場合には、XBL に置かれたコンテントは使用されず、それらのマッチしない全ての要素が代わりに表示されることになります。

ここで、また別の例を見てみましょう。 今度は、両端に拡大と縮小のためのズームボタンを備えた、画像表示用のウィジェットを作りたいとします。 これは、画像と 2 つのボタンを持ったボックスとして作成することが可能です。 このとき、image 要素については、毎回異なったものを指定可能なように、 XBL の外に置く必要があります。

XUL:

<box class="zoombox">
  <image src="images/happy.jpg"/>
  <image src="images/angry.jpg"/>
</box>

XBL:

<binding id="zoombox">
  <content>
    <xul:box flex="1">
      <xul:button label="Zoom In"/>
      <xul:box flex="1" style="border: 1px solid black">
        <children includes="image"/>
      </xul:box>
      <xul:button label="Zoom Out"/>
    </xul:box>
  </content>
</binding>

XUL ファイルの方に明示的に記述された子要素は、XBL の children タグの位置に置かれることになります。 ここでは、2 つの image 要素があるため、両方が並べて追加されます。 その結果、表示は以下のものと同等になります。

<binding id="zoombox">
  <content>
    <xul:box flex="1">
      <xul:button label="Zoom In"/>
      <xul:box flex="1" style="border: 1px solid black">
        <image src="images/happy.jpg"/>
        <image src="images/angry.jpg"/>
      </xul:box>
      <xul:button label="Zoom Out"/>
    </xul:box>
  </content>
</binding>

しかしながら、DOM を使用して見た場合には、子要素の位置に変化はなく元のままになります。 つまり、外枠の XUL ボックスには、2 つ image 要素が子要素として存在しています。 また、内側の境界付きのボックスの子要素は、children タグ 1 つだけになります。 XBL 使用時に DOM を用いる場合、この違いを意識しておくことは重要です。 また、このことは CSS のセレクタに記述するルールについても当てはまります。

複数の children 要素

複数の children 要素を使用することで、特定の種類の要素を置く場所と、それ以外の要素を置く場所を指定することも可能です。 このためには、children 要素に includes 属性を追加して、 そこに縦棒記号 (|) で区切ったタグ名のリストを設定することで、そのリストに含まれる要素だけをその場所に置くことができます。 例えば、以下の XBL では、テキストラベルとボタンを、他の要素とは別の場所に表示させることが可能です。

var el = env.locale; 例 1 : ソース

<binding id="navbox">
  <content>
    <xul:vbox>
      <xul:label value="Labels and Buttons"/>
      <children includes="label|button"/>
    </xul:vbox>
    <xul:vbox>
      <xul:label value="Other Elements"/>
      <children/>
    </xul:vbox>
  </content>
</binding>

最初の children 要素では、includes 属性の指定によって、labelbutton 要素だけが捉えられます。 そして、2 番目の children 要素には includes 属性がないため、残りのすべての要素が捉えられることになります。

var el = env.locale; 関連ページ: XBL リファレンスの 匿名コンテント セクション

次のセクションでは、属性情報を匿名コンテントへ継承する方法を見ていきます。

ドキュメントのタグと貢献者

Contributors to this page: ethertank, Mgjbot, Morishoji
最終更新者: ethertank,