or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-dragula

Drag and drop so simple it hurts - a lightweight JavaScript library for implementing drag and drop functionality in web applications.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/dragula@3.7.x

To install, run

npx @tessl/cli install tessl/npm-dragula@3.7.0

index.mddocs/

Dragula

Dragula is a lightweight JavaScript drag and drop library that provides an intuitive API for implementing drag and drop functionality in web applications. It features automatic sort order detection, visual feedback through shadows, touch event support, seamless click handling, and broad browser compatibility including IE7+.

Package Information

  • Package Name: dragula
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install dragula
  • Browser Support: IE7+ and all modern browsers
  • Framework Support: Vanilla JavaScript, Angular, React

Core Imports

const dragula = require('dragula');

ES modules:

import dragula from 'dragula';

You'll also need to include the CSS:

<link rel="stylesheet" href="node_modules/dragula/dist/dragula.css">

Or with bundlers:

import 'dragula/dist/dragula.css';

Basic Usage

import dragula from 'dragula';

// Basic setup with containers
const containers = [
  document.querySelector('#left'),
  document.querySelector('#right')
];
const drake = dragula(containers);

// With options
const drake = dragula(containers, {
  copy: true,
  revertOnSpill: false,
  removeOnSpill: true,
  direction: 'vertical'
});

// Listen to events
drake.on('drop', (el, target, source, sibling) => {
  console.log('Element dropped:', el);
  console.log('Into container:', target);
  console.log('From container:', source);
  console.log('Before sibling:', sibling);
});

// Manual drag operations
drake.start(element);  // Start dragging
drake.end();          // End drag
drake.cancel();       // Cancel drag
drake.remove();       // Remove element

Capabilities

Factory Function

Creates a new drake instance with drag and drop functionality.

/**
 * Create a drake instance for drag and drop operations
 * @param {HTMLElement[]} containers - Array of DOM elements that act as drag containers
 * @param {DragulaOptions} options - Configuration options
 * @returns {Drake} Drake instance
 */
function dragula(containers, options);

Drake Instance

The drake instance returned by the dragula factory function.

interface Drake {
  /** Array of container elements for this drake instance */
  containers: HTMLElement[];
  
  /** Whether an element is currently being dragged */
  dragging: boolean;
  
  /** Manually start dragging an element */
  start(item: HTMLElement): void;
  
  /** End the current drag operation gracefully */
  end(): void;
  
  /** Cancel the current drag operation */
  cancel(revert?: boolean): void;
  
  /** Remove the currently dragged element from DOM */
  remove(): void;
  
  /** Clean up all event listeners and destroy the drake */
  destroy(): void;
  
  /** Check if an element can be moved by this drake */
  canMove(item: HTMLElement): boolean;
  
  /** Register event listener */
  on(eventName: string, listener: Function): Drake;
  
  /** Register one-time event listener */
  once(eventName: string, listener: Function): Drake;
  
  /** Remove event listeners */
  off(eventName?: string, listener?: Function): Drake;
  
  /** Emit an event */
  emit(eventName: string, ...args: any[]): Drake;
}

Configuration Options

Complete configuration options for customizing drag and drop behavior.

interface DragulaOptions {
  /** Array of container elements (alternative to first parameter) */
  containers?: HTMLElement[];
  
  /** Function to determine if element is a container */
  isContainer?: (el: HTMLElement) => boolean;
  
  /** Function to determine if element can be moved */
  moves?: (el: HTMLElement, source: HTMLElement, handle: HTMLElement, sibling: HTMLElement) => boolean;
  
  /** Function to determine if element can be dropped in target */
  accepts?: (el: HTMLElement, target: HTMLElement, source: HTMLElement, sibling: HTMLElement) => boolean;
  
  /** Function to prevent drag from starting */
  invalid?: (el: HTMLElement, handle: HTMLElement) => boolean;
  
  /** Copy elements instead of moving them */
  copy?: boolean | ((el: HTMLElement, source: HTMLElement) => boolean);
  
  /** Allow sorting in copy-source containers */
  copySortSource?: boolean;
  
  /** Return element to original position when spilled */
  revertOnSpill?: boolean;
  
  /** Remove element from DOM when spilled */
  removeOnSpill?: boolean;
  
  /** Direction for determining drop position ('vertical' or 'horizontal') */
  direction?: 'vertical' | 'horizontal';
  
  /** Container for mirror elements during drag */
  mirrorContainer?: HTMLElement;
  
  /** Allow text selection in input elements */
  ignoreInputTextSelection?: boolean;
  
  /** X-axis movement threshold before drag starts */
  slideFactorX?: number;
  
  /** Y-axis movement threshold before drag starts */
  slideFactorY?: number;
}

Event System

Comprehensive event system for tracking drag and drop operations.

// Event listener registration
drake.on(eventName, listener);

// Available events:

/** Element was lifted from source container */
'drag': (el: HTMLElement, source: HTMLElement) => void;

/** Drag operation ended */
'dragend': (el: HTMLElement) => void;

/** Element was dropped into target container */
'drop': (el: HTMLElement, target: HTMLElement, source: HTMLElement, sibling: HTMLElement | null) => void;

/** Element was returned to original container */
'cancel': (el: HTMLElement, container: HTMLElement, source: HTMLElement) => void;

/** Element was removed from DOM */
'remove': (el: HTMLElement, container: HTMLElement, source: HTMLElement) => void;

/** Visual shadow element was moved */
'shadow': (el: HTMLElement, container: HTMLElement, source: HTMLElement) => void;

/** Element is over a container */
'over': (el: HTMLElement, container: HTMLElement, source: HTMLElement) => void;

/** Element was dragged out of container */
'out': (el: HTMLElement, container: HTMLElement, source: HTMLElement) => void;

/** Element was cloned (mirror or copy) */
'cloned': (clone: HTMLElement, original: HTMLElement, type: 'mirror' | 'copy') => void;

Event Usage Examples:

const drake = dragula([container1, container2]);

// Track when items are dropped
drake.on('drop', (el, target, source, sibling) => {
  console.log(`Moved ${el.textContent} from ${source.id} to ${target.id}`);
  if (sibling) {
    console.log(`Placed before ${sibling.textContent}`);
  }
});

// Handle drag start
drake.on('drag', (el, source) => {
  el.classList.add('is-moving');
});

// Clean up after drag ends
drake.on('dragend', (el) => {
  el.classList.remove('is-moving');
});

// Handle copies
drake.on('cloned', (clone, original, type) => {
  if (type === 'copy') {
    clone.id = original.id + '-copy';
  }
});

// One-time event listener
drake.once('drop', (el, target) => {
  console.log('First drop completed!');
});

// Remove specific event listener
function myDragHandler(el, source) {
  console.log('Dragging started');
}
drake.on('drag', myDragHandler);
drake.off('drag', myDragHandler);  // Remove specific handler

// Remove all listeners for an event type
drake.off('drop');  // Remove all drop listeners

// Remove all listeners for all events
drake.off();  // Clean up everything

CSS Classes

Dragula applies CSS classes during drag operations for styling.

/* Applied to mirror container during drag */
.gu-unselectable {
  /* Prevents text selection */
}

/* Applied to source element during drag */
.gu-transit {
  /* Typically adds opacity */
}

/* Applied to mirror/ghost element */
.gu-mirror {
  /* Fixed positioning and z-index */
}

/* Helper class for hiding elements */
.gu-hide {
  display: none !important;
}

Advanced Usage Patterns

Dynamic Container Management:

const drake = dragula();

// Add containers dynamically
drake.containers.push(document.querySelector('#new-container'));

// Remove containers
const index = drake.containers.indexOf(oldContainer);
if (index > -1) {
  drake.containers.splice(index, 1);
}

Copy vs Move Behavior:

const drake = dragula([sourceContainer, targetContainer], {
  copy: (el, source) => {
    // Copy from source, move within target
    return source === sourceContainer;
  },
  accepts: (el, target, source, sibling) => {
    // Don't allow copies back to source
    return target !== sourceContainer;
  }
});

Custom Drag Handles:

const drake = dragula([container], {
  moves: (el, source, handle, sibling) => {
    // Only allow dragging by elements with 'drag-handle' class
    return handle.classList.contains('drag-handle');
  }
});

Touch and Mobile Support:

// Dragula automatically handles touch events
const drake = dragula([container], {
  // Adjust slide factors for better touch experience
  slideFactorX: 5,
  slideFactorY: 5
});

Validation and Restrictions:

const drake = dragula([container1, container2], {
  accepts: (el, target, source, sibling) => {
    // Custom drop validation logic
    return target.dataset.accepts === el.dataset.type;
  },
  invalid: (el, handle) => {
    // Prevent dragging certain elements
    return el.classList.contains('no-drag');
  }
});