Motion · GSAP-style

Draggable

$('.card').draggable({ bounds: '#board', inertia: true }). Works with mouse, touch and pen, and with the arrow keys for keyboard users.

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.

Live · A snapping slider and a card with a drop target

Drag me (or use arrow keys)
Drop zone
View the source for this demo
HTML
<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>
JavaScript
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

JavaScript
$.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

$.Draggable.create(target, { type, bounds, inertia, snap, liveSnap, edgeResistance, lockAxis, onDrag… }) · $(sel).draggable(vars) · $.Draggable.hitTest(a, b)

Pointer, touch and keyboard dragging.

Reference: jskjs.drag.js →

Migrating

Coming from GSAPDraggable.create() → $.Draggable.create(), same options and callbacks (this.x, this.y inside them). inertia doesn't need a separate InertiaPlugin.
Coming from jQuery UI.draggable({ containment }) → .draggable({ bounds }).

Related features