はじめに
前回の記事『Webページ上に状況依存ヘルプを作成する』では、ブラウザの特定の領域にリッチテキストのヘルプツールヒントを関連付けるにはどうすればよいかを考察しました。特定のイメージやテキストの上にマウスポインタを置いたときに、クライアントサイドの簡単なJavaScriptとHTMLマークアップによって、画像やリッチテキストを含むヘルプウィンドウが表示されるようにしたわけです。このような状況依存ヘルプには、Webページに追加的な情報を表示する場合やWebページ上のデータをさらに詳しく説明する場合に、表示スペースを節約できるメリットがあります。
前回の記事は、状況依存ヘルプシステムの基礎作りに重点を置いていたため、いくつか足りない点がありました。すぐ気付くのは、マウスが状況依存領域を横切るとすぐにヘルプウィンドウが表示され、状況依存領域を離れるとすぐに消えることです。この動作は操作性の面で2つの問題を引き起こします。第一の問題は、画面上を移動するマウスがたまたまヘルプ領域を通過しただけでヘルプウィンドウが表示され、目障りになることです。第二の問題は、ヘルプウィンドウ内にリンクが含まれている場合や長いテキストのためにスクロールが必要な場合に、ヘルプ領域の外にマウスを移動するとヘルプウィンドウが消えてしまうことです。
この状況依存ヘルプシステムには、こうした操作性の問題の他に、ページ開発者にとってそれほどユーザーフレンドリでないという問題もあります。すべてのスクリプトと<div>
および<iframe>
要素をWebページに手動で追加してヘルプ領域のイベントハンドラ(onmouseover
とonmouseout
)を定義する必要があるからです。理想的には、必要なすべてのスクリプトとマークアップをASP.NET分離コードクラスの1行のコードで自動的に追加できるようにしたいところです。
この記事では、前回紹介した初歩的な状況依存ヘルプシステムの改良方法を考えます。まず前述の操作性の問題を解決し、次にASP.NET 2.0のクラスを作成します。このクラスのメソッドを使って、特定のヘルプ領域のヘルプウィンドウと必要なスクリプトを追加しようというわけです。では、本題に入りましょう!
前回の記事『Webページ上に状況依存ヘルプを作成する』をまだお読みでない方は、そちらから先に読むことをお勧めします。
ヘルプウィンドウの開閉がすぐに行われないようにする
一般的なWebページやWindowsアプリケーションでは、ツールヒント対応のインターフェイス領域上をマウスが通過しただけではツールヒントは表示されず、マウスをその領域で一呼吸止めたときに初めて表示されるようになっています。しかし、先週の記事で紹介した状況依存ヘルプシステムでは、マウスがヘルプ領域を横切るとヘルプウィンドウが直ちに表示されます。この過敏な動作は、ブラウザ画面上でマウスを移動するときに目障りな印象を与えます。状況依存ヘルプを表示するつもりがなくてもマウスを画面上で動かすとヘルプ領域をいくつか通過してヘルプウィンドウが表示されてしまうからです。これらのヘルプウィンドウは、画面上でそのままマウスを動かせば消えますが、ヘルプウィンドウがパッと現れてすぐ消えるとユーザーが混乱するばかりでなく、ユーザーに不快な思いをさせる可能性があります。
この問題を改善するには、少し猶予時間を置いてからウィンドウを表示するようにします。つまり、ヘルプ領域上にマウスが来てもヘルプウィンドウを直ちに表示せず、半秒ほど待ってからヘルプウィンドウを表示します。半秒の待ち時間以内にマウスがヘルプ領域を出た場合はヘルプウィンドウを表示しません。
JavaScriptのsetTimeout(expression, delay)
関数は、指定された猶予時間(ミリ秒単位)の経過後に特定の式を実行します。setTimeout
を使用するときに注意すべき点は、この関数が非ブロック関数であることです。setTimeout
文のところまで来ると、この文中の式が、指定時間後に実行される待ち行列に追加されます。待ち行列への追加後、setTimeout
関数に続くJavaScript行が間を置かずに実行されます。これは言い換えると、指定した猶予時間は非同期的に消化されるということです。猶予時間が経過するまで制御フローがsetTimeout
コマンドのところで待機するわけではありません。
そこでこの待機機能を実現するために、前回の記事でヘルプウィンドウを表示するのに使っていたcsi_showHelpFloatWindow
関数を次の2つに分割しました。
- csi_showHelpFloatWindow
- csi_showHelpFloatWindowInternal
waitDurationInMilliseconds
を受け取ります。waitDurationInMilliseconds
パラメータには、マウスがヘルプ領域に入ってからヘルプウィンドウを表示するまでの時間をミリ秒単位で指定します。この関数はsetTimeout
関数を用いてcsi_showHelpFloatWindowInternal
を呼び出します。 その他に、ウィンドウの表示をキャンセルするかどうかを指示するフラグ変数が必要です。例えば、マウスがヘルプ領域に入ったときは、csi_showHelpFloatWindow
関数が呼び出され、setTimeout
関数を通じて、csi_showHelpFloatWindowInternal
関数を例えば500ミリ秒後に呼び出すように設定されます。500ミリ秒以内にマウスがヘルプ領域から出た場合は、本来ならばヘルプウィンドウを表示する必要はないのですが、現在のままではcsi_showHelpFloatWindowInternal
関数が実行されてしまいます。マウスの動きに応じてこの関数を取り消す機能が用意されていないからです。
そこで、オープンコマンドがキャンセルされたかどうかを示すフラグ変数を使うことにします。この変数はcsi_showHelpFloatWindow
内でfalse
に設定され、ヘルプ領域のイベントハンドラcsi_showHelpFloatWindow
内でtrue
に設定されます。csi_showHelpFloatWindowInternal
関数は、キャンセルフラグがfalse
の場合にのみ実行を継続します。1つのページ上に複数の種類のヘルプウィンドウ(windowIDの異なるヘルプウィンドウ)が存在する可能性があるので、フラグ変数が1つではうまくいきません。ヘルプウィンドウの種類ごとにフラグが必要です。これを実現するには、次のように配列を使用します(強調表示されている部分に注目)。
// Array to hold the 'flags' to determine // whether a window's open has been cancelled var csi_cancelOpenArray = new Array(); function csi_showHelpFloatWindow(windowID, objID, horizPadding, vertPadding, goRight, waitDurationInMilliseconds) { // keep the window open csi_cancelOpenArray[windowID] = false; setTimeout("csi_showHelpFloatWindowInternal('" + windowID + "','" + objID + "'," + horizPadding + "," + vertPadding + "," + goRight + ");", waitDurationInMilliseconds); } function csi_showHelpFloatWindowInternal(windowID, objID, horizPadding, vertPadding, goRight) { // exit function immediately if open command has been cancelled if (csi_cancelOpenArray[windowID] == true) return; ... Same logic for displaying the help window as seen in last week's article ... }
マウスがヘルプ領域の外に出たら、フラグ(csi_cancelOpenArray[windowID]
)をtrue
に設定する必要があります。これを実現するためにcsi_hideHelpFloatWindow
関数を書き換えます(この関数はヘルプ領域のonmouseout
イベントから実行されます)。
function csi_hideHelpFloatWindow(windowID) { // cancel the open csi_cancelOpenArray[windowID] = true; ... }
同様にして、ヘルプウィンドウを開いたヘルプ領域からマウスが出てからヘルプウィンドウを閉じるまでの猶予時間を追加します。この猶予時間を設けることで、ユーザーはマウスをヘルプ領域からヘルプウィンドウへ移動し、そこでヘルプウィンドウの操作(スクロールやハイパーリンクのクリックなど)を行えるようになります。これを実現するために別のフラグ配列(csi_cancelCloseArray
)を使用します。これはヘルプ領域から出るときにcsi_hideHelpFloatWindow
関数内でfalse
に設定され、マウスがヘルプ領域に入ったとき、あるいはマウスがヘルプウィンドウそのものに入ったときにtrue
に設定されます。ウィンドウ表示前の猶予時間と同じく、これを実現するためにcsi_hideHelpFloatWindow
関数を次の2つの関数に分割します。
- csi_hideHelpFloatWindow
- csi_hideHelpFloatWindowInternal
waitDurationInMilliseconds
を受け取ります。このパラメータには、マウスがヘルプ領域を出てからヘルプウィンドウを隠すまでの猶予時間をミリ秒単位で指定します。この関数はsetTimeout
関数を使用してcsi_hideHelpFloatWindowInternal
を呼び出します。// Array to hold the 'flags' to determine // whether a window's close has been cancelled var csi_cancelCloseArray = new Array(); function csi_hideHelpFloatWindow(windowID, waitDurationInMilliseconds) { // cancel the open csi_cancelOpenArray[windowID] = true; // wait before hiding window csi_cancelCloseArray[windowID] = false; setTimeout("csi_hideHelpFloatWindowInternal('" + windowID + "');", waitDurationInMilliseconds); } function csi_hideHelpFloatWindowInternal(windowID) { // exit function immediately if close command has been cancelled if (csi_cancelCloseArray[windowID] == true) return; ... Same logic for hiding the help window as seen in last week's article ... }
また、csi_showHelpFloatWindow
とヘルプウィンドウのonmouseoverイベントで、csi_cancelCloseArray
内の適切なフラグをtrueに設定します。詳細については、この記事のダウンロードサンプルを参照してください。