<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>Node-Link Tree</title>
<script src="d3.v3.min.js"></script>
<style type="text/css">
.node rect {
cursor: pointer;
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}
.node text {
font: 10px sans-serif;
}
path.link {
fill: none;
stroke: #ccc;
stroke-width: 1.5px;
}
#chart svg{ width:100% !important;}
</style>
</head>
<body>
<!-- load the d3.js library -->
<script src="http://d3js.org/d3.v3.min.js"></script>
<div id="toolTip" class="tooltip" style="opacity: 0;">
<div id="head" class="header"></div>
<div id="header1" class="header1"></div>
<div id="header2" class="header2"></div>
<div style="position: absolute; left: 10px" >
<div id="SwissDiv" style="width:200px; left: 0px; top: 10px; position: absolute;" class="selected">
<div class="header3">
<br />
Error Count
</div>
<div class="header-rule"></div>
<div id="errorCount" class="header4"></div>
</div>
</div>
<div class="tooltipTail"></div>
</div>
<div id="chart"></div>
<script type="text/javascript">
var margin = { top: 30, right: 10, bottom: 10, left: 10 },
width = 200 - margin.left - margin.right,
halfWidth = width ,
height = 500 - margin.top - margin.bottom,
i = 0,
duration = 500,
root;
var getChildren = function (d) {
var a = [];
if (d.winners) for (var i = 0; i < d.winners.length; i++) {
d.winners[i].isRight = true;
d.winners[i].parent = d;
a.push(d.winners[i]);
}
return a.length ? a : null;
}
;
var tree = d3.layout.tree()
.size([height, width])
;
var diagonal = d3.svg.diagonal()
.projection(function (d) { return [d.y, d.x]; });
var elbow = function (d, i) {
var source = calcLeft(d.source);
var target = calcLeft(d.target);
var hy = (target.y - source.y) / 2;
if (d.isRight) hy = -hy;
return "M" + (source.y) + "," + (source.x+17)
+ "H" + (source.y + hy)
+ "V" + (target.x+17 )+ "H" + target.y;
};
var connector = elbow;
var calcLeft = function (d) {
var l = d.y;
if (!d.isRight) {
l = d.y - halfWidth;
l = halfWidth - l;
}
return { x: d.x, y: l };
};
var vis = d3.select("#chart").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 + ")");
var toArray = function (item, arr) {
arr = arr || [];
var i = 0, l = item.children ? item.children.length : 0;
arr.push(item);
for (; i < l; i++) {
toArray(item.children[i], arr);
}
return arr;
};
// d3.json("bracket.json", function (json) {
root = {
"name": "Workflow",
"winners": [
{
"name": "Initialization","count":10,
"winners": [
{"name": "Step1","count":1,
"winners": [
{"name": "Step1.1","count":5},
{"name": "Step1.2","count":20},
{"name": "Step1.3","count":1} ]
},
{"name": "Step2","count":2,
"winners": [
{"name": "Step2.1","count":20},
{"name": "Step2.2","count":3},
{"name": "Step2.3","count":10} ]
},
{"name": "Step3","count":0}
]
},
{"name": "Underwriting",
"winners": [
{"name": "Step4","count":20},
{"name": "Step5","count":3},
{"name": "Step6","count":10} ]
},
{"name": "Data Inbound",
"winners": [
{"name": "Step7","count":2},
{"name": "Step8","count":5},
{"name": "Step9","count":20} ]
}
]
};
root.x0 = height / 2;
root.y0 = width / 2;
var t1 = d3.layout.tree().size([height, halfWidth]).children(function (d) { return d.winners; });
// t2 = d3.layout.tree().size([height, halfWidth]).children(function (d) { return d.challengers; });
t1.nodes(root);
// t2.nodes(root);
var rebuildChildren = function (node) {
node.children = getChildren(node);
if (node.children) node.children.forEach(rebuildChildren);
}
rebuildChildren(root);
root.isRight = false;
update(root); // });
function update(source) {
// Compute the new tree layout.
var nodes = toArray(source);
// Normalize for fixed-depth.
nodes.forEach(function (d) { d.y = d.depth * 180 + halfWidth; });
// Assign Color
nodes.forEach(function (d) { d.color = "#009900" });
SetColor(nodes);
// Update the nodes…
var node = vis.selectAll("g.node")
.data(nodes, function (d) { return d.id || (d.id = ++i); });
// Enter any new nodes at the parent's previous position.
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("transform", function (d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
.on("click", click);
nodeEnter.append("rect")
. attr("width", 70)
.attr("height", 30)
.on("mouseover", function (d) { node_onMouseOver(d); })
.on("mouseout", function (d) {
toolTip.transition()
.duration(500)
.style("opacity", "0")
.style("fill-opacity", "0") ;
})
.style("fill", function (d) { return d.color; });
// For Image Add
nodeEnter.append("image");
var lastNodes= nodeEnter.filter(function (d) { if (!( d.children || d._children)){ return d} ;});
lastNodes.select("image").remove();
nodeEnter.append("text")
.attr("dy", 18)
.attr("text-anchor", "Left")
.text(function (d) { return ( d.name) })
.style("cursor","pointer")
.style("fill-opacity", 1e-6)
.on("mouseover", function (d) { node_onMouseOver(d); })
.on("mouseout", function (d) {
toolTip.transition()
.duration(500)
.style("opacity", "0")
.style("fill-opacity", "0") ; });
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr("transform", function (d) { p = calcLeft(d); return "translate(" + p.y + "," + p.x + ")"; });
nodeUpdate.select("rect")
.attr("width", 70)
.attr("height", 30)
.style("fill", function (d) { return return d.color;});
nodeUpdate.select("text")
.style("fill-opacity", 1);
// For Image
nodeUpdate.select("image")
.attr("xlink:href", function(d){ return d._children ? "http://findicons.com/files/icons/2332/super_mono/64/toggle_expand.png": "http://findicons.com/files/icons/2332/super_mono/64/toggle_collapse.png"})
.attr("x", 70)
.attr("y", 8)
.attr("width", 16)
.attr("height", 16);
// Transition exiting nodes to the parent's new position.
var nodeExit = node.exit().transition()
.duration(duration)
.attr("transform", function (d) { p = calcLeft(d.parent || source); return "translate(" + p.y + "," + p.x + ")"; })
.remove();
nodeExit.select("rect")
.attr("width", 70)
.attr("height", 30);
// .attr("r", 1e-6);
nodeExit.select("text")
.style("fill-opacity", 1e-6);
// Update the links...
var link = vis.selectAll("path.link")
.data(tree.links(nodes), function (d) { return d.target.id; });
// Enter any new links at the parent's previous position.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function (d) {
var o = { x: source.x0, y: source.y0 };
return connector({ source: o, target: o });
});
// Transition links to their new position.
link.transition()
.duration(duration)
.attr("d", connector);
// Transition exiting nodes to the parent's new position.
link.exit().transition()
.duration(duration)
.attr("d", function (d) {
var o = calcLeft(d.source || source);
if (d.source.isRight) o.y -= halfWidth - (d.target.y - d.source.y);
else o.y += halfWidth - (d.target.y - d.source.y);
return connector({ source: o, target: o });
})
.remove();
// Stash the old positions for transition.
nodes.forEach(function (d) {
var p = calcLeft(d);
d.x0 = p.x;
d.y0 = p.y;
});
// 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;
}
isFirst=false;
update(source);
}
}
function GetColorCode( errorCount)
{
var colorCode;
if(errorCount==0)
{
colorCode="#009900";
}
else if (errorCount>=1 && errorCount<=9)
{
colorCode="#FFFFFF";
}
else if(errorCount>=9 )
{
colorCode="#FFFF00";
}
return colorCode;
}
function node_onMouseOver(d) {
toolTip.transition()
.duration(200)
.style("opacity", "1");
header.text(d.name);
// header1.text((d.depth > 1) ? "Header1" : "");
// if (d.depth > 2) header1.html(header1.html() + " - " + "Header2");
errorCount.text(d.count);
toolTip.style("left", (d3.event.pageX + 15) + "px")
.style("top", (d3.event.pageY - 75) + "px");
}
function SetColor(nodes) {
for (var y = 0; y < nodes.length; y++) {
var node = nodes[y];
var errorCount=0;
var colorName='';
var colors=[];
if (node.children || node._children) {
SetColor(node.children?node.children : node._children);
for (var z = 0; z < (node.children? node.children.length:node._children.length); z++) {
var child = node.children? node.children[z]: node._children[z];
if(!(child.children?child.children : child._children ))
{
child.color=GetColorCode( child.count);
colors.push(GetColorCode((child.count) ? child.count : 0));
}
else
colors.push(child.color);
}
if( colors.indexOf("#FFFF00")>-1)
colorName="#FFFF00";
else if(colors.indexOf("#009900")>-1)
colorName="#009900";
else if(colors.indexOf("#FFFFFF")>-1)
colorName="#FFFFFF";
node.color= colorName;
}
}
}
</script>
</body>
</html>
body {
overflow: auto;
margin: 0;
font-size: 14px;
font-family: "Helvetica Neue", Helvetica;
}
#chart, #header, #footer {
position: absolute;
top: 0;
}
#header, #footer {
z-index: 1;
display: block;
font-size: 36px;
font-weight: 300;
text-shadow: 0 1px 0 #fff;
}
#header.inverted, #footer.inverted {
color: #fff;
text-shadow: 0 1px 4px #000;
}
#header {
top: 80px;
left: 140px;
width: 1000px;
}
#footer {
top: 680px;
right: 140px;
text-align: right;
}
rect {
fill: none;
pointer-events: all;
}
pre {
font-size: 18px;
}
line {
stroke: #000;
stroke-width: 1.5px;
}
.string, .regexp {
color: #f39;
}
.keyword {
color: #00c;
}
.comment {
color: #777;
font-style: oblique;
}
.number {
color: #369;
}
.class, .special {
color: #1181B8;
}
a:link, a:visited {
color: #000;
text-decoration: none;
}
a:hover {
color: #666;
}
.hint {
position: absolute;
right: 0;
width: 1280px;
font-size: 12px;
color: #999;
}
.node circle {
cursor: pointer;
stroke-width: 1.5px;
}
.node text {
font-size: 11px;
}
path.link {
fill: none;
stroke: #ccc;
stroke-width: 1.5px;
}
div.tooltip {
position: absolute; /* reference for measurement */
text-align: left;
pointer-events: none; /* 'none' tells the mouse to ignore the rectangle */
background-color:rgba(255,255,255,0.8) !important;
/*width: 400px;*/
width: 200px;
/*height: 165px;*/
height:100px;
padding: 10px;
border: 1px solid #D5D5D5;
font-family: arial,helvetica,sans-serif;
position: absolute;
font-size: 1.1em;
color: #333;
padding: 10px;
border-radius: 3px;
background: rgba(255,255,255,0.9);
color: #000;
box-shadow: 0 1px 5px rgba(0,0,0,0.4);
-moz-box-shadow: 0 1px 5px rgba(0,0,0,0.4);
border:1px solid rgba(200,200,200,0.85);
z-index:20000000000 !important;
/*opacity:100 !important;
-ms-opacity:1 !important;*/
}
div.tooltipTail {
position: absolute;
left:-7px;
top: 72px;
width: 7px;
height: 13px;
background: url("images/tail_white.png") 50% 0%;
}
div.toolTipBody {
position:absolute;
height:100px;
width:230px;
}
div.header {
text-transform: uppercase;
text-align: left;
font-size: 14px;
margin-bottom: 2px;
color:#666;
text-align:center;
}
div.header-rule{
height:1px;
margin:1px auto 3px;
margin-top:7px;
margin-bottom:7px;
background:#ddd;
width:125px;
}
div.header1{
text-transform: uppercase;
text-align: left;
font-size: 12px;
margin-bottom: 2px;
color:#333;
text-align:center;
}
div.header2{
color:#000;
/* text-transform:uppercase;*/
font-size: 11px;
text-align:center;
font-style:italic;
}
div.header3 {
text-align: left;
font-size: 11px;
/* width:170px;*/
text-align:center;
}
div.header4 {
/* position:absolute;*/
text-align:center;
right:10px;
top:28px;
font-size: 16px;
/* width:100px;*/
text-align:center;
overflow:hidden;
font-weight:bold;
}
/* Navigation */
.nytg-navBar {
border-top: solid 1px #DDD;
padding: 15px 0 0;
margin: 0 10px;
z-index: 100;
position: absolute;
width: 950px;
}
.nytg-navigation {
}
.nytg-navigation li {
color: #999;
font-size: 14px;
cursor: pointer;
float: left;
padding: 10px 18px;
border-top: solid 1px #CCC;
border-bottom: solid 1px #CCC;
border-left: solid 1px #CCC;
background: #f9f9f9;
margin: 0 0;
}
.nytg-navigation li:first-of-type{
border-radius: 4px 0 0 4px;
}
.nytg-navigation li:last-of-type{
border-right: solid 1px #CCC;
border-radius: 0 4px 4px 0;
}
.nytg-navigation li.selected {
color: #000;
background: #e9e9e9;
border-color: #AAA;
box-shadow: inset 0px 0px 4px rgba(0,0,0,0.2);
}
.nytg-navigation li.selected {
color: #000;
background: #e9e9e9;
border-color: #AAA;
box-shadow: inset 0px 0px 4px rgba(0,0,0,0.2);
}
div.selected {
color: #000;
background: #e9e9e9;
border-color: #AAA;
box-shadow: inset 0px 0px 4px rgba(0,0,0,0.2);
padding-bottom:10px;
}