Tam-calendar.js

これは何?

Tam-calendar.js はウェブページにカレンダーを表示する JavaScript です。以下のような特長をそなえています。

  • カレンダーを table 要素で表現する。個々の日付や曜日などは td 要素であらわす。td 要素が何をあらわしているか、知りたいときは class 属性を見ればわかるようになっている。たとえば 「2007年1月1日の日付」なら、<td class="date y2007 m01 d01"> というように。
  • スタイルシートのセレクタ指定ではこのクラスの組み合わせを使うと便利。たとえば「12月の週末」なら、td.m12.weekend {color: green;} というように。
  • デフォルトで指定されるクラス以外にも、任意のクラスを追加指定できる。たとえば日本の祝祭日や個人的なイベントの情報と組み合わせるような場合ではとても役に立つ。
  • テキストの表示はフィルタ関数を指定することによりカスタマイズが可能。日本語と英語の基本的なパターンは定義済みなので(例: “Monday”, “Mon”, “M”, “月”) フィルタを選ぶだけで切り替えられる。
  • テキストをクリックした際のリンクやアクションの指定などが簡単にできるようになっている。
  • もちろん、週の始めを日曜にしたり月曜にしたり、簡単に設定できる。

下は Google Calendar 風のスタイルシートを適用したサンプル(スクリーンショット) です。

Tam-calendar.js with Google Calendar style CSS

目次

ダウンロード

Tam-calendar.js は Google Code からダウンロードできます。Subversion で管理されているので以下のように svn でアクセスすることもできます。

svn checkout http://tam-calendar.googlecode.com/svn/trunk/ tam-calendar

使い方

Tam-calendar.js は Prototype.js をベースに書かれているので、Prototype.js も合わせてロードしないと動作しません。

下にもっとも単純な HTML のサンプルを示します。これはただ単にその月のカレンダーを表示するだけです。

<html>
<head>
  <title>Calendar Sample</title>
  <script src="prototype.js" type="text/javascript"></script>
  <script src="tam_calendar.js" type="text/javascript"></script>
  <script type="text/javascript">
    //<![CDATA[
			
    function load() {
      var cal = new Calendar($('calendar'));
      cal.render();
    }
			
    //]]>
  </script>
</head>
<body onload="load()">
  <div id="calendar"></div>
</body>
</html>

太字の部分を書き換えることでさまざまにカスタマイズすることができます。

表示する月を指定する

render() はデフォルトでは現在の月のカレンダーを表示します。表示する月を明示的に指定するには、引数に月と年の数値を渡します。

たとえば、現在の年の4月を表示するには、

render(3);

とします。月が 0 から始まることに注意してください。4月なら 3、12月なら 11 です。これは JavaScript の Date オブジェクトの実装にならってそのようにしています。

年も指定するなら、第2引数に年の数値を渡します。たとえば「2008年の4月」を指定するなら以下のように。

render(3, 2008);

年はそのまま 2008 で構いません。

週が月曜から始まるようにする

render() はデフォルトでは日曜を週の始めの曜日として表示します。この週の始まる曜日を変更するには、Calendar オブジェクトの weekStart プロパティの値を変更します。

たとえば週の始めを月曜にするには以下のようにします。

var cal = new Calendar($(’calendar’));
cal.weekStart = Week.MONDAY;
cal.render();

Week オブジェクトは週の曜日をプロパティとして持っています。その他の曜日は下記の一覧表をご覧ください。

Week.SUNDAY 日曜
Week.MONDAY 月曜
Week.TUESDAY 火曜
Week.WEDNESDAY 水曜
Week.THURSDAY 木曜
Week.FRIDAY 金曜
Week.SATURDAY 土曜

矢印をクリックすると前/翌月のカレンダーに切り替わるようにする

左上と右上に矢印が表示されますが、デフォルトではこれらをクリックしても何も起こりません(まだ怒らないで!)。Tam-calendar.js はカスタマイズの自由度をできるだけ高めることを大切に考えて作られていますが、ここで Tam-calendar.js 全体を通して貫かれているカスタマイズの作法について紹介したいと思います。

まずは、左上の矢印をクリックしたら前月のカレンダーが表示されるようにすることを例に見ていきましょう。

Tam-calendar.js においては、左上の矢印はただの td 要素のひとつに過ぎず、特別な扱いはされません。ただしその class 属性には nav と previous という値がセットされているはずです。まず手始めに DOM Element オブジェクトとしてのこの td 要素を、クラスの組み合わせを利用して選び出します。

