[PR]この占いで運命を切り開け!:無料診断でわかる血液型のヒミツ

XUL チュートリアル - 6.6 - テンプレート
戻る 内容 リファレンス 進む

XUL チュートリアル - テンプレート (Template)

このセクションでは、データをもつ要素の生成を見ることにしましょう。

要素を生成する

XUL には、RDF が提供するデータ、つまり、RDF ファイルや内部データリソースのいずれかから、要素を作る方法があります。ブックマークや履歴、メールメッセージなど Mozilla が提供するリソースは数多くあります。これらに関する詳細は、次のセクションで説明します。

通常、ツリー項目やメニュー項目などの要素は、データを使って生成されます。しかし、メニューやツリーは、特殊な場合には、非常に役に立つものですが、必要なら別の要素を使うこともできます。これら別の要素を使うことから始めましょう。ツリーとメニューの場合は、もっと多くのコードが必要になるからです。

RDF データに基づいて要素の生成ができるようにするには、簡単なテンプレートを提供する必要があります。これは、作られる要素それぞれで複製されることになります。本質的に、これは、最初の要素のためだけのものです。残りの要素は、最初の要素に基づいて、組み立てられます。

テンプレートは、template 要素を使って作られます。その内部には、組み立てられる個々の要素で使いたい要素を置くことができます。template 要素は、組み立てられる要素を含むコンテナの中に置くべきです。例えば、ツリーを使っている場合、template 要素は、tree 要素の中に置くべきです。

これは、例を使えばもっとうまく説明できます。簡単な例を取り上げることにしましょう。トップレベルのブックマークの各々でボタンが使いたいとします。Mozilla は、ブックマークリソースを提供しています。これは、データを取得するのに使うことができます。この場合は、ボタンを作るつもりなので、トップレベルのブックマーク (あるいはブックマークフォルダー) だけを取得します。子供のブックマークのためには、ツリーやメニューなどの階層を表示する要素を使う必要があります。

この例と内部 RDF データソースを参照する他の例はすべて、クロム URL から RDF データソースをロードする場合にのみ、動作します。セキュリティー上の理由から、Mozilla は、他の URL から RDF データソースをアクセスすることを許しません。
例 6.6.1
<box datasources="rdf:bookmarks" ref="NC:BookmarksRoot"
    orient="vertical" flex="1">
  <template>
    <button uri="rdf:*" label="rdf:http://home.netscape.com/NC-rdf#Name"/>
  </template>
</box>

ここでは、個々のトップレベルブックマークのためのボタンのカラムをもつ垂直方向のボックスが作られています。templatebutton が一つあるのが分かるでしょう。このボタンは、作る必要のあるボタンすべての基礎として使われます。下のイメージで、個々のブックマークのためのボタンセットが作られていることが分かるでしょう。

テンプレート自身は、垂直方向のボックスの内部に置かれています。ボックスには、特殊属性が 2 つあります。これによって、ボックスをテンプレートで使うことができます。 これら 2 つの属性は、データがどこから来るのかを指定するために使われています。

ボックスの最初の属性は、datasources 属性です。これは、要素を作るために、どんなデータを RDF データソースが提供するのか宣言するのに使われています。この場合は、rdf:bookmarks が使われています。多分、これは、ブックマークデータソースを使う意味だと推測できるでしょう。この場合、このデータソースは、Mozilla によって提供されています。自分自身のデータソースを使うには、以下の例で示しているように、datasources 属性に RDF ファイルの URL を指定します。

<box datasources="chrome://zoo/content/animals.rdf"
  ref="urn:animals:data">

同時に複数のデータソースを指定することもできます。それには、属性値内でデータソースをスペースで区切ります。これは、複数のソースからデータを表示するのに使うことができます。

