v7.3.0
SupportExamplesFree Trial

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 relatedElements along with the main element
  • Firing useful events beforeDragStart, dragStart, drag, drop, abort
  • Validation by setting a valid Boolean 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

const buttonContainer = DomHelper.createElement({ id : 'buttonContainer', parent : targetElement, style : { display : 'flex', gap : '1em' } }); const toolbar = new Toolbar({ insertFirst : targetElement, style : 'margin-bottom: 2em;width:40em', items : { button : { type : 'button', disabled : true, text : 'Drag buttons here' } } }); new Button({ appendTo : buttonContainer, rendition : 'filled', text : 'Drag me', icon : 'fa fa-tree', onClick : ({ source: button }) => Toast.show('Merry Xmas') }); new Button({ appendTo : buttonContainer, rendition : 'filled', text : 'Drag me to toolbar', icon : 'fa fa-globe', onClick : ({ source: button }) => Toast.show('Hello World') }); const dragHelper = new DragHelper({ outerElement : targetElement, // Only allow drag of buttons inside the fiddle targetSelector : '#buttonContainer .b-button', // Only allow drops on the toolbar dropTargetSelector : '.b-toolbar', callOnFunctions : true, onDragStart() { // Highlight the drop target area toolbar.element.style.outline = '1px dashed #aaa'; }, async onDrop({ context, event }) { // Clear the highlight toolbar.element.style.outline = ''; if (context.valid) { const button = Widget.fromElement(context.grabbed); if (toolbar.widgetMap.helpLabel) { toolbar.remove(toolbar.widgetMap.helpLabel); } await this.animateProxyTo(toolbar.contentElement.lastElementChild || Rectangle.content(toolbar.contentElement), { align : toolbar.contentElement.lastElementChild ? 'l-r' : 'l-l', // Some offset to account for the margin between buttons offset : toolbar.contentElement.lastElementChild ? [10, 0] : null }); toolbar.add(button); Toast.show('👍 Nice drop!'); } } }); fiddle.on('destroy', () => dragHelper.destroy());

Two modes

DragHelper supports two modes:

  • container - moving / rearranging elements within and between specified containers
  • translateXY - 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

No results

Configs

Configs are options you supply in a configuration object when creating an instance of this class
  • Set to false to not apply width/height of cloned drag proxy elements.

  • Set to true to clone the dragged target, and not move the actual target DOM node.

  • Constrain translate drag to dragWithin elements bounds (set to false to allow it to "overlap" edges)

  • Containers whose elements can be rearranged (and moved between the containers). Used when mode is set to "container".

  • dragProxyCls : Stringb-drag-proxy
    private

    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

  • draggingCls : Stringb-dragging
    private

    CSS class added to the source element in Container drag

  • dropPlaceholderCls : Stringb-drop-placeholder
    private

    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 true to hide the original element while dragging (applicable when cloneTarget is true).

  • A CSS selector used to exclude elements when using container mode

  • invalidCls : Stringb-drag-invalid

    CSS class added when drag is invalid

  • lockX : Booleanfalse

    Configure as true to disallow dragging in the X axis. The dragged element will only move vertically.

  • lockY : Booleanfalse

    Configure as true to disallow dragging in the Y axis. 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.

  • mode : 'container'/'translateXY'translateXY

    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 false to 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 true to stack any related dragged elements below the main drag proxy element. Only applicable when using translate mode with cloneTarget

  • Internal listeners, that cannot be removed by the user.

Properties

Properties are getters/setters or publicly accessible variables on this class
  • isDragHelper : Booleantrue
    READONLY
    static
    ADVANCED
    Identifies an object as an instance of DragHelper class, or subclass thereof.
  • isEvents : Booleantrue
    READONLY
    static
    ADVANCED
    Events
    Identifies an object as an instance of Events class, or subclass thereof.
  • properties : Object
    internal
    static
    Base

    A class property getter for the default values of internal properties for this class.

  • isDragging : Boolean
    READONLY

    Returns true if a drag operation is active

  • emptyArray : Array
    internal
    READONLY
    Base

    An empty array that can be used as a default value.

  • emptyObject : Object
    internal
    READONLY
    Base

    An empty object that can be used as a default value.

  • isDragHelper : Booleantrue
    READONLY
    ADVANCED
    Identifies an object as an instance of DragHelper class, or subclass thereof.
  • config : Object
    READONLY
    ADVANCED
    Base

    Returns a copy of the full configuration which was used to configure this object.

  • isConstructing : Boolean
    READONLY
    ADVANCED
    Base

    This property is set to true before the constructor returns.

  • isDestroying : Boolean
    READONLY
    ADVANCED
    Base

    This property is set to true on entry to the destroy method. It remains on the objects after returning from destroy(). If isDestroyed is true, this property will also be true, so there is no need to test for both (for example, comp.isDestroying || comp.isDestroyed).

Functions

Functions are methods available for calling on the class
  • onClassMixedIn( )
    internal
    static
    Base

    This optional class method is called when a class is mixed in using the mixin() method.

  • initClass( )
    static
    ADVANCED
    Base

    Registers this class type with its Factory

  • abort( )
    ASYNC

    Abort dragging


    Triggers: abort

  • initListeners( )
    private

    Initialize listener

  • update( )
    private

    Updates drag, called when an element is grabbed and mouse moves


    Triggers: drag

  • Internal function used to hook destroy() calls when using thisObj

  • Internal function used restore hooked destroy() calls when using thisObj

  • doDestroy( )
    internal
    Events

    Auto detaches listeners registered from start, if set as detachable

  • once( )
    private
    Events

    Internal function used to run a callback function after an event is triggered

  • Removes all listeners registered to this object by the application.

Events

Events are triggered for certain actions in this class and can be listened for to react to those actions in your code

Event handlers

Event handlers are callbacks called as a result of certain actions in this class

Source path

Core/helper/DragHelper.js

Contents