<form id="form" method="post" action="/send.php" class="form">
<h2>Регистрация</h2>
<label class="form-control">
<span>Имя</span>
<input
data-req="Имя обязательное"
data-name="Проверьте правильность Имени"
data-success="Поля валидное"
type="text"
name="username"
placeholder="Введите здесь Ваше имя"/>
</label>
<label class="form-control">
<span>Фамилия</span>
<input
data-req="Фамилия обязательное"
data-surname="Проверьте правильность Фамилии"
data-success="Поля валидное"
type="text"
name="userlastname"
placeholder="Введите здесь Вашу фамилию"/>
</label>
<label class="form-control">
<span>Почта</span>
<input
data-req="Email обязателен"
data-email="Проверьте правильность email"
data-success="Поля валидное"
type="text" name="email"
placeholder="Введите Вашу почту"
/>
</label>
<label class="form-control">
<span>Номер телефона</span>
<input
data-req="Номер телефона обязателен"
data-tel="Проверьте правильность номера телефона"
data-success="Поля валидное"
type="tel" name="tel"
placeholder="Введите Ваш номер телефона"
/>
</label>
<label class="form-control">
<span>Пароль</span>
<input
data-req="Пароль обязателен"
data-password="Проверьте правильность пароля"
data-success="Поля валидное"
type="password" name="password"
placeholder="Введите Ваш пароль"
/>
</label>
<label class="form-control">
<span>Подтверждение пароля</span>
<input
data-req="Пароль обязателен"
data-password="Проверьте правильность пароля"
data-success="Поля валидное"
type="password" name="password2"
placeholder="Введите пароль снова"
/>
</label>
<label class="form-control form-control--line">
<span>Я согласен с условиями</span>
<input name="agree" data-req="Обязательно согласитесь" type="checkbox"/>
</label>
<button type="submit">Зарегистрироваться</button>
</form>
@import url('https://fonts.googleapis.com/css?family=Nunito&display=swap');
:root {
--success-color: #0cb854;
--error-color: #ee1f09;
}
* {
box-sizing: border-box;
}
body {
background-color: #f9fafb;
font-family: 'Nunito', sans-serif;
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
margin: 0;
}
.container {
background-color: #fff;
border-radius: 5px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
width: 500px;
}
h2 {
text-align: center;
margin: 0 0 20px;
}
.form {
padding: 30px 40px;
}
.form-control {
display: block;
margin-bottom: 10px;
padding-bottom: 20px;
position: relative;
}
.form-control span {
color: rgb(58, 58, 58);
display: block;
margin-bottom: 5px;
}
.form-control input {
border: 2px solid #c9c9c9;
border-radius: 4px;
display: block;
width: 100%;
padding: 10px;
font-size: 14px;
}
.form-control input:focus {
outline: 0;
border-color: #777;
}
.form-control--line {
display: flex;
align-items: center;
}
.form-control--line span {
margin-bottom: 0;
margin-right: 5px;
}
.form-control--line input {
width: auto;
}
.form-control.success input {
border-color: var(--success-color);
}
.form-control.error input {
border-color: var(--error-color);
}
.form-control small.error-item {
color: var(--error-color);
visibility: hidden;
}
.form-control small.success-item {
color: var(--success-color);
visibility: hidden;
}
.form-control.error small,
.form-control.success small {
display: block;
visibility: visible;
}
.form button {
cursor: pointer;
background-color: #3498db;
border: 2px solid #3498db;
border-radius: 4px;
color: #fff;
display: block;
font-size: 16px;
padding: 10px;
margin-top: 20px;
width: 100%;
}
function ValidateForm (_form) {
const errorClass = 'error';
const successClass = 'success';
const labelClass = 'form-control';
const errorItemClass = 'error-item';
const successItemClass = 'success-item'
const _elements = _form.elements;
_form.addEventListener('submit', event => {
event.preventDefault();
const formData = new FormData(_form);
this.checkFormElements();
if (this.formValidate()) {
try {
fetch(_form.action, {
method: _form.method,
body: formData
})
.then(response => {
if (response.ok) {
console.log('Форма отправлена успешно');
} else {
console.log('Ошибка отправки формы');
}
})
} catch(error) {
console.error('Ошибка: ', error);
}
}
});
for(let _element of _elements) {
_element.addEventListener('input', () => {
this.checkFormSingleElement(_element);
});
}
this.checkFormElements = function () {
for(let _element of _elements) {
this.checkFormSingleElement(_element);
}
}
this.checkFormSingleElement = function (_element) {
const reqMessage = _element.dataset.req;
const emailMessage = _element.dataset.email;
const telMessage = _element.dataset.tel;
const nameMessage = _element.dataset.name;
const surNameMessage = _element.dataset.surname;
const passwordMessage = _element.dataset.password;
const successMessage = _element.dataset.success;
this.clearErrorAndSuccess(_element);
if (reqMessage) {
this.checkRequired(_element, reqMessage);
}
if (emailMessage) {
this.checkEmail(_element, emailMessage, successMessage);
}
if (telMessage) {
this.checkTel(_element, telMessage, successMessage);
}
if (nameMessage) {
this.checkName(_element, nameMessage, successMessage);
}
if (surNameMessage) {
this.checkName(_element, surNameMessage, successMessage);
}
if(passwordMessage) {
this.checkPassword(passwordMessage, successMessage);
}
}
this.checkRequired = function (_element, reqMessage) {
const notValidStr = _element.value.trim().length === 0;
const notValidCheckbox = _element.type === 'checkbox' && _element.checked === false;
if (notValidStr || notValidCheckbox) {
this.createErrorTemplate(_element, reqMessage);
}
}
this.checkName = function (_element, message, successMessage) {
const nameStr = _element.value.trim();
const nameRegExp = /^[a-zA-Zа-яА-ЯёЁ\s-]{2,50}$/;
if (!nameRegExp.test(nameStr)) {
this.createErrorTemplate(_element, message);
} else {
this.createSuccessTemplate(_element, successMessage);
}
}
this.checkEmail = function (_element, message, successMessage) {
const emailStr = _element.value.trim();
const emailRegExp = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;
if (!emailRegExp.test(emailStr)) {
this.createErrorTemplate(_element, message);
} else {
this.createSuccessTemplate(_element, successMessage);
}
}
this.checkTel = function (_element, message, successMessage) {
const phoneStr = _element.value.trim();
const phoneRegExp = /^\+?[0-9\s\-()]{7,}$/;
if (!phoneRegExp.test(phoneStr)) {
this.createErrorTemplate(_element, message);
} else {
this.createSuccessTemplate(_element, successMessage);
}
}
this.checkPassword = function (message, successMessage) {
const allPasswords = _form.querySelectorAll('input[type="password"]');
const arrPasswordValues = Array.from(allPasswords).map(item => item.value.trim());
const passwordRegExp = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;
const checkPassByRegExp = arrPasswordValues.every(pass => passwordRegExp.test(pass));
const checkPassByUniqueness = new Set(arrPasswordValues).size === 1;
if (!checkPassByUniqueness || !checkPassByRegExp) {
allPasswords.forEach((value) => this.createErrorTemplate(value, message));
} else {
allPasswords.forEach(value => this.createSuccessTemplate(value, successMessage));
}
}
this.createErrorTemplate = function (_element, message) {
const parent = _element.closest(`.${labelClass}`);
parent.classList.add(errorClass);
parent.insertAdjacentHTML('beforeend', `<small class=${errorItemClass}>${message}</small>`);
}
this.createSuccessTemplate = function (_element, message) {
const parent = _element.closest(`.${labelClass}`);
if (parent) {
parent.classList.add(successClass);
parent.insertAdjacentHTML('beforeend',`<small class=${successItemClass}>${message}</small>`)
}
}
this.clearErrorAndSuccess = function (_element) {
const parent = _element.closest(`.${labelClass}`);
if (parent) {
parent.classList.remove(errorClass, successClass);
parent.querySelectorAll(`.${errorItemClass}, .${successItemClass}`).forEach(item => item.remove());
}
}
this.formValidate = function () {
let allValid = true;
for(let _element of _elements) {
const parent = _element.closest(`.${labelClass}`);
if (parent.classList.contains(errorClass)) {
allValid = false;
break;
}
}
return allValid;
}
}
new ValidateForm(document.querySelector('#form'));
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.