このセクションでは、イベントオブジェクトについて調査し、その後、付加的なイベントについても説明します。
イベントオブジェクト
それぞれのイベントハンドラは、イベントオブジェクトを保持する引数を、1 つとります。 属性形式のイベントリスナーでは、このイベントは、スクリプトコードから「event
」という名前で参照可能な暗黙の引数になります。 addEventListener 形式の場合は、リスナー関数の第 1 引数がイベントオブジェクトになります。 イベントオブジェクトには、イベント処理の間に調査可能なプロパティがたくさんあります。 プロパティの完全な一覧は、XULPlanet のオブジェクトリファレンス で参照可能です。
前のセクションでは、イベントが発生した要素への参照を保持する、event
の target
プロパティについて見ています。 それと類似したプロパティである currentTarget
は、現在処理中のイベントリスナーを持っている要素を保持しています。 下の例では、currentTarget
は常に vbox
を保持しますが、 target
は、特定の要素、つまり button
か checkbox
のどちらか活性化された方を保持します。
<vbox oncommand="alert(event.currentTarget.tagName);"> <button label="OK"/> <checkbox label="Show images"/> </vbox>
イベント伝播の中止
どこかでイベントを処理したのなら、そのイベントがどこまで伝播 されたかに関係なく、そのイベントが他の要素にも送信されるのを止めたい、 言い換えると、捕捉フェーズや、浮上フェーズが続かないように停止したいことがあると思います。 イベント伝播を停止する方法は、イベントリスナーを要素へ結びつける方法に依存して、いくつかの手段があります。
イベントの捕捉フェーズは、浮上フェーズの前に行われることを思い出してください。 捕捉リスナーは、常に浮上リスナーの前に起動されます。 イベント捕捉処理によって、イベントの伝播が中止された場合、後続の捕捉リスナーや全ての浮上リスナーは、イベントの通知を受けることはありません。 イベントの伝播を中止させるには、以下の例で示すように、イベントオブジェクトの stopPropagation
メソッドを呼び出します。
<hbox id="outerbox"> <button id="okbutton" label="OK"/> </hbox> <script> function buttonPressed(event){ alert('Button was pressed!'); } function boxPressed(event){ alert('Box was pressed!'); event.stopPropagation(); } var button = document.getElementById("okbutton"); button.addEventListener('command',buttonPressed,true); var outerbox = document.getElementById("outerbox"); outerbox.addEventListener('command',boxPressed,true); </script>
この例では、個別のイベントリスナーがボタンとボックスのそれぞれに設定されています。 stopPropagation
メソッドが、ボックスのリスナーから呼び出されるため、ボタンのリスナーが呼び出されることはありません。 stopPropagation
の呼び出しを取り除いた場合、両方のリスナーが呼び出され、両方のアラートが現れることになります。
デフォルトの動作を妨げる
イベントに対応するイベントハンドラが登録されていない場合は、捕捉と浮上の両方のフェーズが終了した後、要素はそのイベントをデフォルトの方法で処理します。 何が行われるかは、イベントの種類と要素の種類に依存します。 例えば、「popupshowing」イベントは、ポップアップへ表示直前に送られて、デフォルトの動作はポップアップの表示になります。 このデフォルトの動作を妨げた場合、ポップアップは表示されなくなります。 デフォルトの動作を妨げるには、イベントオブジェクトの preventDefault
メソッドを、以下の例のように呼び出すことで可能です。
<button label="Types" type="menu"> <menupopup onpopupshowing="event.preventDefault();"> <menuitem label="Glass"/> <menuitem label="Plastic"/> </menupopup> </button>
あるいは、属性イベントリスナーの場合は、単にコードから false を返すことでも可能です。 デフォルトの動作をさせないことと、 stopPropagation
メソッドで、イベントの伝播を中止することとは同じではないことに注意してください。 デフォルトの動作が妨げられたとしても、イベントの伝播は続行されます。 同様に stopPropagation
メソッドは、デフォルトの動作を妨げません。 両方とも止めたい場合は、両方のメソッドを呼び出さなければなりません。
伝播、あるいはデフォルトの動作のいずれにおいても、いったん中止された場合、そのイベントに対しては、どちらも再開させることはできないことに注意してください。
以下に、利用可能なイベントの一部について記述します。 完全な一覧は、XULPlanet のイベントリファレンス で参照することができます。
マウスイベント
マウス固有の動作に対する処理に用いられるイベントを、以下に記述します。
- click
- 要素の上で、マウスボタンが押されて離されたときに呼び出されます。
- dblclick
- マウスボタンがダブルクリックされたときに呼び出されます。
- mousedown
- 要素の上で、マウスボタンが押された瞬間に呼び出されます。イベントハンドラはマウスボタンが押された直後に、離されるのを待たず、呼び出されます。
- mouseup
- 要素の上で、マウスボタンが離されたときに呼び出されます。
- mouseover
- 要素の上に、マウスポインタが重なったときに呼び出されます。これを要素のハイライト処理に利用することもできますが、 CSS で自動的に行う方法が提供されているため、イベント処理で行うべきではありません。といっても、ステータスバーに何らかのヘルプを表示させたい場合には使う必要があるでしょう。
- mousemove
- 要素の上で、マウスポインタが動いたときに呼び出されます。ユーザがマウスを動かすたびにイベントが呼び出されるため、このハンドラで時間を要する処理を行うことは避けるべきです。
- mouseout
- 要素の上から、マウスポインタが離れたときに呼び出されます。要素のハイライトを消したり、ステータスバーのテキストを取り除くために利用できます。
利用者が、マウスボタンを押し下げたまま、マウスをあちこちに動かすときに発生する、ドラッグ関連のイベントもあります。 それらのイベントは、ドラッグ&ドロップに記述されています。
マウスボタンイベントプロパティ
マウスボタンイベントが発生した場合、イベントオブジェクトにはどのマウスボタンが押されたかや、マウスポインタの位置などを表す、付加的なプロパティが多数利用可能になります。 どのマウスボタンが押されたかは、event
の button
プロパティにより得られます。 設定される値は、 0 が左ボタン、1 が中央ボタン、2 右はボタンになります。 ただし、マウスの設定を変えた場合、これらの値とは異なっていることがあります。
detail
プロパティは、ボタンが何回連続して素早くクリックされたかを保持しています。 これによりシングルクリック、ダブルクリック、トリプルクリックの判別が可能になります。 もちろん、ダブルクリックのみのチェックを行いたい場合は、代わりに dblclick を使うことができます。 click イベントは最初のクリックで一度、次のクリックでもう一度、3度目のクリックで更にもう一度といった具合に送出されますが、 dblclick イベントは、ダブルクリックごとに、一度だけ送出されます。
button
と detail
プロパティは、マウスボタン関連のイベントにのみ設定され、マウスポインタ移動関連のイベントには設定されません。 例えば、mousemove イベントでは、両プロパティとも 0 に設定されます。
マウス位置イベントプロパティ
また、イベントが発生したときのマウス位置の座標を保持するプロパティについては、すべてのマウスイベントで設定されます。 設定される座標は、2 つあり、それぞれ基点が異なっています。 まず、screenX
と screenY
プロパティは、画面 (screen) の左上隅からの相対座標を示しています。 次に、clientX
と clientY
プロパティは、文書の左上隅からの相対座標を示しています。 マウス座標を表示する例を、以下に示します。
<script> function updateMouseCoordinates(event){ var text = "X:" + event.clientX + " Y:" + event.clientY; document.getElementById("xy").value = text; } </script> <label id="xy"/> <hbox width="400" height="400" onmousemove="updateMouseCoordinates(event);"/>
この例では、効果の確認を容易にするために、ボックスのサイズを明示的に指定しています。 イベントハンドラは、clientX
と clientY
プロパティを取得して文字列に変換し、ラベルの value
プロパティに代入しています。 引数として、「event
」を updateMouseCoordinates
関数に渡さなければならないことに注意してください。 また、マウスを、ボックスの境界を越して素早く動かしたとき、座標の更新がボックスの境界である 400 の手前で止まることが確認できると思います。 これは、mousemove イベントが、マウスの動く速さに依存した間隔で発生するために、 マウスが境界から若干離れたところにある場合でも、次のイベントが発生するまでの間に、境界を越した位置まで移動することができるためです。 明らかに、マウスの軌跡にあるすべての画素を通過するごとに mousemove イベントを送出するのが非効率すぎるということは理解してもらえる思います。
要素相対の座標
イベントが発生した場所を、ウインドウ全体ではなく、その要素との相対的な座標で取得したいことは、しばしばあると思います。 そのためには、次のコードで示すように、イベントの位置から要素の位置を引き算することで求めることが可能です。
var element = event.target; var elementX = event.clientX - element.boxObject.x; var elementY = event.clientY - element.boxObject.y;
XUL 要素は、ボックスオブジェクトを持っており、
プロパティを利用して取得できます。 ボックスオブジェクトについての詳細は、後のセクションで学ぶことになりますが、 ここでは、とりあえず要素の x, y 座標を含む、要素の表示のされ方に関係する情報を保持しているものであると理解してください。 この例のコードでは、boxObject
から得られる要素の座標と、イベントの座標の引き算を行うことで、要素内の相対的なイベントの位置を算出しています。boxObject
load イベント
load イベントは、XUL ファイルの読み込みが完了して、内容が表示される直前に、文書 (
タグ) に送出されます。 通常、このイベントは、利用者にウインドウが使用可能になる前に行う必要のある、フィールドの初期化などの処理を行うために使用されます。 なお、こういった初期化処理は、スクリプトを関数の外のトップレベルに追加するのではなく、load イベントを利用して行うべきです。 そうしないと、XUL 要素が読み込まれる前だったり、完全に初期化されていないことがあるため、何かが予期した動作にならない可能性があります。 load イベントを使うには、 window
タグ内に window
属性を設定します。 必要に応じて、インターフェイスを初期化するコードを load ハンドラから呼び出すようにしてください。onload
ウインドウが閉じられたとき、あるいはブラウザに表示されている場合で、ページが別の URL に変えられたときに呼び出される、unload イベントというのもあります。 このイベントは、例えば変更された情報を保存する場合などに利用できます。
次のセクションでは、キーボードショートカットの追加方法について見ていきます。