Поведение удаления в мультиселект-интерфейсах часто требует обратимого действия: пользователь удаляет последний выбранный элемент и ожидает, что он не исчезнет полностью, а вернётся в поле ввода для немедленного редактирования. В Tom Select это реализуется через механизм восстановления последнего элемента при нажатии Backspace в пустом поле ввода.
Ключевая логика основана на перехвате клавиатурного события и анализе состояния инпута: если текст отсутствует и курсор находится в начале строки, Backspace интерпретируется не как удаление символа, а как команда на извлечение последнего выбранного элемента из коллекции.
Внутри Tom Select обработка клавиатуры централизована. Событие
keydown анализируется на уровне основного input-элемента.
Для Backspace применяется дополнительная проверка состояния:
При совпадении условий инициируется логика “restore”.
input.addEventListener('keydown', function(e) {
if (e.key === 'Backspace') {
if (self.items.length && !self.inputValue.length) {
self.restoreLastItem();
e.preventDefault();
}
}
});
Фактическая реализация в библиотеке более сложная, но концептуально опирается на этот паттерн.
Функция восстановления не просто удаляет элемент из массива выбранных значений. Она выполняет обратную операцию по отношению к стандартному добавлению:
this.itemsrestoreLastItem() {
const value = this.items.pop();
const option = this.options[value];
this.removeItem(value, true);
this.setTextboxValue(option.text);
this.refreshOptions();
}
Главная идея заключается в том, что пользователь не теряет контекст: удалённый элемент становится редактируемым значением.
Tom Select использует модульную систему плагинов, где restore-on-backspace подключается как независимое расширение поведения.
new TomSelect('#select', {
plugins: ['restore_on_backspace']
});
При инициализации плагин регистрирует обработчики клавиатуры и расширяет стандартный цикл обработки input-событий.
В некоторых конфигурациях плагин комбинируется с другими расширениями:
new TomSelect('#select', {
plugins: [
'remove_button',
'restore_on_backspace'
]
});
В таком случае поведение удаления через кнопку и через клавиатуру становится согласованным.
Наиболее заметный эффект проявляется в multiple режиме.
При отсутствии restore-on-backspace стандартное поведение выглядит
так:
С включённым механизмом:
Это делает интерфейс ближе к “редактируемым тегам”, а не к статичному списку.
Критическим условием является состояние каретки. Если курсор не в начале строки, Backspace ведёт себя стандартно — удаляет символы.
Логика упрощённо:
if (input.selectionStart === 0 && input.value === '') {
restoreLastItem();
}
Это предотвращает конфликт между редактированием текста и управлением выбранными значениями.
При включённой опции create: true восстановленный
элемент может сразу становиться редактируемым новым значением.
new TomSelect('#select', {
create: true,
plugins: ['restore_on_backspace']
});
Сценарий:
Таким образом достигается псевдо-undo без отдельной истории изменений.
При активном hideSelected поведение становится более
контекстным. Поскольку выбранные элементы скрываются из dropdown,
восстановление через Backspace фактически возвращает их в доступный
список.
new TomSelect('#select', {
hideSelected: true,
plugins: ['restore_on_backspace']
});
Логика обновления списка опций должна учитывать синхронизацию скрытых элементов после восстановления.
При ограничении maxItems восстановление становится
способом “переноса” элемента обратно в input для замены:
new TomSelect('#select', {
maxItems: 3,
plugins: ['restore_on_backspace']
});
Если лимит достигнут, восстановленный элемент может быть повторно добавлен только после удаления или модификации текущего состояния.
При добавлении пользовательских обработчиков клавиатуры важно учитывать порядок выполнения. Tom Select обрабатывает события до или после внешних listeners в зависимости от capture-фазы.
Типичный конфликт:
Решение заключается в контроле preventDefault и проверке
состояния input до выполнения пользовательской логики.
На мобильных устройствах и при использовании IME (например, азиатских методов ввода) поведение Backspace может отличаться:
Поэтому в ряде реализаций добавляется дополнительная проверка через
input event, а не только keydown.
Tom Select поддерживает три связанных слоя состояния:
items — выбранные значенияoptions — доступные элементыinputValue — текущее значение поляrestore_on_backspace синхронизирует эти слои следующим образом:
items уменьшается на 1inputValueoptions обновляется через
refreshOptionsЛюбая рассинхронизация приводит к визуальным артефактам: “потерянным” тегам или дублированию.
В некоторых кастомных сборках добавляется дополнительная семантика:
Пример кастомного расширения:
TomSelect.define('smart_restore', function(options) {
this.onKeyD own = (function() {
const original = this.onKeyDown;
return function(e) {
if (e.key === 'Backspace' && this.items.length > 0 && this.inputValue === '') {
if (this.items.length > 1) {
this.restoreLastItem();
}
return;
}
return original.apply(this, arguments);
};
})();
});
С точки зрения взаимодействия с интерфейсом, восстановление через Backspace превращает поле выбора в гибрид между текстовым редактором и списком тегов. Последний выбранный элемент становится частью редактируемого потока, а не статичной сущностью.
Такой подход особенно полезен в сценариях:
При этом важно учитывать риск случайного восстановления при быстром удалении нескольких элементов подряд, что может требовать дополнительной задержки или debounce-логики на уровне событий клавиатуры.