Join MDN and developers like you at Mozilla's View Source conference, 12-14 September in Berlin, Germany. Learn more at https://viewsourceconf.org

Anonymous Content

この翻訳は不完全です。英語から この記事を翻訳 してください。

はじめに

バインディングは、content 要素を使って「無名コンテンツテンプレート」を定義することができます。このテンプレートはバインディングの結びつけの間にバウンド要素の周辺に生成されるだろうコンテンツ (内容) ツリーを記述します。単独のタグを使ってバウンドドキュメントに宣言された要素は、複数の子供要素によって構築され、この実装(XUL側)はバウンドドキュメントから隠されます。

例えば、HTML ファイルアップロードコントロールは多くのブラウザではテキストフィールドとボタンで構成された混合部品として表示されます。ファイル部品のためのサンプル XBL バインディングは以下のようになるでしょう。

<binding id="fileupload">
  <content>
    <html:input type="text"/>
    <html:input type="button"/>
  </content>
</binding>

このコンテンツ (content) は親要素から見えないため、「匿名コンテンツ」と呼ばれます。

スコープ使用 と DOM を使ったアクセス

バインディングが結びつけられ、特定の条件が満たされたとき、バインディングの content 要素の子供は複製されます。XBL 名前空間の要素と属性は決して複製されません。バウンド要素の配下に生成されたコンテンツでは、最上位ノードの parentNode ポインタはバウンド要素に設定されます。無名コンテンツの要素はバウンド要素より上位に構築されるとき、最上位要素の parentNode ポインタはバウンド要素の parentNode に設定されます。すべての無名ノードの ownerDocument ポインタは生成時にバウンドドキュメントにセットされます。

結局、無名コンテンツはドキュメント内部の遮断された自身の領域の中に存在しています。parentNode を使って、無名コンテンツノードは明示された親を参照することができますが、明示された親は自分の無名子供について何も知りません。無名コンテンツはバウンド要素のための childNodes リストを通じてアクセス可能ではありません。そして、バウンド要素の子供を通して順次アクセスするための firstChild/nextSibling を使ったアクセスも可能ではありません。 The anonymous content is accessible only through special methods like getAnonymousNodes and getAnonymousElementByAttribute.

無名コンテンツはドキュメント内部のノードに「スコープ」の概念を取り入れます。無名コンテンツ要素はまた、その無名コンテンツを生成するのに結びつけられたバインディングを持つことができるため、このスコープ使用は任意のネストのレベルをとることができます。

明示的なコンテンツは「ドキュメントレベルのスコープ」であると呼ばれます。無名コンテンツノードは自身の「バインディングレベルのスコープ」にあります。バインディングのスコープは無名ノードの生成する責任を持つバインディングを含むバウンド要素によって決定されます。

要素のスコープは DocumentXBL インタフェース上の getBindingParent メソッドを使って決定されます。詳細情報は セクション 3 を参照のこと。このメソッドは無名ノードに責任を持つそのノードを囲んでいるスコープの中のバウンド要素を返します。もし、ドキュメントレベルのスコープで要素上で呼び出されたら、null を返します。

(例えば getElementsByTagName のような) 要素上で呼び出されることのできる DOM メソッドは同じスコープにあるノードだけを見ることができるでしょう。(例えば getElementById のような) ドキュメント上で呼び出されるメソッドは、ドキュメントレベルのスコープにあるノードだけ参照することができます。

コンテンツの生成

生成の規則

バインディングが要素に結びつけられるときはいつでも、無名コンテンツは生成されたり破棄されたりする可能性があります。新しいバインディングが結びつけられると、明示的なつながりの中のバインディングは無名コンテンツテンプレートを持っているか見るために調べられます。テンプレートをともなうつながりの中の大半の派生バインディングは、無名コンテンツが生成されるべきか決定するのに使われるものです。

