Валидация полей произвольных форм и контейнеров на jQuery
- Категория: Код
- – Автор: Игорь (Администратор)
Вам когда-нибудь приходилось искать скрипты и плагины для валидации произвольных форм и контейнеров? Когда тэг "form" не используемая конструкция? И когда необходимо проверять корректность полей в любое время, а не по зашитым концептуальным механизмам? Можно долго спорить о необходимости соблюдать стандартны и поддерживать отправку данных через полную перезагрузку страницы. Тем не менее, сегодня, большинство web-приложений уже не возможно представить без поддержки javascript-a. Отключите javascript - и сервисы станут бесполезными, несмотря на то, что вы сможете зарегистрироваться, войти и пройтись по нескольким страницам.
Примечание: Речь идет о том, что тег form предназначен для отправки данных методом POST и требует перезагрузки страницы или фрейма. Тем не менее, чем дальше, тем реже используется этот метод, и тем чаще те же самые данные отправляются ajax-ом, которому в общем все равно, какие теги использовались перед формированием данных.
Примечание: Конечно, существуют интернет-гиганты, которым в обязательном порядке необходимо поддерживать разные способы и режимы. Но, в их случае даже самый маленький процент подразумевает миллионы пользователей.
Рассмотрим существующие плагины для валидации форм на jQuery
Сноска: Название плагинов умышленно не приводится в статье, так как задачей является не критика конкретных приложений, а создание простого инструмента, который можно применить к произвольным формам.
Большинство существующих скриптов для валидации форм имеют несколько серьезных ограничений, которые далеко не всегда можно обойти простыми заглушкам или которые потребуют от вас длительной рутины.
- Жесткая привязка к тэгу "form". Поэтому если у вас есть несколько десятков форм, построенных на div-ах или таблицах, и вы твердо решили использовать популярные решения, то готовьтесь потратить кучу времени на ручное добавление тегов и корректировку скриптов и стилей.
- Привязка к именам полей. Некоторые валидаторы привязываются к названиям полей, а это значит написание простыней javasript-а для каждого случая. Если для пары форм это не страшно, то для коллекции это уже означает длительную ручную генерацию кода.
- Отсутствие валидации по требованию, без необходимости инициализации плагина. Вы не можете взять и один раз вручную проверить форму. Нужно правильно составить форму (правда, это везде нужно, но суть не в этом), затем инициализировать движок плагина, который в обязательном порядке привяжет кучу скриптов к элементам формы. И уже после этого вызвать метод isValid, который не всегда доступен в явном виде. Иногда, этот метод еще нужно "как-то" вытащить из внутренних механизмов.
Примечание: С одной стороны, вполне логично, что привязка идет к тегу форм, так как плагины появились "после". С другой стороны, сегодня скрипты позволяют быстро создавать и собирать данные из любых произвольных форм. При определенном уровне любопытства и настойчивости, вы можете легко создать форму только на тэгах "span"(div) и "input", при этом выглядеть она будет точно так же, как и все другие.
Разумеется, большинство плагинов имеют много приятных моментов. Но, по большому счету, они сводятся к:
- Наличию преднастроенных валидаторов. По сути, готовых регулярных выражений
- Проверкам различных типов. Включая проверку данных нескольких полей (например, подтверждение пароля и т.п.)
- Возможности создания собственных валидаторов
- Красивой анимации со всплывающими окошками и появляющимися подсказками
Если раньше красивая анимация и навороченный механизм сами по себе были достаточно вескими аргументами в пользу использования того или иного плагина, то сегодня это уже не совсем так. Найти готовые регулярные выражения для проверок большинства известных типов полей - задача не очень сложная. Большое число разнотипных проверок уже не столь актуально, как раньше. Стремление к минимализму форм ведет к уменьшению количества проверок. Попробуйте вспомнить, когда вы в последний раз встречали проверки, которые бы отличались от валидации текста, исключая повторение пароля? Необходимость в создании собственных валидаторов, при обилии уже готовых регулярных выражений, встречается все реже и реже. Красивая анимация и всплывающие подсказки в окошках когда-то будоражили фантазию и придавали приложениям очарование и неповторимость. Тем не менее, сегодня, достаточно пометить красным цветом хорошо известные всем поля, и большинство пользователей сами поймут, что именно необходимо исправить.
Примечание: Не стоит считать, что плагины не имеют смысла и что их не стоит использовать. Существует достаточно много ситуаций, когда написание кода с нуля обойдется намного дороже, чем использование готовых плагинов. В данной статье речь идет о тех ситуациях, когда ограничения плагинов либо создают препятствия, либо их плюсы не сильно превышают затраты по времени и силам.
Пишем скрипт для валидации произвольных форм на jQuery
Сноска: Вам совершенно не обязательно писать приложение с нуля, пример с готовым скриптом и стилями можно скачать по ссылке в конце статьи.
Прежде, чем реализовывать свой механизм, необходимо определиться с его возможностями и ограничениями:
- Форма хранится в одном произвольном контейнере. Это может быть span, div, table и так далее. Важно то, что форма это отдельный элемент DOM. Сохранение данных с 15 разных контейнеров - это уже не обычная форма, с любой точки зрения.
- Скрипт должен поддерживать как валидацию на лету, так и произвольную проверку любых форм или даже отдельных полей, без каких-либо привязок скриптов или других ограничений.
- Плагин должен быть простым как с точки зрения настройки и запуска, так и с точки зрения организации и кода.
- Необходимо, чтобы его можно было расширить в любое время. Добавить валидаторы. Встроить всплывающие сообщения. И многое другое.
- Настройка валидаторов полей должна быть не только универсальной, но и простой
И первым делом, переходим к самому важному, к определению основного механизма - вызова проверок для полей. Ведь, выбранный алгоритм будет напрямую влиять не только на сложность настройки, но и на количество букв, которое вам придется набирать, чтобы его корректно запустить. Исходя из составленных требований, самым простым механизмом будет вызов валидаторов по наличию классов стилей в атрибуте "class". Во-первых, стили легко задаются и не накладывают серьезных ограничений. Во-вторых, их можно добавлять и убирать в любой момент. В-третьих, если какие-то классы стилей вы уже используете в своем проекте, то их переименование, как в скрипте валидации, так и в полях, решается простой заменой одной строки на другую, без кардинального изменения кода.
Примечание: К сожалению, даже обилие javascript проверок и обработчиков событий не уберегут ни одно приложение от необходимости валидации данных на серверной стороне. Помните, что можно без особых усилий составить и вызвать отправку данных практически на любом браузере.
Составим тестовый проект
Теперь, составим тестовый проект со следующей структурой:
- css - каталог со стилями
- template.css - файл стилей
- images - каталог для картинок для стилей валидации
- icon-fail.png - иконка для некорректно заполненного поля
- icon-ok.png - иконка для правильно заполненного поля
- js - каталог для скриптов
- jquery-validate.js - скрипт валидации произвольных форм
- index.html - тестовая форма
Примечание: При составлении структуры тестового проекта, старайтесь максимально приблизить ее к структуре настоящего проекта. Это поможет вам отловить проблемы, связанные со структурой, еще на этапе разработке.
Файл стилей - template.css
Большую часть файла стилей занимают стили самой формы, что бы демонстрационный пример выглядел привлекательно. Для самого же плагина нужны только первые два правила ".field-input.input-ok" и ".field-input.input-error"
Примечание: Старайтесь добавлять даже к тестовым формам хотя бы минимальны дизайн. Чем ближе тестовый проект будет к реальному, тем больше шансов отловить ошибки и скрытые проблемы. Например, картинка в "background" для проверенных полей будет занимать часть поля. Это означает, что для полей с большим объемом текста необходимо предусматривать отступы в стилях.
Файл скрипта валидации произвольных форм на jQuery - jquery-valiate.js
Так как скрипт достаточно простой и в самих комментариях подробно описана вся необходимая информация, то файл приводится целиком:
Тестовая страница с формами - index.html
Тестовая страница достаточно проста. Ее основное пространство занимает html-код самих форм демонстрационного примера. Сам же вызов плагина для создания валидации на лету, а так же запуск ручной валидации по нажатию на кнопку, занимают всего несколько строк.
Теперь, сохраняем все файлы в проекте, открываем index.html в любом браузере и переходим к первичному тестированию результата.
Смотрим результат выполнения скрипта валидации на jQuery в тестовом проекте
После того как вы откроете файл, перед вами должна появится следующего вида страница:
Как видно, на экране будут отображаться две формы. Форма следа будет проверяться на валидацию в режиме реального времени, т.е. при каждом вводе в текстовые поля, а так же при нажатии на кнопку "отправить форму". Форма справа будет проверяться вручную, только при нажатии на кнопку "Отправить форму". В остальное время форма останется нетронутой.
Теперь, убедимся, что валидация происходит в те моменты, когда это необходимо, и что формы никак не влияют друг на друга. Выглядеть это будет примерно так:
Как видно, в форма слева проводилась валидация на лету. А в форме слева валидация происходила только по нажатию на кнопку "Отправить форму."
Закончив, первичное тестирование, необходимо снова пройтись по возможностям и ограничениям составленным в самом начале:
- Форма хранится в одном произвольном контейнере. - Выполнено. Форма не зависит от конкретного элемента. Обрабатывает произвольный контейнер
- Валидация как на лету, так и вручную. - Выполнено. Валидацию можно производить как на лету, так и вручную
- Плагин должен быть простым - Выполнено. Код очень простой. Настройка форм заняла не более 5 минут. Для запуска плагина понадобилось всего пара строчек
- Можно было расширить в любое время - Выполнено. Добавление валидаторов элементарное. Можно добавить как в опции по умолчанию, так и во время запуска плагина. Так как код простой, то добавить функциональность то же просто.
- Настройка валидаторов должна быть универсальной и простой - Выполнено. Валидаторы указываются через классы стилей.
Теперь, у вас есть легкий и простой плагин на jQuery, который можно применять для валидации произвольных форм как на лету, так и в ручном режиме. При этом, плагин легко расширяется как с точки зрения количества проверок, так и с точки зрения дополнительной функциональности.
Ссылка для скачивания плагина с тестовым проектом находится тут:
☕ Понравился обзор? Поделитесь с друзьями!
Комментарии / отзывы
Спасибо за великолепную статью.
Как можно прикрутить сообщение об ошибке которое показывается над или под полем ввода?
Я так понял, надо как-то прикрутить инфу из статьи "Как сделать всплывающие окна на jQuery (информеры)?", но там всё построено на кнопках, а как пименить это к валидации полей в реальном времени?
К сожалению в кодах я не силён... :-?
Во, хотя бы ка у Вас на сайте в этой форме!
Всплывающие окна на jQuery - это не то, что нужно. Вам нужно смотреть в сторону tooltip (всплывающие подсказки). И, к сожалению, если вы не очень сильны в кодах, то будет не так просто.
Тем не менее, tooltip можно добавить в функцию validItem.
Достаточно проверять результат validResult перед отправкой.
Например:
if (!validResult) {
// Здесь идет код, который добавляет tooltip c сообщением к полю
$(item).tooltip('Заполните поле')
}
Жаль нет возможности скиншот прицепить.
Эту форму в которой пишу сами написали? Есть статья как её сделать?
Или напишите как сделать скрипт внизу этого поля "осталось столько-то символов".
Второй момент. Эта форма для отправки основана на модуле jComments. Поэтому немного другое.
Валидация заработала. у меня на инпуте висит виртуальная клавиатура. Она у меня заглючила, потом "выздоровела", и после этого всё стало работать!
Спасибо.
Так, а в чем проблема? Пишется данная функция за 5 минут. Вот пример:
--------------------------------------------
// Проверка для повторяющихся полей,
// имя поля, которое должно повториться указывается в атрибуте "confirm-field"
if (cl === 'confirmfield') {
validResult
&= ($(options.container).find('[Name="' + $(item).attr('confirm-field') + '"]').val()
== $(item).val());
}
else if (cl.substring(0, cl.length > 'rangelen'.length ? 8 : cl.length) === 'rangelen') {
var params = cl.split('-');
if(params.length === 3) {
var minlen = parseInt(params[1]),
maxlen = parseInt(params[2]);
if (!isNaN(minlen) && !isNaN(maxlen) && minlen <= maxlen) {
validResult &= (($(item).val().length >= minlen) && ($(item).val().length <= maxlen));
}
}
}
// Иначе обычная проверка
else if (typeof (options.validators[cl]) === 'function') {
validResult &= options.validators[cl](item.val());
}
--------------------------------------------
Ну и используете для проверки классы вида "rangelen-3-12"
П.С. Кстати, в русском языке достаточно много хороших слов. Например, расширить, добавить, увеличить и так далее :)
Позволю себе вопрос по существу. Похоже, в результате работы скрипта валидации очищается массив $_POST, или я ошибаюсь? Дело в том, что я хотел после валидации формы сделать ее отправку с использованием ajax. Для этого взял где-то такую функцию:
function call() {
var msg = $('#formid').serialize();
$.ajax({
type: 'POST',
url: 'logger.php',
data: msg,
success: function(data) {
$('.results').html(data);
},
error: function(xhr, str){
alert('Error Code: ' + xhr.responseCode);
}
});
}
и сделал ее вызов сразу после этого алерта:
alert('Валидация первой формы прошла успешно!');
call();
По скрипту ответ ниже
П.С. По поводу русского языка, не будем развивать тему, для этого есть другие сайты.
$logline.=' | ';
foreach($_POST as $key => $value)
{
$logline .= $key.' - '.$_POST[$key].' ';
};
В тестовой ситуации (для сферического коня в вакууме и с отключенной валидацией) это работает, с включенной валидацией - пишет пустые значения.
Возможно, я не прав, или call() нужно делать из другого места - был бы признателен за рекомендации. Либо, если это не слишком обременительно для Вас, возможно, Вы могли бы дополнить Ваш пример отправкой формы после успешной валидации с использованием ajax. Но для меня было бы более чем достаточно рекомендации, откуда именно лучше вызывать call().
Спасибо.
--------------------------------------
function getArray(container) {
var sendArray = [];
$(container).find('input, textarea').each(function () {
sendArray.push({
name: $(this).attr('name'),
value: $(this).val()
});
});
return sendArray;
}
--------------------------------------
И тогда в коде call изменяйте строчку
--------------------------------------
var msg = $('#formid').serialize();
--------------------------------------
на
--------------------------------------
var msg = getArray('#formid');
--------------------------------------
Единственно, сейчас функция getArray рассчитана только на input и textarea (в их текстовом представлении). Для select, чекбоксов и радиобаттонов, функцию нужно доделать.
В целом, все прекрасно, но хотелось бы внести еще два улучшения.
1. После успешной отправки все данные в форме хорошо бы стереть, чтобы юзеру было спокойнее.
2. И после этого хорошо бы выдать сообщение об успешной отправке. Например, в пределах div с формой добавим div с текстом:
Текст до отправки формы
и после отправки формы он должен поменяться. Я пробую так:
document.getElementById(msg2user).innerHTML = "Форма успешно получена";
На вид вроде бы так и должно быть, но текст не обновляется. Очевидно, моих скромных познаний недостаточно, и/или этот оператор стоит не там, где нужно. У меня это здесь:
function call() {
var msg = getArray('#formx');
$.ajax({
type: 'POST',
url: 'logger_cz.php',
data: msg,
success: function(data) {
$('.results').html(data);
document.getElementById(msg2user).innerHTML = "Форма успешно получена";
},
error: function(xhr, str){
alert('Error Code: ' + xhr.responseCode);
}
});
}
В общем-то, без этих двух пунктов можно обойтись, но как-то это нехорошо. Если Вас не затруднит подсказать, как это решить, буду Вам весьма признателен.
Спасибо.
function call() {
var msg = getArray('#formx');
$.ajax({
type: 'POST',
url: 'logger.php',
data: msg,
success: function(data) {
document.getElementById('msg2user').innerHTML = "Данные получены";
$('.results').html(data);
},
error: function(xhr, str){
alert('Error Code: ' + xhr.responseCode);
}
});
$(':input','#formx')
.not(':button, :submit, :reset, :hidden')
.val('')
.removeAttr('checked')
.removeAttr('selected');
}
В общем, все отлично, большое спасибо. Если надумаете доделать функцию для select, чекбоксов и радиобаттонов - это будет вообще предел мечтаний. Спасибо еще раз, и успехов Вам.
Насчет функции для select, checkbox и radiobutton. Эта задача не совсем относится к скрипту. Поясню о чем речь. Обычно, валидация накладывается на уже существующие механизмы отправки данных, ну или в крайнем случае делается совместно со сбором данных.
Тем не менее, в зависимости от того, как сделаны формы сбор информации, очистка и прочее могут быть жутко специфичны.
Так, к примеру, если речь идет о стандартной отправке данных через post, то валидация и не должна ничего собирать, так как все данные идут в теге form.
Если же речь идет об ajax отправке данных, то тут есть, как минимум, несколько моментов. Во-первых, сами формы могут динамически формироваться (например, зависимые списки с подгрузкой или же просто полностью html-формы) и под них уникальный скрипт - это уже целая библиотека. Во-вторых, события в виде очистки - это локальная задача отдельного проекта. Кто-то будет чистить часть полей, кто-то все, а кто-то оставит как есть. В-третьих, сегодня существует немало готовых элементов управления (красивые кнопки и т.д.), которые обычно хранят данные в скрытых input-ах. Соответственно, их очистка ни к чему не приведет, а только лишь нарушит логику скриптов красивых кнопок, списков и прочего.
Поэтому, такие функции обычно пишутся под конкретные задачи, а скрипт валидации рассчитан для использования как "универсальную" и "легко добавляемую" функциональность.
Ну и в коментах убило "под них уникальный скрипт - это уже целая библиотека", а на фига тогда jquery тут? Для замещения только querySelectorAll и смены классов полей довольно глупо выглядит. имхо.
Достало засилье прямо скажем не без багов надстройки над багами...
jQuery используется в очень многих сайтах. И тому много причин. Удобство, куча плагинов и прочее.
Кроме того, какой смысл, если многие берут готовые скрипты, а потом просто допиливают. Например, можно тултипы добавить, сделать подсказки, добавить анимацию и много чего другого.
Если же вас не устраивает jQuery, то, как вы сами сказали, можете переписать и добавить свои методы - дело не такое уж сложное под конкретный сайт. Достаточно взять из скрипта его основу. Проблема больше в кроссбраузерности. Зачем писать велосипед, если есть готовое и популярное решение.
По поводу "Ну и в коментах убило "под них уникальный скрипт - это уже целая библиотека", а на фига тогда jquery тут". Тут все просто. Если заглянуть чуть глубже, то вылезет немало проблем и пожеланий. А это значит, что скрипт будет расти как грибы.
На странице множество форм и отправляются каждая форма одной кнопкой на которой прикручена одна функция:
Сама функция отправки формы:
function saveForm(){
var data=[]
data.push(formartForm($('*[data-type="config"][dat a-id="page"]').find('form').serializeArray()))
data.push(formartForm($('*[data-type="config"][dat a-id="jump"]').find('form').serializeArray()))
data.push(formartForm($('*[data-type="config"][dat a-id="button"]').find('form').serializeArray()))
$('*[data-type="html"]').each(function(){
data.push(formartForm($('*[data-type="config"][dat a-id='+$(this).attr('data-id')+']').find('form').s erializeArray()))
})
var msg = getArray({config_list:data});
$.ajax({
type: "POST",
url : EDITABLE_PAGE_URL+'/config_edit?if_h5=1&page_id={$ Request.param.editable_page_id}',
dataType : 'json',
data : {config_list:data},
success : function (data, status) {
layer.msg(data.message)
}
})
}
Как прикрутить к ajax функции saveForm() проверку валидации вашего кода?
Заранее, спасибо!
window.validation.isValid({ container: '[ТУТ СЕЛЕКТОР НУЖНОЙ ФОРМЫ]' })
И так для каждой формы. И если все формы прошли валидацию, то отправляете ajax запрос.
Это не блокирует отправку формы через ajax, а нужно блокировать отправку формы, если форма не прошла валидацию.
Нужно проверку валидации прикрутить к ajax. Как это сделать?
Если бы для каждой формы была бы своя кнопка отправки формы, то это бы не вызвало у меня затруднений написать проверку для каждой формы отдельно.
Но в данном случае форм много, а функция saveForm() одна для всех ворм на странице, которая отправляет только одну, активную форму, а не все формы разом.
var checkValid = true;
$('*[data-type="html"]').each(function(){
data.push(formartForm($('*[data-type="config"][dat a-id='+$(this).attr('data-id')+']').find('form').serializeArray()))
if ($('*[data-type="config"][dat a-id='+$(this).attr('data-id')+']').find('form').l ength > 0) {
checkValid &= window.validation.isValid({ container: '*[data-type="config"][dat a-id='+$(this).attr('data-id')+'] form' });
}
})
if (!checkValid) {
return;
}
Ну и разметьте форму маркерами CSS
Цитата: В файл .css добавил
Цитата: Но это не подходит. Нужно, чтобы JS создавал псевдоэлементы.
Поможете ответом?
if (!validResult)
$(item).addClass(options.errorClass).removeClass(options.okClass).prev("em").remove(),
$(item).before("");
// Поле прошло валидацию
else
$(item).addClass(options.okClass).removeClass(options.errorClass).prev("em").remove(),
$(item).before("");
Если на странице 7-10 форм, то валидация в режиме онлайн тормозит или совсем не делает проверку, типа виснет.
Функционирует только с кнопки.
А если 3-4 формы, то хорошо.
В общем не панацея эта валидация на классах .css.
7-10 форм. Ну зависит от объемов и того как применяется. В этом смысле код
for(var cnt = 0; cnt < 100000000; cnt++) {
for(var cnt2 = 0; cnt2 < 100000000; cnt2++) {
//something
}
}
легко подвесит любую страницу.
Кроме кнопки, еще существует параметр liveCheck для валидации каждого отдельного поля в онлайн режиме.
Ну и плагин писался для общих задач. Чаще всего это одна форма с десятком полей.
Поэтому вы не поняли зачем каждый раз удалять em.
.before("");
вот разные.
Но ваш редактор может снова удалить код и вы не увидите содержание .before("");