Home > イヌでもわかるJavaScript講座 お品書き
イヌでもわかるJavaScript講座 お品書き へ戻ります
イヌでもわかるJavaScript講座


Step.22 - 月間カレンダーに挑戦


いままでのステップの知識でこのような月間カレンダー表も作れてしまいます。お部屋(ホームページ)のインテリアにどうぞ。(^^;


Step テーマ
● setDate 日付を変更する

実行例




リスト


<script type="text/javascript"><!--
// ****************
//      下準備
// ****************
myDate = new Date();// 今日の日付データ取得
myWeekTbl = new Array("日","月","火","水","木","金","土"); // 曜日テーブル定義
myMonthTbl= new Array(31,28,31,30,31,30,31,31,30,31,30,31);// 月テーブル定義
myYear = myDate.getFullYear(); // 年を取得
if (((myYear%4)==0 && (myYear%100)!=0) || (myYear%400)==0){// うるう年だったら...
myMonthTbl[1] = 29; //  2月を29日とする
}
myMonth = myDate.getMonth();// 月を取得(0月〜11月)
myToday = myDate.getDate();// 今日の'日'を退避
myDate.setDate(1);// 日付を'1日'に変えて、
myWeek = myDate.getDay();//  '1日'の曜日を取得
myTblLine = Math.ceil((myWeek+myMonthTbl[myMonth])/7);// カレンダーの行数
myTable = new Array(7*myTblLine);// 表のセル数分定義
 
for(i=0; i<7*myTblLine; i++) myTable[i]=" ";// myTableを掃除する
for(i=0; i<myMonthTbl[myMonth]; i++)myTable[i+myWeek]=i+1;// 日付を埋め込む
 
// ***********************
//      カレンダーの表示
// ***********************
document.write("<table border='1'>");// 表の作成開始
document.write("<tr><td colspan='7' bgcolor='#7fffd4'>");// 見出し行セット
document.write("<strong>",myYear, "年", (myMonth+1), "月カレンダー</strong>");
document.write("</td></tr>");
 
document.write("<tr>");// 曜日見出しセット
for(i=0; i<7; i++){ // 一行(1週間)ループ
document.write("<td align='center' ");
if(i==0)document.write("bgcolor='#fa8072'>");// 日曜のセルの色
else document.write("bgcolor='#ffebcd'>");// 月〜土のセルの色
document.write("<strong>",myWeekTbl[i],"</strong>");// '日'から'土'の表示
document.write("</td>");
}
document.write("</tr>");
 
for(i=0; i<myTblLine; i++){// 表の「行」のループ
document.write("<tr>");// 行の開始
for(j=0; j<7; j++){// 表の「列」のループ
document.write("<td align='center' ");// 列(セル)の作成
myDat = myTable[j+(i*7)];// 書きこむ内容の取得
if (myDat==myToday)document.write("bgcolor='#00ffff'>");// 今日のセルの色
else if(j==0) document.write("bgcolor='#ffb6c1'>");// 日曜のセルの色
else document.write("bgcolor='#ffffe0'>");// 平日のセルの色
document.write("<strong>",myDat,"</strong>");// 日付セット
document.write("</td>");// 列(セル)の終わり
}
document.write("</tr>");// 行の終わり
}
document.write("</table>");// 表の終わり
// --></script>



サンプルだけの HTMLは こちらへ

説明


リストの長さを見て、「ダメだこりゃ!」と思わないでください。
中身はたいしたことは していません。ただ、長いだけです。コメントもふんだんに入れました。(^^;

このカレンダーも星の数ほど やり方、考え方があります。
リストを見ていて、私のやり方に自分をあわせる必要はありません。
「どうしてこんなことをやるんだ? こうじゃいけないのかな?」
と思ったりするようでしたら、もうプログラマーです。自分のやり方に変更してみましょう。
「これおかし〜んとちゃうか?」
はい、間違ってます。メールで教えてあげましょう。(^^;


さて、このカレンダーの考え方を説明します。

カレンダーといっても、縦と横、つまり、行と列の2次元の「表」です。
表の内容も連続した数字(1〜31)を埋めていくだけですから、なんとなくイケそうな気がします。
はい、やることはそれだけです。(^^;


まず問題になるのは、月のはじめは 表の左上の 日曜日から始まるわけではないこと。
初日の曜日によって、左に空きのセル(つまり先月)ができます。
ということは、月末の右にも空きのセル(つまり来月)ができます。
そして、その月によって、行の数が可変になります。
初日が土曜日で月が 30日まであれば 6行、初日が日曜日の 2月(28日) であれば 4行になります。


「当たり前じゃん」と思うでしょう。 「はい、当たり前です。」
しかし、この当たり前の文章をそのままプログラムに翻訳しないといけません。(^^;

前回の Step で、固定テーブルを ただ、ループを使って表にしました。
今回もそれでいきます。
つまり、今月の固定テーブルをあらかじめ作成して、あとは前回のステップ同様、ループで表示させていきます。
「なんだ、簡単そうじゃん!」
「はい、簡単です。」(^^;


今回は うるう年 処理をあえてコンピュータにまかせず、自力で解決する方法をとります。 な〜に、簡単なことです。

myMonthTbl = new Array( 31,28,31,30,31,30,31,31,30,31,30,31 );
月の終わりのテーブル(配列)です。とりあえず、2月は28日をセットします。
※ Array配列は、Step.2 参照

4 で割り切れる年が うるう年 です。
しかし、100で割り切れると うるう年 ではありません。
ところが、400で割り切れるとうるう年なんです。 知ってましたか?(^^;
では、翻訳しましょう。
if ( ((myYear%4)==0 && (myYear%100)!=0) || (myYear%400)==0 ){
     myMonthTbl[1] = 29;    // うるう年なら 2月を 29日とする
}


今月の初日(1日) の曜日を取得します。
myDate.setDate(1);
getDate() があるのですから、setDate() もあります。これは、コンピュータのシステム時計を変えるわけではありません。
myDate の日付情報をパラメータの日付に変更するだけです。
これで初日の日付情報に変わるので、曜日の取得は楽勝です。

カレンダーに今日の日付を違う色でマークしたいので、初日に情報を変える前に、今日を退避させておきます。
myToday = myDate.getDate();
※ Date()、getDate()は、Step.3 参照


さて、下準備が終われば、今月の固定テーブルの作成に取り掛かりましょう。

まず、気になる行の数を計算します。

これから、例として説明するために、今日は 2013年6月10日 だったことにしましょう。

      1
2345678
9101112131415
16171819202122
23242526272829
30      
2013年6月は 上のような、6行のカレンダーになります。
この場合、myWeek は 初日の曜日、つまり、土曜日ですから 6 が入っているはずです。
myWeek = myDate.getDay();

6月なので、myMonth は 5 。
myMonth = myDate.getMonth();

末日は、myMonthTbl[5] なので、30 です。
myMonthTbl[ myMonth ]

( 6 + 30 ) / 7 の小数点切り上げ、つまり、2013年6月のカレンダーは 6行となります。
忘れないうちに myTblLine に 行数を 退避させます。(^^;
myTblLine = Math.ceil ( ( myWeek + myMonthTbl[myMonth] ) / 7 ) ;

このカレンダーだと、7日 * 6行 つまり、42個のセル(今月の固定テーブル) が必要です。作りましょう。
myTable = new Array( 7 * myTblLine ) ;

先月と来月の空きセルは 全角スペース(空白) を表示します。
for (i=0; i<7*myTblLine; i++) myTable[ i ] = " ";
めんどくさいから、42個全部に 空白を入れました。(^^; 本当に血液型A型か? (-o-?)

さて、今月の日付を このテーブル(myTable) に埋め込みましょうか。
for (i=0; i<myMonthTbl[myMonth]; i++) myTable[ i+myWeek ] = i+1;

上の 6月のパターンで考えると、
for (i=0; i<30; i++) myTable[ i+6 ] = i+1;
※ myTable[ 6 〜 35 ] に 1 〜 30 をセットしました。

表の行をなくして、横に一直線のセルとして考えると、ちゃんと myTable に表のイメージ通りの位置に 日付がセットされましたね。
「イメージが湧かないんだけど。。」
「orz...」
myTable[0〜41] の配列番号
0123456
78910111213
14151617181920
21222324252627
28293031323334
35363738394041
myTable[0〜41] の値
1
2345678
9101112131415
16171819202122
23242526272829
30
「最初から 字じゃなくて、絵で説明せんかい!」(-o-メ
「orz...」


それでは、カレンダーを表示しましょう。

前回の表作成と違うのは、今回は「列」がある点です。
横に7個表示したら、改行!? しないといけません。

上のパターンで言うと、7個、列を表示するのを、6行、繰り返せば良いのです。
つまり、7回のループを 6回ループするんです。(^^; あ、あたまが・・ (-o-;

イメージでプログラムすると、
for ( i = 0; i < 6; i++ ) {
    for ( j = 0; j < 7; j++ ) {
        document.write ( 該当セル位置に 該当する日付を表示 );
    }
}
ループの中にループ。2重ループです。
1個目のループに i を使ったので、2個目のループは、j です。
「i , j じゃなくて、y, x のほうが わかりやすくないかい?」(@_@;)
「orz...」


「どうして、カレンダー表示のルーチンがこんなに長いの?ひょっとして、複雑なのでは?」
「いえ、見出しとセルに色をつけたりしたから、こんなに長くなりました。」
「見出しと色がなければ、短いものです。」^^;
「だったら、つけるな、バカタレが!」 (-o-メ
「 どうせなら・・・」(T_T)

document.write("<table border='1'>");// 表の作成開始
document.write("<tr><td colspan='7' bgcolor='#7fffd4'>");// 見出し行セット
document.write("<strong>",myYear, "年", (myMonth+1), "月カレンダー</strong>");
document.write("</td></tr>");
普通に書けば、
  <table border="1">
  <tr><td colspan="7" bgcolor="#7FFFD4">
  <strong>2013年6月カレンダー</strong>
  </td></tr>
2013年6月カレンダー
が、作りたかったわけです。


document.write("<tr>");// 曜日見出しセット
for(i=0; i<7; i++){// 一行(1週間)ループ
document.write("<td align='center' ");
if(i==0)document.write("bgcolor='#fa8072'>");// 日曜のセルの色
else document.write("bgcolor='#ffebcd'>");// 月〜土のセルの色
document.write("<strong>",myWeekTbl[i],"</strong>");// '日'から'土'の表示
document.write("</td>");
}
document.write("</tr>");
普通に書けば、
  <tr>
  <td align="center" bgcolor="#FA8072"><strong>日</strong></td>
  <td align="center" bgcolor="#FFEBCD"><strong>月</strong></td>
  <td align="center" bgcolor="#FFEBCD"><strong>火</strong></td>
  <td align="center" bgcolor="#FFEBCD"><strong>水</strong></td>
  <td align="center" bgcolor="#FFEBCD"><strong>木</strong></td>
  <td align="center" bgcolor="#FFEBCD"><strong>金</strong></td>
  <td align="center" bgcolor="#FFEBCD"><strong>土</strong></td>
  </tr>

が、作りたかったわけです。


for(i=0; i<myTblLine; i++){// 表の「行」のループ
document.write("<tr>");// 行の開始
for(j=0; j<7; j++){// 表の「列」のループ
document.write("<td align='center' ");// 列(セル)の作成
myDat = myTable[j+(i*7)];// 書きこむ内容の取得
if (myDat==myToday)document.write("bgcolor='#00ffff'>");// 今日のセルの色
else if(j==0) document.write("bgcolor='#ffb6c1'>");// 日曜のセルの色
else document.write("bgcolor='#ffffe0'>");// 平日のセルの色
document.write("<strong>",myDat,"</strong>");// 日付セット
document.write("</td>");// 列(セル)の終わり
}
document.write("</tr>");// 行の終わり
}
document.write("</table>");// 表の終わり
普通に書けば、
※ タグ省略
      1
2345678
9101112131415
16171819202122
23242526272829
30      
が、作りたかったわけです。


横に 7回ループ( j ) を 縦に 6回ループ( i ) しながら、myTable の 中身(日付)を セルに セットしていきます。
myDat = myTable[ j + ( i * 7 ) ];

メインは この 1行なんです。


お疲れ様でした。 (^^;


参考ステップ
Step.21 TABLEタグを JavaScriptで作成してみましょう 
Step.23 月間カレンダーに先月と来月も表示してみましょう 


 
イヌでもわかるJavaScript講座 お品書き へ戻ります