- PVSM.RU - https://www.pvsm.ru -

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

Привет!

Как-то, год назад [1] я писал о своей небольшой библиотеке, которая облегчает разработку форм на сайтах. Недавно я выпустил 3-ю версию, которая, по-сути, была переписана с нуля, чтобы стать правильней и удобней. Но в своей статье я не буду повторять README [2] и ДЕМО [3], а лучше покажу на практике, каким образом она помогает писать меньше кода.

Но прежде, хотелось бы дать немного информации о новой версии. В ней, я избавился от зависимости malsup jquery.form [4] для отправки файлов, и один большой репозитарий я разделил на несколько мелких самостоятельных репозитариев, сохранив, при этом, общую сборку "всё-в-одном":

  • поддержка дополнительных событий форм (form-extra-events [5]);
  • полифил HTML5 form-атрибутов (form-association-polyfill [6]);
  • поддержка отправки файлов через iframe для старых браузеров (jquery-iframe-ajax [7]);
  • и, собственно, сама библиотека (paulzi-form [8]).

Дополнительные события форм

Во второй версии библиотеки я столкнулся с проблемой необходимости соблюдения определённого порядка подключения скриптов. Например, раньше нельзя было подключать данный скрипт перед стандартным скриптом валидации Yii2, дело в том, что на событие submit навешиваются все скрипты, которые так или иначе должны обработать отправку, в частности произвести валидацию, и нет никакой гарантии что кто-то это событие не прервёт вызовом preventDefault(). Поэтому, в случае неверного порядка подключения, сначала происходила блокировка формы, а затем валидация, и, если были ошибки валидации, повторно отправить форму было уже нельзя. form-extra-events решает эту проблему, он предоставляет несколько новых типов событий формы, одно из которых гарантирует то, что форма отправляется, и этот процесс уже нельзя прервать. Кроме того, генерируются события начала и завершения отправки формы, что используется во всех остальных возможностях библиотеки.

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

Библиотека, облегчающая разработку форм на сайтах (v3) - 1Для демонстрации полезности библиотеки, я набросал прототип типичного интернет-магазина на Bootstrap:
http://paulzi.ru/paulzi-form-site/ [9]

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

Html5 form-атрибуты

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

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

Библиотека, облегчающая разработку форм на сайтах (v3) - 3Теперь, обратим внимание на фильтр в каталоге [9]. Если отметить галочкой «Intel Core i5» и отправить данную форму, то даже если другие поля не заполнены, мы всё равно получим длинную простыню из параметров после перехода:

?proce_from=&proce_to=&tdp_from=&tdp_from=&line[]=i5

Используя библиотеку, если добавить к форме атрибут data-submit-empty="false" незаполненные поля не будут отправляться, и в результате получится более человекопонятный URL:

?line[]=i5

Блокировка повторной отправки

Библиотека, облегчающая разработку форм на сайтах (v3) - 4Рассмотрим форму заказа обратного звонка. Если вы сделаете двойной щелчок по кнопке отправки формы, форма у вас отправится дважды, и вам придёт два письма. Это неправильно, поэтому скрипт по-умолчанию блокирует возможность повторной отправки формы, до тех пор, пока запрос не выполнится. Пример корректной работы можно увидеть в форме «Написать нам». Регулируется это поведение путём установки атрибута data-lock="false"

Индикация состояния отправки

Библиотека, облегчающая разработку форм на сайтах (v3) - 5Иногда, процесс отправки формы может занимать длительное время (отправка файла, процессороёмкий обработчик, медленный интернет), и если никак не отобразить, что форма отправляется, пользователь рано или поздно подумает, что либо он не нажал кнопку, либо что-то зависло, и нажмёт кнопку повторно. Пример такой формы — форма «Написать нам». В библиотеке предусмотрено несколько вариантов, в прототипе я использовал атрибуты data-loading-text и data-loading-icon, которые изменяют текст кнопки и добавляют иконку. Также к форме и кнопке добавляются классы form-loading и btn-loading, это позволяет застилизовать состояние через CSS.

AJAX-отправка формы

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

Обработка AJAX-ответов

Библиотека, облегчающая разработку форм на сайтах (v3) - 6Посмотрим на пример посложнее — кнопка добавления в корзину на странице каталога [9]. При нажатии на неё надо не просто выполнить запрос и вывести сообщение — нужно обновить краткий список содержимого корзины при наведении и обновить счётчик количества товаров в ней. Этот момент тоже учтён, и я постарался сделать максимально гибкий обработчик 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 и зона поиска данным селектором — весь документ. Всё это позволяет провести описанные выше действия без единой строчки кода.

Сценарии

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

Настройки

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

Заключение

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

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

Автор: PaulZi

Источник [12]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/161000

Ссылки в тексте:

[1] Как-то, год назад: https://habrahabr.ru/post/261347/

[2] README: https://github.com/paulzi/paulzi-form/blob/master/README.ru.md

[3] ДЕМО: http://paulzi.ru/paulzi-form/

[4] malsup jquery.form: http://malsup.com/jquery/form/

[5] form-extra-events: http://github.com/paulzi/form-extra-events

[6] form-association-polyfill: http://github.com/paulzi/form-association-polyfill

[7] jquery-iframe-ajax: http://github.com/paulzi/jquery-iframe-ajax

[8] paulzi-form: https://github.com/paulzi/paulzi-form

[9] http://paulzi.ru/paulzi-form-site/: http://paulzi.ru/paulzi-form-site/

[10] корзине: http://paulzi.ru/paulzi-form-site/cart.html

[11] настройки: https://github.com/paulzi/paulzi-form#global-options

[12] Источник: https://habrahabr.ru/post/306278/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best