ref 属性は、データソース内のどこからデータを検索したいのかを指示します。ブックマークの場合、NC:BookmarksRoot の値が、ブックマーク階層のルートを指示するのに使われています。別の値が使えるかどうかは、使用するデータソースに依存します。データソースとして自分自身の RDF ファイルを使っている場合は、その値は、RDF の BagSeqAlt 要素の about 属性の値に対応するものになります。

上のボックスにこれら 2 つの属性を追加することによって、テンプレートを使った要素の生成ができます。しかし、テンプレート内の要素には、別の宣言が必要です。上の例で、buttonuri があり、label 属性の値が普通のものではないことに気が付いたかもしれません。

label 属性は、ブックマークの名前を指定する参照名にすぎません。それは、データソースが使うネームスペース URL を取り、フィールド名を追加することによって、組み立てられています。これが理解できない場合は、前のセクションの最後の部分を読み返してみて下さい。そこでは、RDF のリソースをどうすれば参照できるか説明してあります。ここでは、ブックマークの名前だけを使いますが、他の数多くのフィールドが利用できます。

ボタンの label は、この特殊な URI に設定されています。ボタンのラベルをブックマークの名前に設定したいからです。button のどの属性、あるいは他のどの要素にも、URI を置くことができました。これらの属性の値は、データソース、この場合はブックマークが提供するデータで置き換えられます。ボタンのラベルがブックマークの名前に設定できたので、ここはこれでよいでしょう。

下の例は、どうすれば、データソースを使って、ボタンの他の属性が設定できるか示しています。もちろん、これは、データソースが適切なリソースを提供していることを仮定しています。いいリソースがなければ、属性の値は、空文字列に設定して下さい。

<button class="rdf:http://www.example.com/rdf#class"
  uri="rdf:*"
  label="rdf:http://www.example.com/rdf#name"/>
  crop="rdf:http://www.example.com/rdf#crop"/>

お分かりのように、個々のデータソースが提供する属性を使って、動的に、要素のリストを生成できます。

uri 属性は、テンプレートの出発点として使われる要素を指定するのに使われています。これについては、ツリーのテンプレートを作るときに見ることにしましょう。

これらの機能を、テンプレートがあるコンテナ (この場合はボックス) とテンプレート内部の要素に追加することによって、外部データから様々な興味深い内容リストを生成することができます。もちろん、テンプレート内に複数の要素を置き、どの要素の属性にも特殊な RDF 参照を追加することもできます。下の例はこれを示しています。

例 6.6.2
<box datasources="rdf:bookmarks" ref="NC:BookmarksRoot"
    orient="vertical" flex="1">
  <template>
    <button uri="rdf:*" label="rdf:http://home.netscape.com/NC-rdf#Name"/>
    <button uri="rdf:*" label="rdf:http://home.netscape.com/NC-rdf#URL"/>
  </template>
</box>

作られた新しい要素は、機能的に、XUL ファイル内に直接置いた要素と何の違いもありません。id 属性が、テンプレートを通じて作られたすべての要素に追加されています。これは、リソースを識別する値に設定されています。これは、リソースを識別するのに使用できます。

2 つのリソースの値は、キャレット (^) で区別することによって、連結することができます。例えば

例 6.6.3
<box datasources="rdf:bookmarks" ref="NC:BookmarksRoot"
    orient="vertical" flex="1">
  <template>
    <button uri="rdf:*" label="rdf:http://home.netscape.com/NC-rdf#Name^rdf:http://home.netscape.com/NC-rdf#URL"/>
  </template>
</box>

ルール

以前の例のイメージで、上から 4 番目と 下から 3 番目のボタンは、内容がハイフンだけのボタンであることに気が付いたかもしれません。これらは、ブックマークリスト内のセパレーターです。通常使われるのと同じように、RDF ブックマークデータソースは、セパレーターがあたかも通常のブックマークであるかのように表示されています。実際に表示してもらいたいのは、セパレーターの場合、単純な水平線を描画することです。セパレーターにボタンは欲しくありません。これは、2 種類の内容を作らせたいということです。一つは通常のブックマークのため、もう一つはセパレーターのための内容です。

