blob: 81c2359c5208b168444b70be921987cc0f1fd34f (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
---
title: PopupEvents
slug: Archive/Mozilla/XUL/PopupGuide/PopupEvents
tags:
- XUL
- XUL Popup Guide
translation_of: Archive/Mozilla/XUL/PopupGuide/PopupEvents
---
<h2 id="Popup_Events" name="Popup_Events">ポップアップイベント</h2>
<p>ポップアップやメニューに関連するイベントにはいくつかの種類があります。</p>
<p>以下の一覧はそれらのイベントの概要です。</p>
<table class="standard-table">
<tbody>
<tr>
<th><code>contextmenu</code></th>
<td>コンテキストメニューを開くように要求したときに、キーボードとマウスのどちらによって開かれるかに関わらず発生する。このイベントは、コンテキストメニューを関連付けられていない要素に対しても発生する。詳しい利用法は<a href="/ja/docs/XUL/PopupGuide/ContextMenus#Context_Menu_Events">コンテキストメニューイベント</a>を参照。</td>
</tr>
<tr>
<th><code>popupshowing</code></th>
<td><code>menupopup</code> 、<code>panel</code> 、<code>tooltip</code> において、それらが表示される直前に発生する。一般に、コンテキストに基づいてポップアップ上のアイテムを追加または調整するのに使用される。</td>
</tr>
<tr>
<th><code>popupshown</code></th>
<td><code>menupopup</code> 、<code>panel</code> 、<code>tooltip</code> において、それらが表示されるとすぐに発生する。</td>
</tr>
<tr>
<th><code>popuphiding</code></th>
<td><code>menupopup</code> 、<code>panel</code> 、 <code>tooltip</code> において、それらが隠されようとするとすぐに発生する。ユーザがメニューからアイテムを選択した場合にも、他の部分をクリックしてポップアップを閉じた場合にも発生する。</td>
</tr>
<tr>
<th><code>popuphidden</code></th>
<td><code>menupopup</code> 、<code>panel</code> 、 <code>tooltip</code> において、それらが隠されるとすぐに発生する。</td>
</tr>
</tbody>
</table>
<h3 id="The_popupshowing_event" name="The_popupshowing_event"><code>popupshowing</code> イベント</h3>
<p>ポップアップが表示される直前には、そのポップアップで <code>popupshowing</code> イベントが発生します。このイベントは、ポップアップが開かれる方法に関係なく、ユーザの操作によって開かれた場合にも、スクリプトから <span id="m-openPopup"><code><a href="https://developer.mozilla.org/ja/docs/Mozilla/Tech/XUL/Method/openPopup">openPopup</a></code></span> メソッドや <span id="m-openPopupAtScreen"><code><a href="https://developer.mozilla.org/ja/docs/Mozilla/Tech/XUL/Method/openPopupAtScreen">openPopupAtScreen</a></code></span> メソッドを呼び出した場合にも発生します。<code>popupshowing</code> イベントのリスナーは、一般にコンテキストに基づいてポップアップの内容を調整するのに使用されます。たとえば画像上で右クリックしたら画像に関係するアイテムをコンテキストメニューに表示し、リンク上で右クリックしたらリンクに関係するアイテムを表示するといったことができます。<code>popupshowing</code> イベントリスナーでは、メニューが表示される前に、必要に応じてメニューの追加や変更を行うことができます。<code>popupshowing</code> イベントのコンテキストメニューに対する使用例は<a href="/ja/docs/XUL/PopupGuide/ContextMenus#Hiding_and_Showing_Menu_Items_based_on_Context">コンテキストによるメニューアイテムの表示非表示</a>を参照してください。</p>
<p>また、この方法はどんな種類のポップアップにも使用できます。この例では、パネル内部のラベルが現在の時間に基づいて初期化されます。</p>
<pre class="brush:xml"><panel id="time-panel" onpopupshowing="this.lastChild.value = (new Date()).toLocaleFormat('%T')">
<label value="Time:" />
<label id="time" />
</panel>
<toolbarbutton label="Show Time" popup="time-panel" />
</pre>
<p><img src="/@api/deki/files/305/=Popupguide-popupshowing.png"></p>
<p><code>popupshowing</code> リスナー内から <a href="/ja/docs/Web/API/Event/preventDefault" title="なし"><code>preventDefault</code></a> メソッドを呼び出すことにより、メニューやポップアップの表示を抑止することができます。<code>popupshowing</code> イベントのデフォルトの動作は、ポップアップの表示を継続させることです。preventDefault メソッドはこの動作の発生を抑止するため、ポップアップは開かれなくなります。</p>
<pre class="brush:xml"><menu label="Edit">
<menupopup onpopupshowing="if (gDisallowed) event.preventDefault();">
<menuitem label="Undo" />
<menuitem label="Redo" />
</menupopup>
</menu>
</pre>
<p>この例では、グローバル変数 <code>gDisallowed</code> をチェックしたあと、 <a href="/ja/docs/Web/API/Event/preventDefault" title="なし"><code>preventDefault</code></a> メソッドを呼び出しています。If you want to prevent a context menu from opening it is better to call <code>preventDefault</code> with a handler for the contextmenu event instead, to avoid the extra steps necessary to fire the <code>popupshowing</code> event if it isn't needed.</p>
<p>入れ子のサブメニューを使う時には、<code>popupshowing</code> イベントの中で、そのイベントが適切なポップアップに対応するものかどうか必ず確認するようにしてください。なぜなら、ポップアップイベントは浮上 (<span style="color: green;">bubble</span>)するので、親メニューはそれ自体が開いた時にも、サブメニューが開いた時にも <code>popupshowing</code> イベントを受け取るからです。例を示します。</p>
<pre class="brush:xml"><menu label="File">
<menupopup onpopupshowing="if (event.target == this) adjustFileMenu(this);">
<menu label="Open">
<menupopup>
<menuitem label="File..." />
<menuitem label="Page" />
</menupopup>
</menu>
</menupopup>
</menu>
</pre>
<p>イベントのターゲットを調べて、イベントが目的の menupopup に対応するものかを調べています。このようにしなければ、関数 adjustFileMenu は外側の menupopup が開かれた時にも、内側の menupopup が開かれた時にも呼び出されてしまいます。イベントの浮上はすべてのポップアップイベントで発生します。</p>
<h3 id="The_popupshown_event" name="The_popupshown_event"><code>popupshown</code> イベント</h3>
<p><code>popupshown</code> イベントは、ポップアップが表示されるとすぐに発生します。<span id="m-openPopup"><code><a href="https://developer.mozilla.org/ja/docs/Mozilla/Tech/XUL/Method/openPopup">openPopup</a></code></span> メソッドや <span id="m-openPopupAtScreen"><code><a href="https://developer.mozilla.org/ja/docs/Mozilla/Tech/XUL/Method/openPopupAtScreen">openPopupAtScreen</a></code></span> メソッドを呼び出した場合、ポップアップはそれらのメソッドが返るまで開かれません。したがって、<code>popupshown</code> イベントはスクリプトが終了し、UI が更新されるとすぐに発生します。<code>popupshown</code> イベントはこれがいつ起こるかを知るのに役立ちます。</p>
<p><code>popupshown</code> イベントの利用法の 1 つとして、他のメニューを開くために使用する方法があります。この方法は、次の例のように、プログラムからサブメニューを開かなければならないときに必要になります。なぜなら、親メニューを開かずにサブメニューを直接開くことはできないからです。</p>
<pre class="brush:xml"><script>
function openFileMenu() {
var filemenu = document.getElementById("file-menu");
filemenu.addEventListener("popupshown", fileMenuOpened, false);
filemenu.open = true;
}
function fileMenuOpened(event) {
if ( event.target != document.getElementById("file-menupopup") ) {
return;
}
var filemenu = document.getElementById("file-menu");
filemenu.removeEventListener("popupshown", fileMenuOpened, false);
var openmenu = document.getElementById("open-menu");
openmenu.open = true;
}
</script>
<menu id="file-menu" label="File">
<menupopup id="file-menupopup">
<menu id="open-menu" label="Open">
<menupopup>
<menuitem label="File..." />
<menuitem label="Page" />
</menupopup>
</menu>
</menupopup>
</menu>
<button label="Open" oncommand="openFileMenu();" />
</pre>
<p>ボタンを押すと、関数 <code>openFileMenu</code> が呼ばれます。この関数は、 <a href="/ja/docs/Web/API/Element/addEventListener" title="この項目についての文書はまだ書かれていません。書いてみませんか?"><code>addEventListener</code></a> メソッドを使って "File" メニューに <code>popupshown</code> イベントリスナーを取り付けます。これにより、"File" メニューで <code>popupshown</code> イベントが発生すると、関数 <code>fileMenuOpened</code> が呼ばれるようになります。</p>
<p>関数 <code>fileMenuOpened</code> は、まずイベントのターゲットが適切なポップアップかどうかを調べ、そうでなければすぐに返ります。次に、<code>popupshown</code> イベントリスナーをふたたび削除します。イベントリスナーが重複して追加されないようにするため、必ずこれを実行しなければなりません。最後に、関数 <code>openFileMenu</code> と同じ方法を使って "Open" サブメニューを開きます。このようにすると、外側のメニューと内側のメニューの両方を開くボタンが完成します。</p>
<h3 id="The_popuphiding_event" name="The_popuphiding_event"><code>popuphiding</code> イベント</h3>
<p>ポップアップが閉じると、画面から消える直前に、そのポップアップで <code>popuphiding</code> イベントが発生します。<code>popuphiding</code> イベントに対するリスナーを利用すると、<code>popupshowing</code> イベントとは逆に、ポップアップ上のアイテムをふたたび削除したり隠したりできます。<code>popuphiding</code> イベントは、ポップアップが隠された方法に関わらず、ユーザがメニューからアイテムを選択した場合でも、ポップアップの外側をクリックした場合でも、<kbd>Escape</kbd> キーを押してメニューをキャンセルした場合でも発生します。また、<code>popupshowing</code> イベントと <code>popuphiding</code> イベントは、ユーザがメニューバー上でマウスを動かして、メニューやサブメニューを表示させたり隠したりした場合にも発生します。</p>
<p>この例では、ポップアップが隠れるたびに <code>textbox</code> の内容が消去されます。</p>
<pre class="brush:xml"><panel onpopuphiding="document.getElementById('search').value = '';">
<textbox id="search" />
<button label="Search" oncommand="doSearch();" />
</panel>
</pre>
<p>イベントの <a href="/ja/docs/Web/API/Event/preventDefault" title="なし"><code>preventDefault</code></a> メソッドを呼び出すと、ポップアップが非表示になるのを抑止することができます。そうすると、ポップアップは閉じられなくなります。通常は、これはするべきではありません。たとえば、確実に値が入力されるようにしたければ、値が入力されていなくてもコードがそれを処理できるように UI を作り直した方がはるかに良いでしょう。そうしないと、ユーザはポップアップが閉じられないことに混乱してしまいます。</p>
<p>ユーザがメニューの中から何かを選択した場合には、 <code>menupopup</code> が閉じるのをキャンセルすることはできません。キャンセルするにはすでに遅すぎるからです。この場合、選択された menuitem にすでに <code>command</code> イベントが送られており、その操作はすでに実行されています。これは、ポップアップが取り除かれた後に <code>popuphiding</code> イベントが発生する特殊なケースの 1 つです。こうなっている理由は、非常によくあるケースである、メニューアイテムの動作がモーダルダイアログを開くものである場合のためです。この場合、ダイアログが開かれる前に、まずメニューを取り除く必要があります。そうしないと、すでにアクティブではない親ウィンドウにメニューが残されたままにされてしまいます。そのため、ポップアップがまず取り除かれるのです。すなわち、<code>popuphiding</code> イベントはモーダルダイアログが閉じられるまで発生しないということに注意してください。</p>
<p>メニューが閉じられても <code>popuphiding</code> イベントが発生しない場合があります。そのため、<code>popuphiding</code> イベントリスナでは必要なコードを呼び出さないようにするべきです。メニューやポップアップを再初期化する場合には、<code>popupshowing</code> イベントで行う方が良いでしょう。<code>popuphiding</code> イベントが送られないケースの 1 つは、メニューがドキュメントから削除された場合です。これはイベントを送る対象となる要素がすでに存在しないからです。もう 1 つは、ドキュメントがアンロードされた場合です。</p>
<h3 id="The_popuphidden_event" name="The_popuphidden_event"><code>popuphidden</code> イベント</h3>
<p><code>popuphidden</code> イベントは、ポップアップが閉じられた後に発生します。</p>
<p>メニューが連鎖的に開かれている場合、すなわち、あるメニューと少なくとも 1 つの階層のサブメニューが開かれている場合、まず最も低い階層の<span style="color: darkgreen; background: #ef9;">【訳注: 最も深い】</span>サブメニューで <code>popuphiding</code> イベントが発生します。それからそのメニューが閉じ、<code>popuphidden</code> イベントが発生します。そして、次に高い階層のメニューで、すべてのメニューが閉じられるまでこの行程が繰り返されます。すなわち、サブメニューが長く連なって開かれている場合、<code>popuphiding</code> イベントと <code>popuphidden</code> イベントが順番に何度も発生するということになります。最上位のメニューが <code>popuphidden</code> イベントを受け取った時、すべてのメニューが閉じられたことを知ることができます。</p>
|