開発情報・ナレッジ

投稿者: SPIRERS ナレッジ向上チーム 2023年1月12日 (木)

ビジュアル設定フォームにリアルタイムチェック機能をコピペで実装できる強化ガジェット

コピペするだけでフォーム入力の際にリアルタイムで入力値をチェックしてくれる機能を実装できます。
簡単に実装できますので、フォーム入力補助機能を強化したい時に活用してみてください。
デモはこちら

機能・前提

機能
・必須入力チェック
・メールアドレスチェック
・パスワード強度チェック
前提
・JavaScript のため、対応していないブラウザがあります
・ビジュアル設定が前提となりますので、ソース設定にてタグ構成を変更した場合動作しない可能性がございます
・必須入力のフィールドをグループ化した場合、必須入力チェックが動作いたしません
・ファイルフィールドに対して、リアルタイムでの必須入力チェックは動作いたしません

設定方法

ページの「Javascript」タブに以下のコードを貼り付けてください。
Javascript
// 設定値
const formCheck_Function = [true, true, true]; // [必須チェック, メールアドレスチェック, パスワード強度チェック]
const formCheck_MsgRequired = "入力必須です";
const formCheck_MsgEmail = "メールアドレスの形が正しくありません";
const formCheck_PassCharacter = [true, true, true, true]; // パスワード文字種 [英語小文字, 英語大文字, 数字, 記号]
const formCheck_PassMinimum = 8; // パスワード最小文字数

// 原則変更不可
// 複数強化パーツがある場合、変更あり
window.onload = function () {
    formCheckListener();
};

// 変更不可
// 複数強化パーツがある場合、下記を変更不可箇所に追加
function formCheckListener() {
	if (formCheck_Function[0]) {
		document.querySelectorAll('input[type="text"], input[type="number"], input[type="tel"], input[type="password"], textarea, select').forEach( x => {
			x.addEventListener('blur', () => {
				let val = x.value;
	
				if (val == '') {
					let el = x.closest('div.sp-form-data');
	
					if (el.lastElementChild.className == 'sp-form-error') {
						el.lastElementChild.remove();
					}
					if (el.previousElementSibling.children[0]) {
						if (el.previousElementSibling.children[0].className == 'sp-form-required') {
							el.insertAdjacentHTML('beforeend', '<span class="sp-form-error">' + formCheck_MsgRequired + '</span>');
						}
					}
				} else {
					let el = x.closest('div.sp-form-data');
	
					if (el.lastElementChild.className == 'sp-form-error') {
						el.lastElementChild.remove();
					}
				}
			});
		});
		
		document.querySelectorAll('select').forEach( x => {
			x.addEventListener('change', () => {
				let val = x.value;
	
				if (val == '') {
					let el = x.closest('div.sp-form-data');
	
					if (el.lastElementChild.className == 'sp-form-error') {
						el.lastElementChild.remove();
					}
					if (el.previousElementSibling.children[0]) {
						if (el.previousElementSibling.children[0].className == 'sp-form-required') {
							el.insertAdjacentHTML('beforeend', '<span class="sp-form-error">' + formCheck_MsgRequired + '</span>');
						}
					}
				} else {
					let el = x.closest('div.sp-form-data');
	
					if (el.lastElementChild.className == 'sp-form-error') {
						el.lastElementChild.remove();
					}
				}
			});
		});
	
		document.querySelectorAll('input[type="checkbox"]').forEach( x => {
			x.addEventListener('change', () => {
				let selectionHorizontal = x.closest('div.sp-form-selection-horizontal');
				let selectionVertical = x.closest('div.sp-form-selection-vertical');
				let checkedFlag = 0;
	
				if (selectionHorizontal) {
					selectionHorizontal.querySelectorAll('input[type="checkbox"]').forEach( x => {
						let checked = x.checked;
						if (checked) {checkedFlag += 1;}
					});
				} else if (selectionVertical) {
					selectionVertical.querySelectorAll('input[type="checkbox"]').forEach( x => {
						let checked = x.checked;
						if (checked) {checkedFlag += 1;}
					});
				}
	
				if (checkedFlag == 0) {
					let el = x.closest('div.sp-form-data');
	
					if (el.lastElementChild.className == 'sp-form-error') {
						el.lastElementChild.remove();
					}
					if (el.previousElementSibling.children[0]) {
						if (el.previousElementSibling.children[0].className == 'sp-form-required') {
							el.insertAdjacentHTML('beforeend', '<span class="sp-form-error">' + formCheck_MsgRequired + '</span>');
						}
					}
				} else {
					let el = x.closest('div.sp-form-data');
	
					if (el.lastElementChild.className == 'sp-form-error') {
						el.lastElementChild.remove();
					}
				}
			});
		});
	}

	if (formCheck_Function[0] == true || formCheck_Function[1] == true) {
		document.querySelectorAll('input[type="email"]').forEach( x => {
			x.addEventListener('blur', () => {
				let pattern = /^[A-Za-z0-9]{1}[A-Za-z0-9_.-]*@{1}[A-Za-z0-9_.-]+.[A-Za-z0-9]+$/;
				let val = x.value;
	
				 if (pattern.test(val) == false && val != '' && formCheck_Function[1] == true) {
					let el = x.closest('div.sp-form-data');
	
					if (el.lastElementChild.className == 'sp-form-error') {
						el.lastElementChild.remove();
					}
					el.insertAdjacentHTML('beforeend', '<span class="sp-form-error">' + formCheck_MsgEmail + '</span>');
				} else if (val == '' && formCheck_Function[0] == true) {
					let el = x.closest('div.sp-form-data');
	
					if (el.lastElementChild.className == 'sp-form-error') {
						el.lastElementChild.remove();
					}
					if (el.previousElementSibling.children[0]) {
						if (el.previousElementSibling.children[0].className == 'sp-form-required') {
							el.insertAdjacentHTML('beforeend', '<span class="sp-form-error">' + formCheck_MsgRequired + '</span>');
						}
					}
				} else {
					let el = x.closest('div.sp-form-data');
	
					if (el.lastElementChild.className == 'sp-form-error') {
						el.lastElementChild.remove();
					}
				}
			});
		});
	}

	if (formCheck_Function[2]) {
		document.querySelectorAll('input[type="password"]').forEach( x => {
			x.addEventListener('input', () => {
				let val = x.value;
				let el = x.closest('div.sp-form-data');
				let pas = el.firstElementChild.className;
	
				if (pas == 'sp-form-password-weak' || pas == 'sp-form-password-medium' || pas == 'sp-form-password-strong') {
					el.firstElementChild.remove();
				}
	
				checkPasswordStrength(val, el);
			});
		});
	}
}

