Draggable Elements PURE HYPERSCRIPT
Reusable behavior with parameters and custom events
This example shows how to create a reusable "Draggable" behavior that can be installed
on any element, with support for custom drag handles, event hooks, and smooth positioning.
behavior
install
measure
custom events
halt event
Instructions: Drag the boxes by their title bars. Notice the shadow effect during dragging!
Draggable Item 1
Drag me by the title bar!
Draggable Item 2
I'm draggable too!
Draggable Item 3
Move me around!
The Behavior Definition
behavior Draggable(dragHandle)
init
if no dragHandle set the dragHandle to me
end
on pointerdown(clientX, clientY) from dragHandle
halt the event
trigger draggable:start
measure x
set startX to it
measure y
set startY to it
set xoff to clientX - startX
set yoff to clientY - startY
repeat until event pointerup from document
wait for pointermove(clientX, clientY) or
pointerup(clientX, clientY) from document
add { left: ${clientX - xoff}px; top: ${clientY - yoff}px; }
trigger draggable:move
end
trigger draggable:end
end
end
Usage Example
<div class="draggable-item"
_="install Draggable(dragHandle: .titlebar in me)
on draggable:start add .dragging
on draggable:end remove .dragging">
<div class="titlebar">Draggable Item</div>
<div class="content">Drag me!</div>
</div>
How it works:
- Install behavior:
install Draggable(dragHandle: .titlebar in me)
- Initialize: If no drag handle specified, use the element itself
- Capture start: On pointerdown, measure current position and calculate offset
- Track movement: Loop until pointerup from document, updating position on each pointermove
- Custom events: Trigger draggable:start, draggable:move, draggable:end for hooks
- CSS injection: Use template strings to add position styles directly
Advanced Concepts:
- Behaviors: Reusable components that encapsulate logic
- Parameters:
Draggable(dragHandle) accepts configuration
- init block: Runs once when behavior is installed
- measure: Get element dimensions and position
- halt the event: Prevent default behavior and stop propagation
- Event listening:
from document listens for pointer events at document level
- Custom events:
trigger eventName for lifecycle hooks
- Event parameters: Destructure event properties in handler signature
Custom Event Hooks:
draggable:start - Fired when drag begins (great for adding visual feedback)
draggable:move - Fired during each movement (could track distance, log position)
draggable:end - Fired when drag completes (save state, check drop zones)
Try it yourself:
- Add boundaries: Check position limits before applying styles
- Snap to grid: Round positions to nearest 20px
- Drop zones: Use draggable:end to check if element is over a target
- Multiple behaviors: Install other behaviors alongside Draggable
Key insight about event flow: The behavior listens for pointer events from document rather than
just from dragHandle. This ensures the drag continues smoothly even when the pointer moves quickly and temporarily
leaves the drag handle's bounds. The halt the event on pointerdown prevents text selection during drag.
Note about behaviors: The behavior feature requires full hyperscript implementation.
If dragging doesn't work yet, it indicates the behavior system needs implementation. The behavior code above is defined
in a <script type="text/hyperscript"> tag at the bottom of this page.