Pull to refresh

Плагин для «живых» форм

Reading time 4 min
Views 15K
Статья посвящена плагину, который упрощающает жизнь client-side программиста.

При заполнении формы случается так, что учитывая введенные данные, форму нужно менять (прятать и показывать поля). Простейший пример: при заказе доставки товара пользователь выбрал «самовывоз», значит поля про адрес доставки можно спрятать, зато было бы здорово показать карту проезда для самовывоза.

И что дальше

Часто такая логика остается без реализации, однако если вы заботитесь о своих пользователях, то делать это нужно.

Первый стандартный подход это сделать некий пошаговый мастер, где форма для каждого шага генерируется на стороне сервера. По-моему мнению это неудачный вариант, так как требует муторной работы по разбиению процесса на шаги, написанию тонны кода да удовольствия от работы с такой формой мало.

Второй подход это писать «портянки» javascript'а который всю эту логику реализует на стороне клиента. Особенно грустно писать «каскадную» логику типа «если ввели a в поле A, показать B, если ввели c в поле B, то показать D. Если в A ввели что-то другое, спрятать B, а потом D».

Оба варианта нельзя назвать удобными. Прежде всего потому что логика реализуется императивным стилем вместо уместного для таких случаев декларативного. Но выход есть!

Решение

В общем когда возникла потребность реализовывать еще одну такую форму, то было решено написать наконец плагин для jQuery который бы:
  • реагировал на заполнение полей формы
  • позволял описать стандартную логику типа показать, спрятать, добавить вариант в select в одну-две строки
  • сам бы заботился о каскадном выполнении действий и их откате
  • требовал бы для изучения пару минут


Получившийся плагин я назвал jQuery.grewform (типа растущая форма). Без разглагольствований – простейший пример. Опишем реализованную логику русским языком:
Если  #first имеет значение "show", то нужно показывать #p2. Если #second имеет значение "gogo", то нужно показывать #p3.

Теперь посмотрим как эта логика описана с использованием плагина:
$('form').grewform({

    //Если  #first имеет значение "show", то нужно показывать #p2
    '#first[value=show]':{
        show:'#p2'
    },

    //Если #second имеет значение "gogo", то нужно показывать #p3
    '#second[value=gogo]':{
        show:'#p3'
    }

})


Подробнее

Далее идёт подробное описание работы плагина. Если вам всё более-менее понятно из приведенного выше примерчика, можете пропустить этот раздел статьи и перейти к описанию возможностей.
Поведение плагина задается набором правил. Каждое правило состоит из терма и набора действий. После инициализации, а так при каждом изменении формы плагин проверяет терм каждого правила. При проверке определяется соответствие терма текущему состоянию формы. Каждое правило может оказаться в одном из трех положений:
  1. при прошлой проверке терм не соответствовал состоянию, а теперь соответствует
  2. при прошлой проверке терм соответствовал состоянию, а теперь не соответствует
  3. соответствие терма состоянию формы не изменилось

В первом случае правило помечается как сработавшее, элементы DOM описанные в терме (по сути изменение этих элементов привело к срабатыванию правила) получают метку (добавляется класс) показывающую что на них «висит» сработавшее правило такое-то. После чего запускаются по очереди все описанные в правиле действия. Второй случай более интересен. Аналогично, правило помечается как уже не сработавшее, пометки с элементов удаляются. После чего запускаются негативы действий описанных в правиле (показали что-то? Теперь спрячем!), причем если в процессе в DOM прячутся или удаляются какие-то элементы, то сначала проверяется
не «висит» ли на них каких-либо правил (см. случай №1), если это так то запускается процесс «отката» для этих правил (работает как случай №2). В третьем случае ничего не происходит.
Стоит отметить, что про проверке соответствия термов учитываются только видимые элементы формы.

Возможности

Выражение по которому определяется не пора ли запускать действия (терм) это CSS/jQuery-совместимый селектор. Если в форме находятся элементы соответствующие селектору, то запускаются действия этого правила. Иногда нужно чтобы правило сработало только при двойном (тройном, четверном...) условии, для этого можно использовать функцию AND (пример). Это единственное изменение синтаксиса, а точнее дополнение.
В первом примере используется селектор [value=show]. Особо хорошо знающие jQuery справедливо скажут, что такие селекторы не должны работать если value был изменен в процессе выполнения кода. Однако плагин поддерживает актуальное состояние атрибута value для всех <input/>, соответсвенно всё работает как надо.
Перейдём к описанию разновидностей действий. Вот их список с описанием синтаксиса:
{
    show:'elements_selector',   //показать элементы (slideDown; slideUp при откате)
    hide:'elements_selector',    //спрятать элементы (slideUp; slideDown при откате)
    disable:'elements_selector' //добавляет disabled="disabled" к атрибутам элемента (убирает при откате)
    enable:'elements_selector' //убирает атрибут элемента disabled  (добавляет disabled="disabled" при откате)
    check:'elements_selector'  //добавляет checked="checked" к атрибутам элемента (убирает при откате)
    uncheck:'elements_selector' //убирает атрибут элемента checked  (добавляет checked="checked" при откате)
    set_value:'elements_selector',  //задаёт value для <input>, для <select> добавляет selected="selected" у соответствующего <option>
    add_options:            //добавляет <option> в <select>
    {
        '<select> selector':{
                      'value_1':'display_value_1', //соответствует <option value="1">display_value_1</option>
                      'value_2':'display_value_2',
              ...
                }
        or
        '<select> selector': function   //должна возвращать объект (формат - {'value_1':'display_value_1',...})
    },
    custom:     //для особых случаев
    {
        match:function,       //будет вызвана при срабатывании правила
        unmatch:function,   //будет вызвана при откате
    }
}


Как было сказано выше описываются только позитивные события, т.е. только те что должны произойти при срабатывании правила. Действия отката вычисляются автоматически.
Как видно почти все действия имеют следующий синтаксис:
название_действия:'селектор элементов'
Синтаксис селектора так-же полностью CSS/jQuery-совместимый. Над элементами найденными по селетору будет произведено указанное действие. Собственно все действия описаны выше в коде.

Под конец самый большой и мощный пример – форма заказа психологической консультации =)

Need help

Я начал писать этот плагин 2 недели назад и мы уже используем его в 2 формах на продакшне. Буду очень благодарен, если вы попробуете этот плагин и расскажите чего вам не хватает.

Ссылки:


© картинка взята из книги Code Complete
Tags:
Hubs:
+110
Comments 67
Comments Comments 67

Articles