Валидация полей формы при отпускании клавиши. Развитие валидации форм

Добрый день, уважаемый читатель. В этой статье я бы хотел обратиться к теме проверки содержимого форм на стороне клиента. На заре становления языков, работающих на клиенте, эта задача была основной. Со временем эти языки обросли новыми возможностями (манипуляция DOM, управление стилями и пр.), но задача проверки форм не исчезла. Правда с появлением HTML5 стало возможным указывать такой тип поля формы, как email, и браузер сам возьмет на себя его проверку. Такая возможность на данный момент реализована в Opera, так что расчитывать на нее пока особо не приходится. Поэтому я бы и хотел рассмотреть этот вопрос основательно. В большинстве случаев валидация проводится так: каждому полю раздаётся id, и затем при submit"е вытаскиваем их, попутно проверяя содержимое. И всем хорош данный подход, кроме отсутствия в нем системности. Поэтому хочу предложить вашему вниманию свое решение данной проблемы.Итак понеслася! В качестве примера приведена несложная форма, содержащая поля для имени, почтового ящика и пола.
HTML-код файла:
input { border: 1px solid #D4E2F7; } input { margin: 3px 0px 3px 15px; } ....

male
female

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

Function createField() { var members = new Array("required", "regexp"); for(var i = 0; i < arguments.length; i++) { this] = arguments[i]; } } // absolute regexp createField.prototype.regexp = /^{1,}$/ig; createField.prototype.valid = false; createField.prototype.required = true; createField.prototype.nullify = function() { this.valid = false; };

Далее в прототипе укажем значения по умолчанию полей.
regexp - регулярка, которой должно удовлетворять значение соответствующего поля.
valid - результат проверки значения поля регулярным выражением regexp .
required - индикатор того: требуется ли данное поле (можно ли оставить поле незаполненным).
nullify() - метод, возвращающий поле valid в исходное состояние.

Var single = new Array(); single["name"] = new createField(); single["email"] = new createField(true, /^+@+\.{2,4}$/); single["sex"] = new createField(true, /male$/ig);
Создаем как бы праобраз нашей формы. В ней будет 3 поля с именами name, email и sex, каждое из которых не может остаться незаполненным. Притом значения 2х последних полей должны удовлетворять указанным во втором параметре регулярном выражении.
var Singleton = { fields: single, regForm: false, nullify_values: function() { for(i in this.fields) { this.fields[i].nullify(); } }, ... };
В данном участке кода мы объявляем объект Singleton. Назначение поля fields понятно. Поле regForm - объект, содержащий форму. Через него мы и будем получать доступ к полям формы и их значениям.
Метод nullify_values() возвращает значение поля valid у «подобъектов» (т.к. fields это массив объектов) в исходное состояние.

