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

9 comments:

  1. Hi
    Does this require node to have x and y values ?
    I want to draw plot where .css("left" and TOp are unknown but I know which is parent and which is child ?
    Can this auto Position nodes without such information ?

    ReplyDelete
    Replies
    1. x & y are being calculated for you by dagre.

      Delete
  2. It will be helpful if you post an example at jsfiddle.net like http://jsfiddle.net/gXuS7/ but with auto positioning , where one doesnot know css top and left that is where to put divs

    ReplyDelete
  3. Hi, Thanks for this blog - really it helped me to move further. I am also using JSPlumb and Dojo. But I had a query , with above reference I could rearrange the nodes of jsplumb connection. But I could not rearrange the edges. Those remain there itself. Does it need to get dragged along with the rearranged nodes? Or do we need to rearrange edges seperately as done in the last step.

    ReplyDelete
  4. Hi, Thanks for this blog - really it helped me to move further. I am also using JSPlumb and Dojo. But I had a query , with above reference I could rearrange the nodes of jsplumb connection. But I could not rearrange the edges. Those remain there itself. Does it need to get dragged along with the rearranged nodes? Or do we need to rearrange edges seperately as done in the last step.

    ReplyDelete
    Replies
    1. If you redraw the node, it redraw the edges in the right positions.

      Delete
  5. This comment has been removed by the author.

    ReplyDelete
  6. Hi, thanks for this blog.

    Could anyone please tell how to start the alignment of the elements from the middle instead of left side inside a container (div).

    I see this code, is doing the positioning, I thought to give left padding but from centre the elements are not spreading like a tree evenly in left and right direction and are restricting y coordinate and spreading towards right side

    g.nodes().forEach(function(v) {
    $("#" + v).css("left", g.node(v).x + "px");
    $("#" + v).css("top", g.node(v).y + "px");
    });

    Please suggest

    ReplyDelete
  7. hi can you please help me with your code align blocks as a vertical position and I need align as horizontal position.

    ReplyDelete