Sortable
Sortable is a simple JavaScript class, that implements a small, fast and fairly robust “sortable” interaction.
Component
The sortable component is a helper that makes a list of HTMLElement
s sortable.
new Sortable(container, config);
name | type | description |
---|---|---|
container | HTMLElement | The parent container of the sortable items |
config | SortableConfig | See below. |
When passing a drag handle, the item itself is not draggable, but only when touching the drag handle.
The component can be configured:
{
items: string,
handle?: string,
}
name | type | description |
---|---|---|
items | string | The selector string to query for the sortable (= movable) items. |
config.handle | string|undefined | A selector (inside of the item) to query for the drag handle element. |
Example
Given the HTML structure:
<ul id="sortable-example">
<li class="list-item">Entry 1</li>
<li class="list-item">Entry 2</li>
<li class="list-item">Entry 3</li>
</ul>
you can integrate the sortable like this:
let container = document.getElementById("sortable-example");
let sortable = new Sortable(container, {
items: ".list-item",
handle: ".drag-handle"
});
// register event listener
sortable.on(
"changed",
(items, result) => {}
);
// Don't forget to actually initialize the component
sortable.init();
// you can also destroy the sortable, to remove all DOM integrations
sortable.destroy();
// later you can recreate it
sortable.init();
Events
changed
The event is triggered if the order of the items has changed. It is not triggered if you release the dragged item at the same place as it was before.
(items, result) => { /* ... */ }
name | type | description |
---|---|---|
items | HTMLElement[] | The HTMLElement s in the new order. |
result.item | HTMLElement | The HTMLElement that was moved. |
result.before | HTMLElement|null | The HTMLElement the moved item was inserted before. If null , the item was moved to the end of the list. |
start
The event is triggered as soon as dragging an item has started.
(item) => { /* ... */ }
name | type | description |
---|---|---|
item | HTMLElement | The dragged item. |
end
The event is triggered as soon as dragging has stopped (by dropping or aborting).
The event handler doesn’t receive any arguments.
Hook
New in version 5.8.0: The hook was added in v5.8.0
.
There is also a preact hook, that eases the implementation in JSX components:
import {useSortable} from "mojave/ui/hooks";
import {createRef, h, JSX} from "preact";
export function MyComponent (props: {items: Item[]}): JSX.Element|null
{
let containerRef = createRef();
useSortable(
containerRef,
{items: "li"}, // these are just the options from a regular sortable
(item, before) => console.log("Moved item with ID ", item, " before item with ID ", before, " \\o/")
);
return (
<ul ref={containerRef}>
{props.items.map(item => (
<li data-id={item.id}>{item.label}</li>
)}
</ul>
);
}
The hook has the following signature:
useSortable(
ref: RefObject<HTMLElement>,
config: SortableConfig,
onChange: (item: number, before: number|null) => void,
idFetcher?: (element: HTMLElement) => number,
);
name | type | description |
---|---|---|
ref | RefObject<HTMLElement> | The reference to the container element. |
config | SortableConfig | Configuration to init the sortable. |
onChange | Function | The callback which is called as soon as the order has changed. |
idFetcher | Function | A function that receives an HTMLElement and returns the ID of the element. By default it looks at the data-id attribute. |
The config
is the SortableConfig from above.
The onChange
callback receives two parameters:
item (number)
the ID of the item that was moved.before (number|null)
the ID of the item it was moved before. Ifbefore
isnull
the item was moved to the end of the list.
This implementation also supports sorting elements on a paginated list. The meaning of “moved to the end of the list” changes then to “to the end of the page”.
The idFetcher
is responsible for receiving an HTMLElement
and returning the ID from it. The default implementation looks at the data-id
attribute.