Firefox のサイドバーは、新しいウィンドウや複雑なオーバーレイを必要とせずにリッチインタフェースを追加するための、比較的広く、サイズ変更可能なスペースです。サイドバーは、ユーザが望む広さで表示され、あなたの作りこんだデータとコントロールを追加できるフレームを提供します。ブックマークや履歴のサイドバーに馴染みがあるでしょう。開いたことが無ければ、メニューの [表示] > [サイドバー] からどちらかを開いてください。これらはキーボードショートカットで開いたり閉じたりすることもできます。
サイドバーを追加するために必要なコードはとても簡単です。『Firefox サイドバーの作成』 に説明があります。 この説明よりもさらに簡単です。必要なことは、サイドバーの表示メニューにオーバーレイを適用するだけです。
<menupopup id="viewSidebarMenu"> <menuitem id="xulschoolhello-sidebar" label="&xulschoolhello.sidebar.title;" accesskey="&xulschoolhello.sidebar.accesskey;" type="checkbox" autoCheck="false" group="sidebar" sidebarurl="chrome://xulschoolhello/content/sidebar.xul" sidebartitle="&xulschoolhello.sidebar.title;" oncommand="toggleSidebar('xulschoolhello-sidebar');" /> </menupopup>
MDC ページの例には、新しいサイドバーを開くショートカットキーの組み合わせが含まれています。キーボードショートカットは、Firefox の基本的な機能であり、すばらしいことに、あなたの拡張機能にも独自のショートカットキーを追加できます。問題は、正しいキーボードショートカットを選ぶことがとても難しいことです。AdBlock Plus の作者による解説と Mozilla キーボードリファレンス を参照してください。まとめると、Ctrl+Shift+(任意の文字) のような Firefox と競合しないキーの組み合わせが使用できますが、他の拡張機能が同じ組み合わせを使用しているかどうかを知る方法はありません。ショートカットキーは使い慣れたユーザにはとても価値のあるものですが、決してこれに頼ってはいけません。
サイドバーの XUL ページには、他の XUL ウィンドウやオーバーレイと同様に、どのようなコンテンツでも表示できます。僅かな違いの一つは、XUL サイドバーは、window 要素や dialog 要素の代わりに、page ルート要素を使用して定義されることです。また、サイドバーが開かれた時に load イベント、閉じられた時に unload イベントが毎回発生するため、これらをサイドバーの初期化や後始末に利用できます。
もう一つの考慮すべき重要な違いは、ユーザがサイドバーのサイズを自由に変更できるため、表示幅が狭くなってしまう場合があることです。サイドバー内のコンテンツの幅に注意して、その幅に関係なく使いやすくなるように設計してください。サイドバーの幅を CSS で制限する方法やサイズ変更を無効化する方法もありますが、これらは良い方法とは言えません。サイドバーの幅を固定サイズにすると、アクセシビリティやユーザビリティの問題が起こる原因になります。
広いスペースを必要としない方法で管理すれば、サイドバーで多くのコンテンツが利用できます。以下のセクションでは、このための役立つ XUL 要素を見ていきます。これらを使用すれば、コンテンツを上に積み上げたり異なるセクションを簡単に切り替えたりできます。
tabbox 要素
tabbox 要素は、タブ化された tabpanel 要素のビューを作成します。Firefox の設定ウィンドウの詳細パネルを開くと tabbox 要素の例が見られます。タブのスタイルは使用しているオペレーティングシステムに合わせられるため、タブボックスの CSS を変更することは避けてください。一方で、見かけの異なる tabbox のような振る舞いをする UI が必要な場合は、tabbox を使用して CSS で外観を変更するとよいでしょう。カスタムで作成された要素を使用すると、アクセシビリティや機能に問題を起こす原因になることがあります。
タブ付きビューの作成は非常に簡単です。以下に例を示します。
<tabbox id="xulschoolhello-tabbox"> <tabs> <tab label="&xulschoolhello.mainTab.label;" /> <tab label="&xulschoolhello.advancedTab.label;" /> </tabs> <tabpanels> <tabpanel> <!-- メインパネル用のコンテンツ --> </tabpanel> <tabpanel> <!-- 詳細パネル用のコンテンツ --> </tabpanel> </tabpanels> </tabbox>
デフォルトでは最初のタブが選択されます。tab 要素で selected 属性を true に設定すると、そのタブをデフォルトで選択されるタブにできます。
tabpanel は、どのようなコンテンツでも保持できます。ただし、すべてのタブボックスは、上部のタブストリップや最も大きなパネルのコンテンツと同じだけ大きくなることを考慮しなければなりません。タブパネル内のコンテンツのバランスを取り、不揃いのパネルやほとんど空のパネルが無いようにしてください。
デッキとスタック
時々、一つの tabbox で提供されるよりもきめの細かいコントロールを必要とすることがあるでしょう。このような場合は、deck 要素と stack 要素を使用してください。これらは、サイドバーと並んで多くの状況で使用でき、とても役立ちます。
deck は、タブの無い tabbbox のようなものです。これは、selectedIndex 属性の値に従って、一度に一つの子ノードだけを表示します。次の例では、1 番目の子ノードではなく、2 番目の子ノードがデフォルトで表示されます。
<deck selectedIndex="2"> <hbox> <!-- 1 番目の子ノードのコンテンツ --> </hbox> <hbox> <!-- 2 番目の子ノードのコンテンツ --> </hbox> </deck>
この例は、要素の属性名にすべて小文字が使用される代わりにキャメルケースが使用されている数少ない例の一つです。
deck のサイズは、tabbox と同様に、子ノードの中で最も大きなものに依存します。
deck や stack の子ノードには、hbox 要素や vbox 要素を使用することをお勧めします。コードが読みやすくなり、管理しやすくなります。
deck は、異なる状況によって僅かに変化するだけの大きな XUL コードでとても役立つ場合があります。例えば、2 つの異なる目的で使用されるウィンドウがあり、それらの違いが、ある場合は値を持ち、もう一つの場合は他の何かになるような、ラベルに違いがあるだけの場合です。この場合は、.properties ファイルと stringbundle 要素を使用する方法がありますが、特に、動的なテキストを必要とする場合だけは、単純なことのために多くのコードを書かなければなりません。代わりに、2 つのラベルを持つ deck を使用し、ウィンドウの目的に応じて selectedIndex を変更する方法があります。この方法なら DTD が使用でき、コードを簡単なままにできます。
stack 要素は deck に似ていますが、常にすべての子ノードが重なって表示されます。これは、複雑な UI を個別のレイヤーに分けることができ、レイアウトの可能性が広がります。stack の一般的な使用方法の一つとして、前面のオブジェクトのサイズに応じて上下左右に引き延ばせる背景画像を置くことができます:
<stack> <hbox flex="1"> <image src="chrome://xulschoolhello/skin/stack-bg.png" flex="1" /> </hbox> <hbox> <!-- コンテンツ --> </hbox> </stack>
背景画像は CSS で引き伸ばすことができないため、この回避策が必要になります。
(※ Firefox 3.6 以降は CSS プロパティの -moz-background-size で可能)
stack 要素のそれほど一般的でない使用方法として、left 属性と top 属性を子ノードに使用して、レイヤー上のコンテンツの絶対位置を指定できます。このような配置の仕方は、様々な芸術的な効果のために役立ちます。また、デスクトップやダッシュボードのようなインタフェースで、ユーザの指定した位置にアイテムを配置したり各アイテムを重ねたりできます。とはいえ、これはとても容易に複雑なコードになってしまいます。
要素を伸縮自在にすることと絶対位置に配置することは同時に行えません。
ツリー
Firefox のブックマークサイドバーと履歴サイドバーは、コンテンツの表示に tree 要素を使用しています。tree は、大量の情報をコンパクトにまとめて表示する必要がある場合に、もう一つの強力な選択肢となります。ツリーには少数のルートノードだけが表示され、ユーザがその中から必要なものを広げられます。ツリーをデータのテンプレートと結びつけると特に力を発揮しますが、このトピックは後で取り上げます。ツリーについての詳細は、XUL チュートリアルのページをお読みください。
tree 要素は、XUL の中で最も複雑な要素かもしれません。用途がとても広く順応性が高いため、特定の用途に合わせるためにある程度の作業が必要になります。ツリーを実際に階層構造を持つテーブルとして表示する場合は、ツリーのコンテンツを行と列に置き換えて定義します。以下は、簡単なツリーの例です:
<tree flex="1"> <treecols> <treecol label="&xulschoolhello.nameColumn.label;" flex="1" /> <treecol label="&xulschoolhello.greetingColumn.label;" flex="3" /> </treecols> <treechildren> <treeitem> <treerow> <treecell label="Peter" /> <treecell label="Hey, what's up?" /> </treerow> </treeitem> <treeitem> <treerow> <treecell label="John"/> <treecell label="Good evening, how are you doing?" /> </treerow> </treeitem> </treechildren> </tree>
tree の行のテキストは、locale ファイルからのテキストを使用していないため、コードに直接書かれています。実際の拡張機能では、データベースやリモート API などのデータソースからのデータを使用します。この tree は、一階層の深さしかないため、たいしたツリーではありません。さらに念入りに作られたツリーは次のようになります:
<tree flex="1"> <treecols> <treecol label="&xulschoolhello.nameColumn.label;" flex="1" /> <treecol label="&xulschoolhello.greetingColumn.label;" flex="3" /> </treecols> <treechildren> <treeitem> <treerow> <treecell label="Peter" /> <treecell label="Hey, what's up?" /> </treerow> </treeitem> <!-- container 属性を指定する必要があるので注意してください --> <treeitem container="true" open="true"> <treerow> <treecell label="John"/> <treecell label="Good evening, how are you doing?" /> </treerow> <treechildren> <treeitem> <treerow> <treecell label="John Jr." /> <treecell label="Bah, bah!" /> </treerow> </treeitem> </treechildren> </treeitem> </treechildren> </tree>
この例では、"John" の行の子ノードに "John Jr." の行があります。treechildren 要素は、John の treeitem 要素の子ノードとして置かれており、treeitem には container 属性が設定されている必要があります。
ツリーのコードを手書きにすることはとても時間がかかるため、多くの XML コードを続けて書くのが大変なことは明らかです。これが、tree 要素を使用する時は外部のデータソースからのデータを表示する大きな理由です。また、JavaScript や DOM 関数を使用してツリーを構築しても、とても複雑になります。そうするよりも、テンプレートを使用して構築したほうがよいでしょう。このトピックについては、後で別の種類のデータソースとテンプレートを見ていく時に取り上げます。
ツリーにスタイルを追加することも興味をそそられます。MDC のガイドに、このことだけを扱ったツリーにスタイル付けする方法のページがあります。ブックマークサイドバーや履歴サイドバーを見れば、ツリーのほとんどの部分が CSS でカスタマイズ可能なことが分かるでしょう。
This tutorial was kindly donated to Mozilla by Appcoast.