生成のためのチェックがなされる時にバウンド要素の下に見つかったすべての明示的なコンテンツ (内容) のためのテンプレート内部で定義されている挿入点がある時だけ、無名コンテンツはテンプレートから生成されます。バインディングが明示的なコンテンツ (内容) に対する挿入点を何も定義していなければ、バウンド要素が明示的な子供を持たない時に限り、無名コンテンツは構築されるでしょう。

すべての明示的な子供が有効な挿入点を持つと仮定すると、無名コンテンツはバウンド要素の下に生成されます。生成に責任を持つバインディングは「第一生成バインディング」と呼ばれます。第一生成バインディングがバウンド要素上で変更されるときはいつでも、バウンド要素のスコープにあるすべての無名ノードは破棄されます。

contentgenerated イベント

Note: The contentgenerated event is not implemented yet; see バグ 223411.

コンテンツがバインディングのテンプレートからビルドされるときはいつでも、contentgenerated が発生します。バインディングではバインディングがコンテンツを生成した後に実行されるためのスクリプトを含んだ contentgenerated ハンドラを定義できます。

コンテンツ生成ハンドラは第一生成バインディングが変化しバインディングがバウンド要素周辺でコンテンツを生成するべきと判断されるときに必ず呼び出されます。バインディングのつながりのためのこのハンドラは基底バインディングからもっとも派生したバインディングまでいつも発生します。つながりのすべてのバインディングからのコンテンツが生成されるまで、どのハンドラも呼び出されません。

contentdestroyed イベント

第一生成バインディングが変更 (他のバインディングになるか、まったく何にもならないか) される時はいつでも、もし無名コンテンツがすでに現在バウンド要素の周辺にある時、そのコンテンツは破棄されます。コンテンツの破棄に先立って、contentdestroyed イベントが発生します。

ハンドラはつながりの最も派生したバインディングから基底バインディングまで実行されます。すべてのハンドラはコンテンツが実際に破棄される前に発生します。ハンドラが発生した時、第一生成バインディングはまだ変更されていません。

属性転送

無名コンテンツ要素上の属性は、バウンド要素上の属性に結び付けることができます。属性がバウンド要素上にセットもしくは削除される時はいつでも、無名コンテンツ上の対応する属性もセットもしくは削除されます。テンプレートのどの無名コンテンツ要素上でも、inherits 属性は継承されるべき属性のカンマ (,) で区切られたリストで定義するために使うことができます。名前空間をともなう属性は、名前空間接頭辞を使って定義されることができ、属性名はコロン (:) で区切られます。

例えば、HTML ファイルアップロードコントロール上で、無名テキストフィールドは自動的にバウンド要素から value 属性を継承するために組み立てられます。

<xbl:binding id="fileUploadControl">
  <xbl:content>
    <html:input type="text" xbl:inherits="value"/>
    <html:input type="button" value="Browse..."/>
  </xbl:content>
</xbl:binding>

inherits リストのどのエントリも、属性を単にリストする (上記例の value のように) ことや、バウンド要素上の属性に結び付けるべき無名コンテンツ上の属性で構成されるイコール (=) で区切られたペアの中で定義することができます。無名コンテンツ属性は最初にならべられます。

xbl:text という特別な値を = で区切られたペア中で使用することができます。ここで定義されている接頭辞は XBL 名前空間のことです。ペアの左辺値として定義された時、xbl:text は右辺値の属性は無名要素の下のテキストノードとして貯えられるべきだということを示します。右辺値として使われた時、xbl:text はバウンド要素の明示的な子供の生のテキストノードは融合すべきで、戻り値は左辺値の属性として貯えられるべきだということを示します。

xbl:text 値はそれ自身でリストの中に現れることはできません。xbl:text はイコール (=) で区切られたペアの中でだけ使われます。

コンテンツがテンプレートから生成された時、inherits 属性は複製されないことを注意してください。

挿入点

<children> と <element>

Note: The element tag is not implemented (yet?); see バグ 98712.

