Статьи

Мастерство HTML5: проверка ограничений

HTML5 Mastery серия изображений

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

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

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

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

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

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

Во второй части серии «HTML5 Mastery» мы уже упоминали, насколько важен тип кодировки форм. Мы также рассмотрели три хорошо известных типа кодирования. Остается вопрос: как на самом деле строятся ценности? Точное поведение браузера зависит от протокола, который указан для action . Теперь мы предполагаем HTTP или HTTPS для простоты.

В принципе, браузер имеет два варианта:

  1. Измените действие для переноса значений формы.
  2. Отправьте значения через тело запроса.

Оба используют примерно одинаковую процедуру. Короче мы находим следующие шаги:

  1. Построить набор данных с правильной кодировкой.
  2. Создайте запрос с набором данных и типом кодировки.
  3. Отправьте запрос.

Конструкция набора данных формы подразумевает несколько тонких вопросов, которые не очень хорошо известны. Например, имеет значение, если была нажата кнопка для отправки формы. В этом случае значение кнопки передается на сервер. Это можно использовать для определения, какая кнопка была нажата.

1
2
3
4
<form>
    <input type=submit name=foo value=bar>
    <input type=submit name=foo value=baz>
</form>

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

1
foo=bar

Запуск отправки формы из JavaScript приведет к тому, что контент не будет передан. Код JavaScript использует метод submit() экземпляра HTMLFormElement .

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

Следующий пример иллюстрирует это поведение.

1
2
3
<form>
    <input type=image src=test.png name=foo value=bar>
</form>

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

Содержимое запросов может выглядеть аналогично следующему фрагменту.

1
foo.x=71&foo.y=38&foo=bar

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

Отправка формы

Отправка формы программно приведет к передаче одного значения.

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

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

1
2
3
4
5
var form = document.querySelector(‘form’);
form.addEventListener(‘submit’, function (ev) {
    // always abort!
    ev.preventDefault();
}, false);

Провести живую проверку легко в теории. Однако указанные события DOM могут работать не так, как предполагалось. Например, событие change текстового поля запускается только после того, как текстовое поле потеряло свой фокус. Это может произойти, когда пользователь нажимает кнопку отправки. Поэтому взаимодействие с валидацией нарушено и не ощущается живым.

Вместо этого имеет смысл использовать событие keyup или input . Хотя первое является рабочим решением в случае текстового поля, второе работает для всех элементов ввода (как и ожидалось). Единственным ограничением является то, что он был введен с HTML5 и может не поддерживаться некоторыми старыми браузерами.

Имея это в виду, давайте сравним различные события, чтобы увидеть порядок выполнения. Следующий тестовый код помогает нам.

1
2
3
4
5
6
7
var input = document.querySelector(‘input’);
 
[‘input’, ‘keyup’, ‘change’].forEach(function (eventName) {
    input.addEventListener(eventName, function (e) {
        console.log(eventName + ‘ event triggered’);
    }, false);
});

Для нашего тестового элемента <input> мы видим следующий результат при проверке несколькими буквами. В конце мы используем клавишу табуляции, чтобы явно убрать фокус.

Входное событие HTML5

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

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

Рассмотрим следующий очень простой HTML:

1
<form id=main><input><input><input></form><input form=main>

Мы используем атрибут form HTML5 для объявления одного поля <form> вне его. Тем не менее, событие input просто работает, потому что события на самом деле всплывают в DOM-дереве. Следовательно, конкретное событие, вызванное полем снаружи, не будет видно.

Поэтому самый надежный способ — получить форму и выполнить итерацию по дочерним elements указанным в коллекции elements . Здесь собраны все назначенные поля (кроме типа ввода image ).

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

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

Архитектура проверки HTML-ограничений

API также довольно открыт, так что мы можем запрашивать результаты, полученные браузером, или расширять результаты браузера. Validation псевдоинтерфейса также наследуется другими интерфейсами, а не только HTMLInputElement .

Давайте посмотрим пример кода. В следующем коде мы сначала проверяем, возможна ли вообще проверка формы. Если это так, то мы заботимся о результате проверки для поля с type=date . Если пользователь выбрал действительную дату, мы проверяем статус флажка.

1
2
3
4
5
6
7
8
9
var form = document.querySelector(‘form’);
var date = document.querySelector(‘#birthday’);
 
if (form.willValidate) {
    if (!date.validity.valid || checkbox.checked)
        checkbox.setCustomValidity(»);
    else
        checkbox.setCustomValidity(‘You need to agree to our terms.’);
}

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

HTML5 знает довольно много разных типов ввода. Но ведь их можно сгруппировать в три класса:

  • Текст
  • номер
  • Дата

Разница не видна из свойства value . Здесь мы всегда получаем string значение. В конце концов, значение будет представлено в виде текста. Следствием наличия этих трех групп является различное поведение в отношении определенных типов ограничений.

Следующие ограничения работают почти всегда одинаково:

  • required , в результате чего valueMissing если длина value равна нулю
  • minlength , что приводит к tooShort если длина строки слишком мала
  • maxlength , что приводит к tooLong если длина строки слишком велика

Есть, конечно, исключения. Например, флажок реагирует на required в checked . Выбор цвета будет проверен на valueMissing если он required и содержит недопустимый цвет. Другие типы реагируют аналогично.

Другие возможные ограничения зависят от конкретного типа ввода. Тип определяет способ обработки значения. Это рассматривается как текст? Это представляет число? Ограничение реагирует на это.

Давайте возьмем тип ввода date в качестве примера. Если установлена ​​правильная дата, мы получаем valueMissing если ограничено required . Кроме того, badInput устанавливается, если что-то действительно было введено. Однако в случае действительной даты у нас может быть одна или несколько из следующих ошибок проверки:

  • rangeUnderflow , если дата меньше указанной в атрибуте min
  • rangeOverflow , если дата превышает дату, указанную в атрибуте max
  • stepMismatch , если дата не удовлетворяет предоставленному шаблону step

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

Для ввода текста есть также атрибут pattern , который позволяет нам указать регулярное выражение для проверки. Если тип ввода поддерживает это ограничение, то в случае сбоя отмечается patternMismatch .

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

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