これは、rule 要素を使って行なうことができます。作りたいと思った要素の個々のバリエーションにルールを定義します。この場合、ブックマークのためのルールとセパレーターのためのルールが必要でしょう。個々のルールは、別々の条件になります。rule 要素に置かれる属性によって、どのルールがどの RDF リソースに適用されるかが決まります。

どのルールがデータに適用されるかを調べると、個々の rule は、順番にマッチするかチェックされることが分かります。これは、要素を定義する順序が重要だということです。前にあるルールが後ろにあるルールよりも優先されます。

以下の例は、前の例に 2 つのルールを付けたものです。

例 6.6.4
<window
  id="example-window"
  title="Bookmarks List"
  xmlns:html="http://www.w3.org/1999/xhtml"
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"  
  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

 <box datasources="rdf:bookmarks" ref="NC:BookmarksRoot"
    orient="vertical" flex="1">
  <template>

    <rule rdf:type="http://home.netscape.com/NC-rdf#BookmarkSeparator">
     <html:hr uri="rdf:*" size="1"/>
    </rule>

    <rule>
      <button uri="rdf:*" label="rdf:http://home.netscape.com/NC-rdf#Name"/>
    </rule>
  
  </template>
 </box>

</window>

ルールを 2 つ使うことによって、テンプレートの内容を選択して生成することができました。最初の rule では、rdf:type 属性から分かるように、ブックマークのセパレーターが選ばれます。2 番目の rule には属性は一つもありません。そのため、すべてのデータがこれにマッチします。

rule タグに置かれた属性はすべて、マッチするかどうかの基準として使われます。この場合、rdf:type がセパレーターを識別するのに使われています。この属性は、RDF ブックマークデータソース内で、セパレーター用の特殊な値に設定されています。これによって、セパレーターをそれ以外のものから区別できます。RDF 内容の Description 要素にあるすべての属性に対して、同様のテクニックが使えます。

ブックマークデータソースは、個々のリソースに rdf:type 属性を追加します。上の例の最初のルールに与えられた特殊な URL 値は、セパレーターのために使われています。これは、セパレーターが最初のルールに従い、水平方向のバーを表示する HTML の hr 要素を生成するということです。セパレーター以外の要素は、最初のルールにはマッチしないので、2 番目のルールに行きます。2 番目のルールには属性が何もありません。これは、すべてのデータにマッチするということです。もちろん、これがセパレーター以外のデータに適用して欲しかったものです。ルール内では、HTML 要素も許されるということに気が付いたかもしれません。

RDF ネームスペースの属性を取得したかったので (rdf:type)、window タグにネームスペース宣言を付け加える必要があった点にも気付くべきでしょう。これを行なわなかったら、その属性は XUL ネームスペース内で探されることになります。それはそこにはないので、ルールはマッチしません。自分自身のカスタムネームスペースを使う場合、それにマッチさせるには、ネームスペース宣言を付け加える必要があります。

2 番目のルールを取り除いたらどうなるか推測してみて下さい。結果は、セパレーターが 2 つだけ表示され、ブックマークは表示されなくなります。ブックマークはルールのどれともマッチしないからです。

簡単に言うと、rule に置かれた属性すべてが RDF リソースの対応する属性とマッチする場合に、ルールはマッチします。RDF ファイルの場合、リソースは、Description 要素になります。

しかしながら、中には、小さな例外があります。idrdf:propertyrdf:instanceOf 属性に基づいたマッチはできません。しかし、自分のネームスペースをもつ自分の属性しか使えないので、多分、これは、実際には、問題にならないでしょう。

最初の例のように、ルールのないテンプレートは、実際は、属性のないルールを一つもつテンプレートと機能的に等価であることに注意して下さい。

ツリー付きのテンプレート

