いくつもの要素に対して、同じようにイベントに反応させるようにしたり、一括して状態の変化を反映させたいことは、しばしばあると思います。 このために、ブロードキャスタを利用することができます。
コマンドと属性の自動転送
ここまでに説明したように、ボタンなどの要素は、コマンドと結びつけることが可能です。
このとき、
要素に command
属性を付加すれば、そのコマンドに結びつけられた要素も自動的に無効化されます。
これを利用して、作成する必要があるコードを単純化することができます。
また、この技法は、それ以外の属性に対しても適用することが可能です。
例えば、disabled
属性を、label
要素に付加した場合、コマンドに結びつけられたすべてのボタンは、同じラベルを共有することになります。
command
var el = env.locale; 例 1 : ソース 表示
<command id="my_command" label="Open"/> <button command="my_command"/> <checkbox label="Open in a new window" command="my_command"/>
この例では、ボタンは
属性を持っていませんが、結びつけられたコマンドの方が持っています。
このため、ボタンは、コマンドに設定されたラベルを共有することになります。
また、チェックボックスは、最初からラベルを持っていますが、これもコマンドのラベルによって上書きされます。
その結果、ボタンとチェックボックスは、両方とも同じラベル「Open」を持つことになります。
label
コマンドの
属性を変更した場合、ボタンとチェックボックスのラベルも、それに追随して変更されます。
これは、以前のセクションで見た、label
属性の変更が、他の要素へ伝播する挙動と類似しています。
disabled
属性の自動転送は、いろいろな目的のために利用できます。 例えば、ブラウザの「戻る」動作を無効化したいと考えているとします。 このとき、メニューの「戻る」コマンド、ツールバーの「戻る」ボタン、キーボードショートカット (例えば Alt + ←)、ポップアップメニューの「戻る」コマンドのすべてを無効化する必要があります。 このために、スクリプトを作成することもできますが、退屈なコードを大量に記述することになります。 加えて、「戻る」動作が導入されている箇所を、すべて押さえておく必要があるという欠点もあります。 また、この方法では、ブラウザの拡張機能で、新たに「戻る」操作が追加されても、それについては無効化することができません。 しかしながら、単純に「戻る」の動作自体を無効化すれば、「戻る」動作を実行するすべての要素が、自ら無効になるようになっていれば、この機能は簡単に実現できます。 これは、コマンドが持つ属性の自動転送機能を利用することで実現することが可能です。
ブロードキャスタ
コマンドが持っている属性の自動転送と類似の機能を持つ要素として、ブロードキャスタ (
) があります。
ブロードキャスタは、コマンドと同様の方法で属性の自動転送をサポートします。
ブロードキャスタは、コマンドと同じように機能しますが、
コマンドが (複数の操作から起動される) 同一の動作をまとめるために利用されるのに対し、ブロードキャスタは (複数の要素に影響する) 状態に関する情報を保持するために利用される点が異なります。
例えば、 broadcaster
は、「戻る」「切り取り」「削除」といった動作のために利用しますが、
command
は、フラグの保持、具体的には「利用者がオンラインかどうか」といった情報を示すために利用します。
前者の場合は、メニュー項目やツールバーボタンなどを、戻るべきページが無いときや、切り取りや削除の対象となるテキストが無いときなどに、一括して無効化する必要があり、
後者の場合は、利用者がオフラインからオンラインにモードを切り替えたときに、種々の UI 要素の状態を更新する必要があることを想定しています。
broadcaster
ブロードキャスタの最も単純な記述例を以下に示します。
他の要素から参照可能にするために、
属性は常に設定する必要があります。
id
<broadcasterset> <broadcaster id="isOffline" label="Offline"/> </broadcasterset>
このブロードキャスタを「観察」している任意の要素は、ブロードキャスタの
属性が変更されるのに応じて、自動的に変更されていきます。
他の表示されない要素と同様に、label
要素が、ブロードキャスタの置き場所として提供されています。
すべてのブロードキャスタは、一箇所にまとめておくために、broadcasterset
要素内に宣言しておくべきでしょう。
broadcasterset
要素をオブザーバとして設定する
ブロードキャスタを「観察」している要素のことを、オブザーバ (observer) と呼びます。
要素をオブザーバにするためには、
属性を追加します。
これは、要素を observes
要素に結びつけるときに、command
属性を利用するのと類似しています。
例えば、ボタンを上記のブロードキャスタのオブザーバにする場合は、以下のようになります。
command
<button id="offline_button" observes="isOffline"/>
このボタンには、
属性が置かれており、値には観察対象となるブロードキャスタの observes
が設定されています。
この例では、ボタンは、前の例で定義した id
isOffline
を id とするブロードキャスタを観察することになります。
このため、ブロードキャスタの
属性の値が変更されると、オブザーバの label
属性の値も更新されます。
label
さらに、他の要素をオブザーバとして追加していくことが可能です。 1 つのブロードキャスタを観察する要素はいくつ設定してもかまいません。 もちろん、観察する要素は 1 つだけでもよいのですが、それではあまり得られるものがありません。 ブロードキャスタを使用する主な目的は、属性を複数の箇所へ転送することにあるからです。 ブロードキャスタは、複数の要素が属性を観察する必要があるときにのみ利用するべきだと思います。 以下に、いくつかのオブザーバを追加で定義した例を示します。
<broadcaster id="offline_command" label="Offline" accesskey="f"/> <keyset> <key id="goonline_key" observes="offline_command" modifiers="accel" key="O"/> </keyset> <menuitem id="offline_menuitem" observes="offline_command"/> <toolbarbutton id="offline_toolbarbutton" observes="offline_command"/>
この例では、
と label
が、ブロードキャスタから、キー要素、メニュー項目、ツールバーボタンへと転送されます。
このとき、キー要素は、受け取った属性をどれも利用しませんが、ブロードキャスタが無効化されるとそれに応じて無効化されることになります。
accesskey
ブロードキャスタは、任意の属性を観察するために利用できます。
オブザーバは、ブロードキャスタから、任意に設定された属性の値を全部、値が変更されるたびに受け取ります。
ブロードキャスタの、任意の属性のいずれかの値が変更されたときは、全てオブザーバに通知され、オブザーバは自分の属性値で該当するものを更新します。
ブロードキャスタに設定されていない属性については、オブザーバの属性は変更されません。
ただし、
と id
の 2 つの属性については、共有させることはありえないため、オブザーバ側が更新されることはありません。
また、開発者が独自に定義した属性についても、必要なら利用することが可能です。
persist
ほとんど場面でコマンドが使えるため、ブロードキャスタはそれほど頻繁には用いられません。
属性の自動転送という点から見たとき、
要素と command
要素に実質的な違いはありません。
この 2 つは、挙動としては同じですが、使用する場合の意味づけの部分が異なっています。
コマンドは動作に、ブロードキャスタは状態のために使用するようにしてください。
なお、意味づけを無視すれば、実際には、broadcaster
属性の値として、ブロードキャスタ以外の要素を設定してもかまわないため、
任意の要素をブロードキャスタのように振舞わせることも可能です。
observes
observes 要素
ブロードキャスタを観察するとき、特定の属性だけを観察するように限定する方法もあります。
そのためには、
要素を利用します。
この要素を、観察したい属性と対になるように置くことで、要素をオブザーバとして定義することが可能です。
observes
要素は、オブザーバとなる要素の子要素にする必要があります。
以下に例を示します。
observes
var el = env.locale; 例 2 : ソース 表示
<broadcasterset> <broadcaster id="isOffline" label="Offline" accesskey="f"/> </broadcasterset> <button id="offline_button"> <observes element="isOffline" attribute="label"/> </button>
要素には、2 つの属性が設定されています。
最初の observes
属性には、観察するブロードキャスタの id を指定します。
2 番目の element
属性には、観察する属性を指定します。
この例では、指定の結果、ボタンのラベルがブロードキャスタから転送されるようになるため、
ブロードキャスタのラベルが変更されると、ボタンのラベルも更新されることになります。
このとき、attribute
要素自身は変更されませんが、代わりに、この要素を中に含んでいる、ボタン (observes
) 要素が変更されることになります。
なお、button
属性は、観察されていないので、ボタンには転送されないことに注意してください。
もし accesskey
属性も観察させたいのなら、もう 1 つ accesskey
要素を追加する必要があります。
または、observes
要素を利用する代わりに、 observes
属性をボタンに直接設定することで、すべての属性を観察させることもできます。
observes
broadcast イベント
要素には、付加的なイベントハンドラ observes
onbroadcast
を設定することができます。
このイベントは、ブロードキャスタの属性の変化が、観察しているオブザーバに通知されるときに発生します。
以下に例を示します。
var el = env.locale; 例 3 : ソース 表示
<broadcasterset> <broadcaster id="colorChanger" style="color: black"/> </broadcasterset> <button label="Test"> <observes element="colorChanger" attribute="style" onbroadcast="alert('Color changed');"/> </button> <button label="Observer" oncommand="document.getElementById('colorChanger').setAttribute('style','color: red');" />
この例では、2 つのボタンがあります。 1 つは「Test」、もう 1 つは 「Observer」というラベルがつけられています。 Test ボタンがクリックされても何も起きませんが、 Observer ボタンがクリックされると 2 つのことが発生します。 まず、Test ボタンのテキストが赤色になり、次に、「Color changed」というメッセージのアラートが表示されます。
このとき発生した事象を順に見ていくと、
まず、Observer ボタンがクリックされて、その
ハンドラが呼び出されます。
そのスクリプトでは、ブロードキャスタへの参照を取得し、そのスタイルの oncommand
color
を、赤(red)に変更しています。
このとき、ブロードキャスタ自体は画面に表示されないので、何の影響も与えませんが、Test ボタンにはスタイルの変化の通知を受けるオブザーバが存在します。
要素の observes
と element
属性によって、スタイルの変化が検知されます。
スタイルの変更は、自動的に Test ボタンに適用されます。
attribute
次に、ブロードキャストによる転送が発生したため、イベントハンドラ onbroadcast
が呼び出されます。
この結果、アラートメッセージが表示されます。
この broadcast イベントは、
要素の属性が変化した場合についてのみ発生することに注意して下さい。
ボタンのスタイルを直接変更したとしても、broadcast イベントは発生しないため、アラートは表示されません。
broadcaster
最初の
(Test ボタン) のコードをいくつか複製した場合、複製したボタンに対して 1 つずつ、複製した個数分のアラートが表示されることになります。
これは、それぞれのボタンがオブザーバであり、スタイルが変更されると、全てに通知が行われるためです。
button
次のセクションでは、 XUL 要素による文書オブジェクトモデルの利用について見ていきます。