APIs
DndService is the single class provided in bcx-aurelia-dnd. Technically, it can work with any front-end framework.
DndService Constructor
You don’t need to use constructor in Aurelia app, Aurelia DI (dependency injection) handles creation of shared singleton instance for you.
in Aurelia app, use dependency injection to create shared singleton instance.
in other kind of apps, create a shared instance for the whole app to share.
If you use bcx-aurelia-dnd not in an Aurelia app, you can create an instance manually, like
const dndService = new DndService();
That’s an instance without Aurelia Event Aggregator support. Events 'dnd:willStart', 'dnd:didStart', 'dnd:willEnd', 'dnd:didEnd', 'dnd:didCancel' would not fire.
You can also create an instance with Aurelia Event Aggregator support. Use that sharedEa to subscribe to events.
import {EventAggregator} from 'aurelia-event-aggregator';
const sharedEa = new EventAggregator();
const dndService = new DndService(sharedEa)
Published events through Aurelia Event Aggregator
dnd:willStartjust before starting of DnD session, allisProcessing,model,isHovering… are stillundefined.dnd:didStartjust after starting of DnD session, allisProcessing,model,isHovering… have been set. But none of any targets receiveddndHover()/dndDrop()callback.dnd:willEndjust before end of a DnD session, allisProcessing,model,isHovering… are still set. Just before a target (if there is valid one with canDrop:true under the mouse) receivesdndDrop()callback.dnd:didEndafter a DnD session finished. allisProcessing,model, … are set toundefined. FinaldndDrop()callback has been fired if there is a valid target.dnd:didCancelafter a DnD session is cancelled by ESC key. allisProcessing,model, … are set toundefined. NodndDrop()callback will be called. None ofdnd:willEndanddnd:didEndevents will be fired.
dndService.isProcessing
trueduring a DnD session.undefinedwhen not in a DnD session.
dndService.model
- the
modelobject cached from the result ofsourceDelegate.dndModel().undefinedwhen not in a DnD session.
dndService.addSource(delegate: SourceDelegate, options: SourceOptions)
- typically called inside Aurelia component’s
attached()callback.
Source delegate
TypeScript type import { SourceDelegate } from 'bcx-aurelia-dnd';
- if
options.elementis absent,delegate.dndElementmust be a DOM element, used for source element. - if
options.elementis present,delegate.dndElementis ignored,options.elementis used as source element. delegate.dndModel()is mandatory. Called once, when DnD session starts. It needs to return a model describing the meaning of a drag. There is no requirement on the shape of returned model.delegate.dndCanDrag()is optional. Checked when DnD session starts. If it returns falsy value, the Dnd session would not start from this source delegate. The session could still start from another source delegate whose DOM element is the parent (or ancestor) of this one, aka nested dnd sources.delegate.dndPreview(model)is optional. Called once, when DnD session starts. It needs to return a newly created DOM element, with reasonable size, and not yet attached to DOM tree. Inputmodelis the cached result ofsourceDelegate.dndModel(). It could also return null or undefined, in that case,DndServicewill fall back to use default preview.- if
options.noPreviewis true,delegate.dndPreview(model)is ignored.
dnd property on source delegate
TypeScript type import { SourceDelegateInjectedDnd } from 'bcx-aurelia-dnd';
dndproperty was filled or created (if does not exist) for every source delegate bydndService.delegate.dnd.isProcessingexactly same asdndService.isProcessing.delegate.dnd.isStartingSourcea boolean. During a DnD session, it’struefor the DnD source that the DnD session was started with, false for every other DnD sources..
Source options (optional)
TypeScript type import { SourceOptions } from 'bcx-aurelia-dnd';
options.elementmanually pass a DOM element as source element, instead of defaultdelegate.dndElement.options.handlera DOM element as drag handler. It should be a decedent of source element. It limits where drag can start, doesn’t affect preview.options.noPreviewturn off preview.options.hideCursorhide cursor during a DnD session.options.centerPreviewToMousePositioncenter preview to mouse position. Default preview position is aligned to source element top left corner.
dndService.addTarget(delegate: TargetDelegate, options: TargetOptions)
- typically called inside Aurelia component’s
attached()callback.
Target delegate
TypeScript type import { TargetDelegate } from 'bcx-aurelia-dnd';
- if
options.elementis absent,delegate.dndElementmust be a DOM element, used for target element. - if
options.elementis present,delegate.dndElementis ignored,options.elementis used as target element. delegate.dndCanDrop(model), mandatory. Called once, when DnD session starts. Inputmodelis the cached result ofsourceDelegate.dndModel().delegate.dndDrop(location), mandatory. Called once, when DnD session ends (mouse released) on target element anddelegate.dnd.canDropis true.delegate.dndHover(location), optional. Called every time mouse moves during a DnD session, whendelegate.dnd.canDropis true and eitherdelegate.dnd.isHoveringordelegate.dnd.isHoveringShallowlyis true.- When two (or more) target elements overlap, and both have
delegate.dnd.canDroptrue,dndHover()could be called on both target delegates at same time, butdndDrop()would be only called on the top target.
dnd property on target delegate
TypeScript type import { TargetDelegateInjectedDnd } from 'bcx-aurelia-dnd';
dndproperty was filled or created (if does not exist) for every target delegate bydndService.delegate.dnd.isProcessingexactly same asdndService.isProcessing.delegate.dnd.modelexactly same asdndService.model.delegate.dnd.canDropcached result ofdelegate.dndCanDrop(model).undefinedwhen not in a DnD session.delegate.dnd.isHoveringShallowlytruewhen mouse is hovering directly over target element.undefinedwhen not in a DnD session.delegate.dnd.isHoveringtruewhen mouse is hovering within target element region.undefinedwhen not in a DnD session.
Target options (optional)
TypeScript type import { TargetOptions } from 'bcx-aurelia-dnd';
options.element, manually pass a DOM element as target element, instead of defaultdelegate.dndElement.
Location payload for dndHover(location: DndLocation) and dndDrop(location: DndLocation)
TypeScript type import { DndLocation } from 'bcx-aurelia-dnd';
location.mouseStartAtdrag start mouse location {x, y} (not {left, top}).location.mouseEndAtdrop end mouse location {x, y} fordndDrop(), or current mouse location fordndHover().location.sourceElementRectsource element location and size {x, y, width, height}.location.previewElementRectpreview element location and size {x, y, width, height}.location.targetElementRecttarget element location and size {x, y, width, height}.
All
xandy, are page offset (relative to whole HTML body), not client offset (relative to browser current view-port). Page offset is stabler to use than client offset, especially when there is scrolling or browser zooming.
For convenience,
previewElementRectalways presents. Even if you turn off the preview, it still reports location and size as if you were using default preview.
sourceElementRectis not current location of source element. It is a cached location for the source element when DnD session started.
dndService.removeSource(delegateOrElement: SourceDelegate | Element) and dndService.removeTarget(delegateOrElement: TargetDelegate | Element)
- typically called inside Aurelia component’s
detached()callback.