D3 Treemap with mouseover events to show details about each website and link to the site. PLEASE NOTE - that this is using dummy data!
xxxxxxxxxx
•
<meta charset="utf-8">
<title>Websites</title>
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
<style>
body {
font-family: "Helvetica", Helvetica, Arial, sans-serif;
font-size: 10px;
background-color: black;
}
p, .formHeading, .agency-name {
color: white
}
.formHeading {
font-size: 18px;
}
form {
position: absolute;
color: white
}
#close {
float:right;
color: white;
display:inline-block;
padding:2px 5px;
background: red;
cursor: pointer;
}
.node-website, .node-agency {
font: 10px sans-serif;
line-height: 12px;
overflow: hidden;
position: absolute;
text-indent: 2px;
cursor: pointer;
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
.node-agency, .agency-name {
pointer-events: none;
}
#tooltip {
position: absolute;
width: 220px;
height: auto;
padding: 10px;
z-index: 1;
background-color: white;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
-webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
-moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
}
#tooltip.hidden {
display: none;
}
#tooltip p {
margin: 0;
color: black;
font-family: sans-serif;
font-size: 16px;
line-height: 20px;
}
}
</style>
<body>
<div class="row">
<div class="col-md-2">
<h3 class = "formHeading">Selected sites: <strong><span id="numberofsites">0</span></strong></h3>
<br>
<h3 class = "formHeading" > Choose one or more topics:</h3>
<form id="showhidetopics" name="formTopic">
<div><label><input class = "formCheckbox" type="checkbox" name="Births-deaths-marriages"> Births, deaths, marriages</label></div>
<div><label><input class = "formCheckbox" type="checkbox" name="Citizenship-and-immigration"> Citizenship and immigration</label></div>
<div><label><input class = "formCheckbox" type="checkbox" name="Community-arts-and-sport"> Community, arts and sport</label></div>
<div><label><input class = "formCheckbox" type="checkbox" name="Consumer-rights"> Consumer rights</label></div>
<div><label><input class = "formCheckbox" type="checkbox" name="Crime-law-and-justice"> Crime, law and justice</label></div>
<div><label><input class = "formCheckbox" type="checkbox" name="Driving-and-transport"> Driving and transport</label></div>
<div><label><input class = "formCheckbox" type="checkbox" name="Education-and-training"> Education and training</label></div>
<div><label><input class = "formCheckbox" type="checkbox" name="Emergencies-and-disasters"> Emergencies and disasters</label></div>
<div><label><input class = "formCheckbox" type="checkbox" name="Environment-and-climate"> Environment and climate</label></div>
<div><label><input class = "formCheckbox" type="checkbox" name="Health"> Health</label></div>
<div><label><input class = "formCheckbox" type="checkbox" name="History-culture-and-heritage"> History, culture and heritage</label></div>
<div><label><input class = "formCheckbox" type="checkbox" name="Housing-and-property"> Housing and property</label></div>
<div><label><input class = "formCheckbox" type="checkbox" name="Internet-media-and-communication"> Internet, media and communication</label></div>
<div><label><input class = "formCheckbox" type="checkbox" name="Money-benefits-and-tax"> Money, benefits and tax</label></div>
<div><label><input class = "formCheckbox" type="checkbox" name="Parliament-and-politics"> Parliament and politics</label></div>
<div><label><input class = "formCheckbox" type="checkbox" name="Passports-travel-and-tourism"> Passports, travel and tourism</label></div>
<div><label><input class = "formCheckbox" type="checkbox" name="Work-and-jobs"> Work and jobs</label></div>
</form>
</div>
<div class="col-md-10" id="viz" ></div>
</div>
<div class="row">
<div class="col-md-6">
</div>
<div class="col-md-6">
<form>
<label><input type="radio" class="boxsize" name="mode" value="size"> Size</label>
<label><input type="radio" class="boxsize" name="mode" value="count" checked> Count</label>
</form>
</div>
</div>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script>
var buffer = 40;
var cellpadding = 1;
var windowWidth = ((window.innerWidth - buffer)/12) * 10 ;
var windowHeight = window.innerHeight - buffer - 30;
//console.log(windowWidth);
var margin = {top: 20, right: 10, bottom: 10, left: 10},
width = windowWidth - margin.left - margin.right,
height = windowHeight - margin.top - margin.bottom;
//var color = d3.scale.category20b();
//var color = d3.scale.ordinal().range([ "#efedf5", "#dadaeb", "#bcbddc", "#9e9ac8", "#807dba", "#6a51a3", "#54278f", "#3f007d"]); //colorbrewer purples
var color = d3.scale.ordinal().range([/*'rgb(229,245,224)', 'rgb(199,233,192)', 'rgb(161,217,155)', */'rgb(116,196,118)','rgb(65,171,93)','rgb(35,139,69)','rgb(0,109,44)','rgb(0,68,27)']); //colorbrewer Greens
//var highlightColor = "#de77ae";
var highlightColor = "red";
var treemap = d3.layout.treemap()
.size([width, height])
.sticky(true)
.padding(cellpadding)
.mode("squarify") //default
.value(function(d) { return 1; })
.children( function(d) { return d.values ; } );
var div = d3.select("#viz").append("div")
.style("position", "relative")
.style("width", (width + margin.left + margin.right) + "px")
.style("height", (height + margin.top + margin.bottom) + "px")
.style("left", margin.left + "px")
.style("top", margin.top + "px");
var clickCount = 0;
var mouseClick = function(d) {
var xPosition = d3.event.pageX;
var yPosition = d3.event.pageY;
// stop tooltip going off the right or bottom side of screen
if (xPosition > (width/2)) {xPosition = xPosition - 242; }
else xPosition = xPosition + 25;
if (yPosition > (height/2)) {yPosition = yPosition - 200; };
clickCount++;
d3.selectAll(".node-website").style("box-shadow", "none" );
d3.select(this)
.style("box-shadow", "inset 0 0 10px white");
d3.select("#tooltip")
.style("left", xPosition + "px")
.style("top", yPosition + "px")
.style("z-index", 100);
d3.select("#tooltip #website")
.html('<a href="https://'+ d.website +'" target="_blank">' + d.website + '</a>');
d3.select("#tooltip #agency")
.text(d.parent.key);
d3.select("#tooltip #size")
.text(d.size);
d3.select("#tooltip #screenshot") //<img src="https://localhost:8080/images/dia.png" width="220px" />
//.html('<img src="https://localhost:8080/images/http_' + d.website + '.png" width="200px" />');
.html('<img src="sample.png" width="200px" />');
d3.select("#tooltip").classed("hidden", false);
if (clickCount === 1) {
singleClickTimer = setTimeout(function() {
clickCount = 0;
}, 250); }
else if (clickCount === 2) {
clearTimeout(singleClickTimer);
clickCount = 0;
hideTooltip();
d3.selectAll(".node-website").style("box-shadow", "none" );
}
};
d3.csv("govtwebsites.csv", function (data) {
var treeData = { "key": "Government Web Domain", "values": d3.nest()
.key(function (d) { return d.Agency; })
.entries(data)
};
var node = div.datum(treeData).selectAll(".node")
.data(treemap.nodes)
.enter().append("div")
.attr("class", function(d) { return d.children ? "node-agency" : "node-website" ; })
.call(position)
.style("border", "solid 1px black")
.on("click", mouseClick);
color.domain(node.map(function(d) { return d.key ;}));
node.style("background", function(d) { return d.children ? color(d.key) : color(d.parent.key); });
d3.selectAll(".node-website")
.append("div")
.attr("class","agency-name")
.text(function(d) { if (d.y - cellpadding === d.parent.y && d.x - cellpadding === d.parent.x) {return d.parent.key ;}} )
.style("z-index", function(d) { if (d.y - cellpadding === d.parent.y && d.x - cellpadding === d.parent.x) {return 99 ;}} );
d3.selectAll(".boxsize").on("change", function change() {
hideTooltip();
var value = this.value === "count"
? function() { return 1; }
: function(d) { return d.size; };
node
.data(treemap.value(value).nodes)
.transition()
.duration(3500)
.call(position);
});
///////////////////////////////
d3.selectAll(".formCheckbox").on("change", updateNodeColors);
function updateNodeColors () {
hideTooltip();
var count = 0;
node
.transition()
.style("background", function(d) {
var matchesATopic = false,
topics = ["Births-deaths-marriages",
"Citizenship-and-immigration",
"Community-arts-and-sport",
"Consumer-rights",
"Crime-law-and-justice",
"Driving-and-transport",
"Education-and-training",
"Emergencies-and-disasters",
"Environment-and-climate",
"Health",
"History-culture-and-heritage",
"Housing-and-property",
"Internet-media-and-communication",
"Money-benefits-and-tax",
"Parliament-and-politics",
"Passports-travel-and-tourism",
"Work-and-jobs"],
topicsForm = document.forms.formTopic;
if (d.children) {
//console.log("has children " + d.key);
} else {
for (i = 0; i < topics.length; i++) {
//console.log(topics[i]);
if (topicsForm[topics[i]].checked == true) {
//console.log(d[topics[i]]);
if (d[topics[i]] == "X" ) {
matchesATopic = true;
//console.log(d.key + " " + matchesATopic);
count++;
break;
};
};
}
};
if (matchesATopic) { return highlightColor }
else return d.children ? color(d.key) : color(d.parent.key);
});
d3.select("#numberofsites").text(count);
};
});
///////////////////////////////
function hideTooltip () {
d3.select("#tooltip").classed("hidden", true);
}
function position() {
this.style("left", function(d) { return d.x + "px"; })
.style("top", function(d) { return d.y + "px"; })
.style("width", function(d) { return Math.max(0, d.dx - 1) + "px"; })
.style("height", function(d) { return Math.max(0, d.dy - 1) + "px"; });
}
</script>
<div id="tooltip" class="hidden">
<span id='close' onclick='hideTooltip()'>X</span>
<p><strong id="website"></strong></p>
<p><span id="screenshot"></span></p>
<p>Owner: <span id="agency"></span></p>
<p>Pages: <span id="size"></span></p>
</div>
</body>
Modified http://d3js.org/d3.v3.min.js to a secure url
https://code.jquery.com/jquery-1.11.0.min.js
https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js
https://d3js.org/d3.v3.min.js