#目的
スポーツ関連のアプリを担当。
試合時間を設定するフォームで form_for の変数をつかったフレーム派生である
をアプリで使用していたが入力フォームがダサいので何とかならないかと頼まれたタスク。
<%= f.datetime_select :fight_time, use_month_numbers: true, default: Time.zone.now.tomorrow.beginning_of_hour, class:'form-control text-white' %>
カラムにはdatetimeと、日付 + 時間 が一つの値として入っているので、カラムこの二つを分けて送信することを考えると、既にアプリが佳境に入っていた為手直し工数に時間が掛かるな~~と探した。
#ソースコード
<div class='form-team mt-3'>
<%= f.label :試合日時, class:'text-center col-12 text4' %><br />
<input class="datetime W-100 text-white custom-select" id="hizuke" type="datetime-local" name="game[fight_time]" required %>
<small class="form-text text-muted"> ※ 過去の日付は無効です。</small>
<div class="mb-2">
<span id="error1" class="form-team error" aria-live="polite"></span>
</div>
</div>
#参考
参考によると対応しているブラウザによって表示される入力表示が違うらしいが、今回のwebアプリはPCユーザーはターゲットではなかったのでGoサインが出た。
#目的2
今回は上の実装だけでは終わらない。
もともとのコード
<%= f.datetime_select :fight_time, use_month_numbers: true, default: Time.zone.now.tomorrow.beginning_of_hour, class:'form-control text-white' %>
tomorrowだなんだの部分でデフォルトの値をページを開いた時の次の日の00分になる様にしている。
次はこれをjavascriptを使ってやって見る。
#ソースコード
<script>
//今日の日時を取得したのをフォーマットを整えて日付フォームにデフォルトで表示
window.onload = function () {
var date = new Date();
var year = date.getFullYear();
var month = date.getMonth() + 1;
var day = date.getDate();
var hours = date.getHours();
var hoursPlus5 = date.getHours() +5;
var minutes = date.getMinutes();
var toTwoDigits = function (num, digit) {
num += ''
if (num.length < digit) {
num = '0' + num
}
return num
}
// フォームのデフォルト設定。開催日はページ開いた時点の5時間後、募集締め切りはそれより一時間早い
var yyyy = toTwoDigits(year, 4)
var mm = toTwoDigits(month, 2)
var dd = toTwoDigits(day, 2)
var h = toTwoDigits(hoursPlus5, 2)
var m = toTwoDigits(minutes, 2)
var today = yyyy + "-" + mm + "-" + dd + "\T" + h + ":" + m;
var hours2 = hours -"1"
var h2 = toTwoDigits(hours2, 2)
var deadLine = yyyy + "-" + mm + "-" + dd + "\T" + h2 + ":" + m;
document.getElementById("hizuke").value = today;
document.getElementById("hizuke2").value = deadLine;
var button = document.getElementById("new-game-button");
button.onclick = function(){
var settingGameday = document.getElementById("hizuke").value;
var settingDeadline = document.getElementById("hizuke2").value;
var error1 = document.getElementById('error1');
var error2 = document.getElementById('error2');
var settingDuration = document.getElementById("duration").value;
var error3 = document.getElementById('error3');
if (settingDuration % 15 != 0){
error3.innerHTML = "※試合時間は15分単位です";
error3.className = "error active";
return false;
}
if (settingGameday < today) {
console.log(settingGameday);
error1.innerHTML = "※試合日時を過去の日程で設定することは出来ません";
error1.className = "error active";
return false;
} else if (settingGameday < settingDeadline) {
console.log(settingDeadline);
error2.innerHTML = "※募集締切時間は試合日時より早い日時に設定して下さい";
error2.className = "error active";
return false;
} else{
this.submit();
}
}
};
</script>
#参考
自作で全部やるかぁ~↓
【Javascript入門】日付のフォーマット処理まとめ | 侍エンジニア塾ブログ | プログラミング入門者向け学習情報サイト
上は一体なにしてんのや↓
【JavaScript】日付処理 - Qiita
Dateの扱いナイーブやわ~↓
JavaScript の Date は罠が多すぎる - Qiita
datetime型のフォーマットについて調べないと解決しないやん!! ↓
PHP - htmlフォームのinput type="datetime-local"の初期値にmysqlのdatetime型の値を表示する(95555)|teratail
ほうほう↓
【HTML/Javascript】 input="date"に現在の日付(今日の日付)を設定する - ワカログ -Wakalog-
#解説
と上の5つの良いところを持ってきて合作にしました。
ずいぶん冗長ですが思い付いたままかいたものになります。リファクタリングなんて後後。
datetime-localの扱いについての記事が少なかったので手こずったのはこちらです。
同じ処理を行うひとがいるとは思えませんがどうぞ参考に。
下の方はこのアプリ関連なのでざっくり。
1、試合時間が現在の時間より過去にならないように。デフォルトで5時間後(次の日でもいいけど天邪鬼)
2、試合の締め切り時間をデフォルトで試合時間の一時間前
等表側で制限をかけてフォームの送信を止めてます。
↓ 別記事 フォームの送信STOPにはreturn false ↓
formのsubmit()を止めるときはpreventDefault()じゃなくてreturn falseを返す - Qiita
バックスラッシュはエスケープされて¥になります。
以上