77 lines
2.7 KiB
JavaScript
77 lines
2.7 KiB
JavaScript
const rules = {
|
|
min: (value, min) => value.length >= min,
|
|
upper: (value) => /[A-Z]/.test(value),
|
|
lower: (value) => /[a-z]/.test(value),
|
|
number: (value) => /\d/.test(value),
|
|
symbol: (value) => /[^a-zA-Z0-9]/.test(value),
|
|
email: (value, _min, email) => {
|
|
if (!email) return true;
|
|
return !value.toLowerCase().includes(email.toLowerCase());
|
|
},
|
|
match: (_value, _min, _email, confirm) => {
|
|
if (!confirm) return false;
|
|
return true;
|
|
}
|
|
};
|
|
|
|
export function initPasswordHints() {
|
|
const containers = document.querySelectorAll('[data-password-hints]');
|
|
if (!containers.length) return;
|
|
|
|
containers.forEach((container) => {
|
|
const passwordSelector = container.dataset.passwordInput;
|
|
const confirmSelector = container.dataset.confirmInput;
|
|
const emailSelector = container.dataset.emailInput;
|
|
const passwordInput = passwordSelector ? document.querySelector(passwordSelector) : null;
|
|
const confirmInput = confirmSelector ? document.querySelector(confirmSelector) : null;
|
|
const emailInput = emailSelector ? document.querySelector(emailSelector) : null;
|
|
const minLength = Number.parseInt(container.dataset.minLength || '12', 10);
|
|
const items = container.querySelectorAll('[data-rule]');
|
|
|
|
const setState = (item, state) => {
|
|
item.classList.remove('is-valid', 'is-invalid');
|
|
if (state === 'valid') item.classList.add('is-valid');
|
|
if (state === 'invalid') item.classList.add('is-invalid');
|
|
};
|
|
|
|
const evaluate = () => {
|
|
const password = passwordInput?.value ?? '';
|
|
const confirm = confirmInput?.value ?? '';
|
|
const email = emailInput?.value ?? '';
|
|
const hasValue = password.length > 0 || confirm.length > 0;
|
|
|
|
items.forEach((item) => {
|
|
const rule = item.dataset.rule;
|
|
if (!rule) return;
|
|
if (!hasValue) {
|
|
setState(item, 'neutral');
|
|
return;
|
|
}
|
|
if (rule === 'match') {
|
|
if (password === '' || confirm === '') {
|
|
setState(item, 'neutral');
|
|
return;
|
|
}
|
|
setState(item, password === confirm ? 'valid' : 'invalid');
|
|
return;
|
|
}
|
|
const check = rules[rule];
|
|
if (!check) return;
|
|
const ok = check(password, minLength, email, confirm);
|
|
setState(item, ok ? 'valid' : 'invalid');
|
|
});
|
|
};
|
|
|
|
if (passwordInput) passwordInput.addEventListener('input', evaluate);
|
|
if (confirmInput) confirmInput.addEventListener('input', evaluate);
|
|
if (emailInput) emailInput.addEventListener('input', evaluate);
|
|
evaluate();
|
|
});
|
|
}
|
|
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', initPasswordHints);
|
|
} else {
|
|
initPasswordHints();
|
|
}
|