# Graph

`dia.Graph`

is the model holding all cells (elements and links) of the diagram. It inherits from mvc.Model. The collection of all the cells is stored in the property ** cells** as an mvc.Collection.

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

In order for JointJS to find the correct constructor for your cell, the `graph`

option `cellNamespace`

must be provided in its constructor function when a graph is instantiated. Built-in shapes are usually located in the `shapes`

namespace, so this is a common namespace to use. It's possible to add custom shapes to this namespace, or alternatively, you may like to use a different namespace completely.

For example, if `joint.shapes`

is provided as the value of `cellNamespace`

, and a cell is of type `'custom.Element'`

, then the graph looks up the `shapes.custom.Element`

model when deserializing a graph from JSON format. If the graph is instantiated as e.g. `const graph = new dia.Graph({}, { cellNamespace: myCustomNamespace })`

, then the `graph`

will read the model definition from the `myCustomNamespace.custom.Element`

object instead. This option is often used in combination with the `cellViewNamespace`

option on the joint.dia.Paper object.

## constructor

## Methods

### addCell()

`graph.addCell(cell[, opt])`

Add a new cell to the graph. If `cell`

is an array, all the cells in the array will be added to the graph. Any additional option or custom property provided in the options object will be accessible in the callback function of the graph add event.

If `opt.dry`

is set to `true`

, the graph reference is not stored on the `cell`

after it's added.

If `opt.async`

is set to `false`

, this ensures the `cell`

is rendered synchronously.

If `opt.sort`

is set to `false`

, the `cell`

will be added at the end of the collection.

`const rect = new joint.shapes.standard.Rectangle({`

position: { x: 100, y: 100 },

size: { width: 90, height: 30 },

attrs: { label: { text: 'my rectangle' } }

});

const rect2 = rect.clone();

const link = new joint.shapes.standard.Link({ source: { id: rect.id }, target: { id: rect2.id } });

const graph = new joint.dia.Graph({}, { cellNamespace: joint.shapes });

graph.addCell(rect).addCell(rect2).addCell(link);

### 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.

### 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:

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.

### 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.

### 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).

### 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] }`

.

### 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:

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.

### disconnectLinks()

`graph.disconnectLinks(element)`

Disconnect all the associated links with the `element`

.

### 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.

### 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.

### 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'`

.

### 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)

### 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);`

### getCell()

`graph.getCell(id)`

Get a cell from the graph by its `id`

.

### 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).

### 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 });

### 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.

### getConnectedLinks()

`graph.getConnectedLinks(element [, opt])`

Get all links connected with `element`

.

If `opt.inbound === true`

, return only inbound connected links. Conversely, if `opt.outbound === true`

, return only outbound connected links. If both of these options are left undefined, or if both of them are set to `true`

, return both inbound and outbound links.

By default, this function returns only immediate (shallow) inbound and outbound links - no recursion. (Note that connections from `element`

to embedded child elements, and connections to `element`

from embedding parent elements count as shallow, too - they too are returned.)

If `opt.deep === true`

, return all outside links that connect with `element`

or any of its descendants (descendants meaning elements that are embedded or deeply embedded within `element`

). The `inbound`

and `outbound`

options can still be applied on top of this option.

Note that the specification of `opt.deep`

excludes links that connect two descendants of `element`

(enclosed links). If you do need to find all links connected with and/or enclosed within `element`

, you should use `opt.deep === true`

alongside an additional option: `opt.includeEnclosed === true`

.

If `opt.indirect === true`

, also return links that can only be considered connected to `element`

if we go against the flow of directed links at link-link connections.

Example use:

`var links = graph.getConnectedLinks(element); // inbound and outbound`

var links = graph.getConnectedLinks(element, { outbound: true });

var links = graph.getConnectedLinks(element, { deep: true }); // inbound and outbound

var links = graph.getConnectedLinks(element, { inbound: true, deep: true });

var links = graph.getConnectedLinks(element, { outbound: true, deep: true, includeEnclosed: true });

var links = graph.getConnectedLinks(element, { indirect: true });

### 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).

### 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).

### 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).

### getLinks()

`graph.getLinks()`

Return an array of all links in the graph. The links are sorted by their `z`

index (the smallest `z`

being first).

### 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.

### 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).

### getSinks()

`graph.getSinks()`

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

.

### getSources()

`graph.getSources()`

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

.

### 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.

### getSuccessors()

`graph.getSuccessors(element [, opt])`

Return an array of all the successors of `element`

. By default, a Depth-first search algorithm is used (important for the order of returned elements).

If `opt.breadthFirst`

is set to `true`

, use a Breadth-first search algorithm instead.

Generally, `getSuccessors`

cares about the direction of the links. It follows links from their source to target only. The resulting array contains the elements that you visit if you follow the directed links. The links are simply navigated, and embedding is not considered.

In the following image, the successors of `A`

are `C`

and `B`

. Embedding is not taken into account.

If `opt.deep`

is set to `true`

, embedded elements are taken into account too (see dfs() for details). That means elements connected to any of the descendants are also successors.

In the following image, if `{ deep: false }`

, the only successor of `A`

is `D`

. Embedding is not taken into account. If `{ deep: true }`

, and `B`

is embedded in `A`

, that means the successors of `A`

are `C`

and `D`

.

### 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.

### isPredecessor()

`graph.isPredecessor(elementA, elementB)`

Return `true`

if `elementB`

is a predecessor of `elementA`

.

### 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)`

.

### 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)`

.

### isSuccessor()

`graph.isSuccessor(elementA, elementB)`

Return `true`

if `elementB`

is a successor of `elementA`

.

### maxZIndex()

`graph.maxZIndex()`

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

### minZIndex()

`graph.minZIndex()`

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

### removeCells()

`graph.removeCells(cells[, opt])`

`graph.removeCells(cell, cell, ..[, opt])`

Removes the given cells from the graph.

### removeLinks()

`graph.removeLinks(element)`

Remove all the associated links with the `element`

.

### 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 want to replace all the cells in one go. The `options`

object can optionally contain additional data that is passed over to the event listeners of the graph reset event.

### 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.

### 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());`

### 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.

## Events

Graph triggers several events of its own that you can react on.

*add*

Triggered when a new cell is added to the graph.

`graph.on('add', function(cell) {`

alert('New cell with id ' + cell.id + ' added to the graph.')

})

*change*

Generic event triggered for any change in the graph.

*remove*

Triggered when a cell is removed from the graph.

## 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

}

]

}