dnd
Drag-and-drop utilities for browser UI - draggable elements with JSON data payload, dragstart/drag/dragend callbacks, drop zones with dragover/dragleave/drop handling, and sortable lists that reorder themselves when items are dragged.
Load with: use dnd
What this module does
dnd wraps the HTML5 Drag and Drop API in a simple state-object pattern.
A draggable is a state object linked to a DOM element that carries a JSON-serialised
data payload through the drag operation. A drop zone is a separate state object that
handles incoming drops and fires a callback with the decoded payload.
The sortable-list helper makes any list of DOM elements reorderable by drag-and-drop, swapping items in the underlying list and calling an on-change callback.
Quick example
use dnd
# --- Draggable ---
item = dndne()
item = dndel(item, my_dom_element)
item = dndda(item, {id: 42, label: "Task A"})
item = dndon(item, \(dat, e) prn("drag started with " + jsn.enc(dat)))
item = dndgo(item) # attach drag event listeners
# --- Drop zone ---
zone = dropn()
zone = drope(zone, drop_target_element)
zone = dropa(zone, \(dat, e) prn("dropped: " + dat))
zone = dropg(zone) # attach drop event listeners
# --- Sortable list ---
s = sortn(my_item_elements)
s = sorto(s, \(new_order) prn("reordered"))
s = sortg(s) # attach drag events to all items
Functions
Draggable
dndne()
Creates a new drag state: {el: nil, dat: nil, onst: nil, onmv: nil, oned: nil, drg: fls}.
dndel(state, element)
Sets the DOM element to make draggable.
dndda(state, data)
Sets the data payload. This is JSON-encoded and stored in the drag event's dataTransfer under the key "txt".
dndon(state, fn)
Registers callbacks: the first call sets onst (dragstart), the second sets onmv (drag/move), and the third sets oned (dragend). Dragstart receives (data, event), others receive (event).
dndgo(state)
Attaches the drag event listeners to the element: sets draggable = tru, wires ondragstart, ondrag, and ondragend. Returns the updated state.
Drop zone
dropn()
Creates a new drop zone state: {el: nil, onov: nil, onlv: nil, ondrp: nil}.
drope(state, element)
Sets the DOM element to use as the drop target.
dropo(state, fn)
Registers callbacks: first call sets onov (dragover), second sets onlv (dragleave). Both receive the drag event.
dropa(state, fn)
Registers the ondrp (drop) callback. Receives (data_string, event) where data_string is the raw JSON from dataTransfer.getData("txt").
dropg(state)
Attaches event listeners to the drop zone element. dragover and drop call preventDefault() to allow the drop. Returns updated state.
Sortable list
sortn(items)
Creates a sortable state from a list of DOM elements: {lst: items, onchg: nil, itm: nil}.
sorto(state, fn)
Sets the on-change callback, called with the reordered list whenever a drag-drop swap happens.
sortg(state)
Attaches drag-and-drop listeners to every item in the list. On drop, swaps the source and target items in the list array and fires the on-change callback. Drag index is stored in dataTransfer under "idx".
Notes
- Requires a browser host environment with an HTML5 Drag and Drop API.
- The
dnddata payload is JSON-encoded on dragstart and available as a raw string in the drop callback - decode withjsn.decas needed. - Requires
trl.