В этой третьей части статьи, состоящей из трех частей, мы завершим изучение проверки собственных форм в браузерах. Часть 1 обсуждала общие аспекты пользовательского интерфейса и CSS. Часть 2 изучила несколько свойств HTML и JavaScript API.

В этой части мы рассмотрим собственные сообщения об ошибках и предложим общие рекомендации, как перейти к действительно пригодной для использования собственной проверке формы.

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

Сообщения об ошибках

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

С самого начала следует отметить одно: эти сообщения не стилизованы (хотя когда-то они были в Chrome). Так что. К настоящему времени мы ожидаем такого рода вещей.

Кроме того, сообщения проверки собственной формы не отображаются в Firefox 53. Это подтвержденная ошибка, которая не встречается ни в 52, ни в 54. Остальная часть этой статьи игнорирует ошибку, и вам не следует запускать какие-либо тесты в Firefox 53.

Отображение сообщений об ошибках

Когда браузеры показывают собственные сообщения об ошибках? Оказывается, есть только два триггера: если пользователь отправляет форму, и если reportValidity() вызывается в недопустимом поле формы. В этом нет ничего неразумного. В обоих случаях мы хотим предупредить пользователя о возможных проблемах проверки.

Конечно, ни один из триггеров не показывает сообщение об успешном выполнении, если поле имеет допустимое значение. Сообщения об успехе полностью игнорируются в API, где в CSS есть как минимум :valid.

В части 1 мы увидели, что проверка onblur, то есть отображение сообщения об ошибке, как только пользователь покидает поле, является лучшим моментом. Итак, лучший способ запуска собственных сообщений об ошибках кажется очевидным:

field.onblur = function () {
	this.reportValidity()
}

Кажется просто, правда? К сожалению, в Chrome и Safari это дает поистине ужасную осечку, потому что в этих браузерах reportValidity(), помимо отображения сообщения об ошибке, делает акцент на проблемном поле. Хуже того, если поле получает фокус, сообщение об ошибке скрывается. Итак, теперь происходит следующее:

  1. Пользователь оставляет недопустимое поле, срабатывает обработчик события размытия.
  2. Появляется сообщение об ошибке.
  3. Поле сфокусировано.
  4. Сообщение об ошибке исчезает.

Попробуйте эффект здесь. Сначала используйте Firefox или Edge для правильной версии, затем используйте Chrome или Safari для версии с ошибками.

В результате пользователю кажется, что он не может покинуть поле формы по неуказанным причинам. Это действительно ужасный UX, и он оставляет пользователя в неведении относительно того, что происходит.

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

Что касается Edge, он не поддерживает reportValidity(), поэтому этот фрагмент кода не будет работать. Может быть, у Edge действительно лучшая реализация здесь.

Скрытие сообщений об ошибках

Когда скрываются сообщения об ошибках? Самое главное, когда поле сфокусировано. В некоторых ситуациях это имеет смысл; иногда поле получает фокус, потому что пользователь начинает редактировать значение. Однако иногда это не имеет смысла; сообщение об ошибке также исчезает, когда поле a получает фокус программно, как мы видели в приведенном выше примере onblur.

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

Edge, Firefox, Safari и большинство Chromia на мобильных устройствах скрывают сообщение об ошибке, когда пользователь прокручивает страницу. Это не очень хорошая идея: почему бы пользователю не разрешить прокрутку?

Более одной ошибки

Если пользователь отправляет форму и, таким образом, запускает собственные сообщения об ошибках, вполне возможно, что форма содержит более одной ошибки. Что тогда происходит? Ничего хорошего, так как теперь вы сами сможете угадать. У нас не может быть хороших вещей.

Если форма отправлена, браузер просматривает все поля формы по порядку, а если он находит недопустимое поле, он останавливается и показывает правильное сообщение об ошибке. Это может показаться логичным, но имеет несколько неожиданных последствий для Chrome и Safari. (Firefox и Edge справляются с этим лучше, как мы увидим позже.) Попробуйте здесь, чтобы увидеть, что именно произойдет.

Chrome и Safari показывают первое сообщение об ошибке и сосредотачиваются на проблемном поле формы. Пользователь корректирует значение. Что теперь? Пользователь думает, что он готов, и снова отправляет форму, но видит новое всплывающее сообщение об ошибке. Это плохой UX. Необязательно отправлять форму несколько раз, чтобы найти все сообщения об ошибках.

Firefox и Edge справляются с этим лучше: они выделяют все недопустимые поля, а не только первое, красным контуром, чтобы обозначить, что они недействительны. Это в значительной степени обязательно, и Chrome и Safari должны реализовать это немедленно.

(А как насчет дальтонизма? Красный цвет не подойдет, но контур все еще немного толще, чем обычная граница формы. Я не знаю ни одного исследования, которое доказывает или опровергает, что это работает, поэтому мы должны доверять Mozilla и команды разработчиков браузеров Microsoft здесь.)

Кроме того, Edge на ПК (но не на мобильных устройствах) и Firefox на Android (но не на Windows или Mac) выдает сообщение об ошибке каждый раз, когда пользователь фокусируется на недопустимом поле. Теперь это действительно действительно хорошо продуманная полезная функция. Пользователь видит красный контур и понимает, что поле недействительно. Но почему? Щелкните по нему, и вы увидите причину. Идеально! Все браузеры должны везде реализовывать это поведение. Конечно, не по причинам.

Недействительное событие

Давайте немного поговорим о недопустимом событии. Недействительное событие? Да, есть. Более того, оказывается, что все браузеры его поддерживают. Неудивительно, что он срабатывает, когда поле формы оказывается недопустимым, то есть когда checkValidity() или reportValidity() находит недопустимое поле или когда это делает процесс отправки.

Мы можем подавить собственное сообщение об ошибке, вернув false или используя event.preventDefault(). Возможно, вы захотите это сделать.

Следующая проблема: недопустимое событие не всплывает. Почему нет? Потому что браузеры странные.

К счастью, на помощь приходит старинный трюк. Мы должны установить недопустимый обработчик событий в форме на этапе захвата, например:

document.forms[0].addEventListener('invalid',function (e) {
	e.preventDefault();
},true);

Этот фрагмент кода подавляет все собственные сообщения об ошибках, но структура по-прежнему отображается в Firefox и Edge, а форма не отправляется. Вероятно, это самый полезный фрагмент кода, который вы найдете во всей серии статей.

Действительное событие

Если есть недопустимое событие, имело бы смысл, если бы было и действительное событие, верно? Он срабатывает всякий раз, когда поле формы проверяется и оказывается действительным. Это привело бы к таким простым скриптам:

document.forms[0].addEventListener('invalid',function (e) {
	e.target.showErrorMessage();
},true);
document.forms[0].addEventListener('valid',function (e) {
	e.target.hideErrorMessage();
},true);

Было бы замечательно и логично, если бы это мероприятие действительно сработало. Очевидно, что это не так. Браузеры не впечатлены нашими жалкими попытками логики и упорно отказываются им подыгрывать. Мы возражаем тем, что не впечатляемся браузерами. Это не помогает, но, по крайней мере, заставляет нас чувствовать себя хорошо.

Заключение

На этом завершается наш исчерпывающий и неудовлетворительный обзор проверки форм CSS и JavaScript в современных браузерах. Хотите вывод? Вы получите один.

Не работает.

Позвольте мне немного пояснить это. Для вас совершенно нормально выбрать одну или две хорошие функции и использовать их в своем собственном скрипте. Однако в этой статье мы хотели создать UX для проверки правильности формы с использованием только встроенных функций. Это не удалось, потому что нативные функции никуда не годятся.

Каждая хорошая идея в API проверки ограничений или в CSS компенсируется несколькими очень плохими, а браузеры делают вещи еще более беспорядочными, игнорируя разумные меры предосторожности UX, такие как разрешение пользователю видеть сообщения проверки формы при любых обстоятельствах.

Несмотря на то, что эти функции были реализованы много лет назад, они все еще не готовы к использованию в прайм-тайм. Для ваших пользователей гораздо лучше работает старомодная проверка форм JavaScript, которую мы писали последние двадцать лет.

Рекомендации

На случай, если это прочитает кто-либо из поставщика браузеров или органа по стандартизации, который действительно заботится о помощи пользователям и веб-разработчикам, вот мои рекомендации по проверке нативной формы, которая действительно работает:

  • Поддержка :user-error или :user-invalid, чтобы поля формы оценивались только после того, как у пользователя была возможность что-то сделать. (Из всех рекомендаций, которые я даю, это единственная, которая, вероятно, будет выполнена.)
  • CSS :valid и :invalid должны запускаться размытием, а не нажатием клавиши. Пользователи не хотят, чтобы их беспокоили, пока они заполняют поле формы. Покажите результаты, когда они будут готовы.
  • Помимо fieldset:invalid и form:invalid, также должно работать label:invalid.
  • maxlength и minlength должны проверять значения по умолчанию так же, как и все другие ограничения. (Это может означать, что все другие ограничения также ждут действий пользователя; меня это не волнует. Я добиваюсь согласованности.)
  • Примите кровавое решение на input:before/after. Поддержка этого явно была бы лучшим решением, но даже постоянное отсутствие поддержки было бы предпочтительнее нынешней чепухи в Chrome и Safari.
  • Добавьте атрибут, например error-message, для полей формы и input:error-message, чтобы его стилизовать. (Может быть, добавить языковые варианты, такие как error-message-en-us, error-message-fr и т. Д., Которые основаны на заданном языке документа?)
  • Или может просто заставить title содержать сообщение об ошибке? В любом случае прекратите текущую чушь про title работу только с patterned полями. Последовательность!
  • Разделите setCustomValidity() на два метода: один для установки текста сообщения об ошибке в поле, а второй для установки значения допустимости поля как «истина» или «ложь».
  • Убрать автоматический фокус с reportValidity().
  • Реализуйте допустимое событие в дополнение к недопустимому событию. Также сделайте их пузырящимися. Не допускать пузырей событий здесь - ерунда.

Кроме того, сообщения об ошибках должны быть полностью переработаны:

  • Добавьте сообщения об успехе - в части 1 мы увидели, что они могут быть важны в некоторых ситуациях, например, когда пользователь исправляет ошибку.
  • После отправки браузеры должны отображать все сообщения об ошибках сразу.
  • Не скрывайте сообщения об ошибках, когда пользователь прокручивает. Фактически, скрыть их только тогда, когда пользователь завершит повторный ввод значения (другими словами, onblur).
  • Скопируйте поведение Edge / Firefox, при котором все недопустимые поля выделяются красным контуром.
  • Скопируйте поведение Edge / Firefox, показывающее сообщение об ошибке, когда пользователь фокусируется на недопустимом поле.
  • Создавайте методы, которые явно отображают и скрывают собственные сообщения об ошибках и больше ничего не делают.
  • Обеспечьте простой декларативный способ переписывания сообщений об ошибках по умолчанию. Фактически, распространите это на все поля формы, даже на простые text.

Пока эти изменения не будут внесены, давайте спокойно забудем о проверке собственных форм. Это больше неприятностей, чем пользы.