Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

HTML5 Drag-and-Drop implemented as Svelte actions

License

NotificationsYou must be signed in to change notification settings

rozek/svelte-drag-and-drop-actions

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

a lightweight but flexible HTML5 Drag-and-Drop implemented as Svelte actions

some of its Features:

All examples are live and may be changed on the fly!

  • HTML5 drag-and-drop features remain available (seeexample)
  • works on mobile devices (when combined withsvelte-drag-drop-touch)
  • supports custom drag images (from existing DOM elements orfrom HTML markup)
  • drag images may even be dynamically created (seeexample)
  • supports simple dragging (i.e., without dropping, seeexample, don't worry if the example seems to lag - it's just because of the amount of console output)
  • provides mechanisms to reduce the code needed to implement element dragging (seeexample)
  • can restrict dragging to a given region (seeexample)
  • supports automatic scrolling (aka "panning") of partially visible elements while s.th. is dragged over them (seeexample), works fine even on Chrome for desktop (which already provides panning out of the box)
  • can mimicreal dragging of an element (and not just of a "ghost image" while the original stands still, see many examples, f.e.this one)
  • can suppress the drag image at all (offering a bunch of new possibilites using the same code base, see many of the examples, f.e.this one)
  • supports dragging elements from a given handle only (instead of the whole element itself, seeexample)
  • offers visual feedback of dragged elements and drop zones by simple styling (using dynamically assigned CSS classes, see several examples, such asthis one)
  • recognizes when a draggable stands still (i.e., it's "held") over a drop zone for a given time (seeexample)
  • provides lots of live(!)examples for many use cases
  • however, unfortunately,svelte-drag-and-drop-actions may also suffer from any bugs in the browser implementations of native HTML drag-and-drop (thinking of Safari 13.0/13.1, f.e.) if they can not be compensated by the author

HTML5 Drag-and-Drop allows web applications to provide a visual user interface for transfering data between HTML elements or exchanging data with a browser's environment. Using HTML5 Drag-and-Drop for theoperation of an application (i.e. the repositioning, resizing or reordering of elements) is difficult and suffers from some browser-specific bugs.

Instead of fully re-implementing the visual operation of web applications with mouse and touch gestures (as done inagnostic-draggable orsvelte-dnd-action),svelte-drag-and-drop-actions builds upon already existing HTML5 Drag-and-Drop functionality and simply extends it. The result is a lightweight package with a surprisingly simple programming interface. (And because this module is tree-shakable, using the plain dragging functionality only - i.e., without support for dropping - will reduce the import size even further)

A first Svelte component based onsvelte-drag-and-drop-actions is thesvelte-sortable-flat-list-view.

But try yourself: there are a number ofexamples that can be tried out live

NPM users: please consider theGithub README for the latest description of this package (as updating the docs would otherwise always require a new NPM package version)

Mobile Developers: since many mobile platforms lack support for native HTML5 drag-and-drop, you should consider importingsvelte-drag-drop-touch as a polyfill (a simple import of that package will suffice - there is no extra programming needed)

Firefox Users: because of an old but still unfixedbug in Mozilla Firefox, svelte-drag-and-drop-actions do not work properly in Firefox browsers. Right now, I have no idea how to work around that bug without affecting other browsers and in a way that survives the moment when Mozilla finally fixes that bug...

Just a small note: if you like this module and plan to use it, consider "starring" this repository (you will find the "Star" button on the top right of this page), so that I know which of my repositories to take most care of.

Installation

npm install svelte-drag-and-drop-actions

Usage Example

The following example illustrates plain dragging of a "Draggable" within the bounds of a given "Arena". Read on to understand how it is working.

<scriptcontext="module">importDragDropTouchfrom'svelte-drag-drop-touch'// for mobile platformsimport{asDraggable}from'svelte-drag-and-drop-actions'</script><script>letDraggableX=20,DraggableY=20,DraggableWidth=80,DraggableHeight=30letArenaWidth=400,ArenaHeight=400functiononDragMove(x,y,dx,dy){DraggableX=x;DraggableY=y}functiononDragEnd(x,y,dx,dy){DraggableX=x;DraggableY=y}</script><divstyle="  display:block; position:relative;  width:{ArenaWidth}px; height:{ArenaHeight}px; margin:20px;  border:dotted 1px black; border-radius:4px;"><divstyle="    display:block; position:absolute;    left:{DraggableX}px; top:{DraggableY}px; width:{DraggableWidth}px; height:{DraggableHeight}px;    background:forestgreen; color:white; line-height:30px; text-align:center; cursor:move;"use:asDraggable={{minX:0,minY:0,maxX:ArenaWidth-DraggableWidth,maxY:ArenaHeight-DraggableHeight,onDragStart:{x:DraggableX,y:DraggableY},onDragMove,onDragEnd}}>Drag me!</div></div>

Additional,more detailled examples can be found below.

Functional Principle

Svelte is a Framework for buildingreactive applications, i.e. it assumes, that there is someapplication state which is used to construct the application's user interface - and whenever any part of this state changes, the corresponding interface elements are updated accordingly.

svelte-drag-and-drop-actions takes this mechanism into account and assumes that position and size of draggable elements are also part of the application's state. For that reason, the module does not perform any dragging, resizing, sorting (or similar) itself but only provides the coordinates and dimensions needed to update state and - in succession - the visual appearance of any affected elements.

Combined with a rather declarative API (designed with the most common use cases in mind), such an approach leads to a lightweight and easily usable module which still offers programmers full control over the actual side-effects of dragging (and dropping)

If this sounds too abstract, just have a look at theexamples: many of them illustrate specific use cases and may therefore serve as a basis for your own development.

Nota bene: since it is based on native HTML5 drag-and-drop,svelte-drag-and-drop-actions principally also allows dragging and dropping between multiple windows (or tabs) of the same browser or even between browsers. To what extent this works, depends on the participating browsers, the data types involved (transferring text often works best), and may also depend on the operating system used.

Exported Types

TypeScript programmers may import the following types in order to benefit from static type checking (JavaScript programmers may simply skip this section):

  • type Position = { x:number, y:number }
    aPosition instance represents a single point in a linearly scaled cartesic coordinate system. It may be considered as the same coordinate system a browser uses when coordinates are measured in pixels (px) - with one important exception: the origin of this system can be chosen by the programmer. An intelligent choice of such an origin may simplify the callbacks provided forsvelte-drag-and-drop-actions and allow to use delivered coordinates, f.e., to set the size of an element directly and without any need for additional calculations.
  • type PositionReference = (
     'parent' | 'body' | string | HTMLElement | SVGElement // | MathMLElement
    )
    aPositionReference specifies, relative to which element the mouse or touch position is measured. This decision becomes important, if the referred element is scrollable and/or its position or size may be changed by external code (which is neither part of this module nor any of the configured callbacks)
  • type DragDummy = (
     string | HTMLElement | SVGElement | 'standard' | 'none' |
     ((DraggableExtras:any, Element:HTMLElement | SVGElement) => HTMLElement | SVGElement)
    )
    aDragDummy specifies which drag image will be shown during dragging (see below for details)
  • type DraggableOptions = {
     Extras?:any, relativeTo?:PositionReference, onlyFrom?:string, neverFrom?:string,
     Dummy?:DragDummy, DummyOffsetX?:number, DummyOffsetY?:number,
     minX?:number, minY?:number, maxX?:number, maxY?:number,
     Pannable?:string|HTMLElement|SVGElement,
     PanSensorWidth?:number, PanSensorHeight?:number, PanSpeed?:number,
     onDragStart?:Position | ((DraggableExtras:any) => Position),
     onDragMove?:(x:number,y:number, dx:number,dy:number, DraggableExtras:any) => void,
     onDragEnd?: (x:number,y:number, dx:number,dy:number, DraggableExtras:any) => void,
    }
    aDraggableOptions instance holds all options for a "Draggable" (see below for details)
     
  • type DropOperation = 'copy'|'move'|'link'
    aDropOperation specifies whether the data associated with a droppable element should be copied, moved or linked to a drop target (native HTML5 drag-and-drop jargon calls this an "effect")
  • type DataOfferSet = { [Type:string]:string }
    DataOfferSet instances are dictionaries listing the various data formats offered by a droppable object and the actually offered data for every format. The keys into aDataOfferSet are often MIME types (or the special value "DownloadURL") but could well be any kind of string (exceptnone) - a detail which is often used to overcome some limitations of native HTML 5 drag-and-drop
  • type DroppableOptions = DraggableOptions & {
     Extras?:any, Operations?:string, DataToOffer?:DataOfferSet,
     onDropZoneEnter?:(x:number,y:number, DropZoneExtras:any, DroppableExtras:any) => void,
     onDropZoneHover?:(x:number,y:number, DropZoneExtras:any, DroppableExtras:any) => void,
     onDropZoneLeave?:(DropZoneExtras:any, DroppableExtras:any) => void,
     onDropped?: (x:number,y:number, Operation:DropOperation,
         TypeTransferred:string, DataTransferred:any, DropZoneExtras:any, DroppableExtras:any) => void
     }
    aDroppableOptions instance holds allextra options for a "Droppable" (please note, that this includes allDraggableOptions shown above, see below for details)
     
  • type TypeAcceptanceSet = { [Type:string]:string }
    TypeAcceptanceSet instances are dictionaries listing the various data formats accepted by a drop zone and the permitted drop operations for every format. The keys into aTypeAcceptanceSet are the same as for the abovementionedDataOfferSets
  • type DropZoneOptions = {
     Extras?:any, TypesToAccept?:TypeAcceptanceSet, HoldDelay?:number,
     Pannable?:string|'this'|HTMLElement|SVGElement,
     PanSensorWidth?:number, PanSensorHeight?:number, PanSpeed?:number,
     onDroppableEnter?: (x:number,y:number, Operation:DropOperation,
         offeredTypeList:string[], DroppableExtras:any, DropZoneExtras:any) => boolean|undefined,
     onDroppableMove?: (x:number,y:number, Operation:DropOperation,
         offeredTypeList:string[], DroppableExtras:any, DropZoneExtras:any) => boolean|undefined,
     onDroppableHold?: (x:number,y:number, DroppableExtras:any, DropZoneExtras:any) => void,
     onDroppableLeave?: (DroppableExtras:any, DropZoneExtras:any) => void,
     onDrop?: (x:number,y:number, Operation:DropOperation,
         DataOffered:any, DroppableExtras:any, DropZoneExtras:any) => string,
    }
    aDropZoneOptions instance holds all options for a drop target (see below for details)

use:asDraggable

use:asDraggable should be used for elements which will only be dragged around (but never dropped onto another element). Many use cases (from draggable windows over draggable nodes of graphical shapes to the resize handles found in many visual designers) only need this kind of behaviour.

The type annotiations shown below are relevant for TypeScript programmers only, JavaScript programmers may simply ignore them.

use:asDraggable={options}

is the classical pattern for Svelte actions.use:asDraggable supports the following options (bundled into an instance of typeDraggableOptions):

  • Extras?:any
    Extras are an optional, user-defined value which can be used during drag-and-drop operations within the same application to identify the draggable component. They become useful as soon as multiple draggables share the same callbacks
     
  • relativeTo?:PositionReference
    relativeTo is an optionalPositionReference (defaulting toparent) which specifies relative to which element the current mouse or touch position is measured during dragging. It may be set tobody for measurements relative to the current document body, toparent for measurements relative to the draggable's containing element, to a CSS selector for measurements relative to the Draggable's closest element matching the given selector (or 'body' otherwise) or to a given HTML or SVG element (which must be part of the document)
  • onlyFrom?:string
    onlyFrom is an optional, comma-separated list of CSS selectors identifying the inner elements of a draggable element, from which a drag operation must be started in order to be allowed. IfonlyFrom is missing, noonlyFrom restriction is applied
  • neverFrom?:string
    neverFrom is an optional, comma-separated list of CSS selectors identifying the inner elements of a draggable element, from which a drag operation mustnever be started in order to be allowed. IfneverFrom is missing, noneverFrom restriction is applied
     
  • Dummy?:DragDummy
    Dummy specifies which "drag image" to show at the current mouse or touch position during dragging.Dummy is optional (defaulting tonone) and may be set tostandard (for the HTML5 standard behaviour which usually shows a semi-transparent copy of the actual draggable), tonone (effectively showing nothing), to some HTML code (which is used to construct the element to be shown during dragging), to a function which receives the draggable's configured extras and the element to be dragged as its arguments and returns an HTML element to be used as the drag dummy or to an already existing HTML element (which must be visible).Important: creating a drag image from HTML or from a function is quite tricky - the approach used here is lightweight but may cause some flickering when dragging is started. Such flickering can usually be avoided by setting the CSS "overflow" of the document body to "hidden". Where this is not possible, constructing an image from HTML usinghtml2canvas may be an (albeit no longer lightweight) alternative. If a function is used to construct the dummy, that function should also care itself about removing the newly created HTML element after use (see below for a suitable example)
  • DummyOffsetX?:number
    DummyOffsetX is an optional number (defaulting to 0) specifying the horizontal offset between the current x position of a mouse or finger during dragging and the shown drag image. It is used ay the second argument toDataTransfer.setDragImage without prior change
  • DummyOffsetY?:number
    DummyOffsetY is an optional number (defaulting to 0) specifying the vertical offset between the current y position of a mouse or finger during dragging and the shown drag image. It is used ay the third argument toDataTransfer.setDragImage without prior change
     
  • minX?:number
    minX is an optional number (defaulting to -Infinity) specifying the smallest possible value for thex component of any drag result. Please note: a configured drag image may well be dragged beyond configured limits - for that reason, such limits are most often combined withDummy:'none' to effectively hide the drag image
  • minY?:number
    minY is an optional number (defaulting to -Infinity) specifying the smallest possible value for they component of any drag result. Please note: a configured drag image may well be dragged beyond configured limits - for that reason, such limits are most often combined withDummy:'none' to effectively hide the drag image
  • maxX?:number
    maxX is an optional number (defaulting to Infinity) specifying the largest possible value for thex component of any drag result. Please note: a configured drag image may well be dragged beyond configured limits - for that reason, such limits are most often combined withDummy:'none' tto effectively hide the drag image
  • maxY?:number
    maxY is an optional number (defaulting to Infinity) specifying the largest possible value for they component of any drag result. Please note: a configured drag image may well be dragged beyond configured limits - for that reason, such limits are most often combined withDummy:'none' to effectively hide the drag image
     
  • Pannable?:string|HTMLElement|SVGElement
    some browsers provide automatic scrolling of only partially visible elements while a Draggable is dragged over them - but most do not, which is whysvelte-drag-and-drop-actions implements its own "panning".Pannable is an optional parameter specifying the element which should be scrolled automatically. It should be a (not necessarily immediate) container of the Draggable and may be set to the DOM element itself or a CSS selector which identifies the desired container. If omitted, no panning will be performed.
  • PanSensorWidth?:number
    PanSensorWidth is an optional ordinal number (defaulting to20) which specifies the width (in pixels) of the horizontal pan sensor area: panning starts as soon as the mouse pointer (or finger) gets closer than the given number of pixels to the left or right border of the configuredPannable. If set to0, no horizontal panning will be performed
  • PanSensorHeight?:number
    PanSensorHeight is an optional ordinal number (defaulting to20) which specifies the height (in pixels) of the vertical pan sensor area: panning starts as soon as the mouse pointer (or finger) gets closer than the given number of pixels to the upper or lower border of the configuredPannable. If set to0, no vertical panning will be performed
  • PanSpeed?:number
    PanSpeed is an optional ordinal number (defaulting to10) which specifies the "speed" of automatic scrolling - values in the range of 10...20 are reasonable choices, but it is always a good idea to make this parameter configurable for the users of your application. If set to0, no panning will be performed
     
  • onDragStart?:Position | ((DraggableExtras:any) => Position)
    onDragStart is either an optionalPosition (defaulting to{x:0, y:0}) or a function returning such aPosition. When invoked, that function receives anyExtras configured for the affected draggable. In either case, this parameter specifies the coordinate values from which to start dragging.Important: these "coordinates" do not necessarily represent a particular point on the screen - in fact, e.g., a resize handle may choose to start with the current width and height of the element to be resized and then directly use the results of anyonDragMove oronDragEnd as the new element width and height without additional computation
  • onDragMove?: (x:number,y:number, dx:number,dy:number, DraggableExtras:any) => void
    onDragMove is an optional callback which (if given) is called repeatedly during dragging. When invoked, it receives the current drag result (inx andy, with an initial value chosen byonDragStart), the offset between this and the previous invocation (indx anddy) and anyExtras configured for the affected draggable
  • onDragEnd?: (x:number,y:number, dx:number,dy:number, DraggableExtras:any) => void
    onDragEnd is is an optional callback which (if given) is called once when dragging has finished. When invoked, it receives the final drag result (inx andy, with the origin chosen byonDragStart), the offset between this and the most recent invocation ofonDragMove (indx anddy) and anyExtras configured for the affected draggable

While being dragged, the CSS classdragged is assigned to the draggable element (not the drag image!). It will be removed again as soon as dragging has ended.

use:asDraggable should never be combined withuse:asDroppable (as the latter already includes the former) - if you want an element to be dropped somewhere, simply useuse:asDroppable alone.

use:asDraggable may, however, be combined withuse:asDropZone in order to implement draggable drop zones.

use:asDroppable

use:asDroppable is an extension ofuse:asDraggable and should be used for elements which will not only be dragged around but also dropped onto another element. Because of the underlying HTML5 drag-and-drop, dropping an element onto another one may lead to an exchange of data - butsvelte-drag-and-drop-actions extends that functionality (for elements within the same application) and gives the programmer full control over what a "drop" will trigger (you could even delegate the actual action to take after dropping to the droppable, which sometimes turns out to be easier than the "classical" approach where the drop target is responsible)

Warning: some platforms show proper feedback while dragging a droppable over a drop target only forcopy as configured drop operation.

The type annotiations shown below are relevant for TypeScript programmers only, JavaScript programmers may simply ignore them.

use:asDroppable={options}

is the classical pattern for Svelte actions.use:asDroppable supports the following options (some of them being equal or, at least, similar to those listed underuse:asDraggable):

  • Extras?:any
    Extras are an optional, user-defined value which can be used during drag-and-drop operations within the same application to identify the droppable component or its associated data. They become useful as soon as multiple droppables share the same callbacks
     
  • relativeTo?:PositionReference
    relativeTo is an optionalPositionReference (defaulting toparent) which specifies relative to which element the current mouse or touch position is measured during dragging. It may be set tobody for measurements relative to the current document body, toparent for measurements relative to the draggable's containing element, to a CSS selector for measurements relative to the Draggable's closest element matching the given selector (or 'body' otherwise) or to a given HTML or SVG element (which must be part of the document)
  • onlyFrom?:string
    onlyFrom is an optional, comma-separated list of CSS selectors identifying the inner elements of a droppable element, from which a drag-and-drop operation must be started in order to be allowed. IfonlyFrom is missing, noonlyFrom restriction is applied
  • neverFrom?:string
    neverFrom is an optional, comma-separated list of CSS selectors identifying the inner elements of a droppable element, from which a drag-and-drop operation mustnever be started in order to be allowed. IfneverFrom is missing, noneverFrom restriction is applied
     
  • Dummy?:DragDummy
    Dummy specifies which "drag image" to show at the current mouse or touch position during dragging.Dummy is optional (defaulting tostandard) and may be set tonone (effectively showing nothing), tostandard (for the HTML5 standard behaviour which usually shows a semi-transparent copy of the actual draggable), to some HTML code (which is used to construct the element to be shown during dragging), to a function which receives the draggable's configured extras and the element to be dragged as its arguments and returns an HTML element to be used as the drag dummy or to an already existing HTML element (which must be visible).Important: creating a drag image from HTML is quite tricky - the approach used here is lightweight but may cause some flickering when dragging is started. Such flickering can usually be avoided by setting the CSS "overflow" of the document body to "hidden". Where this is not possible, constructing an image from HTML usinghtml2canvas may be an (albeit no longer lightweight) alternative. If a function is used to construct the dummy, that function should also care itself about removing the newly created HTML element after use (see below for a suitable example)
  • DummyOffsetX?:number
    DummyOffsetX is an optional number (defaulting to 0) specifying the horizontal offset between the current x position of a mouse or finger during dragging and the shown drag image. It is used ay the second argument toDataTransfer.setDragImage without prior change
  • DummyOffsetY?:number
    DummyOffsetY is an optional number (defaulting to 0) specifying the vertical offset between the current y position of a mouse or finger during dragging and the shown drag image. It is used ay the third argument toDataTransfer.setDragImage without prior change
     
  • minX?:number
    minX is an optional number (defaulting to -Infinity) specifying the smallest possible value for thex component of any drag result. Please note: a configured drag image may well be dragged beyond configured limits - for that reason, such limits are most often combined withDummy:'none' to effectively hide the drag image
  • minY?:number
    minY is an optional number (defaulting to -Infinity) specifying the smallest possible value for they component of any drag result. Please note: a configured drag image may well be dragged beyond configured limits - for that reason, such limits are most often combined withDummy:'none' to effectively hide the drag image
  • maxX?:number
    maxX is an optional number (defaulting to Infinity) specifying the largest possible value for thex component of any drag result. Please note: a configured drag image may well be dragged beyond configured limits - for that reason, such limits are most often combined withDummy:'none' tto effectively hide the drag image
  • maxY?:number
    maxY is an optional number (defaulting to Infinity) specifying the largest possible value for they component of any drag result. Please note: a configured drag image may well be dragged beyond configured limits - for that reason, such limits are most often combined withDummy:'none' to effectively hide the drag image
     
  • Pannable?:string|HTMLElement|SVGElement
    some browsers provide automatic scrolling of only partially visible elements while a Draggable is dragged over them - but most do not, which is whysvelte-drag-and-drop-actions implements its own "panning".Pannable is an optional parameter specifying the element which should be scrolled automatically. It should be a (not necessarily immediate) container of the Draggable and may be set to the DOM element itself or a CSS selector which identifies the desired container. If omitted, no panning will be performed.Please note:Pannables should be configured for Droppables only if panning should solely be performed while these Droppables are dragged over the givenPannable (which then does not necessarily have to be a DropZone). If you want a DropZone to be automatically scrolled when an arbitrary Droppable is dragged over it, configure panning for the DropZone instead. If you want both, configure both - it's safe to do so
  • PanSensorWidth?:number
    PanSensorWidth is an optional ordinal number (defaulting to20) which specifies the width (in pixels) of the horizontal pan sensor area: panning starts as soon as the mouse pointer (or finger) gets closer than the given number of pixels to the left or right border of the configuredPannable. If set to0, no horizontal panning will be performed
  • PanSensorHeight?:number
    PanSensorHeight is an optional ordinal number (defaulting to20) which specifies the height (in pixels) of the vertical pan sensor area: panning starts as soon as the mouse pointer (or finger) gets closer than the given number of pixels to the upper or lower border of the configuredPannable. If set to0, no vertical panning will be performed
  • PanSpeed?:number
    PanSpeed is an optional ordinal number (defaulting to10) which specifies the "speed" of automatic scrolling - values in the range of 10...20 are reasonable choices, but it is always a good idea to make this parameter configurable for the users of your application. If set to0, no panning will be performed
     
  • Operations?:string
    Operations is either a blank-separated list ofDropOperations ('copy','move' or'link'), the keywordall (which includes all three available operations) or the keywordnone (which effectively suppresses dropping) and specifies which kind of data transfer the droppable component is going to support
  • DataToOffer?:DataOfferSet
    DataToOffer is a plain JavaScript object whose keys represent the various data formats a droppable component supports and whose corresponding values contain the transferrable data in that format. Often, the given keys denote MIME formats (which simplifies data transfer between different applications) or contain the special value "DownloadURL", but - in principle - any string (exceptnone) may be used
     
  • onDragStart?:Position | ((DroppableExtras:any) => Position)
    onDragStart is either an optionalPosition (defaulting to{x:0, y:0}) or a function returning such aPosition. When invoked, that function receives anyExtras configured for the affected droppable. In either case, this parameter specifies the coordinate values from which to start dragging.Important: these "coordinates" do not necessarily represent a particular point on the screen - in fact, e.g., a resize handle may choose to start with the current width and height of the element to be resized and then directly use the results of anyonDragMove oronDragEnd as the new element width and height without additional computation
  • onDragMove?: (x:number,y:number, dx:number,dy:number, DroppableExtras:any) => void
    onDragMove is an optional callback which (if given) is called repeatedly during dragging. When invoked, it receives the current drag result (inx andy, with an initial value chosen byonDragStart), the offset between this and the previous invocation (indx anddy) and anyExtras configured for the affected droppable
  • onDragEnd?: (x:number,y:number, dx:number,dy:number, DroppableExtras:any) => void
    onDragEnd is an optional callback which (if given) is called once when dragging has finished. When invoked, it receives the final drag result (inx andy, with the origin chosen byonDragStart), the offset between this and the most recent invocation ofonDragMove (indx anddy) and anyExtras configured for the affected droppable
     
  • onDropZoneEnter?: (x:number,y:number, DropZoneExtras:any, DroppableExtras:any) => void
    onDropZoneEnter is an optional callback which (when invoked) indicates that the droppable has entered the bounds of a drop target which accepts (some of) the given data it offers.x andy contain the current coordinates of the mouse or fingerrelative to the drop zone,DropZoneExtras are anyExtras configured for the entered drop zone andDroppableExtras anyExtras configured for the affected droppable (which becomes useful as soon as multiple droppables share the same callbacks)
  • onDropZoneHover?: (x:number,y:number, DropZoneExtras:any, DroppableExtras:any) => void
    onDropZoneHover is an optional callback which (when invoked) indicates that the droppable is still moving within the bounds of a drop zone which accepts (some of) the given data it offers.x andy contain the current coordinates of the mouse or fingerrelative to the drop zone,DropZoneExtras are anyExtras configured for the hovered drop zone andDroppableExtras anyExtras configured for the affected droppable (which becomes useful as soon as multiple droppables share the same callbacks)
  • onDropZoneLeave?: (DropZoneExtras:any, DroppableExtras:any) => void
    onDropZoneLeave is an optional callback which (when invoked) indicates that the droppable has either just left the bounds of a previously entered drop zone or that drop zone has decided to no longer accept any data offered by the droppable.DropZoneExtras are anyExtras configured for the left drop zone andDroppableExtras anyExtras configured for the affected droppable (which becomes useful as soon as multiple droppables share the same callbacks)
  • onDropped?: (x:number,y:number, Operation:DropOperation, TypeTransferred:string, DataTransferred:any, DropZoneExtras:any, DroppableExtras:any) => void}
    onDropped is an optional callback which (when invoked) indicates that the droppable has just been dropped onto a drop zone - and it could now be up to the droppable to react accordingly (including the possibility to perform the requested operation itself, instead of the drop zone).x andy contain the coordinates of the mouse or fingerrelative to the drop zone when the droppable was dropped,Operation contains the performed drop operation (if known - orundefined otherwise),TypeTransferred indicates the type of the actually transferred data (if known - orundefined otherwise),DataTransferred is the actually transferred data itself (if known - orundefined otherwise),DropZoneExtras are anyExtras configured for the drop zone andDroppableExtras anyExtras configured for the affected droppable (which becomes useful as soon as multiple droppables share the same callbacks)

