Thursday, 30 October 2014

Automatic graph layout with javascript (JsPlumb, jQuery and Dagre)

This post solves the limitation of JsPlumb graph layout by integrating with Dagre.

First, I assume that you assign an ID (which is supposed to be unique) to each node in your JsPlumb graph and a class "node" and JsPlumb graph are already created and you want to add automatic layout to that graph.

Now you can get all the nodes with jQuery as follows:
var nodes = $(".node");
And you can get all edges using your JsPlum instance using:
var edges = inst.getAllConnections();
With nodes and edges, you have everything you need to use dagre. Here's the simple code to layout your graph:
// construct dagre graph from JsPlumb graph
var g = new dagre.graphlib.Graph();
g.setGraph({});
g.setDefaultEdgeLabel(function() { return {}; });

var nodes = $(".node");
for (var i = 0; i < nodes.length; i++) {
    var n = nodes[i];
    g.setNode(n.id, {width: n.width(), height: n.height()});
}
var edges = inst.getAllConnections();
for (var i = 0; i < edges.length; i++) {
    var c = edges[i];
    g.setEdge(c.source.id,c.target.id );
}
// calculate the layout (i.e. node positions)
dagre.layout(g);

// Applying the calculated layoutg.nodes().forEach(function(v) {
    $("#" + v).css("left", g.node(v).x + "px");
    $("#" + v).css("top", g.node(v).y + "px");
})
You can put the above code in a function (i.e. layout(nodes, jsPlumbInst)) to apply to any jsPlumb graph.

Thanks to Yuri Gor for creating a live demo at https://codepen.io/yurigor/pen/vXYomB