document.getElementsByClassNames() (この関数は Tam-calender.js での独自拡張です) はクラス名のセットを引数に受け、そのすべてのクラスがセットされた要素の配列を返します。nav と previous がセットされた要素を得るには次のようにします。

var nav_prev = document.getElementsByClassNames('.nav.previous', $('calendar'))[0];

# 実際には 1行です。改行されて見えても改行は無視してください。

第1引数はクラス名のセットですが、”.” (ピリオド) で連結された文字列の形式で渡されることに注意してください。これは CSS のクラスセレクタの構文と同じと考えるとわかりやすいでしょう。先頭にもピリオドが必要なのでお忘れなく。

第2引数は要素を探す範囲を指定します。要素が指定されるとその子孫要素のなかから該当する要素を探します。第2引数の指定がない場合はドキュメント全体から探そうとします。

document.getElementsByClassNames() は結果を配列として返します。この場合は、nav と previous がセットされた要素が1つしかないことがわかりきっているので、用があるのは配列の最初の要素だけになります。

さて、これでカスタマイズの対象となる DOM Element オブジェクトが得られました。これをクリックしたら前月のカレンダーが表示されるようにしたいので、onClick のイベントプロパティを変更できれば良さそうです。

nav_prev.onclick = function() { cal.render(prev_month, prev_month_year); }

クリックされた時に実行される関数を指定しますが、必要な動作は Calendar オブジェクトの render() をもう一回実行することです。その時 render() の引数として、前月の月と年を指定してやります。

前月の月と年はどのようにして得られるでしょうか。Calendar オブジェクトには previousMonth() という便利な関数が用意されていて、これは現在表示中の月の前の月とその年を連想配列として返します(同様に nextMonth() という関数もあります)。これを使って以下のようにして prev_month と prev_month_year を得るとよいでしょう。

var prev = cal.previousMonth();
var prev_month = prev.month;
var prev_month_year = prev.year;

これら一連の処理が、かならず render() 後に行なわれる必要があることに注意してください。なぜなら render() されなければ td 要素自体がまだ存在しないからです。指定された処理が render() 後に行なわれるように、Calendar オブジェクトの afterRenderHook プロパティを指定しておきます。afterRenderHook プロパティには render() 後に実行されるフック関数を指定します。

以上の処理をまとめると以下のようになります。

var cal = new Calendar($('calendar'));
cal.afterRenderHook = function() {
  var nav_prev = document.getElementsByClassNames('.nav.previous', $('calendar'))[0];
  var prev = cal.previousMonth();
  var prev_month = prev.month;
  var prev_month_year = prev.year;
  nav_prev.onclick = function() { cal.render(prev_month, prev_month_year); }
}
cal.render();

テキストを他のページにリンクさせる

カレンダー上の日付から、たとえばその日のイベントについてのページにリンクさせる、というのはよく見られる使い方だと思います。次はそのやり方をお見せします。

例として、11月23日の日付から、ウィキペディアの「勤労感謝の日」のページにリンクを張るようにしてみます。まずは対象となるカレンダー上の日付、つまりそれをあらわす td 要素を選択しますが、この方法は先に説明したとおり、document.getElementsByClassNames() を使います。

先に全体のコードをお見せしましょう。

var cal = new Calendar($('calendar'));
cal.afterRenderHook = function() {
  var kinros = document.getElementsByClassNames('.m11.d23', $('calendar'));
  kinros.each(function(kinro) {
    var kinro_a = kinro.getElementsByTagName('a')[0];
    kinro_a.href = "http://ja.wikipedia.org/wiki/%E5%8B%A4%E5%8A%B4%E6%84%9F%E8%AC%9D%E3%81%AE%E6%97%A5";
  });
}
cal.render(10);

今回は配列の各要素についてループさせてちゃんと処理するようにしてみました(実際には、同じ月の中に11月23日が2つ以上あるはずもないので、最初の要素だけ処理すればよかった)。Prototype.js の拡張による each() を使うと配列の処理が簡潔に書けます。

Tam-calendar.js ではあらかじめすべてのテキストを a タグでラップしているので、リンクを指定するには td 要素の下から a 要素を探して、それに href プロパティを指定してやるだけで実現できます。しかしよく使われる機能なので、これでも冗長に思えるかもしれません。

次のように書き換えることもできます。

var cal = new Calendar($('calendar'));
cal.afterRenderHook = function() {
  var kinros = document.getElementsByClassNames('.m11.d23', $('calendar'));
  kinros.each(function(kinro) {
    Calendar.href(kinro, "http://ja.wikipedia.org/wiki/%E5%8B%A4%E5%8A%B4%E6%84%9F%E8%AC%9D%E3%81%AE%E6%97%A5");
  });
}
cal.render(10);

