
Статья посвящена плагину, который упрощающает жизнь 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'
}
})
Подробнее
Далее идёт подробное описание работы плагина. Если вам всё более-менее понятно из приведенного выше примерчика, можете пропустить этот раздел статьи и перейти к описанию возможностей.
Поведение плагина задается набором правил. Каждое правило состоит из терма и набора действий. После инициализации, а так при каждом изменении формы плагин проверяет терм каждого правила. При проверке определяется соответствие терма текущему состоянию формы. Каждое правило может оказаться в одном из трех положений:
- при прошлой проверке терм не соответствовал состоянию, а теперь соответствует
- при прошлой проверке терм соответствовал состоянию, а теперь не соответствует
- соответствие терма состоянию формы не изменилось
В первом случае правило помечается как
сработавшее, элементы
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
комментарии (67)