While being dragged, the CSS classdragged is assigned to the draggable element (not the drag image!). It will be removed again as soon as dragging has ended.

While over a drop zone which accepts (some of) the data offered, the CSS classdroppable is assigned to the draggable element (not the drag image!). It will be removed again as soon as dragging has ended or the droppable has been left.

use:asDraggable should never be combined withuse:asDroppable (as the latter already includes the former) - if you want an element to be dropped somewhere, simply useuse:asDroppable alone.

use:asDroppable may, however, be combined withuse:asDropZone in order to implement draggable drop zones which may itself be dropped over other drop zones.

use:asDropZone

use:asDropZone marks an element as a "drop zone" which allows "droppable" elements to be dropped onto it in order to trigger an operation.

The type annotiations shown below are relevant for TypeScript programmers only, JavaScript programmers may simply ignore them.

use:asDropZone={options}

is the classical pattern for Svelte actions.use:asDropZone supports the following options (bundled into an instance of typeDropZoneOptions):

  • Extras?:any
    Extras are an optional, user-defined value which can be used during drag-and-drop operations within the same application to identify the drop zone component. They become useful as soon as multiple drop zones share the same callbacks
     
  • TypesToAccept?:TypeAcceptanceSet
    TypesToAccept is a plain JavaScript object whose keys represent the various data formats a drop zone accepts and whose corresponding values contain a blank-separated, perhaps empty, list of supported drop operations for that format. Often, the given keys denote MIME formats (which simplifies data transfer between different applications) or contain the special value "DownloadURL", but - in principle - any string (exceptnone) may be used. Note: since native HTML5 drag-and-drop implementations often fail reporting a correct "dropEffect", the given drop operations can not be properly checked - with the exception, that types with empty operation lists will never be accepted
  • HoldDelay?:number
    when a droppable has entered a drop zone and remains there for at leastHoldDelay milliseconds without much movement, theonDroppableHold callback of that drop zone is invoked (if it exists). Such a callback may be used to perform activities such as expanding a collapsed tree list entry, opening an input dialog or similar. The property is optional: when missing,onDroppableHold will never be called
  • Pannable?:string|HTMLElement|SVGElement
    some browsers provide automatic scrolling of only partially visible elements while a Draggable is dragged over them - but most do not, which is whysvelte-drag-and-drop-actions implements its own "panning".Pannable is an optional parameter specifying the element which should be scrolled automatically. It may be set tothis (if the DropZone itself should be scrolled), to the DropZone's own DOM element, the DOM element of a (not necessarily immediate) container of the DropZone, or a CSS selector which identifies such a container. If omitted, no panning will be performed.Please note:Pannables should be configured for DropZones only if panning should always be performed while an arbitrary Droppable is dragged over them. If you want aPannable to be automatically scrolled only when its inner Draggables are dragged over it, configure panning for those Draggables instead (thePannable then does not necessarily have to be a DropZone itself). If you want both, configure both - it's safe to do so
  • PanSensorWidth?:number
    PanSensorWidth is an optional ordinal number (defaulting to20) which specifies the width (in pixels) of the horizontal pan sensor area: panning starts as soon as the mouse pointer (or finger) gets closer than the given number of pixels to the left or right border of the configuredPannable. If set to0, no horizontal panning will be performed
  • PanSensorHeight?:number
    PanSensorHeight is an optional ordinal number (defaulting to20) which specifies the height (in pixels) of the vertical pan sensor area: panning starts as soon as the mouse pointer (or finger) gets closer than the given number of pixels to the upper or lower border of the configuredPannable. If set to0, no vertical panning will be performed
  • PanSpeed?:number
    PanSpeed is an optional ordinal number (defaulting to10) which specifies the "speed" of automatic scrolling - values in the range of 10...20 are reasonable choices, but it is always a good idea to make this parameter configurable for the users of your application. If set to0, no panning will be performed
     
  • onDroppableEnter?: (x:number,y:number, Operation:DropOperation, offeredTypeList:string[], DroppableExtras:any, DropZoneExtras:any) => boolean|undefined
    onDroppableEnter is an optional callback which (when invoked) indicates that a droppable has entered this drop zone and that this droppable's data is at least partially acceptable.x andy contain the current coordinates of the mouse or fingerrelative to the drop zone,Operation is the requested drop operation (if known - orundefined otherwise),offeredTypeList is a JavaScript array containing the offered data "types",DroppableExtras are anyExtras configured for the entering droppable andDropZoneExtras anyExtras configured for the affected drop zone (which becomes useful as soon as multiple drop zones share the same callbacks). The callback should returnfalse if the offered data turns out not to be acceptable after all - or anything else (includingundefined) otherwise
  • onDroppableMove?: (x:number,y:number, Operation:DropOperation, offeredTypeList:string[], DroppableExtras:any, DropZoneExtras:any) => boolean|undefined
    onDroppableMove is an optional callback which (when invoked) indicates that a droppable is still moving within the bounds of this drop zone and that this droppable's data is at least partially acceptable.x andy contain the current coordinates of the mouse or fingerrelative to the drop zone,Operation is the requested drop operation (if known - orundefined otherwise),offeredTypeList is a JavaScript array containing the offered data "types",DroppableExtras are anyExtras configured for the hovering droppable andDropZoneExtras anyExtras configured for the affected drop zone (which becomes useful as soon as multiple drop zones share the same callbacks). The callback should returnfalse if the offered data turns out not to be acceptable after all - or anything else (includingundefined) otherwise
  • onDroppableHold?: (x:number,y:number, DroppableExtras:any, DropZoneExtras:any) => void
    onDroppableHold is an optional callback which (when invoked) indicates that a droppable whose data is at least partially acceptable, stood still for at leastHoldDelay milliseconds within the bounds of this drop zone.x andy contain the current coordinates of the mouse or fingerrelative to the drop zone,DroppableExtras are anyExtras configured for the held droppable andDropZoneExtras anyExtras configured for the affected drop zone (which becomes useful as soon as multiple drop zones share the same callbacks).Warning: be careful with what to do within that callback - if you disturb the flow of events (e.g., by invokingwindow.alert), the visual feedback for drag-and-drop may get mixed up!
  • onDroppableLeave?: (DroppableExtras:any, DropZoneExtras:any) => void
    onDroppableLeave is an optional callback which (when invoked) indicates that a droppable whose data was at least partially acceptable, moved outside the bounds of this drop zone.DroppableExtras are anyExtras configured for the leaving droppable andDropZoneExtras anyExtras configured for the affected drop zone (which becomes useful as soon as multiple drop zones share the same callbacks)
  • onDrop?: (x:number,y:number, Operation:DropOperation, DataOffered:any, DroppableExtras:any, DropZoneExtras:any) => string
    onDrop is an optional callback which (when invoked) indicates that a droppable (whose data is at least partially acceptable) was dropped within the bounds of this drop zone - and it may now be up to the drop zone to perform the requested operation.x andy contain the current coordinates of the mouse or fingerrelative to the drop zone,Operation is the requested drop operation (if known - orundefined otherwise),DataOffered is a JavaScript object, whose keys represent the various data formats offered and whose corresponding values contain the offered data in that format,DroppableExtras are anyExtras configured for the droppable andDropZoneExtras anyExtras configured for the affected drop zone (which becomes useful as soon as multiple drop zones share the same callbacks). The callback should return the data format actually accepted or, at least,undefined to report thatany offered data was accepted - orfalse if the offered data turned out not to be acceptable after all

