]> nos-oignons.net Git - graphnion.git/commitdiff
Refactor Pie charts.
authoropi <opi@no-log.org>
Tue, 10 Mar 2015 23:45:02 +0000 (00:45 +0100)
committeropi <opi@no-log.org>
Tue, 10 Mar 2015 23:45:02 +0000 (00:45 +0100)
graphnion.js [new file with mode: 0644]

diff --git a/graphnion.js b/graphnion.js
new file mode 100644 (file)
index 0000000..b4ac1a6
--- /dev/null
@@ -0,0 +1,161 @@
+(function(window){
+    'use strict';
+
+    /*global define, module, exports, require */
+    var Graphnion = {};
+
+    Graphnion.pie = function (selector, options) {
+        return new GraphnionPie(selector, options);
+    };
+
+
+    /**
+     * Pie graphs
+     */
+
+    function GraphnionPie(selector, options) {
+
+        // Default settings
+        var defaults = {
+            type: 'consensus',
+            size : 150,
+            colors : {
+                relays : "#111",
+                others : "#666"
+            }
+        }
+        // main element
+        this.selector = selector;
+
+        // option cache
+        this.options = {};
+        options = options || {};
+
+        this.options.type = options.type || defaults.type;
+        this.options.size = options.size || defaults.size;
+        this.options.colors = options.colors || defaults.colors;
+        this.options.onionoo = options.onionoo;
+
+
+        // initialize some attributes
+        this.init();
+        this.callOnionoo();
+    }
+
+    Graphnion.version = "0.1";
+
+    GraphnionPie.prototype = {
+        constructor: GraphnionPie,
+
+        init : function() {
+            var self = this;
+
+            this.radius = this.options.size / 2,
+            this.labelRadius = this.radius - (this.options.size / 10)
+            this.formatPercent = d3.format(".2%");
+            this.arc = d3.svg.arc()
+                .outerRadius(this.radius - (this.options.size / 10))
+                .innerRadius(this.radius - (this.options.size / 4));
+
+            this.pie = d3.layout.pie()
+                .sort(null)
+                .value(function(d) { return d.frac; });
+
+            switch (this.options.type) {
+                case 'consensus':
+                    this.field = "consensus_weight_fraction";
+                    break;
+                case 'guard':
+                    this.field = "guard_probability";
+                    break;
+                case 'middle':
+                    this.field = "middle_probability";
+                    break;
+                case 'exit':
+                    this.field= "exit_probability";
+                    break;
+            }
+        },
+
+        draw : function(frac) {
+            var self = this;
+
+            var data = [
+                {
+                    frac: frac,
+                    color: this.options.colors.relays
+                },
+                {
+                    frac: (1 - frac),
+                    color: this.options.colors.others
+                }
+            ];
+
+            var svg = d3.select(this.selector).append("svg")
+                .style("margin", "auto")
+                .attr("width", this.options.size)
+                .attr("height", this.options.size)
+                .append("g")
+                .attr("transform", "translate(" + this.options.size / 2 + "," + this.options.size / 2 + ")");
+
+
+            var text = svg.append("text")
+                .attr("text-anchor", "middle")
+                .attr("dy", ".35em")
+                .text(this.formatPercent(frac));
+
+            var g = svg.selectAll(".arc")
+                .data(this.pie(data))
+                .enter()
+                    .append("g")
+                    .attr("class", "arc");
+
+            g.append("path")
+                .attr("d", this.arc)
+                .style("fill", function(d) { return d.data.color; });
+
+        },
+
+        callOnionoo : function() {
+            var self = this;
+
+            // Create Onionoo url
+            var url = "https://onionoo.torproject.org/details?type=relay&fields=fingerprint,nickname," + this.field;
+            if (typeof this.options.onionoo.contact !== 'undefined') {
+                url += "&contact=" + this.options.onionoo.contact;
+            }
+            else if (typeof this.options.onionoo.family !== 'undefined') {
+                url += "&family=" + this.options.onionoo.family;
+            }
+
+            // Load data, and draw graph
+            d3.json(url, function(error, data) {
+                if (error) return console.warn(error);
+
+                var frac = self.computeData(data);
+                self.draw(frac);
+            });
+        },
+
+        computeData : function(rawData) {
+            var self = this;
+
+            var frac = 0;
+            rawData['relays'].forEach(function(d) {
+                frac += d[self.field];
+            });
+            return frac;
+        }
+
+    }
+
+
+    if (typeof define === 'function' && define.amd) {
+        define("Graphnion", ["d3"], Graphnion);
+    } else if ('undefined' !== typeof exports && 'undefined' !== typeof module) {
+        module.exports = Graphnion;
+    } else {
+        window.Graphnion = Graphnion;
+    }
+
+})(window);
\ No newline at end of file