Commit f04c66c4 authored by Nikolay Gromov's avatar Nikolay Gromov

Добавил валидацию форм

parent 45b6df3b
......@@ -11,4 +11,6 @@ require('../off-canvas/off-canvas.js');
require('../modal/modal.js');
require('../tabs/tabs.js');
require('../baron/baron.js');
require('../object-fit-polyfill/object-fit-polyfill.js');
require('../form-validation/form-validation.js');
require('../../js/script.js');
......@@ -23,7 +23,6 @@
@import "../logo/logo.scss";
@import "../main-nav/main-nav.scss";
@import "../modal/modal.scss";
@import "../object-fit-polyfill/object-fit-polyfill.scss";
@import "../off-canvas/off-canvas.scss";
@import "../or/or.scss";
@import "../page/page.scss";
......@@ -37,6 +36,7 @@
@import "../tabs/tabs.scss";
@import "../social/social.scss";
@import "../to-top/to-top.scss";
@import "../object-fit-polyfill/object-fit-polyfill.scss";
@import "../../scss/print.scss";
......@@ -180,4 +180,18 @@
background-color: #fff !important;
}
}
&__row {
@include row();
}
&__col-1-2 {
@include col();
@include col(md, 6);
}
&__col-2-2 {
@include col();
@include col(md, 12);
}
}
/* global document */
const closest = require('closest');
const ready = require('../../js/utils/documentReady.js');
ready(function(){
// Для всех форм страницы
const forms = Array.from(document.querySelectorAll('form[data-check-form]'));
forms.forEach(function(form){
// Подпишемся на событие отправки
form.addEventListener('submit', function(e){
let valid = true;
// Проверим все текстовые инпуты
const fieldsText = Array.from(form.querySelectorAll('input[data-check-pattern]'));
fieldsText.forEach(function(input){
if(!checkFieldText(input)) valid = false;
});
// Проверим все чекбоксы
const fieldsCheckbox = Array.from(form.querySelectorAll('input[data-check-state]'));
fieldsCheckbox.forEach(function(input){
if(!checkFieldCheckbox(input)) valid = false;
});
// Если были ошибки, не отправляем форму
if(!valid) e.preventDefault();
});
});
// Для всех проверяемых текстовых полей
const fieldsText = Array.from(document.querySelectorAll('input[data-check-pattern]'));
fieldsText.forEach(function(input){
input.addEventListener('blur', function(){ checkFieldText(input); });
});
// Для всех проверяемых чекбоксов
const fieldsCheckbox = Array.from(document.querySelectorAll('input[data-check-state]'));
fieldsCheckbox.forEach(function(input){
input.addEventListener('change', function(){ checkFieldCheckbox(input); });
});
function checkFieldText(input) {
input.addEventListener('input', function(){ checkFieldText(input); });
const regExp = new RegExp(input.dataset.checkPattern, 'gi');
const result = regExp.test(input.value);
const errorClass = 'field-text--error';
const parent = closest(input, '.field-text');
result ? parent.classList.remove(errorClass) : parent.classList.add(errorClass);
return result;
}
function checkFieldCheckbox(input) {
const trueVal = input.dataset.checkState == 'on' ? true : false;
const result = trueVal === input.checked
const errorClass = 'field-checkbox__input-wrap--error';
const parent = closest(input, '.field-checkbox__input-wrap');
result ? parent.classList.remove(errorClass) : parent.classList.add(errorClass);
return result;
}
});
Включается при указании на теге `form` атрибута `data-check-form`.
Для текстовых полей: по событию `blur` содержимое поля анализируется на соответствие регулярному выражению из атрибута `data-check-pattern`.
Для чекбоксов: по событию `change` проверяется соответствия состояния и `data-check-state="on"` (`off`).
<p class="alert alert--warning">Блок не имеет классов, упоминаемых в разметке. Чтобы взять его в сборку, упомяните <code>form-validation</code> в <code>config.js#alwaysAddBlocks</code>.</p>
<p class="alert alert--warning">Pug «умно» обрабатывает строки, убирая обратный слеш (<code>\</code>), этот символ в pug нужно экранировать: не <code>\d</code>, а <code>\\d</code>. <br>См. пример кода ниже.</p>
......@@ -2,4 +2,4 @@
<p class="alert alert--warning">Блок не имеет классов, упоминаемых в разметке. Чтобы взять его в сборку, упомяните <code>object-fit-polyfill</code> в <code>config.js#alwaysAddBlocks</code>.</p>
[Полифил](https://github.com/bfred-it/object-fit-images). [Добавленный PostCSS-плагин](https://github.com/ronik-design/postcss-object-fit-images).
Инструменты: [полифил](https://github.com/bfred-it/object-fit-images), [PostCSS-плагин, реализующий автоматическое применение полифила](https://github.com/ronik-design/postcss-object-fit-images).
......@@ -716,6 +716,99 @@ block content
+block-lib-code()
include:show-code(first-line='//- Pug-файл этого блока:') ../blocks/form/form.pug
+block-lib('form-validation', 'Валидатор форм', true)
include:markdown-it(html='true') ../blocks/form-validation/readme.md
+form()(class='blocks-library__row', data-check-form='true')
.blocks-library__col-1-2
+field-text({
title: 'Имя',
helpText: 'Имя юзера. Не менее 3-х символов. Обязательно.',
attrs: {
require: true,
'data-check-pattern': '^[a-zа-яё]+.{2,}'
}
})
.blocks-library__col-1-2
+field-text({
title: 'Фамилия',
helpText: 'Фамилия. Не менее 2-х символов. Не обязательно.',
attrs: {
'data-check-pattern': '^[a-zа-яё]+.+'
}
})
.blocks-library__col-1-2
+field-text({
title: 'Телефон',
helpText: 'Обязательно.',
attrs: {
type: 'tel',
require: true,
placeholder: '+7 (000) 000-00-00',
'data-check-pattern': '[\\+]?\\d?[\\s|-]?[(]?\\d{0,3}[)]?[\\s|-]?\\d{3}[\\s|-]?\\d{2}[\\s|-]?\\d{2}'
}
})
.blocks-library__col-1-2
+field-text({
title: 'Электромыло',
helpText: 'Обязательно.',
attrs: {
type: 'email',
require: true,
'data-check-pattern': '[a-z0-9!#$%&\'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&\'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?'
}
})
.blocks-library__col-2-2
+field-checkbox([
{
title: 'Принимаю условия, передаю квартиру во владение Николаю.',
helpText: 'Это шутка, чекбокс можно спокойно отмечать. Или же нет.',
attrs: {
name: 'checkCheck',
'data-check-state': 'on',
}
},
{
title: 'Должен. Быть. Неотмеченным.',
helpText: 'Иначе всё — тлен!',
attrs: {
name: 'checkOff',
'data-check-state': 'off',
checked: true,
}
},
])
.blocks-library__col-2-2
+field-actions()
+btn('Отправить', 'primary')
+block-lib-code()
pre.code
code +field-text({
code title: 'Фамилия',
code helpText: 'Фамилия. Не менее 2-х символов. Не обязательно.',
code attrs: {
code 'data-check-pattern': '^[a-zа-яё]+.+'
code }
code })
code +field-text({
code title: 'Телефон',
code helpText: 'Обязательно.',
code attrs: {
code type: 'tel',
code require: true,
code placeholder: '+7 (000) 000-00-00',
code 'data-check-pattern': '[\\+]?\\d?[\\s|-]?[(]?\\d{0,3}[)]?[\\s|-]?\\d{3}[\\s|-]?\\d{2}[\\s|-]?\\d{2}'
code }
code })
code +field-text({
code title: 'Электромыло',
code helpText: 'Обязательно.',
code attrs: {
code type: 'email',
code require: true,
code 'data-check-pattern': '[a-z0-9!#$%&\'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&\'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?'
code }
code })
+block-lib('scroll-link', 'Якорные ссылки', false)
include:markdown-it(html='true') ../blocks/scroll-link/readme.md
+scroll-link('Описание блока <code>page</code>', '#page')
......@@ -829,6 +922,20 @@ block content
+block-lib-code()
include:show-code(first-line='//- Pug-файл этого блока:') ../blocks/baron/baron.pug
+block-lib('object-fit-polyfill', 'Поддержка object-fit для IE', false)
include:markdown-it(html='true') ../blocks/object-fit-polyfill/readme.md
img.ofp-demo(src='img/demo-avatar-m.png', alt='Аватар', style='width: 128px; height: 64px;')
img.ofp-demo(src='img/demo-avatar-f.png', alt='Аватар', style='width: 64px; height: 64px;')
+block-lib-code()
div
pre.code
code &lt;img src="img/demo-avatar-m.png" class="semantic-class" style="width: 128px; height: 64px;" alt="Аватар" />
code &lt;img src="img/demo-avatar-f.png" class="semantic-class" style="width: 64px; height: 64px;" alt="Аватар" />
pre.code
code .semantic-class {
code object-fit: cover;
code }
.burger.blocks-library__menu-toggler(data-toggle='off-canvas')
span(data-toggle='off-canvas')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment