前回はデータ入力部分をより使いやすくするための修正を行いました。
今回はログインやユーザー登録で情報を入力する際に、リアルタイムで入力チェックを行い、すべてのチェックがクリアできたときだけ送信ボタンを押せるようにする処理を追加します。
ログイン・新規ユーザー登録スタイリング修正
情報入力チェック処理実装の前に、スタイリングの修正を行います。
PC画面の入力要素の幅をスマホ表示時と同様に親要素に対して100%になるように修正します。
//ユーザー登録フォーム
&--join {
width: 80%;
span {
//省略
}
//↓↓追加↓↓
label[for="initial_savings"] {
align-items: center;
input[type="number"] {
width: 95%;
}
span {
width: 5%;
font-size: 1.6rem;
text-align: right;
}
}
//↑↑追加↑↑
input[type="text"],
input[type="password"],
input[type="number"] {
//width: 40%; 削除
//min-width: 20rem; 削除
padding: 0.7rem 0.3rem; //★変更
background-color: #fff;
@include m.mq(sp) {
//width: 90%; 削除
padding: 0.5rem 0.3rem;
}
}
//↓↓追加↓↓
input[type="text"],
input[type="password"] {
width: 100%;
}
//↑↑追加↑↑
}
//ログインフォーム
&--login {
//省略
span {
//省略
}
input[type="text"],
input[type="password"] {
width: 100%; //★変更
//min-width: 20rem; 削除
padding: 0.7rem 0.3rem; //★変更
background-color: #fff;
@include m.mq(sp) {
// width: 100%; 削除
padding: 0.5rem 0.3rem;
}
}
//省略
}
貯蓄額を入力する要素のHTML構造も少し修正します。
<p>貯蓄額<span>(任意・変更可)</span></p>
<label for="initial_savings" class="u-flex-box"> <!--forとclass属性追加-->
<input type="number" autocomplete="off" name="initial_savings" id="initial_savings" value="<?php echo h($initial_savings); ?>">
<span>円</span> <!--inputの後付からspanに変更-->
</label>
input要素がPC表示でも100%になりました。
しかし画面幅が広い場合に、入力要素も長くなってしまうので長さの最大値を指定します。
.p-section {
//ユーザー登録入力セクション
//ユーザー登録確認セクション
&__join-input,
&__join-confirm {
width: 70%;
min-width: 45rem;
max-width: 60rem; //★追加
//省略
//ログインフォームセクション
&__login {
width: 70%;
min-width: 45rem;
max-width: 60rem; //★追加
//省略
//メッセージセクション
&__message {
margin: 2rem auto;
&--join {
width: 70%;
min-width: 45rem;
max-width: 60rem; //★追加
animation: error-message 1s alternate;
//省略
以上でスタイリング修正は完了です。
新規ユーザー登録の情報入力チェック
まずは新規ユーザー登録の際の情報入力チェック処理を実装します。
この入力チェックは、チェックを入れたいinput要素にonkeyup属性を追加し、JavaScriptの関数をセットするという方法で追加します。
関数作成の前に下準備を行います。
・文字数が足りない場合のメッセージや、パスワードの安全性の結果をinput要素の下に表示させるp要素の追加
・input要素のclass属性にjs-checkを追加(貯蓄額input以外)
・input要素にonkeyup属性を追加(貯蓄額input以外)
・「確認画面へ」ボタンにid属性とその値submitButtonを追加
<!--input要素内一部属性を抜粋しています-->
<div class="p-form__vertical-input">
<p>ニックネーム<span class="c-text--red">※必須</span><span>※12文字以内</span></p>
<input type="text" id="nickname" class="js-check" onkeyup="" required> <!--onkeyupとjs-checkクラス追加-->
<p class="nickname-check" id="nicknameCheck"></p> <!--追加-->
</div>
<div class="p-form__vertical-input">
<p>ユーザー名<span class="c-text--red">※必須</span><span>※半角英数字6〜12文字</span></p>
<input type="text" id="username" class="js-check" onkeyup="" required> <!--onkeyupとjs-checkクラス追加-->
<p class="username-check" id="usernameCheck"></p> <!--追加-->
</div>
<div class="p-form__vertical-input">
<p>パスワード<span class="c-text--red">※必須</span><span>※半角英数字6〜12文字</span></p>
<input type="password" id="password" class="js-check" onkeyup="" required> <!--onkeyupとjs-checkクラス追加-->
<p class="pass-check" id="passCheck"></p> <!--追加-->
</div>
<div class="p-form__vertical-input">
<p>確認パスワード<span class="c-text--red">※必須</span></p>
<input type="password" id="passwordConfirm" class="js-check" onkeyup="" required> <!--onkeyupとjs-checkクラス追加-->
</div>
<!--貯蓄額入力要素省略-->
<input id="submitButton" type="submit" value="確認画面へ"> <!--id属性submitButton追加-->
それではJavaScriptで入力チェックの関数を作成します。
jsディレクトリ直下に新しく「input-check.js」ファイルを作成し以下の初期設定プログラムを記述します。
/*============
チェック変数定義
=============*/
let nicknameClear = 0, //ニックネームチェッククリア(1が代入されるとクリア)
usernameClear = 0, //ユーザーネームチェッククリア(上記同様)
passwordClear = 0, //パスワードチェッククリア(上記同様)
passwordConfirmClear = 0, //パスワード確認チェッククリア(上記同様)
clearSum = 0, //クリアした項目数の合計
clearVal = 0; //必要なクリア数
/*===============
チェック要素定数定義
================*/
//URLのGETパラメータ「mode」を取得(修正するボタン押下時使用)
const paramMode = new URL(window.location.href).searchParams.get("mode");
//各チェックinput要素取得
const nickname = document.getElementById("nickname");
const username = document.getElementById("username");
const password = document.getElementById("password");
const passwordConfirm = document.getElementById("passwordConfirm");
const input_check = document.getElementsByClassName("js-check");
//input要素下、メッセージ表示p要素取得
const nicknameCheck = document.getElementById("nicknameCheck");
const usernameCheck = document.getElementById("usernameCheck");
const passCheck = document.getElementById("passCheck");
//送信ボタン要素取得
const submitButton = document.getElementById("submitButton");
続いて、onkeyupイベント内で使う関数を作成します。この関数はonkeyup属性にセットする関数とは別物です。
まずは文字列の長さをチェックする関数です。この関数を実行すると、メッセージに表示する文字列を返してくれます。
//引数(チェックするinnput要素, メッセージ表示p要素, 指定文字数)
const checkLength = (checkVal, checkElement, min) => {
if (checkVal.value.length < min) {
//inputの値が指定文字数(min)未満の場合
//メッセージ表示要素にshortクラス追加
checkElement.classList.add("short");
//メッセージ本文を返す
return min + "文字以上入力してください";
} else {
//inputの値が指定文字数(min)以上のとき
//メッセージ表示要素からshortクラス削除
checkElement.classList.remove("short");
//メッセージ本文(空文字)を返す
return "";
}
};
続いて、パスワードの強度をチェックする関数を作成します。こちらの関数も上記の関数同様、メッセージに表示する文字列を返してくれます。
パスワードの強度の処理については以下の記事を参考にしました。
//引数(チェックするinnput要素, メッセージ表示p要素)
const checkStrength = (checkVal, checkElement) => {
let strength = 0; //パスワードの強度
// 英字の大文字と小文字を含んでいれば+1
if (checkVal.value.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/)) strength += 1;
// 英字と数字を含んでいれば+1
if (checkVal.value.match(/([a-zA-Z])/) && checkVal.value.match(/([0-9])/))
strength += 1;
// 点数を元に強さを計測
if (checkVal.value.length < 6) {
//inputの値が6文字未満のとき
//メッセージ表示要素からweak, normal, strongクラスを削除
checkElement.classList.remove("weak", "normal", "strong");
//メッセージ本文とパスワード強度の数値を配列形式で返す
return ["パスワードは6文字以上で入力してください", strength];
} else if (checkVal.value.length >= 6 && strength < 1) {
//inputの値が6文字以上かつ強度の数値が1未満のとき
//メッセージ表示要素からnormal, strongクラスを削除
checkElement.classList.remove("normal", "strong");
//メッセージ要素にweakクラスを追加
checkElement.classList.add("weak");
//メッセージ本文とパスワード強度の数値を配列形式で返す
return ["英数字を各1文字以上入れてください", strength];
} else if (checkVal.value.length >= 6 && strength === 1) {
//inputの値が6文字以上かつ強度の数値が1のとき
//メッセージ表示要素からweak, strongクラスを削除
checkElement.classList.remove("weak", "strong");
//メッセージ要素にnormalクラスを追加
checkElement.classList.add("normal");
//メッセージ本文とパスワード強度の数値を配列形式で返す
return ["パスワード強度:中", strength];
} else if (checkVal.value.length >= 6 && strength > 1) {
//inputの値が6文字以上かつ強度の値が1より大きいとき
//メッセージ表示要素からweak, normalクラスを削除
checkElement.classList.remove("weak", "normal");
//メッセージ要素にstrongクラスを追加
checkElement.classList.add("strong");
//メッセージ本文とパスワード強度の数値を配列形式で返す
return ["パスワード強度:強", strength];
}
};
onkeyupイベント内で使う関数の作成が完了しました。
続いて各inputのonkeyup属性にセットする関数を作成します。関数は項目ごとの関数と全項目共通の関数があります。
以下は項目ごとの関数です。
const nicknameChange = () => {
//先ほど作成した長さをチェックする関数を実行返ってきたメッセージをメッセージ要素に挿入
//引数(ニックネームinput要素, ニックネームinput下メッセージ要素, 最低必要文字数)
nicknameCheck.innerHTML = checkLength(nickname, nicknameCheck, 1);
//ニックネームinputの値が6文字以上のときはチェッククリア
if (nickname.value.length > 0) nicknameClear = 1;
//6文字未満のときはチェッククリアを0にする
else nicknameClear = 0;
};
const usernameChange = () => {
//先ほど作成した長さをチェックする関数を実行し返ってきたメッセージをメッセージ要素に挿入
//引数(ユーザーネームinput要素, ユーザーネームinput下メッセージ要素, 最低必要文字数)
usernameCheck.innerHTML = checkLength(username, usernameCheck, 6);
//ユーザーネームinputの値が6文字以上のときはチェッククリア
if (username.value.length >= 6) usernameClear = 1;
//6文字未満のときはチェッククリアを0にする
else usernameClear = 0;
};
const passChange = (page) => {
if (page === "join") {
//先ほど作成した強度をチェックする関数を実行し返ってきたメッセージをメッセージ要素に挿入
//引数(ユーザーネームinput要素, ユーザーネームinput下メッセージ要素)
//配列で返されるので、末尾に[0]をつける
passCheck.innerHTML = checkStrength(password, passCheck)[0];
if (
//先ほど作成した強度をチェックする関数を実行し帰ってきた強度の数値が1以上かつパスワードinputの値が6文字以上のとき
checkStrength(password, passCheck)[1] >= 1 &&
password.value.length >= 6
)
//パスワードチェッククリア
passwordClear = 1;
//それ以外のときはパスワードチェッククリアを0にする
else passwordClear = 0;
}
};
const passConfirmChange = () => {
//パスワード確認inputの値が1文字以上のときはチェッククリア
if (passwordConfirm.value.length > 0) passwordConfirmClear = 1;
//パスワード確認inputの値が1文字未満のときはチェッククリアを0にする
else passwordConfirmClear = 0;
};
続いて項目共通の関数です。
const inputCheck = (page) => {
//引数がjoinのとき
if (page === "join") {
//チェッククリアの合計を計算(対象項目は4項目)
clearSum =
nicknameClear + usernameClear + passwordClear + passwordConfirmClear;
//チェッククリアに必要な数値(4項目分のため)
clearVal = 4;
}
//チェッククリアの合計とクリアに必要な数が一致したら送信ボタンから
//disabled属性を外し押せるようにする
if (clearSum === clearVal) submitButton.disabled = false;
//チェッククリアの合計とクリアに必要な数が不一致のときは送信ボタンに
//disabled属性を追加し無効にする
else submitButton.disabled = true;
};
各関数pageという引数を用いているのは、ログインページなど他のページでも使い回すためです。
それでは上記の関数を各inputのonkeyup属性にセットします。
まずはbodyの閉じタグの前に作成したJSファイルを読み込む記述を追記します
<script src="../js/input-check.js"></script>
そして各inputに関数をセットし、確認画面へのボタンにdisabledを追加します。
<!--属性一部割愛-->
<!--ニックネームinput-->
<input type="text" id="nickname" class="js-check" onkeyup="nicknameChange();inputCheck('join');">
<!--ユーザーネームinput-->
<input type="text" id="username" class="js-check" onkeyup="usernameChange();inputCheck('join');">
<!--パスワードinput-->
<input type="password" id="password" class="js-check" onkeyup="passChange('join');inputCheck('join');">
<!--パスワード確認input-->
<input type="password" class="js-check" id="passwordConfirm" onkeyup="passConfirmChange();inputCheck('join');">
<!--確認画面へボタン-->
<input id="submitButton" type="submit" value="確認画面へ" disabled>
関数をセットすると以下のように入力チェックが実行され、チェックがクリアするまで確認画面へのボタンが押下できないようになります。
※事前にdisabledのCSS指定をしています。
入力チェック処理が完了しましたが、このままではすでに登録されているユーザー名で遷移しようとした場合や、ユーザー名とパスワードが同一文字列の場合、パスワードとパスワード確認が一致しない場合でエラーが出た際と確認画面で「修正する」を押した時に、再入力しても「確認画面へ」が押下できない不具合が発生するので、エラー時の処理を追加します。
まず不具合が出る原因は、〇〇〇〇Check変数に入れている値が、画面遷移で0にリセットされるので、inputに情報が復元されてもチェックが通っていない判定になることが原因です。
そこでエラーが出ているときは、再入力の必要があるパスワード確認input以外のチェックを通している状態に初期値をセットするプログラムを追記します。
まずはJSファイルを読み込んでいる上にPHPの変数をJavaScriptに渡す記述を追加します。
<script>
const usernameExist = '<?= $exist ?>';
const sameStr = '<?= $samestr ?>';
const passwordMatch = '<?= $password_match ?>';
</script>
<!--↑↑追加↑↑-->
<script src="../js/input-check.js"></script>
この変数を使って、エラー時は強制的にパスワード確認以外はクリア値にセットするプログラムを追記します。
if (
paramMode === "modify" || //予め取得していたGETパラメータのmodeがmodifyのときまたは
typeof usernameExist !== "undefined" || //すでに登録されているユーザー名エラー変数が存在するときまたは
typeof sameStr !== "undefined" || //ユーザー名とパスワードが同一文字列エラ変数が存在するときまたは
typeof passwordMatch !== "undefined" //パスワード確認が一致しない場合
) {
//ニックネーム、ユーザー名、パスワード入力チェックをクリア状態にセット
nicknameClear = 1;
usernameClear = 1;
passwordClear = 1;
}
以上で新規ユーザー登録の入力チェック処理実装は完了です。
ログインの情報入力チェック
続いてログイン画面の情報入力チェックを実装します。
関数の基礎は完成しているので、必要な記述を追加してinputのonkeyup属性にセットします。
まずはメッセージを表示する要素の追加とinput要素にonkeyup属性と関数のセット、id属性の追加を行います。
引数にはloginを指定しています。
<div class="p-form__vertical-input">
<p>ユーザー名<span>※半角英数字6〜12文字</span></p>
<input type="text" name="username" id="username" onkeyup="usernameChange();inputCheck('login');" required>
<p class="username-check" id="usernameCheck"></p>
</div>
<div class="p-form__vertical-input">
<p>パスワード<span>※半角英数字6〜12文字</span></p>
<input type="password" name="password" id="password" onkeyup="passChange('login');inputCheck('login');" required>
<p class="pass-check" id="passCheck"></p>
</div>
ログインへと初期設定へのボタンにid属性とdisabledの追加をします。
<?php if ($login_times === 'not_first') : ?>
<input id="submitButton" type="submit" value="ログイン" disabled>
<?php endif; ?>
<?php if ($login_times === 'first') : ?>
<input id="submitButton" type="submit" value="初期設定へ" disabled>
<?php endif; ?>
JSファイルの読み込みを記述します。
<script src="./js/input-check.js"></script>
引数にloginを指定したので、loginのときの処理を各関数に追記します。
//passChange関数
const passChange = (page) => {
if (page === "join") {
passCheck.innerHTML = checkStrength(password, passCheck)[0];
if (
checkStrength(password, passCheck)[1] >= 1 &&
password.value.length >= 6
)
passwordClear = 1;
else passwordClear = 0;
}
//↓↓追加↓↓
else if (page === "login") {
passCheck.innerHTML = checkLength(password, passCheck, 6);
if (password.value.length >= 6) passwordClear = 1;
else passwordClear = 0;
}
//↑↑追加↑↑
};
//inputCheck関数
const inputCheck = (page) => {
if (page === "join") {
clearSum =
nicknameClear + usernameClear + passwordClear + passwordConfirmClear;
clearVal = 4;
}
//↓↓追加↓↓
else if (page === 'login') {
clearSum =
usernameClear + passwordClear;
clearVal = 2;
}
//↑↑追加↑↑
if (clearSum === clearVal) submitButton.disabled = false;
else submitButton.disabled = true;
};
以上でログイン画面での情報入力チェック処理実装は完了です。
最後に
今回はログイン画面と新規ユーザー登録画面で入力チェックをリアルタイムで行う処理の追加を行いました。
次回はパスワードを忘れた際の再設定機能を実装します。
最後までお読みいただきありがとうございました。
コメント