|
readme(document.getElementById("readme")); |
|
|
|
var chartElem = d3.select("body #chart"); |
|
|
|
var yAxisLabel = ["Number of PPR Sales","PPR Median Price (€)"]; |
|
|
|
//Pop up tip when floating over bar |
|
var tip = d3.tip().attr('class', 'd3-tip').offset([ -10, 0 ]).html(tipHtml); |
|
|
|
var margin = { |
|
top : 20, |
|
right : 60, |
|
bottom : 30, |
|
left : 40 |
|
}, width = 960 - margin.left - margin.right, height = 500 - margin.top |
|
- margin.bottom; |
|
|
|
var x0 = d3.scale.ordinal().rangeRoundBands([ 0, width ], .1); |
|
var x1 = d3.scale.ordinal(); |
|
var y = d3.scale.linear().range([ height, 0 ]); |
|
var color = d3.scale.ordinal().range(pinColours()); |
|
var xAxis = d3.svg.axis().scale(x0).orient("bottom"); |
|
var yAxis = d3.svg.axis().scale(y).orient("left") |
|
.tickFormat(d3.format(".2s")) |
|
.tickSize(-width, 0, 0); |
|
|
|
var dataSets = mungeData(), colNames, rowName, data; |
|
|
|
// default selections |
|
var selectedRegion = parseParamWithDefault('r',['ireland','dublin', 'exdublin']); |
|
var selectedPeriod = parseParamWithDefault('p',['month','quarter']); |
|
var selectedStat = parseParamWithDefault('s',['volume','median']); |
|
document.selR.selR[selectedRegion].checked = true; |
|
document.selP.selP[selectedPeriod].checked = true; |
|
document.selS.selS[selectedStat].checked = true; |
|
|
|
selectionChanged(); |
|
|
|
/** |
|
* Selection changed - remove and redo graph |
|
*/ |
|
function selRegion(r) { |
|
selectedRegion = r; |
|
selectionChanged(); |
|
} |
|
|
|
function selPeriod(p) { |
|
selectedPeriod = p; |
|
selectionChanged(); |
|
} |
|
|
|
function selStat(s) { |
|
selectedStat = s; |
|
selectionChanged(); |
|
} |
|
|
|
function selectionChanged() { |
|
d3.select("svg").remove(); |
|
var selection = 6 * selectedStat + 2 * selectedRegion + selectedPeriod; |
|
data = dataSets[selection]; |
|
doSvg(); |
|
} |
|
|
|
function doSvg() { |
|
|
|
d3.select("#lastupdate").html(rowName.replace("X","").replace(/_/g, "-")); |
|
|
|
var svg = chartElem.append("svg").attr("width", |
|
width + margin.left + margin.right).attr("height", |
|
height + margin.top + margin.bottom).call(tip).append("g").attr( |
|
"transform", "translate(" + margin.left + "," + margin.top + ")"); |
|
|
|
x0.domain(data.map(function(d) { |
|
return d[rowName]; |
|
})); |
|
x1.domain(colNames).rangeRoundBands([ 0, x0.rangeBand() ]); |
|
y.domain([ 0, d3.max(data, function(d) { |
|
return d3.max(d.cols, function(d) { |
|
return d.value; |
|
}); |
|
}) ]); |
|
|
|
svg.append("g").attr("class", "x axis").attr("transform", |
|
"translate(0," + height + ")").call(xAxis); |
|
|
|
svg.append("g").attr("class", "y axis").call(yAxis).append("text") |
|
.attr("transform", "rotate(-90)").attr("y", 6).attr("dy", |
|
".3em").style("text-anchor", "end").text(yAxisLabel[selectedStat]); |
|
|
|
var state = svg.selectAll(".Xlabel").data(data).enter().append("g") |
|
.attr("class", "Xlabel").attr("transform", function(d) { |
|
return "translate(" + x0(d[rowName]) + ",0)"; |
|
}); |
|
|
|
state.selectAll("rect").data(function(d) { |
|
return d.cols; |
|
}).enter().append("rect").attr("width", x1.rangeBand()).attr("x", |
|
function(d) { |
|
return x1(d.name); |
|
}).attr("y", function(d) { |
|
return y(d.value); |
|
}).attr("height", function(d) { |
|
return height - y(d.value); |
|
}).style("fill", function(d) { |
|
return color(d.name); |
|
}).on('mouseover', tip.show).on('mouseout', tip.hide); |
|
|
|
var legend = svg.selectAll(".legend").data(colNames.slice().reverse()) |
|
.enter().append("g").attr("class", "legend").attr("transform", |
|
function(d, i) { |
|
return "translate(5," + i * 20 + ")"; |
|
}); |
|
|
|
legend.append("rect").attr("x", width + margin.left).attr("width", 18).attr( |
|
"height", 18).style("fill", color); |
|
|
|
legend.append("text").attr("x", width + margin.left - 6).attr("y", 9).attr("dy", |
|
".35em").style("text-anchor", "end").text(function(d) { |
|
return d; |
|
}); |
|
|
|
} |
|
|
|
|
|
function tipHtml(d) { |
|
var s = "<span class='h'>" + d.name + ":</span> <span class='v'>" + d.value + "</span>"; |
|
// Include YoY value if any |
|
if (d.yoy != "") { |
|
s += "<br><span class='h'>YoY:</span> <span class='" |
|
+ (d.yoy.charAt(0) == '+' ? "vp" : "vm") + "'>" + d.yoy + "</span>";} |
|
return s; |
|
} |
|
|
|
|
|
function mungeData(sheet) { |
|
|
|
|
|
var dataSets = []; |
|
var yoyFormat = d3.format("+.0f"); |
|
|
|
var pprNames = ["VolIrlM","VolIrlQ","VolDubM","VolDubQ","VolXdbM","VolXdbQ", |
|
"MedIrlM","MedIrlQ","MedDubM","MedDubQ","MedXdbM","MedXdbQ"]; |
|
pprNames.forEach(function (n) { |
|
var pprName = "PPR" + n + ".csv"; |
|
var sheet = extractGistData(gistData[pprName].content); |
|
colNames = sheet.colNames; |
|
rowName = sheet.rowName; |
|
var data = sheet.data; |
|
data.forEach(function(d) { |
|
d.cols = colNames.map(function(name) { |
|
var idx = colNames.indexOf(name); |
|
// calculate YoY for years after first |
|
var value = +d[name].replace(',',''); |
|
var yoy = idx > 0 ? yoyFormat(value / d[colNames[idx - 1]].replace(',','') |
|
* 100 - 100) |
|
+ "%" : ""; |
|
return { |
|
name : name, |
|
value : value, |
|
yoy : yoy |
|
}; |
|
}); |
|
}); |
|
dataSets.push(data); |
|
}); |
|
|
|
return dataSets; |
|
|
|
} |