positionCaretOnClick

В текстовых полях с маской поведение курсора определяется не только стандартной логикой браузера, но и правилами маски, которые управляют допустимыми позициями ввода. При использовании Inputmask обычная модель «клик → установка каретки в точку клика» заменяется алгоритмом сопоставления позиции клика с ближайшим допустимым слотом маски.

Каретка в контексте маски — это указатель текущей позиции ввода, который должен учитывать:

  • фиксированные символы маски (разделители, префиксы, литералы),
  • позиции для ввода (placeholder-слоты),
  • правила смещения при неполном вводе,
  • ограничения по типу данных (числа, даты, телефоны и т. д.).

Без дополнительной настройки клик внутри поля приводит к пересчёту позиции каретки через внутренний механизм адаптации маски.


Базовое поведение при клике

При стандартной конфигурации Inputmask выполняет следующие шаги:

  1. Получение координаты клика внутри input-поля.
  2. Определение символной позиции относительно строки маски.
  3. Поиск ближайшего допустимого input-слота.
  4. Перемещение каретки в найденную позицию.
  5. Коррекция позиции, если текущий символ является литералом маски.

Особенность заключается в том, что позиция клика почти никогда не совпадает с реальной позицией ввода. Например, в маске вида:

+7 (999) 999-99-99

клик по символу ( или пробелу не может установить каретку туда напрямую, и происходит «перепривязка» к ближайшему 9.


Опция positionCaretOnClick

Поведение клика контролируется параметром positionCaretOnClick, который задаёт стратегию установки каретки при взаимодействии с полем ввода.

Основная задача параметра — определить, насколько строго Inputmask должен уважать позицию клика пользователя.

Механизм применяется только при событиях:

  • click
  • focus (в некоторых сценариях)
  • touchend на мобильных устройствах

Режимы работы positionCaretOnClick

Логическое управление

В простейшем варианте параметр принимает логическое значение:

  • true — активирует интеллектуальное позиционирование каретки,
  • false — отключает перерасчёт позиции клика.

При отключённом режиме поведение упрощается: каретка чаще устанавливается в первую доступную позицию ввода или в конец уже заполненной части маски.


Стратегия пересчёта позиции

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

Логика включает:

  • определение типа символа в точке клика (литерал или placeholder),
  • проверку доступности ввода в этой позиции,
  • поиск ближайшего допустимого индекса слева или справа,
  • учет режима заполнения (forward / reverse ввод).

Поведение при клике на заполненную часть

Если поле уже частично заполнено, позиционирование каретки становится зависимым от состояния данных:

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

Взаимодействие с placeholder и символами маски

Mask engine различает два типа символов:

  • placeholder-символы (например, _ или 9),
  • литералы маски (скобки, пробелы, дефисы).

При расчёте позиции каретки:

  • литералы игнорируются как цели для позиционирования,
  • placeholder-символы считаются допустимыми позициями ввода,
  • переход через литерал происходит автоматически.

Пример:

(999) 999-9999

Клик на ) приведёт к установке каретки в ближайший 9, так как литерал не является точкой ввода.


Особенности алгоритма расчёта позиции

Алгоритм позиционирования можно представить как последовательность шагов:

  1. Получение абсолютного индекса клика.

  2. Проверка соответствия символа маске.

  3. Поиск ближайшего input-слота:

    • приоритет вперёд,
    • при невозможности — назад.
  4. Проверка доступности позиции (не заблокирована ли она правилом mask definition).

  5. Установка каретки.

Важной особенностью является то, что алгоритм не работает с «визуальной» позицией текста, а опирается на внутреннее представление маски.


Поведение при частично заполненной маске

При наличии введённых данных поведение становится контекстным.

Сценарий 1: клик в пустую часть

Каретка устанавливается в первый доступный незаполненный слот.

Сценарий 2: клик внутри заполненной области

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

  • принадлежит текущему сегменту ввода,
  • не нарушает последовательность маски.

Сценарий 3: клик перед префиксом

Если маска содержит фиксированный префикс (например, +7), клик до него игнорируется, и каретка переносится сразу после префикса.


Мобильные устройства и touch-события

На мобильных устройствах поведение усложняется из-за особенностей touch-интерфейса:

  • координаты клика менее точны,
  • виртуальная клавиатура влияет на перерасчёт позиции,
  • браузер может самостоятельно корректировать selection range.

Inputmask компенсирует это дополнительной нормализацией позиции:

  • округление индекса,
  • повторная проверка допустимости слота,
  • защита от установки каретки в недопустимые позиции.

Влияние выделения текста

Если при клике происходит выделение части строки, positionCaretOnClick учитывает:

  • наличие selection range,
  • пересечение с литералами,
  • допустимость массового редактирования.

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


Кастомизация поведения через функцию

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

  • нестандартных масок,
  • динамических правил ввода,
  • интеграции с UI-компонентами.

Функция получает контекст события и текущую позицию, после чего возвращает индекс каретки.

Типовая логика внутри функции:

  • анализ исходной позиции клика,
  • проверка маски и текущего значения,
  • возврат скорректированной позиции.

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

  • всегда ставить каретку в конец заполненной части,
  • запрещать переход в определённые сегменты,
  • фиксировать ввод в конкретных блоках.

Конфликты с автозаполнением и browser autofill

Автозаполнение браузера может изменять значение input до срабатывания click-обработчиков, что влияет на позиционирование каретки.

В таких случаях:

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

Связь с другими механизмами Inputmask

Поведение positionCaretOnClick тесно связано с:

  • showMaskOnHover — влияет на визуальное восприятие позиции,
  • autoUnmask — может менять длину строки и сдвигать индексы,
  • clearIncomplete — изменяет доступность слотов,
  • greedy — влияет на распределение placeholder-ов.

При изменении этих параметров алгоритм позиционирования может существенно меняться даже при одинаковом клике.


Типичные эффекты при неправильной настройке

Некорректная конфигурация приводит к характерным проблемам:

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

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


Поведенческая модель в терминах слотов

Внутренне маска рассматривается как набор слотов:

  • занятые слоты (введённые данные),
  • свободные слоты (placeholder),
  • запрещённые слоты (литералы).

positionCaretOnClick управляет тем, в какой слот будет переведена каретка после события click, минимизируя отклонения от допустимой структуры ввода и обеспечивая согласованность между визуальной позицией и логической моделью маски.