導入
問い合わせフォームや会員登録フォームで、生年月日を入力するプルダウン、よくありますよね。
その中で、月の末日というのは、「3月は31日まで」「9月は30日まで」「2月はうるう年なら29日まで」など、年月によって変わってきます。
存在しない日付は、最初から選択肢に無いほうが望ましいですよね。
ということで今回は、選択された「年月」から、選択可能な「日」を自動生成してくれる、さらにはうるう年も考慮にいれた、いい感じのフォームをjqueryで実装します。
1. フォームを作る
最初にシンプルなフォームを作ります。
<form action="./confirm.php" method="POST" enctype="multipart/form-data”>
<table>
<tr>
<th>生年月日のフォーム</th>
<td>
<div class="flex-container">
<select id="year" name="year" class="field-year">
</select>
<label>年</label>
<select id="month" name="month" class="field-year">
</select>
<label>月</label>
<select id="day" name="day" class="field-year">
</select>
<label>日</label>
</div>
</td>
</tr>
<tr>
</table>
<input type="submit" value="送信" class="btn btn-blue">
</form>
セレクトボックスの中身は、以下のように<option>を一つずつ書くこともできますが、たとえば今回のように1970年から2022年だと、コードがとんでもなく長くなってしまいます。
<option value=“1970”>1970</option>
<option value=“1971”>1971</option>
<option value=“1972”>1972</option>
なので、選択肢を生成する関数を新たに作ります。
//年の選択肢生成
var createYearOption = (startNum, endNum, current) => {
let optionDom = '';
for (let i = startNum; i <= endNum; i++) {
if (i === current) { //現在年と合致する場合は初期値にする
option = '<option value="' + i + '" selected>' + i + '</option>';
} else {
option = '<option value="' + i + '">' + i + '</option>';
}
optionDom += option;
}
$("#year").append(optionDom);
}
optionの先頭と最後のvalue、現在の年を引数に取り、指定した個数分、<option>を生成します。
生成された<option>は、optionDomに追加されていき、最後の<option>まで追加されたら、セレクトボックスの中にinsertします。
同様に「月」と「日」の関数も作ります。
//月の選択肢生成
var createMonthOption = (startNum, endNum, current) => {
let optionDom = '';
for (let i = startNum; i <= endNum; i++) {
if (i === current) {
option = '<option value="' + i + '" selected>' + i + '</option>';
} else {
option = '<option value="' + i + '">' + i + '</option>';
}
optionDom += option;
}
$("#month").append(optionDom);
}
//日の選択肢生成
var createDayOption = (startNum, endNum, current) => {
let optionDom = '';
for (let i = startNum; i <= endNum; i++) {
if (i === current) {
option = '<option value="' + i + '" selected>' + i + '</option>';
} else {
option = '<option value="' + i + '">' + i + '</option>';
}
optionDom += option;
}
$("#day").append(optionDom);
}
あとはこれをページに読み込むと同時に呼び出してあげます。
その前に現在日時も取得しておきましょう。
ちなみに、getMonth()に1を足しているのは、getMonth()の戻り値が、1月の場合は0、2月の場合は1というように、現在月-1の数値であるためです。
//今日の日付、年、月、日 を取得
var today = new Date();
var thisYear = today.getFullYear();
var thisMonth = today.getMonth() + 1;
var thisDate = today.getDate();
var thisMonthDay = 31;
//作った関数を呼び出す
$(document).ready(function(){
createYearOption(1970,thisYear, thisYear);
createMonthOption(1,12,thisMonth);
createDayOption(1,thisMonthDay,thisDate);
});
これでとりあえず、生年月日を選択できるセレクトボックスの完成です。
しかし、このフォームには問題があります。
「2月30日」や「9月31日」などの存在しないであろう日付を選べてしまうのです。うるう年の影響も考慮しなくてはなりません。
2. うるう年判定関数を作る
次に、うるう年かどうかを判定する関数を作っておきます。
うるう年の定義は以下の通りです。
1.西暦年号が4で割り切れる
2.1の例外として、西暦年号が100で割り切れて400で割り切れない年は平年とする
これを踏まえて作った関数が以下になります。
//うるう年判定の関数
function isLeapYear(year){
if( (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) {
return true;
} else{
return false;
}
}
はい、これで引数に数字を入れて、うるう年ならtrue、うるう年じゃないならfalseを返す関数ができました。
3. フォームに組み込む
年、または月が選択されたとき、それに対応する日数を判定する処理を作ります。
流れとしては、以下のような条件分岐で日数を判定し、それを先程作った、日付を生成してくれる関数createDayOption(1,thisMonthDay,thisDate);
のthisMonthDayに入れるといった感じです。
$("#year").change(function(){ //年が選択されたとき
var selected_year = $(this).val(); //現時点の年に入っている値を取得
var selected_month = $('#month').val(); //現時点の月に入っている値を取得
var month_days = [0,31,28,31,30,31,30,31,31,30,31,30,31];//各月の日数
thisMonthDay = month_days[selected_month];
if(selected_month == 2 && isLeapYear(selected_year) == true){ //うるう年かつ2月のとき
thisMonthDay = 29;
}
$("#day").empty();
createDayOption(1, thisMonthDay, 1);
});
change()はselect要素の中身が変更された際にイベント処理を実行する関数なので、「年が選択されたとき」に処理が行われます。
同じように「月が選択されたとき」の処理も書きます。
$("#month").change(function(){ //月が選択されたとき
var selected_year = $('#year').val();
var selected_month = $(this).val();
var month_days = [0,31,28,31,30,31,30,31,31,30,31,30,31];//各月の日数
thisMonthDay = month_days[selected_month];
if(selected_month == 2 && isLeapYear(selected_year) == true){ //うるう年かつ2月のとき
thisMonthDay = 29;
}
$("#day").empty();
createDayOption(1, thisMonthDay, 1);
});
これで、年または月を選択すると、それに対応した日付の選択肢が反映される(うるう年も考慮された)セレクトボックスが完成しました!
おわりに
いかがだったでしょうか。
思った以上に長いコードになってしまったので、リファクタリングの余地が大いにある気がしますが、個人的には今後フォームを作るときに迷わなくて済みそうです。
よかったら是非参考にしてみてください!