D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
mforando
Full window
Github gist
Division-Role Interface
Built with
blockbuilder.org
<!DOCTYPE html> <head> <meta charset="utf-8"> <script src="https://d3js.org/d3.v4.min.js"></script> <style> body { margin:0; position:fixed; top:0; right:0; bottom:0; left:0; font-family:Franklin Gothic Medium; font-size:20px; } #container{ display:inline-block; } #left{ display:inline-block; vertical-align:top; } #right{ display:inline-block; vertical-align:top; width:400px; } #addDiv{ width:100%; display:block; } #addDiv:hover{ background:rgb(220,220,220); } .node circle { stroke-width: 1.5px; } .node text { font: 13px Franklin Gothic Book; } .link { fill: none; stroke: #ccc; stroke-width: 1px; } </style> </head> <div id="container"> <div id="left"> </div> <div id="right"> <div id="divisionCont"> <div id="addDiv">+ Add a Division</div> </div> </div> </div> <body> <script> var counter = 0; d3.select("#addDiv").on("click",function(d){ var cont = d3.select("#divisionCont") .append("div") .attr("class","divisionDiv") .style("display","block") var divisionCont = cont.append("div") .attr("class","divisionControls") counter = counter + 1 divisionCont.append("input") .attr("class","divInput") .attr("type","text") .property("value","New Division" + counter) divisionCont.append("span") .text(" - ") .on("click",function(d){ d3.select(this.parentNode).remove() }) divisionCont.append("span") .text(" Add Person ") .on("click",function(d){ var roleDiv = d3.select(this.parentNode) .append("div") .attr("class","divRoles") .style("display","block") .style("position","relative") var roleTree = roleDiv.append("div") .attr("class","roleTree") .style("display","inline-block") .style("width","20px") .style("height","auto") .style("display","absolute") .style("top","15px") .style("background","yellow") counter = counter + 1 roleDiv.append("input") .attr("type","text") .style("height","20px") .property("value","New Role" + counter) getTree() }) getTree() }) function getTree(){ var treelinks = [{"parent":null,"name":"main"}] d3.selectAll(".divisionControls").each(function(){ var divisionName = d3.select(this).select(".divInput").property("value"); treelinks.push({"parent":"main","name":divisionName}) console.log(d3.select(this).selectAll(".divRoles")) if(d3.select(this).selectAll(".divRoles").empty()){ treelinks.push({"parent":divisionName,"name":"foo"}) } else{ //get children of division. If there arent any, create a null child to store process d3.select(this).selectAll(".divRoles").each(function(){ var roleName = d3.select(this).select("input").property("value") treelinks.push({"parent":divisionName,"name":roleName}) }) } }) var dataMap = treelinks.reduce(function(map, node) { map[node.name] = node; return map; }, {}); var treeData1 = []; treelinks.forEach(function(node) { var parent = dataMap[node.parent]; if (parent) { (parent.children || (parent.children = [])) .push(node); } else { treeData1.push(node); } }); var i = 0, duration = 1000, root; var treemap = d3.tree() .size([svgWidth,200]) .separation(function(a, b) { return (a.parent == b.parent ? 5:25) ; }) //console.log(treeData1) var treeData = treeData1[0] root = d3.hierarchy(treeData, function(d) { return d.children; }); root.x0 = svgWidth; root.y0 = 0; var treeData = treemap(root); var nodes = treeData.descendants(), links = treeData.descendants().slice(1); console.log(nodes) nodes.forEach(function(d){ d.y = (d.depth)* 200/3}); var node = chart.selectAll('.node').data(nodes, function(d) {return d.data.id; }); var nodeEnter = node.enter() .append('g') .attr('class', 'node') .attr("transform", function(d) {return "translate(" + d.x + "," + d.y + ")";}) .on('click', click); svg.selectAll(".node") .append('circle') .attr('class', 'node') .attr('r', 6) .style("fill","white"); // Add labels for the nodes nodeEnter.append('text') .attr("dy", ".35em") .attr("x", function(d) {return d.children || d._children ? -11 : 11;}) .attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; }) .style("font-size","10px") .text(function(d){return d.data.name; }); // UPDATE var nodeUpdate = nodeEnter.merge(node); // Transition to the proper position for the node nodeUpdate .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); nodeUpdate.select('text').text(function(d){return d.data.name; }) // Update the node attributes and style nodeUpdate.selectAll('circle') .attr('r', 6) .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; }) .attr('cursor', 'pointer') .style("stroke", function(d) { return "black" // return colors(d.data.depth) }) var nodeExit = node.exit() .remove(); var link = chart.selectAll('path.link') .data(links, function(d) {return d.data.name + "-" + d.data.parent; }); var linkEnter = link.enter().insert('path', "g") .attr("class", "link") .attr('d', function(d){ var o = {x: d.x, y: d.y} return diagonal(o, o) }); // UPDATE var linkUpdate = linkEnter.merge(link); linkUpdate.attr("d", function(d) { return "M" + d.x + "," + d.y + "C" + d.x + "," + (d.y + d.parent.y) / 2 + " " + d.parent.x + "," + (d.y + d.parent.y) / 2 + " " + d.parent.x + "," + d.parent.y; }) var linkExit = link.exit() .attr("d", function(d) { return "M" + d.x + "," + d.y + "C" + d.x + "," + (d.y + d.parent.y) / 2 + " " + d.parent.x + "," + (d.y + d.parent.y) / 2 + " " + d.parent.x + "," + d.parent.y; }) .remove(); nodes.forEach(function(d){ d.x0 = d.x; d.y0 = d.y; }); // Creates a curved (diagonal) path from parent to the child nodes function diagonal(s, d) { path = `M ${s.x} ${s.y} C ${(s.x + d.x) / 2} ${s.y}, ${(s.x + d.x) / 2} ${d.y}, ${d.x} ${d.y}` return path } // Toggle children on click. function click(d) { if (d.children) { d._children = d.children; d.children = null; } else { d.children = d._children; d._children = null; } update(d); } } var svgHeight = 800; var svgWidth = 500; var margin = {top: 20, right: 10, bottom: 20, left: 10}; var svg = d3.select("#left").append("svg") .attr("width", svgWidth + margin.left + margin.right) .attr("height", svgHeight + margin.top + margin.bottom) .style("border","1px solid black") var chart = svg.append("g") .attr("transform","translate("+margin.top+"," + margin.left + ")") </script> </body>
https://d3js.org/d3.v4.min.js