// Generated by CoffeeScript 1.4.0 (function() { var PAD_MULTIPLIER, R, d3cola, defs, enter_nodes, graph, height, i, l, levels, links, n, nn, nodes, svg, topological_order, width, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _len5, _len6, _len7, _m, _n, _o, _p, _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6; graph = { nodes: [ { id: 'A' }, { id: 'B' }, { id: 'C' }, { id: 'D' }, { id: 'E' }, { id: 'F' }, { id: 'G' }, { id: 'H' }, { id: 'I' }, { id: 'J' }, { id: 'Z' } ], links: [ { id: 1, source: 'A', target: 'B' }, { id: 2, source: 'A', target: 'C' }, { id: 3, source: 'A', target: 'D' }, { id: 4, source: 'B', target: 'E' }, { id: 5, source: 'B', target: 'F' }, { id: 6, source: 'C', target: 'G' }, { id: 7, source: 'C', target: 'F' }, { id: 8, source: 'F', target: 'G' }, { id: 9, source: 'G', target: 'H' }, { id: 10, source: 'G', target: 'I' }, { id: 11, source: 'H', target: 'I' }, { id: 12, source: 'I', target: 'J' }, { id: 13, source: 'Z', target: 'B' } ] }; /* objectify the graph */ /* resolve node IDs (not optimized at all!) */ _ref = graph.links; for (_i = 0, _len = _ref.length; _i < _len; _i++) { l = _ref[_i]; _ref1 = graph.nodes; for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { n = _ref1[_j]; if (l.source === n.id) { l.source = n; } if (l.target === n.id) { l.target = n; } } } /* store the node index into the node itself */ _ref2 = graph.nodes; for (i = _k = 0, _len2 = _ref2.length; _k < _len2; i = ++_k) { n = _ref2[i]; n.i = i; } /* store neighbor nodes into each node */ _ref3 = graph.nodes; for (i = _l = 0, _len3 = _ref3.length; _l < _len3; i = ++_l) { n = _ref3[i]; n.in_neighbors = []; n.out_neighbors = []; } _ref4 = graph.links; for (_m = 0, _len4 = _ref4.length; _m < _len4; _m++) { l = _ref4[_m]; l.source.out_neighbors.push(l.target); l.target.in_neighbors.push(l.source); } /* compute longest distances */ topological_order = tsort(graph.links.map(function(l) { return [l.source.i, l.target.i]; })); _ref5 = graph.nodes; for (_n = 0, _len5 = _ref5.length; _n < _len5; _n++) { n = _ref5[_n]; n.longest_dist = -Infinity; } graph.nodes[0].longest_dist = 0; graph.nodes[10].longest_dist = 0; for (_o = 0, _len6 = topological_order.length; _o < _len6; _o++) { i = topological_order[_o]; n = graph.nodes[i]; _ref6 = n.out_neighbors; for (_p = 0, _len7 = _ref6.length; _p < _len7; _p++) { nn = _ref6[_p]; if (nn.longest_dist < n.longest_dist + 1) { nn.longest_dist = n.longest_dist + 1; } } } graph.constraints = []; /* create the alignment contraints */ levels = _.uniq(graph.nodes.map(function(n) { return n.longest_dist; })); levels.forEach(function(depth) { return graph.constraints.push({ type: 'alignment', axis: 'y', offsets: graph.nodes.filter(function(n) { return n.longest_dist === depth; }).map(function(n) { return { node: n.i, offset: 0 }; }) }); }); R = 18; PAD_MULTIPLIER = 3.5; /* create the position contraints */ levels.forEach(function(depth, i) { var n1, n2; if (i < levels.length - 1) { n1 = _.find(graph.nodes, function(n) { return n.longest_dist === depth; }); n2 = _.find(graph.nodes, function(n) { return n.longest_dist === depth + 1; }); return graph.constraints.push({ axis: 'y', left: n1.i, right: n2.i, gap: 2 * R }); } }); svg = d3.select('svg'); width = svg.node().getBoundingClientRect().width; height = svg.node().getBoundingClientRect().height; defs = svg.append('defs'); /* define arrow markers for graph links */ defs.append('marker').attr({ id: 'end-arrow', viewBox: '0 0 10 10', refX: 4 + R, refY: 5, orient: 'auto' }).append('path').attr({ d: 'M0,0 L0,10 L10,5 z' }); /* create nodes and links */ links = svg.selectAll('.link').data(graph.links, function(d) { return d.id; }); links.enter().append('line').attr('class', 'link'); nodes = svg.selectAll('.node').data(graph.nodes, function(d) { return d.id; }); enter_nodes = nodes.enter().append('g').attr('class', 'node'); enter_nodes.append('circle').attr('r', R); /* draw the label */ enter_nodes.append('text').text(function(d) { return d.id; }).attr('dy', '0.35em'); /* cola layout */ graph.nodes.forEach(function(v) { v.width = PAD_MULTIPLIER * R; return v.height = PAD_MULTIPLIER * R; }); d3cola = cola.d3adaptor().size([width, height]).linkDistance(60).constraints(graph.constraints).avoidOverlaps(true).nodes(graph.nodes).links(graph.links).on('tick', function() { /* update nodes and links */ nodes.attr('transform', function(d) { return "translate(" + d.x + "," + d.y + ")"; }); return links.attr('x1', function(d) { return d.source.x; }).attr('y1', function(d) { return d.source.y; }).attr('x2', function(d) { return d.target.x; }).attr('y2', function(d) { return d.target.y; }); }); enter_nodes.call(d3cola.drag); d3cola.start(100, 30, 30); }).call(this);