Skip to content

Instantly share code, notes, and snippets.

@Dulani
Created April 17, 2014 23:18
Show Gist options
  • Save Dulani/11016730 to your computer and use it in GitHub Desktop.
Save Dulani/11016730 to your computer and use it in GitHub Desktop.
.node {
cursor: pointer;
}
.node circle {
fill: #fff;
stroke: #f98415;
stroke-width: 1.5px;
}
.node text {
font: 12px sans-serif;
}
.link {
fill: none;
stroke: #ededed;
stroke-width: 1.5px;
}
.tooltip {
font-family: sans-serif;
position: absolute;
width: 20em;
padding: 1em;
font-size: 12px;
background: #f8f8f8;
border: 1px solid #ededed;
border-radius: 8px;
pointer-events: none;
}
<!DOCTYPE html>
<html>
<head>
<meta name="description" content="Initial working version with CJ Taxonomy." />
<script src="http://d3js.org/d3.v3.min.js"></script>
<meta charset=utf-8 />
<title>Criminal Justice Technologies Taxonomy Tree</title>
<script id="JSONdata" type="application/json">
{
"name": "CJ Technologies",
"children": [
{
"name": "Facility Operations Related Technologies",
"children": [
{
"name": "Individual Behavior Shaping Within Facility",
"children": null
},
{
"name": "Internal Access Control",
"children": null
},
{
"name": "Internal Environmental Control",
"children": null
},
{
"name": "Logistics",
"children": null
},
{
"name": "Physical Perimeter Security (sensors above)",
"children": null
},
{
"name": "Population Health Care",
"children": null
}
]
},
{
"name": "Information Analysis",
"children": [
{
"name": "Analytical Methods",
"children": null
},
{
"name": "Computational Tools",
"children": null
},
{
"name": "Organizational Innovations",
"children": null
}
]
},
{
"name": "Information Collection",
"children": [
{
"name": "Community interaction tools ",
"children": null
},
{
"name": "Field analytic tools or test technologies",
"children": null
},
{
"name": "Fixed surveillance and detection",
"children": null
},
{
"name": "Laboratory Tools and Techniques for Evidence Analysis (Forensics Technologies)",
"children": null
},
{
"name": "Mobile surveillance and detection",
"children": null
},
{
"name": "Organizational Performance Monitoring Tools",
"children": null
},
{
"name": "Personnel Management and Performance Monitoring Tools",
"children": null
},
{
"name": "Specialized Mission Collection Tools",
"children": null
}
]
},
{
"name": "Information Delivery",
"children": [
{
"name": "External Communications",
"children": [
{
"name": "Public Alert",
"size": 4709.8
},
{
"name": "Public Information Functions",
"size": 2204.6
}
]
},
{
"name": "Fixed Location Communications",
"children": [
{
"name": "Voice",
"size": 4322
},
{
"name": "Video",
"size": 3699.5
},
{
"name": "Data",
"size": 4227.7
}
]
},
{
"name": "Personnel Communications",
"children": [
{
"name": "Voice",
"size": 3385
},
{
"name": "Data",
"size": 3114.8
}
]
},
{
"name": "Vehicle-Based Communications",
"children": [
{
"name": "Voice",
"size": 3400.8
},
{
"name": "Video",
"size": 3287.9
},
{
"name": "Data",
"size": 1880.9
}
]
}
]
},
{
"name": "Information Management",
"children": [
{
"name": "Information Technology Systems for Managing Mission-Related Data",
"children": null
},
{
"name": "Information Technology Systems for Managing Organizational Resources",
"children": null
},
{
"name": "Physical File Tracking",
"children": null
},
{
"name": "System Integration and Sharing",
"children": null
}
]
},
{
"name": "Personal Protection or Augmentation",
"children": [
{
"name": "Body Armor",
"children": null
},
{
"name": "Physiological Monitoring",
"children": null
},
{
"name": "Respiratory Protection",
"children": null
},
{
"name": "Visual Augmentation (Night Vision)",
"children": null
}
]
},
{
"name": "Training Technologies",
"children": [
{
"name": "Simulators",
"children": null
},
{
"name": "Technology-mediated teaching",
"children": null
}
]
},
{
"name": "Vehicles",
"children": [
{
"name": "Aircraft",
"children": [
{
"name": "Fixed Wing",
"size": 3137.1
},
{
"name": "Rotorcraft",
"size": 4479.8
},
{
"name": "Unmanned Aerial Vehicles",
"size": 4457.6
}
]
},
{
"name": "Associated Technologies",
"children": [
{
"name": "Sirens, Markings and Warning Indicators",
"size": 1623.1
},
{
"name": "Vehicle Armor",
"size": 1077
}
]
},
{
"name": "Ground",
"children": [
{
"name": "Automobiles",
"size": 3038.9
},
{
"name": "Motorcycles",
"size": 2279.3
},
{
"name": "Unmanned Ground Vehicles",
"size": 3670.6
},
{
"name": "Specialized Ground Vehicles",
"size": 1493
}
]
},
{
"name": "Watercraft",
"children": null
}
]
},
{
"name": "Weapons and Force",
"children": [
{
"name": "Less-than-Lethal Weapons",
"children": [
{
"name": "Firearms Based Technologies",
"size": 2053.3
},
{
"name": "Batons",
"size": 3726.3
},
{
"name": "Stun",
"size": 4870.8
},
{
"name": "Sound Based",
"size": 4291.8
},
{
"name": "Water ",
"size": 3151.1
},
{
"name": "Irritants",
"size": 1579.9
},
{
"name": "Foam",
"size": 4794.5
}
]
},
{
"name": "Lethal Weapons",
"children": [
{
"name": "Firearms",
"size": 2538.9
},
{
"name": "Sighting, night scopes, etc.",
"size": 2568.8
}
]
},
{
"name": "Pursuit management",
"children": null
},
{
"name": "Restraint technologies",
"children": null
},
{
"name": "Specialized task technologies",
"children": null
},
{
"name": "Training",
"children": null
}
]
}
]
}
</script>
</head>
<body>
<div id="map"></div>
</body>
</html>
/*var testjson = '{ "name":"START", "children":[ { "name":"Parent 1", "children":[ { "name":"Child 1", "children":[ { "name":"Child 1.1", "description":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed.", "url":"http:example.com" } ] }, { "name":"Child 2", "children":[ { "name":"Child 2.1", "description":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed.", "url":"http:example.com" } ] } ] } ] }';
*/
var testjson = document.getElementById("JSONdata");
//var root = JSON.parse(json.textContent);
var margin = {top: 0, right: 120, bottom: 20, left: 120},
width = 960 - margin.right - margin.left,
height = 800 - margin.top - margin.bottom;
var i = 0,
duration = 750,
root;
var tree = d3.layout.tree()
.size([height, width]);
var diagonal = d3.svg.diagonal()
.projection(function(d) { return [d.y, d.x]; });
var svg = d3.select("#map").append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//root = JSON.parse(testjson);
root = JSON.parse(testjson.textContent);
root.x0 = height / 2;
root.y0 = 0;
function collapse(d) { //Handles the initial collapsing?
if (d.children) {
d._children = d.children;
d._children.forEach(collapse);
d.children = null;
}
}
console.log(root);
root.children.forEach(collapse);
console.log(root);
update(root);
function update(source) {
var nodes = tree.nodes(root).reverse(),
links = tree.links(nodes);
nodes.forEach(function(d) { d.y = d.depth * 180; });
var node = svg.selectAll("g.node")
.data(nodes, function(d) { return d.id || (d.id = ++i); });
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
.on("click", click);
nodeEnter.append("circle")
.attr("r", 1e-6)
.style("fill", function(d) { return d._children ? "#FAC492" : "#fff"; });
nodeEnter.append("text")
.attr("x", function(d) { return d.children || d._children ? -10 : 10; })
.attr("dy", ".35em")
.attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
.text(function(d) { return d.name; })
.style("fill-opacity", 1e-6)
.on("mouseover", mouseover)
.on("mousemove", mousemove)
.on("mouseout", mouseout);
var nodeUpdate = node.transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });
nodeUpdate.select("circle")
.attr("r", 4.5)
.style("fill", function(d) { return d._children ? "#FAC492" : "#fff"; });
nodeUpdate.select("text")
.style("fill-opacity", 1);
var nodeExit = node.exit().transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
.remove();
nodeExit.select("circle")
.attr("r", 1e-6);
nodeExit.select("text")
.style("fill-opacity", 1e-6);
var link = svg.selectAll("path.link")
.data(links, function(d) { return d.target.id; });
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function(d) {
var o = {x: source.x0, y: source.y0};
return diagonal({source: o, target: o});
});
link.transition()
.duration(duration)
.attr("d", diagonal);
link.exit().transition()
.duration(duration)
.attr("d", function(d) {
var o = {x: source.x, y: source.y};
return diagonal({source: o, target: o});
})
.remove();
nodes.forEach(function(d) {
d.x0 = d.x;
d.y0 = d.y;
});
}
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
update(d);
}
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 1e-6);
function mouseover(d) {
if (!d.children) {
div
.html('<h2>' + d.name + '</h2><p>' + d.description + '</p>')
.transition()
.duration(500)
.style("opacity", 1);
}
}
function mousemove(d) {
if (typeof d.description !== 'undefined') {
div
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY) + "px");
}
}
function mouseout(d) {
div.transition()
.duration(500)
.style("opacity", 1e-6);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment