CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-sortablejs

JavaScript library for reorderable drag-and-drop lists on modern browsers and touch devices

Pending
Overview
Eval results
Files

utilities.mddocs/

Utilities

Collection of DOM manipulation and helper functions for advanced integrations and custom implementations.

Capabilities

Event Management

Utilities for attaching and removing event listeners with cross-browser compatibility.

/**
 * Add event listener to element
 * @param el - Target element
 * @param event - Event name
 * @param fn - Event handler function
 */
Sortable.utils.on(el: HTMLElement, event: string, fn: Function): void;

/**
 * Remove event listener from element
 * @param el - Target element
 * @param event - Event name
 * @param fn - Event handler function
 */
Sortable.utils.off(el: HTMLElement, event: string, fn: Function): void;

Usage Examples:

const { on, off } = Sortable.utils;

function handleClick(evt) {
  console.log('Element clicked:', evt.target);
}

// Add event listener
on(document.getElementById('myButton'), 'click', handleClick);

// Remove event listener
off(document.getElementById('myButton'), 'click', handleClick);

// Handle multiple events
const events = ['mousedown', 'touchstart'];
events.forEach(event => on(element, event, handleStart));

CSS Manipulation

Utilities for getting and setting CSS properties and classes.

/**
 * Get or set CSS property on element
 * @param el - Target element
 * @param prop - CSS property name
 * @param value - CSS property value (omit to get current value)
 * @returns Current property value when getting
 */
Sortable.utils.css(el: HTMLElement, prop: string, value?: string): string | void;

/**
 * Toggle CSS class on element
 * @param el - Target element
 * @param name - Class name
 * @param state - Force state (true=add, false=remove, undefined=toggle)
 */
Sortable.utils.toggleClass(el: HTMLElement, name: string, state?: boolean): void;

Usage Examples:

const { css, toggleClass } = Sortable.utils;

// Get CSS property
const width = css(element, 'width'); // '200px'

// Set CSS property
css(element, 'background-color', 'red');
css(element, 'transform', 'translateX(100px)');

// Toggle class
toggleClass(element, 'active'); // Toggle
toggleClass(element, 'selected', true); // Force add
toggleClass(element, 'hidden', false); // Force remove

Element Searching

Utilities for finding and querying DOM elements.

/**
 * Find elements within a context
 * @param ctx - Context element to search within
 * @param tagName - Tag name to search for
 * @param iterator - Optional iterator function for filtering
 * @returns Array of matching elements
 */
Sortable.utils.find(ctx: HTMLElement, tagName: string, iterator?: Function): HTMLElement[];

/**
 * Check if element matches selector
 * @param el - Element to test
 * @param selector - CSS selector
 * @returns Whether element matches selector
 */
Sortable.utils.is(el: HTMLElement, selector: string): boolean;

/**
 * Find closest ancestor matching selector
 * @param el - Starting element
 * @param selector - CSS selector
 * @param ctx - Context element (search boundary)
 * @returns Closest matching ancestor or null
 */
Sortable.utils.closest(el: HTMLElement, selector: string, ctx?: HTMLElement): HTMLElement | null;

Usage Examples:

const { find, is, closest } = Sortable.utils;

// Find all divs within container
const divs = find(container, 'div');

// Find draggable items with custom filter
const draggableItems = find(container, '*', (el) => {
  return !el.classList.contains('no-drag');
});

// Check if element matches selector
if (is(element, '.sortable-item')) {
  console.log('Element is sortable item');
}

// Find closest sortable container
const sortableContainer = closest(draggedElement, '.sortable-list');

Element Manipulation

Utilities for cloning, positioning, and measuring elements.

/**
 * Clone an element
 * @param el - Element to clone
 * @returns Cloned element
 */
Sortable.utils.clone(el: HTMLElement): HTMLElement;

/**
 * Get element index within parent
 * @param el - Target element
 * @param selector - Optional selector to filter siblings
 * @returns Element index
 */
Sortable.utils.index(el: HTMLElement, selector?: string): number;

/**
 * Get child element at specific index
 * @param el - Parent element
 * @param childNum - Child index
 * @param options - Options object with draggable selector
 * @returns Child element at index
 */
Sortable.utils.getChild(el: HTMLElement, childNum: number, options?: { draggable?: string }): HTMLElement;

Usage Examples:

const { clone, index, getChild } = Sortable.utils;

// Clone element
const clonedElement = clone(originalElement);
document.body.appendChild(clonedElement);

// Get element index
const elementIndex = index(element); // Position among all siblings
const draggableIndex = index(element, '.draggable'); // Position among draggable siblings

// Get specific child
const firstChild = getChild(container, 0);
const firstDraggable = getChild(container, 0, { draggable: '.sortable-item' });

Object and Function Utilities

Utilities for object manipulation and function optimization.

/**
 * Extend target object with source objects
 * @param dst - Target object
 * @param src - Source objects
 * @returns Extended target object
 */
Sortable.utils.extend(dst: object, ...src: object[]): object;

/**
 * Throttle function calls
 * @param fn - Function to throttle
 * @param ms - Throttle interval in milliseconds
 * @returns Throttled function
 */
Sortable.utils.throttle(fn: Function, ms: number): Function;

Usage Examples:

const { extend, throttle } = Sortable.utils;

// Extend objects
const config = extend({}, defaultOptions, userOptions);

// Throttle expensive operations
const expensiveOperation = throttle(() => {
  console.log('This only runs once every 100ms');
  updateComplexUI();
}, 100);