ブックマークのためのボタンリストの作り方を見ました。しかし、ブックマークのリストは、ツリー内に置く方が適しているでしょう。そうすれば、子供のブックマークも見ることができるからです。ツリーをテンプレートで使う上で、特殊なことは何もありません。適切な場所に様々なツリー要素を置かなければならないだけです。下の例はその方法を示しています。

例 6.6.5
<window
  id="example-window"
  title="Bookmarks List"
  xmlns:html="http://www.w3.org/1999/xhtml"
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"  
  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

  <tree flex="1" datasources="rdf:bookmarks" ref="NC:BookmarksRoot">
   <template>

    <rule rdf:type="http://home.netscape.com/NC-rdf#BookmarkSeparator">
      <treechildren flex="1" >
       <treeitem uri="rdf:*">
         <treerow>
           <treecell>
             <html:hr size="1"/>
           </treecell>
         </treerow>
       </treeitem>
      </treechildren>
    </rule>

    <rule>
      <treechildren flex="1">
       <treeitem uri="rdf:*">
         <treerow>
           <treecell class="treecell-indent" label="rdf:http://home.netscape.com/NC-rdf#Name" flex="1"/>
         </treerow>
       </treeitem>
      </treechildren>
    </rule>

   </template>
  </tree>

</window>

同じ 2 つのルールを再び使っていますが、今回は、ボックスではなくツリーの内部にあります。前の場合と同様に、RDF データソース内のそれぞれのリソースは、ルールに対してマッチするか調べられ、その結果に基づいて要素が作られます。この場合は、treeitem 要素が、個々の要素のために作られます。

ここは、uri 属性が役立つところです。例では、ツリー項目はルールの直接の子孫ではないにも関わらず、それがツリー項目に置かれている点に注意して下さい。この属性は、個々のリソースに対して繰り返したい要素だけに置く必要があります。複数の treechildren 要素は欲しくないので、それはそこには置きません。代りに、treeitem 要素に uri 属性を置きます。実質上、uri 属性をもつ要素の外側 (あるいは上) の要素は複製されません。一方、uri 要素とその内部にある要素は、個々のリソースに対して複製されます。

イメージで、トップレベルの要素の下の子供要素が自動的に追加されている点に注意して下さい。XUL は、テンプレートやルールにツリー要素やメニュー要素がある場合、子供要素を追加する方法を知っています。そのため、XUL は、RDF データにあるのと同じ数のネストされたツリー要素を生成します。

RDF データソースの興味深い部分は、リソースの値は、データが必要になるときにだけ決められるということです。これは、リソース階層のもっと深い場所にある値は、ユーザーがツリー内のそのノードに進むまでは決められないということです。これは、データが動的に決められるようなデータソースの場合に役立ちます。

個々のルール内にもっとたくさんの treecell 要素を置くことによって、複数のカラムをもつツリーも簡単に作ることができます。個々のルールに同じ数のセルを加える必要があります。セパレーターの場合、個々のセルには、水平線を置きます。

面白いのは、これが、実際に Mozilla でブックマークウィンドウが作られている方法に近いものだということです。必要なのは、追加フィールドを幾つかとメニューバーを加え、整形的な変更をすることです。

その他のルールの属性

これ以外に rule に追加できる 2 つの属性があります。これを使うと、特殊な環境でマッチさせることができます。いずれも boolean 属性です。

上の 2 つの属性は、実際には、お互いの逆ではありません。リソースは、コンテナか空コンテナかもしれません。しかし、これは、コンテナではないリソースとは違います。例えば、ブックマークフォルダーはコンテナですが、子供をもつ場合もあればもたない場合もあります。しかし、ブックマークやセパレーターはコンテナではありません。

これら 2 つの属性を別の属性と組み合わせて、もっと特殊なルールにマッチさせることができます。


(進む) 次は、Mozilla が提供するデータソースの幾つかを見ることにしましょう。

例: 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5

XUL チュートリアル - 6.6 - テンプレート
戻る 内容 リファレンス 進む

[PR]〈特集〉内側からの美容法:うるおい美人の秘密を公開!キューサイ