Pointer events, transforms, keyboard
The add-on listens to Pointer Events, so one code path covers mouse, touch and pen. Elements move with transform (or left/top with type: 'left,top'), constrained by bounds — an element, a selector or a { minX, maxX, minY, maxY } box.
Focusable draggables respond to the arrow keys (Shift for bigger steps), so the same control works without a pointer. snap takes a step size, an array of values or a function. $.Draggable.hitTest(a, b) tells you when two elements overlap.
View the source for this demo
<label id="dr-label" for="dr-knob">Volume: <b id="dr-val">0</b></label>
<div id="dr-track" class="dr-track" style="margin-top:8px"><div id="dr-knob" class="dr-knob" tabindex="0" role="slider" aria-labelledby="dr-label" aria-valuemin="0" aria-valuemax="10" aria-valuenow="0"></div></div>
<div id="dr-board" class="dr-board">
<div id="dr-card" class="dr-card" tabindex="0">Drag me (or use arrow keys)</div>
<div id="dr-bin" class="dr-bin">Drop zone</div>
</div>const track = $('#dr-track')[0];
$.Draggable.create('#dr-knob', {
type: 'x', bounds: '#dr-track',
snap: v => Math.round(v / ((track.clientWidth - 42) / 10)) * ((track.clientWidth - 42) / 10),
onDrag() { show(this.x); }, onDragEnd() { show(this.x); }
});
function show(x) {
const v = Math.round(x / ((track.clientWidth - 42) / 10));
$('#dr-val').text(v);
$('#dr-knob').attr('aria-valuenow', v);
}
$('#dr-card').draggable({
bounds: '#dr-board', inertia: true,
onDrag() { $('#dr-bin').toggleClass('hot', $.Draggable.hitTest('#dr-card', '#dr-bin')); },
onDragEnd() {
const hit = $.Draggable.hitTest('#dr-card', '#dr-bin');
$('#dr-bin').toggleClass('hot', hit).text(hit ? 'Dropped ✓' : 'Drop zone');
}
});More examples
Options at a glance
$.Draggable.create('.knob', {
type: 'x', // 'x', 'y', 'x,y' (default) or 'left,top'
bounds: '.track', // element, selector or { minX, maxX, minY, maxY }
snap: 20, // step, array of values, or function
inertia: true, // glide after release
onPress() {}, onDrag() {}, onDragEnd() {}, onRelease() {}
});API
Pointer, touch and keyboard dragging.
Reference: jskjs.drag.js →Migrating
Draggable.create() → $.Draggable.create(), same options and callbacks (this.x, this.y inside them). inertia doesn't need a separate InertiaPlugin..draggable({ containment }) → .draggable({ bounds }).Related features
Flip layout animation
Animate any layout change — reordering, filtering, grid to list — with the jskjs.flip.js add-on.
Open →MotionTransforms
Animate x, y, rotate, scale, scaleX, scaleY, skewX and skewY independently — jsKjs composes them into one transform per frame.
Open →PulseUI directives
The jskjs.ui.js add-on brings the Alpine plugins to Pulse: kj-collapse, $persist, kj-trap, kj-mask, $money, kj-intersect and kj-resize.
Open →