|
"use strict"; |
|
|
|
var inputUrl = "https://input.mozilla.org/api/v1/feedback/?happy=1&date_delta=1d&format=json"; |
|
var width = 420, |
|
barHeight = 20; |
|
|
|
var x = d3.scale.linear() |
|
.range([0, width]); |
|
|
|
var chart = d3.select(".chart") |
|
.attr("width", width); |
|
|
|
var last = d3.select(".last"); |
|
|
|
var barsSVG = chart.append('g') |
|
.classed('bars', true); |
|
var labelsSVG = chart.append('g') |
|
.classed('labels', true); |
|
|
|
var updateData = function() { |
|
var url = inputUrl + '&foo=' + Date.now(); |
|
|
|
d3.json(url, function(error, data) { |
|
var productData; |
|
|
|
console.log(error); |
|
console.log(data); |
|
|
|
// Make an aggregator that splits data by product name, and then reduces |
|
// the groups by counting the number of elements in it. |
|
var aggregator = d3.nest() |
|
.key(function(d) { |
|
return d.product = d.product || 'Unknown'; |
|
}) |
|
.rollup(function(group) { |
|
return {name: group[0].product, value: group.length}; |
|
}); |
|
|
|
// Apply the aggregator and retrieve values. Add Total. Sort |
|
// by length. |
|
productData = aggregator.map(data.results, d3.map).values(); |
|
productData.push({name: 'Total', value: data.count}) |
|
productData.sort(function(a, b) { return d3.descending(a.value, b.value); }); |
|
|
|
console.log('data', productData); |
|
|
|
x = x.domain([0, d3.max(productData, function(d) { return d.value; })]); |
|
|
|
// Data join |
|
var bars = barsSVG.selectAll('rect').data(productData); |
|
var labels = labelsSVG.selectAll('text').data(productData); |
|
var recent = last.selectAll('div') |
|
.data(data.results.slice(0, 10).reverse(), function(d) { return d.created + d.description; }); |
|
|
|
// Enter |
|
bars.enter() |
|
.append('rect'); |
|
labels.enter() |
|
.append('text'); |
|
recent.enter() |
|
.insert('div', ':first-child') |
|
.style('opacity', 0) |
|
.transition() |
|
.duration(2000) |
|
.text(function (d) { return d.created + ': ' + d.description; }) |
|
.style('opacity', 1); |
|
|
|
// Update |
|
bars.attr('x', 0) |
|
.attr('y', function(d, i) { return i * barHeight; }) |
|
.attr("height", barHeight - 1) |
|
.attr("width", 0) |
|
.transition() |
|
.attr("width", function(d) { return x(d.value); }); |
|
|
|
labels.attr("x", function(d) { return 5; }) |
|
.attr("y", function(d, i) { return (i + 0.6) * barHeight; }) |
|
.text(function(d) { return d.name + ': ' + d.value; }) |
|
.style('text-anchor', 'middle-left'); |
|
|
|
// Exit |
|
bars.exit() |
|
.transition() |
|
.attr("width", 0) |
|
.remove(); |
|
labels.exit().remove(); |
|
recent.exit().remove(); |
|
}); |
|
}; |
|
|
|
updateData(); |
|
|
|
// Pulls recent data every 2 minutes. |
|
setInterval(updateData, 120000); |