目次

    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日」や「11月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];//各月の日数
    thisMonthDaymonth_days[selected_month];
     
    if(selected_month == 2) { //2月のみ個別で判定
    if(isLeapYear(selected_year)){
    thisMonthDay = 29; //うるう年
    } else{
    thisMonthDay = 28; //うるう年じゃない
    }
    }

    $("#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];//各月の日数
    thisMonthDaymonth_days[selected_month];
     
    if(selected_month == 2) { //2月のみ個別で判定
    if(isLeapYear(selected_year)){
    thisMonthDay = 29; //うるう年
    } else{
    thisMonthDay = 28; //うるう年じゃない
    }
    }

    $("#day").empty();
    createDayOption(1, thisMonthDay, 1);
    });


    これで最初は現在日時が選択されていて、年または月を選択すると、対応する日数の選択肢が反映される(うるう年も考慮した)セレクトボックスが完成しました!

    まとめ

    いかがだったでしょうか。
    思った以上に長いコードになってしまったので、改良の余地があるような気がしますが、個人的には今後フォームを作るときに迷わなくて済みそうです。
    よかったら是非参考にしてみてください!

    参考資料


    PREV
    2022.07.11
    インタラクションデザインとは - 後編
    NEXT
    2022.07.11
    Python&cronを使って定期的に自動でSlackに投稿する