UNPKG

tiny-essentials

Version:

Collection of small, essential scripts designed to be used across various projects. These simple utilities are crafted for speed, ease of use, and versatility.

461 lines (279 loc) โ€ข 12.9 kB
# ๐Ÿงฒ TinyDragger TinyDragger enables customizable **drag-and-drop** behavior for HTML elements. It supports visual proxies, jail boundaries, collision detection, vibration feedback, drop restrictions, and custom events โ€” all with a lightweight and flexible architecture. --- ## โœจ Features - ๐Ÿ–ฑ๏ธ Mouse & touch drag support - ๐Ÿ”’ Jail constraints to restrict dragging area - ๐Ÿ’ฅ Collision detection with other elements - ๐Ÿ”„ Auto-revert to original position - ๐ŸŽฎ Vibration feedback via `navigator.vibrate()` - ๐Ÿ‘ป Visual clone during drag (proxy) - ๐ŸŽจ Fully configurable class names - ๐Ÿ“ฆ Clean destroy method with memory-safe teardown - ๐Ÿ”” Custom drag and drop events --- ## ๐Ÿ“ฆ Installation ```js import TinyDragger from './TinyDragger.js'; ``` --- ## ๐Ÿงฐ Constructor ```ts new TinyDragger(targetElement, options?) ``` ### Parameters: | Name | Type | Default | Description | | --------------- | ------------- | ------------ | --------------------------------- | | `targetElement` | `HTMLElement` | **required** | The element to enable dragging on | | `options` | `Object` | `{}` | Optional configuration | ### Options: | Option | Type | Default | Description | | ----------------------- | ------------------------------ | ---------------------- | ----------------------------------------------------------- | | `jail` | `HTMLElement` | `null` | Optional container that restricts movement | | `collisionByMouse` | `boolean` | `false` | Use mouse position instead of bounding box for collision | | `classDragging` | `string` | `'dragging'` | Class applied to the clone element | | `classBodyDragging` | `string` | `'drag-active'` | Class applied to the `<body>` during dragging | | `classJailDragging` | `string` | `'jail-drag-active'` | Class applied to jail while dragging | | `classJailDragDisabled` | `string` | `'jail-drag-disabled'` | Class applied to jail when dragging is disabled | | `classDragCollision` | `string` | `'dragging-collision'` | Class applied to elements when collision is detected | | `classHidden` | `string` | `'drag-hidden'` | Class used to hide the original element while dragging | | `lockInsideJail` | `boolean` | `false` | Prevent drag from exceeding jail bounds | | `dropInJailOnly` | `boolean` | `false` | Prevent drop outside the jail area | | `multiCollision` | `boolean` | `false` | Enables returning multiple collided elements | | `vibration` | `VibrationPatterns` or `false` | `false` | Vibration feedback configuration | | `revertOnDrop` | `boolean` | `false` | Return to original position after dropping | | `mirrorElem` | `boolean` | `true` | Use a visual clone instead of dragging the original element | | `defaultZIndex` | `number` | `9999` | Sets the z-index value applied when dragging starts | --- ## ๐Ÿ“ณ Vibration Patterns ```ts type VibrationPatterns = { start: number[] | false, end: number[] | false, collide: number[] | false, move: number[] | false } ``` --- ## ๐Ÿ“š Public Methods ### `enable()` ๐Ÿ”“ Re-enables dragging after being disabled. --- ### `disable()` ๐Ÿšซ Temporarily disables dragging. Still allows re-enabling later. --- ### `destroy()` ๐Ÿ’ฃ Fully disables the instance, removes event listeners, and clears any DOM state. --- ### `addCollidable(element: HTMLElement)` โž• Adds an element to the collision tracking list. ๐Ÿ›‘ Throws if the element is not a valid `HTMLElement`. --- ### `removeCollidable(element: HTMLElement)` โž– Removes an element from the collision list. ๐Ÿ›‘ Throws if the element is not a valid `HTMLElement`. --- ### `setVibrationPattern({ startPattern, endPattern, collidePattern, movePattern })` ๐Ÿ“ณ Updates the vibration patterns used during drag events. Each pattern must be either `false` or an array of numbers. --- ### `disableVibration()` ๐Ÿ”• Turns off all vibration feedback. --- ### `getOffset(event: MouseEvent | Touch): { x: number, y: number }` ๐Ÿ“ Returns the X and Y offset from the event to the top-left corner of the element. ๐Ÿ›‘ Throws if the event is invalid. --- ### `getCollidedElementByRect(rect: DOMRect): HTMLElement | null` ๐ŸŽฏ Detects if a `DOMRect` collides with any registered collidable elements. ๐Ÿ›‘ Throws if the rect is invalid. --- ### `getAllCollidedElementsByRect(rect: DOMRect): HTMLElement[]` ๐Ÿ“Œ Returns **all elements** currently intersecting the given rectangle. Useful for detecting multiple overlaps when dragging. ๐Ÿ›‘ Throws if `rect` is not a valid `DOMRect` with numeric `left`, `right`, `top`, and `bottom` properties. --- ### `getCollidedElement(x: number, y: number): HTMLElement | null` ๐Ÿ“Œ Detects if the given screen coordinates collide with any tracked element. ๐Ÿ›‘ Throws if `x` or `y` is not a number. --- ### `getAllCollidedElements(x: number, y: number): HTMLElement[]` ๐Ÿ“Œ Detects **all elements** currently under the given screen coordinates. Works well when `collisionByMouse` is enabled. ๐Ÿ›‘ Throws if `x` or `y` is not a number. --- ### `getDragging(): boolean` ๐Ÿ”„ Returns whether dragging is currently active. --- ### `getLockInsideJail(): boolean` ๐Ÿ”’ Returns whether movement is restricted inside the jail container. --- ### `setLockInsideJail(value: boolean): void` โš™๏ธ Sets whether movement is restricted inside the jail container. ๐Ÿ›‘ Throws if `value` is not a boolean. --- ### `getRevertOnDrop(): boolean` โ†ฉ๏ธ Returns whether the element should revert to its original position on drop. --- ### `setRevertOnDrop(value: boolean): void` โš™๏ธ Sets whether the element should revert to its original position on drop. ๐Ÿ›‘ Throws if `value` is not a boolean. --- ### `getCollisionByMouse(): boolean` ๐Ÿ–ฑ๏ธ Returns whether collision detection uses mouse position instead of element bounding rectangles. --- ### `setCollisionByMouse(value: boolean): void` โš™๏ธ Sets whether collision detection uses mouse position instead of element bounding rectangles. ๐Ÿ›‘ Throws if `value` is not a boolean. --- ### `getDropInJailOnly(): boolean` ๐Ÿšซ Returns whether dropping is restricted inside the jail container. --- ### `setDropInJailOnly(value: boolean): void` โš™๏ธ Sets whether dropping is restricted inside the jail container. ๐Ÿ›‘ Throws if `value` is not a boolean. --- ### `checkDragCollision(event: MouseEvent | Touch): void` ๐ŸŽฏ Checks for collision between the drag proxy and registered elements. ๐Ÿ’ฅ Applies or removes the collision class depending on overlap. ๐Ÿ“ณ Triggers vibration if configured. --- ### `execCollision(event: MouseEvent | Touch): { inJail: boolean; collidedElement: HTMLElement | null }` ๐Ÿงฉ Executes collision detection logic based on the drag position and mode. ๐Ÿ“ Uses either the mouse point or the proxy rectangle depending on `collisionByMouse`. ๐Ÿ”’ Respects `dropInJailOnly` and jail boundaries. ๐Ÿ›‘ Returns `{ inJail: false, collidedElement: null }` if dragging is not active. --- ### `getTarget(): HTMLElement` ๐ŸŽฏ Returns the original element being dragged. --- ### `getJail(): HTMLElement | null` ๐Ÿšง Returns the jail container element if one is set. Returns `null` if no jail is configured. --- ### `getDragProxy(): HTMLElement | null` ๐Ÿ‘ป Returns the current proxy (clone) element being dragged. Returns `null` if no proxy is active. --- ### `getLastCollision(): HTMLElement | null` ๐Ÿ’ฅ Returns the last collided element (if any). --- ### `getCollidables(): HTMLElement[]` ๐Ÿงฒ Returns the list of elements that are considered for collision detection. --- ### `getDragHiddenClass(): string` ๐Ÿ‘€ Returns the CSS class used to hide the original element during dragging. --- ### `getClassDragging(): string` ๐ŸŽฌ Returns the CSS class applied to the clone while it is being dragged. --- ### `getClassBodyDragging(): string` ๐Ÿง Returns the CSS class applied to `<body>` when dragging is active. --- ### `getClassJailDragging(): string` ๐Ÿ—๏ธ Returns the CSS class applied to the jail element while dragging is active. --- ### `getClassJailDragDisabled(): string` ๐Ÿšซ Returns the CSS class applied to the jail when dragging is disabled. --- ### `getClassDragCollision(): string` โš ๏ธ Returns the CSS class applied to elements when a collision is detected. --- ### `getVibrations(): { start: number[] | false, end: number[] | false, collide: number[] | false, move: number[] | false }` ๐ŸŽต Returns the full vibration pattern configuration used during dragging. --- ### `getStartVibration(): number[] | false` ๐Ÿ“ณ Returns the vibration pattern used at the **start** of a drag. --- ### `getEndVibration(): number[] | false` ๐Ÿ“ด Returns the vibration pattern used at the **end** of a drag. --- ### `getCollideVibration(): number[] | false` ๐ŸŽฏ Returns the vibration pattern used when **colliding** with another element. --- ### `getMoveVibration(): number[] | false` ๐Ÿšถ Returns the vibration pattern used during **movement** while dragging. --- ### `isEnabled(): boolean` โœ… Returns whether the drag-and-drop functionality is currently enabled. --- ### `getDefaultZIndex(): number` ๐ŸŽฏ Returns the current default `z-index` used when a draggable item is picked up. --- ### `setDefaultZIndex(newZIndex: number): void` ๐Ÿ› ๏ธ Sets a new default `z-index` to be used during drag operations. > Throws `TypeError` if `newZIndex` is not a finite number. --- ### `isMirrorEnabled(): boolean` ๐ŸŽฏ Returns whether the draggable element uses a **mirror** (`true`) or the **original element** (`false`) during dragging. --- ### `setMirrorEnabled(useMirror: boolean): void` ๐Ÿ› ๏ธ Defines whether the draggable element should use a **mirror clone** or move the **original element**. > Throws `TypeError` if `useMirror` is not a boolean. --- ## ๐Ÿ” Events The target element will emit these events: | Event | Description | | ---------- | ------------------------------------------------ | | `drag` | Fired at the beginning of a drag | | `dragging` | Continuously fired while dragging | | `drop` | Fired at the end of the drag with collision info | ### Example: ```js targetEl.addEventListener('drop', (e) => { console.log('Dropped on:', e.detail.target); }); ``` --- ## ๐Ÿ›ก๏ธ Error Handling * Throws errors if the constructor options are of invalid types. * Throws if using destroyed instances (`destroy()` has been called). * Throws on invalid usage of methods like `addCollidable` or `getOffset`. --- ## โœ… Example ```js const box = document.getElementById('draggableBox'); const jail = document.getElementById('jailContainer'); const dragger = new TinyDragger(box, { jail, lockInsideJail: false, collisionByMouse: false, revertOnDrop: false, vibration: { start: [30], move: [5], collide: [80], end: [20, 10, 20], }, }); const dropTarget = document.getElementById('dropArea'); dragger.addCollidable(dropTarget); box.addEventListener('drop', (e) => { if (e.detail.target === dropTarget) { alert('Dropped successfully!'); } }); ``` --- ## ๐Ÿงผ Clean-Up Call `.destroy()` to completely remove drag behavior and all event listeners: ```js dragger.destroy(); ``` --- ## ๐Ÿงช Testing & Styling * ๐ŸŽจ **Example Stylesheets:** You can find optional example styles to get started or test layout integration in: ``` dist/v1/css/TinyDraggerExample.css dist/v1/css/TinyDraggerExample.min.css ``` * ๐Ÿงฑ **Test Environment:** A ready-to-use HTML test page is available at: ``` test/html/TinyDragger ``` This includes practical demos and scenarios to test dragging, collision, jail constraints, and more. --- ## ๐Ÿง  Notes * Touch support uses the first touch point only. * Make sure your draggable element has `position: relative` or `absolute` if itโ€™s meant to be positioned manually after drop.