В заключительной статье этой серии из трех частей о веб-формах 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 отключен.