function checkPasswordStrength(password, element) {
	let numerator = 0;
	let denominator = 0;

	if (formCheck_PassCharacter[0]) {
		denominator += 1;
		if (password.match(/[a-z]/)) {
			numerator += 1;
		}
	}
	if (formCheck_PassCharacter[1]) {
		denominator += 1;
		if (password.match(/[A-Z]/)) {
			numerator += 1;
		}
	}
	if (formCheck_PassCharacter[2]) {
		denominator += 1;
		if (password.match(/\d/)) {
			numerator += 1;
		}
	}
	if (formCheck_PassCharacter[3]) {
		denominator += 1;
		if (password.match(/[^a-zA-Z\d]/)) {
			numerator += 1;
		}
	}
	if (formCheck_PassMinimum) {
		denominator += 1;
		let num = formCheck_PassMinimum - 1;
		if (password.length > num) {
			numerator += 1;
		}
	}

	let strength = Math.round(numerator / denominator * 100);

	if (strength < 50) {
		element.insertAdjacentHTML('afterbegin', '<span class="sp-form-password-weak">パスワード強度:弱</span>');
	} else if (strength >= 50 && strength < 100) {
		element.insertAdjacentHTML('afterbegin', '<span class="sp-form-password-medium">パスワード強度:中</span>');
	} else if (strength >= 100) {
		element.insertAdjacentHTML('afterbegin', '<span class="sp-form-password-strong">パスワード強度:強</span>');
	}
}
設定値
formCheck_Function どのチェックを有効にするかの設定ができます。
配列で設定する必要があり [必須チェック, メールアドレスチェック, パスワード強度チェック] の順番に設定してください。
動作を有効にしたい場合は「true」、必要ない場合は「false」としてください。

例:必須チェックとメールアドレスチェックのみ動作させたい場合
[true, true, false]
※配列内の「,」を消すと正しく動作しなくなりますのでご注意ください。
formCheck_MsgRequired 入力必須チェック時のエラーメッセージを設定できます。
formCheck_MsgEmail メールアドレスチェック時のエラーメッセージを設定できます。
formCheck_PassCharacter パスワード入力に必要となる文字種を設定することができます。
配列で設定する必要があり [英語小文字, 英語大文字, 数字, 記号] の順番で設定してください。
必要な文字種の場合は「true」、必要ない文字種であれば「false」としてください。

例:パスワードに英語小文字、英語大文字、数字を入れる必要がある場合
[true, true, true, false]
※配列内の「,」を消すと正しく動作しなくなりますのでご注意ください。
formCheck_PassMinimum パスワードの最小文字数を設定することができます。

例:パスワードが8文字以上でなくてはならない場合は、「8」と設定してください。


次に以下のパスワード強度用デザインCSSをページの「CSS」タブに貼り付けてください。
デザインに関しては適宜変更していただいて問題ありません。
※クラス名を変えるとパスワード強度チェックが正しく動作しなくなりますのでご注意ください。
CSS
.sp-form-password-weak {
    width: 180px;
    text-align: center;
    margin-bottom: 0.5rem;
    padding: 0.5rem;
    background:rgba(248,54,0,0.5);
    border: 1.5px solid rgba(248,54,0,1);
    border-radius: 10px;
}

.sp-form-password-medium {
    width: 180px;
    text-align: center;
    margin-bottom: 0.5rem;
    padding: 0.5rem;
    background:rgba(249,212,35,0.4);
    border: 1.5px solid rgba(249,212,35,1);
    border-radius: 10px;
}

.sp-form-password-strong {
    width: 180px;
    text-align: center;
    margin-bottom: 0.5rem;
    padding: 0.5rem;
    background:rgba(12,247,45,0.3);
    border: 1.5px solid rgba(12,247,45,1);
    border-radius: 10px;
}

ビジュアル設定フォームブロックの作成方法などに関しては、こちら を参照してみてください。

最後に

設定後は動作確認を必ず行い、動作に問題がないか確認をしてください。
不具合やほかのやり方が知りたい等あれば、下記の「コンテンツに関しての要望はこちら」からご連絡ください。
解決しない場合はこちら コンテンツに関しての
要望はこちら