While being hovered by a droppable whose data offered is at least partially acceptable, the CSS classhovered is assigned to the drop zone element. It will be removed again as soon as either dragging has ended, the droppable has left the drop zone or the droppable's offered data is no longer acceptable.

use:asDropZone may be combined with eitheruse:asDraggable oruse:asDroppable (not both together) in order to implement draggable drop zones which may perhaps itself be dropped over other drop zones.

Examples

Dragging only

Drag-and-Drop

Caveats

Simply extending already existing native HTML5 drag-and-drop functionality has a lot of advantages - but also some disadvantages, as there are:

  • the cursor shown while dragging is under full control of the native drag-and-drop implementation and can not be influenced programmatically (with the minor exception of setting a proper drop operation for a Droppable)
  • a custom drag image must either be an image object or a visible(!) element within the document from which a snapshot is taken
  • the configured drag image can not be changed during dragging as it is constructed when dragging starts and never updated again
  • in some browsers, as soon as the document is scrolled (even a little bit only) a custom drag dummy "slides in" to its designated position when dragging starts rather than appears there from the beginning - this seems to be a browser bug which the author cannot compensate

Build Instructions

You may easily build this package yourself.

Just installNPM according to the instructions for your platform and follow these steps:

  1. either clone this repository usinggit ordownload a ZIP archive with its contents to your disk and unpack it there
  2. open a shell and navigate to the root directory of this repository
  3. runnpm install in order to install the complete build environment
  4. executenpm run build to create a new build

You may also look into the author'sbuild-configuration-study for a general description of his build environment.

License

MIT License

About

HTML5 Drag-and-Drop implemented as Svelte actions

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors2

  •  
  •  

[8]ページ先頭

©2009-2025 Movatter.jp