(function() { var global, height, update, width; width = 960; height = 500; /* SELECTION - store the selected node */ /* EDITING - store the drag mode (either 'drag' or 'add_link') */ global = { selection: null }; window.main = function() { return d3.json('entities-pages.json', function(error, graph) { var container, svg; global.graph = graph; global.graph.objectify = function() { /* resolve node IDs (not optimized at all!) */ var l, n, _i, _len, _ref, _results; _ref = global.graph.links; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { l = _ref[_i]; _results.push((function() { var _j, _len2, _ref2, _results2; _ref2 = global.graph.nodes; _results2 = []; for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) { n = _ref2[_j]; if (l.source === n.id) { l.source = n; continue; } if (l.target === n.id) { l.target = n; continue; } else { _results2.push(void 0); } } return _results2; })()); } return _results; }; global.graph.objectify(); /* create the SVG */ svg = d3.select('body').append('svg').attr('width', width).attr('height', height); /* ZOOM and PAN */ /* create container elements */ container = svg.append('g'); container.call(d3.behavior.zoom().scaleExtent([0.25, 6]).on('zoom', (function() { return global.vis.attr('transform', "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); }))); global.vis = container.append('g'); /* create a rectangular overlay to catch events */ /* WARNING rect size is huge but not infinite. this is a dirty hack */ global.vis.append('rect').attr('class', 'overlay').attr('x', -500000).attr('y', -500000).attr('width', 1000000).attr('height', 1000000).on('click', (function(d) { /* SELECTION */ global.selection = null; d3.selectAll('.node').classed('selected', false); return d3.selectAll('.link').classed('selected', false); })); /* END ZOOM and PAN */ global.colorify = d3.scale.category10(); /* initialize the force layout */ global.force = d3.layout.force().size([width, height]).charge(-800).linkDistance(30).on('tick', (function() { /* update nodes and links */ global.vis.selectAll('.node').attr('transform', function(d) { return "translate(" + d.x + "," + d.y + ")"; }); return global.vis.selectAll('.link').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; }); })); /* DRAG */ global.drag = global.force.drag().on('dragstart', function(d) { return d.fixed = true; }); return update(); }); }; update = function() { /* update the layout */ var links, new_nodes, nodes; global.force.nodes(global.graph.nodes).links(global.graph.links).start(); /* create nodes and links */ /* (links are drawn with insert to make them appear under the nodes) */ /* also define a drag behavior to drag nodes */ /* dragged nodes become fixed */ nodes = global.vis.selectAll('.node').data(global.graph.nodes, function(d) { return d.id; }); new_nodes = nodes.enter().append('g').attr('class', 'node').on('click', (function(d) { /* SELECTION */ global.selection = d; d3.selectAll('.node').classed('selected', function(d2) { return d2 === d; }); return d3.selectAll('.link').classed('selected', false); })); links = global.vis.selectAll('.link').data(global.graph.links, function(d) { return "" + d.source.id + "->" + d.target.id; }); links.enter().insert('line', '.node').attr('class', 'link').on('click', (function(d) { /* SELECTION */ global.selection = d; d3.selectAll('.link').classed('selected', function(d2) { return d2 === d; }); return d3.selectAll('.node').classed('selected', false); })); links.exit().remove(); new_nodes.call(global.drag); new_nodes.filter(function(d) { return d.type !== 'page'; }).append('circle').attr('r', 9).attr('stroke', function(d) { return global.colorify(d.type); }).attr('fill', function(d) { return d3.hcl(global.colorify(d.type)).brighter(3); }); new_nodes.filter(function(d) { return d.type === 'page'; }).append('rect').attr('x', -8).attr('y', -8).attr('width', 16).attr('height', 16).attr('stroke', function(d) { return global.colorify(d.type); }).attr('fill', function(d) { return d3.hcl(global.colorify(d.type)).brighter(3); }); /* draw the label */ new_nodes.append('text').text(function(d) { return d.value; }).attr('dy', '0.35em'); return nodes.exit().remove(); }; }).call(this);