Drag and drop для сортировки

Функциональность перетаскивания элементов в интерфейсах выбора основана на возможности изменять порядок уже выбранных значений без необходимости их удаления и повторного добавления. В Tom Select этот механизм реализуется через плагин drag_drop, который добавляет поддержку сортировки выбранных элементов непосредственно внутри поля выбора.

Основой работы является расширение поведения компонента, при котором каждый выбранный элемент становится draggable-узлом внутри контейнера значений. При изменении порядка библиотека синхронизирует внутреннее состояние массива выбранных значений с новым визуальным порядком.

Активация механизма выполняется подключением встроенного плагина:

new TomSelect('#select', {
    plugins: ['drag_drop'],
    maxItems: null
});

После подключения каждый выбранный элемент становится доступен для перетаскивания. Пользователь может менять порядок значений мышью или жестами на тач-устройствах, а библиотека автоматически обновляет внутреннюю модель данных.

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

Внутренняя модель сортировки

Tom Select хранит выбранные значения в виде массива. При использовании drag and drop изменяется именно порядок этого массива, а не только DOM-представление.

Принцип работы можно описать следующим образом:

  1. Пользователь инициирует перетаскивание элемента.
  2. Элемент временно фиксируется как активный drag-узел.
  3. При перемещении отслеживается позиция относительно соседних элементов.
  4. После завершения перетаскивания выполняется перестановка в массиве значений.
  5. Срабатывает обновление состояния компонента.

Таким образом, визуальное изменение порядка всегда синхронизировано с данными формы.

Поведение при множественном выборе

В режиме multiple drag and drop сортировка приобретает ключевое значение, так как порядок элементов становится частью семантики данных.

new TomSelect('#select', {
    plugins: ['drag_drop'],
    maxItems: 10
});

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

  • сериализацию формы;
  • отправку данных на сервер;
  • отображение в UI после повторной инициализации.

При повторной загрузке значения восстанавливаются в том же порядке, в котором они были сохранены.

Стилизация перетаскиваемых элементов

Плагин добавляет специальные CSS-классы, которые позволяют управлять состояниями элементов во время drag операции. Основные состояния:

  • элемент в процессе перетаскивания;
  • потенциальная позиция вставки;
  • контейнер активного взаимодействия.

Пример пользовательской стилизации:

.ts-wrapper .item {
    cursor: grab;
}

.ts-wrapper .item.dragging {
    opacity: 0.6;
    cursor: grabbing;
}

.ts-wrapper .item.drop-before {
    border-left: 2px solid #4a90e2;
}

Изменение внешнего вида важно для повышения предсказуемости интерфейса, особенно при большом количестве выбранных элементов.

Синхронизация с внешними данными

При интеграции с сервером или сторонними формами необходимо учитывать, что порядок элементов имеет значение и должен сериализоваться корректно.

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

const select = new TomSelect('#select', {
    plugins: ['drag_drop']
});

const value = select.getValue();

В режиме multiple возвращается массив значений в актуальном порядке после сортировки.

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

<select id="select" multiple>
    <option value="1">A</option>
    <option value="2">B</option>
    <option value="3">C</option>
</select>

После drag and drop порядок в DOM синхронизируется с внутренним состоянием, что обеспечивает корректную отправку через стандартный form submit.

Особенности работы с сортировкой и поиском

При включённом поиске (режим фильтрации опций) drag and drop действует только на уже выбранные элементы. Поисковый список не участвует в сортировке, что предотвращает конфликт между фильтрацией и изменением порядка.

Однако важно учитывать:

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

Ограничения и предсказуемость поведения

Сортировка drag and drop в Tom Select имеет ряд ограничений, обусловленных архитектурой компонента:

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

При использовании кастомных render-функций важно сохранять структуру элементов, так как изменение шаблона может повлиять на корректность drag-событий.

Интеграция с кастомным рендерингом

Tom Select позволяет переопределять отображение выбранных элементов через render:

new TomSelect('#select', {
    plugins: ['drag_drop'],
    render: {
        item: function(data, escape) {
            return `<div class="item-custom">${escape(data.text)}</div>`;
        }
    }
});

При этом важно сохранять возможность перетаскивания, не блокируя pointer-events и не изменяя контейнерные элементы так, чтобы нарушалась структура сортируемого узла.

Поведение на мобильных устройствах

На touch-устройствах drag and drop реализуется через обработку touch-событий. Логика остаётся аналогичной десктопной версии, но взаимодействие происходит через длительное удержание и перемещение пальцем.

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

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

Событийная модель

Во время сортировки могут использоваться события компонента, связанные с изменением состояния:

  • изменение порядка выбранных элементов;
  • обновление значения компонента;
  • завершение drag операции.

Типичный сценарий обработки:

new TomSelect('#select', {
    plugins: ['drag_drop'],
    onChange: function(value) {
        console.log('Новое состояние:', value);
    }
});

Любое изменение порядка приводит к вызову обновления состояния, что позволяет синхронизировать UI с внешними системами управления данными.

Производительность при большом количестве элементов

При работе с большим числом выбранных значений drag and drop может создавать нагрузку на DOM из-за постоянных перерасчётов позиций элементов. В таких сценариях критичны:

  • минимизация кастомной вложенности элементов;
  • отказ от сложных CSS-анимаций во время drag;
  • ограничение количества одновременно выбранных элементов.

Tom Select оптимизирует перестроение списка, но основная нагрузка остаётся на браузере, так как сортировка происходит на уровне DOM.

Поведение при программной модификации порядка

Помимо пользовательского drag and drop, порядок можно изменять программно через обновление значения:

select.setValue(['3', '1', '2']);

В этом случае визуальный порядок перестраивается автоматически, полностью соответствуя переданному массиву. Это позволяет синхронизировать серверный порядок с клиентским интерфейсом без ручного вмешательства пользователя.

При комбинировании программной сортировки и drag and drop приоритет всегда остаётся за последним изменением состояния, так как пользовательское действие перезаписывает порядок массива значений.