無名コンテンツの交互配置

XBL バインディングは、無名コンテンツをバウンド要素とその明示的子供との間に綴じ込みます。それらは XBL の children タグや element タグを使うことでそのようにできます。いくつかの children タグはバインディングの無名コンテンツテンプレートで使われるでしょう。children が使われている場所は「挿入点」と呼ばれます。

挿入点には二種類あります。明示的なそれと、継承されたそれです。明示された挿入点はバウンド要素の明示的な子供が挿入された場所を指定します。明示的な挿入点は、第一生成バインディング上で見つかった時にだけ使われます。他のバインディング上の明示的な挿入点は無視されます。

継承された挿入点は、無名コンテンツを導くつながりの次のバインディングによって生成された無名コンテンツを置くのに使われます。そのバインディングは基底バインディングのための継承された挿入点を定義することもできます。このパターンはバインディングのつながりのすべての段階で同様です。

includes 属性を使って定義された XPath セレクタはどの挿入点の下に与えられた子供を置くべきかを決めます。どの属性も定義されていない時、挿入点は一般のものと考えられ、すべてのコンテンツに一致します。

与えられたコンテンツの断片のために使われた挿入点は、コンテンツテンプレートの第一階層であるとき、要素に合致するノードセットのセレクタに、はじめて遭遇しました。

element タグは無名コンテンツを生成する要素に関係するバウンド要素の位置を定義します。たった一つの element タグだけが無名コンテンツテンプレートに存在することができます。第一生成バインディングでないバインディング上に働きかけるどの element タグも無視されます。もし、バウンド要素がそれを生成する無名コンテンツの下などに再配置されると、第一バインディングに生成されたすべてのルート無名要素は修正されたツリーのバウンド要素のために使われる挿入点に配置されます。

element 要素と children 要素は、コンテンツがテンプレートから生成された時、決して複製されないことに注意してください。

DOM の変更の処理

挿入点は、要素が DOM へ挿入されたり、DOM から切り離されたりする時に、使われるために続きます。要素が挿入または追加される時、すべての挿入点は無名コンテンツ生成の間明示された子供を最初に配置する時に適用されるのとまったく同じ規則に従ってチェックされます。新しく挿入された子供に、挿入点が見つからなければ、バインディングはもうバウンド要素にはめ込まれず、すべての無名コンテンツは破棄されます。

要素が取り除かれた時はいつでも、それは単に要素に生成されたすべての無名コンテンツに従ってその挿入点から見えなくなります。

標準 DOM API を使ってバウンド要素の下に含まれる無名コンテンツを操作することは可能です。もし、挿入点を含んだ無名コンテンツが削除されると、挿入点の下で見つかったどの明示された子供も一致する他の挿入点に再配置されます。繰り返しますが、もしすべての子供が再配置されなければ、無名コンテンツは破棄されます。

[編集者メモ: 挿入点回収、動的挿入点新規作成、挿入点削除といった API は必要か? ElementXBL 上ではどうか?]

イベントフローとターゲット

フローとスコープを超えたターゲット設定

DOM イベントは、明示された対象上で可能に発生するのと同様に、無名対象上で発生します。イベントフローが同じスコープの中にある限り、DOM Level 2 Events 仕様書 で概説されている振る舞いと違いはありません。

イベントは、全要素が children タグと element タグによって再配置された後の最終的な変換後のコンテンツモデルを流れていきます。

バウンド要素のスコープにある無名要素からバウンド要素自身へイベントがフローする (流れる) ときはいつでも、二つのうちいずれかの動きが発生します。一方のイベントはバウンド要素が対象になるための対象変更で、もう一方のイベントは停止と次のフェーズへの移行です。イベントが対象変更となると、イベントの target フィールドはバウンド要素に設定されます。イベントの発生源である元の無名コンテンツはイベントオブジェクトの新しいフィールドである originalTarget から得ることができます。

