XBL で定義した要素へのイベントハンドラの追加

続いては、XBL で定義された要素にイベントハンドラを追加する方法について見ていきます。

イベントハンドラ

通常の XUL の場合と同じように、XBL がバインドされた要素で発生したマウスクリックやキーの押し下げなどのイベントは、そのままコンテントの中にある個々の要素にも送られていきます。 XBL の場合には、イベントをトラップして処理するときにも専用の方法を用いる必要があると予測していたかもしれませんが、 前のセクションの最後の例で示したように、XBL のコンテントの中に置かれた要素には、必要に応じてイベントハンドラを追加することが可能です。 そのときの例では、いくつかのボタンに対して oncommand ハンドラの追加を行いました。

handler 要素

しかしながら、コンテント全体、つまり content タグの中で定義されたすべての要素を対象にしたイベントハンドラを追加したい場合もあると思います。 これは、フォーカスイベントやブラーイベントをトラップするような場面で役に立つはずです。 このようなイベントハンドラは、handler 要素を使用して定義できます。 この要素には、単一のイベントハンドラと対応するアクションを記述していきます。 また、必要なら、複数のハンドラを使用することも可能です。 イベントが handler の対象イベントのどれともマッチしない場合は、通常の場合と同じように、単に内側のコンテントに送られることになります。

一般的なハンドラの構文は、以下のようになります。

<binding id="binding-name">
  <handlers>
    <handler event="event-name" action="script"/>
  </handlers>
</binding>

ハンドラはすべて、handlers 要素の中に置きます。 個々の handler 要素では、event 属性で指定した特定のイベントを処理するためのアクションを定義します。 イベントには、clickfocus といった、XUL と JavaScript でサポートしている種類のものであれば指定することが可能です。 なお、使用するイベント名の最初に「on」を付けないことに注意してください。

このハンドラは、イベントが発生したときにカスタムプロパティを変更するために、よく利用されます。 例えば、カスタムチェックボックスを作成する場合には、 checked プロパティを、利用者がチェックボックスをクリックしたときに変更する必要があるかもしれません。

<handlers>
  <handler event="mouseup" action="this.checked=!this.checked"/>
</handlers>

上記のチェックボックス上で、利用者がマウスボタンをクリックして放したとき、 mouseup イベントが送出されて、ここで定義したハンドラが呼び出されます。 その結果、checked プロパティの状態が反転します。 また、同様に要素がフォーカスを得たときにプロパティを変更したい場合もあると思います。 このとき、場合によっては特殊なスタイルプロパティ -moz-user-focus を利用して、 要素がフォーカス可能であるか否かを変更する必要があるかもしれません。 このプロパティによって、要素がフォーカス可能かどうかを制御することが可能です。 (参照: フォーカスと選択)

マウスイベントを処理する

マウスイベントの場合、button 属性を使用することで、 ハンドラに対して特定のボタンで起こったイベントだけをトラップするように指定することが可能です。 この属性がない場合には、ハンドラは、どのボタンが押された場合のイベントでも全てトラップすることになります。 button 属性に設定する値には、左マウスボタンを対象にする場合は「0」、中央マウスボタンの場合は「1」、右マウスボタンの場合は「2」を設定します。

<handlers>
  <handler event="click" button="0" action="alert('Left button pressed');"/>
  <handler event="mouseup" button="1" action="alert('Middle button pressed')"/>
  <handler event="click" button="2" action="alert('Right button pressed');"/>
</handlers>

キーイベントを処理する

また、キーイベントの場合は、マッチさせるキーを指定したり、特定の修飾キーが押されている場合だけマッチするように限定したりするために、 XUL の key 要素が持っている属性に類似した、いくつかの属性を使用することが可能です。 前の例を拡張して、スペースバーが押された場合に、チェックボックスの checked プロパティの変更を行うようにする例を以下に示します。

<handlers>
  <handler event="keypress" key=" " action="this.checked=!checked"/>
</handlers>

