Hierarchical Layout
The Hierarchical layout positions vertices in a hierarchy, oriented either vertically or horizontally. The classic use cases for this layout are such things as a family tree or an org chart.
As of version 6.1.0 this layout is deprecated. The Hierarchy
layout now offers all of the functionality this layout offers and more. In 7.x versions of the Toolkit this layout will no longer be available.
Note This layout does not, by default, refresh when edges are added/removed, for performance reasons (as it has to visit the entire dataset). You can set refreshLayoutOnEdgeConnect
on a render
call to get the layout to refresh when edges are added/removed:
var surface = toolkit.render(someElement, {
layout:{
type:"Hierarchical",
options:{
}
},
refreshLayoutOnEdgeConnect:true
});
Parameters
Home > @jsplumbtoolkit/browser-ui > HierarchicalLayoutParameters
HierarchicalLayoutParameters interface
Warning: This API is now obsolete.
From 6.1.0 use the
Hierarchy
layout instead
Parameters for the Hierarchical Layout.
Signature:
export interface HierarchicalLayoutParameters extends AbstractHierarchicalLayoutParameters<Vertex>
Extends: AbstractHierarchicalLayoutParameters<Vertex>
Properties
Property | Modifiers | Type | Description |
---|---|---|---|
align? | HierarchicalLayoutAlignment | (Optional) Optional, defaults to "center". Instructs the layout how to place child nodes with respect to their parent nodes. By default, a group of child nodes is centered on its parent. The layout also supports "start" and "end" for this value, which work in much the same way as "flex-start" and "flex-end" do in CSS: for a hierarchical layout with the root at the top of the tree and the child nodes underneath, a value of "start" for align would cause the first child of the root to be placed immediately under the root, with its first child immediately underneath, etc. The remainder of the content would fan out to the right. This option also works in conjunction with invert and orientation:"vertical" | |
invert? | boolean | (Optional) Optional, defaults to false. If true, the layout will be inverted, ie. the root node will be at the bottom for horizontal layouts, and to the right for vertical layouts | |
orientation? | HierarchicalLayoutOrientation | (Optional) Optional, defaults to "vertical". Valid values are "vertical" and "horizontal". | |
spacing? | HierarchicalLayoutSpacing | (Optional) Optional, defaults to "auto". Valid values are: "auto" (Spacing.auto ) Spaces each node and its parent according to the size of the biggest node in the given node's level. "compress" (Spacing.compress ) Uses a regular spacing between each node and its parent |
Home > @jsplumbtoolkit/browser-ui > AbstractHierarchicalLayoutParameters
AbstractHierarchicalLayoutParameters interface
Signature:
export interface AbstractHierarchicalLayoutParameters<T extends HasId> extends AbsoluteBackedLayoutParameters
Extends: AbsoluteBackedLayoutParameters
Properties
Property | Modifiers | Type | Description |
---|---|---|---|
getChildVertices? | HierarchicalLayoutChildVerticesFunction<T> | (Optional) Optional function used to determine the edges to traverse to find children from some node | |
getRootNode? | (toolkit: JsPlumbToolkit) => Array<Vertex> | (Optional) Optional. A function that is given the Toolkit instance as argument and is expected to return either a single node/group, or an array of nodes/groups, to use as the root(s) for the layout | |
ignoreLoops? | boolean | (Optional) Defaults to true. If a loop is found during the layout it is usually ignored, unless this is set to true. | |
ignorePorts? | boolean | (Optional) Defaults to false, meaning that ports are taken into account when figuring the list of edges from some vertex. If you set this to true , ports will be ignored and the layout will only consider edges connected directly to each vertex. | |
multipleRoots? | boolean | (Optional) Optional, defaults to true. If false, multiple roots are not supported, and assuming you have not overridden getRootNode, the layout uses the first node found in the dataset (otherwise it still uses the result of your getRootNode function) | |
rootNode? | Array<Vertex> | (Optional) Optional. Defines the node/group to use as the root of the tree. This may be provided either as a node/group id or as a node/group object. If this parameter is not specified and multipleRoots is not false then the layout uses the result(s) of the getRootNode function; otherwise it uses the first node/group found in the dataset. |
Home > @jsplumbtoolkit/browser-ui > AbsoluteBackedLayoutParameters
AbsoluteBackedLayoutParameters interface
Parameters for a layout that extends AbsoluteBackedLayout
Signature:
export interface AbsoluteBackedLayoutParameters extends LayoutParameters
Extends: LayoutParameters
Properties
Property | Modifiers | Type | Description |
---|---|---|---|
absoluteBacked? | boolean | (Optional) Defaults to false. If true, then the layout will use any position values found in the data for a given vertex. |
Home > @jsplumbtoolkit/browser-ui > LayoutParameters
LayoutParameters interface
Base interface for layout parameters. All layout parameter interfaces extend this.
Signature:
export interface LayoutParameters extends Record<string, any>
Extends: Record<string, any>
Properties
Property | Modifiers | Type | Description |
---|---|---|---|
height? | number | (Optional) Optional fixed height for the layout. | |
locationFunction? | LocationFunction | (Optional) Optional function that, given some vertex, can provide the x/y location of the vertex on the canvas | |
padding? | PointXY | (Optional) Optional padding to put around the elements. | |
width? | number | (Optional) Optional fixed width for the layout. |
The layout at the top of this page shows the horizontal
. Here we show the same dataset in the vertical
orientation:
Hierarchical layout with align:start
Hierarchical layout with align:end
Determining children of a vertex
The getChildEdges
function, which is an optional parameter on the Hierarchical layout, forms the core of how the Hierarchical layout traverses the dataset. It is defined as:
getChildEdges = function(vertex:Vertex, toolkit:JsPlumbToolkit):Array<Edge>;
Its purpose is to return a list of Edge objects for the given node/group, where the edges define the connections from this node/group to what should be considered its children. The default implementation of this is:
function(vertex:Vertex, toolkit:JsPlumbToolkit) {
return toolkit.getAllEdgesFor(vertex, (e:Edge) => {
const target = isPort(e.target) ? e.target.getParent() : e.target
return ( e.source === vertex || (this._ignorePorts !== true && isPort(e.source) && e.source.getParent() === vertex) ) &&
this.adapter.filter(target)
})
}
Which basically says, get all the edges for which this node/group (or port, if connecting via ports is enabled) is the source.
Custom implementations of this function can, for example, test the type
of edges, to exclude certain types from determining the structure of the hierarchy:
function(vertex:Vertex, toolkit:JsPlumbToolkit) {
return toolkit.getAllEdgesFor(vertex, function(e) {
return e.data.type !== "FLOATING" && e.source === vertex || (this._ignorePorts !== true && isPort(e.source) && e.source.getParent() === vertex)
});
}
Here we test each edge to see if it is of type FLOATING
, and if so, we do not return it. The result would be that the hierarchical layout would be determined by the other edges; any edges of this type would still be drawn, of course. They would simply be painted to/from wherever in the hierarchy the two end nodes/groups were located.
Determining the root node(s)
In the Hierarchical layout there are always one or more "root" vertices, which are vertices that are to be placed at the root of the hierarchy. The Hierarchical layout uses the optional getRootNode
function to determine the root node/group (s), the default implementation of which is as follows:
function(toolkit:JsPlumbToolkit) {
if (params.options.multipleRoots !== false) {
return toolkit.filter((o:any) => {
if (isNodeVertex(o)) {
const targetEdges = o.getTargetEdges()
// a node/group can be root if it has no target edges, or if it has only loopback edges, and it is not excluded by the filter.
return (targetEdges.length === 0 || _allTargetEdgesLoopback(targetEdges, o)) && this.adapter.filter(o)
} else {
return false
}
}).getAll()
}
else {
return this._vertices.length > 0 ? [ this._vertices[0] ]: null
}
}
When multipleRoots
is enabled (which it is by default) then this function searches for all nodes/groups that are not targets of any edges. When multipleRoots
is set to false
, the function returns the first node in the dataset. You should keep this default behaviour in mind when using this layout - be sure that the first node in your dataset is your root (or provide your own getRootNode
function).
Padding between elements
You can control the amount of whitespace between elements via the padding
parameter. In the demonstration below we use a value of
150 pixels for both axes:
layout:{
type:"Hierarchical",
options:{
padding:{
x:150, y:150
}
}
}
Compare the above with the default value of 60 pixels:
Note that the node elements are not smaller in the first of these two previous examples - the surface has been told to automatically adjust its zoom level to fit all the content in the viewport.
Examples
Simple Example
Here we tell the Surface what the ID of the node to use as the root is, and we specify some padding and a horizontal
orientation.
toolkit.render(someElement, {
layout:{
type:"Hierarchical",
options:{
rootNode:"rootNodeId",
padding:[ 50, 50 ],
orientation:"horizontal"
}
}
});
Edge Filter example
Taken from the discussion above: only edges that are not of type FLOATING
will determine the structure of the hierarchy.
toolkit.render(someElement, {
layout:{
type:"Hierarchical",
options:{
getChildEdges:(v:Vertex, toolkit:JsPlumbToolkit) => {
return toolkit.getAllEdgesFor(vertex, (e:Edge) => {
return e.data.type !== "FLOATING" && e.source === nodeOrGroup || (params.ignorePorts !== true && isPort(e.source) && e.source.getParent() === vertex)
})
}
}
}
})
Root Nodes example
Return all Node vertices whose type is ROOT
to use as the roots of the hierarchy.
toolkit.render(someElement, {
layout:{
type:"Hierarchical",
options:{
getRootNodes:(toolkit:JsPlumbToolkit) => {
return toolkit.filter((o:Base) => {
return (isNode(o) && o.type === "ROOT")
}).getAll()
}
}
}
})