Skip to main content

Selections

A selection is a collection of nodes, groups, ports and edges (zero or more of each), upon which operations can be made that affect the entire set at once.

You can work with these in one of two ways - either use the current selection associated with an instance of the Toolkit, or create an ad-hoc selection.

Current selection

Each instance of the toolkit maintains a current selection, exposing several methods for you to work with it. Changes to the current selection are propagated to all surfaces registered on some instance of the toolkit.

The principal methods for working with the current selection are:

setSelection(obj)

Set the current selection. Here, obj can take a number of forms:

  • A node, group, port or edge object
  • A list of nodes/groups/ports/edges
  • Another selection
  • A path

addToSelection(obj)

Add something to the current selection. Here, obj can take a number of forms:

  • A node, group, port or edge object
  • A list of nodes/groups/ports/edges
  • Another selection
  • A path

addPathToSelection(params)

A helper method to get a path (see here) and add it to the current selection.

removeFromSelection(obj)

Remove something from the current selection. Valid values for obj are the same as for the addToSelection and setSelection methods.

getSelection()

Get the current selection. This returns a Selection, which is a selector-like object that offers a number of methods for performing operations on the selection as a whole.

  • append append a new item to the current selection
  • clear clear the current selection (same as calling toolkit.clearSelection()
  • each Iterate the selection. The required callback signature is function(index, object).
  • eachEdge Iterate through only the edges in the selection.
  • eachNode Iterate through only the nodes/ports in the selection.
  • remove Remove the given item from the current selection.

clearSelection()

Clears the current selection. This method is analogous to calling getSelection().clear().

--

Selecting Descendants

If you are working with hierarchical data, you can use the Toolkit to get a list of descendants of some vertex (and, optionally, the edges to and from each vertex):

const descendants = toolkit.selectDescendants(someNode)

The return value is a Selection, with all of the methods discussed above available. By default this selection does not include the focus node or any edges, but the method signature is as follows:

Home > @jsplumbtoolkit/core > JsPlumbToolkit > selectDescendants

JsPlumbToolkit.selectDescendants() method

Selects all descendants of some Node or Group, and, optionally, the Node/Group itself.

Signature:

selectDescendants(obj: string | Node | Group, includeFocus?: boolean, includeEdges?: boolean): Selection<Edge | Node | Group>;

Parameters

ParameterTypeDescription
objstring | Node | GroupNode/Group, or ID of Node/Group, to select
includeFocusbooleanWhether or not to include the focus node/group in the returned dataset. Defaults to false.
includeEdgesbooleanWhether or not to include edges in the returned dataset. Defaults to false.

Returns:

Selection<Edge | Node | Group>

So this call would return all of a vertex's descendants plus the vertex itself:

var descendants = toolkit.selectDescendants(someNode, true);

And this would get the descendants, the node itself, and any edges connecting the nodes in the set:

var descendants = toolkit.selectDescendants(someNode, true, true);

AdHoc selection

In addition to the current selection, you can also select a set of vertices and/or edges on an adhoc basis:

  • select(obj)
  • deselect(obj)

Here, obj can be some node/group/port/edge, or the ID of some node, group or port, or an array of a combination of these.


Filtering objects

A more powerful method to use to get a set of objects is filter, which, as the name suggests, can filter the contents of some Toolkit instance according to a few criteria. There are two ways to call this method.

Filtering with a function

You can pass a Function as argument to the filter method, which is expected to return true to indicate that a given object should be included:

import { Node } from "@jsplumbtoolkit/core"

let selection = toolkit.filter((obj) => {
return (obj.objectType === Node.objectType)
})

Note here that this function is given every object managed by the Toolkit instance - meaning all groups, nodes and edges. So you can use objectType to test if the object is a node or an edge. In this simple example we have simply returned all the nodes in the Toolkit instance.

Another example of using a function:

import { Node } from "@jsplumbtoolkit/core"

let selection = toolkit.filter((obj) => {
return obj.objType === Node.objectType && obj.data.maxValue < 150
});

Here we return only nodes whose maxValue is less than 150.

Filtering with a match object

Alternatively, you can pass a match object in to the filter method:

let selection = toolkit.filter({
maxValue:150
});

Here we've told the Toolkit we are interested only in vertices whose maxValue is exactly 150. Note that with a match object only exact matches are supported: we cannot recreate the previous example in which vertices whose maxValue was less than 150 are returned.

You can match an arbitrary number of values:

let selection = toolkit.filter({
maxValue:150,
lorem:"ipsum"
});

Here we get vertices with a maxValue of 150 and a lorem of "ipsum".

Partial matches with a match object

You can instruct the Toolkit that an object that matches at least one entry in the match object should be included in the output (by default, every value must match):

let selection = toolkit.filter({
maxValue:150,
lorem:"ipsum"
}, true)

...by passing in true as the second argument to the filter function. So in this example we now get vertices that have a maxValue of 150 and/or a lorem of "ipsum".


Selecting objects with the mouse

The Surface operates in one of two modes:

  • pan

The default mode, in which the mouse is used to pan the UI and support click events etc.

  • select

In this mode, the mouse is used to select objects in the UI using click and drag ("lasso" selection). Holding down the Shift key while selecting causes new objects to be added to the current selection. Otherwise, each new click and drag operation causes the current selection to be replaced.

note

To use the lasso selection you have to import the @jsplumbtoolkit/browser-ui-plugin-lasso and configure the lasso plugin on your surface. See the plugin documentation for more details.

Lasso selection works in the same way as AutoCAD: selecting from left to right will add nodes that intersect, in any amount, with the current selected area. Selecting from right to left will add only nodes that are completely enclosed by the current selected area.

Select mode

By default, the lasso draws an element on screen that indicates the selected area:

Lasso default mode

You can also run the lasso in 'inverted' mode:

Lasso inverted mode

To do this, you must set a flag on the lasso plugin's options:


import { LassoPlugin } from "@jsplumbtoolkit/browser-ui-plugin-lasso"

toolkitInstance.render(someElement, {
..
plugins:[
{
type:LassoPlugin.type,
options:{
invert:true
}
}
]
...
});

Filtering lasso selections

You can provide a list of classes that indicate elements upon which a mousedown should not launch the lasso:


import { LassoPlugin } from "@jsplumbtoolkit/browser-ui-plugin-lasso"

toolkitInstance.render({
...
plugins:[
{
type:LassoPlugin.type,
options:{
filter: ".controls, .controls *, .miniview, .miniview *",
}
}
]
...
});

This example is from the Hierarchical layout demo that ships with the Toolkit.

Lasso CSS

In 'normal' mode, the element drawn on screen is given a class of jtk-lasso. In 'inverted' mode, the elements drawn on screen (there are 4 - top, bottom, left and right) are given a class of jtk-lasso-mask.


Removing everything in a selection

This is a fairly common use case when working with a selection:

let selection = toolkit.selectDescendants(someNode)
toolkit.remove(selection)

Here we used the selectDescendants method, but we could have used any method that returns a selection or path - select, selectDescendants, filter or getPath.


Appending selections

You can append selections to each other:

let selection1 = toolkitInstance.select(["1", "2", "3"]);

// we have a selection containing nodes 1, 2 and 3

let selection2 = toolkitInstance.getPath({source:"1", target:"17"});

// we have a selection containing the path from node 1 to node 17

selection1.append(selection2);

This is perhaps a spurious example. But you get the idea.


Limiting selection size

You can limit the number of group, nodes and/or edges in a selection or Toolkit instance's currentSelection. This can be useful in a few ways: maybe your app wants to enforce that only one node is selected at any point in time, for instance. Or maybe you want to maintain a selection queue of fixed size for some purpose.

Limiting the Toolkit's Current selection

You can provide constructor parameters to control this behaviour:


import { Selection } from "@jsplumbtoolkit/core"
import { newInstance } from "@jsplumbtoolkit/browser-ui-vanilla"

const tk = newInstance({
maxSelectedNodes:1,
maxSelectedGroups:1,
maxSelectedEdges:1,
selectionCapacityPolicy:Selection.DISCARD_NEW
});

Here we have specified that at most 1 node, 1 group and 1 edge may be selected, and that when the user tries to add a new node or edge to the current selection, it should be discarded. The other option - the default option - for selectionCapacityPolicy is Selection.DISCARD_EXISTING, which takes the 0th element from the underlying list.

You can also control these values with setter methods:

tk.setMaxSelectedNodes(4)
tk.setMaxSelectedGroups(3)
tk.setMaxSelectedEdges(3)
tk.setSelectionCapacityPolicy(Selection.DISCARD_EXISTING)

Limiting an AdHoc selection

To set limits and control the capacity policy of an ad-hoc selection, these methods are available:

var sel = tk.select() // create an empty selection
sel.setMaxNodes(4)
sel.setMaxEdges(3)
sel.setCapacityPolicy(Selection.DISCARD_EXISTING);

Hiding/Showing selections

Once you have a selection, you can instruct a surface to hide/show the entire selection at once:

var sel = tk.select(["node1", "node2"]);
surface.setVisible(sel, false);

Here we assume the existence of a Toolkit called tk and a Surface called surface.