Перейти к содержимому

Sort

Плагин Sort позволяет легко изменять порядок элементов, перетаскивая их мышью.

Эта функциональность полезна для таких вещей, как доски Kanban, списки дел, сортируемые столбцы таблицы и т. д.

Функциональность перетаскивания, используемая в этом плагине, обеспечивается проектом SortableJS.

Установка

Вы можете использовать этот плагин, включив его из тега <script> или установив с помощью менеджера пакетов.

Через CDN

Вы можете подключить CDN-сборку этого плагина с помощью тега <script>, только подключать нужно ДО основного JS-файла Alpine.

<!-- Sort Plugin -->
<script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/sort@3/dist/cdn.min.js"></script>
<!-- Alpine Core -->
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3/dist/cdn.min.js"></script>

Через менеджер пакетов

Вы можете установить Sort для использования внутри вашей сборки следующим образом:

Окно терминала
npm i @alpinejs/sort

Затем инициализируйте его в своей сборке:

import Alpine from 'alpinejs';
import sort from '@alpinejs/sort';
Alpine.plugin(sort);
Alpine.start();

Использование

Основным API для использования этого плагина является директива x-sort. Добавив x-sort к элементу, его дочерние элементы, имеющие атрибут x-sort:item, становятся сортируемыми - то есть вы можете перетаскивать их мышью, и они будут менять положение.

<div x-data>
<ul x-sort>
<li x-sort:item>кошка</li>
<li x-sort:item>мышка</li>
<li x-sort:item>собака</li>
</ul>
</div>
  • кошка
  • мышка
  • собака

Обработчики сортировки

Можно реагировать на изменения сортировки, передавая функцию-обработчик x-sort и добавляя ключи к каждому элементу с помощью x-sort:item. Вот пример простой функции-обработчика, которая показывает диалоговое окно с изменённым ключом элемента и его новой позицией:

<div x-data>
<ul x-sort="alert($item + ' - ' + $position)">
<li x-sort:item="1">кошка</li>
<li x-sort:item="2">мышка</li>
<li x-sort:item="3">собака</li>
</ul>
</div>
  • кошка
  • мышка
  • собака

Обработчик x-sort будет вызываться каждый раз, когда порядок сортировки элементов изменится. Магическое свойство $item будет содержать ключ отсортированного элемента (полученный из x-sort:item), а $position будет содержать новую позицию элемента (начиная с индекса 0).

Вы также можете передать функцию-обработчик в x-sort, и эта функция получит item и position в качестве первого и второго параметров:

<div x-data="{ handle: (item, position) => { ... } }">
<ul x-sort="handle">
<li x-sort:item="1">лиса</li>
<li x-sort:item="2">волк</li>
<li x-sort:item="3">медведь</li>
</ul>
</div>

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

Сортировка групп

Этот плагин позволяет перетаскивать элементы из одного сортируемого списка x-sort в другой, добавляя соответствующее значение x-sort:group в оба списка:

<div x-data>
<ul x-sort x-sort:group="todos">
<li x-sort:item="1">кошка</li>
<li x-sort:item="2">мышка</li>
<li x-sort:item="3">собака</li>
</ul>
<ol x-sort x-sort:group="todos">
<li x-sort:item="1">енот</li>
<li x-sort:item="2">ласка</li>
<li x-sort:item="3">хорёк</li>
</ol>
</div>
  • кошка
  • мышка
  • собака
  1. енот
  2. ласка
  3. хорёк

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

Держатели для перетаскивания

По умолчанию каждый дочерний элемент x-sort:item можно перетаскивать, щёлкая и перетаскивая в любом месте внутри него. Однако вы можете назначить более мелкий и конкретный элемент в качестве «держателя для перетаскивания», чтобы с остальными элементами можно было взаимодействовать как обычно, а на перетаскивание мыши реагировал только держатель:

<div x-data>
<ul x-sort class="list-none">
<li x-sort:item>
<span x-sort:handle> 🦊 </span>лиса
</li>
<li x-sort:item>
<span x-sort:handle> 🐺 </span>волк
</li>
<li x-sort:item>
<span x-sort:handle> 🐻 </span>медведь
</li>
</ul>
</div>
  • 🦊 лиса
  • 🐺 волк
  • 🐻 медведь

Как видно из приведённого выше примера, мордочки животных можно перетаскивать, а их названия — нет.

Призрачные элементы

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

По умолчанию при перетаскивании на месте исходного элемента будет оставлена «дыра» (пустое место).

