onKeyDown и onBeforeWrite

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


Позиция onKeyDown в цепочке обработки ввода

onKeyDown вызывается в момент нажатия клавиши, до того как браузер выполнит стандартное изменение значения input. На этом этапе Inputmask получает доступ к «сырому» намерению пользователя — факту нажатия клавиши, включая код клавиши, модификаторы и текущее состояние маски.

Основные характеристики этапа:

  • Срабатывание происходит до изменения значения поля
  • Доступен event.key, event.code, ctrlKey, altKey, shiftKey
  • Значение input ещё не модифицировано
  • Маска находится в состоянии «до применения операции»

Этот уровень обработки используется для:

  • блокировки нежелательных символов до их попадания в значение
  • управления навигацией внутри маски (стрелки, backspace, delete)
  • кастомной логики обработки управляющих клавиш
  • предотвращения стандартного поведения браузера

В контексте Inputmask onKeyDown часто выступает как фильтр первого уровня, позволяющий предотвратить ненужные операции ещё до этапа перерасчёта маски.


Управление поведением ввода через onKeyDown

Логика обработки на этом этапе строится вокруг анализа клавиши и текущего состояния маски. Типичный сценарий включает проверку допустимости действия и возврат управляющего результата.

Ключевые сценарии использования:

  • перехват Backspace для корректного удаления с учётом структуры маски
  • блокировка ввода символов, не соответствующих шаблону
  • переопределение поведения Enter или Tab
  • управление позиционированием курсора

Внутри Inputmask этот этап тесно связан с механизмом caret-менеджмента, так как изменение позиции курсора до применения изменений позволяет избежать неконсистентного состояния.


Особенности обработки состояния на этапе keydown

На уровне keydown отсутствует итоговое значение, поэтому любые вычисления происходят на основе:

  • текущего value input
  • позиции каретки
  • конфигурации маски
  • вводимого символа

Это делает этап чувствительным к асинхронным изменениям состояния DOM. В отличие от более поздних стадий, здесь невозможно опираться на «будущее» значение поля — только на предполагаемое действие.


Переход к стадии формирования нового значения

После обработки события клавиатуры Inputmask переходит к вычислению нового состояния строки. На этом этапе формируется промежуточное представление значения, которое ещё не записано в DOM, но уже существует в логике маски.

Именно здесь подготавливается структура, которая затем будет передана в этап записи.


Роль onBeforeWrite в жизненном цикле Inputmask

onBeforeWrite вызывается непосредственно перед тем, как новое значение будет записано в input. В отличие от onKeyDown, этот хук работает уже с результатом вычислений маски.

Основные характеристики:

  • срабатывает после применения логики маски
  • получает доступ к финальному значению перед записью
  • может модифицировать итоговую строку
  • влияет на то, что реально попадёт в DOM

Этот этап можно рассматривать как финальный фильтр и трансформер результата.


Структура данных на этапе onBeforeWrite

На момент вызова onBeforeWrite доступны:

  • текущее значение input до записи
  • новое вычисленное значение
  • позиция каретки после преобразования
  • состояние маски и буфера
  • контекст изменения (ввод, удаление, вставка)

Это позволяет выполнять не только фильтрацию, но и структурную модификацию результата.


Применение onBeforeWrite для трансформации значения

onBeforeWrite используется для:

  • форматирования результата перед записью
  • динамической корректировки маски
  • условного изменения вывода в зависимости от контекста
  • нормализации значения (например, приведение к единому формату)

В отличие от onKeyDown, здесь уже нет необходимости интерпретировать намерение пользователя — оно уже преобразовано в итоговую операцию.


Сравнение уровней контроля

Разделение onKeyDown и onBeforeWrite отражает двухуровневую архитектуру управления вводом.

onKeyDown: уровень намерения

  • работает с фактом нажатия клавиши
  • позволяет предотвратить действие
  • управляет вводом до изменения значения
  • ориентирован на события клавиатуры

onBeforeWrite: уровень результата

  • работает с вычисленным значением
  • изменяет итог перед записью
  • не управляет клавиатурой напрямую
  • ориентирован на состояние данных

Промежуточное состояние между событиями

Между onKeyDown и onBeforeWrite Inputmask выполняет несколько внутренних шагов:

  • интерпретация нажатия
  • вычисление новой позиции каретки
  • применение правил маски
  • формирование буферного значения
  • подготовка итоговой строки

Это промежуточное состояние не является частью DOM, но критично для корректной работы системы маскирования.


Поведение при вставке данных

При вставке текста различие между этапами становится особенно заметным:

  • onKeyDown может зафиксировать Ctrl+V или Cmd+V
  • дальнейшая логика определяет вставляемый фрагмент
  • onBeforeWrite получает уже обработанную строку

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


Работа с кареткой в двух стадиях

Позиция курсора является одной из ключевых сущностей в Inputmask и обрабатывается на обоих уровнях.

На onKeyDown:

  • определяется потенциальное движение каретки
  • учитываются ограничения маски
  • блокируются некорректные переходы

На onBeforeWrite:

  • финализируется итоговая позиция
  • корректируется с учётом изменённого значения
  • синхронизируется с DOM-обновлением

Разделение позволяет избежать рассинхронизации между визуальным курсором и внутренним состоянием маски.


Влияние асинхронных операций

Хотя оба хука работают в синхронном контексте, их поведение может взаимодействовать с внешними асинхронными изменениями состояния:

  • обновление значения через JavaScript
  • программная установка value
  • реакция на внешние события

В таких случаях onBeforeWrite становится более надёжной точкой контроля, так как оперирует уже вычисленным результатом, независимо от источника изменения.


Ограничения управления на уровне onKeyDown

Несмотря на высокую степень контроля, onKeyDown имеет ограничения:

  • не видит итогового значения после применения маски
  • не может корректно предсказать все трансформации
  • зависит от браузерного поведения клавиатуры
  • требует ручной синхронизации с логикой Inputmask

Поэтому его использование эффективно только для ранней фильтрации и блокировки.


Ограничения onBeforeWrite

onBeforeWrite, в свою очередь, ограничен тем, что:

  • не влияет на сам факт нажатия клавиши
  • не может отменить уже произведённую интерпретацию ввода
  • работает только с результатом, а не с намерением

Это делает его непригодным для задач блокировки ввода, но оптимальным для форматирования.


Комбинированное использование уровней

Архитектура Inputmask предполагает совместное использование обоих хуков:

  • onKeyDown управляет входным потоком событий
  • onBeforeWrite управляет итоговым состоянием данных

Такая модель обеспечивает разделение ответственности между:

  • предотвращением некорректных действий
  • корректировкой результата после обработки

Стабильность маски при сложных сценариях ввода

При сложных масках (например, с условными сегментами, динамическими разделителями или переменной длиной блоков) взаимодействие onKeyDown и onBeforeWrite становится критическим.

Типичные проблемы, решаемые этим разделением:

  • разрыв структуры маски при быстром вводе
  • некорректная обработка удаления символов в середине строки
  • конфликт вставки и автозаполнения
  • рассинхронизация каретки и значения

Разнесение логики по этапам позволяет изолировать эти проблемы и обрабатывать их на соответствующем уровне.