Drag/Drop Manager

A common use case in the sorts of applications for which the Toolkit is useful is the requirement to be able to
drag and drop new nodes/groups onto the workspace. Surface widgets already support this concept via the
registerDroppableNodes method, but the Drop Manager, an optional new include from version 1.13.1 onwards, offers
a more flexible approach to achieving the same goal.

Briefly, the Drop Manager offers:

the ability to drag objects onto the whitespace of the canvas

the ability to drag object onto groups or nodes

the ability to drag objects onto edges

the ability to disable the drag/drop functionality programmatically

The Surface's registerDroppableNodes method (discussed here )offers the first two of these points, but not the second two, and,
importantly, it requires either that the draggable nodes be present in the DOM at the time that the method is called,
or that you refresh the handle returned from the method if you make changes to the DOM and you wish the drag/drop
functionality to track those changes. The Drop Manager attaches a delegated event handler to the object containing
items you wish to drag, and does not need to be refreshed when changes are made.

At some point in the future, registerDroppableNodes will be deprecated on the Surface widget, and eventually removed.

Basic Example

newjsPlumbToolkitDropManager({surface:SomeSurfaceWidget,source:someHTMLElementContainingDraggableChildren,selector:".draggable-child",onDrop:function(data,target,draggedElement,event,position){console.log("drop on node or group",arguments);},onCanvasDrop:function(data,canvasPosition,draggedElement,event,position){console.log("drop on canvas",arguments);},onEdgeDrop:function(data,target,draggedElement,event,position){console.log("drop on edge",arguments);}})

The arguments here are:

surface Required. Identifies the Surface widget with which to interact

Our dataGenerator here extracts the value of the data-type attribute on the element being dragged, and
returns it in an object. The return value of the dataGenerator is what is passed in as the data argument to
the various drop methods.

Controlling drop targets

You can control which parts of the Surface act as drop targets. Here we'll disable everything except dropping
on edges:

newjsPlumbToolkitDropManager({surface:SomeSurfaceWidget,source:someHTMLElementContainingDraggableChildren,selector:".draggable-child",allowDropOnNodesOrGroups:false,allowDropOnCanvas:false,allowDropOnEdges:true,dataGenerator:function(el){return{type:el.getAttribute("data-type")}},onEdgeDrop:function(data,target,draggedElement,event,position){console.log("drop on edge",arguments);}})

Note that the default value for any allowDropOn*** flag is true, so in this case we did not need to include
allowDropOnEdges:true, we just did it to show you the flag.

Filtering drop targets

In addition to setting any of the allowDropOn*** flags, you can use filters to exclude elements at drag time.
In this example we'll filter out any node/group that has foo:true in its data:

newjsPlumbToolkitDropManager({surface:SomeSurfaceWidget,source:someHTMLElementContainingDraggableChildren,selector:".draggable-child",allowDropOnCanvas:false,allowDropOnEdges:false,dropFilter:function(data,nodeOrGroup){returnnodeOrGroup.data.foo!==true;},onDrop:function(data,target,draggedElement,event,position){console.log("drop on node or group",arguments);}})

The method signature for dropFilter is:

exporttypeDropFilter<T>=(data:T,target:Node|Group)=>boolean;

It is also possible, when drag starts, to decide whether or not you want the dragged element to be droppable
on the canvas:

newjsPlumbToolkitDropManager({surface:SomeSurfaceWidget,source:someHTMLElementContainingDraggableChildren,selector:".draggable-child",allowDropOnCanvas:false,allowDropOnEdges:false,canvasDropFilter:function(data){returndata.type==="someDroppableOnCanvasType";},onDrop:function(data,canvasPosition,draggedElement,event,position){console.log("drop on canvas",arguments);}})

In order to use these classes for visual cues in the UI, you'll probably want to define slightly different selectors for each target type. Let's
suppose when a drag starts we want to outline our canvas and any nodes/groups with a purple line, and we want to draw any possible target edges with a purple line too:

Usage from within Typescript

The Drop Manager takes a type parameter T that identifies the type of data that your dataGenerator function is
going to return. You'll see the type T listed in various function definitions above; if you are not using Typescript
then this type parameter disappears and you don't need to think about it.