Если вы хотите показать «призрака» оригинального элемента на его месте вместо пустого пространства, добавьте модификатор .ghost к x-sort:

<div x-data>
<ul x-sort.ghost>
<li x-sort:item>бурундук</li>
<li x-sort:item>капибара</li>
<li x-sort:item>муравьед</li>
</ul>
</div>
  • бурундук
  • капибара
  • муравьед

Стилизация элемента-призрака

По умолчанию элемент-«призрак» имеет CSS-класс .sortable-ghost, прикреплённый к нему во время перетаскивания исходного элемента.

Это позволяет легко добавлять любые пользовательские стили:

<style>
.sortable-ghost {
opacity: .5 !important;
color: lime;
}
</style>
<div x-data>
<ul x-sort.ghost>
<li x-sort:item>гиена</li>
<li x-sort:item>шакал</li>
<li x-sort:item>койот</li>
</ul>
</div>
  • гиена
  • шакал
  • койот

Класс sorting на элементе body

Пока элемент перетаскивается, Alpine автоматически добавит класс .sorting к элементу <body> страницы.

Это полезно для стилизации любого элемента на странице условно, используя только CSS.

Например, вы можете иметь предупреждение, которое отображается только во время сортировки элементов пользователем:

<div id="sort-warning">
Функциональность страницы при сортировке ограничена
</div>

Чтобы показать это только при сортировке, используйте CSS-селектор body.sorting:

#sort-warning {
display: none;
}
body.sorting #sort-warning {
display: block;
}

Баг с CSS-свойством hover

В настоящее время существует баг в Chrome и Safari (не в Firefox), который вызывает проблемы с наведением стилей.

Рассмотрим HTML, где каждый элемент списка оформляется по-разному в зависимости от состояния наведения (здесь мы используем класс .hover от Tailwind для условного добавления рамки):

<div x-sort>
<div x-sort:item class="hover:border">страус</div>
<div x-sort:item class="hover:border">курица</div>
<div x-sort:item class="hover:border">павлин</div>
</div>

Если вы перетащите один из элементов в списке ниже, то увидите, что эффект наведения будет ошибочно применен к любому элементу на месте исходного:

<div x-data>
<ul x-sort class="flex flex-col items-start">
<li x-sort:item class="hover:border border-black">страус</li>
<li x-sort:item class="hover:border border-black">курица</li>
<li x-sort:item class="hover:border border-black">павлин</li>
</ul>
</div>
  • страус
  • курица
  • павлин

Чтобы исправить это, используйте класс .sorting, применяемый к body при сортировке, чтобы ограничить эффект hover, который будет применяться только тогда, когда у body не будет класса .sorting.

Вот как вы можете сделать это прямо в строке, используя произвольные варианты Tailwind:

<div x-sort>
<div x-sort:item class="[body:not(.sorting)_&]:hover:border">страус</div>
<div x-sort:item class="[body:not(.sorting)_&]:hover:border">курица</div>
<div x-sort:item class="[body:not(.sorting)_&]:hover:border">павлин</div>
</div>

Теперь вы можете видеть, что эффект наведения применяется только к перетаскиваемому элементу, а не к остальным в списке.

<div x-data>
<ul x-sort class="flex flex-col items-start">
<li x-sort:item class="[body:not(.sorting)_&]:hover:border border-black">индюк</li>
<li x-sort:item class="[body:not(.sorting)_&]:hover:border border-black">гусь</li>
<li x-sort:item class="[body:not(.sorting)_&]:hover:border border-black">утка</li>
</ul>
</div>
  • индюк
  • гусь
  • утка

Пользовательская конфигурация

Alpine выбирает разумные настройки по умолчанию для конфигурирования SortableJS под капотом. Однако вы можете добавить или переопределить любую из этих опций самостоятельно, используя x-sort:config:

<div x-data>
<ul x-sort x-sort:config="{ filter: '.no-drag', ghostClass: 'text-yellow-500' }">
<li x-sort:item>суррикат</li>
<li x-sort:item class="no-drag">норка (не перетаскивается)</li>
<li x-sort:item>белка</li>
</ul>
</div>
  • суррикат
  • норка (не перетаскивается)
  • белка
<div x-data>
<ul x-sort x-sort:config="{ animation: 0 }">
<li x-sort:item>суррикат</li>
<li x-sort:item>норка</li>
<li x-sort:item>белка</li>
</ul>
</div>
  • суррикат
  • норка
  • белка