イベントハンドラ
HTML の場合と同様に、ほとんどの JavaScript コードは、DOM 要素に取り付けられたイベントハンドラによって実行が開始されます。最も一般的に使用されるイベントは、onload イベントです。これは、オーバーレイや他のウィンドウでウィンドウが読み込まれたことを検出し、初期化コードを実行するために使用されます:
// オーバーレイコードの最後尾に記述します。 window.addEventListener( "load", function() { XulSchoolChrome.BrowserOverlay.init(); }, false);
似たイベントに onunload イベントがあります。これは、コードの後始末をする時に必要になります。
HTML の場合と同様にイベントハンドラを取り付けるもう一つの方法は、ハンドラを XUL コード内に置くことです:
<overlay id="xulschoolhello-browser-overlay" onload="XulSchoolChrome.BrowserOverlay.init();" xmlns="https://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
コンテンツと振る舞いを分けられるため、私たちは最初の方法を好んで使用します。また、要素の属性には "on" プレフィックスが付きますが、addEventListener メソッドは、プレフィックスなしのイベント名を受け取ることに注意してください。リッスンできるイベントのリストを参照して、状況に合ったものを使用してください。要素には、その要素に関連するイベントのみが実装されていますが、ほとんどの要素に実装されているイベントもいくつかあります。特に、下記のイベントを覚えておくとよいでしょう:
- oncommand イベント。これは、XUL で一般的に使用されるイベントの中で最も重要なものです。メニューアイテムやボタン、チェックボックスなどの入力コントロールのための動作を提供する、とても役立つイベントです。ボタンの場合は、ユーザがクリックした時やキーボードでフォーカスして Enter キーを押した時の動作を提供します。このイベントを使用することにより、コントロール要素に対する操作方法を抽象化できます。
- onselect イベント。ツリーやリストボックスで選択が変更された時に発生します。
- onclick イベント。ユーザが要素をクリック (右クリックを含む) した時に発生します。通常は、このイベントをボタンなどの入力要素上で動作の引き金に使用してはいけません。代わりに oncommand イベントを使用してください。
- onfocus と onblur イベント。ユーザがキーボードで操作して要素がフォーカスを受け取った時や外された時に使用されます。フォーカス時の通常とは異なる動作を要素に追加するため、これらのイベントを -moz-user-focus と組み合わせることができます。
- ドラッグ&ドロップ。ドラッグ&ドロップ操作は、いくつかのイベントを発生させます。ドラッグ&ドロップの管理は複雑なため、その作業を楽にする高レベルのラッパーが用意されています。また、ドラッグ&ドロップには 2 つの API が有り、お勧めの新しい方は Firefox 3.5 で導入されました。
イベントハンドラは、event 引数を取ることができます。これは、イベント上の情報を保持する Event オブジェクトです。修飾キー (イベント中にユーザが Alt キーなどの修飾キーを押したままにしている場合) の情報やマウスイベントのためのスクリーン座標、そして最も重要なイベントのターゲット要素の情報を得ることができます。例えば、次のように記述します:
<button label="&xulschoolhello.defaultGreeting.label;" oncommand="XulSchoolChrome.BrowserOverlay.changeGreeting(event);" />
そして、JavaScript コードでは次のようにします:
changeGreeting : function(aEvent) { // more stuff aEvent.target.setAttribute("label", someNewGreeting); }
この例のターゲットは button 要素です。クリックすると、このボタンのテキストが変更されます。event 引数を使用する利点は、メソッドが特定のボタンに依存しないことです。そのため、このメソッドを他の要素にも使用することができます。
さらに詳しいイベントの扱い方については、Event Propagation についてのページをお読みください。簡単に説明すると、イベントの伝達は、キャプチャフェーズで DOM ツリーのルートから目的の要素まで降り、次のバブルフェーズでルートへと戻ります。これらのフェーズ中に、いつでもイベントをキャプチャまたはキャンセルできます。これらのイベントがキャプチャされる地点に到達する前にキャンセルされることはありません。addEventListener メソッドで関数の最後の引数を与えると、イベントを扱うフェーズの制御ができます。
カスタムイベント
これは、あまり使わなくても知っておくべき、とてもパワフルなツールです。DOM createEvent は、ディスパッチとキャプチャが可能なカスタムイベントを作成できる関数です。
カスタムイベントは、役立つコミュニケーション機構として利用できます。特に、XUL ウィンドウとウェブページのコンテンツの間でコミュニケーションを取りたい場合など、一般的な問題に対処する時に役立ちます。ページの読み込み中や表示中に、そのコンテンツを XUL コードで制御することは難しくありません (後で取り上げます) が、あなたの拡張機能の XUL コードが安全な方法でページから情報を受け取ることは難しくなります。ウェブサイトの JavaScript が Firefox や実行中の JavaScript を chrome 特権で制御できてしまい、全く安全でなくなるからです。
例えば、あなたの拡張機能がウェブサイトのページと対話し、このサイト上の何らかの引き金によってあなたの拡張機能に行動を起こさせたいとします。これを解決する一つの方法は、あなたの拡張機能が簡単に認識できるカスタムイベントをサイト上で生成することです。この発生したイベントを、XUL オーバーレイ内でキャプチャしてください:
// オーバーレイのコード内 document.addEventListener( "XSHelloGreetingEvent", function(aEvent) { /* do stuff*/ }, false);
これを行う時は注意してください! 少なくとも、カスタムイベントが生成されたページの URL が正しいか検証すべきです。また、この種類のイベントから起こる動作によって、ユーザのデータが破壊されないようにすべきです。悪意のあるサイトは、これらのイベントによってユーザに損害を与えようとします。ここに、リモートコンテンツとローカルの chrome を分けておく理由があります。必ず守ってください。
さらに後の Intercepting Page Loads セクションで、このセクションを補い、ウェブコンテンツと XUL の間の対話を扱うための基礎固めができます。カスタムイベントについての追加の情報と、ウェブコンテンツと XUL の間のコミュニケーションに使用する方法は、Interaction between privileged and non-privileged pages のコードの例を参照してください。この種類のコミュニケーションについての説明があります。
ブロードキャスタ
一貫性のある UI を保つことも、拡張機能の動作にとって重要な側面です。場合によって、あなたの拡張機能は、ユーザがサービスへログインまたはログアウトした時、あるいは Firefox の状態がオンラインまたはオフラインへ切り替わった時、これらの制御を有効または無効にする必要があります。同時にいくつかの要素を変更する必要があるケースがありますが、これは、JavaScript から管理することは困難です。このようなケースでは、broadcaster 要素を利用してください。
はじめに、broadcaster 要素を broadcasterset 要素の子要素として XUL コードに追加する必要があります。
<broadcasterset id="xulschoolhello-broadcasterset"> <broadcaster id="xulschoolhello-online-broadcaster" /> </broadcasterset>
これらの要素は、完全に不可視なため XUL コード内のどこにでも記述することができますが、他の popupset や commandset などの不可視の要素と共に XUL コードの最上部に記述することをお勧めします。
次に、observes 属性 を使用して、このブロードキャスタとリンクされる XUL 要素を指定する必要があります:
<menuitem id="xulschoolhello-hello-menu-item" label="&xulschoolhello.hello.label;" accesskey="&xulschoolhello.helloItem.accesskey;" observes="xulschoolhello-online-broadcaster" oncommand="XULSchoolChrome.BrowserOverlay.sayHello(event);" />
この属性の値には、broadcaster 要素の id を設定します。これは、この要素が broadcaster に起こるすべての属性の変化を観察することを示します。broadcaster を観察する要素は、いくつでも増やせます。
次に必要なことは、JavaScript を使用して broadcaster 要素内の属性を設定または削除することだけです。これらの属性値は、これを観察するすべてのノードによって自動的に設定または削除されます。また、次の例の label のように既存の値を上書きすることもできます。
let onlineBroadcaster = document.getElementById("xulschoolhello-online-broadcaster"); onlineBroadcaster.setAttribute("label", "Something");
また、observes 要素を観察ノードの子要素として追加することにより、この動作をきめ細やかに制御できます。この要素で観察したい属性を選択できます。
ブロードキャスタは、多くのコードを追加することなく、数多くの要素の一貫性を簡単に管理できるようにします。また、与えられた要素が DOM 内のものかどうか知っておく必要もありません。例えば、カスタマイズ可能なツールバーに与えられたボタンが配置されているかどうか分からない場合、broadcaster を使えば簡単に知ることができます。この方法では、ボタンが配置されているか確認する代わりに、broadcaster に値を設定するだけで済みます。
コマンド
command 要素は、oncommand イベントと共に使用される、コマンドに特化した broadcaster の一種です。これは、Firefox や拡張機能で共通の UI 動作にするための推奨された方式です。command 要素は Firefox で数多く使用されています。DOM Inspector で確認してみてください。
これらの動作は broadcaster 要素と全く同じですが、これらは共有された属性に oncommand がある時に使用されます。私たちのメニューの例に、コマンドの良い実装例があります。
<commandset id="xulschoolhello-commandset"> <command id="xulschoolhello-hello-command" oncommand="XULSchoolChrome.BrowserOverlay.sayHello(event);" /> <!-- More commands. --> </commandset> <!-- More code here... --> <menuitem id="xulschoolhello-hello-menu-item" label="&xulschoolhello.hello.label;" accesskey="&xulschoolhello.helloItem.accesskey;" command="xulschoolhello-hello-command" />
コマンドを command 要素を使用することで、JavaScript の呼び出しを一か所まとめ、コードの重複やバグを避けることができます。また、UI を簡単に調整できます。XUL コードをいくつも繰り返し記述することなく、同じ動作のツールバーボタンやステータスバーボタン、メニューアイテムを追加する拡張機能を作成できます。コマンドとブロードキャスタは、複雑なフォームを持つウィンドウやダイアログの作成を楽にしてくれます。イベント駆動型のコードを拡張機能に追加する時は、これらのことを常に心に留めておいてください。
This tutorial was kindly donated to Mozilla by Appcoast.