Техники валидации форм. Используем нестандартные проверки валидности

24.03.2019

Очень часто при создании форм регистрации, требуется проверить валидность (правильность) введенного email. Это необходимо, чтобы пользователи не могли писать несуществующие email адреса. Разумеется полную проверку email необходимо производить на стороне сервера (после того, как форма была отправлена). Но ведь и перед отправкой формы, email лучше проверить на стороне клиента. Чтобы в случае неправильного ввода, пользователю было выведено специальное сообщение и он сразу же мог исправить свой email.

Именно о проверке email на стороне клиента и пойдет речь в данной статье. Реализовывать мы это будем на jQuery, поэтому чтобы вы все поняли, желательно знать базовые особенности работы с этим фрейворком.

Все исходники, которые применяются в данном уроке, вы можете скачать, кликнув по кнопке ниже.

Шаг 1 - Подготовка. Создаем форму на HTML

Создаем простую страничку на HTML. Обращаю ваше внимание, что к ней обязательно должна быть подключена библиотека jQuery.

Также между тегами head , мы открыли конструкцию script , где собственно и будем писать сам код.





Валидация email на jQuery


// Здесь будем писать код



Проверка email








Шаг 2 - Задаем на событие blur проверку поля

Если пользователь кликнет по полю ввода email, то данное поле получает фокус. После того, как пользователь введет email и уберет курсор мыши из поля, фокус теряется и наступает событие blur . Именно на данное событие мы и повесили обработчик.

