「【ランチタイムラーニング】 初めてのWindowsガジェット」という記事(冒頭の「注」もお読みください)で、お昼を食べながら踏み出す、ガジェット作成の第一歩について説明しました。
この記事では、その記事に掲載したソースコードについて、少し詳しく解説します。
JavaScriptでのタイマー機能の実装
最初はHTMLの開始と、CSSのスタイルの定義です。
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 |
<html> <head> <title></title> <style type="text/css"> body { margin: 0; width:130px; height:100px; font-family:Georgia, "Times New Roman", Times, serif; font-weight:bold; } #gadgetContent { margin-top:20px; width:130px; vertical-align:middle; text-align:center; overflow:hidden; } #nowTime { text-align:left; font-size:x-large; } #setTime { text-align:right; } </style> |
7行目で、bodyの幅を130pxに設定しています。ガジェットがWindows Vistaのサイドバーに貼り付いている状態を「ドッキング」と言いますが、このドッキングの状態では、ガジェットの最大の幅は130pxです。
また、ガジェットをサイドバーに貼り付けず、単独でデスクトップに表示する状態にすることができ、この状態を「アンドック」と言います。
アンドックした状態では、ガジェットの幅は130px以上に設定することができます。多くのガジェットでこの設定を利用して、ドッキングの状態では簡易的なビュー、アンドックした状態ではリッチなインターフェイスを持ったビュー、というようなビューの切り替えを提供しています。ただし、アンドックした状態でも、ガジェットのサイズは縦横共400pxを超えないことをMicrosoftは勧めているそうです。
さて次にHTMLを見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 |
<body onload="init()"> <g:background id="imgBackground"> <span id="gadgetContent"> <span id="nowTime">00:00</span><br /> <input id="setTime" type="text" size="5" id="time" value="55" /> min <br /> <input type="button" value="Start" onclick="startTimer()" /> <input type="button" value="Stop" onclick="finish()" /> </span> </g:background> </body> </html> |
4行目が経過時間を表示するエリア(nowTime)です。そして、5行目に設定時間を入力するフィールド(setTime)があり、6行目、7行目がタイマーを開始、停止するためのボタンです。開始するにはJavaScriptで記述したstartTimer()ファンクション、停止するにはfinish()ファンクションをそれぞれ呼ぶようになっています。
1行目で、このHTMLがロードされたときにJavaScriptで記述したinit()ファンクションを呼ぶようになっていますが、後で出てくるように、今回のガジェットではこのinit()ファンクションは何もしないので、このHTMLがロードされたときは特別な処理は行われません。しかし、今後タイマーの背景画像を変えたりするなどカスタマイズするときに、HTMLがロードされるタイミングでJavaScriptのファンクションを呼ぶ、ということを覚えておきましょう。
最後にJavaScriptを見てみましょう。
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 |
<script type="text/jscript" language="jscript"> var startTime; var secTimerId; var timerId; function init() { // var oBackground = document.getElementById("imgBackground"); // oBackground.src = "url(images/background.png)"; } function startTimer() { startTime = new Date(); doTimer(); } function doSecTimer() { var diffSec = Math.floor(((new Date()).getTime() - startTime.getTime())/1000); var nextTime; var iMin=Math.floor(diffSec/60); var iSec=diffSec%60; var strMin=("0" + iMin); strMin = strMin.substr(strMin.length - 2, 2); var strSec=("0" + iSec); strSec=strSec.substr(strSec.length - 2, 2); document.getElementById('nowTime').innerHTML=strMin + ":" + strSec; nextTime = (startTime + 1000 * (1 + diffSec)) - (new Date()).getTime(); if (0 < nextTime) { secTimerId=setTimeout("doSecTimer()", nextTime); } else { secTimerId=setTimeout("doSecTimer()", 100); } } function doTimer() { var time = Math.abs(document.getElementById('setTime').value * 60 * 1000); doSecTimer(); timerId=setTimeout("finish()", time - ((new Date()).getTime() - startTime.getTime())); } function finish() { clearTimeout(secTimerId); clearTimeout(timerId); } </script> |
ここでは経過時間の常時を更新し(26行目)、毎秒JavaScriptのsetTimeout()でつぎのちょうどの秒にdoSecTimerを呼び出します(30行目)。念のため高負荷がかかっていて表示の次のちょうどの秒が過ぎてしまった場合には単に0.1秒後に再度更新するようにします(32行目)。これをsetTimeout()で設定時間までの時間を計る(39行目,44行目)ことでタイマーを実装しています。
表示の更新は、その時点での時間と開始時間の差分をとって、何秒経過したかを計算します。もちろん1秒ごとに1を足すのが一番簡単ですが、タイマーイベントがジャストの時間に発生しなかったり、そのほかの計算での時間も足されてしまうのでどんどんどんどん遅れることになり、やめたほうが良いでしょう。
また、前述の通りこのガジェットではHTMLがロードされたときに呼ばれるinit()ファンクションでは何もしませんが、7行目、8行目でコメントアウトしてある行のコメントをはずして、背景画像を表示することができるでしょう。
ガジェットでのalertの実装
さてタイマーはこれで実装できるのですが、そもそもタイマーは、指定時間が経過したことを「ぴぴっ」とか言いながら教えてくれてこそ、その本領を発揮できると言うものでしょう。なのにこのタイマーにはアラーム機能がありません。まるで人ごとのように書いてしまいましたが、このセクションでは簡単なアラーム機能を実装しましょう。
そもそも何故このタイマーガジェットはalert()ファンクションを使って、ひょいっとポップアップさせることさえしないのか。それは、alert()ファンクションやconfirm()ファンクションで出てくるポップアップがWindows Vista User Experience Guidelines for the Sidebarに則っていないということでサイドバーガジェットでは無効化されているからです。
それでもとりあえず簡単にポップアップを出したいときもあるではないですか。デバッグするときなんか特に。MSDN Magazineの記事に、そんな開発者の心の叫びに応えた、alert()やconfirm()と同等の機能を実装するやり方(ガジェットプラットフォームが脆弱である一因)が掲載されています。以下が今回のタイマーガジェットにそのやり方を適用する方法です。
ステップ1: ファンクションを準備する
作業フォルダに新しく「Timer.vbs」というファイルを作成して、次のように記述し保存します。
1 2 3 |
sub myAlert(msg) MsgBox msg, 48 , "Message from Timer" end sub |
ステップ2: タイマーガジェットから呼び出す
Timer.htmlの中で、前述のCSSの直後、JavaScriptの直前に次の行を書きます。
1 |
<script src="Timer.vbs" type="text/vbscript"></script> |
同じくTimer.htmlの中の、finish()ファンクションの最初か最後に次の行を書きます。
1 |
myAlert("時間です"); |
これで簡単なアラーム機能ができました。