Skip to main content

Editing edge paths

JsPlumb supports editing the path of edges for each of the different connector types that JsPlumb ships with. The selection of the appropriate editor tool is managed automatically by JsPlumb.

Setup

To setup your app for path editing, you need to set the editablePaths flag in your surface's render options:

Vanilla JS
React
Angular
Vue
Svelte
import { newInstance } from "@jsplumbtoolkit/browser-ui"

const toolkit = newInstance()

const surface = toolkit.render(someElement, {
"editablePaths": true
});

Once you've setup path editing you'll need to invoke it at some point, for which you need to invoke the startEditingPath method on your surface. One common way to do this is by responding to a tap or click event on an edge:

Vanilla JS
React
Angular
Vue
Svelte
import { newInstance,
EVENT_CLICK,
DEFAULT } from "@jsplumbtoolkit/browser-ui"

const toolkit = newInstance()

const surface = toolkit.render(someElement, {
"view": {
"edges": {
[DEFAULT]: {
"events": {
[EVENT_CLICK]: (p) => { p.renderer.startEditingPath(p.edge) }
}
}
}
}
});

The path editor will now stay active until you subsequently call stopEditingPath(). Another common setup for this is to do so in response to a click on a surface canvas (ie. a click on whitespace):

Vanilla JS
React
Angular
Vue
Svelte
import { newInstance,
EVENT_CANVAS_CLICK,
EVENT_CLICK,
DEFAULT } from "@jsplumbtoolkit/browser-ui"

const toolkit = newInstance()

const surface = toolkit.render(someElement, {
"events": {
[EVENT_CANVAS_CLICK]: (p) => { p.renderer.stopEditingPath() }
},
"view": {
"edges": {
[DEFAULT]: {
"events": {
[EVENT_CLICK]: (p) => { p.renderer.startEditingPath(p.edge) }
}
}
}
}
});

Editor types

Each editor offers a different interface for working with path edits.

Orthogonal editors

The orthogonal editor draws a handle on each segment of an edge, which can be dragged at 90 degrees to the direction of travel of the segment, ie. for a vertical segment, you can shift it horizontally, and for a horizontal segment you can shift it vertically.

When you are shifting a segment, if you release the mouse at such a point that the segment you just dragged forms a straight line with a previous or subsequent segment, the segments are coalesced into one. If you drag some segment such that an existing segment ceases to be a straight line, the segment is split and new segment is inserted between them.

Anchor management

Static anchors

In this example we use an edge editor to edit the path of some edge whose anchors are at fixed points (in this case, AnchorLocations.Bottom and AnchorLocations.Top). We've also already called startEditingPath(..) on the surface for you:

Edge path editor
Dynamic anchors

If the edge you are editing has dynamic anchors, the edge editor will draw a placeholder at each end of the edge, which you can drag around to any supported position for the given anchor - here we use the AutoDefault dynamic anchor, which is an anchor that has one position on each of the four sides of the element on which it resides:

Edge path editor

When you start to drag an anchor placeholder, you'll see JsPlumb adds an element indicating an allowed position to which that anchor can be moved.

caution

Dragging an anchor placeholder to a different location will cause the path edits to be cleared and for the default Orthogonal path router to be used to render the path until you make another edit. We chose this approach because changing the position of the anchor can have a fundamental effect on what would be a sensible routing of the path, and JsPlumb would have to make a bunch of assumptions that may or may not be what your user wants.

You can hide the anchor placeholders via CSS - see the CSS classes section below.

Continuous anchors

If your edge is using anchor of type AnchorLocations.Continuous, when you drag an anchor placeholder JsPlumb will highlight the candidate face for the anchor relocation:

Edge path editor
caution

As with Dynamic anchors, dragging an anchor placeholder for a Continuous anchor to a different location will cause the path edits to be cleared and for the default Orthogonal path router to be used to render the path until you make another edit.

User specified anchor positions

If you have specified anchorPositions for some given vertex in your view, eg:

nodes:{
default:{
template:`<div>{{id}}</div>`,
anchorPositions:[
{ x:0, y:0.5, ox:-1, oy:0, id:"left" },
{ x:1, y:0.5, ox:1, oy:0, id:"right" },
{ x:0.5, y:0, ox:0, oy:-1, id:"top" },
{ x:0.5, y:1, ox:0, oy:1, id:"bottom" }
]
}
}

...then the path editor will find these when you call startEditingPath(...), and offer the ability to drag the end points of the edge to each of the available positions:

Edge path editor
Avoiding vertices

By default, the orthogonal connector editor will avoid getting into a situation where either end of the connector intersects the source or target vertex. This is best illustrated with a picture:

Orthogonal connector avoiding vertices - jsPlumb Toolkit, industry standard diagramming and rich visual UI Javascript library

info

This functionality is only applied to the segments at either end of a connector. If you have some connector path that intersects the source or target vertex somewhere in the middle of the path, the path will not be re-routed to avoid the vertex.

Note also that this is a different concept to the of vertex avoidance, which was introduced in version 6.90.0.

