Количество просмотров:

0

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



Продолжение: Разметка форм в HTML5 (первая статья)
Продолжение: Обзор форм HTML5: CSS (вторая статья)

HTML5 позволяет нам осуществлять валидацию форм со стороны клиента без применения кодов Java Script. Тем не менее, нам необходимо усилить встроенную проверку при создании более сложных форм, поскольку:

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

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

Перехват при передаче форм

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

В HTML5 браузер в первую очередь осуществит свою проверку – момент инициализации не наступит, пока в форму не будет введено действительное значение. Поэтому, если вы хотите установить какую-либо сложную операцию, такую как собственное отображение ошибок, сличением с исходным текстом или авто-заполнение полей, вы должны отключить родную валидацию, присвоив свойству формы 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;

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

Свойство поля .willValidate

Каждому полю ввода присваивается свойство .willValidate. Оно принимает значения:

  • true, когда браузер будет проводить собственную валидацию поля ввода;
  • false, когда браузер не будет проводить валидацию поля, или;
  • undefined, когда браузер не поддерживает родную валидацию 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!
Теперь мы знаем, что код внутри первого блока будет считан, когда будет доступна родная валидация. Тем не менее…

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

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

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

не поддерживается в браузерах Firefox 29 и IE11. В действительности эти браузеры сгенерируют следующий код:

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

Однако оба браузера поддерживают валидацию для текстовых полей, поэтому 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. Если нет несоответствий, свойство принимает значение true, если есть – false.

Также есть  метод со свойством поля .reportValidity, которое преобразует текущее состояние проверки в состояние повторной проверки, но оно менее полезное и поддерживается не всеми браузерами.

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

  • 1. устанавливают объект поля .validity, благодаря чему ошибки можно проверить более детально и
  • 2. инициируют присвоение значения invalid, когда не удается провести валидацию. Можно использовать это для того, чтобы отобразить ошибки, изменить цвета и т.д.

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

Объект поля со свойством .Validity

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

.valid – значение true принимается, если в поле нет ошибок, в ином случае принимается значение false.
.valueMissing – значение true принимается, если заполнение поля обязательно, а значение не введено.
.typeMismatch – значение true принимается, если значение имеет неправильный синтаксис, например, это плохо отформатированный e-mail.
.patternMismatch – значение true принимается, если значение не соответствует регулярному выражению атрибута pattern.
.tooLong – значение true принимается, если значение имеет большую длину, чем максимальная установленная длина (maxlength).
.tooShort – значение true принимается, если значение имеет меньшую длину, чем установленная минимальная длина (minlength).
.rangeUnderFlow – значение true принимается, если значение ниже, чем установленный минимум.
.rangeOverflow – значение true принимается, если значение выше, чем установленный максимум.
.badInput – значение true принимается, если введенные данные нельзя преобразовать в формат значения.
.customError – значение true принимается, если у поля есть собственный набор ошибок.

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

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

Вы можете вручную эмулировать объект со свойством .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() и .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, но вам понадобится дополнительный код для проверки адресов e-mail, URL, дат, чисел, диапазонов и т.д.

В связи с чем возникает вопрос: если вы пишете код для валидации поля в устаревших браузерах, зачем вообще нужно использовать родную API проверку браузера? Логичный вывод! Рассмотренный выше код является обязательным только в том случае, если вы хотите гарантировать поддержку всеми браузерами, начиная с IE6 и выше, и гарантировать пользователю правильное отображение. В иных случаях он не является обязательным…
  • • Вам может и не понадобиться для простых форм никакой код JavaScript.  Те, кто используют устаревшие версии браузеров, могут вернуться к проверке со стороны сервера, которая выполняется всегда;
  • • Если вам нужны более сложные формы, но важна поддержка только последними браузерами (начиная с IE10 и выше), вы можете удалить все неподдерживаемые коды валидации. Единственное, вам дополнительно понадобится JavaScript, если в ваших формах используется формат дат, который на данный момент не поддерживается Firefox и IE.;
  • • Даже если вам требуется код для проверки таких полей, как поля для ввода e-mail, чисел и т.д., в версиях IE9 и ниже, старайтесь сделать его простым и удалите его, когда вам не нужна будет поддержка этих браузеров. Пока это довольно запутанно, но потом будет исправлено.
Запомните, что в HTML5 всегда нужно использовать правильный вид поля. В этом случае браузеры обеспечат контроль ввода данных со своей стороны и поспособствуют более быстрой валидации со стороны клиента в том случае, если JavaScript отключен.

Загрузка...