(対象変更か停止か) いずれの動きが起きるかは、イベント型により限定されます。一般に、UI イベントは対象変更し、変異イベントは停止します。この規則の例外を後述します。

focus と blur イベント

focus イベントや blur イベントがスコープの境界を横切るとき、バウンド要素はフォーカス可能かどうか確かめられます。例えば、ユーザエージェントは通常、要素上でフォーカスを得るイベントやフォーカスが離れるイベントを起こします。もし、バウンド要素がフォーカス設定可能なら、そのイベントは目標再設定します。もし、フォーカス設定不能なら、イベントは停止します。フォーカス可能なバウンド要素の下の無名コンテンツのフォーカスが外れ、バウンド要素の無名コンテンツがまたフォーカスを得たとき、フォーカスの離れとフォーカスを得るの両方のイベントは停止します。バウンド要素に関する限り、二つのイベントを通してフォーカスは保たれます。

無名コンテンツはユーザがドキュメントを通してタブで指定したときにフォーカスを受け取ります。同じルールが当てはまります。もし、無名コンテンツがフォーカス設定可能なら、タブでの指定も可能です。しかし、バウンド要素がフォーカス設定不可能なら、イベントはそのバウンド要素に届く前に停止するでしょう。

HTML 4 では、tabindex 属性をフォーカス設定可能な要素のタブ順序を指定するために使うことが出来ます。この属性は無名コンテンツ上にも指定可能です。スコープそれぞれが固有のタブ順序を持っています。あるのスコープ内でのtabindex 値は、他のスコープでは無視されます。

例として、upload (アップロード) コントロールの HTML を考えてみます。これは textfield (テキストフィールド) と button (ボタン) という、二つの交互のフォーカス可能な無名要素からなるフォーカス可能な要素です。テキストフィールドとボタン上では、タブは順序は、タブ押下時に file (ファイル) コントロールのコンポーネントがアクセスされるべき順番を決定するために指定されるべきです。

ユーザが file (ファイル) コントロールがフォーカスを得るようタブを押下したとき、ユーザエージェントは、無名コンテンツ要素によって指定されるタブ順序を使って、いずれかの無名コンテンツもフォーカスを得たのかを決定しなければなりません。そして、file コントロール内部でテキストフィールド上でフォーカスイベントが生成されます。このイベントの流れがスコープを横切ったとき、file コントロール自身の上でフォーカスイベントとなるよう対象が再設定されます。

バウンド要素がすでにフォーカスを得ている場合も、フォーカスイベントは停止されます。たとえば、もしユーザがすでに HTML ファイルアップロードコントロール内部のテキストフィールドにフォーカスを得ているならば、そのファイルアップロードコントロールは今、フォーカスを得ています。もしユーザがまた、ファイルアップロードコントロールの内部のボタンにフォーカスを合わせたとき、そのボタンのために生成されたフォーカスイベントはファイルコントロールに届く前に停止します。それは、ファイルコントロールがすでにフォーカスを得ているからです。

複数のスコープの中のコンテンツがフォーカス可能なため、CSS :focus 疑似要素は階層的です。スタイルルールは、(上記の例の中の) ファイルコントロールとファイルコントロール内部のフォーカスを得た要素の両方にマッチすると仮定して書くことができます。言い換えれば、要素の任意のつながりが、:focus 状態の中に同時にあることができます。

mouseover と mouseout イベント

mouseover イベントと mouseout イベントは、マウスが本当に (ある無名コンテンツに入っていくか出ていくのに加えて) バウンド要素に入ってくか出ていく時にターゲットを新たに定めます。もし、しかし、ユーザがバウンド要素自身から出入りすることなく単に無名要素から他へマウスを動かしたとすると、イベントは停止します。

