このセクションでは、匿名コンテントの要素に属性を継承する方法を見ていきます。
属性を継承する
XBL を使うことによって、実際の実装を隠したまま、複合ウィジェットを構築することが可能です。 しかしながら、ここまでに説明した機能を使うだけでは、毎回同じような匿名コンテントしか生成させることはできません。 外枠のバインドされた要素に属性を付加することで、内部の要素に変更を加えることができるようになれば利用範囲が広がるはずです。
XUL: <searchbox/> XBL: <binding id="searchBinding"> <content> <xul:textbox/> <xul:button label="Search"/> </content> </binding>
この例では、内部の
要素に直接 button
属性が置かれています。 このため、このバインディングを使用すると毎回同じラベルになってしまい、利用する側の意図とは合わない可能性があります。 この例の場合ならば、ラベルを指定するための属性は label
searchbox
側に置けた方が望ましいはずです。 こういった場合のために、XBL では inherits
属性が用意されており、これによってバインドされた要素の方に設定された属性情報を、XBL 側の要素に継承させることが可能になります。 inherits
属性は、XBL 側に置かれた、外枠の要素から属性を継承させたい要素、つまりこの例の場合はボタンに置く必要があります。 なお、この属性の値には、継承したい属性の名前をカンマで区切ったリストを設定します。
<xul:textbox xbl:inherits="flex"/> <xul:button xbl:inherits="label"/>
上記により、コンテントが生成されるときには、
要素は textbox
searchbox
要素から flex
属性を受け取り、
要素は button
searchbox
要素 から
属性を受け取ることになります。 この結果、テキスト入力欄の伸縮性とボタンのラベルは、いずれもバインディングが使われるたびごとに変更できるようになります。 さらに、label
searchbox
要素の方の属性値をスクリプトで変更することで、テキスト入力欄とボタンの属性値を更新することが可能です。 なお、inherits
属性を設定できる要素の数には制限はなく、1 つの要素に複数の属性を継承させても構いません。
inherits
属性には XBL 名前空間に置くために、「xbl:
」という接頭辞が付加されていることを確認してください。 この名前空間は、これらの行以前のどこかで宣言する必要がありますが、 通常は
要素に置くようにします。 以下に例を示します。bindings
<bindings xmlns:xbl="https://www.mozilla.org/xbl" xmlns:xul="https://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <xbl:binding id="buttonBinding"> <xbl:content> <xul:button label="OK" xbl:inherits="label"/> </xbl:content> </xbl:binding>
この例のボタンは、
属性について継承が行われますが、 XBL の方でも、その属性に対する値が直接設定されています。 このテクニックは、バインドされた要素に属性が設定されないときのために、デフォルト値を設定しておく必要があるときに使用します。 つまり、このボタンの場合は、外枠の要素から label
属性を継承することになりますが、 もしも label
属性がない場合には、label
OK
というデフォルト値が使用されることになります。
また、XBL から生成される 2 つの要素に同じ名前の属性を継承させる必要があることもしばしばあると思います。 例えば、
要素と label
要素から、ラベル付きのテキスト入力欄 (横に説明用のテキストがあるテキスト入力欄) を作成する場合、 ラベルは表示するテキストのために textbox
属性を継承する必要があり、 またテキストボックスも、デフォルト値のため同様に value
属性を継承する必要があります。 これを解決するためには、外枠の要素では片方には別の名前の属性を割り当てておき、XBL 側では別の名前にした方の value
inherits
属性で、対応する属性名を明示するようにします。 以下の例は、これを行うためのものです。
XUL: <box class="labeledtextbox" title="Enter some text:" value="OK"/> CSS: box.labeledtextbox { -moz-binding: url('chrome://example/skin/example.xml#labeledtextbox'); } XBL: <binding id="labeledtextbox"> <content> <xul:label xbl:inherits="value=title"/> <xul:textbox xbl:inherits="value"/> </content> </binding>
要素は、textbox
属性を直接継承しています。 このため、ラベルの方に value
属性を設定するためには、別の属性名を使っておいて、その値をマップする必要があります。 ラベルに設定された value
inherits
属性は、labeledtextbox
要素に設定された title
属性を捉え、
要素の label
属性にマップしています。 「<内側の属性名>=<外枠の属性名>」が、属性を別の属性にマップするための構文になります。 もう 1 つ、別の例を示します。value
XUL: <box class="okcancel" oktitle="OK" canceltitle="Cancel" image="happy.png"/> CSS: box.okcancel { -moz-binding: url('chrome://example/skin/example.xml#okcancel'); } XBL: <binding id="okcancel"> <content> <xul:button xbl:inherits="label=oktitle,image"/> <xul:button xbl:inherits="label=canceltitle"/> </content> </binding>
この例の oktitle
属性の値は、最初のボタンの
属性にマップされます。 また、label
canceltitle
属性は、2 番目のボタンの
属性にマップされます。 さらに、最初のボタンには label
属性も継承されます。 その結果、以下のようになります。image
<box class="okcancel" oktitle="OK" canceltitle="Cancel" image="happy.png"> <button label="OK" image="happy.png"/> <button label="Cancel"/> </box>
これらの属性は、内部の (匿名) コンテントに複製される点に注意して下さい。 このため、okcancel
クラスを持ったボックスの属性を変更した場合には、内部のボタンの値も自動的に更新されることになります。 また、属性名として独自のものを使用したことにも気が付いたかもしれません。 XUL では、これは正当な指定として扱われます。
次のセクションでは、バインディングに対して、プロパティ、メソッド、イベントを追加する方法を見ていきます。