HTML5 представляет несколько новых атрибутов для реализации проверки на основе браузера. pattern
Атрибут является регулярным выражением , которое определяет диапазон допустимых входов для textarea
элементов и большинство типов input
. required
Атрибут определяет, требуется ли поле. Для устаревших браузеров, которые не реализуют эти атрибуты, мы можем использовать их значения в качестве основы для полифилла. Мы также можем использовать их для обеспечения более интересного усовершенствования - мгновенной проверки формы.
Мы должны быть очень осторожны, чтобы не увлечься, создавая чрезмерно агрессивную проверку, которая нарушает естественное поведение браузера и попадает на людей. Например, я видел формы, в которых невозможно нажать Tab, то есть исключить перейти на другой input. Очень злоупотребляется javascript, чтобы заставить фокус оставаться внутри поля, пока он не будет действительным. Это очень плохое использование и прямо противоречит рекомендациям по доступности.
То, что мы собираемся сделать в этой статье, гораздо менее навязчиво. Это даже не полная проверка на стороне клиента - это просто тонкое усовершенствование юзабилити, реализованное доступным способом, которое (как я обнаружил при тестировании скрипта) почти идентично тому, что теперь делает Firefox изначально!
Конечно, это не происходит сразу. Если бы это было так, то по умолчанию каждое обязательное поле имело бы эту схему. Вместо этого эти контуры отображаются только после того, как вы взаимодействовали с полем, которое в основном (хотя и не точно) аналогично onchange
событию.
Так вот что мы собираемся делать, используя onchange
в качестве запуска событие. В качестве альтернативы мы могли бы использовать oninput
событие, которое срабатывает, как только любое значение набирается или вставляется в поле. Но это действительно слишком быстро, так как данный метод будет запускать и отключать многие типы событий в быстрой последовательности при наборе текста, создавая эффект мигания, который будет раздражать или отвлекать для некоторых пользователей. И, в любом случае, oninput
не срабатывает от программного ввода, который onchange
делает, и нам может понадобиться, чтобы обрабатывать такие вещи, как автозаполнение от сторонних надстроек.
Определение HTML и CSS
Итак, давайте посмотрим на нашу реализацию, начиная с HTML, на которой она основана:
<form action="#" method="post">
<fieldset>
<legend><strong>Add your comment</strong></legend>
<p>
<label for="author">Name <abbr title="Required">*</abbr></label>
<input
aria-required="true"
id="author"
name="author"
pattern="^([- \w\d\u00c0-\u024f]+)$"
required="required"
size="20"
spellcheck="false"
title="Your name (no special characters, diacritics are okay)"
type="text"
value="">
</p>
<p>
<label for="email">Email <abbr title="Required">*</abbr></label>
<input
aria-required="true"
id="email"
name="email"
pattern="^(([-\w\d]+)(\.[-\w\d]+)*@([-\w\d]+)(\.[-\w\d]+)*(\.([a-zA-Z]{2,5}|[\d]{1,3})){1,2})$"
required="required"
size="30"
spellcheck="false"
title="Your email address"
type="email"
value="">
</p>
<p>
<label for="website">Website</label>
<input
id="website"
name="website"
pattern="^(http[s]?:\/\/)?([-\w\d]+)(\.[-\w\d]+)*(\.([a-zA-Z]{2,5}|[\d]{1,3})){1,2}(\/([-~%\.\(\)\w\d]*\/*)*(#[-\w\d]+)?)?$"
size="30"
spellcheck="false"
title="Your website address"
type="url"
value="">
</p>
<p>
<label for="text">Comment <abbr title="Required">*</abbr></label>
<textarea
aria-required="true"
cols="40"
id="text"
name="text"
required="required"
rows="10"
spellcheck="true"
title="Your comment"></textarea>
</p>
</fieldset>
<fieldset>
<button name="preview" type="submit">Preview</button>
<button name="save" type="submit">Submit Comment</button>
</fieldset>
</form>
Этот пример представляет собой простую форму комментариев, в которой требуются некоторые поля, некоторые проверяются. Области, которые required
также имеют , чтобы обеспечить запасную семантику для вспомогательных технологий, которые не понимают новых aria-required
input типы.
Спецификация ARIA также определяет атрибут, и это то, что мы собираемся использовать, чтобы указать, когда поле является недопустимым (для которого нет эквивалентного атрибута в HTML5). Атрибут, очевидно, обеспечивает доступную информацию, но он может быть также использован в качестве CSS крюка , чтобы применить красный контур:aria-invalid
input[aria-invalid="true"], textarea[aria-invalid="true"] {
border: 1px solid #f00;
box-shadow: 0 0 4px 0 #f00;
}
Мы могли бы просто использовать и не беспокоиться об этом, и, откровенно говоря, это выглядело бы лучше, но тогда у нас не было бы никаких признаков в браузерах, которые не поддерживают теней коробок, таких как IE8.box-shadow
border
Добавление JavaScript
Теперь, когда у нас есть статический код, мы можем добавить скрипты. Первое, что нам понадобится, - это основная функция: addEvent()
function addEvent(node, type, callback) {
if (node.addEventListener) {
node.addEventListener(type, function(e) {
callback(e, e.target);
}, false);
} else if (node.attachEvent) {
node.attachEvent('on' + type, function(e) {
callback(e, e.srcElement);
});
}
}
Затем нам понадобится функция для определения того, должно ли данное поле быть проверено, что просто проверяет, что он не отключен и не читается, и что он имеет либо атрибут, patter
nлибо required
атрибут:
function shouldBeValidated(field) {
return (
!(field.getAttribute("readonly") || field.readonly) &&
!(field.getAttribute("disabled") || field.disabled) &&
(field.getAttribute("pattern") || field.getAttribute("required"))
);
}
Первые два условия могут показаться многословными, но они необходимы, потому что элементы disabled
и readonly
свойства не обязательно будут отражать состояния атрибутов. В Opera, например, поле с жестко закодированным атрибутом по- прежнему будет возвращаться для своего свойства (свойство dot
только соответствует состояниям, которые задаются через скрипты).readonly="readonly"undefinedreadonly
Как только мы получим эти утилиты, мы можем определить основную функцию проверки, которая проверяет поле и затем выполняет фактическую проверку, если это применимо:
function instantValidation(field) {
if (shouldBeValidated(field)) {
var invalid =
(field.getAttribute("required") && !field.value) ||
(field.getAttribute("pattern") &&
field.value &&
!new RegExp(field.getAttribute("pattern")).test(field.value));
if (!invalid && field.getAttribute("aria-invalid")) {
field.removeAttribute("aria-invalid");
} else if (invalid && !field.getAttribute("aria-invalid")) {
field.setAttribute("aria-invalid", "true");
}
}
}
Таким образом поле недействительно если оно требуется, но не имеет значения, или оно имеет шаблон и значение, но значение не соответствует шаблону.
Поскольку patternу
же задан строковым регулярным выражением, то нам нужно передать эту строку RegExp
конструктору и создать объект регулярного выражения, который мы можем проверить по значению. Но нам нужно предварительно проверить значение, чтобы убедиться, что оно не пустое, так что самому регулярному выражению не нужно учитывать пустые строки.
Как только мы установили, является ли поле недопустимым, мы можем управлять его атрибутом, указывая, что это добавление в недопустимое поле, которое его еще не имеет значения, чтобы все это входило в действие, нам нужно привязать функцию проверки к событию. Это должно быть так просто:aria-invalidonchange
addEvent(document, "change", function(e, target) {
instantValidation(target);
});
Однако для того, чтобы работать, onchange
события должны пузыриться (используя технику, которая обычно известна как делегирование событий ), но в Internet Explorer 8 и ранее onchange
события не пузырятся . Мы могли бы просто игнорировать эти браузеры, но я думаю, что это был бы позор, особенно когда проблема настолько проста в обходе. Это просто означает немного более сложный код - нам нужно получить коллекции input и textarea элементы, перебрать их и связать onchange
событие с каждым полем отдельно:
var fields = [
document.getElementsByTagName("input"),
document.getElementsByTagName("textarea")
];
for (var a = fields.length, i = 0; i < a; i++) {
for (var b = fields[i].length, j = 0; j < b; j++) {
addEvent(fields[i][j], "change", function(e, target) {
instantValidation(target);
});
}
}
Смотрим что получилось
Таким образом, мы имеем простое и неинтрузивное усовершенствование для мгновенной проверки формы, предоставляя доступные и визуальные подсказки, чтобы помочь пользователям заполнить формы.
Вы можете посмотреть демо ниже:
После того, как этот скриптинг будет реализован, на самом деле у нас всего лишь пара пропусков и удалений от полного полигона. Такой сценарий выходит за рамки этой статьи, но если вы хотите его развивать дальше, все базовые блоки есть - проверка того, нужно ли проверять поле, проверять поле против шаблона и / или требовать, а также связать триггер Мероприятия.
Я должен признаться, я не уверен, что это действительно того стоит! Если у вас уже есть это усовершенствование (которое работает во всех современных браузерах обратно в IE7), и учитывая, что у вас нет другого выбора, кроме как выполнить проверку на стороне сервера, а также с учетом того, что браузеры, которые поддерживают pattern
и required
уже используют их для проверки перед отправкой - Учитывая все это, действительно ли есть какая-то точка, добавляющая еще один полиполк?