例えば、もしユーザが左から HTML ファイルアップロードコントロールに入ると、mouseover イベントは無名の textfield に対して生成されます。このイベントはまた、file コントロール自身の mouseover も構成要素としているため、このイベントはスコープをまたいで流れるとき、対象が再設定されます。もし、ユーザが textfield から button へマウスを動かせば、mouseout は textfield に生成され、button の mouseover が後を追います。

これらのいずれのイベントも file コントロール自身の mouseover か mouseout で構成されるため、このイベントは file コントロール自身を流れることは許されません。もし、ユーザが右へマウスを動かし続け、button を離れたら、file コントロールをも出てしまっているため、そのとき生成された mouseout は対象を再設定されます。

無名コンテンツと CSS

セレクタとスコープ

バインディングは無名要素をバウンド要素とその明示的な子供との間に綴じ込みます。詳細は 挿入点 を参照のこと。この状況では、明示的コンテンツのノードツリーとは違った新しいツリーが現れます。単独の明示的な親 (バウンド要素) を持つのに加えて、明示的な子供は (子供の挿入点もしくは element タグが使われたときバインディングに生成される) 任意の無名な親のセットをも持ちます。子供、子孫、そして兄弟のセレクタは無名もしくは明示的な要素のパスにマッチします。

CSS に関する限り、無名コンテンツのノードはバウンド要素の子供 (もしくは子孫) です。これらは明示的コンテンツの先祖で、明示的コンテンツの兄弟です。子供、子孫、兄弟セレクタに適用されるスタイルルールは透過してバインディングのスコープを横切り、変更されたもしくはオリジナルのままのコンテンツモデル上で操作されます。

最後に修正されたコンテンツツリーはどのように CSS プロパティ (例:font や color) が継承されるかを決定します。要素は、(ちょうどコンテンツモデルにおいて見られるように) その明示的な親の下になるに至るか、挿入点のつながりを通すネストになるに至ります。ネストになった場合、もっとも内側の無名の親から継承します。

バインディングスタイルシート

バインディングファイルは stylesheet 要素を使ってスタイルシートを読み込むことができます。デフォルトでは、これらのスタイルシートはバウンド要素と、そしてバウンド要素へ結び付けられたすべてのバインディングから生成されたすべての無名コンテンツに適用されます。これらのシートはバインディングが担うルールをともなうシート同様の同じ起源を持っています。DOM を使って結び付けられたバインディングによって読み込まれたスタイルシートは author レベルのシートとして扱われます。

[編集者メモ: バインディングの継承がこのカスケード適用を複雑にしています。author レベルの DOM バインディングは user レベルのバインディングから継承されることもあるからです。もし、両方がシートを読み込んだら、連鎖的適用の中でそれらのシートがどのレベルに属するのか?]

シートはいつももっとも内側のスコープからもっとも外側のスコープへ向かって進みます。この順序であることにより、ウィジェットを定義するバインディングは、ウィジェットのクライアントによって簡単に上書きされうるウィジェットのためのデフォルトの見た目を定義することが出来ます。複数のバインディングが同じ要素に結びつけられたために、シートは基底バインディングからもっとも派生したバインディングにかけて下って進みます。

バインディングでは二つの属性によってスタイルシートのスコープを微調整することができます。一つは inheritstyle で、外のスコープで定義された author シートがインディングに生成された無名コンテンツに影響を与えるかどうかを指定します。第一生成バインディングのみのため、この属性は、スコープが外側のレベルであるいずれかの author シートがバウンド要素に結びつけられたバインディングによって生成された無名コンテンツへ適用されるべきかをみるためにチェックされます。もしこの属性がセットされていれば、外のスコープの author シートで定義されたルールまでたどり着きません。

デフォルトでは、バインディングファイルで定義されたスタイルシートはバウンド要素と要素に結びつけられたバインディングによって生成された無名コンテンツにだけ適用されます。

ユーザエージェントシートとユーザシートは、いつでもすべてのスコープに適用されます。

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

タグ: 
 このページの貢献者: lv7777, ethertank, kohei.yoshino
 最終更新者: lv7777,