Привет, Хабр!
Как-то, год назад я писал о своей небольшой библиотеке, которая облегчает разработку форм на сайтах. Недавно я выпустил 3-ю версию, которая, по-сути, была переписана с нуля, чтобы стать правильней и удобней. Но в своей статье я не буду повторять README и ДЕМО, а лучше покажу на практике, каким образом она помогает писать меньше кода.
Но прежде, хотелось бы дать немного информации о новой версии. В ней, я избавился от зависимости malsup jquery.form для отправки файлов, и один большой репозитарий я разделил на несколько мелких самостоятельных репозитариев, сохранив, при этом, общую сборку "всё-в-одном":
- поддержка дополнительных событий форм (form-extra-events);
- полифил HTML5 form-атрибутов (form-association-polyfill);
- поддержка отправки файлов через iframe для старых браузеров (jquery-iframe-ajax);
- и, собственно, сама библиотека (paulzi-form).
Дополнительные события форм
Во второй версии библиотеки я столкнулся с проблемой необходимости соблюдения определённого порядка подключения скриптов. Например, раньше нельзя было подключать данный скрипт перед стандартным скриптом валидации Yii2, дело в том, что на событие submit навешиваются все скрипты, которые так или иначе должны обработать отправку, в частности произвести валидацию, и нет никакой гарантии что кто-то это событие не прервёт вызовом
preventDefault(). Поэтому, в случае неверного порядка подключения, сначала происходила блокировка формы, а затем валидация, и, если были ошибки валидации, повторно отправить форму было уже нельзя. form-extra-events решает эту проблему, он предоставляет несколько новых типов событий формы, одно из которых гарантирует то, что форма отправляется, и этот процесс уже нельзя прервать. Кроме того, генерируются события начала и завершения отправки формы, что используется во всех остальных возможностях библиотеки.
Сайт-прототип
https://paulzi.ru/misc/github/paulzi-form/v3-site/
Из скриптов используем только jQuery, bootstrap и paulzi-form.all.js. В данном прототипе мы не используем ни строчки JS-кода написанного специально для сайта-прототипа.
Html5 form-атрибуты
switch($action), вместо того, чтобы сразу направить на конкретный action (например, в Yii2). А если вы откроете модальное окно, то увидите, что кнопку отправки пришлось сделать вне самой формы, тем не менее она продолжает функционировать, так как ей был указан атрибут form. А самое главное, данные атрибуты сильно выручают в ситуациях, когда в большой форме нужно сделать маленькую форму, что стандарт HTML запрещает.
Не отправлять пустые поля
?proce_from=&proce_to=&tdp_from=&tdp_from=&line[]=i5
Используя библиотеку, если добавить к форме атрибут data-submit-empty="false" незаполненные поля не будут отправляться, и в результате получится более человекопонятный URL:
?line[]=i5
Блокировка повторной отправки
data-lock="false"
Индикация состояния отправки
Иногда, процесс отправки формы может занимать длительное время (отправка файла, процессороёмкий обработчик, медленный интернет), и если никак не отобразить, что форма отправляется, пользователь рано или поздно подумает, что либо он не нажал кнопку, либо что-то зависло, и нажмёт кнопку повторно. Пример такой формы — форма «Написать нам». В библиотеке предусмотрено несколько вариантов, в прототипе я использовал атрибуты data-loading-text и data-loading-icon, которые изменяют текст кнопки и добавляют иконку. Также к форме и кнопке добавляются классы form-loading и btn-loading, это позволяет застилизовать состояние через CSS.
AJAX-отправка формы
Ну и самое главное, это возможность отправки формы через AJAX. Действительно, у нас в прототипе есть две формы в модальных окнах, логично при нажатии на кнопку отправки не осуществлять переходы между страницами, а просто закрыть модальное окно и вывести сообщение об успехе. И тут всё очень легко — добавляем атрибут
data-via="ajax", и вуаля, форма отправляется через AJAX. И мало того, те, кто хоть раз занимался передачей через AJAX файлов знает, что сделать это не так просто, т. к. поддержка отправки файлов появилось только начиная с XMLHttpRequrest 2. Для этого часто подключают сторонние библиотеки, которые часто требуют написания на серверной части особых обработчиков, хранить файлы во временной папке, а потом при отправке формы в отдельном запросе их оттуда забирать. В нашем же случае, об этом практически не надо задумываться — всё идёт также, как если бы форма отправлялась стандартным способом. При необходимости можно легко вывести процент отправленных данных, подцепившись на событие uploadprogress.
Обработка AJAX-ответов
<span class="badge" data-insert-context="document" data-insert-to=".cart-block .badge" data-insert-mode="replaceWith">43</span> <div class="alert alert-success alert-dismissible" role="alert" data-insert-context="document" data-insert-to=".alert-fixed"> <button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">×</span></button> Товар добавлен в корзину! </div> <div class="cart-block-hover" data-insert-context="document" data-insert-to=".cart-block-hover" data-insert-mode="replaceWith"> <div class="row"> <div class="col-xs-6 text-left">AMD K6</div> <div class="col-xs-6">10 шт.</div> </div> <div class="row"> <div class="col-xs-6 text-left">Intel Celeron</div> <div class="col-xs-6">12 шт.</div> </div> <div class="row"> <div class="col-xs-6 text-left">Intel Core i7</div> <div class="col-xs-6">1 шт.</div> </div> <div class="row cart-block-total"> <div class="col-xs-6 text-left">Итого:</div> <div class="col-xs-6"><span class="price"><span>117 000</span> ₽</span></div> </div> </div>
Как видите, ответ состоит из трёх html-элементов с атрибутами data-insert-to, data-insert-context, data-insert-mode. Эти атрибуты определяют как и в какое место вставить каждый элемент, например, для первого span.badge data-insert-context="document" data-insert-to=".cart-block .badge" data-insert-mode="replaceWith" означает, что данным элементом нужно заменить элемент .cart-block .badge и зона поиска данным селектором — весь документ. Всё это позволяет провести описанные выше действия без единой строчки кода.
Сценарии
data-via атрибут, который укажет как отправлять форму при нажатии на неё.
Настройки
Если вам что-то не нравится, или возникают какие-либо конфликты, в библиотеке можно многое поменять через настройки. Например, нужно ли блокировать повторную отправку всех форм по-умолчанию. Все названия атрибутов также можно поменять.
Заключение
В итоге, подключив библиотеку размером 10 кб, вы получаете самое главное — нужно меньше писать код для разных мелких форм (а то и вовсе не писать), а в довесок получаете несколько приятных возможностей, такие как дополнительные события форм, iframe-транспорт, AJAX-отправка файлов и др.