また、文字で表すことのできないキーをチェックするために、keycode 属性を使用することも可能です。 なお、キーコードの指定値など、さらに詳細な情報については、キーボードショートカットのセクションを参照してください。 また、修飾キーについては、modifiers 属性を追加することでチェックできます。 ここには、以下の値のいずれかを設定します。

alt
利用者が、Alt キーを押す必要があります。
control
利用者が、Control キーを押す必要があります。
meta
利用者が、Meta キーを押す必要があります。
shift
利用者が、Shift キーを押す必要があります。
accel
利用者が、そのプラットフォームで通常キーボードショートカットを呼び出すために使われる修飾キーを押す必要があります。

上記を設定すると、ハンドラはその修飾キーが押されていた場合のみ呼び出されます。 また、これらをスペースで区切って指定することで、複数の修飾キーが押されている場合のみに限定することも可能です。

ハンドラで行うコードが複雑な場合、以下のような構文を代わりに使用することができます。

<binding id="binding-name">
  <handlers>
    <handler event="event-name">
      -- handler code goes here --
    </handler>
  </handlers>
</binding>

ハンドラの例

以下の例では、キーのハンドラをいくつか追加することで、単純なローカルのクリップボード機能を作成しています。

例 1 : ソース

<binding id="clipbox">
  <content>
    <xul:textbox/>
  </content>
  <implementation>
    <field name="clipboard"/>
  </implementation>
  <handlers>
    <handler event="keypress" key="x" modifiers="control"
      action="this.clipboard=document.getAnonymousNodes(this)[0].value; document.getAnonymousNodes(this)[0].value='';"/>
    <handler event="keypress" key="c" modifiers="control"
      action="this.clipboard=document.getAnonymousNodes(this)[0].value;"/>
    <handler event="keypress" key="v" modifiers="control"
      action="document.getAnonymousNodes(this)[0].value=this.clipboard ? this.clipboard : '';"/>
  </handlers>
</binding>

コンテントには、テキスト入力欄が 1 つだけあります。 また、クリップボードの内容を保存するために clipboard フィールドが追加されています。 このため、このクリップボードの操作対象は、この 1 つのテキストボックスのみに限られるということになります。 ただし、この要素を複数生成した場合には、個々のクリップボードは、それぞれでバッファを持つことになるので互いの操作が干渉することはありません。

3 つのハンドラが、切り取りコピー貼り付けのために追加されています。 それぞれのハンドラには、呼び出すためのキーストロークが設定されています。 最初のハンドラは、切り取り操作で、Control キーと x キーが押された場合に呼び出されます。 action 属性に置かれたスクリプトでは、テキスト入力欄のテキストの切り取りと、clipboard フィールドへの保存を行います。 この例は、単純化するため、選択された部分のテキストを切り取るのではなく、単にテキスト全体の切り取りを行います。 このとき、このコードは以下のように動作します。

  1. this.clipboard=document.getAnonymousNodes(this)[0].value;
    
    匿名コンテント配列の最初の要素、つまり、content 要素に置かれた最初 (唯一) の要素である textbox 要素への参照が取得されます。その value プロパティが取得されることで、テキスト入力欄のテキストが取得されます。続いて、この値を clipboard フィールドに代入します。これによって、テキスト入力欄のテキストが、この専用のクリップボードにコピーされることになります。
  2. document.getAnonymousNodes(this)[0].value=''
    
    次に、textbox のテキストとして空の文字列を代入します。これは、テキスト入力欄の テキストをクリアする効果があります。

また、コピー操作も同様ですが、処理後、テキストをクリアしない点が異なります。 貼り付け操作は逆の処理、 つまりテキスト入力欄の値に、clipboard フィールドの値を代入する操作が行われます。 なお、実用レベルで、こうしたクリップボードのキーボードショートカットを実装する場合には、 本物のクリップボードインタフェースを利用するとともに、選択中のテキストのみが処理されるようにする必要があるはずです。

次のセクションでは、既存の XBL 定義を拡張する方法について見ていきます。

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

 このページの貢献者: teoli, ethertank, Mgjbot, Morishoji
 最終更新者: teoli,