|
<!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> |
In the svg there are two layers, republic and northernireland. If you merge them into one layer called "ireland" and then change the code at lines 354 and 359 to read "ireland" instead of "republic" it should work.