Version 5.4.0 of the Community edition has support for a new concept - the ability to specify at drag start/stop what the location of an anchor should be, discussed in this post. This functionality is exposed to users of the Toolkit edition by supporting anchorPositionFinder
values in the view.
#
ExampleThis demonstration exhibits the same behaviour shown in the Community edition demonstration linked above: when you drop a connection on the right hand side of an element, its anchor is on the right face; when you drop on the left hand side, the anchor is on the left face.
These are the render params used to create this:
{ layout:{ type:"Absolute" }, defaults:{ anchor:"Continuous", endpoint:"Dot" }, zoomToFit:true, templates:{ "jtk-template-default":'<div data-jtk-source="true" data-jtk-target="true" data-jtk-target-port-type="twosides"></div>' }, view:{ ports:{ twosides:{ anchorPositionFinder:function(el, elxy, vertex) { var x = elxy.x < 0.5 ? 0 : 1, ox = x === 0 ? -1 : 1; return [x, 0.5, ox, 0] } } } }
Aside from the anchorPositionFinder
function itself, the key piece to grok in this setup is the way the node template is hooked up to the view. This is the html for each node:
<div data-jtk-source="true" data-jtk-target="true" data-jtk-target-port-type="twosides"> </div>
So we've got three attributes declared here:
data-jtk-source="true"
Indicates the node is a connection drag sourcedata-jtk-target="true"
Indicates the node is a connection drag targetdata-jtk-target-port-type="twosides"
Tells the Toolkit that this target should use the port definition calledtwosides
, which is where ouranchorPositionFinder
is declared. Note that in the Toolkit you can make use of logical port mappings like this without actually declaring that the target is a port on the node. In this case, the node itself is still the target, but we're using thetwosides
port definition to define some behaviour.
note
In this demonstration we don't declare a node type; instead we use jtk-template-default
as the ID of the template we provide. In the absence of any other information about how to render a node, the Toolkit will look for a template with that ID.
#
Another ExampleTo illustrate the flexibility of this arrangement, let's create something more complex. We'll have three node types - red
, blue
and green
.
red
nodes will just use the default anchors (Continuous
)green
nodes will use the anchor strategy from the first exampleblue
nodes will place an anchor exactly where the connection was dropped.
The render params for this example are as follows:
{ layout:{ type:"Absolute" }, defaults:{ anchor:"Continuous", endpoint:"Dot" }, zoomToFit:true, view:{ nodes:{ red:{ template:'<div data-jtk-source="true" data-jtk-target="true" style="background-color:red"></div>' }, green:{ template:'<div data-jtk-source="true" data-jtk-target="true" style="background-color:mediumseagreen"></div>', anchorPositionFinder:function(el, elxy, vertex) { var x = elxy.x < 0.5 ? 0 : 1, ox = x === 0 ? -1 : 1; return [x, 0.5, ox, 0] } }, blue:{ template:'<div data-jtk-source="true" data-jtk-target="true" style="background-color:cadetblue"></div>', anchorPositionFinder:function(el, elxy, vertex) { return [elxy.x, elxy.y, 0, 0] } } } }}
Here, we map a template for each node type, and then for blue
and green
types, we provide an anchorPositionFinder
. The logic in the finder for green
is as shown in the example above. For the blue
node type, recall that elxy
is the proportional location of the drop event on the drop element. This coordinate system is the same that Anchors use, so we can just return the values from elxy
directly.
Note also that in this example we have declared anchorPositionFinder
on node definitions, whereas in the previous example we declared the position finder on a port definition. You can define them on any vertex definition - node, port or group.
note
If you're new to the Toolkit and you'd like to know more about views, you can read about them in the documentation