Структура ISBN опирается на два основных стандарта: ISBN-10 и ISBN-13. Оба варианта представляют собой числовые идентификаторы книг с фиксированным форматом и контрольной цифрой, которая вычисляется по определённому алгоритму. В ISBN-10 последняя позиция может содержать символ X, обозначающий значение 10. В ISBN-13 используется только цифровая последовательность. При работе с пользовательским вводом основная задача маски — обеспечить корректное форматирование, контроль допустимых символов и сохранение структуры с возможными разделителями (дефисами или пробелами).
ISBN-10 состоит из четырёх логических частей:
Типичный вид: 0-306-40615-X
ISBN-13 расширяет формат до EAN-13 и всегда начинается с префикса 978 или 979:
Пример: 978-3-16-148410-0
При реализации маски важно учитывать не только длину, но и возможность вариативного расположения дефисов, а также строгую валидацию символов.
Библиотека Inputmask позволяет задать статическую маску с фиксированными позициями:
import Inputmask from "inputmask";
Inputmask("999-9-99-999999-9").mask("#isbn");
Здесь каждая 9 означает допустимую цифру. Дефисы
задаются как литералы и автоматически фиксируются в поле ввода.
Однако такой вариант подходит только для строго фиксированного формата и не учитывает вариативность группировки, которая встречается в реальных ISBN.
Для практических сценариев лучше использовать опцию определения символов и динамических правил:
Inputmask({
mask: "999-9999-9999-9",
placeholder: "",
showMaskOnHover: false,
showMaskOnFocus: true
}).mask("#isbn");
Такой вариант допускает более равномерное распределение групп, но всё ещё остаётся статическим.
ISBN-10 требует особого подхода, поскольку последняя позиция может
быть цифрой или символом X. В Inputmask это реализуется
через пользовательское определение символа.
Inputmask({
mask: "9-999-99999-9",
definitions: {
"9": {
validator: "[0-9Xx]",
cardinality: 1,
casing: "upper"
}
}
}).mask("#isbn10");
Здесь расширяется стандартное поведение цифры, добавляя возможность
ввода X. Приведение к верхнему регистру обеспечивает
унификацию данных.
Часто требуется одно поле, поддерживающее оба формата. В Inputmask это реализуется через массив масок:
Inputmask({
mask: [
"999-9-999-99999-9",
"9-999-99999-9"
],
keepStatic: true
}).mask("#isbn");
Механизм keepStatic управляет выбором наиболее
подходящей маски в зависимости от введённых символов. Первая маска
обычно соответствует ISBN-13, вторая — ISBN-10.
При вставке данных из внешних источников часто встречаются пробелы и лишние символы. Inputmask позволяет нормализовать ввод:
Inputmask({
mask: "999-9999999999",
autoUnmask: true,
removeMaskOnSubmit: true,
onBeforePaste: function (pastedValue) {
return pastedValue.replace(/[^0-9Xx]/g, "");
}
}).mask("#isbn");
Функция onBeforePaste очищает строку до применения
маски, удаляя все символы, кроме допустимых.
Inputmask предоставляет событие oncomplete, которое
срабатывает при полном заполнении маски:
Inputmask({
mask: "999-9-999-99999-9",
oncomplete: function () {
console.log("ISBN заполнен полностью");
},
onincomplete: function () {
console.log("ISBN введён не полностью");
}
}).mask("#isbn");
Это позволяет отделить частичный ввод от завершённого значения без дополнительной логики проверки длины.
Для программной проверки используется метод isValid:
const im = new Inputmask("999-9-999-99999-9");
im.mask("#isbn");
const element = document.querySelector("#isbn");
function checkISBN() {
return im.isValid(element.value);
}
Такой подход позволяет валидировать значение вне контекста DOM-событий.
При необходимости можно изменять маску в зависимости от длины ввода:
Inputmask({
mask: function () {
return this.value.replace(/\D/g, "").length > 10
? "999-9-999-99999-9"
: "9-999-99999-9";
}
}).mask("#isbn");
Функциональная маска позволяет адаптировать поведение поля без пересоздания экземпляра Inputmask.
ISBN допускает разные варианты отображения дефисов, но структурно
остаётся неизменным. Для управления визуальной частью используется
комбинация greedy и clearIncomplete:
Inputmask({
mask: "999-9999999999-9",
greedy: false,
clearIncomplete: true
}).mask("#isbn");
greedy: false уменьшает агрессивное заполнение маски, а
clearIncomplete очищает незавершённые значения при потере
фокуса.
Для улучшения устойчивости формы применяется обработка события
onincomplete и ручная коррекция:
Inputmask({
mask: "999-9-999-99999-9",
onincomplete: function () {
this.value = this.value.trim();
}
}).mask("#isbn");
Такой механизм полезен при интеграции с формами, где требуется минимизация некорректных отправок.
Inputmask поддерживает регулярные выражения, что позволяет описывать формат более гибко:
Inputmask({
regex: "97(8|9)-[0-9]{1,5}-[0-9]{1,7}-[0-9]{1,7}-[0-9Xx]{1}"
}).mask("#isbn");
Этот вариант ближе к спецификации ISBN, но требует более строгого контроля длины сегментов на стороне логики приложения.
Для хранения в базе данных часто требуется убрать форматирование:
Inputmask({
mask: "999-9-999-99999-9",
autoUnmask: true
}).mask("#isbn");
В результате input.value возвращает только цифры без
дефисов, что упрощает индексацию и поиск.
Маска отвечает за структуру ввода, но не заменяет проверку контрольной суммы ISBN. Обычно используется комбинированный подход:
function validateISBN13(value) {
const digits = value.replace(/\D/g, "");
let sum = 0;
for (let i = 0; i < 12; i++) {
sum += (i % 2 === 0 ? 1 : 3) * parseInt(digits[i], 10);
}
const check = (10 - (sum % 10)) % 10;
return check === parseInt(digits[12], 10);
}
Такой подход разделяет ответственность: Inputmask управляет вводом, алгоритм — математической корректностью.
При работе с реактивными интерфейсами важно учитывать обновление значения извне:
const im = new Inputmask("999-9-999-99999-9");
im.mask("#isbn");
document.querySelector("#setValue").addEventListener("click", () => {
im.setValue("9783161484100");
});
Метод setValue корректно применяет форматирование при
программной установке значения, сохраняя структуру маски.
Очистка значения может быть полностью управляемой:
Inputmask({
mask: "999-9-999-99999-9",
clearMaskOnLostFocus: true
}).mask("#isbn");
При потере фокуса поле очищается, если введённое значение не завершено, что снижает риск отправки неполных данных.
Серверная часть обычно ожидает ISBN без форматирования. Поэтому часто используется комбинация:
autoUnmask: trueremoveMaskOnSubmit: trueInputmask({
mask: "999-9-999-99999-9",
autoUnmask: true,
removeMaskOnSubmit: true
}).mask("#isbn");
Это обеспечивает передачу «чистого» значения без необходимости дополнительной обработки на сервере.