Статьи

HTML5 формы: JavaScript и API проверки ограничений

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

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

  • не все браузеры поддерживают все типы ввода HTML5 и селекторы CSS
  • пузыри сообщений об ошибках используют общий текст («пожалуйста, заполните это поле») и их сложно стилизовать
  • :invalid и :required стили применяются при загрузке страницы до того, как пользователь взаимодействует с формой.

Брызги магии JavaScript и API Constraint Validation могут улучшить пользовательский опыт. Имейте в виду, что это может стать немного запутанным, если вы хотите поддерживать широкий спектр браузеров и типов ввода, которые мы постараемся сделать.

Перехват представлений формы

До HTML5 проверка на стороне клиента включала присоединение к форме обработчика submit который проверял бы поля, отображал ошибки и предотвращал событие отправки.

В HTML5 браузер сначала выполнит свою собственную проверку — событие submit не будет запущено, пока форма не будет действительной. Поэтому, если вы хотите сделать что-то сложное, например, отобразить ваши собственные ошибки, сравнить или автоматически заполнить поля, вы должны отключить собственную проверку, установив для свойства noValidate формы noValidate true:

 var form = document.getElementById("myform"); form.noValidate = true; // set handler to validate the form // onsubmit used for easier cross-browser compatibility form.onsubmit = validateForm; 

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

Свойство Field .willValidate

Каждое поле ввода имеет свойство .willValidate . Это возвращает:

  • истина, когда браузер будет нативно проверять поле
  • false, когда браузер не проверит поле, или
  • не определено, когда браузер не поддерживает стандартную проверку HTML5, например, IE8.

