JSort logo

JSort, your JavaScript library for sorting and reordering list or grid items.

GitHub rokobuljan/jsort
NPM @rbuljan/jsort

Grid

Sortable CSS grid. Parent-drop and grab handler supported.

View code

<div id="grid">
  <div>One</div>
  <div>
    <div class="jsort-handler">Handler</div>
    Two
  </div>
</div>

<script type="module">
import JSort from "@rbuljan/jsort";
const elGrid = document.querySelector("#grid");
const jsortGrid = new JSort(elGrid, {/* Options */});
</script>
JSort
2.
3. Link test:
GitHub JSort
Handler
4.
Handler exists but has display: none;
6
7. Input test
8. I'm an Anchor. Sortable and clickable!
Handler
9. DIV child
10.
11. IGNORED!

Groups

Group multiple containers using the data-jsort attribute: data-jsort="group: name"

View code

<ul class="shared">
  <li> A 1 </li>
  <li> A 2 </li>
</ul>
<ul class="shared">
  <li> B 1 </li>
</ul>

<script type="module">
import JSort from "@rbuljan/jsort";
document.querySelectorAll(".shared").forEach((el) => new JSort(el, { group: "shared" }));
</script>
  • A 1
  • A 2
  • A 3
  • A 4
  • A 5

Nested

Add a group: "name" to Options, or use data-jsort="group: name" to your nested elements.

View code

<ul class="nested">
  <li> A
    <ul class="nested">
      <li> B </li>
    </ul>
  </li>
</ul>

<script type="module">
import JSort from "@rbuljan/jsort";
document.querySelectorAll(".nested").forEach((el) => new JSort(el, { group: "nested" }));
</script>
  • A 1
  • B 1
  • C 1
    • C 1 a
    • C 1 a 1
      • D.a 1
      • D.a 2

Swap

Swap items between elements.
Add group: "name", swap: true to Options, or use data-jsort="group: name; swap: true" attribute to your grouped elements.

View code

<ul class="swap" data-jsort="group:a;swap:true;">
  <li> A 1 </li>
  <li> A 2 </li>
</ul>
<ul class="swap" data-jsort="group:a;swap:true;">
  <li> B 1 </li>
</ul>

<script type="module">
import JSort from "@rbuljan/jsort";
document.querySelectorAll(".swap").forEach((el) => new JSort(el));
</script>

Substitutes

  • Player 8
  • Player 14
  • Player 12
  • Player 5

Team

  • Player 9
  • Player 10
  • Player 7
  • Player 3
  • Player 1

Sort beta

What is an animated sortable library without a .sort() method?

View code

import JSort from "@rbuljan/jsort";
const myJSort = new JSort(document.querySelector(".jsort"));
// Your custom sorting logic:
const sortLogic = (a, b) => a.textContent.localeCompare(b.textContent, "en", { numeric: true });
// Sort:
myJSort.sort(sortLogic);
  • Zeus
  • Apollo
  • Aphrodite
  • Athena
  • Hermes
  • Poseidon
  • Ares
  • Hera

FAQ

Here's what's asked the most

How to make items' text selectable
Since the item becomes draggable/sortable, text selection within your items can be achieved by either
  • Add a grab handler child to your items HTML
  • Use in Options the selectorIgnoreTarget like: selectorIgnoreTarget: "p" (to ignore paragraphs descendants)
How to ignore grab of certain items
By default, all immediate children are sortable. There's several ways to ignore certain elements
  • Add the HTML class jsort-ignore to your desired items, or modify the desired class in Options selectorItemsIgnore: ".my-ignore-class" (by default it's ".jsort-ignore")
  • In Options, define a chstom selector for your itens using the :not() CSS selector like: selectorItems: "*:not(.ignore)" and add that chstom .ignore class to your Elements
  • In Options, define a custom items selector: ".item" and add it only to the children items you want to be draggable/sortable
On mobile (touch) how to make sortable items immediately draggable?
By default, on mobile (touch) there's a slight timeout to register scroll-intent, so that large sortable items would not get in the way of a user trying to actually scroll the page/app.
Being aware of this, if instead you want your sortable items to be immediately, seamlessly draggable, you can set the grabTimeout option to 0
On drop, how to get the item's old and new indexes?
As explained in the JSort docs, use the several on* callback options, one being onDrop() and see all the available `data` Object values.


myJSort(Element, {
  onDrop(data) => {
    console.log(data)
    console.log(data.indexGrab, data.indexDrop);
    console.log(this); // if you need even more info
  });
});

Licence

MIT
© 2025 Roko C. Buljan