これで少し短くなりました。

クラスを追加指定する

Tam-calendar.js が用意しているデフォルトのクラスだけでは足りない場合があるかもしれません。たとえば、日本の祝祭日には特別な背景色を指定したいというときに、どのように指定したらよいでしょうか。Tam-calendar.js が用意するデフォルトのクラスの中には、祝祭日をあらわすたとえば holiday といったクラスはありません。そのような場合はクラスを追加指定してください。

お決まりの方法ですが、まずは対象の td 要素を document.getElementsByClassNames() を使って選択します。豊富に用意されたデフォルトのクラスをうまく組み合わせて対象を特定してください。

あとは、通常の DOM Element の処理と同様に、クラスの追加を行ないますが、クラスの追加には Prototype.js の Element.addClassName() を使うと便利です。

11月23日(勤労感謝の日) の日付に対して holiday クラスを追加指定するコードは次のようになります。

var cal = new Calendar($('calendar'));
cal.afterRenderHook = function() {
  var kinros = document.getElementsByClassNames('.m11.d23', $('calendar'));
  kinros.each(function(kinro) {
    Element.addClassName(kinro, 'holiday');
  });
}
cal.render(10);

さて、「11月23日が祝日だとどうしてわかったのか」とか、「他の祝祭日もいちいち書かないといけないのか」とか、「ハッピーマンデーはどうするつもりだ」といったような疑問が当然出てくるでしょう。残念ながらそこまでは Tam-calendar.js では関知できないのですが、プログラムでの利用に適した祝祭日のデータが手に入れば、組み合わせて使うこともそれほど難しくはありません。

たとえば Google Calendar Data API を利用すれば正確な祝祭日データが得られるでしょう。以下の URL で2007年の日本の祝祭日を記述した XML が得られます。

http://www.google.com/calendar/feeds/japanese@holiday.calendar.google.com/public/full?start-min=2007-01-01&start-max=2008-01-01

Google Data API では JSON の利用も可能です。

テキストの書式を指定する

デフォルトでは曜日の書式は英語の省略表記になっていますが、これを変更することも可能です。また、曜日に限らず日付やその他すべてのテキストの書式は変更可能になっています。

render() の際、表示されるテキストは一度フィルタ関数に通されます。Calendar オブジェクトの formatDay プロパティが曜日を出力するためのフィルタ関数です。同様に日付のための formatDate プロパティ、ラベルのための formatLabel プロパティ、ナビゲーションのための formatNav プロパティが用意されています。これらのプロパティの関数を指定することで、自由に書式を変更することができます。

formatDay プロパティの値を変更して曜日の書式を日本語に替えてみましょう。

var cal = new Calendar($('calendar'));
cal.formatDay = function(day) { return Day.JA[day]; }
cal.render();

引数の day には 0(日曜) から 6(土曜) の数値が渡されます。

Day.JA は日本語の曜日の書式を含んだ配列です。Day.JA のほかにも合わせて4種類の定義済み書式が用意されています。

Day.EN_LONG “Sunday”, “Monday”, “Tuesday”, “Wednesday”, “Thursday”, “Friday”, “Saturday”
Day.EN_SHORT “Sun”, “Mon”, “Tue”, “Wed”, “Thu”, “Fri”, “Sat”
Day.EN_MINIMUM “S”, “M”, “T”, “W”, “T”, “F”, “S”
Day.JA “日”, “月”, “火”, “水”, “木”, “金”, “土”

曜日と同様に月の名前についても書式の配列が用意されています。

Month.EN_LONG “January”, “February”, “March”, “April”, “May”, “June”, “July”, “August”, “September”, “October”, “November”, “December”
Month.EN_SHORT “Jan”, “Feb”, “Mar”, “Apr”, “May”, “Jun”, “Jul”, “Aug”, “Sep”, “Oct”, “Nov”, “Dec”

またナビゲーションについては1種類のみが用意されています。

Nav.ARROW “«”, “»”

formatDate プロパティのフィルタ関数には引数として数値が1つ渡されます。この数値は日付(1~31)に相当します。

formatLabel プロパティのフィルタ関数は引数が渡されません。代わりに Calendar オブジェクトの currentYear プロパティ(現在表示中の年) や currentMonth プロパティ(現在表示中の月(0~11)) の値などを内部から参照するとよいでしょう。

formatLabel プロパティの値を変更して、日本語の『YYYY年MM月』という表記に替えてみましょう。

var cal = new Calendar($('calendar'));
cal.formatLabel = function() { return cal.currentYear + "年" + (cal.currentMonth + 1) + "月" }
cal.render();