Поскольку мы отключили встроенную проверку выше, каждое поле будет возвращать false. Давайте создадим наш обработчик validateForm который перебирает все поля и проверяет, доступна ли собственная проверка:

 function validateForm(event) { // fetch cross-browser event object and form node event = (event ? event : window.event); var form = (event.target ? event.target : event.srcElement), f, field, formvalid = true; // loop all fields for (f = 0; f < form.elements; f++) { // get field field = form.elements[f]; // ignore buttons, fieldsets, etc. if (field.nodeName !== "INPUT" && field.nodeName !== "TEXTAREA" && field.nodeName !== "SELECT") continue; 

Цикл перебирает все поля в коллекции elements формы и проверяет их входные данные, а не другие типы, такие как кнопки и наборы полей. Следующая строка важна …

 // is native browser validation available? if (typeof field.willValidate !== "undefined") { // native validation available } else { // native validation not available } 

И false, и undefined являются ошибочными значениями, поэтому вы не можете проверить только field.willValidate !

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

Поддерживает ли браузер тип ввода?

Если вы прочитаете первую часть , вы вспомните, что неподдерживаемые типы ввода возвращаются к text . Например:

 <input type="date" name="dob" /> 

изначально не поддерживается в Firefox 29 или IE11. Эти браузеры будут (эффективно) отображать:

 <input type="text" name="dob" /> 

НО оба браузера поддерживают проверку типов text поэтому field.willValidate НЕ вернет undefined ! Поэтому мы должны проверить, что наш атрибут type соответствует свойству объекта .type — если они не совпадают, нам нужно реализовать устаревшую резервную проверку, например

 // native validation available if (field.nodeName === "INPUT" && field.type !== field.getAttribute("type")) { // input type not supported! Use legacy JavaScript validation } 

Поле .checkValidity () Метод

Если доступна встроенная проверка, можно .checkValidity() метод .checkValidity() для проверки поля. Метод возвращает true, если проблем нет, или false в противном случае.

Существует аналогичный .reportValidity() который возвращает текущее состояние без повторной проверки, хотя это менее полезно и поддерживается не во всех браузерах.

Оба метода также:

  1. установить объект .validity поля, чтобы ошибки могли быть проверены более подробно и
  2. сгенерировать invalid событие в поле, если проверка не пройдена. Это может быть использовано для отображения ошибок, изменения цветов и т. Д. Обратите внимание, что нет соответствующего valid события, поэтому не забудьте сбросить стили ошибок и сообщения при необходимости.

Поле

Объект .validity имеет следующие свойства:

.valid — возвращает true, если в поле нет ошибок или false в противном случае.
.valueMissing — возвращает true, если поле является обязательным, но значение введено.
.typeMismatch — возвращает true, если значение имеет неправильный синтаксис, например, плохо отформатированный адрес электронной почты.
.patternMismatch — возвращает true, если значение не соответствует регулярному выражению атрибута pattern .
.tooLong — возвращает true, если значение длиннее допустимой maxlength .
.tooShort — возвращает true, если значение короче допустимой minlength .
.rangeUnderFlow — возвращает true, если значение меньше min .
.rangeOverflow — возвращает истину, если значение превышает max .
.stepMismatch — возвращает true, если значение не соответствует step .
.badInput — возвращает true, если запись не может быть преобразована в значение.
.customError — возвращает true, если в поле установлена ​​пользовательская ошибка.

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

Поддержка .valid в старых браузерах

Вы можете вручную эмулировать объект .validity в старых браузерах, например

 // native validation not available field.validity = field.validity || {}; // set to result of validation function field.validity.valid = LegacyValidation(field); 

Это гарантирует, что .validity.valid можно протестировать во всех браузерах.

Поле .setCustomValidity () Метод

Метод .setCustomValidity() может быть передан:

  • пустая строка. Это устанавливает поле как допустимое, поэтому .checkValidity() и .validity.valid вернут true , или
  • строка, содержащая сообщение об ошибке, которое будет отображаться в пузыре сообщения (если используется). Сообщение также помечает поле как .checkValidity() поэтому .checkValidity() и .validity.valid будут возвращать false, а invalid событие сработает.

Обратите внимание, что вы также можете проверить текущее сообщение, используя свойство поля .validationMessage .

Собираем все вместе

Теперь у нас есть основа простой, общей кросс-браузерной системы проверки форм:

 var form = document.getElementById("myform"); form.noValidate = true; // set handler to validate the form // onsubmit used for easier cross-browser compatibility form.onsubmit = validateForm; function validateForm(event) { // fetch cross-browser event object and form node event = (event ? event : window.event); var form = (event.target ? event.target : event.srcElement), f, field, formvalid = true; // loop all fields for (f = 0; f < form.elements; f++) { // get field field = form.elements[f]; // ignore buttons, fieldsets, etc. if (field.nodeName !== "INPUT" && field.nodeName !== "TEXTAREA" && field.nodeName !== "SELECT") continue; // is native browser validation available? if (typeof field.willValidate !== "undefined") { // native validation available if (field.nodeName === "INPUT" && field.type !== field.getAttribute("type")) { // input type not supported! Use legacy JavaScript validation field.setCustomValidity(LegacyValidation(field) ? "" : "error"); } // native browser check field.checkValidity(); } else { // native validation not available field.validity = field.validity || {}; // set to result of validation function field.validity.valid = LegacyValidation(field); // if "invalid" events are required, trigger it here } if (field.validity.valid) { // remove error styles and messages } else { // style field, show error, etc. // form is invalid formvalid = false; } } // cancel form submit if validation fails if (!formvalid) { if (event.preventDefault) event.preventDefault(); } return formvalid; } // basic legacy validation checking function LegacyValidation(field) { var valid = true, val = field.value, type = field.getAttribute("type"), chkbox = (type === "checkbox" || type === "radio"), required = field.getAttribute("required"), minlength = field.getAttribute("minlength"), maxlength = field.getAttribute("maxlength"), pattern = field.getAttribute("pattern"); // disabled fields should not be validated if (field.disabled) return valid; // value required? valid = valid && (!required || (chkbox && field.checked) || (!chkbox && val !== "") ); // minlength or maxlength set? valid = valid && (chkbox || ( (!minlength || val.length >= minlength) && (!maxlength || val.length <= maxlength) )); // test pattern if (valid && pattern) { pattern = new RegExp(pattern); valid = pattern.test(val); } return valid; } 

LegacyValidation специально оставлено простым; он проверяет required , minlength , maxlength и регулярные выражения pattern , но вам потребуется дополнительный код для проверки адресов электронной почты, URL-адресов, дат, чисел, диапазонов и т. д.

Что приводит к вопросу: если вы пишете код проверки поля для устаревших браузеров, зачем использовать API-интерфейсы собственных браузеров? Очень хороший момент! Приведенный выше код необходим только в том случае, если вы хотите поддерживать все браузеры начиная с IE6 и предлагать аналогичные пользовательские возможности. Это не всегда будет необходимо …

  • Вам может не потребоваться какой-либо код JavaScript для простых форм. Те, кто использует устаревшие браузеры, могут прибегнуть к проверке на стороне сервера, которая всегда должна быть реализована.
  • Если вам требуются более сложные формы, но требуется только поддержка новейших браузеров (IE10 +), вы можете удалить весь устаревший код проверки. Вам потребуется только дополнительный JavaScript, если в ваших формах используются даты, которые в настоящее время не поддерживаются в Firefox и IE.
  • Даже если вам требуется код для проверки полей, таких как электронные письма, номера и т. Д. В IE9 и ниже, оставьте его простым и удалите его, как только вы перестанете поддерживать эти браузеры. Сейчас немного грязно, но ситуация улучшится.

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