И напоследок самое интересное. Метод submit() , который и заключает в себе основной функционал.
submit: function() { if(this.regForm) { // set property valid to false for every form field this.nullify_values(); var i = null; // walks through the form fields, pick and if required check their values for(i = 0; i < this.regForm.elements.length; i++) { // current field var oField = this.regForm.elements[i]; switch (oField.type) { case "button": case "submit": case "reset": break; case "checkbox": case "radio": if(!oField.checked) { break; } default: // javascript trim function analogue oField.value = oField.value.replace(/^\s*/, "").replace(/\s*$/, ""); if(!oField.value) { oField.value = ""; } // if this field is out of interest if(!this.fields.required) { this.fields.valid = true; this.regForm[i].style.border=""; } // if this field is required else { var match = this.fields.regexp.test(oField.value); // ... and fits regular expression if(match) { this.fields.valid = true; this.regForm[i].style.border=""; } this.fields.regexp.test(oField.value); } } } // now all we need is to check if the whole form is valid // we perform it by comparing number of form fields and number of valid fields // they should be equal var validForm = 0; var fieldsLength = 0; for(i in this.fields) { fieldsLength++; if(this.fields[i].valid) { validForm++; } else { this.regForm[i].style.border="1px solid #FF0000"; break; } } if(validForm == fieldsLength) { this.regForm.submit(); } else { this.nullify_values(); return false; } } }
Сначала обнуляем значения valid. Затем проходимся по полям формы. Если поле не несет особой смысловой нагрузки (типа reset) или не является помеченным галочкой - пропускаем его. Удаляем ведущие и замыкающие пробелы. И если поле является необходимым - проверяем его содержимое с помощью регулярного выражения. Если нет - идем дальше. Теперь осталось посчитать общее количество полей и количество валидных полей. И если они совпадают, то форму можно отправлять.
single = null; window.onload = function() { var regForm = document.forms; Singleton.regForm = regForm; Singleton.regForm.onsubmit = function() { return Singleton.submit(); }; };
И в самом конце мы «занулляем» объект single , чтобы невзначай не изменить значений Singleton.fields , выхватываем форму и даем ей обработчик события submit .

Остренькое1 . Если мы зануляем single , то не уничтожим ли мы попутно и Singleton.fields ? Нет. И вот почему. Присваивая переменной fields объект мы не передаем сам объект, а лишь ссылку на него. Физически объект хранится в так называемой Memory Heap . И не будет удален оттуда garbage collector"ом до тех пор, пока есть хотя бы одна ссылка на него. Таким образом мы лишь удалили ссылку на массив, и объекты не были уничтожены, т.к. существует еще одна ссылка на них, а именно Singleton.fields .

2 . В случае большого количества полей, не требующих валидации, не получится ли так, что создается много объектов, свойства которых по большому счету не нужны? Нет. И вот почему. Когда мы достаем поле объекта интерпретатор JS сначала смотрит в самом объекте и если не находит - в прототипе. Таким образом значения по умолчанию хранятся в прототипе в единственном экземпляре, что не есть накладно.

3 . Почему когда содержимое поля удовлетворяет регулярному выражению я делаю проверку еще раз? На это вразумительного ответа у меня нет. Опытным путем я заметил, что когда применяется функция RegExp.test() , то сначала она возвращает результат ожидаемый, а потом прямо противоположный. Попробуйте закомментировать эту строку и сами увидите, как поведение станет непредсказуемым. В обычном случае такого не наблюдается.

Цимес Данный скрипт обладает большой гибкостью в том смысле, что при переносе придется лишь изменить имена полей (ключи массива single ) и регулярные выражения для их проверки.

Посмотреть работу скрипта можно

Последнее обновление: 08.04.2016

Итак, в нашем распоряжении имеются различные элементы, которые мы можем использовать на форме. Мы можем вводить в них различные значения. Однако нередко пользователи вводят не совсем корректные значения: например, ожидается ввод чисел, а пользователь вводит буквы и т.д. И для предупреждения и проверки некорректного ввода в HTML5 существует механизм валидации.

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

Для создания валидации у элементов форм HTML5 используется ряд атрибутов:

    required : требует обязательного ввода значения. Для элементов textarea, select, input (с типом text, password, checkbox, radio, file, datetime-local, date, month, time, week, number, email, url, search, tel)

    min и max : минимально и максимально допустимые значения. Для элемента input с типом datetime-local, date, month, time, week, number, range

    pattern : задает шаблон, которому должны соответствовать вводимые данные. Для элемента input с типом text, password, email, url, search, tel

Атрибут required

Атрибут required требует обязательного наличия значения:

Валидация в HTML5

Логин:

Пароль:

Если мы не введем в эти поля никаких данных, оставив их пустыми, и нажмем на кнопку отправки, то браузер высветит нам сообщения об ошибке, а данные не будут отправлены на сервер:

В зависимости от браузера визуализация сообщения может несколько отличаться. Также границы некорректного поля ввода могут окрашиваться в красный цвет. Например, поведение при отправке пустых сообщений в Firefox:

Атрибуты max и min

Для ограничения диапазона вводимых значений применяются атрибуты max и min:

Валидация в HTML5

Возраст:

Атрибут pattern

Атрибут pattern задает шаблон, которому должны соответствовать данные. Для определения шаблона используется язык так называемых . Рассмотрим самые простейшие примеры:

Валидация в HTML5

Телефон:

Здесь для ввода номера телефона используется регулярное выражение \+\d-\d{3}-\d{3}-\d{4} . Оно означает, что первым элементом в номере должен идти знак плюс +. Выражение \d представляет любую цифру от 0 до 9. Выражение \d{3} означает три подряд идущих цифры, а \d{4} - четыре цифры подряд. То есть это выражение будет соответствовать номеру телефона в формате "+1-234-567-8901".

Если мы введем данные, которые не соответствуют этому шаблону, и нажмем на отправку, то браузер отобразит ошибку:

Отключение валидации

Не всегда валидация является желаемой, иногда требуется ее отключить. И в этом случае мы можем использовать либо у элемента формы атрибут novalidate , либо у кнопки отправки атрибут formnovalidate :

Валидация в HTML5

Телефон:

Валидация форм

Поля в форме предназначены для сбора информации от посетителей страницы. Но несмотря на все усилия и объяснения, получение правильной информации может оказаться трудным делом. Нетерпеливые или невнимательные посетители могут пропускать важные поля, заполнять поле или несколько полей не полностью, да и попросту нажимать неправильные клавиши. Заполнив таким образом форму, они нажимают кнопку "Отправить", и серверная программа получает набор данных, с которыми она не знает что делать (если не реализована валидация данных на серверной стороне).

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

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

Создатели HTML5 смогли увидеть эту надобность и изобрели способ привлечь браузеры на помощь, переложив задачу проверки с плеч веб-разработчиков на веб-обозреватели. Создатели HTML5 разработали систему проверки на стороне клиента, которая позволяет вставлять основные правила валидации в любое поле . Лучшее в этой системе - это ее простота и легкость: все, что нужно сделать - так это вставить правильный атрибут.

Как работает проверка HTML5?

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

Например, допустим, что определенное поле нельзя оставлять пустым, и посетитель должен ввести в него хоть что-то. В HTML5 это осуществляется с помощью атрибута required в соответствующем поле (далее дорабатываем пример из предыдущей статьи):

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

Проверка выполняется, когда пользователь нажмет кнопку для отправки формы. Если браузер поддерживает формы HTML5, он заметит пустое обязательное для заполнения поле, перехватит вызов отправки формы и отобразит всплывающее сообщение об ошибке:

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

Возникает еще один вопрос: что будет, если нарушено несколько правил проверки, например, не заполнено несколько обязательных полей?

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

Отключение проверки

В некоторых случаях может потребоваться отключить проверку. Например, вы хотите протестировать свой серверный код на правильность обработки поступивших некорректных данных. Чтобы отключить проверку для всей формы, в элемент добавляется атрибут novalidate :

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

Обнаружение незаполненных полей - это только один из нескольких типов проверки. Позже мы рассмотрим обнаружение ошибок в данных разных типов.

Оформление результатов проверки

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

Все, что для этого требуется - это добавить несколько простых CSS3-псевдоклассов. Доступны следующие опции:

required и optional

Применяют форматирование к полю в зависимости от того, использует ли это поле атрибут required или нет;

valid и invalid

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

in-range и out-of-range

Форматирование к полям, для которых используется атрибут min или max, чтобы ограничить их значение определенным диапазоном значений.

Например:

Input:required:invalid { border:1px solid red; }

Проверка с помощью регулярных выражений

Самым мощным (и самым сложным) поддерживаемым HTML5 типом проверки является проверка на основе регулярных выражений. Поскольку JavaScript уже поддерживает регулярные выражения, добавление этой возможности к формам HTML будет вполне логичным шагом.

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

{3}-{3}

Квадратные скобки в начале строки определяют диапазон допустимых символов. Иными словами, группа разрешает любые прописные буквы от А до Z. Следующая за ней часть в фигурных скобках указывает множитель, т.е. {3} означает, что нужны три прописные буквы. Следующее тире не имеет никакого специального значения и означает самое себя, т.е. указывает, что после трех прописных букв должно быть тире. Наконец, обозначает цифры в диапазоне от 0 до 9, а {3} требует три таких цифры.

Регулярные выражения полезны для поиска в тексте строк, отвечающих условиям, заданных в выражении, и проверки, что определенная строка отвечает заданному регулярным выражением шаблону. В формах HTML5 регулярные выражения применяются для валидации.

Для обозначения начала и конца значения в поле символы ^ и $, соответственно, не требуются. HTML5 автоматически предполагает наличие этих двух символов. Это означает, что значение в поле должно полностью совпасть с регулярным выражением, чтобы его можно было считать корректным.

Таким образом следующие значения будут допустимыми для этого регулярного выражения:

QDR-001 WES-205 LOG-104

А вот эти нет:

qdr-001 TTT-0259 5SD-000

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

Чтобы применить полученное тем или иным путем регулярное выражение для проверки значения поля или , его следует добавить в этот элемент в качестве значения атрибута pattern :

Регулярные выражения кажутся идеальным средством для проверки правильности адресов электронной почты. Впрочем, не кажутся, а так оно и есть. Но подождите немного с использованием их таким образом, т.к. в HTML5 уже имеется выделенный тип для адресов электронной почты со встроенным в него регулярным выражением (будет рассмотрен в следующей статье).

Специализированная JavaScript-проверка

Спецификация HTML5 также оговаривает набор свойств JavaScript, с помощью которых можно определить корректность значений полей (или заставить браузер выполнить проверку).

Наиболее полезным из них является метод setCustomValidity() , с использованием которого можно написать специальный сценарий для проверки конкретных полей, который будет работать с системой валидации HTML5.

Осуществляется это следующим образом. Прежде всего, значение соответствующего поля проверяется на правильность. Это делается с помощью обычного события oninput:

В данном примере событие oninput активизирует функцию validateComments(). Ответственность за написание этой функции, проверку текущего значения поля и вызова метода setCustomValidity() лежит на разработчике.

Если с текущим значением поля имеются проблемы, при вызове метода setCustomValidity() ему необходимо передать сообщение об ошибке. Если же текущее значение допустимо, этот метод вызывается с пустой строкой, таким образом очищая специальные сообщения об ошибке, которые могли использоваться ранее.

Function validateComments(input) { if (input.value.length

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

Поддержка проверки браузерами

Разработчики браузеров добавляли поддержку проверки в свои продукты по частям, вследствие чего некоторые версии браузеров поддерживают одни возможности валидации, но не обращают внимания на другие. В таблице ниже указаны минимальные версии браузеров, полностью поддерживающих валидацию HTML5:

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

С другой стороны, ваш веб-сайт может содержать сложные формы, в которых можно сделать массу ошибок при вводе данных, и вы не хотите потерять тех IE-пользователей, которые после первой неудачной попытки заполнить вашу форму не предпримут другую. В таком случае у вас есть два пути: разработать и использовать свою систему проверки или же использовать библиотеку JavaScript, чтобы компенсировать умственную отсталость IE. Какой из этих двух подходов выбрать, зависит от объема и сложности проверки.

Библиотека webforms2 реализует все рассмотренные на данный момент атрибуты. Для использования библиотеки загрузите все ее файлы в папку своего веб-сайта (а лучше в подкаталог папки веб-сайта) и добавьте в веб-странице ссылку на эту библиотеку.

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

Наряду со всеми новыми атрибутами, типами input и CSS3 псевдо-классами, глава о HTML5 формах, так же определяет простой JavaScript API, что позволяет расширять возможности валидации форм несколькими полезными встроенными методами, атрибутами и событиями. Давайте взглянем на обновленное демо , которое подключает API для проверки ограничений валидации.

Каждое поле формы имеет новый атрибут validity . Атрибут validity возвращает объект ValidityState , который предоставляет текущее состояние валидности. Объект ValidityState содержит несколько булевых переменных, которые определяют какое состояние у определенного элемента. В основном их ответы это true/false которые дают возможность разработчику понять что не так с полем:

  • valueMissing
    Этот атрибут возвращает true, если обязательное поле пустое.
  • typeMismatch
    Распространяется на новые типы input. Например, если значение email не корректно, этот атрибут возвратит true.
  • patternMismatch
    Если элемент содержит атрибут pattern и его значение не соответствует условиям регулярного выражения, атрибут вернет true.
  • tooLong
    Если значение какого либо элемента превышает его maxlength, этот атрибут вернет true.
  • rangeUnderflow и rangeOverflow
    Если значение элемента выходит за пределы атрибутов min или max, то этот атрибут вернет true.
  • stepMismatch
    Когда элемент с атрибутом step не соответствует требуемому значению, этот атрибут вернет true.
  • valid
    Если любое из вышеперечисленных значений возвращает true, то этот атрибут вернет false. В противном случае, если все условия выполнятся, то вернет true.
Это еще не все Событие invalid несет еще одну полезную функцию. Он будет вызываться полем, пока его значение будет оставаться невалидным. Так что, с его помощью, мы можем изменять стили полей в соответствии с их текущим состоянием.

Кроме того, метод checkValidity() может быть выполнен на любом отдельном поле или формы в целом, вернув true или false.

Применим к демо Давайте возьмем наше предыдущее демо и улучшим его при помощи API проверки ограничений валидации. Принимая то, что мы узнали от Luke Wroblewski в статье Inline Validation in Web Forms и наши собственные данные, мы можем применить эти идеи в нашей демо форме, чтобы создать оптимальный валидатор.

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

Если данные отвечают требованиям, даже в то время когда поле в фокусе, мы позволим пользователю узнать, что поле валидно. Мы делаем это путем добавления для input события для проверки валидности поля. Если все верно, то мы обновляем стили и показываем результат сразу.

Если поле имеет некорректное значение, а пользователь переходит к следующему полю, событие blur проверит валидность поля, а потом применит invalid стили. Для того, чтобы пользователь мог знать об ошибке. Это сохранит отображение стилей ошибок, до их исправления.

Что насчет старых браузеров? Во всех топиках обсуждаются новинки и поддержка современных браузеров, все это хорошо, но двайте не будем забывать о реальном мире, где мы должны поддерживать и устаревшие браузеры. Для этого я написал скрипт помогающий это делать.

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

Поддержка браузерами

Скрипт протестирован и работает в следующих браузерах:

  • Firefox 1+ - FF4 будет иметь встроенную поддержку;
  • Chrome 4+ - Встроенная поддержка;
  • Safari 3.2+ - Safari 5 имеет встроенную поддержку;
  • Opera 9.6+ - Встроенная поддержка.
Функции эмулируемые скриптом:
  • Каждое поле имеет объект validity , который дает возможность узнать текущее состояние;
  • Доступен метод checkValidity() указывающий что форма или какой то отдельный элемент не валиден;
  • Поддержка атрибутов placeholder , required , min , max и step ;
  • Поддержка атрибутов placeholder и required для textarea ;
  • Поддержка атрибура required для элемента select ;
  • Типы email и url для input будут проверяться с помощью встроенного регулярного выражения.
Изобилие проверок Поддержка браузерами HTML5 форм и моделя CSS3 UI начинает улучшаться. Opera9 продолжит поддержку Web Forms 2.0 пока они не будут объединены с HTML5 формами. В Chrome появилась поддержка с версии 4, Safari получил ее недавно с выходом версии 5, Firefox должен добавить поддержку в предстоящей бета-версии 4 и IE9, если они продолжат свое развитие в таком темпе, тоже должен получить поддержку. Добавить метки

Есть вопросы?

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: