セレクトボックスを使った和暦の入力フォーム作成例

以下の条件を満たす入力フォームの作成例です。
もっとスマートなやり方があるかもしれません。。。

* 和暦に対応する
* DatePickerではなくセレクトボックス形式で
* 不正な日付の入力は極力させないよう元号、年、月、日のセレクトボックスを連動させる

###完成イメージ
![wareki_form.PNG](https://qiita-image-store.s3.amazonaws.com/0/39547/1ba6c40a-d017-fa63-f418-8e4cfdcff5b1.png)

#サンプル
##1. HTML
HTMLでは\<select\>タグのみ定義し、\<option\>タグはJavaScriptで設定します。
レイアウトにはBootstrapのグリッドシステムを使っています。

```wareki_sample.html
<div class="container">
    <div class="form-group">
        <div class="row">
            <div class="col-sm-3">
                <div>
                    <select class="form-control" name="date_of_birth_era" id="date_of_birth_era">
                    </select>
                </div>
            </div>
            <div class="col-sm-3">
                <div class="input-group">
                    <select class="form-control" name="date_of_birth_year" id="date_of_birth_year">
                    </select>
                    <span class="input-group-addon">年</span>
                </div>
            </div>
            <div class="col-sm-3">
                <div class="input-group">
                    <select class="form-control" name="date_of_birth_month" id="date_of_birth_month">
                    </select>
                    <span class="input-group-addon">月</span>
                </div>
            </div>
            <div class="col-sm-3">
                <div class="input-group">
                    <select id="date_of_birth_day" name="date_of_birth_day" class="form-control" >
                    </select>
                    <span class="input-group-addon">日</span>
                </div>
            </div>
        </div>
    </div>
</div>

```
##2. JavaScript - 元号のセレクトボックスに\<option\>を追加する
サーバーサイドのJavaプログラムでフォームへの入力値を受け取ることを想定し、valueにはJavaの和暦クラスで
ERAが返す定数（0～4）を設定しています。

```wareki.js
function setEraOption() {
	var era = $("#date_of_birth_era");
	era.append($('<option>').html('---').val(0));
	era.append($('<option>').html('明治').val(1));
	era.append($('<option>').html('大正').val(2));
	era.append($('<option>').html('昭和').val(3));
	era.append($('<option>').html('平成').val(4));
}
```
##3. JavaScript - 年のセレクトボックスに\<option\>を追加する
元号のvalueに対応した年数をセットします。
平成については現在日付を基準にして最大値を割り出しています。

```wareki.js
function setYearOption() {
	var year = $("#date_of_birth_year");
	var selectEra = $("#date_of_birth_era").val();
	
	year.children().remove();
		var maxYear = 0;
	switch (selectEra) {
	    case "1": maxYear = 45; break;
	    case "2": maxYear = 15; break;
	    case "3": maxYear = 64; break;
	    case "4": maxYear = new Date().getFullYear()-1988; break;
	    default: maxYear = 0; break;
	}
	year.append($('<option>').html('---').val(0));
	for (var i = 1; i <= maxYear; i++) {
	    year.append($('<option>').html(i).val(i));
	}
}
```
##4. JavaScript - 月のセレクトボックスに\<option\>を追加する
```wareki.js
function setMonthOption() {
	var month = $("#date_of_birth_month");
	
	month.append($('<option>').html('---').val(0));
	for (i = 1; i <= 12; i++) {
		month.append($('<option>').html(i).val(i));
	}
}
```
##5. JavaScript - 日のセレクトボックスに\<option\>を追加する
2月の日数は年によって異なるため、年&月に対応した日数の\<option\>を追加しています。

```wareki.js
function setDayOption() {
	var day = $("#date_of_birth_day");
	var selectYear = $("#date_of_birth_year").val();
	var selectMonth = $("#date_of_birth_month").val();
	var selectDay = day.val();
	
	//閏年に対応するため和暦から西暦に変換
	var seirekiYear = warekiToSeireki($("#date_of_birth_era").val(), selectYear);
	var dateobj = new Date(seirekiYear, selectMonth, 0);
	
	day.children().remove();
	$("#date_of_birth_day").append($('<option>').html('---').val(0));
	for (var i = 1; i <= dateobj.getDate(); i++) {
		day.append($('<option>').html(i).val(i));
	}
```
##6. JavaScript - 和暦から西暦に変換する
```wareki.js
function warekiToSeireki(era, year) {
	if (era == 1) {
		return parseInt(year) + 1867;
	} else if(era == 2) {
		return parseInt(year) + 1911;
	} else if(era == 3) {
		return parseInt(year) + 1925;
	} else if(era == 4) {
		return parseInt(year) + 1988;
	}
}
```
##7. JavaScript - 他のセレクトボックスに連動して日のセレクトボックスの\<option\>を調整する
年や月のセレクトボックスを変更した際に不整合とならないよう、日のセレクトボックスの\<option\>を再設定する

```wareki.js
function changeDayOption() {
	var day = $("#date_of_birth_day");
	var selectDay = day.val();
	
	setDayOption();
	//日が選択済みの場合、再度選択状態にする
	(selectDay == null) ? day.val(day.val()[0]) : day.val(selectDay);
}
```
##8. JavaScript - イベントに応じて上記の関数を呼び出す
```wareki.js
// DOM要素の構築完了時にセレクトボックスを初期化する
$(function() {
	$(document).ready(
		function() {
			setEraOption();
			setYearOption();
			setMonthOption();
			setDayOption();
		});	
});

// 元号を変更したら年のセレクトボックスの<option>をセットする
$(function() {
	$("#date_of_birth_era").on("change", function() {
		setYearOption();
	});	
});

// 年を変更し、月が選択済みかつ2の場合、日のセレクトボックスの<option>を調整する（閏年対応）
$(function() {
	$("#date_of_birth_year").on("change", function() {
		if ($("#date_of_birth_month").val() == 2) {
			changeDayOption();
		}
	});	
});

// 月を変更したら日のセレクトボックスの<option>を調整する
$(function() {
	$("#date_of_birth_month").on("change", function() {
		changeDayOption();
	});	
});
```