ポップアップの開閉
ポップアップとメニューはスクリプトによって開閉できます。
メニューを開く
メニューは特別な事をしなくても必要に応じて自動的に表示されます。たとえばメニューのポップアップはメニューのラベルがクリックされれば開きますし、サブメニューは親メニュー要素の上にマウスを乗せれば開きます。
しかし、手動でメニューを開きたい場合もあるでしょう。menu 要素には open プロパティがあり、true に設定するとメニューが開き、false に設定するとメニューが閉じます。 簡単な例を示します。
somemenu.open = true;
この一行のコードによって変数 somemenu が参照するメニューが開きます。open
プロパティを利用できるのは menu や button であり、menupopup ではないということに注意してください。メニューを開くためのボタンの完成例を示します。
<button label="Open Menu" oncommand="document.getElementById('editMenu').open = true;"/> <menu id="editMenu" label="Edit"> <menupopup> <menuitem label="Cut"/> <menuitem label="Copy"/> <menuitem label="Paste"/> </menupopup> </menu>
この手法は menu
、button
、toolbarbutton
のいずれのタグを使った menupopup に対しても用いることができます。popup
または context
属性によって他の要素に取り付けられた menupopup については、下記のポップアップを開くを参照してください。
他の方法でメニューを開いた時と同様に、メニュー上に表示されるコマンドをカスタマイズできるように popupshowing イベントが発生します。
メニューを開くことができない状況がいくつかあります。
- メニューがすでに開いているか、開かれようとしている場合。当然ながら、すでに開いているメニューを開こうとしても何も効果はありません。
- メニューが他のメニューの子であり、親メニューが開いていない場合。この場合、先に親メニューを開く必要があります。サブメニューを開くには、まず親メニューを開き、popupshown イベントリスナ内で子メニューを開きます。このやり方の例は popupshown イベント を参照してください。
- Web ページなどの非特権コンテンツウィンドウのメニューは、ウィンドウにフォーカスがあり、現在アクティブなタブにある間にしかポップアップを開くことができません。つまり、バックグラウンドタブの中のドキュメントはメニューやポップアップを開くことはできません。
メニューを閉じる
ユーザがメニューの中のどれかを選択すると、メニューは自動的に閉じます。メニューアイテムが選択されると、何らかの動作を実行するために command イベントが発生します。ユーザは Escape キーを押してコマンドの選択をキャンセルすることもできます。このときメニューは 1 つだけ閉じますが、そのメニューが親メニューを持つ場合、親メニューは開いたままです。また、メニューの外側をクリックしてメニューの選択をキャンセルすることもできます。この場合、そのメニューだけではなく、その全ての親メニューも閉じられます。
メニューをスクリプトから閉じるには、開くときとは逆に open
プロパティを false に設定します。open プロパティを利用できるのは menu や button であり、menupopup ではありません。
somemenu.open = false;
このコマンドは 1 つのレベルのメニューしか閉じないので、必要ならば同様のコマンドで親メニューを閉じなければなりません。しかし、この例の somemenu はすでに開いていないので、somemenu の子メニューはすべて閉じられます。たとえば、「ファイル」メニューに、最近使用したファイルの一覧を格納したサブメニューがあるとします。両方のメニューが開かれた状態でサブメニューの open
プロパティを false に設定すると、サブメニューは閉じますが、親の「ファイル」メニューは開いたままです。反対に、「ファイル」メニューの open プロパティを false に設定すると、両方のメニューが閉じます。
この手法は menu
、button
、toolbarbutton
のいずれのタグを使った menupopup に対しても用いることができます。popup
または context
属性によって他の要素に取り付けられた menupopup については、下記のポップアップを閉じるを参照してください。
メニューが閉じると、menupopup で popuphiding イベントが発生します。popuphiding イベントをリスンするイベントリスナを取り付けることで、popupshowing イベント中に追加したコマンドを削除するといったことが可能になります。
メニューやポップアップは、それを含むドキュメントやウィンドウが閉じられたときや、menupopup 要素がドキュメントから削除されたときにも閉じられます。こういった場合には、イベントの発生元となる要素が存在しないので、popuphiding や popuphidden イベントは発生しません。これらのイベントで行われるような終了処理を実行したければ、unload イベント中に行うのがいいでしょう。
メニューが開いているか調べる
メニューが開いているかどうかを調べるには、そのメニューの open
プロパティを調べます。open プロパティが true に設定されていればそのメニューは開いており、そうでなければ閉じられています。
var open = somemenu.open;
ポップアップを開く
menu
タグ、button
タグ、toolbarbutton
タグを使った menupopup を開くには、上記のメニューを開くを参照してください。
popup
attribute によって取り付けられたポップアップは、ユーザが左マウスボタンをクリックすると開きます。キーボードによってこの動作を再現することはできないので、必ずそのメニューの機能にアクセスする別の方法を用意するようにしてください。これはユーザインタフェースのほかの場所に代わりになるコマンドを設置するか、メニューを開くショートカットを用意することで可能になります。メニューが開かれれば、通常どおりキーボードによってアイテム間を移動して選択することができます。
context
属性によって取り付けられたポップアップは、ユーザがコンテキストメニューを開こうとする動作を行ったときに開きます。この動作はプラットフォームごとに異なりますが、一般的には要素を右マウスボタンでクリックする必要があります。マウスボタンが 1 つしかない Macintosh システムでは、マウスボタンを押し続けるか、Control キーを押しながらマウスボタンをクリックするとコンテキストメニューが開かれます。Windows では、キーボードのメニューキー (多くのキーボードで Control キーの隣にある、メニューの絵が描かれたキー) を押すか、Shift + F10 キーを押してコンテキストメニューを開く事も出来ます。したがって、ユーザがコンテキストメニューを開くのにマウスを使うものだと決めてかかってはいけません。
openPopup メソッド
ポップアップの openPopup
メソッドを使うと、ポップアップの種類に関係なくプログラムからポップアップを開くことができます。このメソッドは menupopup、panel、tooltip のどの種類のポップアップでも使用でき、また context
属性によって取り付けられたポップアップなど他の方法で開かれるポップアップでも使用できます。
openPopup
メソッドは、ポップアップをどこにどのように配置するかを指定する 6 つの引数を取ります。これらの引数について以下で説明します。openPopup
メソッドは次のように定義されています。
void openPopup(in DOMElement anchorElement, in String position, in long x, in long y, in boolean isContextMenu, in boolean attributesOverride);
まず例を示します。
somepopup.openPopup(anchor, "after_start", 0, 0, false, false);
この例は anchor で参照されるほかの要素のすぐ下にポップアップを開きます。これは anchor が menu
要素であった場合の動作を模倣しています。メニューに対して openPopup
メソッドを使うこともできますが、そのメニューの open
属性を true に設定した方が、menupopup の位置を代わりに処理してくれるのでより簡単です。open 属性は親のメニューや親のボタンで利用できるのに対して、openPopup
メソッドは menupopup 要素で利用できるということに注意してください。
ポップアップのアンカーとは、それに隣接してポップアップが表示される要素ノードのことです。たとえば、あるボタンの隣にポップアップを表示させたければ、そのボタンへの参照を第一引数として openPopup
メソッドに渡します。次の例では、ポップアップが文書要素からの相対的な位置に開かれます。
somepopup.openPopup(document.documentElement, "end_before", 0, 0, false, false);
openPopup の第二引数はアンカーの position
で、これはアンカーのどの辺に対してポップアップを配置するかを指定します。たとえば上の例で使用されている end_before という値を指定すると、ポップアップの左辺がアンカー要素の右辺に接し、双方の上端が揃うように配置されます。この引数はわかりにくいので、ポップアップの位置決めで詳しい利用方法と取り得る値、またそれぞれの値でポップアップがどのように位置合わせされるかを示す画像を参照してください。
openPopup の第三引数と第四引数は、オフセット値 x
と y
です。これらのオフセット値にゼロ以外の値を指定すると、ポップアップが位置決めされてからさらにポップアップの位置を指定することができます。これにより、ポップアップを特定の要素の位置に固定させつつ、その位置を細かく調整することが可能になります。正の値を指定するとポップアップの位置が右か下に調整され、負の値を指定すると左か上に調整されます。
次の例ではポップアップが要素の下に表示されますが、右に 10 pixel、上に 2 pixel オフセットされます。
somepopup.openPopup(anchor, "after_start", 10, -2, false, false);
アンカーと位置決めは、ポップアップが開かれるときの位置のみを指定するということに注意してください。ポップアップが開いている間にアンカーが移動または削除されても、ポップアップはそれに従いません。しかし、ポップアップが開かれている間にポップアップを動かすことは可能です。ポップアップの移動とリサイズを参照してください。
openPopup の第五引数 isContextMenu
は、ポップアップをコンテキストメニューとして開くかどうかを指定するフラグです。コンテキストメニューとして開きたければ true を、そうでなければ false を渡します。この引数に何を設定するかはあなたがどんな方法で openPopup を呼び出すかによって明らかでしょう。同じメニューをどちらの方法で開くこともできるので、このフラグはポップアップがどのように表示されるかには影響しないということに注意してください。これが影響するのは、メニューのフォーカスやハイライトが処理される方法です。状況に応じて適切な値を渡している限りは、双方の細かい違いを知る必要はありません。
しかしながら、Firefox のブックマークを使ってこのフラグの効果を確かめることができます。ブックマークのサブメニュー (ブックマークフォルダ) を開いてみてください。マウスが他のメニューの上に移動するとともにハイライトが変更され、マウスが離れるとサブメニューが閉じることがわかります。今度は同じブックマーク上でコンテキストメニューを開いてみてください。マウスを移動しても他のメニューには影響が無いのがわかります。この違いは isContextMenu フラグの使用によって処理されたものです。
openPopup
メソッドの最後の引数 attributesOverride
は、ポップアップの要素自体に設置された属性が、与えられた引数を上書きするかどうかを指定します。これによりポップアップは position
、left
、top
属性で指定された位置決めの動作を使用することができます。これらの属性の詳細はポップアップの位置決めにあります。
openPopup によるアンカーされないポップアップ
openPopup
メソッドの第一引数が null だと、アンカーされないポップアップが作成されます。この場合、第二引数 position は使用されないため、空文字列を渡してもかまいません。例を示します。
somepopup.openPopup(null, "", 60, 50, false, false);
アンカーされないポップアップはオフセット値 x と y 、この場合は 60 と 50 を、ウィンドウまたはフレームの端からのオフセットとして使用します。この方法では、ポップアップは特定のノードではなく、ウィンドウからの相対的な位置に配置されます。たとえば、マウスをクリックした時に、現在マウスポインタがある位置にポップアップを表示させたいことがあるでしょう。click イベントリスナの例を示します。
function mouseClicked(event) { var panel = document.getElementById("some-panel"); panel.openPopup(null, "", event.clientX, event.clientY, false, false); }
openPopupAtScreen メソッド
2 つめのメソッド openPopupAtScreen
は、ポップアップを画面上の特定の座標に配置するのに利用できます。このメソッドではポップアップは要素にアンカーされず、引数 x
と y
で指定された特定の位置に表示されます。
void openPopupAtScreen(in long x, in long y, in boolean isContextMenu);
引数 isContextMenu
は、コンテキストメニューを開くように指示します。これは openPopup
メソッドのものと同じ機能を持っています。次の例では、水平位置 100、垂直位置 200 にポップアップが開かれます。
popup.openPopupAtScreen(100, 200, false);
ポップアップが部分的もしくは全体的にスクリーンから出るような位置に座標が指定されると、ポップアップは全体が見えるように移動され、必要に応じてリサイズされる事に注意してください。
hidePopup メソッドでポップアップを閉じる
ユーザが Escape キーを押すかポップアップの外側のどこかをクリックすると、ポップアップメニューは閉じます。
menu
、button
、toolbarbutton
タグを使った menupopup を閉じる方法は、上記のメニューを閉じるを参照して下さい。
スクリプトによってポップアップを閉じるには、ポップアップの hidePopup
メソッドを使います。このメソッドは引数を取りません。
popup.hidePopup();
ポップアップが開いているかどうか判別する
メニューに関しては、menu、button もしくは toolbarbutton の open
プロパティを調べれば判別できます。true ならメニューは開いています。
他の種類のポップアップでは、state
プロパティを調べればポップアップが開いているかどうかを判別できます。このプロパティはメニュー、パネル、ツールチップを含む全ての種類のポップアップで利用できます。表示されているポップアップの state
プロパティは open
という値を持ち、ポップアップが閉じると state
プロパティの値は closed
になります。このプロパティは読み込み専用で、menupopup
、panel
またはtooltip
要素で利用できます。
state
プロパティは他にもう 2 つの値を持つことがあります。これらの値は、ポップアップが開いている状態から閉じている状態へ、またはその逆へと移行する間に使用されます。ポップアップが表示されようとしている時には state
プロパティは showing
という値を持ち、ポップアップが消されようとしている時には hiding
という値を持ちます。前者は popupshowing イベント中に起こり、後者は popuphiding イベント中に起こります。
たとえば、state
プロパティは panel
がすでに開かれているかどうかを判別するのに使用できます。パネルが開かれている場合、ユーザはメインウィンドウ内のユーザインタフェースを直接操作していないので、操作を無効にするといったことも可能になります。