Создание собственных определений

В основе гибкости Inputmask лежит система определений (definitions), позволяющая расширять стандартный набор символов маски и задавать собственные правила ввода. Каждое определение представляет собой описание поведения одного символа маски: допустимые значения, способ валидации, правила отображения и преобразования.

Стандартные символы вроде 9 (цифра), a (буква), * (любые символы) реализованы через тот же механизм, что и пользовательские определения, что делает архитектуру расширяемой без изменения ядра библиотеки.


Структура определения символа

Определение задаётся через объект, в котором ключом выступает символ маски, а значением — конфигурация поведения:

Inputmask.extendDefinitions({
  'A': {
    validator: "[A-Za-z]",
    casing: "upper"
  }
});

Каждое определение может включать несколько параметров, влияющих на обработку ввода.

Основные параметры определения

validator Задает правило допустимого символа. Может быть строкой с регулярным выражением или функцией.

validator: "[0-9]"

или

validator: function (chrs, buffer, pos, strict, opts) {
  return /[0-9]/.test(chrs);
}

cardinality Определяет количество символов, которое занимает одно определение. Чаще всего используется значение 1, но возможны расширенные сценарии, где один символ маски соответствует нескольким вводимым символам.

cardinality: 1

casing Управляет регистром вводимых символов.

  • "upper" — преобразование в верхний регистр
  • "lower" — преобразование в нижний регистр
casing: "upper"

placeholder Задает символ-заполнитель для данного элемента маски.

placeholder: "#"

Расширение стандартного набора символов

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

Пример добавления символа, представляющего шестнадцатеричную цифру:

Inputmask.extendDefinitions({
  'h': {
    validator: "[0-9A-Fa-f]",
    casing: "upper"
  }
});

Использование в маске:

Inputmask("hhhh-hhhh").mask(element);

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


Функциональные валидаторы

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

Inputmask.extendDefinitions({
  'X': {
    validator: function (chrs, buffer, pos, strict, opts) {
      const prev = buffer[pos - 1];
      return prev !== chrs;
    }
  }
});

Функциональная форма предоставляет доступ к:

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

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


Использование cardinality в сложных форматах

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

Пример определения блока из двух символов:

Inputmask.extendDefinitions({
  'B': {
    validator: "[0-9A-F]",
    cardinality: 2
  }
});

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


Контекстная логика и динамическая проверка

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

Inputmask.extendDefinitions({
  'D': {
    validator: function (chrs, buffer, pos) {
      const sum = buffer.reduce((acc, val) => acc + (parseInt(val) || 0), 0);
      return (sum + parseInt(chrs)) % 2 === 0;
    }
  }
});

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


Переопределение существующих символов

Система definitions допускает переопределение стандартных символов, что изменяет поведение всей маски без изменения ее структуры.

Inputmask.extendDefinitions({
  '9': {
    validator: "[0-9]",
    placeholder: "0"
  }
});

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


Интеграция с alias и предопределёнными масками

Пользовательские определения часто применяются совместно с alias-конфигурациями. Alias представляет собой именованную маску, внутри которой используются расширенные символы.

Inputmask.extendAliases({
  'productCode': {
    mask: "AA-9999-XX",
    definitions: {
      'A': { validator: "[A-Z]" },
      'X': { validator: "[0-9A-Z]" }
    }
  }
});

Такой подход позволяет инкапсулировать бизнес-логику формата данных внутри одного alias.


Работа с несколькими определениями одновременно

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

Inputmask.extendDefinitions({
  'L': { validator: "[A-Za-z]", casing: "lower" },
  'U': { validator: "[A-Za-z]", casing: "upper" },
  'N': { validator: "[0-9]" }
});

Маска:

Inputmask("LLL-UUU-NNN").mask(element);

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


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

Определения напрямую влияют на работу механизмов автозаполнения и очистки ввода. При включенном режимe автоматической обработки символы преобразуются в соответствии с правилами casing и validator сразу после ввода.

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


Приоритеты и конфликтующие правила

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

  1. Функция validator (если задана)
  2. Регулярное выражение
  3. Стандартные правила Inputmask

Такой порядок позволяет переопределять поведение без нарушения базовой логики библиотеки.


Ограничения и особенности применения

При создании сложных определений учитывается несколько технических аспектов:

  • чрезмерно сложные функции валидации могут снижать производительность при вводе;
  • регулярные выражения применяются на каждый вводимый символ;
  • использование cardinality > 1 усложняет синхронизацию курсора;
  • модификация стандартных символов влияет на все маски, использующие их.

Эти особенности определяют баланс между гибкостью и предсказуемостью поведения системы ввода.


Композиция сложных форматов через definitions

Комбинирование нескольких пользовательских символов позволяет формировать доменные языки масок. Например, формат технических идентификаторов:

Inputmask.extendDefinitions({
  'P': { validator: "[A-Z]" },
  'Q': { validator: "[0-9]" },
  'R': { validator: "[A-Z0-9]" }
});

Маска:

Inputmask("PPQQ-RRRR").mask(element);

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


Поведение при удалении и редактировании

При редактировании значения Inputmask повторно применяет определения к уже введенным символам. Это означает, что изменение rules в definitions может повлиять не только на новые данные, но и на существующее содержимое поля при следующей перерисовке маски.


Маскирование как система правил

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

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

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