#constraint-validation {
--color-main: #9e9e9e;
--color-focus: #26a69a;
--color-error: #f44336;
width: 80%;
.inputArea {
position: relative;
height: torem(52px);
margin-top: torem(32px);
.label {
position: absolute;
top: 0;
left: 0;
color: var(--color-main);
font-size: torem(16px);
line-height: torem(32px);
transition: 0.2s ease-out;
}
.input {
display: block;
width: 100%;
height: torem(32px);
border: 0;
border-bottom: 1px solid var(--color-main);
padding: 0;
margin-bottom: torem(8px);
&:focus {
outline: none;
}
}
.helper {
display: block;
color: var(--color-error);
font-size: torem(12px);
line-height: torem(12px);
opacity: 0;
transition: 0.2s ease-out;
}
&.focus {
.label {
color: var(--color-focus);
font-size: torem(12px);
line-height: torem(16px);
transform: translateY(torem(-16px));
}
.input {
border-bottom: 1px solid var(--color-focus);
}
}
&.invalid {
.input {
border-bottom: 1px solid var(--color-error);
}
.helper {
opacity: 1;
}
}
}
.button {
margin-top: torem(32px);
.submit {
height: torem(36px);
color: color(white);
font-size: torem(14px);
line-height: torem(36px);
background-color: var(--color-focus);
border: 0;
border-radius: torem(3px);
padding: 0 torem(16px);
cursor: pointer;
}
}
}
/**
* 表单聚焦
*/
function focus(e) {
e.target.closest('.inputArea').classList.add('focus');
}
/**
* 表单失去焦点
*/
function blur(e) {
const { value } = e.target;
if (!value) {
e.target.closest('.inputArea').classList.remove('focus');
}
}
/**
* 表单输入变动
*/
function change(e) {
const input = e.target;
input.closest('.inputArea').classList.remove('invalid');
// customValidity设置后将一直保存,需手动清理,然后执行验证
if (input.validity.customError) {
input.setCustomValidity('');
}
input.checkValidity();
}
/**
* 表单invalid处理
*/
function invalid(e) {
e.preventDefault();
const input = e.target;
const inputType = input.getAttribute('type');
const inputArea = input.closest('.inputArea');
const helper = inputArea.querySelector('.helper');
// 自定义相对valueMissing更明确的提示
if (input.validity.valueMissing) {
if (inputType === 'email') {
input.setCustomValidity('Email Required');
} else if (inputType === 'password') {
input.setCustomValidity('Password Required');
}
}
// 相对patternMismatch更明确的提示
if (input.validity.patternMismatch && inputType === 'password') {
helper.innerHTML = `${input.validationMessage.slice(0, -1)}:${input.title}`;
} else {
helper.innerHTML = input.validationMessage;
}
inputArea.classList.add('invalid');
}
/**
* 表单提交,只有完成Constraint Validation才会触发submit事件
*/
function submit(e) {
e.preventDefault();
const form = e.target;
Array.from(form.querySelectorAll('.inputArea')).forEach((elem) => {
elem.classList.remove('focus', 'invalid');
});
form.reset();
}
document.addEventListener('DOMContentLoaded', () => {
const form = document.querySelector('#constraint-validation');
form.addEventListener('submit', submit, false);
Array.from(document.querySelectorAll('.input')).forEach((input) => {
input.addEventListener('focus', focus, false);
input.addEventListener('blur', blur, false);
input.addEventListener('change', change, false);
input.addEventListener('invalid', invalid, false);
});
}, false);