JointJS+ TreeLayoutView

ui.TreeLayoutView

ui.TreeLayoutView is a view on a tree-like graph that implements common tree manipulation interface like detaching and attaching branches, disconnecting nodes from the tree to create floating nodes and more.

Installation

Include joint.ui.treeLayoutView.js and its dependency joint.layout.treeLayout.js to your HTML:

<script src="joint.layout.treeLayout.js"></script>
<script src="joint.ui.treeLayoutView.js"></script>

Usage

First you need to create an object of layout.TreeLayout type. ui.TreeLayoutView is dependent on this and expects this object in its model parameter:

var graphLayout = new joint.layout.TreeLayout({
    graph: graph,
    parentGap: 50,
    siblingGap: 50
});

var treeLayoutView = new joint.ui.TreeLayoutView({
    paper: paper,
    model: graphLayout
});

graphLayout.layout();
Source Code

Configuration

The following table lists options that you can pass to the ui.TreeLayoutView constructor function:

model Instance of joint.layout.TreeLayout. See layout.TreeLayout plugin for more details.
paper JointJS paper object.
useModelGeometry If set to true, the cells position and dimensions will be used as a basis for the TreeLayoutView wrapping rectangle position. By default, this is set to false which causes the TreeLayoutView wrapping rectangle position be based on the bounding box of the selected element views. Sometimes though, your shapes can have certain SVG sub elements that stick out of the view and you don't want these sub elements to affect the TreeLayoutView wrapping rectangle position. In this case, set the useModelGeometry to true.
clone(element) A function, that is applied on the element to create a clone for dragging. It defaults to return element.clone();.
canInteract(element) A predicate, that returns true if the element, which the user interacts with, can be actually dragged. It defaults to return true;.
validateConnection(element, candidateParent, treeLayoutView, details) A predicate, that returns true if the element, which the user interacts with, can be reconnected to the candidateParent. It defaults to return true;. The details object contains additional information about the candidate connection.
Property Description
level The distance of the element from the tree root.
direction The direction of the connection (between the candidateParent and element).
siblingRank The index of the element among its siblings.
siblings An array of sibling elements (children of candidateParent in a particular direction).
validatePosition(element, x, y, treeLayoutView) A predicate, that returns true if the element, which the user interacts with, can be placed (disconnected or translated) at the position x, y. It defaults to return true;.
reconnectElements(elements, parent, siblingRank, direction, treeLayoutView) A function to override the default connection behaviour (this includes connecting sources and reconnecting children).
translateElements(element, x, y, treeLayoutView) A function to override the default translating behaviour (this includes translating sources and disconnecting children).
previewAttrs An object with SVG attributes to be applied onto the preview element. The preview consists of 3 components - child, parent and link. e.g.
{
    child: { opacity: 0.5 },
    link: { opacity: 0.5 },
    parent: { rx: 20, ry: 20 }
}
paperConstructor The type of the paper. Defaults to joint.dia.Paper. This is only useful if you use a different paper type for rendering your graphics. In case you inherit from joint.dia.Paper to implement some specific rendering, you can just pass your constructor function to this parameter and use the paperOptions parameter to pass additional options to your special paper.
paperOptions Options object that will be passed to the internal paper used for rendering graphics.

API

startDragging(elementOrElements) Initiates dragging of a single or multiple elements (dia.Element or an array of dia.Element). Useful when combined with the Selection plugin to drag & drop multiple nodes at once. This is a high-level method, which will start listening to pointermove and pointerup events and executes low-level dragstart, drag and dragend methods accordingly.
cancelDrag() Stop the current drag operation.
canDrop() Has the current drag operation valid drop target? i.e. an element can be reconnected or translated.
dragstart(elements, x, y) Start a new drag operation with elements set as its source.
drag(elements, x, y) Drag the source elements and display preview of the drop location if any.
dragend(elements, x, y) End the drag operation and reconnect/translate the source elements if there was a valid drop target.
enable() Enable the view. The plugin starts listening to the paper and allows the user to reconnect the elements.
disable() Disable the view. Prevent the user from reconnecting the elements.
isDisabled() Return true if the view is disabled. Otherwise, return false. The plugin is enabled by default.

An example on how to integrate the ui.Stencil with TreeLayoutView.

stencil.on({
    'element:dragstart': (cloneView, evt) => {
        // An element that will be added to the graph
        const element = cloneView.model.clone();
        evt.data.elements = [element];
    },
    'element:drag': (cloneView, evt, cloneArea, validDropTarget) => {
        const { elements, dragStarted } = evt.data;
        const { x, y } = cloneArea.center();
        if (validDropTarget) {
            if (!dragStarted) {
                treeView.dragstart(elements, x, y);
                evt.data.dragStarted = true;
            }
            treeView.drag(elements, x, y);
            cloneView.el.style.display = 'none';
        } else {
            // Outside the valid drop target
            treeView.cancelDrag();
            evt.data.dragStarted = false;
            cloneView.el.style.display = 'block';
        }
    },
    'element:dragend': (cloneView, evt, cloneArea, validDropTarget) => {
        const { elements } = evt.data;
        const { x, y } = cloneArea.center();
        const canDrop = validDropTarget && treeView.canDrop();
        treeView.dragend(elements, x, y);
        // Show clone in case of drop animation
        cloneView.el.style.display = 'block';
        stencil.cancelDrag({ dropAnimation: !canDrop });
    }
});