Vanilla JavaScript

Tom Select представляет собой легковесную библиотеку, построенную поверх стандартного HTML <select> и предназначенную для расширения его возможностей без привязки к фреймворкам. В режиме Vanilla JavaScript библиотека подключается напрямую через CDN или локальный файл и инициализируется на уже существующих DOM-элементах.

Базовая модель работы строится вокруг преобразования стандартного элемента формы в управляемый компонент с внутренним состоянием, событиями и API для манипуляции списком опций.

Подключение и базовая инициализация

Минимальная интеграция выполняется через подключение CSS и JS файлов библиотеки:

<link rel="stylesheet" href="tom-select.default.css">
<script src="tom-select.complete.js"></script>

После загрузки DOM выполняется инициализация:

<select id="countries">
  <option value="kz">Kazakhstan</option>
  <option value="ru">Russia</option>
  <option value="us">USA</option>
</select>
new TomSelect("#countries");

При создании экземпляра происходит:

  • скрытие оригинального <select>
  • построение кастомного dropdown-интерфейса
  • привязка событий ввода и выбора
  • синхронизация состояния между UI и DOM

Внутренняя модель данных

Каждый экземпляр Tom Select хранит внутреннее представление опций в виде нормализованного массива объектов:

[
  { value: "kz", text: "Kazakhstan" },
  { value: "ru", text: "Russia" }
]

Эта структура используется для:

  • фильтрации
  • поиска
  • рендера списка
  • управления выбранными значениями

Состояние выбора отделено от DOM и обновляется через API, что снижает количество прямых манипуляций с HTML.

Конфигурация экземпляра

Инициализация принимает объект настроек, влияющий на поведение компонента:

new TomSelect("#countries", {
  maxItems: 1,
  create: false,
  searchField: ["text"]
});

Основные параметры

  • maxItems — ограничение количества выбранных значений
  • create — разрешение добавления новых опций пользователем
  • searchField — поля объекта, участвующие в поиске
  • placeholder — текст-подсказка
  • closeAfterSelect — закрытие dropdown после выбора

Каждый параметр влияет на внутренние алгоритмы фильтрации и рендера.

Механизм поиска и фильтрации

Поиск реализуется через проход по массиву опций и сравнении строки ввода с заданными полями:

query -> normalize -> match -> score -> sort

Алгоритм включает:

  • приведение строки к нижнему регистру
  • разбиение по токенам
  • частичное совпадение
  • приоритизацию точных совпадений

Пример настройки поиска:

new TomSelect("#countries", {
  searchField: ["text", "value"]
});

Динамическое добавление и удаление опций

API позволяет изменять список опций без перезагрузки страницы.

Добавление:

const select = new TomSelect("#countries");

select.addOption({
  value: "de",
  text: "Germany"
});

select.refreshOptions(false);

Удаление:

select.removeOption("de");

При изменении списка происходит пересборка внутреннего индекса поиска.

Управление выбранными значениями

В Vanilla JavaScript режиме управление осуществляется через методы экземпляра:

select.setValue("kz");
select.addItem("ru");
select.removeItem("us");

Разница между уровнями:

  • setValue — полная замена выбора
  • addItem — добавление без сброса
  • removeItem — удаление конкретного значения

Каждое действие вызывает синхронизацию с оригинальным <select>.

Обработка событий

Система событий построена поверх EventEmitter-подобной модели:

const select = new TomSelect("#countries");

select.on("change", (value) => {
  console.log(value);
});

Основные события:

  • change — изменение выбранных значений
  • item_add — добавление элемента
  • item_remove — удаление элемента
  • dropdown_open — открытие списка
  • dropdown_close — закрытие списка
  • type — ввод текста

События позволяют интегрировать компонент в произвольную бизнес-логику.

Асинхронная загрузка данных

Поддерживается режим динамической подгрузки через load:

new TomSelect("#countries", {
  load: function(query, callback) {
    fetch("/api/countries?q=" + query)
      .then(res => res.json())
      .then(data => callback(data));
  }
});

Механизм работает следующим образом:

  • ввод пользователя инициирует запрос
  • библиотека передает query в callback
  • результат нормализуется в формат опций
  • обновляется список dropdown

Рендеринг интерфейса

UI состоит из нескольких ключевых компонентов:

  • input-поле
  • контейнер выбранных элементов
  • dropdown список
  • overlay для фокуса

Каждый элемент создается динамически и обновляется при изменении состояния.

Виртуального DOM нет — обновления происходят через прямые манипуляции с DOM, но оптимизированы через батчинг изменений.

Кастомизация шаблонов

В Vanilla JavaScript режиме доступны шаблоны рендера:

new TomSelect("#countries", {
  render: {
    option: function(data, escape) {
      return `<div>${escape(data.text)}</div>`;
    },
    item: function(data, escape) {
      return `<div class="item">${escape(data.text)}</div>`;
    }
  }
});

Шаблоны позволяют:

  • изменять структуру option
  • добавлять иконки и метаданные
  • внедрять сложную разметку

Функция escape защищает от XSS при выводе данных.

Работа с формами

Компонент полностью совместим с HTML формами. При сабмите:

  • значение передается как обычный <select>
  • multiple режим формирует массив значений
  • disabled состояние блокирует взаимодействие

Пример:

<form>
  <select id="countries" name="country"></select>
  <button type="submit">Send</button>
</form>
new TomSelect("#countries", {
  maxItems: 3
});

Оптимизация производительности

При работе с большими списками применяются стратегии:

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

Особенно критично при списках от 1000+ элементов, где фильтрация и DOM-операции становятся узким местом.

Состояние и синхронизация DOM

Каждое изменение проходит через слой синхронизации:

  1. изменение внутреннего state
  2. обновление UI
  3. обновление <select>
  4. триггер событий

Эта цепочка гарантирует консистентность данных между формой и компонентом.

Уничтожение экземпляра

Удаление компонента выполняется через:

select.destroy();

Процесс включает:

  • восстановление оригинального <select>
  • удаление всех событий
  • очистку DOM-обертки
  • освобождение памяти

Механизм важен при SPA-навигации и динамических интерфейсах, где компоненты часто пересоздаются.