Skip to content

Instantly share code, notes, and snippets.

@b-aleksei
Last active August 22, 2021 09:19
Show Gist options
  • Save b-aleksei/fdcd9f772660a9d66d513a9c772c330d to your computer and use it in GitHub Desktop.
Save b-aleksei/fdcd9f772660a9d66d513a9c772c330d to your computer and use it in GitHub Desktop.
ValidForm
const COUNTRY_CODE = 7;
const onInputPhoneInput = ({target}) => {
const matrix = `+${COUNTRY_CODE} (___) ___-__-__`;
let counter = 0;
let val = target.value.replace(/\D/g, '');
if (!val.length) {
val = `${COUNTRY_CODE}`;
}
target.value = '';
Array.prototype.forEach.call(matrix, (item) => {
let isValNumber = /[_\d]/.test(item) && val.length > counter;
if (isValNumber) {
target.value += val.charAt(counter++);
} else {
target.value += val.length <= counter ? '' : item;
}
});
};
export const onFocusPhoneInput = (target) => {
if (!target.value) {
target.value = `+${COUNTRY_CODE}`;
}
target.addEventListener('input', onInputPhoneInput);
target.addEventListener('blur', onBlurPhoneInput);
};
const onBlurPhoneInput = ({target}) => {
if (target.value === `+${COUNTRY_CODE}`) {
target.value = '';
}
target.removeEventListener('input', onInputPhoneInput);
target.removeEventListener('blur', onBlurPhoneInput);
};
{
"urlServer": "https://echo.htmlacademy.ru",
"errorMessages": {
"required": "Поле не должно быть пустым",
"phone": "Неправильный номер",
"email": "Некорректный email"
},
"statusMessages": {
"success": "Ваша заявка принята",
"fail": "Удаленный сервер не найден",
"error": "Сетевая ошибка, проверьте интернет соединение"
}
}
import {onFocusPhoneInput} from './onFocusPhoneInput';
const validationData = {};
const urlData = 'data/sendForm.json';
fetch(urlData).then((res) => res.json()).then((res) => {
Object.assign(validationData, res);
}).catch(() => {});
/*const getDataFromJson = function(url) {
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onload = function() {
if (xhr.status === 200) {
Object.assign(validationData, JSON.parse(xhr.response));
}
};
xhr.send();
};
getDataFromJson(urlData);*/
export class Validate {
constructor(form, config) {
this.form = typeof form === 'string' ? document.querySelector(form) : form;
if (!(this.form instanceof HTMLElement)) {
return;
}
this.defaultConfig = {
url: null,
classError: 'form-invalid',
statusMessages: null,
regEmail: /^\s*[\w.-]+@[\w-]+\.(?:[\w-]+\.)?[A-Za-z]{2,8}\s*$/,
};
this.config = Object.assign(this.defaultConfig, config);
this.handleEvent = this.handleEvent.bind(this);
this.init();
}
init() {
this.form.addEventListener('focusin', this.handleEvent);
this.form.addEventListener('focusout', this.handleEvent);
this.form.addEventListener('submit', this.handleEvent);
this.form.addEventListener('click', this.handleEvent);
this.form.addEventListener('change', this.handleEvent);
}
handleEvent(e) {
switch (e.type) {
case 'focusin':
if (e.target.hasAttribute('data-validate')) {
e.target.setCustomValidity('');
e.target.parentElement.classList.remove('valid');
e.target.parentElement.classList.remove('invalid');
if (e.target.dataset.validate === 'phone') {
onFocusPhoneInput(e.target);
}
}
break;
case 'focusout':
if (e.target.hasAttribute('data-validate')) {
this.checkValue(e.target);
}
break;
case 'click':
if (e.target.closest('[type="submit"]')) {
this.form.classList.remove(this.config.classError);
const inputs = e.currentTarget.querySelectorAll('[data-validate]:not([disabled])');
inputs.forEach((input) => {
this.checkValue(input);
});
if (!this.form.checkValidity()) { // если форма не валидна
setTimeout(() => {
this.form.classList.add(this.config.classError);
});
}
}
break;
case 'submit':
e.preventDefault();
this.sendData();
break;
}
}
setErrorMes(target, typeError) {
target.parentElement.classList.add('invalid');
const messagesObj = validationData.errorMessages;
const errorEl = target.parentElement.querySelector('[data-error]');
if (!messagesObj) return;
if (errorEl) {
errorEl.innerText = messagesObj[typeError];
}
target.setCustomValidity(messagesObj[typeError]);
}
checkValue(target) {
target.parentElement.classList.remove('valid');
target.parentElement.classList.remove('invalid');
if (!target.value && target.required) {
this.setErrorMes(target, 'required');
return;
}
if (target.dataset.validate === 'email') {
target.value = target.value.trim();
if (target.value && !this.config.regEmail.test(target.value)) {
this.setErrorMes(target, 'email');
return;
}
}
if (target.dataset.validate === 'phone') {
const phoneLength = target.value.replace(/\D/g, '').length;
if (target.value && phoneLength < 11) {
this.setErrorMes(target, 'phone');
return;
}
}
target.parentElement.classList.add('valid');
}
beforeSending() {
document.body.insertAdjacentHTML('beforeend', '<div id="spinner"><div class="swiper-lazy-preloader"></div></div>');
}
afterSending() {
const spinner = document.getElementById('spinner');
if (spinner) {
spinner.remove();
}
}
transferStatus(status) {
console.log(validationData.statusMessages[status]);
}
sendData() {
this.beforeSending();
fetch(this.config.url || validationData.urlServer, {
method: 'post',
body: new FormData(this.form),
}).then((res) => {
if (res.ok) {
this.transferStatus('success');
this.form.reset();
this.form.querySelectorAll('.valid').forEach((i) => {
i.classList.remove('valid');
});
} else {
this.transferStatus('fail');
}
}).catch(() => {
this.transferStatus('error');
}).finally(() => {
this.afterSending();
});
/*const xhr = new XMLHttpRequest();
xhr.open('POST', this.config.url || validationData.urlServer);
xhr.onload = () => {
if (xhr.status === 200) {
console.log(xhr.response);
this.transferStatus('success');
this.form.reset();
this.form.querySelectorAll('.valid').forEach((i) => {
i.classList.remove('valid');
});
} else {
this.transferStatus('fail');
}
this.afterSending();
};
xhr.send(new FormData(this.form));*/
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment