Чтобы предоставить нашим пользователям отличный опыт, мы очень заинтересованы в наших компонентах ввода. Они выделяют ключевые части вводимых данных или поддерживают наших пользователей поведением для более быстрого взаимодействия. Для полного погружения мы гарантируем, что наш продукт работает с устаревшими браузерами (например, с нашим лучшим другом IE11), вечнозелеными браузерами (последние две версии firefox, chrome и safari), а также с их мобильными аналогами.

Проблема

Наше программное обеспечение для отслеживания ошибок ловило отчеты для пользователей Android, которые не могли использовать созданные нами красивые компоненты ввода. Чтобы применить нашу магию, мы слушаем событие HTML keydown. Мы поняли, что на Android keyCode был 229 почти для каждого непечатаемого символа, что оставило нас в недоумении. Время для расследования.

Расследование

Проведя несколько экспериментов, чтобы выяснить, что вызывает это событие, мы смогли понять характеристики этого события:

  • иногда имеет правильный code
  • иногда это также устанавливается как key
  • чаще всего key это Unidentified
  • чаще всего keyCode это 229
  • когда событие Unidentified, то preventDefault() не работает

Мы обнаружили, что в нашем исследовании было слишком много несоответствий, и - случайно - мы определили, что именно программная клавиатура на Android запускает эти события клавиатуры. При этом G-Board работал нормально, а Swiftkey - нет, и в зависимости от того, какая версия была установлена ​​(в сочетании с версией Android), это приводило ко всем этим иногда случаям. С более чем 100 миллионами загрузок Swiftkey, установленным на большинстве наших тестовых устройств, мы не можем игнорировать этот вариант использования, и мы очень хотели найти решение, которое работало бы везде, где мы хотим, чтобы оно работало.

Решение

Мы подумали, что вместо использования события keydown существует также событие input, и последнее предоставляет нам правильные метаданные для дальнейшей обработки события и применения нашего поведения. Поскольку событие InputEvent все еще находится в Рабочем черновике, оно еще не во всех браузерах широко и полноценно поддерживается. К сожалению, IE11 вообще не поддерживает inputevent. Мы были как бы отброшены во времена до IE6, но с теми знаниями, которые у нас есть сегодня. Идея заключалась в поддержке комбинации _16 _ / _ 17_ событий (мы берем все, что доступно в текущем браузере). Конечно, мы не хотели погружаться в мир анализа браузеров, а хотели заниматься тестированием функций. Во-первых, нам нужно было проверить, поддерживается ли событие input в текущем браузере, а во-вторых, содержит ли событие все необходимые нам метаданные (что характерно не для всех существующих браузеров). Вот код для тестирования события input (где inputType равно deleteContentForward):

Теперь, когда мы можем определить, какое событие мы хотим продолжить, нам все еще нужен способ нормализовать его до унифицированного интерфейса, а именно:

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

В качестве побочного эффекта, имея это нормализованное событие, его легче обрабатывать в дальнейшем, поскольку явное указание inputType и navigationType оказывается очень полезным. Это помогает обрабатывать изменения текста и решать проблемы навигации организованным и структурированным способом (в отличие от случая, когда вы обрабатываете только одно событие). Вот небольшая демонстрация, связывающая все это воедино:

Вы могли заметить еще одну проверку event.key.length > 1. Свойство key имеет длину один, если это печатаемый символ, если его длина больше единицы, мы предполагаем, что это любой управляющий символ (и из-за !IS_INPUT_SUPPORTED защиты) мы разрешаем событию быть обработанным.

Перспективы

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