formatNav プロパティのフィルタ関数には引数として数値が1つ渡されます。左側のナビゲーションは 0、右側のナビゲーションは 1 が渡されます。

デフォルトでセットされるクラス

すべての td 要素は4つのタイプのいずれかに属します。4つのタイプとは、日付、曜日、ラベル、ナビゲーションです。

Tam-calendar.js description

それぞれのタイプごとにセットされるクラスが用意されています。

  • 日付の td 要素にセットされるクラス
    クラス 説明
    date 日付の場合に常にセットされる。
    y{YYYY} 日付の年。例: y2007
    m{MM} 日付の月(01~12)。例: m12
    d{DD} 日付の日(01~31)。例: d31
    w{W} 日付の曜日(0~6、0が日曜)。例: w6
    today 日付が今日の日付と同じ場合にセットされる。
    weekend 日付の曜日が土曜か日曜の場合にセットされる。
    weekday 日付の曜日がそれ以外の場合にセットされる。
    current-month 日付が表示中の月に含まれる場合にセットされる。
    previous-month 日付が表示中の月の前月に含まれる場合にセットされる。
    next-month 日付が表示中の月の翌月に含まれる場合にセットされる。
    row{N} テーブル表示上の列の位置(0~5)。例: row5
    col{N} テーブル表示上の行の位置(0~6)。例: col6
  • 曜日の td 要素にセットされるクラス
    クラス 説明
    day 曜日の場合に常にセットされる。
    w{W} 曜日(0~6、0が日曜)。例: w6
    weekend 曜日が土曜か日曜の場合にセットされる。
    weekday 曜日がそれ以外の場合にセットされる。
    col{N} テーブル表示上の行の位置(0~6)。例: col6
  • ラベル(通常は現在表示中の月と年を表示) の td 要素にセットされるクラス
    クラス 説明
    label ラベルの場合に常にセットされる。
  • ナビゲーション(通常は左右の矢印を表示) の td 要素にセットされるクラス
    クラス 説明
    nav ナビゲーションの場合に常にセットされる。
    previous 左側に表示される(「前月へ」を示す) 場合にセットされる。
    next 右側に表示される(「翌月へ」を示す) 場合にセットされる。

カレンダーの上位構造は以下のようになっています。

コンテナ要素(Calendar コンストラクタに引数として渡した要素)
 |
 +- コンテント div 要素
     |
     +- ラベルとナビゲーションを含む table 要素
     |
     +- 曜日と日付を含む table 要素

コンテント以下の上部構造を構成する要素にもそれぞれクラスが適用されます。

  • コンテント div 要素にセットされるクラス
    クラス 説明
    calendar 常にセットされる。
    y{YYYY} 現在表示中のカレンダーの年。例: y2007
    m{MM} 現在表示中のカレンダーの月。例: m12
    t-y{YYYY} 今日の日付の年。例: t-y2007
    t-m{MM} 今日の日付の月(01~12)。例: t-m12
    t-d{DD} 今日の日付の日(01~31)。例: t-d31
    t-w{W} 今日の日付の曜日(0~6、0が日曜)。例: t-w6
  • ラベルとナビゲーションを含む table 要素にセットされるクラス
    クラス 説明
    label-navs 常にセットされる。
  • 曜日と日付を含む table 要素にセットされるクラス
    クラス 説明
    days-dates 常にセットされる。

スタイルのサンプル: Google Calendar 風

div.calendar {
    width: 160px;
    background: #c3d9ff;
    padding: 10px;
    font-size: 70%; 
    font-family:Verdana,Sans-serif;
}
div.calendar table {
    width: 100%;
    border-collapse: collapse;
    border-spacing: 0;
}
div.calendar td {
    text-align: center;
    padding:2px; 
    height: 3.4ex;
}
div.calendar td.nav {
    cursor: pointer;
}
div.calendar td.date {
    background-color: #fff;
}
div.calendar td.current-month { 
    background-color: #ace; 
}
div.calendar td.weekend { 
    background-color: #9bd; 
}
div.calendar td.previous-month, div.calendar td.next-month { 
    background-color: #fff;
}
div.calendar td.weekend.previous-month, div.calendar td.weekend.next-month {
    background-color: #e8eef7; 
}
div.calendar td.today { 
    background-color: #579; 
    color: #fff; 
}
div.calendar td.day {
    background-color: #c3d9ff;
}

3 thoughts on “Tam-calendar.js

  1. 挿入したんですんけどね、ダメでした。

    日本語の『YYYY年MM月』はエラーが出るのでできませんでした。

    ちなみにPrototype v1.5.1.1です。

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s