|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<!-- thanks to http://carisenda.com/sandbox/choropleth/ --> |
|
|
|
<meta charset="utf-8" /> |
|
<title>Irish Sporthorse Foal Registrations</title> |
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script> |
|
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.min.js"></script> |
|
|
|
<link href='https://fonts.googleapis.com/css?family=Carrois+Gothic' rel='stylesheet' type='text/css'> |
|
|
|
<style type="text/css" media="screen"> |
|
body, html { |
|
font-family: 'Carrois Gothic', sans-serif; |
|
padding: 0; |
|
margin: 0; |
|
background-color: #fff; |
|
} |
|
|
|
#container { |
|
width: 800px; |
|
margin-left: auto; |
|
margin-right: auto; |
|
} |
|
h1 { |
|
text-align: center; |
|
} |
|
|
|
ul { |
|
list-style: none; |
|
margin-left: 0; |
|
padding-left: 1em; |
|
text-indent: -1em; |
|
} |
|
|
|
.year_label, .year_total { |
|
fill: black; |
|
text-align:center; |
|
font-family: 'Carrois Gothic', sans-serif; |
|
font-size: 18px; |
|
} |
|
.year_total { |
|
|
|
font-size: 12px; |
|
} |
|
|
|
.slide { |
|
fill: rgb(247,251,255); |
|
} |
|
|
|
|
|
.enabled { |
|
fill: rgb(238,238,238); |
|
color: black; |
|
} |
|
|
|
.bar { |
|
background: red; |
|
} |
|
.county_list { |
|
background: #6bdd8d; |
|
font-size: 12px; |
|
margin: 1px; |
|
padding: 2px; |
|
} |
|
#map, #stats, #selectbar { |
|
float:left; |
|
} |
|
|
|
#stats { |
|
width: 200px; |
|
} |
|
|
|
#nav { |
|
height: 140px; |
|
vertical-align: bottom; |
|
} |
|
|
|
.slide_txt_val { |
|
vertical-align: bottom; |
|
font-size: smaller; |
|
} |
|
.big_year { |
|
font: 200 60px "Helvetica Neue"; |
|
fill: #ddd; |
|
} |
|
|
|
#selectbar { |
|
opacity: 0; |
|
} |
|
|
|
</style> |
|
|
|
</head> |
|
<body> |
|
<!--<h1>Sporthorse Foal Registrations</h1>--> |
|
<div id="container"> |
|
<div id="nav"></div> |
|
<div id="selectbar"> |
|
Breed code<br />Sire's Breedcode |
|
</div> |
|
<div id="map"> |
|
</div> <!-- map --> |
|
|
|
<div id="stats"></div> |
|
</div> |
|
<script> |
|
|
|
var w = 700, |
|
bar_h = 100, // height of div holding bars |
|
bar_top_margin = 30, // space above top of highest bar |
|
bar_padding = 10; // width between bars + padding |
|
default_height = 30; // default height of top bar |
|
|
|
d3.csv("foalreg.csv", function(csv) { |
|
|
|
// load and organise data |
|
|
|
// clean data |
|
csv.forEach(function(v) { |
|
v.year = parseInt(v.year); |
|
v.foals = parseInt(v.foals); |
|
v.mares = parseInt(v.mares); |
|
v.coverings = parseInt(v.coverings); |
|
}); |
|
|
|
// create crossfilter |
|
var cf = crossfilter(csv); |
|
|
|
// create dimensions |
|
cf.county = cf.dimension(function(d) { return d.county; }); |
|
cf.year = cf.dimension(function(d) { return d.year; }); |
|
cf.foals = cf.dimension(function(d) { return d.foals; }); |
|
|
|
// totals by year |
|
var t1 = cf.year.group() |
|
.reduceSum(function(d) { return d.foals; }) |
|
.top(Infinity); |
|
|
|
// convert to an associative array |
|
var year_foals = new Array(); |
|
t1.forEach(function(v) { |
|
year_foals[v.key] = v.value; |
|
}) |
|
|
|
console.log('cf.county.top(3)', cf.county.top(3)); |
|
|
|
// load svg map |
|
d3.xml("ireland.svg", "image/svg+xml", function(xml) { |
|
var importedNode = document.importNode(xml.documentElement, true); |
|
d3.select("div#map") |
|
.each(function() { |
|
this.appendChild(importedNode); |
|
}) |
|
drawYearBars(cf); |
|
updateChart(cf, 1999); |
|
}); |
|
|
|
//////////////////////////////////////////////////////////////////////////////////////// |
|
//////////////////////////////////////////////////////////////////////////////////////// |
|
//////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
function drawYearBars(cf) { |
|
|
|
// create histogram/tabs at top |
|
var year_range = [1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011]; |
|
|
|
// get a list of the years for which there is data |
|
var yrs = cf.year.group() |
|
.reduceSum(function(d) { return d.foals; }) |
|
.top(Infinity) |
|
|
|
var got_years = new Array(); |
|
|
|
yrs.forEach(function(v) { |
|
got_years[v.key] = v.value; |
|
}) |
|
|
|
// scale for histogram |
|
var bar_height = d3.scale.linear() |
|
.domain([0, d3.max(yrs, function(d) { return d.value; })]) |
|
.range([0, bar_h]); |
|
|
|
var bar_width = ( w / (year_range.length-1) ) - bar_padding; |
|
|
|
var bar_xpos = d3.scale.linear() |
|
.domain([0, year_range.length]) |
|
.range([0, w]); |
|
|
|
var tabs = d3.select("#nav") |
|
.append("svg") |
|
.attr("width", w) |
|
.attr("height", bar_h + 40); |
|
|
|
tabs.selectAll("rect") |
|
.data(year_range) |
|
.enter().append("rect") |
|
.attr("x", function(d, i) { return bar_xpos(i); }) |
|
.attr("y", function(d) { |
|
if (got_years[d] != undefined) { |
|
return bar_h + bar_top_margin - bar_height(got_years[d]); |
|
} else { |
|
return bar_h + bar_top_margin - default_height;} |
|
}) |
|
.attr("height", function(d) { |
|
if (got_years[d] != undefined) { |
|
return bar_height(got_years[d]); |
|
} else { |
|
return default_height;} |
|
}) |
|
.attr("width", bar_width) |
|
.attr("id", function(d) { return d; }) |
|
.attr("class", function(d) { |
|
var cls = "slide"; |
|
if (d in got_years) { |
|
cls += " enabled"; |
|
} |
|
return cls; |
|
}) |
|
.on('mouseover', function() { |
|
if (got_years[this.id] != undefined) { |
|
d3.select(this).style("fill", "#6bdd8d"); |
|
updateChart(cf, this.id); |
|
} |
|
}) |
|
.on("mouseout", function(){ |
|
if (got_years[this.id] != undefined) { |
|
d3.select(this).style("fill", "rgb(238,238,238)"); |
|
} |
|
}) |
|
|
|
// add year labels |
|
tabs.selectAll(".year_label") |
|
.data(year_range) |
|
.enter() |
|
.append("text") |
|
.text(function(d) { return d; }) |
|
.attr("class", "year_label") |
|
.attr("text-anchor", "middle") |
|
.attr("x", function(d, i) { |
|
return bar_xpos(i+1) - (bar_width/2) - (bar_padding/2); |
|
}) |
|
.attr("y", function() { |
|
return (bar_h + bar_top_margin - 10 ); |
|
}); |
|
|
|
// add value labels |
|
tabs.selectAll(".year_total") |
|
.data(year_range) |
|
.enter() |
|
.append("text") |
|
.text(function(d) { |
|
if (got_years[d] != undefined) { |
|
return got_years[d]; |
|
} else { |
|
return ''} |
|
}) |
|
.attr("class", "year_total") |
|
.attr("text-anchor", "middle") |
|
.attr("x", function(d, i) { return bar_xpos(i+1) - (bar_width/2) - (bar_padding/2); }) |
|
.attr("y", function(d) { |
|
if (got_years[d] != undefined) { |
|
return bar_h + bar_top_margin - 5 - bar_height(got_years[d] ) ; |
|
} else { |
|
return 0;} |
|
}); |
|
} |
|
|
|
function updateChart(cf, year) { |
|
|
|
var total_foals, |
|
data, |
|
t, |
|
ext, |
|
color, |
|
map, |
|
countiesRepublic, |
|
countiesNI; |
|
|
|
updateMap(cf, year); |
|
|
|
var county_data = cf.foals.top(Infinity); |
|
var ext = [0, 900]; |
|
var county_scale = d3.scale.linear() |
|
.domain(ext) |
|
.range([0, 150]); |
|
|
|
// show top counties list |
|
d3.select("#stats") |
|
.selectAll("div") |
|
.remove(); |
|
|
|
var list = d3.select("#stats") |
|
.selectAll("div") |
|
.data(county_data) |
|
|
|
list |
|
.enter() |
|
.append("div") |
|
.attr("class", "county_list") |
|
.attr("id", function(d) { return d.county + d.year;}) |
|
.text(function(d) { |
|
return toProper(d.county); }) |
|
.call(div_bar); |
|
|
|
list |
|
.exit().remove(); |
|
|
|
|
|
function div_bar() { |
|
this |
|
.style("height", "16px") |
|
.style('white-space', 'nowrap') |
|
.style("width", function(d) { |
|
return county_scale(d.foals)+"px"; |
|
}) |
|
} |
|
|
|
// put the year selected on the map |
|
d3.select(".big_year").remove(); |
|
|
|
var year = d3.select("#ireland").append("text") |
|
.attr("class", "big_year") |
|
.attr("text-anchor", "end") |
|
.attr("y", 490) |
|
.attr("x", 360) |
|
.text(year); |
|
|
|
setCountyBarMouseoverEvent(cf); |
|
|
|
} |
|
|
|
function updateMap (cf, year) { |
|
cf.year.filterExact(year); |
|
total_foals = cf.county.group() |
|
.reduceSum(function(d) { return d.foals;}) |
|
.top(Infinity); |
|
|
|
data = cf.county.top(Infinity); |
|
|
|
t = cf.foals.groupAll().value(); |
|
|
|
ext = d3.extent(data, function(d) { return d.foals; }); |
|
ext = [0,1000]; |
|
|
|
color = d3.scale.linear() |
|
.domain(ext) |
|
.range(["white", "green"]); |
|
|
|
map = d3.select('#map'); |
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////// |
|
////////////// shade the counties of the Republic of Ireland individually ///////////////// |
|
/////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
countiesRepublic = map.selectAll('path.republic') |
|
.style('fill', function(d) { // would normally use attr but svg has used style for fill |
|
|
|
var clr = "#fff"; |
|
// only look at items in the counties layer |
|
if (this.parentNode.id == "republic") { |
|
|
|
var county = this.id.toUpperCase(); |
|
|
|
data.forEach(function(v, i, ar) { |
|
if (v.county == county) { |
|
clr = color(v.foals) |
|
} |
|
}); |
|
} |
|
return clr; |
|
|
|
}); |
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////// |
|
/////////////////// shade the counties of Northern Ireland together /////////////////////// |
|
/////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
countiesNI = map.selectAll('path.northernireland') |
|
.style('fill', function(d) { // would normally use attr but svg has used style for fill |
|
|
|
var clr = "#fff"; |
|
// only look at items in the counties layer |
|
if (this.parentNode.id == "northernireland") { |
|
|
|
var county = this.id.toUpperCase(); |
|
|
|
data.forEach(function(v, i, ar) { |
|
if (v.county == "NORTHERN IRELAND") { |
|
clr = color(v.foals) |
|
} |
|
}); |
|
} |
|
return clr; |
|
|
|
}); |
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
} |
|
|
|
function setCountyBarMouseoverEvent (cf) { |
|
d3.selectAll('div.county_list') |
|
.on('mouseover', function(d) { |
|
// style the bar gray |
|
d3.select(this).style("background", "rgb(238,238,238)"); |
|
|
|
cf.county.filter(d.county); |
|
updateMap(cf, d.year); |
|
}) |
|
.on("mouseout", function(d) { |
|
// style the bar green again |
|
d3.select(this).style("background", "#6bdd8d"); |
|
|
|
var countyID = toProper(d.county); |
|
cf.county.filterAll(); |
|
updateMap(cf, d.year); |
|
|
|
}) |
|
} //setCountyBarMouseoverEvent |
|
|
|
}); |
|
|
|
|
|
function toProper(str) |
|
{ |
|
return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();}); |
|
} |
|
</script> |
|
</body> |
|
</html> |
And thanks for the compliment!