DragHelper
Intro
A drag drop helper class which lets you move elements in page. It supports:
- Dragging the actual element
- Dragging a cloned version of the element
- Dragging extra
relatedElementsalong with the main element - Firing useful events beforeDragStart, dragStart, drag, drop, abort
- Validation by setting a
validBoolean on the drag context object provided to event listeners - Aborting drag with ESCAPE key
- Constraining drag to be only horizontal or vertical using lockX and lockY
- Defining X / Y boundaries using minX, maxX and minY, maxY
- Async finalization (e.g. to show confirmation prompts)
- Animated final transition after mouse up of a valid drop (see animateProxyTo)
- Animated abort transition after an invalid or aborted drop
Two modes
DragHelper supports two modes:
container- moving / rearranging elements within and between specified containerstranslateXY- freely repositioning an element, either using the element or a cloned version of it - a "drag proxy" (default mode)
Container drag mode
Container drag should be used when moving or rearranging child elements within and between specified containers
Example:
// dragging element between containers
let dragHelper = new DragHelper({
mode : 'container',
containers : [ container1, container2 ]
});
Translate drag mode
Use translate drag to reposition an element within its container using translate CSS.
Example:
// dragging element within container
let dragHelper = new DragHelper({
mode : 'translateXY',
targetSelector : 'div.movable'
});
Observable events
In the various events fired by the DragHelper, you will have access to the raw DOM event and some useful context about the drag operation:
myDrag.on({
drag : ({event , context}) {
// The element which we're moving, could be a cloned version of grabbed, or the grabbed element itself
const element = context.element;
// The original mousedown element upon which triggered the drag operation
const grabbed = context.grabbed;
// The target under the current mouse / pointer / touch position
const target = context.target;
}
});
Simple drag helper subclass with a drop target specified:
export default class MyDrag extends DragHelper {
static configurable = {
// Don't drag the actual cell element, clone it
cloneTarget : true,
mode : 'translateXY',
// Only allow drops on DOM elements with 'yourDropTarget' CSS class specified
dropTargetSelector : '.yourDropTarget',
// Only allow dragging elements with the 'draggable' CSS class
targetSelector : '.draggable'
}
construct(config) {
const me = this;
super.construct(config);
me.on({
dragstart : me.onDragStart
});
}
onDragStart({ event, context }) {
const target = context.target;
// Here you identify what you are dragging (an image of a user, grid row in an order table etc) and map it to something in your
// data model. You can store your data on the context object which is available to you in all drag-related events
context.userId = target.dataset.userId;
}
onEquipmentDrop({ context, event }) {
const me = this;
if (context.valid) {
const userId = context.userId,
droppedOnTarget = context.target;
console.log(`You dropped user ${userStore.getById(userId).name} on ${droppedOnTarget}`, droppedOnTarget);
// Dropped on a scheduled event, display toast
Toast.show(`You dropped user ${userStore.getById(userId).name} on ${droppedOnTarget}`);
}
}
};
Dragging multiple elements
You can tell the DragHelper to also move additional relatedElements when a drag operation is starting. Simply provide an array of elements on the context object:
new DragHelper ({
callOnFunctions : true,
onDragStart({ context }) {
// Let drag helper know about extra elements to drag
context.relatedElements = Array.from(element.querySelectorAll('.b-resource-avatar'));
}
});
Creating a custom drag proxy
Using the createProxy you can create any markup structure to use when dragging cloned targets.
new DragHelper ({
callOnFunctions : true,
// Don't drag the actual cell element, clone it
cloneTarget : true,
// We size the cloned element using CSS
autoSizeClonedTarget : false,
mode : 'translateXY',
// Only allow drops on certain DOM nodes
dropTargetSelector : '.myDropTarget',
// Only allow dragging cell elements in a Bryntum Grid
targetSelector : '.b-grid-row:not(.b-group-row) .b-grid-cell'
// Here we receive the element where the drag originated and we can choose to return just a child element of it
// to use for the drag proxy (such as an icon)
createProxy(element) {
return element.querySelector('i').cloneNode();
}
});
Animating a cloned drag proxy to a point before finalizing
To provide users with the optimal user experience, you can set a transitionTo object (with target element and align spec) on the DragHelper´s context object inside a drop listener (only applies to translate mode operations). This will trigger a final animation of the drag proxy which should represent the change of data state that will be triggered by the drop.
You can see this in action in Gantt´s drag-resource-from-grid demo.
new DragHelper ({
callOnFunctions : true,
// Don't drag the actual cell element, clone it
cloneTarget : true,
// We size the cloned element using CSS
autoSizeClonedTarget : false,
mode : 'translateXY',
// Only allow drops on certain DOM nodes
dropTargetSelector : '.myDropTarget',
// Only allow dragging cell elements in a Bryntum Grid
targetSelector : '.b-grid-row:not(.b-group-row) .b-grid-cell'
// Here we receive the element where the drag originated and we can choose to return just a child element of it
// to use for the drag proxy (such as an icon)
createProxy(element) {
return element.querySelector('i').cloneNode();
},
async onDrop({ context, event }) {
// If it's a valid drop, provide a point to animate the proxy to before finishing the operation
if (context.valid) {
await this.animateProxyTo(someElement, {
// align left side of drag proxy to right side of the someElement
align : 'l0-r0'
});
}
else {
Toast.show(`You cannot drop here`);
}
}
});
Useful configs and properties
| Config | Description |
|---|---|
| mode | Drag mode: container or translateXY |
| targetSelector | CSS selector to match draggable elements |
| dropTargetSelector | CSS selector for valid drop targets |
| cloneTarget | Clone the element instead of moving it |
| lockX | Lock horizontal movement |
| lockY | Lock vertical movement |
See also
- DomHelper - DOM element utilities
- EventHelper - DOM event utilities
Configs
Configs are options you supply in a configuration object when creating an instance of this class-
Set to
falseto not apply width/height of cloned drag proxy elements. -
Set to
trueto clone the dragged target, and not move the actual target DOM node. -
Constrain translate drag to dragWithin elements bounds (set to
falseto allow it to "overlap" edges) -
Containers whose elements can be rearranged (and moved between the containers). Used when mode is set to "container".
-
Drag proxy CSS class
-
The amount of pixels to move mouse before it counts as a drag operation
-
Outer element that limits where element can be dragged
-
CSS class added to the source element in Container drag
-
CSS class added to the source element in Container drag
-
A CSS selector added to each drop target element while dragging.
-
A CSS selector used to determine if a drop is allowed at the current position.
-
Set to
trueto hide the original element while dragging (applicable whencloneTargetis true). -
A CSS selector used to exclude elements when using container mode
-
CSS class added when drag is invalid
-
Configure as
trueto disallow dragging in theXaxis. The dragged element will only move vertically. -
Configure as
trueto disallow dragging in theYaxis. The dragged element will only move horizontally. -
Largest allowed x when dragging horizontally.
-
Largest allowed y when dragging horizontally.
-
Smallest allowed x when dragging horizontally.
-
Smallest allowed y when dragging horizontally.
-
Enabled dragging, specify mode:
container Allows reordering elements within one and/or between multiple containers translateXY Allows dragging within a parent container -
The outer element where the drag helper will operate (attach events to it and use as outer limit when looking for ancestors)
-
A CSS selector used to target a child element of the mouse down element, to use as the drag proxy element. Applies to translate mode when using cloneTarget.
-
Configure as
falseto take ownership of the proxy element after a valid drop (advanced usage). -
Scroll manager of the target. If specified, scrolling while dragging is supported.
-
A method provided to snap coordinates to fixed points as you drag
-
A Widget or HTML element to drag. See also targetSelector.
-
A CSS selector used to target draggable elements. See also target.
-
The amount of milliseconds to wait after a touchstart, before a drag gesture will be allowed to start.
-
When using unifiedProxy, use this amount of pixels to offset each extra element when dragging multiple items
-
Set to
trueto stack any related dragged elements below the main drag proxy element. Only applicable when using translate mode with cloneTarget
Properties
Properties are getters/setters or publicly accessible variables on this class-
Identifies an object as an instance of DragHelper class, or subclass thereof.
-
Returns true if a drag operation is active
-
Identifies an object as an instance of DragHelper class, or subclass thereof.
Functions
Functions are methods available for calling on the class-
initListeners( )private
Initialize listener
-
update( )private
Updates drag, called when an element is grabbed and mouse moves
Triggers: drag