Tom Sel ect представляет собой JavaScript-библиотеку для расширения
стандартного элемента <select> с целью добавления
функциональности поиска, множественного выбора, динамической подгрузки
данных и кастомного отображения элементов. Библиотека построена с
акцентом на минимальную зависимость от внешних фреймворков, гибкость API
и расширяемость через плагины.
Основная идея заключается в замене ограниченного поведения нативного
HTML <select> на управляемый компонент с
поддержкой:
Подключение Tom Select возможно через npm или CDN.
npm install tom-select
import TomSelect fr om "tom-select";
import "tom-select/dist/css/tom-select.css";
<select id="select-beast">
<option value="1">Dragon</option>
<option value="2">Unicorn</option>
<option value="3">Phoenix</option>
</select>
new TomSelect("#select-beast");
После инициализации DOM-элемент заменяется управляемым компонентом с отдельной структурой ввода, списка и контейнеров выбранных значений.
Конструктор принимает второй аргумент с набором опций, определяющих поведение компонента.
new TomSelect("#select-beast", {
maxItems: 3,
create: false,
searchField: ["text", "value"],
placeholder: "Выбор сущности"
});
maxItems — ограничение количества выбранных
элементовcreate — разрешение создания новых опцийsearchField — поля для поискаplaceholder — текст-заполнительvalueField, labelField,
options — структура данных при динамической
инициализацииTom Select поддерживает два основных режима данных: статический и динамический.
new TomSelect("#select-beast", {
options: [
{ id: 1, name: "Lion" },
{ id: 2, name: "Tiger" }
],
valueField: "id",
labelField: "name",
searchField: "name"
});
Поддерживается загрузка через load callback.
new TomSelect("#select-beast", {
valueField: "id",
labelField: "title",
searchField: "title",
load: function(query, callback) {
fetch(`/api/items?q=${encodeURIComponent(query)}`)
.then(res => res.json())
.then(data => callback(data))
.catch(() => callback());
}
});
Асинхронная модель предполагает явный вызов callback для завершения загрузки, что позволяет интегрировать любые источники данных.
Функциональность создания новых опций активируется через параметр
create.
new TomSelect("#select-beast", {
create: true
});
Дополнительно возможно переопределение логики создания:
new TomSelect("#select-beast", {
create: function(input) {
return {
value: input.toLowerCase(),
text: input
};
}
});
Созданные элементы интегрируются в текущий список и могут быть выбраны как обычные опции.
Режим множественного выбора активируется через HTML-атрибут
multiple или опцию maxItems.
<select id="tags" multiple>
<option value="js">JavaScript</option>
<option value="ts">TypeScript</option>
</select>
new TomSelect("#tags", {
maxItems: null
});
При множественном выборе элементы отображаются в виде токенов, управляемых через внутренний state-компонент.
Поиск осуществляется по полям, заданным в searchField.
Алгоритм основан на фильтрации строк и может быть расширен.
new TomSelect("#select-beast", {
searchField: ["title", "description"]
});
Поддерживается кастомизация поведения поиска через переопределение
метода score.
new TomSelect("#select-beast", {
score: function(search) {
return function(item) {
return item.label.toLowerCase().includes(search.toLowerCase())
? 1
: 0;
};
}
});
Tom Select предоставляет систему шаблонов для управления отображением элементов.
item — выбранный элементoption — элемент спискаdropdown — контейнер спискаoptgroup_header — заголовок группыnew TomSelect("#select-beast", {
render: {
option: function(data, escape) {
return `<div>${escape(data.text)}</div>`;
},
item: function(data, escape) {
return `<div class="item">${escape(data.text)}</div>`;
}
}
});
Функция escape используется для защиты от XSS при
вставке пользовательских данных.
Поддерживается стандартная HTML-модель группировки:
new TomSelect("#select-beast", {
optgroups: [
{ value: "mammals", label: "Mammals" },
{ value: "birds", label: "Birds" }
],
options: [
{ value: "lion", text: "Lion", optgroup: "mammals" },
{ value: "eagle", text: "Eagle", optgroup: "birds" }
]
});
Группы визуально разделяют список и позволяют структурировать большие наборы данных.
Компонент предоставляет набор событий для отслеживания состояния.
change — изменение выбранных значенийitem_add — добавление элементаitem_remove — удаление элементаdropdown_opendropdown_closefocusblurconst ts = new TomSelect("#select-beast");
ts.on("change", value => {
console.log(value);
});
События позволяют синхронизировать состояние с внешними системами управления данными.
После инициализации доступен программный интерфейс управления.
const ts = new TomSelect("#select-beast");
setValue(value) — установка значенияgetValue() — получение текущего значенияaddItem(value) — добавление элементаremoveItem(value) — удаление элементаclear() — очистка выбораclearOptions() — очистка списка опцийdestroy() — уничтожение экземпляраts.setValue(["1", "2"]);
ts.addItem("3");
ts.clear();
Внутреннее состояние Tom Select основано на синхронизации:
Любое изменение проходит через централизованные методы обновления, что исключает прямое вмешательство в DOM без синхронизации состояния.
Архитектура поддерживает подключение плагинов для расширения функциональности.
new TomSelect("#select-beast", {
plugins: ["remove_button"]
});
Плагины могут:
При работе с удалёнными API часто используется задержка ввода:
new TomSelect("#select-beast", {
loadThrottle: 300
});
Это снижает количество запросов при вводе текста и улучшает производительность при интеграции с серверными поисковыми системами.
Компонент генерирует собственную DOM-структуру:
Классы элементов позволяют полностью переопределять визуальное представление через CSS без изменения логики.
.ts-control {
border: 1px solid #ccc;
}
.ts-dropdown {
max-height: 300px;
overflow: auto;
}
Tom Select часто используется как слой UI поверх API:
Типичная схема интеграции включает:
callbackПри больших списках ключевое значение имеет:
Оптимизация достигается через контроль load,
score и render функций, где можно снижать
вычислительную сложность поиска и рендера.
Компонент управляет состояниями:
Взаимодействие основано на обработчиках событий клавиатуры и мыши, включая навигацию стрелками и выбор через Enter.