🎉 JointJS has new documentation! ðŸ¥³

Joint API

This is the API reference to the open source JointJS core library. If you're looking for the Rappid diagramming toolkit documentation, you can find that here.

JointJS library exports three global variables: joint, V and g.

The joint namespace contains all the objects that you will use to build your diagrams. Additionally, joint.version property tells you which version of JointJS you're using.

The V global is lightweight SVG library that we call Vectorizer. This tiny library makes manipulation with SVG documents much easier. JointJS uses this library internally. Normally, you don't have to get in touch with this library at all but for advanced uses, it can be handy.

The g global is another lighweight library used internally by JointJS that provides many useful geometry operations. Again, you might not get in touch with this library but when you do have the need to perform geometric operations in your applications, you'll certainly find it helpful.

anchors

An anchor of a link is a point in the reference element that this link wants to reach as its endpoint. (In reality, the reference element is probably in the way - then, it is the job of the connection point function to determine the actual location of the route endpoint with the obstructing reference element taken into account.) Anchors are set via an anchor property provided within link end definitions (i.e. the objects provided to link.source() and link.target() functions). (If the reference object is a Link, JointJS looks at linkAnchor property instead.)

There are many built-in anchor functions in JointJS:

Example:

link.source(model, {
    anchor: {
        name: 'midSide',
        args: {
            rotate: true,
            padding: 20
        }
    }
});

The default anchor function is 'center'; this can be changed with the defaultAnchor paper option. Example:

paper.options.defaultAnchor = {
    name: 'midSide',
    args: {
        rotate: true,
        padding: 20
    }
};

JointJS also contains mechanisms to define one's own custom anchor functions.

anchors.bottom

The 'bottom' anchor function places the anchor of the link in the middle of the bottom side of the view bbox. It accepts three arguments, which can be passed within the anchor.args property:

rotate boolean Should the anchor bbox rotate with the end view? Default is false, meaning that the unrotated bbox is used.
dx number Offset the anchor by dx. Default is 0.
string Percentage strings (e.g. '40%') are also accepted.
dy number Offset the anchor by dy. Default is 0.
string Percentage strings (e.g. '40%') are also accepted.

Example:

link.source(model, {
    anchor: {
        name: 'bottom',
        args: {
            rotate: true,
            dx: 10,
            dy: '40%'
        }
    }
});

anchors.bottomLeft

The 'bottomLeft' anchor function places the anchor of the link at the bottom-left corner of the view bbox. It accepts three arguments, which can be passed within the anchor.args property:

rotate boolean Should the anchor bbox rotate with the end view? Default is false, meaning that the unrotated bbox is used.
dx number Offset the anchor by dx. Default is 0.
string Percentage strings (e.g. '40%') are also accepted.
dy number Offset the anchor by dy. Default is 0.
string Percentage strings (e.g. '40%') are also accepted.

Example:

link.source(model, {
    anchor: {
        name: 'bottomLeft',
        args: {
            rotate: true,
            dx: 10,
            dy: '40%'
        }
    }
});

anchors.bottomRight

The 'bottomRight' anchor function places the anchor of the link at the bottom-left corner of the view bbox. It accepts three arguments, which can be passed within the anchor.args property:

rotate boolean Should the anchor bbox rotate with the end view? Default is false, meaning that the unrotated bbox is used.
dx number Offset the anchor by dx. Default is 0.
string Percentage strings (e.g. '40%') are also accepted.
dy number Offset the anchor by dy. Default is 0.
string Percentage strings (e.g. '40%') are also accepted.

Example:

link.source(model, {
    anchor: {
        name: 'bottomRight',
        args: {
            rotate: true,
            dx: 10,
            dy: '40%'
        }
    }
});

anchors.center

The 'center' anchor function is the default anchor function. It places the anchor of the link at center of the view bbox. It accepts three arguments, which can be passed within the anchor.args property:

rotate boolean Should the anchor bbox rotate with the end view? Default is false, meaning that the unrotated bbox is used.
dx number Offset the anchor by dx. Default is 0.
string Percentage strings (e.g. '40%') are also accepted.
dy number Offset the anchor by dy. Default is 0.
string Percentage strings (e.g. '40%') are also accepted.

Example:

link.source(model, {
    anchor: {
        name: 'center',
        args: {
            rotate: true,
            dx: 10,
            dy: '40%'
        }
    }
});

anchors.custom

New anchor functions can be defined in the joint.anchors namespace (e.g. joint.anchors.myAnchor) or passed directly as a function to the anchor property of link source/target (or to the defaultAnchor option of a paper).

In either case, the anchor function must return the anchor as a Point. The function is expected to have the form function(endView, endMagnet, anchorReference, args):

endView dia.ElementView The ElementView to which we are connecting. The Element model can be accessed as endView.model; this may be useful for writing conditional logic based on element attributes.
endMagnet SVGElement The SVGElement in our page that contains the magnet (element/subelement/port) to which we are connecting.
anchorReference g.Point A reference to another component of the link path that may be necessary to find this anchor point. If we are calling this method for a source anchor, it is the first vertex, or if there are no vertices the target anchor. If we are calling this method for a target anchor, it is the last vertex, or if there are no vertices the source anchor...
SVGElement ...if the anchor in question does not exist (yet), it is that link end's magnet. (The built-in methods usually use this element's center point as reference.)
args object An object with additional optional arguments passed to the anchor method by the user when it was called (the args property).

anchors.left

The 'left' anchor function places the anchor of the link in the middle of the left side of the view bbox. It accepts three arguments, which can be passed within the anchor.args property:

rotate boolean Should the anchor bbox rotate with the end view? Default is false, meaning that the unrotated bbox is used.
dx number Offset the anchor by dx. Default is 0.
string Percentage strings (e.g. '40%') are also accepted.
dy number Offset the anchor by dy. Default is 0.
string Percentage strings (e.g. '40%') are also accepted.

Example:

link.source(model, {
    anchor: {
        name: 'left',
        args: {
            rotate: true,
            dx: 10,
            dy: '40%'
        }
    }
});

anchors.midSide

The 'midSide' anchor function places the anchor of the link in the middle of the side of view bbox closest to the other endpoint. It accepts two arguments, which can be passed within the anchor.args property:

rotate boolean Should the anchor bbox rotate with the end view? Default is false, meaning that the unrotated bbox is used.
padding number Offset the anchor by padding away from view bbox. Default is 0.

Example:

link.source(model, {
    anchor: {
        name: 'midSide',
        args: {
            rotate: true,
            padding: 20
        }
    }
});

anchors.modelCenter

The 'modelCenter' anchor function places the anchor of the link at center of the model bbox.

Example:

link.source(model, {
    anchor: {
        name: 'modelCenter'
    }
});

anchors.perpendicular

The 'perpendicular' anchor function tries to place the anchor of the link inside the view bbox so that the link is made orthogonal. The anchor is placed along two line segments inside the view bbox (between the centers of the top and bottom side and between the centers of the left and right sides). If it is not possible to place the anchor so that the link would be orthogonal, the anchor is placed at the center of the view bbox instead. The function accepts one argument, which can be passed within the anchor.args property:

padding number Limit the area inside the view bbox available for placing the anchor by padding. Default is 0.

Example:

link.source(model, {
    anchor: {
        name: 'perpendicular',
        args: {
            padding: 10
        }
    }
});

When the link has no vertices, the other end cell's center is used as a reference point. By default, this means that a link using the 'perpendicular' anchor slides alongside the source element's edge while pointing to target element's center. To invert this behavior, and have the anchor slide alongside the target element's edge while pointing to source element's center, pass a priority option to the target function:

link.target(model, {
    priority: true,
    anchor: {
        name: 'perpendicular',
        args: {
            padding: 10
        }
    }
});

anchors.right

The 'right' anchor function places the anchor of the link in the middle of the right side of the view bbox. It accepts three arguments, which can be passed within the anchor.args property:

rotate boolean Should the anchor bbox rotate with the end view? Default is false, meaning that the unrotated bbox is used.
dx number Offset the anchor by dx. Default is 0.
string Percentage strings (e.g. '40%') are also accepted.
dy number Offset the anchor by dy. Default is 0.
string Percentage strings (e.g. '40%') are also accepted.

Example:

link.source(model, {
    anchor: {
        name: 'right',
        args: {
            rotate: true,
            dx: 10,
            dy: '40%'
        }
    }
});

anchors.top

The 'top' anchor function places the anchor of the link in the middle of the top side of the view bbox. It accepts three arguments, which can be passed within the anchor.args property:

rotate boolean Should the anchor bbox rotate with the end view? Default is false, meaning that the unrotated bbox is used.
dx number Offset the anchor by dx. Default is 0.
string Percentage strings (e.g. '40%') are also accepted.
dy number Offset the anchor by dy. Default is 0.
string Percentage strings (e.g. '40%') are also accepted.

Example:

link.source(model, {
    anchor: {
        name: 'top',
        args: {
            rotate: true,
            dx: 10,
            dy: '40%'
        }
    }
});

anchors.topLeft

The 'topLeft' anchor function places the anchor of the link at the top-left corner of the view bbox. It accepts three arguments, which can be passed within the anchor.args property:

rotate boolean Should the anchor bbox rotate with the end view? Default is false, meaning that the unrotated bbox is used.
dx number Offset the anchor by dx. Default is 0.
string Percentage strings (e.g. '40%') are also accepted.
dy number Offset the anchor by dy. Default is 0.
string Percentage strings (e.g. '40%') are also accepted.

Example:

link.source(model, {
    anchor: {
        name: 'topLeft',
        args: {
            rotate: true,
            dx: 10,
            dy: '40%'
        }
    }
});

anchors.topRight

The 'topRight' anchor function places the anchor of the link at the top-right corner of the view bbox. It accepts three arguments, which can be passed within the anchor.args property:

rotate boolean Should the anchor bbox rotate with the end view? Default is false, meaning that the unrotated bbox is used.
dx number Offset the anchor by dx. Default is 0.
string Percentage strings (e.g. '40%') are also accepted.
dy number Offset the anchor by dy. Default is 0.
string Percentage strings (e.g. '40%') are also accepted.

Example:

link.source(model, {
    anchor: {
        name: 'topRight',
        args: {
            rotate: true,
            dx: 10,
            dy: '40%'
        }
    }
});

connectionPoints

A link connection point is an endpoint of the link route. This point is (usually) different from the link anchor point, as it takes into account the presence of the end element. Connection points are set via an connectionPoint property provided within link end definitions (i.e. the objects provided to link.source() and link.target() functions).

