こんにちは。今回も引き続き、JavaScriptでUIを実装する方法を紹介していきます。今回はやや趣向を変えて、JavaScriptでカレンダーを実装してみます。
Dateオブジェクト
カレンダーを実装する前に、JavaScriptのDateオブジェクトについておさらいしておきましょう。
まず、Dateオブジェクトはnew演算子でインスタンスを作ってから使います。そのとき渡す引数は4つのタイプがあります。
- 引数なし→現在の日時
- 文字列→日付を表す文字列としてパースして解釈
- 数値(1つ)→1970年1月1日00:00:00時点からのミリ秒数として解釈
- 数値(2つ以上)→第一引数から順番に、年、月、日、時、分、秒、ミリ秒として解釈
このように、何か引数を渡すとそれを日時として解釈して、その日時を基点とするDateオブジェクトを作ります。
このDateオブジェクトはgetDate, setDateといった、set/getメソッドをセットで持っており、一度作ったDateオブジェクトの日時を操作することができます。
なお、多くのブラウザはdate.getYearとdate.getFullYearというメソッドを実装しており混同されがちです。実はgetYearのほうはECMAScriptで定義されていない非標準なメソッド(正確には、ECMA 262 5th editionの付録としてその仕様について言及があります)で、IE 6~8以外のブラウザは1900年から数えた年数(2011年なら111)を返すので、getYearは使うべきでないメソッドのひとつです。
また、getFullYear、getMonth、getDateのうち、getMonthだけは0オリジンであることにも注意が必要です。ちなみに、C/Java/Perlなども月は0オリジンです。英語圏では月をJan、Feb、Marなどのように文字で表記することが多いため、0オリジンのほうが配列との相性がよかったのだと思われます。MonthのほかにDay(曜日)も0オリジンです。曜日を表示するのには、0オリジンのほうが都合がよいことが実感できると思います。
ある月の最終日
カレンダーを書く上で、一日と晦日を取得する必要があります。一日は new Date(year, month-1, 1) でよいので簡単ですね(monthにさえ注意すれば!)。問題は晦日です。
といっても、実はちゃんとその方法が用意されていて、日にちに0(もしくはマイナスの値)を渡すとDateオブジェクトは前月に遡ってくれます。
つまり、 new Date(year, month, 0) とすればその月の晦日が取得できます。なお、月についても考慮してくれるので、 2010年の大晦日を取得したい時は、 new Date(2010, 12, 0) で取得できます(わざわざ、new Date(2011, 1, 0) のようにしなくても大丈夫です)。
カレンダーを書く
さてカレンダーを書く際にもう一つ考えなければいけないのが、何列書くか、という問題です。といっても、カレンダーは最短で4週(2月1日が日曜で、うるう年でない場合のみ)、最長で6週の3つのパターンしかないので、6列で決め打ちにしてしまってもよいでしょう。
行数は当然7行ですから、6回ループする中に7回のループを入れ子にするという処理は見えてきました。あとは、どこから一日を始めて、晦日で終了する条件だけですね。
まず、一日は曜日によってどの位置になるかが決定します(曜日によって曜日が決まると言っているようなもので、当たり前のことなのですが)。晦日は加算していった日にちが晦日と一致するところで判断できます。これらの間ではそれぞれの日にちを、それ以外では空白のセルで埋めればシンプルなカレンダーの出来上がりです。
空白のセルには をいれています。これは空白のセルが潰れてしまうことを防ぐための応急処置です。
カレンダーの実装
ここまででカレンダーはほぼ出来上がりなので、見た目や実装について少し工夫してみましょう。
見た目についてはもちろんCSSで制御します。captionやth要素などを使って、なるべく無駄なく装飾します。
さて汎用的な実装の部分ですが、まず外部に公開するメソッドを定義します。この時に、メソッドの中身とメソッドの名前の定義を分けておきます。これにより、公開されているメソッドの見通しがよくなるというメリットがあります。ただ、同じメソッド名を2回書くことになるというデメリット(というほど大した問題ではありませんが)もあります。
このJCalendarはnewした後のオブジェクトについてメソッドを上書きすることで挙動を一部だけ変えることができます。例えば、onclick_dateを上書きすれば、日付をクリックしたイベントを自由に定義することができます。
まとめ
今回はJavaScriptを使ったUIとしてカレンダーの実装を紹介しました。こちらもまだまだ改良の余地があるので、是非自分なりに改良してみてください。
次回はこれまで作ったパーツの幾つかを組み合わせたアプリを作ってみたいと思います。