IMaskjs — простое маскирование в браузере

f59c78735ab544ef847dfc092b58526d.jpg

Нам нужна была работающая и удобная библиотека без зависимостей для маскирования ввода — и мы ее сделали. Через полгода с момента выпуска нулевой версии была выпущена версия 1.0 с многочисленными изменениями и улучшениями:

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


В качестве предисловия


Для меня это первый опыт активного участия в opensource, и я для себя сделал несколько выводов.

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

Нужно больше примеров кода и демо. Страница проекта и документация полностью переработаны.

Нужны рабочие варианты из коробки. Добавлены новые маски и примеры использования.

На мобильных устройствах в настоящее время заставить работать курсор правильно невозможно. Буду рад, если докажете обратное. Все библиотеки, изменяющие ввод стоят перед выбором: сделать удобно для десктопа или чтобы работало на мобильных устройствах. Мы выбрали первое. Чтобы работало на мобильных устройствах необходимо учитывать не только платформы и многочисленные браузеры, но также широкий ассортимент виртуальных клавиатур со своими особенностями. Короче говоря, если хотите чтобы работало — не трогайте курсор при вводе. Серьезно, проверьте сами — так и делают (хотя может они тупо забили). В IMaskjs мы сделали достаточно сложное позиционирование курсора для удобства на десктопе с небольшим хаком под мобильные платформы. Хак известный и заключается в том, чтобы устанавливать курсор с небольшой задержкой после ввода — получилось не сильно лучше, но где-то заработало.

Что нового


Библиотека увеличилась в объеме в 2 раза в основном за счет нового функционала. Наиболее значимым дополнением стали маски для работы с числами и датами:

var numberMask = new IMask(inputElement, {
    mask: Number,
    min: -10000,
    max: 10000,
    thousandsSeparator: ' '
});

var dateMask = new IMask(inputElement, {
    mask: Date,
    min: new Date(2000, 0, 1),
    max: new Date(2020, 0, 1),
    placeholder: {lazy: false}
});


→ Демо тут

Фактически маска для ввода чисел — это надстройка над регулярками. А маска для ввода дат — надстройка над шаблонами. Т.к. дата состоит из условно независимых частей — дня, месяца и года, то для удобства переиспользования маски хотелось иметь возможность отдельной настройки независимых частей маски. Проблема была решена введением групп, которые являются частью основной маски, но также предоставляют возможность независимой обработки значений. Как-то так:

var groupsMask = new IMask(inputElement, {
  mask: '19YY.MM.DD',

  // описание групп
  groups: {
    // общее описание группы
    YY: {
      mask: '00',
      // возможно использование валидатора
      // validate: function (value, group) {}
    },

    // но можно создавать группы из интервала значений или перечислений
    MM: new IMask.MaskedPattern.Group.Range([1, 12]),
    DD: new IMask.MaskedPattern.Group.Range([1, 31])
  }
});


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

В процессе рефакторинга также были выделены модель и представление. Модель предоставляет все возможности маскирования без UI. А представление «склеивает» dom-элемент и модель маски, обеспечивая реагирование на события и обновление элемента. Также довольно просто добавить собственные обработчики событий, например, для поддержки старых браузеров (из коробки поддерживаем IE11+).

Планы на будущее


Ближайшие планы — сделать возможность использовать несколько масок, меняющихся на лету, например, ввод телефона и email. Также возможно появятся плагины под любимые фреймворки.
Мы призадумались, а зачем мы вообще все это делаем, присмотрелись к cleave и text-mask — они ведь тоже хороши в принципе. Конечно каждый выберет свое, но нам наша маска нравится больше.

Несмотря на то, что библиотека неплохо работает в проде с несколькими сотнями тысяч активных пользователей, по-прежнему нет нормальных тестов и 0 issues на github))) Стыд и позор, нет слов. Исправляемся.

© Habrahabr.ru