The built-in functions work by finding an intersection between the link path (the path from the link's source anchor, through its vertices, to its target anchor). However, the functions always only have access to a single path segment; the source connectionPoint is found by investigating the first segment (i.e. source anchor - first vertex, or source anchor - target anchor if there are no vertices), while the target connectionPoint is found by investigating the last segment (i.e. last vertex - target anchor, or source anchor - target anchor). This has consequences if the investigated path segment is entirely contained within the end element.

There are four built-in connection point functions in JointJS:

Example:

link.source(model, {
    connectionPoint: {
        name: 'boundary',
        args: {
            sticky: true
        }
    }
});

The default connection point is 'bbox'; this can be changed with the defaultConnectionPoint paper option. Example:

paper.options.defaultConnectionPoint = {
    name: 'boundary',
    args: {
        sticky: true
    }
};

All four of the built-in connection point functions accept the following optional argument, in addition to their own arguments:

offset number Offset the connection point from the anchor by the specified distance along the end link path segment. Default is 0.

Example:

link.source(model, {
    connectionPoint: {
        name: 'bbox',
        args: {
            offset: 10
        }
    }
});

JointJS also contains mechanisms to define one's own custom connection point functions.

connectionPoints.anchor

The 'anchor' places the connection point so that it coincides with the link end's anchor point (determined either by the anchor function or by the defaultAnchor paper option). The position of the connection point may be modified by several additional arguments, which may be passed within the connectionPoint.args property:

offset number | object An object with x and y properties. The connection point will be moved:
  • from the anchor point by x pixels in the direction of the corresponding link end's path segment.
  • by y pixels in the direction of the corresponding link end's path segment, rotated by 90 degrees anti-clockwise around the anchor point.
If a number is provided, it will be used as the x offset.
align 'top' | 'left' | 'bottom' | 'right' Offset the connection point to the point given by projecting the first vertex onto the vector which points from the anchor point in the direction specified. (If there are no vertices, use the projection of the other anchor point instead.) Notably, if the reference point is not the direction-most point of the two, the connection point is set to be the same as the anchor point. Let us illustrate that outcome and the other possible outcome on the `'top'` direction:
  • The reference point lies below the anchor point. The anchor point is the topmost point of the two, so the connection point receives both the `x` and `y` coordinates from the anchor point. The connection point is set to be coincident with the anchor point.
  • The reference point lies above the anchor point. In this case, the reference point is the topmost point of the two, so the connection point receives the `y` coordinate from the reference point. The connection point still receives the `x` coordinate from the anchor point. This means that the connection point is offset from the anchor point in the `'top'` direction. The three points create a right-angled triangle, with the right angle at the connection point.
alignOffset number After having determined the position of the connection point according to the `align` algorithm (see above), additionally offset the connection point by the specified amount in the direction specified by `align`.

Example:

link.source(model, {
    connectionPoint: {
        name: 'anchor',
        args: {
            offset: 10
        }
    }
});

connectionPoints.bbox

The 'bbox' connection point function is the default connection point function. It places the connection point at the intersection between the link path end segment and the end element bbox. The position of the connection point may be modified by several additional arguments, which may be passed within the connectionPoint.args property:

offset number | object An object with x and y properties. The connection point will be moved:
  • from the anchor point by x pixels in the direction of the corresponding link end's path segment.
  • by y pixels in the direction of the corresponding link end's path segment, rotated by 90 degrees anti-clockwise around the anchor point.
If a number is provided, it will be used as the x offset.
stroke boolean Should the stroke width be included when calculating the connection point? Default is false.

Example:

link.source(model, {
    connectionPoint: {
        name: 'bbox',
        args: {
            offset: 10,
            stroke: true
        }
    }
});

connectionPoints.boundary

The 'boundary' connection point function places the connection point at the intersection between the link path end segment and the actual shape of the end element. (If JointJS is unable to determine the actual shape - e.g. for text - the element bbox is used instead, just as in the 'bbox' connection point function.) The position of the connection point may be modified by several additional arguments, which may be passed within the connectionPoint.args property:

offset number | object An object with x and y properties. The connection point will be moved:
  • from the anchor point by x pixels in the direction of the corresponding link end's path segment.
  • by y pixels in the direction of the corresponding link end's path segment, rotated by 90 degrees anti-clockwise around the anchor point.
If a number is provided, it will be used as the x offset.
insideout boolean What happens if the link path never leaves the interior area of the end element (e.g. because the other end anchor lies within the first end element)? Should the path line be extended until an intersection with the boundary is found? Default is true.
extrapolate boolean What happens if the link path never enters the interior area of the end element (e.g. because the anchor lies outside the end element)? Should the path line be extended to try and find the boundary? Default is false. Note that even if this option is true, an intersection is still not guaranteed. This option takes precedence over connectionPoint.args.sticky.
sticky boolean What happens if the link path never enters the interior area of the end element (e.g. because the anchor lies outside the end element)? Should the closest point on the end element boundary be used instead? Default is false. Note that setting this option to true guarantees that a connection point will be found on the shape boundary.
precision number The precision of the path intersection algorithm. Uses a logarithmic scale; increasing the number by 1 reduces the maximum observed error by a factor of ten. Default is 2, corresponding to 1% error.
selector string A selector to identify subelement/magnet of the end element at whose boundary we want the connection point to be found. Default is undefined, meaning that the first non-group descendant of the end element's node will be considered. (An example of another setting that may be useful is 'root', which forces the usage of the root group bbox instead.)
stroke boolean Should the stroke width be included when calculating the connection point? Default is false.

Example:

link.source(model, {
    connectionPoint: {
        name: 'boundary',
        args: {
            offset: 10,
            insideout: false,
            extrapolate: true,
            sticky: true,
            precision: 3,
            stroke: true
        }
    }
});

connectionPoints.custom

New connection point function can be defined in the joint.connectionPoints namespace (e.g. joint.connectionPoints.myConnectionPoint) or passed directly as a function to the connectionPoint property of link source/target (or to the defaultConnectionPoint option of a paper).

In either case, the connection point function must return the connection point as a Point. The function is expected to have the form function(endPathSegmentLine, endView, endMagnet, args):

endPathSegmentLine g.Line The link path segment at which we are finding the connection point. If we are calling this method for a source connection point, it is the first segment (source anchor - first vertex, or source anchor - target anchor). If we are calling this method for a target connection point, it is the last segment (last vertex - target anchor, or source anchor - target anchor).
endView dia.ElementView The ElementView to which we are connecting. The Element model can be accessed as endView.model; this may be useful for writing conditional logic based on element attributes.
endMagnet SVGElement The SVGElement in our page that contains the magnet (element/subelement/port) to which we are connecting.
args object An object with additional optional arguments passed to the connection point method by the user when it was called (the args property).

connectionPoints.rectangle

The 'rectangle' connection point function places the connection point at the intersection between the link path end segment and the element's unrotated bbox. The position of the connection point may be modified by several additional arguments, which may be passed within the connectionPoint.args property:

offset number | object An object with x and y properties. The connection point will be moved:
  • from the anchor point by x pixels in the direction of the corresponding link end's path segment.
  • by y pixels in the direction of the corresponding link end's path segment, rotated by 90 degrees anti-clockwise around the anchor point.
If a number is provided, it will be used as the x offset.
stroke boolean Should the stroke width be included when calculating the connection point? Default is false.

Example:

link.source(model, {
    connectionPoint: {
        name: 'rectangle',
        args: {
            offset: 10,
            stroke: true
        }
    }
});

connectionStrategies

Connection strategies come into play when the user modifies the position of link endpoints. There are two situations in which this is relevant:

  • When the user drags a link endpoint and connects it to an element or its port. The connection strategy determines the end anchor after the user is finished dragging the link endpoint. (Note that any individual anchor property that might have been assigned on the dragged link endpoint will be overridden by the connection strategy. If necessary, have a look at the custom connectionStrategy documentation for information on replicating the functionality of anchor functions.)
  • When a user creates a link, for example by clicking a port. The connection strategy determines the new link's source anchor.

Both the anchor and connectionPoint properties are rewritten in response to user interaction. None of the built-in connection strategies preserve the originally assigned anchor and connection point functions. To assign precisely what you need as the anchor and connection point functions, you may need to define your own custom connection strategy.

Connection strategies are not assigned on a link-by-link basis. They are set with the connectionStrategy option on a paper.

There are three built-in connection strategies in JointJS:

The default connection strategy is specified as null in paper settings, which is equivalent to joint.connectionStrategies.useDefaults.

Built-in connection strategies are specified by reference to their their name in the joint.connectionStrategies namespace. Example:

paper.options.connectionStrategy = joint.connectionStrategies.pinAbsolute;

connectionStrategies.custom

New connection strategies can be defined in the joint.connectionStrategies namespace (e.g. joint.connectionStrategies.myConnectionStrategy) or passed directly as a function to the connectionStrategy option of a paper.

In either case, the connection strategy function must return an end definition (i.e. an object in the format supplied to the link.source() and link.target() functions). The function is expected to have the form function(endDefinition, endView, endMagnet, coords):

endDefinition object An end definition; the output of the appropriate end function (link.source() or link.target()). An object containing at least an id of the Element to which we are connecting. This object is expected to be changed by this function and then sent as the return value.
endView dia.ElementView The ElementView to which we are connecting. The Element model can be accessed as endView.model; this may be useful for writing conditional logic based on element attributes.
endMagnet SVGElement The SVGElement in our page that contains the magnet (element/subelement/port) to which we are connecting.
coords g.Point A Point object recording the x-y coordinates of the user pointer when the connection strategy was invoked.

Custom connection strategies may be enormously useful for your users. Here we provide some examples of custom functionality.

Connecting to Ancestors

If your diagram makes heavy use of nested elements, it may be useful to always connect links to a top-level ancestor element (instead of the element on which the arrowhead was actually dropped by user interaction):

joint.connectionStrategies.topAncestor = function(end, endView) {

    var ancestors = endView.model.getAncestors();
    var numAncestors = ancestors.length;
    var end = numAncestors ? ancestors[numAncestors - 1] : end;

    return end;
}

paper.options.connectionStrategy = joint.connectionStrategies.topAncestor;

Connecting to Ports

If your diagram uses ports, you usually do not want links to be able to connect anywhere else. The solution is similar to the one above:

joint.connectionStrategies.firstPort = function(end, endView) {

    var ports = endView.model.getPorts();
    var numPorts = ports.length;
    var end = numPorts ? { id: end.id, port: ports[0].id } : end;

    return end;
}

paper.options.connectionStrategy = joint.connectionStrategies.firstPort;

Replicating Built-in Anchor Functions

Furthermore, it is very easy to replicate the built-in anchor functions for connection strategy scenarios - simply apply the anchor function to the received end parameter:

joint.connectionStrategy.midSide = function(end) {

    end.anchor = {
        name: 'midSide',
        args: {
            rotate: true
        }
    };

    return end;
}

paper.options.connectionStrategy = joint.connectionStrategy.midSide;

Replicating Built-in Connection Point Functions

What if we needed to replicate a built-in connection point function instead? We use the same idea as in the previous example:

joint.connectionStrategy.boundary = function(end) {

    end.connectionPoint = {
        name: 'boundary',
        args: {
            offset: 5
        }
    };

    return end;
}

paper.options.connectionStrategy = joint.connectionStrategy.boundary;

Of course, it is also possible to combine both of the examples and assign an anchor as well as connectionPoint to the end parameter of the modified link.

connectionStrategies.pinAbsolute

The pinAbsolute connection strategy records the coordinates of user pointer and assigns the end anchor absolutely, by reference to the top-left corner of the view bbox of the element above which the endpoint was dropped. Absolute positioning ensures that if the element is subsequently resized, the anchor stays at the same absolute distance from the edges (e.g. staying 10 pixels away from the left side and 20 pixels away from the top side).

The end connection point is assigned according to defaultConnectionPoint paper option.

Example:

paper.options.connectionStrategy = joint.connectionStrategies.pinAbsolute;

The end (source or target) that is being modified gets the 'topLeft' anchor assigned by this connection strategy:

end.anchor = {
    name: 'topLeft',
    args: {
    	rotate: true
        dx: (coords.x - bbox.x),
        dy: (coords.y - bbox.y)
    }
};

connectionStrategies.pinRelative

The pinRelative connection strategy records the coordinates of user pointer and assigns the end anchor relatively, by reference to the top-left corner of the view bbox of the element above which the endpoint was dropped. Relative positioning ensures that if the element is subsequently resized, the anchor stays at the same relative distance from the edges (e.g. staying 25% of the way from the left side and 75% of the way from the top side).

The end connection point is assigned according to defaultConnectionPoint paper option.

Example:

paper.options.connectionStrategy = joint.connectionStrategies.pinRelative;

The end (source or target) that is being modified gets the 'topLeft' anchor assigned by this connection strategy:

end.anchor = {
    name: 'topLeft',
    args: {
    	rotate: true
        dx: percentageString(coords.x - bbox.x),
        dy: percentageString(coords.y - bbox.y)
    }
};

connectionStrategies.useDefaults

The useDefaults connection strategy is the simplest connection strategy. It ignores the coordinates of user pointer and assigns the end anchor according to the defaultAnchor paper option and the end connection point according to the defaultConnectionPoint paper option.

Thus, this connection strategy is equivalent to a connection strategy of null.

Example:

paper.options.connectionStrategy = joint.connectionStrategies.useDefaults;

connectors

Connectors take an array of link route points and generate SVG path commands so that the link can be rendered. The connector property of a link can be accessed with the link.connector() function.

There are four built-in connectors in JointJS:

Example:

link.connector('rounded', {
    radius: 20
});

The default connector is 'normal'; this can be changed with the defaultConnector paper option. Example:

paper.options.defaultConnector = {
    name: 'rounded',
    args: {
        radius: 20
    }
}

All four of the built-in connectors accept the following optional argument, in addition to their own arguments:

raw boolean Should the router return the connection path as a g.Path rather than as a string? Default is false.

Example:

link.connector('normal', {
    raw: true
});

JointJS also contains mechanisms to define one's own custom connectors.

Note that the modular architecture of JointJS allows mixing-and-matching connectors with routers as desired; for example, a link may be specified to use the 'jumpover' connector on top of the 'manhattan' router:

var link = new joint.shapes.standard.Link();
link.source(rect);
link.target(rect2);
link.router('manhattan');
link.connector('jumpover');

connectors.custom

New connectors can be defined in the joint.connectors namespace (e.g. joint.connectors.myConnector) or passed directly as a function to the connector property of a link (or to the defaultConnector paper option).

In either case, the connector function must return a g.Path representing the SVG path data that will be used to render the link. The function is expected to have the form function(sourcePoint, targetPoint, routePoints, args):

sourcePoint g.Point The source connection point.
targetPoint g.Point The target connection point.
routePoints Array<g.Point> The points of the route, as returned by the router in use.
args object An object with additional optional arguments passed to the connector method by the user when it was called (the args property).

Example of a connector defined in the joint.connectors namespace:

joint.connectors.wobble = function(sourcePoint, targetPoint, vertices, args) {

    var SPREAD = args.spread || 20;

    var points = vertices.concat(targetPoint)
    var prev = sourcePoint;
    var path = new g.Path(g.Path.createSegment('M', prev));

    var n = points.length;
    for (var i = 0; i < n; i++) {

        var next = points[i];
        var distance = prev.distance(next);

        var d = SPREAD;
        while (d < distance) {
            var current = prev.clone().move(next, -d);
            current.offset(
                Math.floor(7 * Math.random()) - 3,
                Math.floor(7 * Math.random()) - 3
            );
            path.appendSegment(g.Path.createSegment('L', current));
            d += SPREAD;
        }

        path.appendSegment(g.Path.createSegment('L', next));
        prev = next;
    }

    return path;
}

var link = new joint.shapes.standard.Link();
link.source(source);
link.target(target);

link.connector('wobble', {
    spread: 10
});

An example of a connector passed as a function is provided below. Notice that this approach does not enable passing custom args nor can it be serialized with the graph.toJSON() function.

var link = new joint.shapes.standard.Link();
link.source(source);
link.target(target);

link.connector(function(sourcePoint, targetPoint, vertices, args) {

    var SPREAD = 20;

    var points = vertices.concat(targetPoint)
    var prev = sourcePoint;
    var path = new g.Path(g.Path.createSegment('M', prev));

    var n = points.length;
    for (var i = 0; i < n; i++) {

        var next = points[i];
        var distance = prev.distance(next);

        var d = SPREAD;
        while (d < distance) {
            var current = prev.clone().move(next, -d);
            current.offset(
                Math.floor(7 * Math.random()) - 3,
                Math.floor(7 * Math.random()) - 3
            );
            path.appendSegment(g.Path.createSegment('L', current));
            d += SPREAD;
        }

        path.appendSegment(g.Path.createSegment('L', next));
        prev = next;
    }

    return path;
});

connectors.jumpover

The 'jumpover' connector draws straight lines with small arcs in place of link-link intersections. (For the time being, it cannot detect intersections with 'smooth' router links). It accepts the following additional arguments, which can be passed as the connector.args property:

size number The size of the jump (the diameter of the arc, or the length of the empty spot on the line). Defaults to 5.
jump string The style of the jump. Either 'arc' (using an Arcto SVG path command), 'cubic' (using a Curveto path command as a normalized approximation to Arcto), or 'gap' (leaving a blank space). Defaults to 'arc'.
radius number The curve radius of the rounded corners. Default is 0.

Example:

link.connector('jumpover', {
    type: 'gap'
});

connectors.normal

The 'normal' connector is the default connector for links and it is the simplest connector. It simply connects provided route points with straight-line segments.

Example:

link.connector('normal');

connectors.rounded

The 'rounded' connector connects provided route points with straight lines while smoothing all corners on the route. It accepts one additional argument, which can be passed within the connector.args property:

radius number The curve radius of the rounded corners. Default is 10.

Example:

link.connector('rounded', {
    radius: 20
});

connectors.smooth

The 'smooth' connector interpolates route points using a cubic bezier curve.

Example:

link.connector('smooth');

(Deprecated) For the purposes of backwards compatibility, the 'smooth' connector may also be enabled by setting the link.smooth property to true.

// deprecated
link.set('smooth', true)

connectors.curve

The 'curve' connector interpolates route points using a catmull-rom curve converted into cubic bezier curve. Tangents at endings of a curve can be defined using several options.

Available options:

direction curve.Directions The overall direction of the curve. The default is curve.Directions.AUTO.
sourceDirection curve.TangentDirections|object|number The unit vector direction of the tangent at the source point. If the option is an object it must have x and y properties. If the option is a number, it represents an angle relative to the x-axis in the positive direction (counterclockwise).
targetDirection curve.TangentDirections|object|number The unit vector direction of the tangent at the target point. If the option is an object it must have x and y properties. If the option is a number, it represents an angle relative to the x-axis in the positive direction (counterclockwise).
sourceTangent object Vector of the tangent to the curve at the source point. Has priority over the sourceDirection and direction. Object must have x and y properties.
targetTangent object Vector of the tangent to the curve at the target point. Has priority over the targetDirection and direction. Object must have x and y properties.
distanceCoefficient number Coefficient of the tangent vector length relative to the distance between points. The default is 0.6.

The example of how to make the source point tangent always horizontal and target point tangent always go upwards:

link.connector('curve', {
    direction: curve.Directions.HORIZONTAL,
    targetDirection: curve.TangentDirections.UP
});

connectors.curve.Directions

Available values for the direction option.

curve.Directions.AUTO Determines the tangent direction depending on the side of the element where the end point is located.
curve.Directions.HORIZONTAL Limits tangents to horizontal directions (left and right) only.
curve.Directions.VERTICAL Limits tangents to vertical directions (up and down) only.
curve.Directions.CLOSEST_POINT Defines the direction tangent as a vector in the direction of the closest point.
curve.Directions.OUTWARDS Defines the direction tangent as a vector in from the center of the element to the end point.

connectors.curve.TangentDirections

Available values for sourceDirection and targetDirection options.

curve.TangentDirections.AUTO Determines the tangent direction depending on the side of the element where the end point is located.
curve.TangentDirections.UP Sets the direction of the tangent upwards.
curve.TangentDirections.DOWN Sets the direction of the tangent downwards.
curve.TangentDirections.LEFT Sets the direction of the tangent to the left.
curve.TangentDirections.RIGHT Sets the direction of the tangent to the right.
curve.TangentDirections.CLOSEST_POINT Defines the direction tangent as a vector in the direction of the closest point.
curve.TangentDirections.OUTWARDS Defines the direction tangent as a vector from the center of the element to the corresponding end point.

dia.attributes

The attributes in JointJS define how the graphics elements are to be rendered inside of the element and link views. All the standard SVG styling properties are available (both kebab-case and camelCase styles).

In addition JointJS modifies the behavior of existing attributes (the use of calc() for specifying attribute values) and defines new so-called "special" attributes and allows programmers to define their own.

calc()

The calc() function lets you perform calculations when specifying SVG attributes values.

Syntax:

The calc() function takes a simple expression as its parameter, with the expression's result used as the value. The expression can be any simple expression in one of the following forms:

  • Variable
    'calc(w)'
  • Variable Addition or Subtraction
    'calc(w + 5)'
    'calc(h - 10)'
  • Multiplication Variable
    'calc(2 * w)'
    'calc(0.5 * h)'
  • Multiplication Variable Addition or Subtraction
    'calc(2 * w + 5)'
    'calc(0.5 * h - 10)'

Where:

  • Variable is a symbol representing a value that can change, when the model attributes change (size, attrs).

    variable name description
    w width The current width of the model (model.prop('size/width')). The value can be bound to an SVGElement's size instead by using ref attribute.
    h height The current height of the model (model.prop('size/height')). The value can be bound to an SVGElement's size instead by using ref attribute.
    x x The current x coordinate of the SVGElement in the element's coordinate system. If the attribute is not bound to a specific SVGElement with ref attribute, the value of x is always zero.
    y y The current y coordinate of the SVGElement in the element's coordinate system. If the attribute is not bound to a specific SVGElement with ref attribute, the value of y is always zero.
    s shortest The shortest side of the rectangle. The minimum of width and height.
    l longest The longest side of the rectangle. The maximum of width and height.
    d diagonal The length of the diagonal of the rectangle of size width and height.

  • Multiplication is an optional floating number factor of the variable. It's a number followed by the * symbol.
    1.5 *
  • Addition or Subtraction is an optional floating number added or subtracted from the variable. It's a + or - symbol followed by a number.
    + 5
Notes:
  • Expression is case-sensitive.
  • The +, - and * operators do not require whitespace.
  • No extra parentheses are allowed.
  • It is permitted to nest calc() functions, in which case the inner ones are evaluated first. e.g
    'M 0 0 H calc(w - calc(h))'
    .

It can be used with the following attributes:

Examples:
el.resize(200, 100); // dia.Element

// <rect joint-selector="myRect" width="200" height="100" rx="20" ry="10" />
el.attr('myRect', {
   width: 'calc(w)',
   height: 'calc(h)',
   rx: 'calc(0.1*w)',
   ry: 'calc(0.1*h)'
});

// <image joint-selector="myImage" x="105" y="55" />
el.attr('myImage/x', 'calc(0.5*w+5)');
el.attr('myImage/y', 'calc(0.5*h+5)');

// <path joint-selector="myPath" d="M 10 50 190 50" />
el.attr('myPath/d', 'M 10 calc(0.5*h) calc(w-10) calc(0.5*h)')

// <polygon joint-selector="myPolygon" points="0,0 200,0 200,100 0,100" />
el.attr('myPolygon/d', '0,0 calc(w),0 calc(w),calc(h) 0,calc(h)');

// Resize the rectangle to match the text size with extra 5 pixels of padding
// <rect joint-selector="myTextBackground" />
// <text joint-selector="myText" >Some text</text>
el.attr('myTextBackground', {
    ref: 'myText',
    x: 'calc(x - 5)',
    y: 'calc(y - 5)'
    width: 'calc(w + 10)',
    height: 'calc(h + 10)',
 });

Here is the list of all built-in attributes.

dia.attributes.atConnectionLengthIgnoreGradient

Move the subelement to the point at a given distance along the connection path but do not auto-orient it according to the path's gradient. Use a positive number to define the distance from the source of the link and a negative number from the target of the link. It is valid only within the LinkView context.

link.attr('rectSelector', { atConnectionLengthIgnoreGradient: 30, width: 10, height: 10, fill: 'red' });

dia.attributes.atConnectionLengthKeepGradient

alias: atConnectionLength

Move and auto-orient the subelement to the point at a given distance along the connection path. Use a positive number to define the distance from the source of the link and a negative number from the target of the link. It is valid only within the LinkView context.

link.attr('rectSelector', { atConnectionLength: 30, width: 10, height: 10, fill: 'red' });
link.attr('rectSelector', { atConnectionLengthKeepGradient: 30, width: 10, height: 10, fill: 'red' });

dia.attributes.atConnectionRatioIgnoreGradient

Move the subelement to the point at a given ratio of the connection total length but do not auto-orient it according to the path's gradient. It accepts a number in the [0,1] range. It is valid only within the LinkView context.

link.attr('rectSelector', { atConnectionRatioKeepGradient: .5, width: 10, height: 10, fill: 'red' });

dia.attributes.atConnectionRatioKeepGradient

alias: atConnectionRatio

Move and auto-orient the subelement to the point at a given ratio of the connection total length. It accepts a number in the [0,1] range. It is valid only within the LinkView context.

link.attr('rectSelector', { atConnectionRatio: .5, width: 10, height: 10, fill: 'red' });
link.attr('rectSelector', { atConnectionRatioKeepGradient: .5, width: 10, height: 10, fill: 'red' });

dia.attributes.connection

If true, set the shape of the subelement to match the shape of the LinkView (set the 'd' attribute to the result of the link connector). It's valid only for SVGPathElement within the LinkView context.

You can also provide an object with the following options:

Name Type Description
stubs Number If provided, display only the beginning and end stubs of the connection and hide the remaining central section. A positive value determines the length of each stub. If the value is negative, it determines the length of the hidden section of the connection between the two stubs.
link1.attr('pathSelector', { connection: true, stroke: 'red', fill: 'none' });
link2.attr('pathSelector', { connection: { stubs: -20 }});

dia.attributes.containerSelector

Designate another subelement of the cell as a proxy target for the cell's container, whenever this subelement (the one on which this attribute is defined) becomes the target of an embedding. (Usually, this attribute needs to be defined on the `'root'` subelement of the cell, since that is the default target for the cell's container.) Expects a selector.

A change in the cell's container affects the following characteristics of the cell view:

  • embedding highlighter

// `standard.Rectangle` has `root`, `body` and `label` subelements
const rect = new joint.shapes.standard.Rectangle();
// we want to have the `label` on the outside and under the `body` of the rectangle:
rect.attr(['label'], { refY: '100%', textVerticalAnchor: 'top' });
// normally, when a user tries to embed a child to the rectangle, the `root` subelement would be highlighted (the wrapper of `body` and `label`)
// however, we want only the `body` to be highlighted, so we need to specify it as a proxy for `root`:
rect.attr(['root', 'containerSelector'], 'body');

dia.attributes.displayEmpty

Valid only for <text> subelements.

If set to true, the SVGTextElement with empty content will be rendered. It's useful when the text needs to be editable.

dia.attributes.event

The event attribute makes the selected node and its descendants trigger an arbitrary event when clicked (mousedown/touchstart). This event is triggered on the view itself and the paper. The paper handler is called with the signature cellView, evt, x, y, while the cell view handler is called only with evt, x, y.

element.attr({
  image: {
    // pointerdown on the image SVG node will trigger the `element:delete` event
    event: 'element:delete',
    xlinkHref: 'trash.png'
    width: 20,
    height: 20
  }
});
// Binding handler to the event
paper.on('element:delete', function(elementView, evt) {
  // Stop any further actions with the element view e.g. dragging
  evt.stopPropagation();
  if (confirm('Are you sure you want to delete this element?')) {
      elementView.model.remove();
  }
});

dia.attributes.fill

The fill attribute becomes a special attribute only in case it's defined as an object, instead of the usual SVG syntax (e.g. "#ffaabb"). If it's defined as an object, it is assumed to be either a gradient or pattern definition. It must have the form defined by the defineGradient() (resp. definePattern()) paper method.

Gradient

element.attr('rect/fill', {
    type: 'linearGradient',
    stops: [
        { offset: '0%', color: '#E67E22' },
        { offset: '20%', color: '#D35400' },
        { offset: '40%', color: '#E74C3C' },
        { offset: '60%', color: '#C0392B' },
        { offset: '80%', color: '#F39C12' }
    ]
});

Pattern

element.attr('rect/fill', {
    type: 'pattern',
    attrs: {
        width: 10,
        height: 10
    },
    markup: [{
        tagName: 'polygon',
        attributes: {
            points: '0,0 2,5 0,10 5,8 10,10 8,5 10,0 5,2'
        }
    }]
});

dia.attributes.filter

The filter attribute becomes a special attribute only in case it's defined as an object, instead of the usual SVG syntax (e.g. "url(#myfilter)"). If it's defined as an object, it must have the form defined by by the filterGradient() paper method.