$(document).ready(function() { $("#email").blur(function() { // Здесь будем писать код обработки события }); });

Шаг 3 - Проверяем, не является ли поле пустым

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

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

$(document).ready(function() { $("#email").blur(function() { if($(this).val() != "") { // Поле email заполнено (здесь будем писать код валидации) } else { // Поле email пустое, выводим предупреждающее сообщение $(this).css({"border" : "1px solid #ff0000"}); $("#valid").text("Поле email не должно быть пустым"); } }); });

Шаг 4 - Делаем полную проверку введенного email

Если поле было заполнено, мы проверяем, соответствует ли строка введенная пользователем, формату email адреса. Если это так, то поле ввода обводиться зеленой рамкой, если нет, то - красной.

$(document).ready(function() { $("#email").blur(function() { if($(this).val() != "") { var pattern = /^()+@+\.({2,4}\.)?{2,4}$/i; if(pattern.test($(this).val())){ $(this).css({"border" : "1px solid #569b44"}); $("#valid").text("Верно"); } else { $(this).css({"border" : "1px solid #ff0000"}); $("#valid").text("Не верно"); } } else { $(this).css({"border" : "1px solid #ff0000"}); $("#valid").text("Поле email не должно быть пустым"); } }); });

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

Предоставляя пользователю возможность заполнения полей на сайте, следует проверять введенные данные на валидность. Это позволит предупредить пользователя о случайных ошибках, а так же даст дополнительную защиту от спама. Ярким примером является форма обратной связи, обязательными полями которой часто бывают email и телефон. Займемся их проверкой на правильность заполнения с помощью javascript.

Информация лучше воспринимается на примерах, поэтому посмотрим готовую форму в действии:

Пожалуйста, заполните все поля формы!

Для начала разберем применяемые регулярные выражения, а полный код формы и javascript функций я приведу в конце статьи.

Валидность адреса электронной почты

Рассмотрим адрес электронной почты ([email protected]). Вот его обязательные части:

  • Название (test) - один или много символов;
  • Знак собаки (@);
  • Доменное имя почтового сервера (mail) - один или много символов;
  • Точка (.);
  • Доменное имя первого уровня (ru) от двух до пяти букв.

Составим регулярное выражение для наших требований:

/^[\w-\.]+@[\w-]+\.{2,4}$/i

Разберём правило по частям:

  • Регулярное выражение должно открываться и закрываться символами «/» . После закрывающегося символа можно указать директиву. В нашем случае такой директивной является «i» , которая отключает проверку вводимых букв на регистр. То есть, становится не важно, ввели «[email protected]» или «[email protected]».
  • Знаки «^» и «$» обозначают начало и конец проверяемой строки. Если их убрать, то правило вернет положительный результат даже если в начале или конце электронного адреса поставить запрещенные знаки. То есть, при вводе «%:[email protected]#6&» функция проверки вернет положительный результат, так как в строке имеется последовательность символов, удовлетворяющая нашему правилу. Для исключения такой возможности указываем, что правило должно применяться ко всей строке, а не к её части.
  • Блок «[\w-\.]+» отвечает за проверку названия ящика. В квадратных скобках указываем разрешенные символы: «\w» - все латинские буквы, цифры и знак подчеркивания. Так же рекомендую добавлять знак тире и точку «-\.» . «+» после квадратных скобок указывает на возможность повторения символов - один или много раз.
  • Далее идет знак собаки и доменное имя почтового сервера - «@[\w-]+» . Здесь практически тоже самое что и в предыдущем блоке. Исключаем только из набора символов точку.
  • Осталось прописать правило для проверки наличия точки и корректности доменного имени верхнего уровня (ru,com,info). «\.{2,4}» . Для обозначения знака точки мы указываем её с обратным слешем «\.» Без него она будет восприниматься зарезервированным символом регулярки, который обозначает возможность наличия на её месте любого символа. За точкой должно следовать доменное имя верхнего уровня. Это минимум 2 латинские буквы - «{2,4}» .
  • Добрый день, уважаемый читатель. В этой статье я бы хотел обратиться к теме проверки содержимого форм на стороне клиента. На заре становления языков, работающих на клиенте, эта задача была основной. Со временем эти языки обросли новыми возможностями (манипуляция 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 ) и регулярные выражения для их проверки.

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

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

    Ни для кого не секрет, что любые формы на сайте нужно проверять. Нужно проверять как на стороне сервера (must have), так и на стороне клиента. Форм много, и добавлять проверки для каждого поля ввода достаточно противное занятие. Давайте попробуем обобщить данную задачу.
    Если пораскинуть мозгами, то валидация форм как правило сводится к нескольким задачам:
    1) Проверка обязательных полей.
    2) Блокировка нежелательных ввода символов
    3) Проверка введенного значения с желаемым результатом.

    А что лучше всего подходит для проверки строк? Правильно — регулярные выражения, именно их мы и будет активно применять для решения поставленных задач!

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

    Для этого добавим следующий код.

    $("").each(function() { $(this).prop("required", false).attr("data-required", "true"); }).click(function() { $(this).removeClass("error").parent().find(".error-message").text(""); });

    Примечание: Код предполагает наличие библиотеки Jquery, а так же что все инпуты имеют некий родительский контейнер (как правило так оно и бывает в реальных проектах). Пример:

    Приведенный выше код автоматически удалит атрибут required у тегов и создаст вместо него атрибут data-required=»true».

    Для решения второй задачи создадим следующий обработчик:

    $("").keypress(function(e) { if(e.key || .indexOf(e.keyCode) == -1) { if(!new RegExp($(this).data("regexp-input"), "g").test(e.key)) { e.preventDefault(); return false; } } }); $("").keypress(function(e) { if(new RegExp($(this).data("regexp-block"), "g").test(e.key)) { e.preventDefault(); return false; } });

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

    Если же мы хотим разрешить вводить все кроме символов (,), !, ?, то логичней будет воспользоваться обработчиком блокирования символов:

    Для решения третей задачи, нам понадобится вспомогательная функция.

    Function checkRegexp(o, e) { var $this = $(o); $this.removeClass("error"); $this.parent().find("span.error-message").text(""); if($this.data("regexp") && $this.data("regexp") != "") { if($this.parent().find("span.error-message").length == 0) { $this.parent().append(""); } if($this.val() == "" && $this.data("required")) { $this.addClass("error"); $this.parent().find("span.error-message").text("Обязательно к заполнению"); } else { if(!new RegExp("^" + $this.data("regexp") + "$", "g").test($this.val())) { $this.addClass("error"); $this.parent().find("span.error-message").text("Заполненно некорректно"); } } } $this.closest("form").find("").prop("disabled", $this.closest("form").find("input.error").length != 0); }

    Данный код проверяет переданный объект «o» (это будет инпут) и в случае каких либо ошибок создает дополнительный блок span с сообщением об ошибке. Так же данная функция обрабатывает созданный в пункте 1 атрибут data-required.

    Теперь необходимо повесить данную функцию на наши элементы

    $("input").click(function() { $(this).removeClass("error"); }).keyup(function(e) { checkRegexp(this, e); }).blur(function(e) { checkRegexp(this, e); });

    Теперь для проверки валидность поля на желаемый шаблон достаточно добавить тегу атрибут data-regexp, например проверка поля на формат даты в виде ГГГГ-ММ-ДД:

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

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

    Используем CSS

    В CSS существует четыре специальных псевдокласса, применимых к полям формы: :valid (валидное поле ), :invalid (невалидное ), :required (обязательное ) и:optional (необязательное ). Их можно использовать, чтобы добавлять некоторые - хотя и весьма ограниченные - подсказки пользователям, заполняющим форму.

    Используя:valid и:invalid , мы можем показать пользователю, правильно ли заполнено поле по мере ввода.

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

    Стилизация состояний:required и:optional сама по себе не особо полезна, поскольку эта информация обычно указывается в подписях к полям формы. Однако мы можем объединить эти состояния с псевдоклассами:valid / :invalid и стилизовать их комбинации. Например, мы хотим показывать лишь положительный результат, когда валидно обязательное к заполнению поле.


    Используем JavaScript

    JavaScript даёт намного больше возможностей для улучшения работы пользователей с формами. Давайте рассмотрим в качестве примера три числовых поля, у каждого из которых установлен минимум в 10, максимум в 100 и шаг в 10 единиц.

    Устанавливая атрибуты min , max и step , мы можем быть уверены в правильности значения только тогда, когда пользователь использует специальные контролы числового поля. Но что мешает пользователю ввести вручную некорректные данные? Вот что произойдёт, если он вставит 1 , 12 и 123 в три поля и отправит форму:


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

    Добавляем несколько сообщений об ошибках в один тултип

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

    Примечание переводчика : Слово «mismatch» переводится как «несоответствие». Поэтому в значениях patternMismatch , stepMismatch и typeMismatch обратная логика: true - значение не удовлетворяет атрибуту, false - удовлетворяет.

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

    Теперь при попытке отправить форму мы увидим вот это:


    Стало лучше, поскольку теперь будут показываться все сообщения об ошибках, связанные с конкретным полем. Однако другая проблема всё ещё не решена: ошибки по-прежнему показываются лишь для первого поля.

    Это ограничение валидации, устанавливаемое браузером. Чтобы его побороть, нам нужно пойти другим путём.

    Показываем все ошибки для всех полей.

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

    Этого можно добиться какой-то парой дополнительных строчек в нашем коде:

    Вот что происходит при клике на submit теперь:


    Используем нестандартные проверки валидности

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

    Так как мы уже проверяем все возможные ошибки вручную в нашей функции CustomValidation.prototype.checkValidity , мы можем просто-напросто добавить туда ещё несколько проверок.

    Валидация в реальном времени

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