]> nos-oignons.net Git - graphnion.git/blob - graphnion.js
Remove unused labelRadius variable.
[graphnion.git] / graphnion.js
1 (function(window){
2     'use strict';
3
4     /*global define, module, exports, require */
5     var Graphnion = {};
6
7     Graphnion.pie = function (selector, options) {
8         return new GraphnionPie(selector, options);
9     };
10
11
12     /**
13      * Pie graphs
14      */
15
16     function GraphnionPie(selector, options) {
17
18         // Default settings
19         var defaults = {
20             type: 'consensus',
21             size : 150,
22             colors : {
23                 relays : "#111",
24                 others : "#666"
25             }
26         }
27         // main element
28         this.selector = selector;
29
30         // option cache
31         this.options = {};
32         options = options || {};
33
34         this.options.type = options.type || defaults.type;
35         this.options.size = options.size || defaults.size;
36         this.options.colors = options.colors || defaults.colors;
37         this.options.onionoo = options.onionoo;
38
39
40         // initialize some attributes
41         this.init();
42         this.callOnionoo();
43     }
44
45     Graphnion.version = "0.1";
46
47     GraphnionPie.prototype = {
48         constructor: GraphnionPie,
49
50         init : function() {
51             var self = this;
52
53             this.radius = this.options.size / 2,
54             this.formatPercent = d3.format(".2%");
55             this.arc = d3.svg.arc()
56                 .outerRadius(this.radius - (this.options.size / 10))
57                 .innerRadius(this.radius - (this.options.size / 4));
58
59             this.pie = d3.layout.pie()
60                 .sort(null)
61                 .value(function(d) { return d.frac; });
62
63             switch (this.options.type) {
64                 case 'consensus':
65                     this.field = "consensus_weight_fraction";
66                     break;
67                 case 'guard':
68                     this.field = "guard_probability";
69                     break;
70                 case 'middle':
71                     this.field = "middle_probability";
72                     break;
73                 case 'exit':
74                     this.field= "exit_probability";
75                     break;
76             }
77         },
78
79         draw : function(frac) {
80             var self = this;
81
82             var data = [
83                 {
84                     frac: frac,
85                     color: this.options.colors.relays
86                 },
87                 {
88                     frac: (1 - frac),
89                     color: this.options.colors.others
90                 }
91             ];
92
93             var svg = d3.select(this.selector).append("svg")
94                 .style("margin", "auto")
95                 .attr("width", this.options.size)
96                 .attr("height", this.options.size)
97                 .append("g")
98                 .attr("transform", "translate(" + this.options.size / 2 + "," + this.options.size / 2 + ")");
99
100
101             var text = svg.append("text")
102                 .attr("text-anchor", "middle")
103                 .attr("dy", ".35em")
104                 .text(this.formatPercent(frac));
105
106             var g = svg.selectAll(".arc")
107                 .data(this.pie(data))
108                 .enter()
109                     .append("g")
110                     .attr("class", "arc");
111
112             g.append("path")
113                 .attr("d", this.arc)
114                 .style("fill", function(d) { return d.data.color; });
115
116         },
117
118         callOnionoo : function() {
119             var self = this;
120
121             // Create Onionoo url
122             var url = "https://onionoo.torproject.org/details?type=relay&fields=fingerprint,nickname," + this.field;
123             if (typeof this.options.onionoo.contact !== 'undefined') {
124                 url += "&contact=" + this.options.onionoo.contact;
125             }
126             else if (typeof this.options.onionoo.family !== 'undefined') {
127                 url += "&family=" + this.options.onionoo.family;
128             }
129
130             // Load data, and draw graph
131             d3.json(url, function(error, data) {
132                 if (error) return console.warn(error);
133
134                 var frac = self.computeData(data);
135                 self.draw(frac);
136             });
137         },
138
139         computeData : function(rawData) {
140             var self = this;
141
142             var frac = 0;
143             rawData['relays'].forEach(function(d) {
144                 frac += d[self.field];
145             });
146             return frac;
147         }
148
149     }
150
151
152     if (typeof define === 'function' && define.amd) {
153         define("Graphnion", ["d3"], Graphnion);
154     } else if ('undefined' !== typeof exports && 'undefined' !== typeof module) {
155         module.exports = Graphnion;
156     } else {
157         window.Graphnion = Graphnion;
158     }
159
160 })(window);