element.attr('rect/filter', {
    name: 'dropShadow',
    args: {
        dx: 2,
        dy: 2,
        blur: 3
    }
});

dia.attributes.highlighterSelector

Designate another subelement of the cell as a proxy target for the cell's magnet, whenever this subelement (the one on which this attribute is defined) becomes the source/target of a link. (Usually, this attribute needs to be defined on the `'root'` subelement of the cell, since that is the default target for the cell's magnet.) Expects a selector.

A change in the cell's magnet affects the following characteristics of the cell view:

  • magnet highlight

It has no effect on the connection validation and link model attributes.

// `standard.Rectangle` has `root`, `body` and `label` subelements
const rect = new joint.shapes.standard.Rectangle();
// we want to have the `label` on the outside and under the `body` of the rectangle:
rect.attr(['label'], { refY: '100%', textVerticalAnchor: 'top' });
// normally, highlighters would appear around the `root` subelement (the wrapper of `body` and `label`)
// however, we want highlighters to highlight only to the `body` subelement, so we need to specify it as a proxy for `root`:
rect.attr(['root','highlighterSelector'], 'body');

dia.attributes.magnet

When set to true, the subelement can become the source/target of a link during link reconnection. Useful for so called 'ports'. When set to magnet: 'passive', a new link won't be added to the graph when a user clicks on the respective magnet. This use case is common for the creation of 'input' ports.

const paper = new joint.dia.Paper({
    // Other Paper options
    // The default behaviour of magnet validation
    validateMagnet: function(_cellView, magnet, _evt) {
        return magnet.getAttribute('magnet') !== 'passive';
    }
});

const portIn = {
    label: {
        // Label position and markup
    },
    attrs: {
        portBody: {
            // Other portBody attributes
            magnet: 'passive' // No link added upon user click
        },
        label: { text: 'port' }
    },
    markup: [{
        tagName: 'rect',
        selector: 'portBody'
    }]
};

dia.attributes.magnetSelector

Designate another subelement of the cell as a proxy target for the cell's magnet, whenever this subelement (the one on which this attribute is defined) becomes the source/target of a link. (Usually, this attribute needs to be defined on the `'root'` subelement of the cell, since that is the default target for the cell's magnet.) Expects a selector.

A change in the cell's magnet affects the following characteristics of the cell view:

  • link anchor
  • link connection point
  • connector
  • router

It has no effect on the connection validation, magnet highlighter and the source and target link model attributes.

// `standard.Rectangle` has `root`, `body` and `label` subelements
const rect = new joint.shapes.standard.Rectangle();
// we want to have the `label` on the outside and under the `body` of the rectangle:
rect.attr(['label'], { refY: '100%', textVerticalAnchor: 'top' });
// normally, links would connect to the `root` subelement (the wrapper of `body` and `label`)
// however, we want links to connect only to the `body` subelement, so we need to specify it as a proxy for `root`:
rect.attr(['root','magnetSelector'], 'body');

dia.attributes.port

An object containing at least an id property. This property uniquely identifies the port. If a link gets connected to a magnet that has also a port object defined, the id property of the port object will be copied to the port property of the source/target of the link.

dia.attributes.ref

Markup or CSS selector pointing to an element that is used as a reference for relative positioning attributes.

dia.attributes.refCx

Set cx attribute of the subelement relatively to the width of the element referenced to by the selector in ref attribute. If the value is in the [0, 1] interval (or expressed in percentages, e.g. '80%'), the cx of the subelement will be set as a percentage of the width of the referenced element. If the value is <0 or >1, the height of the subelement will be smaller/bigger than the width of the referenced element by the amount specified. Note that this makes sense only for SVG elements that support rx and ry attributes, such as <ellipse>.

dia.attributes.refCy

Set cy attribute of the subelement relatively to the height of the element referenced to by the selector in ref attribute. If the value is in the [0, 1] interval (or expressed in percentages, e.g. '80%'), the cy of the subelement will be set as a percentage of the height of the referenced element. If the value is <0 or >1, the height of the subelement will be smaller/bigger than the height of the referenced element by the amount specified. Note that this makes sense only for SVG elements that support rx and ry attributes, such as <ellipse>.

dia.attributes.refDKeepOffset

Set d attribute of the <path> subelement relatively to the dimensions and position of the element referenced by the selector in the ref attribute. The refD path data is scaled so that the path's dimensions match the reference element's dimensions, and translated so that the path's origin matches the origin of the reference element.

The original path data offset is preserved. This means that if the top-left corner of the refD bounding box does not lie at 0,0, the gap between the path and origin is preserved in the rendered shape, as well.

var Path = joint.dia.Element.define('examples.Path', {
    attrs: {
        path: {
            refDKeepOffset: 'M 10 10 30 10 30 30 z', // path offset is 10,10
            fill: 'red',
            stroke: 'black'
        }
    }
}, {
    markup: 'path'
});

var p = (new Path()).resize(40, 40).addTo(graph);
// the rendered path's `d` attribute will be 'M 10 10 50 10 50 50 z'
// can be obtained by `p.findView(paper).vel.findOne('path').attr('d');`

dia.attributes.refDResetOffset

alias: refD

Set d attribute of the <path> subelement relatively to the dimensions and position of the element referenced by the selector in the ref attribute. The refD path data is scaled so that the path's dimensions match the reference element's dimensions, and translated so that the path's origin matches the origin of the reference element.

The original path data offset is not preserved. This means that if the top-left corner of the refD bounding box does not lie at 0,0, the path is translated so that this gap disappears. The rendered path then fits perfectly into the reference element's bounding box.

var Path = joint.dia.Element.define('examples.Path', {
    attrs: {
        path: {
            refDResetOffset: 'M 10 10 30 10 30 30 z', // path offset of 10,10 will be discarded
            fill: 'red',
            stroke: 'black'
        }
    }
}, {
    markup: 'path'
});

var p = (new Path()).resize(40, 40).addTo(graph);
// the rendered path's `d` attribute will be 'M 0 0 40 0 40 40 z'
// can be obtained by `p.findView(paper).vel.findOne('path').attr('d');`

dia.attributes.refDx

alias: ref-dx

Make x-coordinate of the subelement relative to the right edge of the element referenced to by the selector in ref attribute.

dia.attributes.refDy

Make y-coordinate of the subelement relative to the bottom edge of the element referenced to by the selector in ref attribute.

dia.attributes.refHeight

alias: ref-height

Set height of the subelement relatively to the height of the element referenced to by the selector in ref attribute. If the value is in the [0, 1] interval (or expressed in percentages, e.g. '80%'), the height of the subelement will be set as a percentage of the height of the referenced element. If the value is <0 or >1, the height of the subelement will be smaller/bigger than the height of the referenced element by the amount specified. Note that this makes sense only for SVG elements that support width and height attributes, such as <rect>.

dia.attributes.refHeight2

Same as refHeight. Useful when one needs to resize an element absolutely and relatively at the same time. Note that all percentages are relative to 100% of the referenced height.

{ refHeight: 20, refHeight2: '-75%' } // resizes the element to 25% of the reference height (25% = 100% - 75%) plus extra 20 pixels

dia.attributes.refPointsKeepOffset

Set the points attribute of the <polygon> or <polyline> subelement relatively to the dimensions and position of the element referenced by the selector in the ref attribute. The refPoints are scaled so that the subelement's dimensions match the reference element's dimensions, and translated so that the their origin matches the origin of the reference element.

The original points offset is preserved. This means that if the top-left corner of the refPoints bounding box does not lie at 0,0, the gap between the points and origin is preserved in the rendered shape, as well.

var Polygon = joint.dia.Element.define('examples.Polygon', {
    attrs: {
        polygon: {
            refPoints: '10,10 30,10 30,30', // points offset is 10,10
            fill: 'red',
            stroke: 'black'
        }
    }
}, {
    markup: 'polygon'
});

var p = (new Polygon()).resize(40, 40).addTo(graph);
// the rendered polygon's `points` attribute will be '10,10 50,10 50,50'
// can be obtained by `p.findView(paper).vel.findOne('polygon').attr('points');`

dia.attributes.refPointsResetOffset

alias: refPoints

Set the points attribute of the <polygon> or <polyline> subelement relatively to the dimensions and position of the element referenced by the selector in the ref attribute. The refPoints are scaled so that the subelement's dimensions match the reference element's dimensions, and translated so that the their origin matches the origin of the reference element.

The original points offset is not preserved. This means that if the top-left corner of the refPoints bounding box does not lie at 0,0, the subelement is translated so that this gap disappears. The rendered subelement then fits perfectly into the reference element's bounding box.

var Polygon = joint.dia.Element.define('examples.Polygon', {
    attrs: {
        polygon: {
            refPoints: '10,10 30,10 30,30', // points offset of 10,10 will be discarded
            fill: 'red',
            stroke: 'black'
        }
    }
}, {
    markup: 'polygon'
});

var p = (new Polygon()).resize(40, 40).addTo(graph);
// the rendered polygon's `points` attribute will be '0,0 40,0 40,40'
// can be obtained by `p.findView(paper).vel.findOne('polygon').attr('d');`

dia.attributes.refRCircumscribed

Set the r attribute of the subelement relatively to the circumscribed size (length of the diagonal of the bounding box) of the element referenced by the selector in the ref attribute. If the value is in the [0, 1] interval (or expressed in percentages, e.g. '80%'), the r of the subelement will be set as a percentage of the size of the referenced element. If the value is <0 or >1, the size of the subelement will be smaller/bigger than the size of the referenced element by the amount specified. Note that this makes sense only for SVG elements that support r attribute, such as <circle>.

dia.attributes.refRInscribed

alias: refR

Set the r attribute of the subelement relatively to the inscribed size (width or height of the bounding box, whichever is smaller) of the element referenced by the selector in the ref attribute. If the value is in the [0, 1] interval (or expressed in percentages, e.g. '80%'), the r of the subelement will be set as a percentage of the size of the referenced element. If the value is <0 or >1, the size of the subelement will be smaller/bigger than the size of the referenced element by the amount specified. Note that this makes sense only for SVG elements that support r attribute, such as <circle>.

dia.attributes.refRx

Set rx attribute of the subelement relatively to the width of the element referenced to by the selector in ref attribute. If the value is in the [0, 1] interval (or expressed in percentages, e.g. '80%'), the rx of the subelement will be set as a percentage of the width of the referenced element. If the value is <0 or >1, the height of the subelement will be smaller/bigger than the width of the referenced element by the amount specified. Note that this makes sense only for SVG elements that support rx and ry attributes, such as <ellipse>.

dia.attributes.refRy

Set ry attribute of the subelement relatively to the height of the element referenced to by the selector in ref attribute. If the value is in the [0, 1] interval (or expressed in percentages, e.g. '80%'), the ry of the subelement will be set as a percentage of the height of the referenced element. If the value is <0 or >1, the height of the subelement will be smaller/bigger than the height of the referenced element by the amount specified. Note that this makes sense only for SVG elements that support rx and ry attributes, such as <ellipse>.

dia.attributes.refWidth

alias: ref-width

Set width of the subelement relatively to the width of the element referenced to by the selector in ref attribute. If the value is in the [0, 1] interval (or expressed in percentages, e.g. '80%'), the width of the subelement will be set as a percentage of the width of the referenced element. If the value is <0 or >1, the width of the subelement will be smaller/bigger than the width of the referenced element by the amount specified. For example, 'ref-width': .75 sets the width of the subelement to 75% of the width of the referenced element. 'ref-width': 20 makes the width to be 20px less than the width of the referenced element. Note that this makes sense only for SVG elements that support width and height attributes, such as <rect>.

dia.attributes.refWidth2

Same as refWidth. Useful when one needs to resize an element absolutely and relatively at the same time. Note that all percentages are relative to 100% of the referenced width.

{ refWidth: 20, refWidth2: '-75%' } // resizes the element to 25% of the reference width (25% = 100% - 75%) plus extra 20 pixels

dia.attributes.refX

alias: ref-x

Make x-coordinate of the subelement relative to the x-coordinate of the element referenced to by the selector in ref attribute. If ref-x is in the (0,1) interval (or expressed in percentages, e.g. '80%'), the offset is calculated from the fraction of the bounding box of the referenced element. Otherwise, it is an absolute value in pixels.

dia.attributes.refX2

Same as refX. Useful when one needs to position an element absolutely and relatively at the same time.

{ refX: '50%', refX2: 20 } // moves the element by 50% of the referenced width plus extra 20 pixels.

dia.attributes.refY

alias: ref-y

Make y-coordinate of the subelement relative to the y-coordinate of the element referenced to by the selector in ref attribute. If ref-y is in the (0,1) interval (or expressed in percentages, e.g. '80%'), the offset is calculated from the fraction of the bounding box of the referenced element. Otherwise, it is an absolute value in pixels.

dia.attributes.refY2

Same as refY. Useful when one needs to position an element absolutely and relatively at the same time.

{ refY: '50%', refY2: 20 } // moves the element by 50% of the referenced height plus extra 20 pixels.

dia.attributes.resetOffset

If set to true, the subelement offset (the distance from x0 y0 to the most top-left point) will be reset to x0 y0.

element.attr({
  path: {
    // The path bbox for `d="M 10 10 20 20"` is x10 y10 w10 h10.
    d: 'M 10 10 20 20',
    // The path bbox will be changed to x0 y0 w10 h10.
    // This has same effect as passing path with `d="M 0 0 10 10"`
    resetOffset: true
  }
});

dia.attributes.sourceMarker

Valid for <path> subelements. It draws an SVG element at the beginning of a path (the source of the link). The element is automatically rotated based on the path direction. It must have the form defined by the defineMarker() paper method.

link.attr('line/sourceMarker', {
  type: 'circle', // SVG Circle
  fill: '#666',
  stroke: '#333',
  r: 5, // radius of the circle
  cx: 5 // move the centre of the circle 5 pixels from the end of the path
});

dia.attributes.stroke

The stroke attribute becomes a special attribute only in case it's defined as an object. This has the exact same behaviour as the fill attribute.

dia.attributes.style

An object containing CSS styles for a subelement.

dia.attributes.targetMarker

Valid for <path> subelements. The same as sourceMarker but draws an SVG element at the end of the path. Note the coordinate system for drawing is rotated by 180 degrees for convenience (this allows to use the same marker for source and target and have them both face the connected elements).

dia.attributes.text

Valid only for <text> subelements.

The text attribute contains the text that should be set on the subelement. If the provided string does not contain any newline characters ('\n'), the text is set directly as the content of the <text> subelement. Alternatively, if the provided string has multiple lines, each line becomes the content of a <tspan> child of the <text> subelement.

If you need the text to be automatically wrapped inside the <text> subelement, you should use the textWrap attribute instead. It can automatically add line breaks into the provided string as necessary, and mark them with newline characters.

dia.attributes.textPath

Valid only for <text> subelements. textPath can be either a string or an object.

If it is a string, it specifies a path the text will be rendered along.

If it is an object, then it can contain a d property that specifies the path the text will be rendered along. Alternatively use selector property, which is useful for targeting a specific SVGPathElement within the shape. The option expects a string selector (CSS or JSONMarkup selector). Use startOffset property to control the text position on the path (e.g. '50%', 20). See the Vectorizer.text method for more details.

dia.attributes.textVerticalAnchor

Valid only for <text/> subelements. The attribute is used to (top-, middle- or bottom-) align a text, relative to a point determined by reference to provided x, y, refX, refY, and similar attributes. See the Vectorizer.text method for more details.

dia.attributes.textWrap

Valid only for <text> subelements.

Similar to the text attribute, except the provided string is automatically wrapped to fit within the reference bounding box.

Expects an object with a text property and optional width and height, which can adjust the final size of the wrapped text. Negative values decrease the dimension (e.g. to add padding around the wrapped text); positive values increase the dimension. Percentage values are accepted as well.

If the text cannot fit into the bounding box as specified, the overflowing words are cut off. If the ellipsis option is provided, an ellipsis string is inserted before the cutoff. If no words can fit into the bounding box at all, no text is inserted. See util.breakText for more info.

textWrap: {
  text: 'lorem ipsum dolor sit amet consectetur adipiscing elit',
  width: -10, // reference width minus 10
  height: '50%', // half of the reference height
  ellipsis: true // could also be a custom string, e.g. '...!?'
}

dia.attributes.title

Add the text-only description in form of a <title> element to the associated node. The title is not rendered as part of the graphics, but it's displayed as a tooltip.

element.attr('rect/title', 'Description of the rectangle');

dia.attributes.vertexMarker

Valid for <path> subelements. The same as sourceMarker but draws SVG elements at every vertex of the path.

dia.attributes.xAlignment

alias: x-alignment

If set to 'middle', the subelement will be centered around its new x-coordinate.

dia.attributes.yAlignment

alias: y-alignment

If set to 'middle', the subelement will be centered around its new y-coordinate.

dia.Cell

The basic model for diagram cells. It's a Backbone model with a few additional properties and methods. Most importantly, every cell has a unique ID that is stored in the id property.

dia.Cell.define

define(type [, defaultAttributes, prototypeProperties, staticProperties])

Helper to define a new Cell class or extend an existing one.

The type must be a unique identifier of the class, which determines the location of the class definition in the joint.shapes namespace (type is the path to the class definition delimited by dots: .). When creating an instance of the cell, attributes will be set to the value from the defaultAttributes, unless overridden by subclass or instance attributes.

