В заключительной статье этой серии из трех частей о веб-формах 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()
который возвращает текущее состояние без повторной проверки, хотя это менее полезно и поддерживается не во всех браузерах.
Оба метода также:
- установить объект
.validity
поля, чтобы ошибки могли быть проверены более подробно и - сгенерировать
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 отключен.