Shows the distribution of browsers and browser versions of Greasemonkey users over the past 30 days. Data from addons.mozilla.org, and massaged to a usable format by Yahoo Pipes.
xxxxxxxxxx
<html>
<head>
<title>Greasemonkey users by browser version</title>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/d3@1.29.5/d3.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/d3@1.29.5/d3.layout.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/d3@1.29.5/d3.time.js"></script>
<script type="text/javascript" src="amo.js"></script>
<style type="text/css">
svg {
width: 960px;
height: 500px;
border: solid 1px #ccc;
font: 10px sans-serif;
shape-rendering: crispEdges;
}
body, html { margin: 0; }
</style>
</head>
<body>
<script type="text/javascript">
var w = 960
, h = 500
, a = 748 // Greasemonkey
, d = 30 // number of days
, p = [20, 50, 30, 20]
, x = d3.scale.ordinal().rangeRoundBands([0, w - p[1] - p[3]])
, y = d3.scale.linear().range([0, h - p[0] - p[2]])
, z = d3.scale.category20c()
, legend = d3.time.format("%Y-%m-%d")
, data, folded; // for ease of peeking at the input data from the js console
var svg = d3.select("body").append("svg:svg")
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("transform", "translate(" + p[3] + "," + (h - p[2]) + ")");
get_amo_stats(got_amo_stats, a, d);
function got_amo_stats(stats) {
folded = fold_by(data = stats/*, /([^\/]+)\// */);
var apps = Object.keys(folded[0]).filter(function(n) { return /[A-Z]/.test(n); });
draw(folded, apps);
}
// stats: an object with some keys on a "Browser/maj[.min[.build[...]]]" format
// output: ditto but with [.build[...]] keys rolled into "Browser/major" keys
// regexp: if given, a regexp whose first match group defines how to fold keys
// (example: /^(.*\/(?:0|[1-9]\d*\.?\d*))/ folds into x/0, x/1.0, ...)
function fold_by(stats, regexp) {
function fold(obj) {
var data = {}, renamed, key, val;
for (key in obj) {
val = obj[key];
if ((renamed = rename(key)))
data[renamed] = (data[renamed] || 0) + val;
else
data[key] = val;
}
return data;
}
var want = regexp || /^(.*\/\d+)/ // /^(.*\/(?:0|[1-9]\d*\.?\d*))/
, rename = function(k) { var m = want.exec(k); return m && m[1]; };
return stats.map(fold);
}
function draw(data, keys) {
// Transpose the data into layers by browser name+version.
var names = d3.layout.stack()(keys.map(function(key) {
return data.map(function(d) {
return { x: d.date, y: d[key], n: key };
});
}));
// Compute the x-domain (by date) and y-domain (by top).
x.domain(names[0].map(function(d) { return d.x; }));
y.domain([0, d3.max(names[names.length - 1], function(d) { return d.y0 + d.y; })]);
// Add a group for each browser version
var key = svg.selectAll("g.key")
.data(names)
.enter().append("svg:g")
.attr("class", "key")
.style("fill", function(d, i) { return z(i); })
.style("stroke", function(d, i) { return d3.rgb(z(i)).darker(); });
// ...with a browser name tooltip.
key.append("svg:title").text(function(d) { return d[0].n; });
// Add a rect for each date.
var rect = key.selectAll("rect")
.data(Object)
.enter().append("svg:rect")
.attr("x", function(d) { return x(d.x); })
.attr("y", function(d) { return -y(d.y0) - y(d.y); })
.attr("height", function(d) { return y(d.y); })
.attr("width", x.rangeBand());
// Add a label per date.
var label = svg.selectAll("text")
.data(x.domain())
.enter().append("svg:text")
.attr("x", function(d) { return x(d) + x.rangeBand() / 2; })
.attr("y", 6)
.attr("text-anchor", "middle")
.attr("dy", ".71em")
.text(legend);
// Add y-axis rules.
var rule = svg.selectAll("g.rule")
.data(y.ticks(5))
.enter().append("svg:g")
.attr("class", "rule")
.attr("transform", function(d) { return "translate(0," + -y(d) + ")"; });
rule.append("svg:line")
.attr("x2", w - p[1] - p[3])
.style("stroke", function(d) { return d ? "#fff" : "#000"; })
.style("stroke-opacity", function(d) { return d ? .7 : null; });
rule.append("svg:text")
.attr("x", w - p[1] - p[3] + 6)
.attr("dy", ".35em")
.text(d3.format(",d"));
}
</script>
</body>
</html>
Modified http://mbostock.github.com/d3/d3.js?1.29.1 to a secure url
Modified http://mbostock.github.com/d3/d3.layout.js?1.29.1 to a secure url
Modified http://mbostock.github.com/d3/d3.time.js?1.29.1 to a secure url
https://mbostock.github.com/d3/d3.js?1.29.1
https://mbostock.github.com/d3/d3.layout.js?1.29.1
https://mbostock.github.com/d3/d3.time.js?1.29.1