Синтаксис создания собственных масок

Библиотека Cleave.js позволяет создавать динамические маски ввода на основе набора правил. В основе механизма лежит разделение значения на блоки (blocks) и применение разделителей (delimiters) либо специальных обработчиков.

Собственная маска строится вокруг следующих параметров:

new Cleave('.input-element', {
    blocks: [4, 4, 4, 4],
    delimiter: '-'
});

Результат:

1234-5678-9012-3456

Массив blocks определяет длину каждой части строки, а delimiter — символ-разделитель между ними.


Базовый синтаксис пользовательской маски

Минимальная конфигурация включает:

new Cleave(selector, {
    blocks: [],
    delimiter: ''
});

Основные свойства

Свойство Назначение
blocks размеры сегментов
delimiter единый разделитель
delimiters массив разных разделителей
uppercase автоматический upper-case
lowercase автоматический lower-case
numericOnly разрешение только цифр
prefix фиксированный префикс
noImmediatePrefix отложенный вывод префикса
rawValueTrimPrefix удаление префикса из rawValue

Простая текстовая маска

Пример пользовательского идентификатора:

new Cleave('.code-input', {
    blocks: [3, 3, 3],
    delimiter: ':',
    uppercase: true
});

Формат:

ABC:DEF:GHI

Что происходит внутри

  1. Пользователь вводит символы
  2. Cleave.js распределяет их по блокам
  3. После заполнения блока добавляется разделитель
  4. Значение автоматически преобразуется в верхний регистр

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

Если требуется несколько различных разделителей:

new Cleave('.serial-input', {
    blocks: [2, 4, 2, 6],
    delimiters: ['-', '/', '#']
});

Результат:

12-3456/78#123456

Принцип работы

Количество элементов в delimiters должно быть на единицу меньше количества блоков.

Фактически:

blocks.length - 1 === delimiters.length

Маски фиксированной структуры

Номер документа

new Cleave('.passport', {
    blocks: [2, 2, 6],
    delimiters: [' ', '-'],
    uppercase: true
});

Результат:

AB 12-123456

Использование numericOnly

Свойство numericOnly запрещает ввод любых нечисловых символов.

new Cleave('.numeric-code', {
    blocks: [5, 5],
    delimiter: '-',
    numericOnly: true
});

Попытка ввода:

12AB345

Превратится в:

12345

Сложные комбинированные маски

Маска лицензии

new Cleave('.license', {
    prefix: 'LIC',
    blocks: [3, 4, 4],
    delimiters: ['-', '-'],
    uppercase: true
});

Результат:

LIC-ABCD-1234

Особенности prefix

Стандартное поведение

new Cleave('.invoice', {
    prefix: 'INV',
    blocks: [3, 6],
    delimiter: '-'
});

Поле сразу содержит:

INV-

Отключение немедленного вывода

new Cleave('.invoice', {
    prefix: 'INV',
    noImmediatePrefix: true,
    blocks: [3, 6],
    delimiter: '-'
});

Теперь префикс появится только после начала ввода.


Управление rawValue

Cleave.js хранит два значения:

Тип Описание
formatted value отображаемое значение
rawValue значение без форматирования

Пример:

new Cleave('.bank-code', {
    blocks: [4, 4, 4],
    delimiter: '-'
});

Ввод:

1234-5678-9999

rawValue:

123456789999

Получение значения:

const cleave = new Cleave('.bank-code', {
    blocks: [4, 4, 4],
    delimiter: '-'
});

console.log(cleave.getRawValue());

Комбинация uppercase и lowercase

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

Верхний регистр

new Cleave('.upper', {
    blocks: [4, 4],
    delimiter: '-',
    uppercase: true
});

Нижний регистр

new Cleave('.lower', {
    blocks: [4, 4],
    delimiter: '-',
    lowercase: true
});

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

Неполное заполнение

new Cleave('.partial', {
    blocks: [2, 2, 2, 2],
    delimiter: '-'
});

Во время ввода:

12-
12-34-
12-34-56-

Маска формируется постепенно.


Маски без разделителей

new Cleave('.compact', {
    blocks: [4, 4, 4]
});

Разделители отсутствуют, но ограничение длины блоков сохраняется.


Ограничение длины пользовательского формата

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

blocks: [3, 3, 3]

Максимум:

9 символов

Если используется delimiter:

delimiter: '-'

Отображаемая длина:

11 символов

Но rawValue остаётся длиной 9.


Вложенная логика пользовательских масок

Маска может изменяться динамически.

Пример смены структуры

const cleave = new Cleave('.dynamic', {
    blocks: [4, 4],
    delimiter: '-'
});

document.querySelector('.dynamic')
    .addEventListener('input', function(e) {

        if (e.target.rawValue.length > 8) {

            cleave.destroy();

            new Cleave('.dynamic', {
                blocks: [4, 4, 4],
                delimiter: '-'
            });
        }
    });

Маски для внутренних идентификаторов

Формат отдела и сотрудника

new Cleave('.employee-id', {
    blocks: [2, 3, 5],
    delimiters: ['/', '-'],
    uppercase: true
});

Результат:

HR/452-98125

Использование нескольких инстансов

const inputs = document.querySelectorAll('.masked');

inputs.forEach(input => {

    new Cleave(input, {
        blocks: [3, 3, 3],
        delimiter: '.'
    });

});

Удаление маски

Метод destroy() удаляет обработчики и форматирование.

const cleave = new Cleave('.field', {
    blocks: [4, 4],
    delimiter: '-'
});

cleave.destroy();

Поведение курсора

Cleave.js автоматически корректирует позицию курсора при:

  • вставке текста;
  • удалении символов;
  • вставке разделителей;
  • изменении структуры маски.

Это особенно важно для сложных пользовательских шаблонов.


Маски с нестандартными разделителями

Использование Unicode-символов

new Cleave('.unicode-mask', {
    blocks: [2, 2, 2],
    delimiters: ['•', '→']
});

Результат:

12•34→56

Маски для HEX-кодов

new Cleave('.hex-input', {
    blocks: [2, 2, 2],
    delimiter: ':',
    uppercase: true
});

Результат:

AF:45:1C

Формирование MAC-адресов

new Cleave('.mac-address', {
    blocks: [2, 2, 2, 2, 2, 2],
    delimiter: ':',
    uppercase: true
});

Результат:

AA:BB:CC:DD:EE:FF

Обработка вставки из буфера

При вставке строки Cleave.js:

  1. удаляет лишние символы;
  2. применяет ограничения блоков;
  3. повторно строит формат;
  4. нормализует разделители.

Пример:

Буфер:

123456789012

Маска:

blocks: [4, 4, 4],
delimiter: '-'

Результат:

1234-5678-9012

Использование onValueChanged

Обработчик позволяет реагировать на изменение значения.

new Cleave('.tracking', {

    blocks: [4, 4, 4],
    delimiter: '-',

    onValueChanged: function(event) {

        console.log(event.target.value);
        console.log(event.target.rawValue);

    }

});

Создание универсального генератора масок

function createMask(selector, config) {

    return new Cleave(selector, {
        blocks: config.blocks,
        delimiters: config.delimiters,
        delimiter: config.delimiter,
        uppercase: config.uppercase,
        numericOnly: config.numericOnly
    });

}

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

createMask('.product-code', {
    blocks: [3, 5, 2],
    delimiters: ['-', '/'],
    uppercase: true
});

Частые ошибки при создании пользовательских масок

Несоответствие blocks и delimiters

Ошибка:

blocks: [2, 2, 2],
delimiters: ['-']

Правильно:

blocks: [2, 2, 2],
delimiters: ['-', '-']

Конфликт uppercase и lowercase

Ошибка:

uppercase: true,
lowercase: true

Использоваться должен только один режим.


Отсутствие numericOnly для цифровых масок

Без этого параметра пользователь сможет вводить текст.


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

Наиболее затратные операции:

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

Оптимизация

Хорошая практика:

const config = {
    blocks: [4, 4, 4],
    delimiter: '-'
};

document.querySelectorAll('.mask')
    .forEach(el => new Cleave(el, config));

Интеграция с формами

const cleave = new Cleave('.payment-id', {
    blocks: [4, 4, 4],
    delimiter: '-'
});

form.addEventListener('submit', function() {

    hiddenInput.value = cleave.getRawValue();

});

В интерфейсе отображается форматированное значение, а на сервер отправляется очищенная строка.


Создание адаптивных масок

Маска по типу документа

function buildMask(type) {

    switch(type) {

        case 'passport':

            return {
                blocks: [2, 2, 6],
                delimiters: [' ', '-']
            };

        case 'tax':

            return {
                blocks: [3, 3, 3],
                delimiter: '.'
            };

    }

}

Работа с HTML-атрибутами

<input
    type="text"
    class="serial"
/>
new Cleave('.serial', {
    blocks: [5, 5],
    delimiter: '-'
});

Инициализация через DOM-элемент

const input = document.querySelector('.device-id');

new Cleave(input, {
    blocks: [4, 4, 4],
    delimiter: ':'
});

Полная пользовательская конфигурация

new Cleave('.advanced-mask', {

    prefix: 'SYS',

    noImmediatePrefix: true,

    blocks: [3, 4, 4, 2],

    delimiters: ['-', '/', '#'],

    uppercase: true,

    onValueChanged: function(event) {

        console.log(event.target.value);

    }

});

Результат:

SYS-ABCD/1234#99