// Call frequently, but execution is throttled
window.addEventListener('scroll', expensiveOperation);

Async Utilities

Utilities for scheduling and managing asynchronous operations.

/**
 * Schedule function for next tick
 * @param fn - Function to schedule
 * @returns Ticket ID for cancellation
 */
Sortable.utils.nextTick(fn: Function): number;

/**
 * Cancel scheduled function
 * @param id - Ticket ID from nextTick
 */
Sortable.utils.cancelNextTick(id: number): void;

Usage Examples:

const { nextTick, cancelNextTick } = Sortable.utils;

// Schedule for next tick
const ticketId = nextTick(() => {
  console.log('This runs on next tick');
  updateUI();
});

// Cancel if needed
if (shouldCancel) {
  cancelNextTick(ticketId);
}

// Common pattern for DOM updates
nextTick(() => {
  // DOM changes are batched and applied efficiently
  element.style.transform = 'translateX(100px)';
  element.classList.add('moved');
});

Direction Detection

Utility for detecting sort direction in containers.

/**
 * Detect sort direction of container
 * @param el - Container element
 * @returns Direction string ('horizontal' or 'vertical')
 */
Sortable.utils.detectDirection(el: HTMLElement): string;

Usage Examples:

const { detectDirection } = Sortable.utils;

// Detect container direction
const direction = detectDirection(container);
console.log('Container direction:', direction); // 'horizontal' or 'vertical'

// Use in custom logic
if (detectDirection(container) === 'horizontal') {
  setupHorizontalScrolling();
} else {
  setupVerticalScrolling();
}

Internal Property Access

Utility for accessing Sortable's internal property key.

/**
 * Internal property key used to store Sortable instances on elements
 */
Sortable.utils.expando: string;

Usage Examples:

const { expando } = Sortable.utils;

// Access sortable instance directly (advanced usage)
const sortableInstance = element[expando];

if (sortableInstance) {
  console.log('Element has sortable instance:', sortableInstance);
}

Complete Utils Interface

interface SortableUtils {
  // Event management
  on(el: HTMLElement, event: string, fn: Function): void;
  off(el: HTMLElement, event: string, fn: Function): void;
  
  // CSS manipulation
  css(el: HTMLElement, prop: string, value?: string): string | void;
  toggleClass(el: HTMLElement, name: string, state?: boolean): void;
  
  // Element searching
  find(ctx: HTMLElement, tagName: string, iterator?: Function): HTMLElement[];
  is(el: HTMLElement, selector: string): boolean;
  closest(el: HTMLElement, selector: string, ctx?: HTMLElement): HTMLElement | null;
  
  // Element manipulation
  clone(el: HTMLElement): HTMLElement;
  index(el: HTMLElement, selector?: string): number;
  getChild(el: HTMLElement, childNum: number, options?: { draggable?: string }): HTMLElement;
  
  // Object and function utilities
  extend(dst: object, ...src: object[]): object;
  throttle(fn: Function, ms: number): Function;
  
  // Async utilities
  nextTick(fn: Function): number;
  cancelNextTick(id: number): void;
  
  // Direction detection
  detectDirection(el: HTMLElement): string;
  
  // Internal property access
  expando: string;
}

Advanced Usage Patterns

Custom Sortable Implementation

Using utilities to build custom drag-and-drop functionality:

const { on, off, css, closest, throttle } = Sortable.utils;

class CustomDragDrop {
  constructor(element) {
    this.element = element;
    this.items = [];
    this.init();
  }
  
  init() {
    on(this.element, 'mousedown', this.handleMouseDown.bind(this));
    this.handleMouseMove = throttle(this.handleMouseMove.bind(this), 16);
  }
  
  handleMouseDown(evt) {
    const item = closest(evt.target, '.draggable-item', this.element);
    if (!item) return;
    
    this.draggedItem = item;
    css(item, 'opacity', '0.5');
    
    on(document, 'mousemove', this.handleMouseMove);
    on(document, 'mouseup', this.handleMouseUp.bind(this));
  }
  
  handleMouseMove(evt) {
    if (!this.draggedItem) return;
    css(this.draggedItem, 'transform', `translate(${evt.clientX}px, ${evt.clientY}px)`);
  }
  
  handleMouseUp() {
    if (this.draggedItem) {
      css(this.draggedItem, 'opacity', '');
      css(this.draggedItem, 'transform', '');
      this.draggedItem = null;
    }
    
    off(document, 'mousemove', this.handleMouseMove);
    off(document, 'mouseup', this.handleMouseUp);
  }
}

Framework Integration Helper

Using utilities to integrate with UI frameworks:

const { on, off, nextTick } = Sortable.utils;

class ReactSortableHelper {
  static attachToRef(ref, options, onOrderChange) {
    if (!ref.current) return null;
    
    const sortable = Sortable.create(ref.current, {
      ...options,
      onEnd: (evt) => {
        nextTick(() => {
          // Ensure React state updates after DOM changes
          const newOrder = sortable.toArray();
          onOrderChange(newOrder);
        });
        
        options.onEnd && options.onEnd(evt);
      }
    });
    
    return sortable;
  }
  
  static detachFromRef(sortable) {
    if (sortable) {
      sortable.destroy();
    }
  }
}

Install with Tessl CLI

npx tessl i tessl/npm-sortablejs

docs

configuration.md

core-api.md

events.md

index.md

plugins.md

utilities.md

tile.json