// Define a new Ellipse class in `joint.shapes.examples` namespace
// Inherits from generic Element class
var Ellipse = joint.dia.Element.define('examples.Ellipse', {
    // default attributes
    markup: [{
        tagName: 'ellipse',
        selector: 'ellipse' // not necessary but faster
    ],
    attrs: {
        ellipse: {
            fill: 'white',
            stroke: 'black',
            strokeWidth: 4,
            refRx: .5,
            refRy: .5,
            refCx: .5,
            refCy: .5
        }
    }
});

// Instantiate an element
var ellipse = (new Ellipse()).position(100, 100).size(120, 50).addTo(graph);

// Define a new ColoredEllipse class
// Inherits from Ellipse
var ColoredEllipse = Ellipse.define('examples.ColoredEllipse', {
    // overridden Ellipse default attributes
    // other Ellipse attributes preserved
    attrs: {
        ellipse: {
            fill: 'lightgray'
        }
    }
}, {
    // prototype properties
    // accessible on `this.(...)` - as well as, more precisely, `this.prototype.(...)`
    // useful for custom methods that need access to this instance
    // shared by all instances of the class
    randomizeStrokeColor: function() {
        var randomColor = '#' + ('000000' + Math.floor(Math.random() * 16777215).toString(16)).slice(-6);
        return this.attr('ellipse/stroke', randomColor);
    }
}, {
    // static properties
    // accessible on `this.constructor.(...)`
    // useful for custom methods and constants that do not need an instance to operate
    // however, a new set of static properties is generated every time the constructor is called
    // (try to only use static properties if absolutely necessary)
    createRandom: function() {
        return (new ColoredEllipse()).randomizeStrokeColor();
    }
});

// Instantiate an element
var coloredEllipse = ColoredEllipse.createRandom().position(300, 100).size(120, 50).addTo(graph);

dia.Cell.markup

markup

Either an XML string or JSON markup specifying an array of JSON elements. Used as a template to build DOM Elements on the fly when the associated cellView is rendered.

XML String

A valid XML string that contains either a single tagName or XML that can be parsed with DOMParser.

markup: 'rect'
markup: '<rect class="rectangle"/>'
markup: '<rect><g><circle/><circle/></g>'

Note that defining Cell markup with XML strings is slower than defining it with JSON arrays, precisely because of the need for parsing. We strongly recommend you to use the JSON markup for your Cell definitions.

JSON Markup

JSON markup is defined recursively as an array of JSONElement, where JSONElement is a plain object with the following properties:

  • tagName (string) (required) The type of element to be created.
  • selector (string) A unique selector for targeting the element within the attr cell attribute.
  • groupSelector (string | string[]) A selector for targeting multiple elements within the attr cell attribute. The group selector name must not be the same as an existing selector name.
  • namespaceURI (string) The namespace URI of the element. It defaults to SVG namespace "http://www.w3.org/2000/svg".
  • attributes (object with attributes name-value pairs) Attributes of the element.
  • style (object with CSS property-value pairs) The style attribute of the element.
  • className (string) The class attribute of the element.
  • children (JSONMarkup) The children of the element.
  • textContent (string) The text content of the element.
// single DOM element
markup: [{ tagName: 'rect' }]

// multiple DOM elements
markup: [{
    tagName: 'rect',
    selector: 'body'
}, {
    tagName: 'text',
    selector: 'label',
    attributes: {
        'stroke': 'none'
    }
}]

// nested DOM elements
markup: [{
    tagName: 'g',
    children: [{
        tagName: 'circle',
        selector: 'circle1',
        groupSelector: 'circles'
    }, {
        tagName: 'circle',
        selector: 'circle2',
        groupSelector: 'circles'
    }]
}]
JSON Markup attributes

Anything you define in markup is evaluated once at CellView creation (the DOM elements and their attributes). That means it's important to think about the runtime of your application. If you have SVG attributes that don't change throughout the runtime, you can add them to the markup.

As markup is something all instances of the element type are expected to have in common, inheriting from the subtype prototype is more efficient. Nevertheless, it is still possible to provide custom markup to individual instances of your class by providing markup later.

Anything in the attrs attribute is evaluated on every change of the model (e.g. a resize or an attrs change). As JointJS special attributes mostly depend on the current state of the model (size, attrs, angle), they should always be defined inside attrs.

SVG attributes that are modified at some point in the application should also be added to attrs (e.g. user changes the color of the element).

joint.dia.Element.define('standard.Rectangle', {
    attrs: {
        body: {
            width: 'calc(w)',
            height: 'calc(h)',
            stroke: 'red',
            fill: '#333333' // We wan't to modify the fill color of our instances
        },
        label: {
            // attributes
        }
    }
}, {
    markup: [{
        tagName: 'rect',
        selector: 'body',
        attributes: {
            'stroke-width': 2 // Use native SVG kebab-case for attributes in markup
        }
    }, {
        tagName: 'text',
        selector: 'label',
        attributes: {
            'stroke': 'none' // We don't need any instances to have a stroke value for text
        }
    }]
});
Setting attributes with selectors
Here are simple rules how SVG attributes are set on the nodes when one uses combination of selector and groupSelector.
  • selector is unique i.e. can target a single node only.
  • selector takes precedence over groupSelector.
  • groupSelector targeting n nodes takes precedence over groupSelector targeting m nodes for n < m. When n === m the order how the attributes are applied is unspecified.

In the example below, the circle with the selector circle1 is filled with "red" color. All the other circles are filled with "blue" color.

cell.attr({
    circle1: { fill: 'red' },
    circles: { fill: 'blue', stroke: 'black' }
});
dia.Cell.prototype.getParentCell
cell.getParentCell()

Return the parent cell of cell or null if there is none.

dia.Cell.prototype.isElement
cell.isElement()

Always returns false. The reason the method is here is that both joint.dia.Element and joint.dia.Link inherit from joint.dia.Cell. This method is useful if you don't know what the cell is. Calling cell.Element() is equivalent to cell instanceof joint.dia.Element. Example:

var cell = graph.getCell(myId)
if (cell.isElement()) {
    // Do something if the cell is an element.
}
dia.Cell.prototype.parent
cell.parent()

Return the parent property of the cell.

If the cell is a part of an embedding, the id of the parent cell is returned as a string.

If you need to be sure that a Cell is returned (and not its id), use the cell.getParentCell function instead.

cell.parent(parentId [, opt])

Set the parent property of the cell to parentId provided.

dia.CellView

The view for the joint.dia.Cell model. It inherits from Backbone.View and is responsible for:

  • Rendering a cell inside of a paper
  • Handling the cell's pointer events
  • Provides various methods for working with the cell (visually)

To find the view associated with a specific cell (model), use the findViewByModel method of the paper. For example:

var cellView = paper.findViewByModel(cell);

dia.CellView.custom

When you define a custom CellView, which listens to the underlying model changes and update itself (modifying its sub-elements directly) you should follow the instructions below in order to make the view work correctly in the async mode.

Note, that when a view needs an update (a model attribute has changed e.g. size has changed), it requests the update from the paper first. The paper confirms the update immediately (sync mode) or in the next animation frame (async mode). The updates may be also held by the paper as long as the paper is frozen and released when the paper changes its state to unfrozen.

The update requests are sent to the paper via flags and later received back all at once. The paper accumulates flags received and confirms the updates when the right time has come.

Methods and terminology

flagLabel - is an arbitrary string or array of strings

flags - are encoded flag labels

CellView.prototype.presentationAttributes - is an object that maps model attributes to flag labels.

CellView.prototype.confirmUpdate(flags, opt) - This method receives all scheduled flags and based on them updates the view

CellView.prototype.hasFlag(flags, flagLabel) - Checks whether a flagLabel is present in the current update.

CellView.addPresentationAttributes(presentationAttributes) - Extends the CellView presentation attributes with another presentationAttributes. - The method makes sure the original CellView attributes are preserved. It returns a new object with all presentation attributes.

Usage
const FadeView = joint.dia.ElementView.extend({
    // Make sure that all super class presentation attributes are preserved
    presentationAttributes: joint.dia.ElementView.addPresentationAttributes({
        // mapping the model attributes to flag labels
        faded: 'flag:opacity'
    }),
    confirmUpdate(flags, ...args) {
        joint.dia.ElementView.prototype.confirmUpdate.call(this, flags, ...args);
        if (this.hasFlag(flags, 'flag:opacity')) this.toggleFade();
    },
    toggleFade() {
        this.el.style.opacity = this.model.get('faded') ? 0.5 : 1;
    }
});
dia.CellView.prototype.findAttribute
cellView.findAttribute(attribute, node)

Return the value of the specified attribute of node.

If node does not set a value for attribute, start recursing up the DOM tree from node to look for attribute at the ancestors of node. If the recursion reaches CellView's own node and attribute is not found even there, return null.

dia.CellView.prototype.findBySelector
cellView.findBySelector([selector, root, selectors])

Return an array of subelements of this CellView which are identified by selector. If no such subelements are found, return an empty array.

This method mimics jQuery element search methods in that it always returns an array. If you are only expecting to find a single subelement (most common scenario), you can get it by accessing the first element in the returned array – e.g. this.findBySelector('body')[0].

If you do not specify a selector, the root of the CellView is returned as the only element of the return array. For backwards compatibility, the same applies also if you provide the special value selector = '.'. By default root = this.el (the wrapping <g> SVGElement of the CellView), but if you provide a different root (see below), then that value is returned instead.

By default, JointJS searches for matching subelements among descendants of this.el SVGElement. As an advanced feature, you may provide a different root – e.g. an el SVGElement of another CellView. Then JointJS searches for matching subelements among the descendants of that SVGElement.

By default, JointJS uses this.selectors array for reference. (The selectors array is a cached structure of this CellView's SVGElement descendants as defined by the markup attribute of the Cell model from which the CellView was initialized.) As an advanced feature, you may provide a different selectors array for the search – e.g. a selectors array of another CellView.

(Deprecated) For backwards compatibility, if no matching subelement is found among selectors, then jQuery is used to try and find an element through CSS selectors ($(root).find(selector).toArray()). If you are using standard shapes, you may disable this functionality for increased performance by setting useCSSSelectors = false in the global config.

dia.CellView.prototype.findPortNode
cellView.findPortNode(portId)

Return the port element of this CellView that is identified by portId (i.e. the SVGElement within this.el which has 'port': portId).

If the CellView does not have a port identified by portId, return null.

cellView.findPortNode(portId, selector)

If selector is also specified, return the subelement of the port element that is identified by selector, according to the rules of the cellView.findBySelector() function.

If the port element does not have a subelement that matches selector, return null.

dia.CellView.prototype.highlight
cellView.highlight([el[, options]])

Add a highlighter to the cell view.

When the method is called, the cell:highlight paper event is triggered.

For greater flexibility use highlighters API instead.

Arguments:

  • el - if not provided, then the cell view's el will be used
  • options:
    • highlighter:
      • name - the name of the highlighter (see highlighters)
      • options - an options object that will be passed directly to the highlighter specified by name
    • type - the type of highlighting
dia.CellView.prototype.unhighlight
cellView.unhighlight([el[, options]])

Removes a highlighter added to the cell view.

When the method is called, the cell:unhighlight paper event is triggered.

It is important to note that if you highlighted a cell using custom options, you must provide those exact same options when using the unhighlight method.

To avoid this and for greater flexibility use highlighters API instead.

dia.Element

The basic model for diagram elements. It inherits from joint.dia.Cell with a few additional properties and methods specific to elements. For a quick introduction to elements, see our tutorial.

Elements' properties may be split into several groups according to their function:

Geometry

  • position - coordinates of the element, provided as an object with x and y keys. The property may be accessed or set directly using regular Backbone set('position')/get('position') methods or through Element's translate() method.
  • angle - angle of rotation of the element in degrees. The rotation origin is always the center of the element. The property may be accessed or set directly using regular Backbone set('angle')/get('angle') methods or through Element's rotate() method.
  • size - size of the element, provided as an object with width and height keys. The property may be accessed or set directly using regular Backbone set('size')/get('size') methods or through Element's translate() method.

Presentation

Each joint.dia.Element defines its own SVG markup which is then used by joint.dia.ElementView to render the element to the paper. For instance, the joint.shapes.standard.Rectangle element (which inherits from joint.dia.Element) defines its markup using the JSON array notation as follows:

markup: [{
    tagName: 'rect',
    selector: 'body',
}, {
    tagName: 'text',
    selector: 'label'
}]

As we can see, the joint.shapes.standard.Rect shape consists of two subelements: one SVGRectElement named 'body' and one SVGTextElement named 'label'. The attrs object refers to the subelements' names (selectors) to provide SVG attributes to these constituent SVGElements.

Styling

The keys of the attrs object are selectors that match subelements defined in the element's markup. The values of this object are SVG attributes that will be set on the selected subelements. One can find the full list of SVG attributes and their descriptions online, e.g. on MDN.

For example, in order to set a red fill color on a subelement called 'body', the attrs object would contain:

body: { fill: 'red' }

If you simply need to change a value of an attribute, it is not recommended to modify the attrs object directly. Instead, use the element.attr() method.

We can use the joint.shapes.standard.Rectangle element (which inherits from joint.dia.Element) as an example. The attrs object in its definition is provided below:

attrs: {
    body: {
        refWidth: '100%',
        refHeight: '100%',
        strokeWidth: 2,
        stroke: '#000000',
        fill: '#FFFFFF'
    },
    label: {
        textVerticalAnchor: 'middle',
        textAnchor: 'middle',
        refX: '50%',
        refY: '50%',
        fontSize: 14,
        fill: '#333333'
    }
}

Notice that the object makes use of special JointJS attributes (e.g. refWidth, textVerticalAnchor) on top of standard SVG attributes (e.g. stroke, fill). All of these special attributes are listed in the attributes section of this documentation. You should also refer to our tutorial on special attributes.

Attributes

Attributes defined in markup are evaluated once at CellView creation, while attributes defined in attrs are evaluated on every model change. As JointJS special attributes usually depend on the current state of the model, we should define them in attrs, along with any other SVG attributes that will be modified in the runtime of your application.

Z

The z property specifies the stack order of the element in the SVG DOM. An element with a higher z value will be rendered in front of an element with a lower z value. (This also applies to Links.)

Ports

You may define and group ports on the Element with the ports attribute. Each can have its own markup and attrs, and its own label. Grouped ports may share properties and behaviors. See the element ports documentation for more information.

Nesting

The last two properties of elements are embeds and parent. These two are related to elements that contain or are contained within other elements, forming a hierarchical structure.

  • embeds - a list of id's of the Cells that are embedded inside this Element.
  • parent - the id of the Element that is the parent of this element. When a parent element is translated, all its children get translated too.

Events

Elements trigger several special events, detailed in the element events documentation.

Custom Element

It is possible to extend the joint.dia.Element class to create a custom element. A custom element may override Element properties to assign its own defaults. These values override builtin defaults, if provided, and are applied to all instances of the new Element type, unless an individual instance overrides them with its own values. The following Element properties are applicable in this context:

  • markup - provide default element markup for all instances of this Element type, specified with a JSON array.
  • attrs - provide default element styling for all instances of this Element type. These allow you to change the style and size of SVG elements, identified by their selectors.

Creating custom elements is explained in more detail in our tutorial.

dia.Element.events

The following list contains events that you can react on:

  • change - generic event triggered for any change on the element - fn(element, opt)
  • change:position - triggered when the element changes its position - fn(element, newPosition, opt)
  • change:angle - triggered when the element gets rotated - fn(element, newAngle, opt)
  • change:size - triggered when the element gets resized - fn(element, newSize, opt)
  • change:attrs - triggered when the element changes its attributes - fn(element, newAttrs, opt)
  • change:embeds - triggered when other cells were embedded into the element - fn(element, newEmbeds, opt)
  • change:parent - triggered when the element got embedded into another element - fn(element, newParent, opt)
  • change:z - triggered when the element is moved in the z-level (toFront and toBack) - fn(element, newZ, opt)
  • transition:start - triggered when a transition starts. - fn(element, pathToAttribute)
  • transition:end - triggered when a transiton ends. - fn(element, pathToAttribute)
// Listening for changes of the position to a single element
element1.on('change:position', function(element1, position) {
  alert('element1 moved to ' + position.x + ',' + position.y);
});
// All elements events are also propagated to the graph.
graph.on('change:position', function(element, position) {
  console.log('Element ' + element.id + 'moved to ' + position.x + ',' + position.y);
});
// Using the option parameter and a custom attribute
graph.on('change:custom', function(element, custom, opt) {
  if (opt.consoleOutput) {
    console.log('Custom attribute value changed to "' + custom + '"');
  }
});
element2.prop('custom', 'myValue', { consoleOutput: true });

dia.Element.ports

Ports

Many diagramming applications deal with elements with ports. Ports are usually displayed as circles inside diagram elements and are used not only as "sticky" points for connected links, but they also further structure the linking information. It is common that certain elements have lists of input and output ports. A link might not then point to the element as a whole, but to a certain port instead.

It's easy to add ports to arbitrary shapes in JointJS. This can be done either by passing a ports definition as an option in the constructor, or using the ports API to get/add/remove single or multiple ports. For more information on how to define ports please see the Port configuration section.

Port API on joint.dia.Element
Port configuration
// Single port definition
const port = {
    // id: 'abc', // Generated if `id` value is not present
    group: 'a',
    args: {}, // Extra arguments for the port layout function, see `layout.Port` section
    label: {
        position: {
            name: 'left',
            args: { y: 6 } // Extra arguments for the label layout function, see `layout.PortLabel` section
        },
        markup: [{
            tagName: 'text',
            selector: 'label'
        }]
    },
    attrs: {
        body: { magnet: true, width: 16, height: 16, x: -8, y: -4, stroke: 'red', fill: 'gray'},
        label: { text: 'port', fill: 'blue' }
    },
    markup: [{
        tagName: 'rect',
        selector: 'body'
    }]
};

// a.) Add ports in constructor.
const rect = new joint.shapes.standard.Rectangle({
    position: { x: 50, y: 50 },
    size: { width: 90, height: 90 },
    ports: {
        groups: {
            'a': {}
        },
        items: [
            { group: 'a' },
            port
        ]
    }
});

// b.) Or add a single port using API
rect.addPort(port);

rect.getGroupPorts('a');
/*
   [
       { * Default port settings * },
       { * Follows port definition * },
       { * Follows port definition * }
    ]
*/

id string It is automatically generated if no id is provided. IDs must be unique in the context of a single shape - two ports with the same port id are therefore not allowed (Element: found id duplicities in ports. error is thrown).
group string Group name, more info in the groups section.
args object Arguments for the port layout function. Available properties depend on the type of layout. More information can be found in layout.Port.
attrs object JointJS style attribute definition. The same notation as the attrs property on Element.
markup MarkupJSON | string

Custom port markup. Multiple roots are not allowed. Valid notation would be:

markup: [{
    tagName: 'g',
    children: [{
        tagName: 'rect',
        selector: 'bodyInner',
        className: 'outer',
        attributes: {
            'width': 15,
            'height': 15,
            'fill': 'red'
        }
    }, {
        tagName: 'rect',
        selector: 'bodyOuter',
        className: 'inner',
        attributes: {
            'width': 15,
            'height': 15,
            'fill': 'blue',
            'x': 10
        }
    }]
}]

The default port looks like the following: <circle class="joint-port-body" r="10" fill="#FFFFFF" stroke="#000000"/>.

label object Port label layout configuration. E.g. label position, label markup. More information about port label layouts can be found in layout.PortLabel.
  • label.position
string | object

Port label position configuration. It can be a string for setting the port layout type directly with default settings, or an object where it's possible to set the layout type and options.

{ position: 'left'}

// or ...
{
    position: {
        name: 'left',
        args: {
            dx: 10
        }
    }
}
  • label.position.name
string It states the layout type. It matches the layout method name defined in the joint.layout.PortLabel namespace: name: 'left' is implemented as joint.layout.PortLabel.left.
  • label.position.args
object Additional arguments for the layout method. Available properties depend on the layout type. More information can be found in the layout.PortLabel section.
  • label.markup
MarkupJSON | string Custom port label markup. Multiple roots are not allowed. The default port label looks like the following: <text class="joint-port-label" fill="#000000"/>.
z number | string

An alternative to HTML z-index. z sets the position of a port in the list of DOM elements within an ElementView.

Shapes most likely consist of 1 or more DOM elements, <rect/>, <rect/><text/><circle/> etc. Ports are placed into the main group element elementView.el, so it will act as the port container. Ports with z: 'auto' are located right after the last element in the main group. Ports with z defined as a number are placed before a DOM element at the position (index within the children of the container, where only the original markup elements, and ports with z: 'auto' are taken into account) equal to z.

For instance, the first shape from the demo above with the following markup...

markup: [{
    tagName: 'rect',
    selector: 'bodyMain',
    className: 'bodyMain'
}, {
    tagName: 'rect',
    selector: 'bodyInner',
    className: 'bodyInner'
}, {
    tagName: 'text',
    selector: 'label',
    className: 'label'
}]

...will be rendered like this:

<g model-id="...">
    <g class="joint-port"></g>         <!-- z: 0 -->
    <rect class="bodyMain"></rect>
    <g class="joint-port"></g>         <!-- z: 1 -->
    <rect class="bodyInner"></rect>
    <text class="label"></text>
    <g class="joint-port"></g>         <!-- z: 3 -->
    <g class="joint-port"></g>         <!-- z: auto -->
</g>

Ports will be placed in the rotatable group if it's defined in the shape's markup. Ports with z: 'auto' are located right after the last element in the rotatable group. In the demo above, the second shape is defined with a rotatable group and the following markup:

markup: [{
    tagName: 'g',
    selector: 'rotatable',
    className: 'rotatable',
    children: [{
        tagName: 'g',
        selector: 'scalable',
        className: 'scalable',
        children: [{
            tagName: 'rect',
            selector: 'bodyMain',
            className: 'bodyMain'
        }]
    }, {
        tagName: 'rect',
        selector: 'bodyInner',
        className: 'bodyInner'
    }, {
        tagName: 'text',
        selector: 'label',
        className: 'label'
    }]
}]

It will be rendered like this:

<g model-id="...">
    <g class="rotatable">
        <g class="joint-port"></g>         <!-- z: 0 -->
        <g class="scalable"><rect class="bodyMain"></rect></g>
        <g class="joint-port"></g>         <!-- z: 1 -->
        <rect class="bodyInner"></rect>
        <text class="label"></text>
        <g class="joint-port"></g>         <!-- z: 3 -->
        <g class="joint-port"></g>         <!-- z: auto -->
    </g>
</g>

All properties described above are optional, and everything has its own default. E.g. element.addPorts([{}, {}]) will add 2 ports with default settings.

Port groups configuration

While single port definitions are useful, what if we want more control over our ports? This is where a port group can come into play. A group allows us to define multiple ports with similar properties, and influence the default port alignment. Any individual port can override a property in a port group definition except the type of layout(E.g. position: 'left'). The group definition defines the layout, and the individual port args are the only way a port can affect it.

// Port definition for input ports group 
const portsIn = {
    position: {
        name: 'left', // Layout name
        args: {}, // Arguments for port layout function, properties depend on type of layout
    },
    label: {
        position: {
            name: 'left',
            args: { y: 6 }
        },
        markup: [{
            tagName: 'text',
            selector: 'label',
        }]
    },
    attrs: {
        body: { magnet: 'passive', width: 15, height: 15, stroke: 'red', x: -8, y: -8 },
        label: { text: 'in1', fill: 'black' }
    },
    markup: [{
        tagName: 'rect',
        selector: 'body'
    }]
};

// Define port groups in element constructor
const rect = new joint.shapes.basic.Rect({
    // ...
    ports: {
        groups: {
            'group1': portsIn,
            // 'group2': ...,
            // 'group3': ...,
        },
        items: [
             // Initialize 'rect' with port in group 'group1'
            {
                group: 'group1',
                args: { y: 40 } // Overrides `args` from the group level definition for first port 
            }
        ]
    }
});

// Add another port using Port API
rect.addPort(
    { group: 'group1', attrs: { label: { text: 'in2' }}}
);

position string | object Port position configuration. It can be a string to set the port layout type directly with default settings, or an object where it's possible to set the layout type and options.
  • position.name
string It states the layout type. Match the layout method name defined in the joint.layout.Port namespace: name: 'left' is implemented as joint.layout.Port.left.
  • position.args
object Arguments for the port layout function. Available properties depend on the type of layout. More information can be found in layout.Port.
attrs object JointJS style attribute definition. The same notation as the attrs property on Element.
markup MarkupJSON | string

Custom port markup. Multiple roots are not allowed. Valid notation would be:

markup: [{
    tagName: 'g',
    children: [{
        tagName: 'rect',
        selector: 'bodyInner',
        className: 'outer',
        attributes: {
            'width': 15,
            'height': 15,
            'fill': 'red'
        }
    }, {
        tagName: 'rect',
        selector: 'bodyOuter',
        className: 'inner',
        attributes: {
            'width': 15,
            'height': 15,
            'fill': 'blue',
            'x': 10
        }
    }]
}]

The default port looks like the following: <circle class="joint-port-body" r="10" fill="#FFFFFF" stroke="#000000"/>.

label object Port label layout configuration. E.g. label position, label markup. More information about port label layouts can be found in the layout.PortLabel section.
  • label.position
string | object

Port label position configuration. It can be a string for setting the port layout type directly with default settings, or an object where it's possible to set the layout type and options.

{ position: 'left'}

// or ...
{
    position: {
        name: 'left',
        args: {
            dx: 10
        }
    }
}
  • label.position.name
string It states the layout type. It matches the layout method name defined in the joint.layout.PortLabel namespace: name: 'left' is implemented as joint.layout.PortLabel.left.
  • label.position.args
object Additional arguments for the layout method. Available properties depend on the layout type. More information can be found in the layout.PortLabel section.
  • label.markup
MarkupJSON | string Custom port label markup. Multiple roots are not allowed. The default port label looks like the following: <text class="joint-port-label" fill="#000000"/>.
Custom markup

Both port and port label can have custom markup...

var rect = new joint.shapes.basic.Rect({
    // ...
});

rect.addPort({
    markup: [{
        tagName: 'rect', selector: 'body', attributes: { 'width': 20, 'height': 20, 'fill': 'blue' }
    }]
});

rect.addPort({
    markup: [{
        tagName: 'rect', selector: 'body', attributes: { 'width': 16, 'height': 16, 'fill': 'red' }
    }],
    label: {
        markup: [{ tagName: 'text', selector: 'label', attributes: { 'fill': '#000000' }}]
    },
    attrs: { label: { text: 'port' }}
});

...or, it can be set as an default port markup/port label markup on an element model:

var rect = new joint.shapes.basic.Rect({
    portMarkup: [{
        tagName: 'rect',
        selector: 'body',
        attributes: {
            'width': 20,
            'height': 20,
            'fill': 'blue',
            'stroke': 'black',
            'stroke-width': 5 // Use native SVG kebab-case for attributes in markup
        }
    }],
    portLabelMarkup: [{
        tagName: 'text',
        selector: 'label',
        attributes: {
            'fill': 'yellow'
        }
    }]
    // ...
});
dia.Element.prototype.addPort
element.addPort(port, [opt])

Add a single port, where port could be defined as described in section Port interface

dia.Element.prototype.addPorts
element.addPorts(ports, [opt])

Add array of ports. Ports are validated for id duplicities, if there is a id collision, no new ports are added, where port could be defined as describe in section Port interface

dia.Element.prototype.addTo
element.addTo(graph)

Add the element to the graph (an instance of joint.dia.Graph). This is equivalent to calling graph.addCell(element).

dia.Element.prototype.angle
element.angle()

Return the rotation of the element in degrees (0° - 360°).

dia.Element.prototype.attr
element.attr(attrs [, opt])

Set presentation attributes (SVG and JointJS attributes) on view subelements. attrs can either be an object or string representing a path to a nested attribute. If it is an object, the keys of the attrs object are selectors (JSON Markup Selector or CSS Selector) matching the subelements. The values are objects containing SVG attributes and their values. attrs object will be mixed with attrs property of the element model. This is a convenient way of rewriting only some of the attributes of the subelements. For overwriting all attributes of all subelements, use element.set('attrs', attrs).

element.attr({
    // selectors as defined in the JSON markup
    body: { refWidth: '100%', refHeight: '100%' },
    label: { text: 'My Label' },
    // using CSS selectors is significantly slower
    rect: { fill: 'blue' },
    text: { fill: 'white', fontSize: 15 },
    '.myrect2': { fill: 'red' }
});
The method is not suitable for storing custom data on the model. For that, use prop() or set() methods.
element.set('confirmed', true);
element.prop('data/count', 10);
element.attr(path, value [, opt])

An alternative call using a string/array path and a value:

element.attr('body/fill', 'red');
element.attr(['label', 'fontSize'], 12);
// Note: an equivalent expression is also
element.prop('attrs/label/fontSize', 12);
element.attr([path])

Get attribute value defined by a path. If no path provided the whole attrs object is returned.

element.attr('body/fill') === 'red';
element.attr(['label', 'fontSize']) === 12;
dia.Element.prototype.clone
element.clone(options)

Returns a new instance of the element with identical attributes. If options.deep === true, then all the embedded cells (elements, links) of the element are cloned as well. In this case, the return value is an array of instances rather then a single instance.

dia.Element.prototype.embed
element.embed(cell, [opt])
element.embed(cells, [opt])

Embed a cell (element or link) or an array of cells into the element. The element then becomes a parent of the embedded cell. When a parent is moved (translated), all cells embedded into that parent will move as well. If links are embedded, their vertices move with the parent. This way both options are available: if a link is not embedded but its source/target elements are and their parent moves, the embedded elements move with the parent but the link vertices stay at the same position. If the link is embedded with its source/target elements, its vertices move as the parent moves.

dia.Element.prototype.findView
element.findView(paper)

Find view (joint.dia.ElementView) for the element model in the paper. This is a shortcut to the equivalent call paper.findViewByModel(element)

dia.Element.prototype.fitEmbeds
element.fitEmbeds([opt])

Resize the element so that it fits all the embedded elements inside it. If opt.deep is true, the resizing will be done recursively for any embedded elements that contain embedded elements themselves. Set opt.padding if you want certain padding on all the parent elements.

dia.Element.prototype.getAbsolutePointFromRelative
element.getAbsolutePointFromRelative(x, y)
element.getAbsolutePointFromRelative(relativePoint)

Accept a point in the coordinate system of the element and return the point in the graph coordinate system, represented as a g.Point.

The element coordinate system has its origin [0,0] at the element.position() rotated by the element.angle(). Each axis x and y are rotated by the same angle.

dia.Element.prototype.getAncestors
element.getAncestors()

Return an array of all the ancestors of this element starting from the immediate parent all the way up to the most distant ancestor.

dia.Element.prototype.getBBox
element.getBBox([opt])

Return the bounding box of the element model, represented as a g.Rect.

Keep in mind that this function reports the dimensions of the element's model, not the dimensions of the element's view. (For example, the model bounding box does not include any associated ports). See the documentation of the elementView.getBBox function for details about the differences.

if (element1.getBBox().intersect(element2.getBBox())) {
    // intersection of the two elements
}
opt description
deep Return the union of the element's bounding box and all the elements embedded into it.
rotate Return the bounding box after the element's rotation.
dia.Element.prototype.getEmbeddedCells
element.getEmbeddedCells([opt])

Return an array of all the embedded cells of an element. If all you need is id's of all the embedded cells, use element.get('embeds'). If opt.deep is true, all the deeply embedded cells will be returned. The order in which the cells are returned depends on the search algorithm used. By default, Depth-first search (DFS) algorithm is used. If opt.breadthFirst is true, the Breadth-first search algorithm will be used instead.

dia.Element.prototype.getGroupPorts
element.getGroupPorts(groupName)
Returns an array of all ports on the element with the given groupName. If there is no such a port an empty array is returned.
dia.Element.prototype.getPort
element.getPort(id)

Returns the port specified by an id. If such a port does not exist the method returns undefined.

dia.Element.prototype.getPortIndex
element.getPortIndex(portId)
Returns the port index in the array of port items.
dia.Element.prototype.getPorts
element.getPorts()

Returns an array of all ports on the element. If there is no port an empty array is returned.

dia.Element.prototype.getPortsPositions
element.getPortsPositions(groupName)

Returns the positions and the angle of all ports in the group, relatively to the element position.

dia.Element.prototype.getRelativePointFromAbsolute
element.getRelativePointFromAbsolute(x, y)
element.getRelativePointFromAbsolute(absolutePoint)

Accept a point in the graph coordinate system and return the point in the coordinate system of the element, represented as a g.Point.

The element coordinate system has its origin [0,0] at the element.position() rotated by the element.angle(). Each axis x and y are rotated by the same angle.

dia.Element.prototype.getTransitions
element.getTransitions()

Return an array of all active transitions (their paths).

dia.Element.prototype.hasPort
element.hasPort(id)

Check if an element contains a port with id. Returns boolean.

dia.Element.prototype.hasPorts
element.hasPorts()

Check if an element has any ports defined. Returns boolean.

dia.Element.prototype.insertPort
element.insertPort(before, port, [opt])

Insert a new port before another port, where port could be defined as described in section Port interface and before is either an index, port id or port itself.

dia.Element.prototype.isElement
element.isElement()

Always returns true. The reason the method is here is that both joint.dia.Element and joint.dia.Link inherit from joint.dia.Cell. This method is useful if you don't know what the cell is. Calling cell.isElement() is equivalent to cell instanceof joint.dia.Element. Example:

var cell = graph.getCell(myId)
if (cell.isElement()) {
    // Do something if the cell is an element.
}
dia.Element.prototype.isEmbeddedIn
element.isEmbeddedIn(element [, opt])

Return true if the element is embedded in another element element. If opt.deep is false, only direct parentage will be checked. opt.deep is true by default.

dia.Element.prototype.portProp
element.portProp(portId, path, [value])

Set properties, possibly nested, on the element port. This is an equivalent of the attr() method but this time for custom data properties.

element.portProp('port-id', 'attrs/circle/fill', 'red');
element.portProp('port-id', 'attrs/circle/fill');  // 'red'

element.portProp('port-id', 'attrs/circle', { r: 10, stroke: 'green' });
element.portProp('port-id', 'attrs/circle'); // { r: 10, stroke: 'green', fill: 'red' }
dia.Element.prototype.position
element.position([opt])

If position() is called without arguments, it returns the current position.

Option Default Description
parentRelative false The method returns the current position of the element relative to its parent.
element.position(x, y, [opt])

Set the element position to x and y coordinates. This is almost equivalent to element.set('position', { x, y }, opt). However, this method provides some additional functionality.

Option Default Description
parentRelative false If set to true the x and y coordinates will be treated relatively to the parent element of this element. If the element has no parent or the parent is a link, the option is ignored.
deep false If set to true it will position the element and its descendants while keeping the original distances of the descendants to/from the element origin. The relative distances of the descendants are maintained.
restrictedArea null If set to a rectangle, the translation of the element will be restricted to that rectangle only. The restrictedArea is an object of the form { x: Number, y: Number, width: Number, height: Number }. This is useful, e.g. if you want to restrict the translation of an embedded element within its parent. The only thing you have to do in this case is to pass the bounding box of the parent element to the restrictedArea option:

myElement.position(x, y, { restrictedArea: myElement.getParentCell().getBBox() })

The code above makes sure that the element myElement never crosses the bounding box of its parent element. Note that this also works if the element myElement has other embedded elements. In other words, the bounding box of the myElement that is used to calculate the restriction is the total bounding box, including all its children (in case they are sticking out).

el1.position(100, 100);
el1.embed(el2);
el2.position(10, 10, { parentRelative: true });
el2.position() // --> 110@110
el1.position(200,200, { deep: true });
el2.position() // --> 210@210
const restrictedArea = paper.getArea();
el.position(x, y, { restrictedArea }); // --> makes sure x and y is within the area provided
dia.Element.prototype.prop
element.prop(properties)

Set properties, possibly nested, on the element model. This is an equivalent of the attr() method but this time for custom data properties.

element.prop('name/first', 'John')
element.prop('name/first')  // 'John'
element.prop({ name: { first: 'John' } })
// Nested arrays are supported too:
element.prop('mylist/0/data/0/value', 50)
element.prop({ mylist: [ { data: [ { value: 50 } ] } ] })

To overwrite attributes, enable rewrite mode by adding { rewrite: true } as the 3rd argument. This differs from the default behaviour which is to merge our properties.

element.prop('custom/state/isCollapsed', true);
element.prop('custom/state', { isActive: false }, { rewrite: true });

// Output from element.toJSON();
// We can see our attributes have been overwritten
{
    "type": "standard.Rectangle",
    "position": { "x": 0, "y": 0 },
    "size": { "width": 1, "height": 1 },
    "angle": 0,
    "id": "b1c02090-e46a-4d90-a5dc-5096f1559b9f",
    "custom": {
        "state": {
            "isActive": false
        }
    },
    "attrs": {}
}

Advanced: Pass { isolate: true } if the property change does not affect the connected links. Typically, changing the element fill color has zero effect on attached links. By default, the element and all connected links are updated.

element.attr(['body', 'fill'], 'red', { isolate: true });
dia.Element.prototype.remove
element.remove(options)

Remove the element from the graph. All its embedded elements will get removed too and the element gets unembedded from its parent element. By default, all the associated links are removed too. To suppress this behaviour, set options.disconnectLinks === true. In this case, all the associated links get disconnected from this element rather then removed completely from the graph.

dia.Element.prototype.removeAttr
element.removeAttr(path, [options])

Remove a previously set attribute from the element. path can either be a string that specifies the path to the, possibly nested, attribute to be removed or an array of more paths. The associated element view makes sure the element gets re-rendered properly. If options is passed, it can contain data that is passed over to the event listeners for the change:attrs event triggered on the element itself and also on the graph the element is in.

dia.Element.prototype.removePort
element.removePort(port, [opt])

Remove a port from an element, where port is a port object, or portId.

dia.Element.prototype.removePorts
element.removePorts(ports [, opt])

Remove an array of ports from the element.

The ports can be specified as Port interfaces or portIds. The function skips over any ports in the array that do not exist on the element.

element.removePorts([opt])

If no array is provided, the function removes all ports from the element.

dia.Element.prototype.resize
element.resize(width, height [, opt])

Resize an element in place so that the "scalable" group has width width and height height. In place in this case means that the top-left corner of the element stays at the same position after resizing. In other words, the element is streched to the bottom/right (by default). To change the direction of resizing, set opt.direction to one of 'left', 'right', 'top', 'bottom', 'top-right', 'top-left', 'bottom-left' or 'bottom-right' (the default).

There is a difference between a classical scale and resize operations. resize doesn't actually scale the whole SVG <g> element grouping all its subelements. It only scales subelements of the <g class"scalable"/> group. This is very useful and brings a lot of flexibility in defining which subelements should be scaled and which not. Imagine a simple rectangle element with text inside. Usually, when we resize the whole element, we expect the rectangle to get scaled while the text should stay the same size, only its position should be adjusted so that the text stays in the center of the rectangle. This can be easilly achieved by adding the <rect/> element to the <g class"scalable"/> group in the markup and positioning the text subelement relatively to the <rect /> element: <text ref-x=".5" ref-y=".5" ref="rect" />. Note that neither of ref-x, ref-y and ref attributes is an SVG standard attribute. These are special attributes introduced by JointJS. More on these in the section on Special attributes.

dia.Element.prototype.rotate
element.rotate(deg, [absolute, origin, opt])

Rotate an element by deg degrees around its center. If the optional absolute parameter is true, the deg will be considered an absolute angle, not an addition to the previous angle. If origin is passed in the form of an object with x and y properties, then this point will be used as the origin for the rotation transformation.

dia.Element.prototype.scale
element.scale(sx, sy, origin[, opt])

Scales the element's position and size relative to the given origin.

dia.Element.prototype.stopTransitions
element.stopTransitions([path])

Stops all running transitions. If parameter path is provided, it will stop only transitions specified by this path.

dia.Element.prototype.toBack
element.toBack([opt])

Move the element so it is behind all other cells (elements/links). If opt.deep is true, all the embedded cells of this element will get higher z index than that of this element in a Breadth-first search (BFS) fashion. This is especially useful in hierarchical diagrams where if you want to send an element to the back, you don't want its children (embedded cells) to be hidden behind that element.

Set opt.breadthFirst to false to index the elements using Depth-first search (DFS).

dia.Element.prototype.toFront
element.toFront([opt])

Move the element so it is on top of all other cells (element/links). If opt.deep is true, all the embedded cells of this element will get higher z index than that of this element in a Breadth-first search (BFS) fashion. This is especially useful in hierarchical diagrams where if you want to send an element to the front, you don't want its children (embedded cells) to be hidden behind that element.

Set opt.breadthFirst to false to index the elements using Depth-first search (DFS).

All elements have a z property defining their z-level in the graph. This z property can even be set directly by element.set('z', 123). This change will be automatically handled by the joint.dia.Paper object associated with the joint.dia.Graph object this element is part of and all the SVG elements will get resorted so that their position in the DOM reflects the z level.

container.embed(el1);
container.embed(el2);
container.toFront({ deep: true });
dia.Element.prototype.toJSON
element.toJSON()

Return a copy of the element's attributes for JSON serialization. This can be used for persistance or serialization. Note that this method doesn't return a JSON string but rather an object that can be then serialized to JSON with JSON.stringify().

dia.Element.prototype.transition
element.transition(path, value [, opt])

Allows to change the element's property gradually over a period of time. This method lets you specify what property to change (path), when the transition will start (options.delay), how long the transition will last (options.duration), how the transition will run (options.timingFunction), and how to interpolate the property value (options.valueFunction).

element.transition('position/x', 250, {
    delay: 100,
    duration: 500,
    timingFunction: function(t) { return t*t; },
    valueFunction: function(a, b) { return function(t) { return a + (b - a) * t }}
});
// will start changing the element's x-coordinate in 100ms, for period of 500ms.

JointJS comes pre-built with some common timing and interpolating functions. The timing functions are defined in the joint.util.timing namespace and the interpolating functions in the joint.util.interpolate namespace. The predefined timing functions are:

  • linear
  • quad
  • cubic
  • inout
  • exponential
  • bounce

and the predefined interpolating functions are:

  • number
  • object
  • hexColor
  • unit

element.transition('attrs/text/font-size', '1em', {
    valueFunction: joint.util.interpolate.unit,
    timingFunction: joint.util.timing.bounce
});
// will start changing the current font size value to 1em in the bounce fashion.
dia.Element.prototype.translate
element.translate(tx, [ty], [opt])

Translate an element by tx pixels in x axis and ty pixels in y axis. ty is optional in which case the translation in y axis will be considered zero. The optional options object opt can be used to pass additional parameters to the event handlers listening on 'change:position' events. opt.transition can be used to initiate an animated transition rather than a sudden move of the element. See joint.dia.Element:transition for more info on transitions. If opt.restrictedArea is set, the translation of the element will be restricted to that area only. The restrictedArea is an object of the form { x: Number, y: Number, width: Number, height: Number }. This is useful, e.g. if you want to restrict the translation of an embedded element within its parent. The only thing you have to do in this case is to pass the bounding box of the parent element to the restrictedArea option:

myElement.translate(50, 50, { restrictedArea: graph.getCell(myElement.get('parent')).getBBox() })

The code above makes sure that the element myElement never crosses the bounding box of its parent element. note that this also works if the element myElement has other embedded elements. In other words, the bounding box of the myElement that is used to calculate the restriction is the total bounding box, including all its children (in case they are sticking out).

dia.Element.prototype.unembed
element.unembed(cell, [opt])
element.unembed(cells, [opt])

Free up an embedded cell or an array of cells from its parent element.

dia.ElementView

The view for the joint.dia.Element model. It inherits from joint.dia.CellView and is responsible for:

  • Rendering an element inside of a paper
  • Handling the element's pointer events
  • Provides various methods for working with the element (visually)

To find the view associated with a specific element (model), use the findViewByModel method of the paper.

var elementView = paper.findViewByModel(element);
dia.ElementView.prototype.addTools
elementView.addTools(toolsView)

Add the provided toolsView (of the joint.dia.ToolsView type) to the element view.

Adding a tools view to an element view is the last (third) step in the process of setting up element tools on an element view:

// 1) creating element tools
var boundaryTool = new joint.elementTools.Boundary();
var removeButton = new joint.elementTools.Remove();

// 2) creating a tools view
var toolsView = new joint.dia.ToolsView({
    name: 'basic-tools',
    tools: [boundaryTool, removeButton]
});

// 3) attaching to an element view
var elementView = element.findView(paper);
elementView.addTools(toolsView);

Every element view we want to attach to requires its own tools view object (ToolsView objects are automatically reassigned to the last element view they are added to). Similarly, every tools view we create requires its own set of tools (ToolView objects are automatically reassigned to the last toolsView.tools array they were made part of).

The element tools are added in the visible state. Use the elementView.hideTools function if this behavior is not desirable (e.g. if you want the element tools to appear in response to user interaction). Example:

elementView.addTools(toolsView);
elementView.hideTools();

paper.on('element:mouseenter', function(elementView) {
    elementView.showTools();
});

paper.on('element:mouseleave', function(elementView) {
    elementView.hideTools();
});
dia.ElementView.prototype.getBBox
elementView.getBBox([opt])

Return a bounding box of the element view.

If opt.useModelGeometry option is set to true, the resulting bounding box is calculated based on the dimensions of the element model. (This means that SVG sub elements sticking out of the element are excluded.) This behavior is similar to the element.getBBox function – but the elementView function transforms the bounding box to match joint.dia.Paper translation and scaling.

dia.ElementView.prototype.getNodeBBox
elementView.getNodeBBox(magnet)

Return the bounding box of the SVGElement provided as magnet (element/subelement/port of this element view).

Use the paper.localToPaperRect function to transform the returned bounding box to match the paper's translation and scaling.

dia.ElementView.prototype.getNodeUnrotatedBBox
elementView.getNodeUnrotatedBBox(magnet)

Return the unrotated bounding box of the SVGElement provided as magnet (element/subelement/port of this element view).

Use the paper.localToPaperRect function to transform the returned bounding box to match the paper's translation and scaling.

dia.ElementView.prototype.hideTools
elementView.hideTools()

Hide all tools attached to this element view.

dia.ElementView.prototype.removeTools
elementView.removeTools()

Remove the tools view attached to this element view.

dia.ElementView.prototype.showTools
elementView.showTools()

Show all tools attached to this element view.

dia.Graph.constructor

joint.dia.Graph is the model holding all the cells (elements and links) of the diagram. It's a Backbone model. The collection of all the cells is stored in the property cells.

The graph is a powerful data model behind all JointJS diagrams. It not only provides an efficient storage for directed graphs but also offers useful algorithms for traversing the graphs.

Additionally, the graph accepts an option object in its constructor function that can contain the cellNamespace option. This option can be used to change the default behavior of JointJS which by default reads cell model definitions from the joint.shapes namespace. For example, if a cell is of type 'myshapes.MyElement', then the graph looks up joint.shapes.myshapes.MyElement model when deserializing a graph from the JSON format. If the graph is instantiated as e.g. var graph = new joint.dia.Graph({}, { cellNamespace: myShapesNamespace }), then the graph will read the model definition from the myShapesNamespace.myshapes.MyElement object instead. This is useful in situations where you don't want to - for any reason - use the joint.shapes namespace for defining your own custom shapes. This option is often used in combination with the cellNamespaceView option on the joint.dia.Paper object.

dia.Graph.events

The following list contains events that you can react on:

  • change - generic event triggered for any change in the graph
  • add - triggered when a new cell is added to the graph
  • remove - triggered when a cell is removed from the graph
  • Moreover, all the events that are triggered on elements or links are propagated to the graph as well.
graph.on('add', function(cell) {
    alert('New cell with id ' + cell.id + ' added to the graph.')
})

dia.Graph.JSON

The JointJS graph JSON representation has the following format:

{
    cells: [// Array of cells (ie. links and elements).
        {
            id: '3d90f661-fe5f-45dc-a938-bca137691eeb',// Some randomly generated UUID.
            type: 'basic.Rect',
            attrs: {
                'stroke': '#000'
            },
            position: {
                x: 0,
                y: 50
            },
            angle: 90,
            size: {
                width: 100,
                height: 50
            },
            z: 2,
            embeds: [
                '0c6bf4f1-d5db-4058-9e85-f2d6c74a7a30',
                'cdbfe073-b160-4e8f-a9a0-22853f29cc06'
            ],
            parent: '31f348fe-f5c6-4438-964e-9fc9273c02cb'
            // ... and some other, maybe custom, data properties
        }
    ]
}
dia.Graph.prototype.addCell
graph.addCell(cell)

Add a new cell to the graph. If cell is an array, all the cells in the array will be added to the graph.

var rect = new joint.shapes.basic.Rect({
    position: { x: 100, y: 100 },
    size: { width: 70, height: 30 },
    attrs: { text: { text: 'my rectangle' } }
})
var rect2 = rect.clone()
var link = new joint.dia.Link({ source: { id: rect.id }, target: { id: rect2.id }  });
var graph = new joint.dia.Graph
graph.addCell(rect).addCell(rect2).addCell(link)
dia.Graph.prototype.addCells
graph.addCells(cells[, opt])
graph.addCells(cell, cell, ..[, opt])

Add new cells to the graph. This is just a convenience method that wraps the addCell method.

dia.Graph.prototype.bfs
graph.bfs(element, iteratee [, opt])

Traverse the graph using the Breadth-first search algorithm starting at element (note the element itself will be visited too). iteratee is a function of the form function(element, distance) {} that will be called with the currently visited element and distance of that element from the root element of the search (the element passed to bfs()). If iteratee explicitely returns false, the search stops.

The following image shows the order in which elements are traversed in the graph:

graph BFS algorithm

Note that the bfs() algorithm is not only capable of traversing tree graphs but it can traverse any directed graph too.

It is smart enough not to traverse an element that was already visited.

If opt.inbound is true, reverse the search direction (it's like reversing all the link directions, i.e. swaping their source and target).

If opt.outbound is true, search follows the link directions. Calling bfs() with opt.outbound set to true is the most common case (graph is traversed following the direction of links).

If none of opt.inbound and opt.outbound are used or both options are set to true, the graph is traversed in both directions (very rare use case).

If opt.deep is true, the traversal takes into account embedded elements too. This option has the usual meaning as in other methods were deep option is used. For example, in a hierarchy A (top level element), A1 (embedded in A), B (top level element), where A is not directly connected to B but its embedded element is (there is a link from A1 ----> B), bfs(A)would not visit B but bfs(A, function() {}, { deep: true }) would.

dia.Graph.prototype.clear
graph.clear([options)

Remove all the cells from the graph. options object can optionally contain additional data that is passed over to the event listeners of the graph cells remove event.

dia.Graph.prototype.cloneCells
graph.cloneCells(cells)

Clone all the cells (elements and/or links) from the cells array and return an object that maps the original cell ID to the clone (i.e. an object of the form { [original cell ID]: [clone] }). The reason why this object is returned instead of an array of clones is that it is very useful to know which object the clone was created for.
The number of clones returned equals cells.length. This function does not simply clone all the cells but it also reconstructs all the source/target and parent/embed references within cells. This is very useful. For example, for a graph A --- L ---> B, cloneCells([A, L, B]) returns { A.id: A2, L.id: L2, B.id: B2 } resulting in a graph A2 --- L2 ---> B2, i.e. the source and target of the link L2 is changed to point to A2 and B2 (in contrast to just looping over cells and calling cell.clone() on each item).

dia.Graph.prototype.cloneSubgraph
graph.cloneSubgraph(cells [, opt])

Clone the whole subgraph, including all the connected links whose source/target is in the subgraph. This is equivalent to calling graph.cloneCells(graph.getSubgraph(cells)).
If opt.deep is true, take into account embedded cells of the subgraph cells.
Return an object of the form { [original cell ID]: [clone] }.

dia.Graph.prototype.dfs
graph.dfs(element, iteratee [, opt])

Traverse the graph using the Depth-first search algorithm starting at element (note the element itself will be visited too). iterate is a function of the form function(element, distance) {} that will be called with the currently visited element and distance of that element from the root element of the search (the element passed to dfs()). If iteratee explicitely returns false, the search stops.

The following image shows the order in which elements are traversed in the graph:

graph DFS algorithm

Note that the dfs() algorithm is not only capable of traversing tree graphs but it can traverse any directed graph too. It is smart enough not to traverse an element that was already visited.

If opt.inbound is true, reverse the search direction (it's like reversing all the link directions, i.e. swaping their source and target).

If opt.outbound is true, search follows the link directions. Calling dfs() with opt.outbound set to true is the most common case (graph is traversed following the direction of links).

If none of opt.inbound and opt.outbound are used or both options are set to true, the graph is traversed in both directions (very rare use case).

If opt.deep is true, the traversal takes into account embedded elements too. This option has the usual meaning as in other methods were deep option is used. For example, in a hierarchy A (top level element), A1 (embedded in A), B (top level element), where A is not directly connected to B but its embedded element is (there is a link from A1 ----> B), dfs(A) would not visit B but dfs(A, function() {}, { deep: true }) would.

dia.Graph.prototype.findModelsFromPoint
graph.findModelsFromPoint(point)

Find elements (instance of joint.dia.Element) under a certain point in the graph. point is an object with x and y properties. Returns an array of elements whose bounding box contains point. Note that there can be more then one element as elements might overlap.

dia.Graph.prototype.findModelsInArea
graph.findModelsInArea(rect)

Find elements (instance of joint.dia.Element) in a certain area in the graph. rect is an object with x, y, width and height properties. Returns an array of elements whose bounding box top/left coordinate falls into the rect rectangle.

dia.Graph.prototype.findModelsUnderElement
graph.findModelsUnderElement(element [, opt])

Find all the elements (instances of joint.dia.Element) that are located below element. opt.searchBy parameter optionally determines what it means for an element to be below another element. Possible values are 'bbox' (default), 'center', 'origin', 'corner', 'topRight', and 'bottomLeft'.

dia.Graph.prototype.fromJSON
graph.fromJSON(jsonObject, [options])

Load a graph from a JSON object (not string). Used in conjunction with the graph.toJSON() function.

The options object may contain additional data that is passed over to graph change event listeners.

Note that this method does not expect a JSON string but rather an object in the JSON format. Use JSON.parse(jsonString) if you need to convert a JSON string into the object form:

graph.fromJSON(JSON.parse(jsonString));

Example of storing stringified JSON objects:

var jsonString = JSON.stringify(graph.toJSON());
// ... send jsonString to the server
// store jsonString to localStorage or do whatever you want
// later on ...
graph.fromJSON(JSON.parse(jsonString));

Example of storing JSON objects directly:

var jsonObject = graph.toJSON();
// ... send jsonObject to the server
// store jsonObject (e.g. in a non-relational database)
// later on ...
graph.fromJSON(jsonObject)
dia.Graph.prototype.getBBox
graph.getBBox()

Returns the bounding box (g.Rect) that surrounds all cells in the graph. It returns null if the graph is empty.

var bbox = graph.getBBox().inflate(10);
dia.Graph.prototype.getCell
graph.getCell(id)

Get a cell from the graph by its id.

dia.Graph.prototype.getCells
graph.getCells()

Return an array of all elements and links in the graph. The cells are sorted by their z index (the smallest z being first).

dia.Graph.prototype.getCellsBBox
graph.getCellsBBox(cells[, opt])

Returns the bounding box (g.Rect) that surrounds all the given cells.

// Get the bounding box of all `el1` successors and their embeds
var bbox = graph.getCellsBBox(graph.getSuccessors(el1), { deep: true });
dia.Graph.prototype.getCommonAncestor
graph.getCommonAncestor(...cells)

Return the common ancestor of all the cells passed as arguments. For example, if an element B is embedded in an element A and an element C is also embedded in the element A, graph.getCommonAncestor(B, C) returns the element A. This also works on an arbitrary deep hierarchy.

dia.Graph.prototype.getElements
graph.getElements()

Return an array of all elements in the graph. The elements are sorted by their z index (the smallest z being first).

dia.Graph.prototype.getFirstCell
graph.getFirstCell()

Get the first cell (element or link) in the graph. The first cell is defined as the cell with the lowest z property (the cell most in the back, see the Presentation section of joint.dia.Element).

dia.Graph.prototype.getLastCell
graph.getLastCell()

Get the last cell (element or link) in the graph. The last cell is defined as the cell with the highest z property (the cell most in the front, see the Presentation section of joint.dia.Element).

dia.Graph.prototype.getNeighbors
graph.getNeighbors(element [, opt])

Get all the neighbors of element in the graph. Neighbors are all the elements connected to element via either an inbound or an outbound link.

Accepts several options, which may be provided inside an opt object:

  • deep - also return all the neighbors of all the elements embedded inside element.
  • inbound - return only inbound neighbors (neighbors connected with a link whose target is the element).
  • outbound - return only outbound neighbors (neighbors connected with a link whose source is the element).
  • indirect - in addition to standard rules (including deep/outbound/inbound modifications), also return the elements that can only be considered neighbors of element if we go against the flow of directed links at link-link connections.
dia.Graph.prototype.getPredecessors
graph.getPredecessors(element [, opt])

Return an array of all the predecessors of element. By default, Depth-first search algorithm is used (important for the order of returned elements).
If opt.breadthFirst is set to true, use Breadth-first search algorithm instead.
If opt.deep is set to true, take into account embedded elements too (see dfs() for details).

dia.Graph.prototype.getSinks
graph.getSinks()

Return an array of all the leafs of the graph. Time complexity: O(|V|).

dia.Graph.prototype.getSources
graph.getSources()

Return an array of all the roots of the graph. Time complexity: O(|V|).

dia.Graph.prototype.getSubgraph
graph.getSubgraph(cells [, opt])

Return an array of cells that result from finding elements/links that are connected to any of the cells in the cells array. This function loops over cells and if the current cell is a link, it collects its source/target elements; if it is an element, it collects its incoming and outgoing links if both the link ends (source/target) are in the cells array. For example, for a single element, the result is that very same element. For two elements connected with a link: A --- L ---> B, the result of getSubgraph([A, B]) is [A, L, B] and the result of getSubgraph([L]) is also [A, L, B].
If opt.deep is true take into account all the embedded cells too when finding neighboring links/elements.

dia.Graph.prototype.getSuccessors
graph.getSuccessors(element [, opt])

Return an array of all the successors of element. By default, Depth-first search algorithm is used (important for the order of returned elements).
If opt.breadthFirst is set to true, use Breadth-first search algorithm instead.
If opt.deep is set to true, take into account embedded elements too (see dfs() for details).

dia.Graph.prototype.isNeighbor
graph.isNeighbor(elementA, elementB [, opt])

Return true if elementB is a neighbor of elementA. A neighbor of an element is another element connected to it via an inbound and/or outbound link.

Accepts several options, which may be provided inside an opt object:

  • deep - return true also if elementB is a neighbor of an element embedded in elementA.
  • outbound - return true only if elementB is a succeeding neighbor of elementA. For example, if elementB is connected to a directed link behind the connection of elementA.
  • inbound - return true only if elementB is a preceding neighbor elementA. For example, if elementB is connected to a directed link ahead of the connection of elementA.
  • indirect - in addition to standard rules (including deep/outbound/inbound modifications), also return true if elementB can only be considered a neighbor of elementA if we go against the flow of directed links at link-link connections.
dia.Graph.prototype.isPredecessor
graph.isPredecessor(elementA, elementB)

Return true if elementB is a predecessor of elementA.

dia.Graph.prototype.isSink
graph.isSink(element)

Return true if element is a leaf, i.e. there is no link coming out of the element. Time complexity: O(1).

dia.Graph.prototype.isSource
graph.isSource(element)

Return true if element is a root, i.e. there is no link that targets the element. Time complexity: O(1).

dia.Graph.prototype.isSuccessor
graph.isSuccessor(elementA, elementB)

Return true if elementB is a successor of elementA.

dia.Graph.prototype.maxZIndex
graph.maxZIndex()

Get the highest Z value in the graph (the value of the cell on front).

dia.Graph.prototype.minZIndex
graph.minZIndex()

Get the lowest Z value in the graph (the value of the cell on the back).

dia.Graph.prototype.removeCells
graph.removeCells(cells[, opt])
graph.removeCells(cell, cell, ..[, opt])

Removes the given cells from the graph.

dia.Graph.prototype.resetCells
graph.resetCells(cells[, opt])
graph.resetCells(cell, cell, ..[, opt])

Reset cells in the graph. Update all the cells in the graph in one bulk. This is a more efficient method of adding cells to the graph if you ou want to replace all the cells in one go. options object can optionally contain additional data that is passed over to the event listeners of the graph reset event.

dia.Graph.prototype.search
graph.search(element, iteratee [, opt])

Traverse the graph starting at element following links. This function is a wrapper around dfs() or bfs(). By default, it uses dfs(). If opt.breadthFirst is set to true, bfs() will be used instead.

dia.Graph.prototype.toJSON
graph.toJSON()

Return an object representation of the graph, which can be used for persistence or serialization. Use the graph.fromJSON() function to load a previously converted graph.

Note that this method does not return a JSON string but rather an object that can then be serialized to JSON with JSON.stringify(jsonObject):

var jsonString = JSON.stringify(graph.toJSON());
dia.Graph.prototype.translate
graph.translate(tx, ty [, opt])

Translate all cells in the graph by tx and ty pixels. It uses the dia.Element.translate() and dia.Link.translate() methods internally.

dia.HighlighterView

The base class for highlighters. The HighlighterView class does not implement any particular visual emphasis. It takes care of the management of the instances and introduce mechanisms for displaying, updating and cleaning arbitrary markings added to the SVGElements of cellViews.

The class is not meant to be initialized with the constructor.

dia.HighlighterView.add

HighlighterView.add(cellView, selector, id, options)

Create an instance of the highlighter and add it to the cellView.

It returns an instance of the HighlighterView.

If a highlighter with the same id exists on the CellView, it is removed and a new highlighter is added and returned. You can check if a highlighter already exists by calling HighlighterView.get().

  • cellView is an instance of dia.CellView.
  • selector points to an SVGElement of the cellView. It must be one of the following types:
    Type Description Example
    String A selector from the cell's markup.
    'root'
    'body'
    Object An object with property selector, which is a selector from the (cell/label/port) markup.
    There is additional property port (id of a port) available for dia.ElementView.
    And property label (index of a label) is available for dia.LinkView.

    If no selector property is provided, the root is used.

    { selector: 'body' } // cells
    { port: 'port1', selector: 'portBody' } // elements
    { label: 1, selector: 'labelBody' } // links
    SVGElement An SVGElement, the descendant of cellView.el or the root itself.
    cellView.el // the root
    cellView.el.querySelector('rect') // an SVGRectangle
  • id is a unique identifier of the highlighter. Only single highlighter with given id can exist on the CellView at one time.
  • options passed to the constructor of the highlighter view.

dia.HighlighterView.get

HighlighterView.get(cellView)

Return an array of highlighters on the cellView. Only highlighters, which are instances of this class are returned.

// Extend the Base Highlighter Class
const ChildHighlighterView = joint.dia.Highlighter.extend({});

const h1 = joint.dia.HighlighterView.add(cellView, 'root', 'id1');
const c1 = ChildHighlighterView.add(cellView, 'root', 'id2');

const parentHighlighters = joint.dia.Highlighters.get(cellView);
assert.ok(parentHighlighters.includes(h1));
assert.ok(parentHighlighters.includes(c1));
const childHighlighters = ChildHighlighterView.get(cellView);
assert.notOk(parentHighlighters.includes(h1));
assert.ok(parentHighlighters.includes(c1));
HighlighterView.get(cellView, id)

Return the highlighter with given id on the cellView. The highlighter returned must be an instance of this class. If such a highlighter does not exist, null is returned.

// Extend the Base Highlighter Class
const ChildHighlighterView = joint.dia.Highlighter.extend({});

const h1 = joint.dia.HighlighterView.add(cellView, 'root', 'h1');
const c1 = ChildHighlighterView.add(cellView, 'root', 'c1');

assert.equal(h1, joint.dia.Highlighters.get(cellView, 'h1));
assert.equal(c1, joint.dia.Highlighters.get(cellView, 'c1));
// There is no instance of ChildHighlighterView on the CellView
assert.equal(null, ChildHighlighterView.get(cellView, 'h1));
assert.equal(c1, ChildHighlighterView.get(cellView, 'c1));

dia.HighlighterView.remove

HighlighterView.remove(cellView)

Remove all the highlighters from the cellView. Only highlighters, which are instances of this class are removed.

HighlighterView.remove(cellView, id)

Remove the highlighter with given id from the cellView. The highlighter which is not an instance of this class is not removed.

dia.HighlighterView.prototype.highlight
highlighter.highlight(cellView, node)

Mark/Emphasize the node (SVGElement) of the cellView. e.g. render a rectangle above the node, add a class to the node.

dia.HighlighterView.prototype.MOUNTABLE
HighlighterView.prototype.MOUNTABLE

If the property is true, the highlighter view is attached to the DOM.

If the property is false, it is not attached upon highlight.

The default is true.

const ChildView = joint.dia.HighlighterView.extend({

    // HighlighterView `el` is not meant to be appended
    MOUNTABLE: false,

    highlight(cellView, node) {
        node.setAttribute('my-attribute', String(cellView.model.get('highlightAttribute')));
    },

    unhighlight(cellView, node) {
        node.removeAttribute('my-attribute');
    }

});
dia.HighlighterView.prototype.unhighlight
highlighter.unhighlight(cellView, node)

Remove marks made by highlight() from the node (SVGElement) of the cellView.

dia.HighlighterView.prototype.UPDATABLE
HighlighterView.prototype.UPDATABLE

If the property is true, the highlighter is updated (highlight() function is called) every time when the related cellView requires an update.

If the property is false, the highlight() method is called only once when the highlighter is added.

The default is true.

const ChildView = joint.dia.HighlighterView.extend({

    MOUNTABLE: false,
    UPDATABLE: false,

    highlight(_cellView, node) {
        node.classList.add('my-class');
    },

    unhighlight(_cellView, node) {
        node.classList.remove('my-class');
    }

});
dia.HighlighterView.prototype.options.layer

layer - the stacking context of the highlighter. Applicable for mountable highlighters only.

null Render the highlighter above the cell. It can be hidden by a cell with a higher z index.
"back" Render the highlighter behind all the cells.
"front" Render the highlighter in front of all the cells.
dia.HighlighterView.prototype.options.z

z - the stacking order (z-index) of the highlighter in the given stacking context. Applicable for mountable highlighters only.

dia.LinkView

The view for the joint.dia.Link model. It inherits from joint.dia.CellView and is responsible for:

  • Rendering a link inside a paper
  • Handling the link's pointer events
  • Providing various methods for working with the link (visually)

To find the view associated with a specific link model, use the paper.findViewByModel() method:

var linkView = paper.findViewByModel(link);

Custom LinkView

It is possible to use a custom default link view for all your links in a paper. This can be set up via the linkView option on the paper object. Several options in joint.dia.LinkView may be overridden in a custom LinkView:

  • shortLinkLength - if link is shorter than the length specified, the size of link tools is scaled down by half. Defaults to 105.
  • doubleLinkTools - render link tools on both ends of the link (only if the link is longer than longLinkLength). Defaults to false.
  • longLinkLength - if length is longer than the length specified and doubleLinkTools: true, render link tools on both ends of the link. Defaults to 155.
  • linkToolsOffset - the offset of link tools from the beginning of the link. Defaults to 40.
  • doubleLinkToolsOffset - the offset of duplicate link tools from the end of the link, if length is longer than longLinkLength and doubleLinkTools: true. Defaults to 65.

A custom LinkView type may also override default LinkView event handlers, or provide new ones. It may be necessary to modify the interactive paper option to prevent interference from builtin event handlers (most notably vertexAdd which listens for pointerdown events).

Example:

var CustomLinkView = joint.dia.LinkView.extend({
    // custom interactions:
    pointerdblclick: function(evt, x, y) {
        this.addVertex(x, y);
    },
    contextmenu: function(evt, x, y) {
        this.addLabel(x, y);
    },

    // custom options:
    options: joint.util.defaults({
        doubleLinkTools: true,
    }, joint.dia.LinkView.prototype.options)
});

var paper = new joint.dia.Paper({
    //...
    linkView: CustomLinkView,
    interactive: { vertexAdd: false } // disable default vertexAdd interaction
});
dia.LinkView.prototype.addLabel
linkView.addLabel(x, y [, angle, opt])

Add a new default label to the link at the (x,y) coordinates provided. See also the link.appendLabel() function.

linkView.addLabel(point [, angle, opt])

Add a new default label to the link at the coordinates specified by point. See also the link.appendLabel() function.

In either case, this method uses the linkView.getLabelPosition() function to determine the new label's position. By default, position.distance is recorded relative to connection length (as a number in the [0,1] range), and position.offset is set relative to the connection (as a number). This behavior may be changed by providing an opt object with some of the accepted boolean flags:

  • absoluteDistance: true records distance absolutely (as distance from beginning of link)
  • reverseDistance: true switches distance to be calculated from end of link, if absoluteDistance
  • absoluteOffset: true records offset absolutely (as x and y from connection)

The angle parameter, if provided, is saved as position.angle attribute inside the returned object. Two additional flags, which may be passed in the opt object, provide more control over label rotation:

  • keepGradient: true - adjust the rotation of the label to match the angle of incline of the path at position.distance
  • ensureLegible: true - if the label text ends up being upside-down, rotate the label by additional 180 degrees to ensure that the text stays legible, if keepGradient

The opt object passed to the label is recorded as label.position.args. The label uses these options during subsequent labelMove interactions.

This function is useful within custom linkView event listener definitions:

var CustomLinkView = joint.dia.LinkView.extend({
    contextmenu: function(evt, x, y) {
        this.addLabel(x, y, 45, {
            absoluteDistance: true,
            reverseDistance: true, // applied only when absoluteDistance is set
            absoluteOffset: true,
            keepGradient: true,
            ensureLegibility: true // applied only when keepGradient is set
        });
    }
});

var paper = new joint.dia.Paper({
    // ...
    linkView: CustomLinkView,
    interactive: { vertexAdd: false } // disable default vertexAdd interaction
});
dia.LinkView.prototype.addTools
linkView.addTools(toolsView)

Add the provided toolsView (of the joint.dia.ToolsView type) to the link view.

Adding a tools view to a link view is the last (third) step in the process of setting up link tools on a link view:

// 1) creating link tools
var verticesTool = new joint.linkTools.Vertices();
var segmentsTool = new joint.linkTools.Segments();
var boundaryTool = new joint.linkTools.Boundary();

// 2) creating a tools view
var toolsView = new joint.dia.ToolsView({
    name: 'basic-tools',
    tools: [verticesTool, segmentsTool, boundaryTool]
});

// 3) attaching to a link view
var linkView = link.findView(paper);
linkView.addTools(toolsView);

Every link view we want to attach to requires its own tools view object (ToolsView objects are automatically reassigned to the last link view they are added to). Similarly, every tools view we create requires its own set of tools (ToolView objects are automatically reassigned to the last toolsView.tools array they were made part of).

The link tools are added in the visible state. Use the linkView.hideTools function if this behavior is not desirable (e.g. if you want the link tools to appear in response to user interaction). Example:

linkView.addTools(toolsView);
linkView.hideTools();

paper.on('link:mouseenter', function(linkView) {
    linkView.showTools();
});

paper.on('link:mouseleave', function(linkView) {
    linkView.hideTools();
});

Note that the above example may not work as expected if toolsView includes the SourceArrowhead tool and/or the TargetArrowhead tool - the link tools view might not be hidden when the link is reconnected to a topic. See our link tools tutorial for more information.

dia.LinkView.prototype.addVertex
linkView.addVertex(x, y)

Add a new default vertex to the link at the coordinates provided, and let the linkView automatically determine the index of the new vertex in the vertices array. If you need to add the vertex at a custom index, use the link.addVertex() function instead.

This method uses the linkView.getVertexIndex() function to determine the index of the new vertex in the vertices array. The linkView checks the distance of vertices in the link.vertices array from the beginning of path and compares it to the distance of the added vertex. The new vertex is inserted before the first farther vertex in the vertices array.

This function is useful within custom linkView event listener definitions. The following example adds a new vertex on a double click event, instead of a pointerdown event (which is the default behavior):

var CustomLinkView = joint.dia.LinkView.extend({
    pointerdblclick: function(evt, x, y) {
        this.addVertex(x, y);
    }
});

var paper = new joint.dia.Paper({
    // ...
    linkView: CustomLinkView,
    interactive: { vertexAdd: false } // disable default vertexAdd interaction
});
dia.LinkView.prototype.findLabelNode
linkView.findLabelNode(index)

Return the root SVGElement of the label at given index. If label at index doesn't exist, null is returned.

linkView.findLabelNode(index, selector)

Return an SVGElement referenced by selector of the label at given index. If there is no label at index or no SVGElement was found by the selector, null is returned.

dia.LinkView.prototype.getBBox
linkView.getBBox([opt])

Return a bounding box of the link view.

If opt.useModelGeometry option is set to true, the resulting bounding box is calculated based on the dimensions of the link model. (This means that a simplified polyline is used and portions of curved links may be sticking out of the reported bounding box.) This behavior is similar to the link.getBBox function – but the linkView function transforms the bounding box to match joint.dia.Paper translation and scaling.

dia.LinkView.prototype.getClosestPoint
linkView.getClosestPoint(point)

Return the point on the connection that lies closest to point.

dia.LinkView.prototype.getClosestPointLength
linkView.getClosestPointLength(point)

Return the length of the connection up to the point that lies closest to point.

dia.LinkView.prototype.getClosestPointRatio
linkView.getClosestPointRatio(point)

Return the ratio (normalized length) of the connection up to the point that lies closest to point. The returned value lies in the interval [0,1] (inclusive).

dia.LinkView.prototype.getConnection
linkView.getConnection()

Return a geometric representation of the connection (instance of g.Path).

dia.LinkView.prototype.getConnectionLength
linkView.getConnectionLength()

Return a cached total length of the connection in pixels.

dia.LinkView.prototype.getConnectionSubdivisions
linkView.getConnectionSubdivisions()

Return a cached array of segment subdivision arrays of the connection. (See g.Path.prototype.getSegmentSubdivisons() documentation for more information.)

dia.LinkView.prototype.getLabelCoordinates
linkView.getLabelCoordinates(labelPosition)

Return the x and y coordinates based on the provided labelPosition object.

See link.label() documentation for more information about the position object.

An object in the format { x: number, y: number } is returned.

dia.LinkView.prototype.getLabelPosition
linkView.getLabelPosition(x, y [, angle, opt])

Return a label position object based on the x and y coordinates provided.

The function translates the provided coordinates and angle into an object with three fields:

  • distance - the distance (following the line) of the point on the line that is closest to point x,y.
  • offset - the distance between the closest point and the point x,y.
  • angle - the angle of the label relative to the connection line, as determined by the angle parameter, or 0 if angle was not specified.

By default, position.distance is calculated as relative to connection length (as a number in the [0,1] range that records the length ratio), and position.offset is calculated as relative to the connection (as a number recording the perpendicular distance). The user may change this behavior by providing an opt object with some of the following accepted boolean flags:

  • absoluteDistance: true - record distance absolutely (as absolute distance from beginning of link, a positive number)
  • reverseDistance: true - if absoluteDistance: true, record distance absolutely from end of link (as a negative number)
  • absoluteOffset: true - record offset absolutely (as x and y distance from closest point)

Please note that if the absoluteOffset flag is not set, label can only be placed/moved in the area that is reachable by lines perpendicular to the link (that is, the label can never be moved beyond link endpoints).

Two additional flags, which may be passed in the opt object, provide control over label rotation:

  • keepGradient: true - adjust the rotation of the label to match the angle of incline of the path at position.distance
  • ensureLegible: true - if the label text ends up being upside-down, rotate the label by additional 180 degrees to ensure that the text stays legible, if keepGradient

The opt object passed to the label is recorded as label.position.args. The label uses these options during subsequent labelMove interactions.

An object in the following format is returned:

{
    distance: number,
    offset: number | { x: number, y: number },
    angle: number,
    args?: {
        absoluteDistance?: boolean,
        reverseDistance?: boolean, // applied only when absoluteDistance is set
        absoluteOffset?: boolean,
        keepGradient?: boolean,
        ensureLegible?: boolean // applied only when keepGradient is set
    }
}

See link.label() documentation for more information about the position object.

This function can be used to add a custom label to the link.labels array, in situations when the linkView.addLabel() function is not sufficient. For example:

var CustomLinkView = joint.dia.LinkView.extend({
    contextmenu: function(evt, x, y) {
        var idx = -1; // add at end of `labels`
        var label = {
            markup: '<g class="label"><circle /><path /></g>',
            attrs: {
                circle: {
                    r: 15,
                    fill: 'lightgray',
                    stroke: 'black',
                    strokeWidth: 2
                },
                path: {
                    d: 'M 0 -15 0 -35 20 -35',
                    stroke: 'black',
                    strokeWidth: 2,
                    fill: 'none'
                }
            },
            position: this.getLabelPosition(x, y, 45, {
                absoluteOffset: true,
                keepGradient: true,
                ensureLegible: true
            })
        }
        this.model.addLabel(idx, label);
    }
});

var paper = new joint.dia.Paper({
    // ...
    linkView: CustomLinkView,
    interactive: { vertexAdd: false } // disable default vertexAdd interaction
});
dia.LinkView.prototype.getNodeBBox
elementView.getNodeBBox(magnet)

Return the bounding box of the SVGElement provided as magnet (model of this link view).

Use the paper.localToPaperRect function to transform the returned bounding box to match the paper's translation and scaling.

dia.LinkView.prototype.getNodeUnrotatedBBox
elementView.getNodeUnrotatedBBox(magnet)

Return the unrotated bounding box of the SVGElement provided as magnet (model of this link view).

Use the paper.localToPaperRect function to transform the returned bounding box to match the paper's translation and scaling.

dia.LinkView.prototype.getPointAtLength
linkView.getPointAtLength(length)

Return the point on the path that lies length away from the beginning of the connection.

dia.LinkView.prototype.getPointAtRatio
linkView.getPointAtRatio(ratio)

Return the point on the path that lies ratio (normalized length) away from the beginning of the connection.

dia.LinkView.prototype.getSerializedConnection
linkView.getSerializedConnection()

Return a cached path data of the connection (the value of the 'd' SVGPathElement attribute).

dia.LinkView.prototype.getTangentAtLength
linkView.getTangentAtLength(length)

Return a line tangent to the path at point that lies length away from the beginning of the connection.

dia.LinkView.prototype.getTangentAtRatio
linkView.getTangentAtRatio(ratio)

Return a line tangent to the path at point that lies ratio (normalized length) away from the beginning of the connection.

dia.LinkView.prototype.getVertexIndex
linkView.getVertexIndex(x, y)

Return the vertices array index at which to insert a new vertex with the provided x and y coordinates.

The linkView finds the point on the connection that lies closest to the point x,y. Then, the linkView iterates over the vertices in the link.vertices array until one is found that lies farther than the identified closest point. The index of the farther point is returned.

The returned index can be used as the first argument of the link.addVertex function.

dia.LinkView.prototype.hasTools
linkView.hasTools()

Return true if this link view has a tools view attached.

linkView.hasTools(name)

Return true if this link view has a tools view of the provided name attached.

dia.LinkView.prototype.hideTools
linkView.hideTools()

Hide all tools attached to this link view.

dia.LinkView.prototype.removeRedundantLinearVertices
linkView.removeRedundantLinearVertices([opt])

Remove any redundant vertices from the model's vertices array. Return the number of removed vertices.

A vertex is considered redundant if it lies on the straight line formed by the vertex that immediately precedes it and the vertex that immediately follows it. (Intuitively speaking, a vertex is considered redundant if its removal from the link does not change the shape of the link.)

dia.LinkView.prototype.removeTools
linkView.removeTools()

Remove the tools view attached to this link view.

dia.LinkView.prototype.requestConnectionUpdate
linkView.requestConnectionUpdate()

Schedule an update of the connection (anchors, connection points, route and connector) of this link view in the next animation frame (for paper async mode) or run immediately (for paper sync mode). Useful for links with an automatic router (such as manhattan) if the route has to be recalculated due to another element in the graph changing its position.

dia.LinkView.prototype.sendToken
linkView.sendToken(token [, opt, callback])

Send a token along the link. token is an SVG element (or Vectorizer element) that will be animated along the link path for opt.duration milliseconds (default is 1000ms). The callback function will be called once the token reaches the end of the link path.

opt.direction specifies whether the animation should be played forwards ('normal' - from the link source to target, the default) or backwards ('reverse').

Use opt.connection to specify the SVGPathElement for the token to follow. It expects a string selector, e.g. '.connection'.

// Send an SVG circle token along the link.
var vCircle = V('circle', { r: 7, fill: 'green' });
link.findView(paper).sendToken(vCircle, { duration: 500, direction: 'reverse' }, function() {
  console.log('animation end');
});

Note that in the code above, we use the Vectorizer mini-library to create the SVG circle element.

See the Petri Net simulator demo for a full working example.

dia.LinkView.prototype.showTools
linkView.showTools()

Show all tools attached to this link view.

dia.LinkView.prototype.sourceAnchor
linkView.sourceAnchor

A prototype variable. Contains a g.Point that records the position of the source anchor of the link, as determined by the anchor function specified on the link's source.

dia.LinkView.prototype.sourceBBox
linkView.sourceBBox

A prototype variable. Contains a g.Rect that records the position and dimensions of the bounding box of the source magnet (element/subelement/port), as determined by the link's source definition.

If the source is defined as a point, a g.Rect is returned that records the position of the point and has the dimensions (1,1).

dia.LinkView.prototype.sourcePoint
linkView.sourcePoint

A prototype variable. Contains a g.Point that records the position of the source connection point of the link, as determined by the connection point function specified on the link's source.

dia.LinkView.prototype.targetAnchor
linkView.targetAnchor

A prototype variable. Contains a g.Point that records the position of the target anchor of the link, as determined by the anchor function specified on the link's target.

dia.LinkView.prototype.targetBBox
linkView.targetBBox

A prototype variable. Contains a g.Rect that records the position and dimensions of the bounding box of the target magnet (element/subelement/port), as determined by the link's target definition.

If the target is defined as a point, a g.Rect is returned that records the position of the point and has the dimensions (1,1).

dia.LinkView.prototype.targetPoint
linkView.targetPoint

A prototype variable. Contains a g.Point that records the position of the target connection point of the link, as determined by the connection point function specified on the link's target.

dia.Paper.constructor

joint.dia.Paper is the view for the joint.dia.Graph model. It inherits from Backbone View. Accepts an options object in its constructor with numerous settings.

When a paper is associated with a graph, the paper makes sure that all the cells added to the graph are automatically rendered.

var graph = new joint.dia.Graph
var paper = new joint.dia.Paper({
    el: $('#paper'),
    width: 600,
    height: 400,
    gridSize: 10,
    model: graph
});

var rect = new joint.shapes.basic.Rect({
    position: { x: 50, y: 70 },
    size: { width: 100, height: 40 }
});

graph.addCell(rect);

Paper automatically handles this change and renders the rectangle to the SVG document that it internally holds.

dia.Paper.events

The following list contains events that you can react on in a paper:

pointerdblclick

Triggered when pointer is double-clicked on a target (a dblclick event is detected).

The callback function is passed cellView, evt, x and y as arguments.

cell:pointerdblclick Triggered when pointer is double-clicked on a cell.
link:pointerdblclick Triggered when pointer is double-clicked on a link.
element:pointerdblclick Triggered when pointer is double-clicked on an element.
blank:pointerdblclick

Triggered when pointer is double-clicked on the paper outside any cell.

The callback function is passed evt, x and y as arguments.

pointerclick

Triggered when pointer is clicked on a target without pointer movement (a click or touchend event is detected). Occurs alongside pointerdown and pointerup events.

The callback function is passed cellView, evt, x and y as arguments.

cell:pointerclick Triggered when pointer is clicked on a cell.
link:pointerclick Triggered when pointer is clicked on a link.
element:pointerclick Triggered when pointer is clicked on an element.
blank:pointerclick

Triggered when pointer is clicked on the paper outside any cell.

The callback function is passed evt, x and y as arguments.

contextmenu

Triggered when pointer is right-clicked on a target (a contextmenu event is detected).

The callback function is passed cellView, evt, x and y as arguments.

cell:contextmenu Triggered when pointer is right-clicked on a cell.
link:contextmenu Triggered when pointer is right-clicked on a link.
element:contextmenu Triggered when pointer is right-clicked on an element.
blank:contextmenu

Triggered when pointer is right-clicked on the paper outside any cell.

The callback function is passed evt, x and y as arguments.

pointerdown

Triggered when pointer is pressed down on a target (a mousedown or touchstart event is detected). The paper also starts delegating respective pointermove and pointerup events (including their touch counterparts; see below).

The callback function is passed cellView, evt, x and y as arguments.

cell:pointerdown Triggered when pointer is pressed down on a cell.
link:pointerdown Triggered when pointer is pressed down on a link.
element:pointerdown Triggered when pointer is pressed down on an element.
blank:pointerdown

Triggered when pointer is pressed down on the paper outside any cell.

The callback function is passed evt, x and y as arguments.

pointermove

Triggered when pointer is moved over a target while pressed down (a mousemove or touchmove event is detected).

The callback function is passed cellView, evt, x and y as arguments.

cell:pointermove Triggered when pointer is moved over a cell.
link:pointermove Triggered when pointer is moved over a link.
element:pointermove Triggered when pointer is moved over an element.
blank:pointermove

Triggered when pointer is moved over the paper outside any cell.

The callback function is passed evt, x and y as arguments.

pointerup

Triggered when pointer is released on a target after being pressed down (a mouseup or touchend event is detected).

The callback function is passed cellView, evt, x and y as arguments.

cell:pointerup Triggered when pointer is released on a cell.
link:pointerup Triggered when pointer is relased on a link.
element:pointerup Triggered when pointer is released on an element.
blank:pointerup

Triggered when pointer is released on the paper outside any cell.

The callback function is passed evt, x and y as arguments.

Calling evt.stopPropagation() prevents triggering a subsequent pointerclick event.

mouseover

Triggered when pointer begins to hover directly over a target.

The callback function is passed cellView and evt as arguments.

cell:mouseover Triggered when pointer begins to hover directly over a cell.
link:mouseover Triggered when pointer begins to hover directly over a link.
element:mouseover Triggered when pointer begins to hover directly over an element.
blank:mouseover

Triggered when pointer begins to hover over the svg element of the paper outside any cell.

The callback function is passed evt as argument.

mouseout

Triggered when pointer ceases to hover directly over a target.

The callback function is passed cellView and evt as arguments.

cell:mouseout Triggered when pointer ceases to hover directly over a cell.
link:mouseout Triggered when pointer ceases to hover directly over a link.
element:mouseout Triggered when pointer ceases to hover directly over an element.
blank:mouseout

Triggered when pointer ceases to hover over the svg element of the paper outside any cell.

The callback function is passed evt as argument.

mouseenter

Triggered when pointer enters the area above a target.

The callback function is passed cellView and evt as arguments.

cell:mouseenter Triggered when pointer enters the area above a cell.
link:mouseenter Triggered when pointer enters the area above a link.
element:mouseenter Triggered when pointer enters the area above an element.
paper:mouseenter

Triggered when pointer enters the area of the paper (including paper border, if present).

The callback function is passed evt as argument.

mouseleave

Triggered when pointer leaves the area above a target.

The callback function is passed cellView and evt as arguments.

cell:mouseleave Triggered when pointer leaves the area above a cell.
link:mouseleave Triggered when pointer leaves the area above a link.
element:mouseleave Triggered when pointer leaves the area above an element.
paper:mouseleave

Triggered when pointer leaves the area of the paper (including paper border, if present).

The callback function is passed evt as argument.

mousewheel

Triggered when mouse wheel is rotated while pointer is on a target.

The callback function is passed cellView, evt, x, y and delta as arguments.

cell:mousewheel Triggered when mouse wheel is rotated while the pointer is on a cell.
link:mousewheel Triggered when mouse wheel is rotated while the pointer is on a link.
element:mousewheel Triggered when mouse wheel is rotated while the pointer is on an element.
blank:mousewheel

Triggered when mouse wheel is rotated while the pointer is on the paper outside any cell.

The callback function is passed evt, x, y and delta as arguments.

magnet

Triggered when interacting with a magnet target.

The callback function is passed elementView, evt, magnetSVGElement, x, y as arguments.

element:magnet:pointerclick Triggered when pointer is clicked on an element magnet and no link was created yet from this magnet (controlled by magnetThreshold option). Calling evt.stopPropagation() prevents triggering cell:pointerclick and element:pointerclick events.
element:magnet:pointerdblclick Triggered when pointer is double-clicked on an element magnet. Calling evt.stopPropagation() prevents triggering cell:pointerdblclick and element:pointerdblclick events.
element:magnet:contextmenu Triggered when pointer is right-clicked on an element magnet. Calling evt.stopPropagation() prevents triggering cell:contextmenu and element:contextmenu events.
cell:highlight

Triggered when the cellView.highlight method is called on a link or element view.

The callback function is invoked with the following arguments:

  • cellView - highlighted CellView
  • node - highlighted node (SVGElement) of the CellView
  • options - options used when cellView.highlight(node, options) was called. The type property is added to the option object and specifies what type of highlighting interactions caused the highlight.
// Disable built-in highlighting
paper.options.highlighting = false;
// Handle each type of the highlight manually
paper.on('cell:highlight', (cellView, node, options) => {
  switch (options.type) {
    case: joint.dia.CellView.Highlighting.CONNECTING: {
      joint.highlighters.stroke.add(cellView, node, 'id1', { attrs: { 'stroke': 'blue' }});
      break;
    }
    case: joint.dia.CellView.Highlighting.EMBEDDING: {
      joint.highlighters.stroke.add(cellView, node, 'id2', { attrs: { 'stroke': 'red' }});
      break;
    }
    default: {
      joint.highlighters.stroke.add(cellView, node, 'id3');
      break;
    }
  }
});
cell:unhighlight

Triggered when the cellView.unhighlight method is called on a link or element view.

The callback function is invoked with the following arguments:

  • cellView - highlighted CellView
  • node - highlighted node (SVGElement) of the CellView
  • options - options used when cellView.unhighlight(node, options) was called. The type property is added to the option object and specifies what type of highlighting interactions caused the unhighlight.
// Disable built-in highlighting
paper.options.highlighting = false;
// Handle each type of the highlight manually
paper.on('cell:unhighlight', (cellView, _node, options) => {
  switch (options.type) {
    case: joint.dia.CellView.Highlighting.CONNECTING: {
      joint.dia.Highlighter.remove(cellView, 'id1');
      break;
    }
    case: joint.dia.CellView.Highlighting.EMBEDDING: {
      joint.dia.Highlighter.remove(cellView, 'id2');
      break;
    }
    default: {
      joint.dia.Highlighter.remove(cellView, 'id3');
      break;
    }
  }
});
cell:highlight:invalid

Triggered when a highlighter makes an attempt to highlight a node, that doesn't exist on the CellView (e.g. a port was highlighted and now it is removed).

The callback function is passed cellView, highlighterId and highlighter as arguments.

paper.on('cell:highlight:invalid', (cellView, id) => {
  // Remove the invalid highlighter
  joint.dia.HighlighterView.remove(cellView, id);
});
element1.addPort({ id: 'port1' });
const elementView1 = element1.findView(paper);
const highlighter1 = joint.highlighters.mask.add(elementView1, { port: 'port1' }, 'highlighter-id'));
// The following line will trigger the event with (elementView1, 'highlighter-id', highlighter1) arguments.
element1.removePorts();
link:connect

Triggered when a link is connected to a cell. The event is triggered after the user reconnects a link.

The callback function is passed linkView, evt, elementViewConnected, magnet and arrowhead as arguments.

link:disconnect

Triggered when a link is disconnected from a cell. The event is triggered after the user reconnects a link.

The callback function is passed linkView, evt, elementViewDisconnected, magnet and arrowhead as arguments.

link:snap:connect

Triggered when a link is connected to a cell. The event (or multiple events) can be triggered while the user is reconnecting a link and snapLinks option is enabled.

The callback function is passed linkView, evt, elementViewConnected, magnet and arrowhead as arguments.

link:snap:disconnect

Triggered when a link is disconnected from a cell. The event (or multiple events) can be triggered while the user is reconnecting a link and snapLinks option is enabled.

The callback function is passed linkView, evt, elementViewDisconnected, magnet and arrowhead as arguments.

render:done

Triggered when all scheduled updates are done (i.e. all scheduled batches have finished).

[custom]

Custom cell event can be triggered on pointerdown with Event attribute. Calling evt.stopPropagation() prevents triggering all subsequent events.

An example of a simple blank:pointerdown event listener:

paper.on('blank:pointerdown', function(evt, x, y) {
  alert('pointerdown on a blank area in the paper.')
})

Consecutive pointerdown, pointermove and pointerup events can share information through the evt.data object:

// Create a new link by dragging
paper.on({
  'blank:pointerdown': function(evt, x, y) {
    var link = new joint.dia.Link();
    link.set('source', { x: x, y: y });
    link.set('target', { x: x, y: y });
    link.addTo(this.model);
    evt.data = { link: link, x: x, y: y };
  },
  'blank:pointermove': function(evt, x, y) {
    evt.data.link.set('target', { x: x, y: y });
  },
  'blank:pointerup': function(evt) {
    var target = evt.data.link.get('target');
    if (evt.data.x === target.x && evt.data.y === target.y) {
        // remove zero-length links
        evt.data.link.remove();
    }
  }
});
dia.Paper.prototype.checkViewport
paper.checkViewport()

For every view in the paper, determine if it fits into the viewport specified by paper.options.viewport function. Views that fit (views for which that function returns true) are attached to the DOM; views that do not are detached.

While async papers do this automatically, synchronous papers require an explicit call to this method for this functionality to be applied. To show all views again, use paper.dumpViews().

paper.checkViewport(opt)

If opt.viewport is provided, it is used as the callback function instead of paper.options.viewport. The format of the callback method is described in the option's documentation, as are examples of usage.

In async papers, providing opt.viewport causes viewport to be temporarily recalculated according to the provided callback function. This may be useful in situations where you need to show different views depending on context (e.g. viewing a section of the diagram vs. printing all of it).

dia.Paper.prototype.clearGrid
paper.clearGrid()

Hide the current grid.

dia.Paper.prototype.clientOffset
paper.clientOffset()

Returns coordinates of the paper viewport, relative to the application's client area.

dia.Paper.prototype.clientToLocalPoint
paper.clientToLocalPoint(p)

Transform client coordinates represented by point p to the paper local coordinates. This is especially useful when you have a mouse event object and want coordinates inside the paper that correspond to event clientX and clientY point.

var localPoint1 = paper.clientToLocalPoint({ x: evt.clientX, y: evt.clientY });
// alternative method signature
var localPoint2 = paper.clientToLocalPoint(evt.clientX, evt.clientY);

dia.Paper.prototype.clientToLocalRect
paper.clientToLocalRect(rect)

Transform the rectangle rect defined in the client coordinate system to the local coordinate system.

var bcr = paper.svg.getBoundingClientRect();
var localRect1 = paper.clientToLocalRect({ x: bcr.left, y: bcr.top, width: bcr.width, height: bcr.height });
// alternative method signature
var localRect2 = paper.clientToLocalRect(bcr.left, bcr.top, bcr.width, bcr.height);
// Move the element to the center of the paper viewport.
var localCenter = localRect1.center();
var elSize = element.size();
element.position(localCenter.x - elSize.width, localCenter.y - elSize.height);

dia.Paper.prototype.defineFilter
paper.defineFilter(filterDefinition)

Define an SVG filter for later reuse within the paper. The method returns the filter id and the filterDefinition must have the following form:

{
    name: <name of the filter>,
    args: <filter arguments>
}

Where name is the name of the filter. See below for the list of built-in filters. args is an object containing filter parameters. These parameters are dependent on the filter used and are described in the list below as well. Example usage:

var filterId = paper.defineFilter({
    name: 'dropShadow',
    args: {
        dx: 2,
        dy: 2,
        blur: 3
    }
});

svgNode.setAttribute('filter', 'url(#' + filterId + ');

The following is the list of built-in filters. All these filters are defined in the joint.util.filter namespace. This namespace can be extended simply by adding a new method to it with one argument, an object with filter parameters, returning a string representing the SVG filter definition.

  • blur
    • x - horizontal blur
    • y - vertical blur [optional, if not defined y is the same as x]
  • dropShadow
    • dx - horizontal shift
    • dy - vertical shift
    • blur - blur
    • color - color
    • opacity - opacity
  • grayscale
    • amount - the proportion of the conversion. 1 is completely grayscale. 0 leaves the element unchanged.
  • sepia
    • amount - the proportion of the conversion. 1 is completely sepia. 0 leaves the element unchanged.
  • saturate
    • amount - the proportion of the conversion. 0 is completely un-saturated. 1 leaves the element unchanged.
  • hueRotate
    • angle - the number of degrees around the color circle the input samples will be adjusted
  • invert
    • amount - the proportion of the conversion. 1 is completely inverted. 0 leaves the element unchanged.
  • brightness
    • amount - the proportion of the conversion. 0 makes the element completely black. 1 leaves the element unchanged.
  • contrast
    • amount - the proportion of the conversion. 0 makes the element completely black. 1 leaves the element unchanged.
dia.Paper.prototype.defineGradient
paper.defineGradient(gradientDefinition)

Define an SVG gradient for later reuse within the paper. The method returns the gradient id and the gradientDefinition must be an object with the following properties:

Name Type Description
type 'linearGradient' | 'radialGradient' The linearGradient or radialGradient type of the gradient.
id string (optional) - A unique identifier of the gradient. The id is generated if none provided.
attrs object (optional) - Additional SVG attributes for the SVGGradientElement.
stops array An array of stops.

Where a stop is an object with the following properties:

Name Type Description
color string Indicates what color to use at that gradient stop.
offset number | string The offset of the gradient stop.
opacity number (optional) - A number in the [0..1] range representing the transparency of the stop color.
const gradientId = paper.defineGradient({
    type: 'linearGradient',
    stops: [
        { offset: '0%', color: '#E67E22' },
        { offset: '20%', color: '#D35400' },
        { offset: '40%', color: '#E74C3C' },
        { offset: '60%', color: '#C0392B' },
        { offset: '80%', color: '#F39C12' }
    ]
});

svgNode.setAttribute('fill', `url(#${gradientId})`);

For an introduction to gradients, please refer to the tutorial on Filters and Gradients.

dia.Paper.prototype.defineMarker
paper.defineMarker(markerDefinition)

Define an SVG marker for later reuse within the paper. The method returns the marker id and the markerDefinition must be an object with the following properties:

Name Type Description
id string (optional) - A unique identifier of the marker. The id is generated if none provided.
attrs object (optional) - Additional SVG attributes for the SVGMarkerElement.
markup string | array String or JSON Markup of the marker content.
paper.defineMarker({
  id: 'my-marker',
  // The coordinate system for defining the path data
  // ------------------------------------------------
  // 0,0: marker-start, marker-end or marker-mid
  // n,0: n > 0 in path direction
  //      n < 0 opposite path direction
  // 0,m: m > 0 left to the path direction
  //      m < 0 right to the path direction
  markup: `
    <circle cx="6" cy="0" r="12" fill="#7b5cce"/>
    <polygon points="0,0 6,6 12,0 6,-6" fill="#d63865" stroke="#fff" />
  `
});

svgNode.setAttribute('marker-start', `url(#my-marker)`);

An alternative definition of the markerDefinition is:

Name Type Description
id string (optional) - A unique identifier of the marker. The id is generated if none provided.
type string The type of the SVGElement representing the marker ('path', 'circle', 'ellipse', 'rect', 'polyline' and 'polygon').
[SVGAttribute] any (optional) - a presentation SVG attribute (e.g fill: 'red')
const markerId = paper.defineMarker({
  type: 'path', // SVG Path
  fill: '#666',
  stroke: '#333',
  d: 'M 10 -10 0 0 10 10 z'
});

// Draw an arrow at the start and the end of a path
svgPath.setAttribute('marker-start', `url(#${markerId})`);
svgPath.setAttribute('marker-end', `url(#${markerId})`);
dia.Paper.prototype.definePattern
paper.definePattern(patternDefinition)

Define an SVG pattern for later reuse within the paper. The method returns the pattern id and the patternDefinition must be an object with the following properties:

Name Type Description
id string (optional) - A unique identifier of the pattern. The id is generated if none provided.
attrs object (optional) - Additional SVG attributes for the SVGGradientElement.
markup string | array St