Drag to Reorder

A draggable list using the HTML5 drag-and-drop API and `closest <li/>` to find drop targets - about ten lines of hyperscript.

A list whose items can be reordered by dragging. Built directly on the HTML5 drag-and-drop API - hyperscript handles the event wiring, and the DOM's native before() and after() methods do the actual reinsertion.

Example: Drag any row to reorder
<ul class="reorder-list" _="
    on dragstart
        set :dragged to closest <li/> to event.target
        add .is-dragging to :dragged
    on dragend
        remove .is-dragging from :dragged
    on dragover
        halt the event
    on drop
        halt the event
        set target to closest <li/> to event.target
        if target and target is not :dragged
            if event.offsetY > target.offsetHeight / 2
                call target.after(:dragged)
            else
                call target.before(:dragged)
            end
        end
">
    <li draggable="true">๐Ÿ“ Write the docs</li>
    <li draggable="true">๐ŸŽจ Polish the demo</li>
    <li draggable="true">๐Ÿ› Triage the bug list</li>
    <li draggable="true">๐Ÿš€ Cut the release</li>
    <li draggable="true">๐Ÿ“ฃ Post the announcement</li>
</ul>
  • ๐Ÿ“ Write the docs
  • ๐ŸŽจ Polish the demo
  • ๐Ÿ› Triage the bug list
  • ๐Ÿš€ Cut the release
  • ๐Ÿ“ฃ Post the announcement
Try It!

The whole list takes one _= attribute on the parent <ul>:

on dragstart
  set :dragged to closest <li/> to event.target
  add .is-dragging to :dragged
on dragend
  remove .is-dragging from :dragged
on dragover
  halt the event
on drop
  halt the event
  set target to closest <li/> to event.target
  if target and target is not :dragged
    if event.offsetY > target.offsetHeight / 2
      call target.after(:dragged)
    else
      call target.before(:dragged)
    end
  end

Each <li> just needs draggable="true" to opt into the API.

How it works

The HTML5 drag-and-drop API has four events worth caring about for a reorder list:

A few subtleties