【フォーム】開始日時と終了日時を比較してエラーチェック

入力フォームに開始日時と終了日時を分けて入力し、必須入力チェック、開始日時と終了日時の整合性チェックを行います。

開始日時
終了日時

jQuery UI導入用のCSSファイル、jsファイル読み込み、Datepickerのカレンダー選択で日付入力する処理は下記の記事と同様です。入力フォームは「時」と「分」のセレクトボックスのみ追加します。

htmlのコードは下記になります。
「時」と「分」のセレクトボックスはoptionのvalue値に「時」と「分」と同じ値を設定します。何も選択していない状態のoptionのvalue値は空です。

<div class="form_section">
<table class="date-table">
	<tr>
		<th>開始日時</th>
		<td>
			<label class="cal-wrap"><input type="text" class="cal datepicker" readonly="readonly" name="start_date"></label>
			<select name="start_hour" class="time-select">
				<option value="" selected="selected"> </option>
				<option value="10">10</option>
				<option value="11">11</option>
				<option value="12">12</option>
				<option value="13">13</option>
				<option value="14">14</option>
				<option value="15">15</option>
				<option value="16">16</option>
				<option value="17">17</option>
				<option value="18">18</option>
				<option value="19">19</option>
				<option value="20">20</option>
				<option value="21">21</option>
				<option value="22">22</option>
			</select>
			<span>時</span>
			<select name="start_min" class="time-select">
				<option value="" selected="selected"> </option>
				<option value="00">00</option>
				<option value="15">15</option>
				<option value="30">30</option>
				<option value="45">45</option>
			</select>
			<span>分</span>
		</td>
	</tr>
	<tr>
		<th>終了日時</th>
		<td>
			<label class="cal-wrap"><input type="text" class="cal datepicker" readonly="readonly" name="end_date"></label>
			<select name="end_hour" class="time-select">
				<option value="" selected="selected"> </option>
				<option value="10">10</option>
				<option value="11">11</option>
				<option value="12">12</option>
				<option value="13">13</option>
				<option value="14">14</option>
				<option value="15">15</option>
				<option value="16">16</option>
				<option value="17">17</option>
				<option value="18">18</option>
				<option value="19">19</option>
				<option value="20">20</option>
				<option value="21">21</option>
				<option value="22">22</option>
			</select>
			<span>時</span>
			<select name="end_min" class="time-select">
				<option value="" selected="selected"> </option>
				<option value="00">00</option>
				<option value="15">15</option>
				<option value="30">30</option>
				<option value="45">45</option>
			</select>
			<span>分</span>
		</td>
	</tr>
</table>
<div class="btn-style"><a href="#" class="confirm-btn">確認</a></div>
</div>

続いてCSSのコードです。セレクトボックス用のCSSを追加します。

.form_section {
	max-width: 630px;
	margin: 0 auto;
	padding: 0;
}
.date-table {
	border-collapse: collapse;
}
.date-table th {
	color: #53a034;
	padding: 15px 20px 0 0;
	vertical-align: top;
	white-space: nowrap;
}
.date-table td {
	padding: 0 0 1.5em 0;
}
.cal-wrap {
	position: relative;
	cursor: pointer;
	margin: 0 15px 0 0;
}
.cal-wrap:before {
	content: "";
	background: url(icon_calendar.svg) no-repeat;
	background-size: contain;
	height: 22px;
	width: 22px;
	position: absolute;
	top: 0;
	bottom: 0;
	left: 10px;
	margin: auto;
}
input[type="text"].cal {
	font-size: 18px;
	outline: none;
	background: #e9e9e9;
	border-radius: 5px;
	height: 50px;
	line-height: 50px;
	padding: 0 0 0 50px;
	cursor: pointer;
	width: 180px;
	box-sizing: border-box;
	border: 2px solid #ccc;
}
.time-select {
	font-size: 18px;
	outline: none;
	background: #e9e9e9;
	border-radius: 5px;
	height: 50px;
	line-height: 50px;
	width: 70px;
	box-sizing: border-box;
	border: 2px solid #ccc;
}
.btn-style a {
	background: #53a034;
	border-radius: 40px;
	color: #fff;
	display: inline-block;
	font-weight: bold;
	height: 40px;
	line-height: 40px;
	text-align: center;
	width: 100%;
	max-width: 200px;
	text-decoration: none;
}
.error_txt {
	display: block;
	margin: .3em 0 0 0;
	color: #f00;
}
@media screen and (max-width: 480px) {
	.cal-wrap {
		display: block;
		margin: 0 0 1em;
	}
}

最後にjQueryのコードです。
開始の「時」と「分」、終了の「時」と「分」はparseIntで文字列を数値に変換して取得します。Dateを利用して日付を取得する際に、「時」と「分」は数値として処理するためです。セレクトボックスで「時」と「分」を選択していない場合、空のvalue値をparseIntするとNaNが返ります。そのため、必須入力チェックはisNaNを利用して判定しています。開始日時と終了日時の時間差はgetTimeを利用して計算しますが、getTimeはミリ秒を返すため時間差はミリ秒差になります。そのため、割り戻して時間差にします。その際、15分単位は小数点以下になりますが、Math.ceilで切り上げて整数にします。これで時間差が15分以上、すなわち切り上げて1時間以上になれば、時間の整合性チェックはエラーになりません。反対に時間差がマイナス、または開始日時と終了日時が全く同じで時間差が0の場合は、エラーになります。

$(function() {
	if($(".datepicker").length) {
		$(".datepicker").datepicker();
	}

	if($('.confirm-btn').length) {
		var error_html = '<span class="error_txt">※必須項目です。日時を全て選択してください。</span>';
		var error_html_time = '<span class="error_txt">※終了日時は開始日時よりも後に設定してください。</span>';

		$('.confirm-btn').on('click',function() {
			var form_sec = $(this).closest('.form_section');
			var start_date = $(form_sec).find('[name="start_date"]').val();
			var start_hour = parseInt($(form_sec).find('[name="start_hour"]').val());
			var start_min = parseInt($(form_sec).find('[name="start_min"]').val());
			var end_date = $(form_sec).find('[name="end_date"]').val();
			var end_hour = parseInt($(form_sec).find('[name="end_hour"]').val());
			var end_min = parseInt($(form_sec).find('[name="end_min"]').val());

			// エラーリセット
			$(form_sec).find('[name="start_date"]').closest('td').find('.error_txt').remove();
			$(form_sec).find('[name="end_date"]').closest('td').find('.error_txt').remove();

			// 必須チェック
			if(start_date === '' || isNaN(start_hour) || isNaN(start_min)) {
				$(form_sec).find('[name="start_date"]').closest('td').append(error_html);
			}
			if(end_date === '' || isNaN(end_hour) || isNaN(end_min)) {
				$(form_sec).find('[name="end_date"]').closest('td').append(error_html);
			}
			if($(form_sec).find('.error_txt').length) {
				return false;
			}

			// 時間計算
			var start = new Date(start_date + ' ' + start_hour + ':' + start_min);
			var end = new Date(end_date + ' ' + end_hour + ':' + end_min);
			var diff = end.getTime() - start.getTime();
			var diff_hour = Math.ceil(diff / (1000 * 60 * 60) );

			// 時間の整合性チェック
			if ( diff_hour < 1 ) {
				$(form_sec).find('[name="end_date"]').closest('td').append(error_html_time);
				return false;
			}

			return false;
		});
	}
});
タイトルとURLをコピーしました