PHP+jQueryでカレンダーを作る&日付も取得する
前回作った祝日対応カレンダーを利用して、日付をクリックしたら、その日付を取得して、フォームに代入する処理を行います。
▼前回のカレンダーはこちらです
日付取得にはjQueryを使います。
イマドキjQueryなんて、と言われそうですが、jQuery使う方が簡単なので許してください。
jQueryが苦手な方はこちらの記事を読むのがオススメです。
日付取得の流れを考えて言語化する
PHP+HTMLで作られたカレンダーから、クリックした日付を取得したいので、トリガーが「日付をクリック」になります。
もう少し具体的に言うと、日付を表示させている<td>タグをクリックしたら、がトリガーです。
クリックした日付を取得したいので、<td>にdata-dateという属性を追加して、それを取得します。
取得した日付のdata-dateをフォームタグに代入します。
言語化した内容をプログラムで組む
やりたいことが言語化できたので、これをjQueryの文法に当てはめれば完了ですね。
言語化できればプログラムは組めます。
前回作ったカレンダーのプログラム
完成版のソースを先に出しておきます。
要件を整理すると、土日祝日は予約のできないカレンダーを作ってほしい、というものでした。
PHPソース
//祝日の読み込み $file = new SplFileObject("img/syukujitsu.csv"); $file->setFlags(SplFileObject::READ_CSV); $syuku_array = array(); foreach ($file as $line) { if(isset($line[1])){ $date = date("Y-m-d",strtotime($line[0])); $name = $line[1]; $syuku_array[$date] = $name; } } $week = array('日','月','火','水','木','金','土'); $now_month = date("Y年n月"); //表示する年月 $start_date = date('Y-m-01'); //開始の年月日 $end_date = date("Y-m-t"); //終了の年月日 $start_week = date("w",strtotime($start_date)); //開始の曜日の数字 $end_week = 6 - date("w",strtotime($end_date)); //終了の曜日の数字 echo '<table class="cal">'; //該当月の年月表示 echo '<tr>'; echo '<td colspan="7" class="center">'.$now_month.'</td>'; echo '</tr>'; //曜日の表示 日~土 echo '<tr>'; foreach($week as $key => $youbi){ if($key == 0){ //日曜日 echo '<th class="sun">'.$youbi.'</th>'; }else if($key == 6){ //土曜日 echo '<th class="sat">'.$youbi.'</th>'; }else{ //平日 echo '<th>'.$youbi.'</th>'; } } echo '</tr>'; //日付表示部分ここから echo '<tr>'; //開始曜日まで日付を進める for($i=0; $i<$start_week; $i++){ echo '<td></td>'; } //1日~月末までの日付繰り返し for($i=1; $i<=date("t"); $i++){ $set_date = date("Y-m",strtotime($start_date)).'-'.sprintf("%02d",$i); $week_date = date("w", strtotime($set_date)); //土日で色を変える if($week_date == 0){ //日曜日 echo '<td class="sun ng">'.$i.'</td>'; }else if($week_date == 6){ //土曜日 echo '<td class="sat ng">'.$i.'</td>'; }else if(array_key_exists($set_date,$syuku_array)){ //祝日 echo '<td class="sun ng">'.$i.'</td>'; }else if($i < $now_date){ //過去日付はNG echo '<td class="ng">'.$i.'</td>'; }else{ //平日 echo '<td data-date="'.$set_date.'" class="ok">'.$i.'</td>'; } if($week_date == 6){ echo '</tr>'; echo '<tr>'; } } //末日の余りを空白で埋める for($i=0; $i<$end_week; $i++){ echo '<td></td>'; } echo '</tr>'; echo '</table>';
jQuery ソース
<script> $(".ok").click(function(){ let get_date = $(this).data("date"); $('input[name="get_date"]').val(get_date); }); </script>
出来上がった祝日がクリックできないカレンダー
クリックできない日付はグレーになり、白い日付はマウスオーバーでカーソルになり、クリックすると日付のテキストがフォームに代入されます。
また、予約日を選択するカレンダーであるため、過去の日付もクリックできないようにしています。
2024年12月 | ||||||
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
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 |
日付:
土日祝日除外カレンダーPHPソースの解説
カレンダー制作の基礎的な解説は前回の記事を見ていただくとして、今回付け加えた部分を解説します。
付け足したのは、CSSのクラスと、現在日付の取得、data属性になります。
予約可能日はclass="ok" それ以外はngを設定
予約可能日のtdにはclass="ok"を設定し、それ以外の日付にはngのクラスを振ります。
css側で見た目と、マウスオーバー時のアクションを設定します。
予約が可能な日付の場合、data-dateという属性をつけて、日付を設定します。
echo '<td data-date="'.$set_date.'" class="ok">'.$i.'</td>';
jQueryでクリックした日付を取得→代入の処理
予約可能な日付の<td>をクリックした場合をトリガーにするので、okのクラスを持っているtdをクリックした場合、に処理をします。
$(".ok").click(function(){
クリックしたtdのdata-dateを取得する変数を作ります。
let get_date = $(this).data("date");
取得した日付をinputのvalueに代入します。
$('input[name="get_date"]').val(get_date);
これで土日祝日がクリックできないカレンダーが完成しました。
見せ方や出し方はCSSで調節して、お好みに合わせて完成です。
といいたいところなんですが、このままだと月末に近づくにつれて、予約できる日付が存在しなくなる問題があります。
なので、三ヵ月先まで進めるカレンダーにします。
何か月でもいいんですが、あまり先の予約ができても仕方がないので、三ヵ月くらいがいいんじゃないかと。
月送り&戻し機能をつけたカレンダー
現在の月から3ヵ月先までめくれるカレンダーがこちら。
矢印の↑をクリックで次月、↓をクリックで前月に戻ります。
前後3ヵ月を超える場合は矢印が表示されません。
2024年12月 | ↓ | |||||
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
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 |
↑ | 2025年1月 | ↓ | ||||
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
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 |
↑ | 2025年2月 | |||||
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
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 |
基本的な作り方がわかれば、この辺の応用はいろいろなやり方が考えられますね。
月縛りなしで、カレンダーのめくり機能をつけるなら、ajaxを使って取得したい年月日をカレンダー化するのが良いかと思います。
今回のサンプルは、カレンダーを3つ(3ヵ月分)作って、jQueryのfadeInで月の切り替えを行う方式にしています。
細かい解説はあえてしませんが、同じことの繰り返しとなっています。
最終のソースと概要だけ解説して終わりたいと思います!
echo '<div class="cal_disp">'; //祝日の読み込み $file = new SplFileObject("img/syukujitsu.csv"); $file->setFlags(SplFileObject::READ_CSV); $syuku_array = array(); foreach ($file as $line) { if(isset($line[1])){ $date = date("Y-m-d",strtotime($line[0])); $name = $line[1]; $syuku_array[$date] = $name; } } $week = array('日','月','火','水','木','金','土'); $get_date = date("Y-m"); //3ヵ月分なので3回繰り返し for($x=0; $x<3; $x++){ //▼年月に-1を付けて月初を生成 $tt = $get_date.'-1'; //▼現在の日付を起点にfor文の該当月を生成 $now_date = date('Y-m-01', strtotime($tt.'+'.$x.' month')); //▼カレンダーの見出しの年月用 $now_month = date("Y年n月",strtotime($now_date."+".$x." month")); //▼毎月の月末日付取得 $end_day = date("t",strtotime($now_date)); //▼月初めの空セルの生成用 $start_week = date("w", strtotime($now_date.'-01')); //▼jQueryで制御するためユニークなクラスをつける echo '<div class="set_cal'.$x.'">'; echo '<table class="cal">'; //該当月の年月表示 echo '<tr>'; if($x != 0){ $set_x = $x -1; //▼前月に戻す echo '<td class="pre" data-pre="'.$set_x.'">↑</td>'; }else{ echo '<td></td>'; } echo '<td colspan="5" class="center">'.date("Y年n月",strtotime($now_date)).'</td>'; if($x != 2){ $set_n = $x +1; //▼次月にすすむ echo '<td class="next" data-next="'.$set_n.'">↓</td>'; }else{ echo '<td></td>'; } echo '</tr>'; //曜日の表示 日~土 echo '<tr>'; foreach($week as $key => $youbi){ if($key == 0){ //日曜日 echo '<th class="sun">'.$youbi.'</th>'; }else if($key == 6){ //土曜日 echo '<th class="sat">'.$youbi.'</th>'; }else{ //平日 echo '<th>'.$youbi.'</th>'; } } echo '</tr>'; //日付表示部分ここから echo '<tr>'; //開始曜日まで日付を進める for($i=0; $i<$start_week; $i++){ echo '<td></td>'; } //1日~月末までの日付繰り返し $now_date_ymd = strtotime(date("ymd")); for($i=1; $i<=$end_day; $i++){ $set_date = date("Y-m",strtotime($now_date)).'-'.sprintf("%02d",$i); $week_date = date("w", strtotime($set_date)); $set_date_ymd = strtotime($set_date); //土日で色を変える if($week_date == 0){ //日曜日 echo '<td class="sun ng">'.$i.'</td>'; }else if($week_date == 6){ //土曜日 echo '<td class="sat ng">'.$i.'</td>'; }else if(array_key_exists($set_date,$syuku_array)){ //祝日 echo '<td class="sun ng">'.$i.'</td>'; }else if($now_date_ymd >= $set_date_ymd){ //過去日付はNG echo '<td class="ng">'.$i.'</td>'; }else{ //平日 echo '<td data-date="'.$set_date.'" class="ok">'.$i.'</td>'; } if($week_date == 6){ echo '</tr>'; echo '<tr>'; } } //末日の余りを空白で埋める for($i=$week_date; $i<6; $i++){ echo '<td></td>'; } echo '</tr>'; echo '</table>'; echo '</div>'; }//end for echo '</div>';
月送りのjQuery
.nextと.preが追加されています。
.next か .pre をクリックすると次のカレンダーをfadeInして表示してます。
<script> $(".ok").click(function(){ let get_date = $(this).data("date"); $('input[name="get_date"]').val(get_date); }); $(".pre").click(function(){ let pre = $(this).data("pre"); $(".cal_disp div").hide(); $(".cal_disp .set_cal" + pre).fadeIn(); }); $(".next").click(function(){ let next = $(this).data("next"); $(".cal_disp div").hide(); $(".cal_disp .set_cal" + next).fadeIn(); console.log(next); }); </script>