If you want to switch this behaviour off, you can do so in the connector spec:

connector:{
type:"Orthogonal",
options:{
vertexAvoidance:false
}
}

This will be the resulting behaviour:

Orthogonal connector intersecting vertices - jsPlumb Toolkit, flowcharts, chatbots, bar charts, decision trees, mindmaps, org charts and more

Your users can still route the connector around in this setup but they'll have to move a lot more segments.


Straight editors

The straight editor draws a handle at the end of each segment of an edge, which can be dragged in any direction to alter its location. In addition, each segment is assigned a "split" button, allowing the user to split the segment into two, and, when the connector has more than one segment, each segment is assigned a delete button.

Static anchors

In this example we use an edge editor to edit the path of some edge whose anchors are at fixed points (in this case, AnchorLocations.Bottom and AnchorLocations.Top). We've also already called startEditingPath(..) for you:

Edge path editor
Dynamic anchors

If the edge you are editing has dynamic anchors, the edge editor will draw a placeholder at each end of the edge, which you can drag around to any supported position for the given anchor - here we use the AutoDefault dynamic anchor, which is an anchor that has one position on each of the four sides of the element on which it resides:

Edge path editor

When you start to drag an anchor placeholder, you'll see JsPlumb adds an element indicating an allowed position to which that anchor can be moved.

Continuous anchors

If your edge is using anchor of type AnchorLocations.Continuous, when you drag an anchor placeholder JsPlumb will highlight the candidate face for the anchor relocation:

Edge path editor
User specified anchor positions

If you have specified anchorPositions for some given vertex in your view, eg:

nodes:{
default:{
template:`<div>{{id}}</div>`,
anchorPositions:[
{ x:0, y:0.5, ox:-1, oy:0, id:"left" },
{ x:1, y:0.5, ox:1, oy:0, id:"right" },
{ x:0.5, y:0, ox:0, oy:-1, id:"top" },
{ x:0.5, y:1, ox:0, oy:1, id:"bottom" }
]
}
}

...then the path editor will find these when you call startEditingPath(...), and offer the ability to drag the end points of the edge to each of the available positions:

Edge path editor
Smoothed connectors

When you have smooth:true set on your connector, the editor functions slightly differently - the drag handles now represent the location of the control points for the splines that make up the Bezier curve, and when you drag them, the control points are moved accordingly. Also when smooth is set, the editor draws a guideline for each segment.

Edge path editor

Bezier editors

The bezier editor draws two handles - one for each control point in the connector. They are placed where the control point is, and as you drag them around the control points are updated accordingly.

Static anchors

In this example we use an edge editor to edit the path of some edge whose anchors are at fixed points (in this case, AnchorLocations.Bottom and AnchorLocations.Top). We've also already called startEditingPath(..) on the surface for you:

Edge path editor

StateMachine editors

The StateMachine editor draws one handle, located at the connector's control point (the StateMachine connector is a quadratic Bézier curve, with a single control point). As you drag the handle around, the connector's control point is updated.

Edge path editor

Overlays

You can supply a set of overlays to render on an edge for the duration of the edit, for example:


surface.startEditingPath(someEdge, {
overlays:[
{
type:LabelOverlay.type,
options:{
label:"editing...",
location:0.1
}
}
]
})

With this call we get a label overlay at location 0.1:

Edge path editor

Delete button

The edge path editor offers a shortcut method to attach a delete button:

surface.startEditingPath(someEdge, {
deleteButton:true
})

This results in:

Delete button

This will delete the edge without prompting the user. If you'd like to hook into the edge deletion, you can provide an onMaybeDelete function.

surface.startEditingPath(someEdge, {
deleteButton:true,
onMaybeDelete:(edge, connection, doDelete) => {
if (confirm(`Delete edge ${edge.id}`)) {
doDelete()
}
}
})
onMaybeDelete

Clearing path edits

Edits made to a path can be cleared via the the clearPathEdits method on the Surface object.

clearPathEdits (edgeOrConnection:string|Edge|Connection<BrowserElement>):boolean


Active Mode

When you edit an edge with a path editor, the changes are persisted to the edge as its geometry. Additionally, via the concept of activeMode, the editor will listen for new edges added via the mouse, and whenever a new edge is added it is instantly marked edited and its geometry is persisted.

This functionality is switched on by default. To run edge path editing with this switched off you'll need to manually create an EdgePathEditor and specify you do not want activeMode:

Vanilla JS
React
Angular
Vue
Svelte
import { newInstance } from "@jsplumbtoolkit/browser-ui"

const toolkit = newInstance()

const surface = toolkit.render(someElement, {});
const editor = new EdgePathEditor(surface, false)

When activeMode is switched off, an edge that has not been edited does not have a geometry set, and so when you export the dataset with unedited edges, their geometry is not exported, meaning if you subsequently reload the dataset you may not see the same edge paths as when you saved. It is for this reason that we decided to switch on activeMode by default: it seems more intuitive.


CSS classes