PHPackages                             tobento/js-sortable - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. tobento/js-sortable

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

tobento/js-sortable
===================

A simple and lightweight JavaScript library for reorderable drag-and-drop lists or items.

1.0.0(9mo ago)0181MITJavaScript

Since Aug 6Pushed 9mo agoCompare

[ Source](https://github.com/tobento-ch/js-sortable)[ Packagist](https://packagist.org/packages/tobento/js-sortable)[ Docs](https://www.tobento.ch)[ RSS](/packages/tobento-js-sortable/feed)WikiDiscussions 1.x Synced 1mo ago

READMEChangelog (1)DependenciesVersions (2)Used By (1)

JS Sortable
===========

[](#js-sortable)

A simple and lightweight JavaScript library for reorderable drag-and-drop lists or items. It uses the HTML Drag and Drop API which is sadly not supported by touch devices.

You may visit the [**docs.tobento.ch/js-sortable**](https://docs.tobento.ch/js-sortable) page for demo.

Table of Contents
-----------------

[](#table-of-contents)

- [Getting started](#getting-started)
    - [Browser support](#browser-support)
- [Documentation](#documentation)
    - [Basic Usage](#basic-usage)
    - [Options](#options)
    - [Methods](#methods)
    - [Events](#events)
    - [Learn More](#learn-more)
        - [Updating A Sortable List](#updating-a-sortable-list)
        - [Supporting Touch Devices](#supporting-touch-devices)
- [Credits](#credits)

---

Getting started
===============

[](#getting-started)

Browser support
---------------

[](#browser-support)

Modern browser only. No touch devices.

Documentation
=============

[](#documentation)

Basic Usage
-----------

[](#basic-usage)

**1. Include JS**

```

```

**2. Register**

Use the `data-sortable` attribute to automatically register a sortable.

```

    1 - List Item
    2 - List Item
    3 - List Item
    4 - List Item
    5 - List Item

            5.1 - List Item
            5.2 - List Item

    6 - List Item
    7 - List Item
    8 - List Item

    1 - CardDrag
    2 - CardDrag
    3 - CardDrag
    4 - CardDrag

```

Thats all.

**You may get the sorted items**

```

    import sortables from "sortables.js";

    document.addEventListener('DOMContentLoaded', (e) => {
        const items = sortables.get('uniqueID').items();

        // or using the drop event
        sortables.get('uniqueID').listen('drop', (event, sortable) => {
            const items = sortable.items();
        });
    });

```

**Manually creating**

Instead of using the `data-sortable` attribute to register the sortable automatically, you can create sortables manually by using the `create` function:

```

    import sortables from "sortables.js";

    document.addEventListener('DOMContentLoaded', (e) => {
        // create it manually:
        const sortable = sortables.create(document.querySelector('#container'), {
            id: 'uniqueID',
            selector: '.item'
        });

        // you may get the sorted items using the drop event:
        sortable.listen('drop', (event, sortable) => {
            const items = sortable.items();
        });
    });

```

Options
-------

[](#options)

```

```

OptionValueDescription`"id"``"ID"`A unique id.`"selector"``".item"`The items selector`"nestable"``true` or `false`When true, items can be nested if "li" selector. But you may set to false if you want only a one depth list. (optional)`"handle"``.handle`A handle selector to drag items only with. (optional)`"allow"``["id", "anotherId"]`You may set the allowed ids to be sorted within. (optional)`"clone"``true` or `false`When true, the drag item will be cloned. (optional)`"ghost"``true` or `false`When false, the ghost image will not be displayed. (optional)Methods
-------

[](#methods)

```

    import sortables from "sortables.js";

    document.addEventListener('DOMContentLoaded', (e) => {
        // create a sortable object:
        const sortable = sortables.create(document.querySelector('#container'), {
            id: 'ID',
            selector: '.item'
        });

        // you may get a sortable object by id:
        const sortable = sortable.get('ID');

        // you may check if a sortable object exists:
        if (sortable.has('ID')) {
            //
        }

        // you may get the sortable items:
        const items = sortable.items();

        // you may delete a sortable:
        sortables.delete('ID');

        // you may register newly added sortables with the data-sortable attribute:
        sortables.register();
    });

```

Events
------

[](#events)

EventDescription`dragstart`This event is fired **when** the user starts dragging an element.`dragend`This event is fired **when** a drag operation ends.`dragover`This event is fired **when** an element is being dragged over a valid drop target.`dragleave`This event is fired **when** a dragged element leaves a valid drop target.`drop`This event is fired **when** an element is dropped on a valid drop target.```
sortables.get('uniqueID').listen('drop', (event, sortable) => {
    const items = sortable.items();
});
```

Learn More
----------

[](#learn-more)

### Updating A Sortable List

[](#updating-a-sortable-list)

This example shows a possible way to update a reoredered list.

```

    import sortables from "sortables.js";

    document.addEventListener('DOMContentLoaded', (e) => {
        const sortable = sortables.get('list');

        sortable.listen('drop', (event, sortable) => {
            // Get the ul element where the item was dropped:
            const ul = sortable.draggable.closest('ul');

            // Determine the parent id:
            let parentId = 0;
            const parent = ul.parentNode;

            if (parent && parent.hasAttribute('data-id')) {
                parentId = parent.getAttribute('data-id');
            }

            // Get only those li elements within the current ul element (without children):
            const items = ul.querySelectorAll(':scope > li');

            // Build your data structure to update your items using the Fetch API.
            const data = {};
            const length = items.length;

            for (let i = 0; i
    1 - List Item
    2 - List Item
    3 - List Item
    4 - List Item
    5 - List Item

            5.1 - List Item
            5.2 - List Item

    6 - List Item
    7 - List Item
    8 - List Item

```

### Supporting Touch Devices

[](#supporting-touch-devices)

To support touch devices you may consider a polyfill such as the [Dragdroptouch](https://github.com/drag-drop-touch-js/dragdroptouch).

Credits
=======

[](#credits)

- [Tobias Strub](https://www.tobento.ch)
- [All Contributors](../../contributors)

###  Health Score

29

—

LowBetter than 59% of packages

Maintenance57

Moderate activity, may be stable

Popularity7

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity36

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

281d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/055d6a1b5c2384bb179c75ab0b55914231d898fdc4dffeb30770f81200e52206?d=identicon)[TOBENTOch](/maintainers/TOBENTOch)

---

Top Contributors

[![tobento-ch](https://avatars.githubusercontent.com/u/16684832?v=4)](https://github.com/tobento-ch "tobento-ch (1 commits)")

---

Tags

sortabledrag-and-droptobento

### Embed Badge

![Health badge](/badges/tobento-js-sortable/health.svg)

```
[![Health](https://phpackages.com/badges/tobento-js-sortable/health.svg)](https://phpackages.com/packages/tobento-js-sortable)
```

###  Alternatives

[kyslik/column-sortable

Package for handling column sorting in Laravel 6.x

6485.6M21](/packages/kyslik-column-sortable)[symbiote/silverstripe-gridfieldextensions

A collection of useful grid field components

971.8M235](/packages/symbiote-silverstripe-gridfieldextensions)[undefinedoffset/sortablegridfield

Adds drag and drop functionality to Silverstripe's GridField

941.2M50](/packages/undefinedoffset-sortablegridfield)[kartik-v/yii2-sortable

Create sortable lists and grids using HTML5 drag and drop API for Yii 2.0.

433.8M13](/packages/kartik-v-yii2-sortable)[himiklab/yii2-sortable-grid-view-widget

Sortable modification of standard Yii2 GridView widget

80351.1k7](/packages/himiklab-yii2-sortable-grid-view-widget)[kotchuprik/yii2-sortable-widgets

Implementation Rubaxa/Sortable for Yii2. Sortable grid view inside.

61132.2k6](/packages/kotchuprik-yii2-sortable-widgets)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
