Pull to refresh

Библиотека, облегчающая разработку форм на сайтах (v3)

Reading time 6 min
Views 23K

Привет, Хабр!


Как-то, год назад я писал о своей небольшой библиотеке, которая облегчает разработку форм на сайтах. Недавно я выпустил 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 решает эту проблему, он предоставляет несколько новых типов событий формы, одно из которых гарантирует то, что форма отправляется, и этот процесс уже нельзя прервать. Кроме того, генерируются события начала и завершения отправки формы, что используется во всех остальных возможностях библиотеки.


Сайт-прототип


Для демонстрации полезности библиотеки, я набросал прототип типичного интернет-магазина на Bootstrap:
https://paulzi.ru/misc/github/paulzi-form/v3-site/

Из скриптов используем только jQuery, bootstrap и paulzi-form.all.js. В данном прототипе мы не используем ни строчки JS-кода написанного специально для сайта-прототипа.



Html5 form-атрибуты


В чём может пригодиться HTML5 form-атрибуты? Например, в корзине предполагается несколько действий над выбранными товарами — добавить в избранное, отправить на Email, скачать. Конечно, можно было бы сделать единый action, а в параметрах передавать, что конкретно нужно сделать. Но это некрасиво, т. к. порождает использование switch($action), вместо того, чтобы сразу направить на конкретный action (например, в Yii2). А если вы откроете модальное окно, то увидите, что кнопку отправки пришлось сделать вне самой формы, тем не менее она продолжает функционировать, так как ей был указан атрибут form. А самое главное, данные атрибуты сильно выручают в ситуациях, когда в большой форме нужно сделать маленькую форму, что стандарт HTML запрещает.


Не отправлять пустые поля


Теперь, обратим внимание на фильтр в каталоге. Если отметить галочкой «Intel Core i5» и отправить данную форму, то даже если другие поля не заполнены, мы всё равно получим длинную простыню из параметров после перехода:

?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-ответов


Посмотрим на пример посложнее — кнопка добавления в корзину на странице каталога. При нажатии на неё надо не просто выполнить запрос и вывести сообщение — нужно обновить краткий список содержимого корзины при наведении и обновить счётчик количества товаров в ней. Этот момент тоже учтён, и я постарался сделать максимально гибкий обработчик 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">&times;</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 и зона поиска данным селектором — весь документ. Всё это позволяет провести описанные выше действия без единой строчки кода.



Сценарии


Вернёмся на страницу корзины. Как уже было рассмотрено выше, на неё есть несколько кнопок, которые подразумевают разные действия. Например, при нажатии на "оформить" логично отправить форму стандартным механизмом, после чего осуществить редирект на страницу с информацией о заказе. А вот при нажатии на "В избранное", наоборот, лучше не уходить со страницы, а просто отправить форму через AJAX и вывести сообщение об успехе или ошибке. Для этого реализованы сценарии — для любой кнопки можно указать data-via атрибут, который укажет как отправлять форму при нажатии на неё.


Настройки


Если вам что-то не нравится, или возникают какие-либо конфликты, в библиотеке можно многое поменять через настройки. Например, нужно ли блокировать повторную отправку всех форм по-умолчанию. Все названия атрибутов также можно поменять.


Заключение


В итоге, подключив библиотеку размером 10 кб, вы получаете самое главное — нужно меньше писать код для разных мелких форм (а то и вовсе не писать), а в довесок получаете несколько приятных возможностей, такие как дополнительные события форм, iframe-транспорт, AJAX-отправка файлов и др.

Перейти на страницу проекта в Github»

Tags:
Hubs:
+18
Comments 24
Comments Comments 24

Articles