d3_rails 2.7.4 → 2.7.5.v2

Sign up to get free protection for your applications and to get access to all the features.
data/.DS_Store CHANGED
Binary file
data/README.md CHANGED
@@ -14,8 +14,8 @@ or you can use it to build dynamic pages (like jQuery).
14
14
 
15
15
  # D3 Version
16
16
 
17
- The current release of this gem is using **D3 v=2.7.4**
18
- **Last Updated 2-2-2012**
17
+ The current release of this gem is using **D3 v=2.7.5**
18
+ **Last Updated 2-21-2012**
19
19
 
20
20
  # Included Javascripts
21
21
  **minified js files are not included, since the rails asset pipeline sorta necessitates the compiling (and likely minifying) your js files for production**
@@ -32,6 +32,20 @@ The current release of this gem is using **D3 v=2.7.4**
32
32
  science.lin.js
33
33
  science.stats.js
34
34
 
35
+ # D3 charting module
36
+
37
+ ** D3 charts can be be included in your rails application by including the following line in your javascripts manifest **
38
+
39
+ //= require d3_chart_module
40
+
41
+ This will include the following javascripts to your application:
42
+
43
+ box.js
44
+ bullet.js
45
+ chart.js
46
+ horizon.js
47
+ qq.js
48
+
35
49
  ### Installation
36
50
 
37
51
  This gem should work out of the box. All you have to do is add the gem to your Gemfile:
@@ -1,3 +1,3 @@
1
1
  module D3Rails
2
- VERSION = "2.7.4"
2
+ VERSION = "2.7.5.v2"
3
3
  end
data/vendor/.DS_Store ADDED
Binary file
@@ -1,5 +1,5 @@
1
- Copyright (c) 2010, Nicolas Garcia Belmonte
2
- All rights reserved
1
+ Copyright (c) 2010, Michael Bostock
2
+ All rights reserved.
3
3
 
4
4
  Redistribution and use in source and binary forms, with or without
5
5
  modification, are permitted provided that the following conditions are met:
@@ -11,17 +11,16 @@ modification, are permitted provided that the following conditions are met:
11
11
  this list of conditions and the following disclaimer in the documentation
12
12
  and/or other materials provided with the distribution.
13
13
 
14
- * Neither the name of the organization nor the names of its contributors may
15
- be used to endorse or promote products derived from this software without
16
- specific prior written permission.
14
+ * The name Michael Bostock may not be used to endorse or promote products
15
+ derived from this software without specific prior written permission.
17
16
 
18
- THIS SOFTWARE IS PROVIDED BY NICOLAS GARCIA BELMONTE ``AS IS'' AND ANY EXPRESS
19
- OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20
- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
21
- EVENT SHALL NICOLAS GARCIA BELMONTE BE LIABLE FOR ANY DIRECT, INDIRECT,
22
- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
17
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
21
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26
25
  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27
26
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,297 @@
1
+ // Inspired by http://informationandvisualization.de/blog/box-plot
2
+ d3.chart.box = function() {
3
+ var width = 1,
4
+ height = 1,
5
+ duration = 0,
6
+ domain = null,
7
+ value = Number,
8
+ whiskers = d3_chart_boxWhiskers,
9
+ quartiles = d3_chart_boxQuartiles,
10
+ tickFormat = null;
11
+
12
+ // For each small multiple…
13
+ function box(g) {
14
+ g.each(function(d, i) {
15
+ d = d.map(value).sort(d3.ascending);
16
+ var g = d3.select(this),
17
+ n = d.length,
18
+ min = d[0],
19
+ max = d[n - 1];
20
+
21
+ // Compute quartiles. Must return exactly 3 elements.
22
+ var quartileData = d.quartiles = quartiles(d);
23
+
24
+ // Compute whiskers. Must return exactly 2 elements, or null.
25
+ var whiskerIndices = whiskers && whiskers.call(this, d, i),
26
+ whiskerData = whiskerIndices && whiskerIndices.map(function(i) { return d[i]; });
27
+
28
+ // Compute outliers. If no whiskers are specified, all data are "outliers".
29
+ // We compute the outliers as indices, so that we can join across transitions!
30
+ var outlierIndices = whiskerIndices
31
+ ? d3.range(0, whiskerIndices[0]).concat(d3.range(whiskerIndices[1] + 1, n))
32
+ : d3.range(n);
33
+
34
+ // Compute the new x-scale.
35
+ var x1 = d3.scale.linear()
36
+ .domain(domain && domain.call(this, d, i) || [min, max])
37
+ .range([height, 0]);
38
+
39
+ // Retrieve the old x-scale, if this is an update.
40
+ var x0 = this.__chart__ || d3.scale.linear()
41
+ .domain([0, Infinity])
42
+ .range(x1.range());
43
+
44
+ // Stash the new scale.
45
+ this.__chart__ = x1;
46
+
47
+ // Note: the box, median, and box tick elements are fixed in number,
48
+ // so we only have to handle enter and update. In contrast, the outliers
49
+ // and other elements are variable, so we need to exit them! Variable
50
+ // elements also fade in and out.
51
+
52
+ // Update center line: the vertical line spanning the whiskers.
53
+ var center = g.selectAll("line.center")
54
+ .data(whiskerData ? [whiskerData] : []);
55
+
56
+ center.enter().insert("svg:line", "rect")
57
+ .attr("class", "center")
58
+ .attr("x1", width / 2)
59
+ .attr("y1", function(d) { return x0(d[0]); })
60
+ .attr("x2", width / 2)
61
+ .attr("y2", function(d) { return x0(d[1]); })
62
+ .style("opacity", 1e-6)
63
+ .transition()
64
+ .duration(duration)
65
+ .style("opacity", 1)
66
+ .attr("y1", function(d) { return x1(d[0]); })
67
+ .attr("y2", function(d) { return x1(d[1]); });
68
+
69
+ center.transition()
70
+ .duration(duration)
71
+ .style("opacity", 1)
72
+ .attr("y1", function(d) { return x1(d[0]); })
73
+ .attr("y2", function(d) { return x1(d[1]); });
74
+
75
+ center.exit().transition()
76
+ .duration(duration)
77
+ .style("opacity", 1e-6)
78
+ .attr("y1", function(d) { return x1(d[0]); })
79
+ .attr("y2", function(d) { return x1(d[1]); })
80
+ .remove();
81
+
82
+ // Update innerquartile box.
83
+ var box = g.selectAll("rect.box")
84
+ .data([quartileData]);
85
+
86
+ box.enter().append("svg:rect")
87
+ .attr("class", "box")
88
+ .attr("x", 0)
89
+ .attr("y", function(d) { return x0(d[2]); })
90
+ .attr("width", width)
91
+ .attr("height", function(d) { return x0(d[0]) - x0(d[2]); })
92
+ .transition()
93
+ .duration(duration)
94
+ .attr("y", function(d) { return x1(d[2]); })
95
+ .attr("height", function(d) { return x1(d[0]) - x1(d[2]); });
96
+
97
+ box.transition()
98
+ .duration(duration)
99
+ .attr("y", function(d) { return x1(d[2]); })
100
+ .attr("height", function(d) { return x1(d[0]) - x1(d[2]); });
101
+
102
+ // Update median line.
103
+ var medianLine = g.selectAll("line.median")
104
+ .data([quartileData[1]]);
105
+
106
+ medianLine.enter().append("svg:line")
107
+ .attr("class", "median")
108
+ .attr("x1", 0)
109
+ .attr("y1", x0)
110
+ .attr("x2", width)
111
+ .attr("y2", x0)
112
+ .transition()
113
+ .duration(duration)
114
+ .attr("y1", x1)
115
+ .attr("y2", x1);
116
+
117
+ medianLine.transition()
118
+ .duration(duration)
119
+ .attr("y1", x1)
120
+ .attr("y2", x1);
121
+
122
+ // Update whiskers.
123
+ var whisker = g.selectAll("line.whisker")
124
+ .data(whiskerData || []);
125
+
126
+ whisker.enter().insert("svg:line", "circle, text")
127
+ .attr("class", "whisker")
128
+ .attr("x1", 0)
129
+ .attr("y1", x0)
130
+ .attr("x2", width)
131
+ .attr("y2", x0)
132
+ .style("opacity", 1e-6)
133
+ .transition()
134
+ .duration(duration)
135
+ .attr("y1", x1)
136
+ .attr("y2", x1)
137
+ .style("opacity", 1);
138
+
139
+ whisker.transition()
140
+ .duration(duration)
141
+ .attr("y1", x1)
142
+ .attr("y2", x1)
143
+ .style("opacity", 1);
144
+
145
+ whisker.exit().transition()
146
+ .duration(duration)
147
+ .attr("y1", x1)
148
+ .attr("y2", x1)
149
+ .style("opacity", 1e-6)
150
+ .remove();
151
+
152
+ // Update outliers.
153
+ var outlier = g.selectAll("circle.outlier")
154
+ .data(outlierIndices, Number);
155
+
156
+ outlier.enter().insert("svg:circle", "text")
157
+ .attr("class", "outlier")
158
+ .attr("r", 5)
159
+ .attr("cx", width / 2)
160
+ .attr("cy", function(i) { return x0(d[i]); })
161
+ .style("opacity", 1e-6)
162
+ .transition()
163
+ .duration(duration)
164
+ .attr("cy", function(i) { return x1(d[i]); })
165
+ .style("opacity", 1);
166
+
167
+ outlier.transition()
168
+ .duration(duration)
169
+ .attr("cy", function(i) { return x1(d[i]); })
170
+ .style("opacity", 1);
171
+
172
+ outlier.exit().transition()
173
+ .duration(duration)
174
+ .attr("cy", function(i) { return x1(d[i]); })
175
+ .style("opacity", 1e-6)
176
+ .remove();
177
+
178
+ // Compute the tick format.
179
+ var format = tickFormat || x1.tickFormat(8);
180
+
181
+ // Update box ticks.
182
+ var boxTick = g.selectAll("text.box")
183
+ .data(quartileData);
184
+
185
+ boxTick.enter().append("svg:text")
186
+ .attr("class", "box")
187
+ .attr("dy", ".3em")
188
+ .attr("dx", function(d, i) { return i & 1 ? 6 : -6 })
189
+ .attr("x", function(d, i) { return i & 1 ? width : 0 })
190
+ .attr("y", x0)
191
+ .attr("text-anchor", function(d, i) { return i & 1 ? "start" : "end"; })
192
+ .text(format)
193
+ .transition()
194
+ .duration(duration)
195
+ .attr("y", x1);
196
+
197
+ boxTick.transition()
198
+ .duration(duration)
199
+ .text(format)
200
+ .attr("y", x1);
201
+
202
+ // Update whisker ticks. These are handled separately from the box
203
+ // ticks because they may or may not exist, and we want don't want
204
+ // to join box ticks pre-transition with whisker ticks post-.
205
+ var whiskerTick = g.selectAll("text.whisker")
206
+ .data(whiskerData || []);
207
+
208
+ whiskerTick.enter().append("svg:text")
209
+ .attr("class", "whisker")
210
+ .attr("dy", ".3em")
211
+ .attr("dx", 6)
212
+ .attr("x", width)
213
+ .attr("y", x0)
214
+ .text(format)
215
+ .style("opacity", 1e-6)
216
+ .transition()
217
+ .duration(duration)
218
+ .attr("y", x1)
219
+ .style("opacity", 1);
220
+
221
+ whiskerTick.transition()
222
+ .duration(duration)
223
+ .text(format)
224
+ .attr("y", x1)
225
+ .style("opacity", 1);
226
+
227
+ whiskerTick.exit().transition()
228
+ .duration(duration)
229
+ .attr("y", x1)
230
+ .style("opacity", 1e-6)
231
+ .remove();
232
+ });
233
+ d3.timer.flush();
234
+ }
235
+
236
+ box.width = function(x) {
237
+ if (!arguments.length) return width;
238
+ width = x;
239
+ return box;
240
+ };
241
+
242
+ box.height = function(x) {
243
+ if (!arguments.length) return height;
244
+ height = x;
245
+ return box;
246
+ };
247
+
248
+ box.tickFormat = function(x) {
249
+ if (!arguments.length) return tickFormat;
250
+ tickFormat = x;
251
+ return box;
252
+ };
253
+
254
+ box.duration = function(x) {
255
+ if (!arguments.length) return duration;
256
+ duration = x;
257
+ return box;
258
+ };
259
+
260
+ box.domain = function(x) {
261
+ if (!arguments.length) return domain;
262
+ domain = x == null ? x : d3.functor(x);
263
+ return box;
264
+ };
265
+
266
+ box.value = function(x) {
267
+ if (!arguments.length) return value;
268
+ value = x;
269
+ return box;
270
+ };
271
+
272
+ box.whiskers = function(x) {
273
+ if (!arguments.length) return whiskers;
274
+ whiskers = x;
275
+ return box;
276
+ };
277
+
278
+ box.quartiles = function(x) {
279
+ if (!arguments.length) return quartiles;
280
+ quartiles = x;
281
+ return box;
282
+ };
283
+
284
+ return box;
285
+ };
286
+
287
+ function d3_chart_boxWhiskers(d) {
288
+ return [0, d.length - 1];
289
+ }
290
+
291
+ function d3_chart_boxQuartiles(d) {
292
+ return [
293
+ d3.quantile(d, .25),
294
+ d3.quantile(d, .5),
295
+ d3.quantile(d, .75)
296
+ ];
297
+ }
@@ -0,0 +1,237 @@
1
+ // Chart design based on the recommendations of Stephen Few. Implementation
2
+ // based on the work of Clint Ivy, Jamie Love, and Jason Davies.
3
+ // http://projects.instantcognition.com/protovis/bulletchart/
4
+ d3.chart.bullet = function() {
5
+ var orient = "left", // TODO top & bottom
6
+ reverse = false,
7
+ duration = 0,
8
+ ranges = d3_chart_bulletRanges,
9
+ markers = d3_chart_bulletMarkers,
10
+ measures = d3_chart_bulletMeasures,
11
+ width = 380,
12
+ height = 30,
13
+ tickFormat = null;
14
+
15
+ // For each small multiple…
16
+ function bullet(g) {
17
+ g.each(function(d, i) {
18
+ var rangez = ranges.call(this, d, i).slice().sort(d3.descending),
19
+ markerz = markers.call(this, d, i).slice().sort(d3.descending),
20
+ measurez = measures.call(this, d, i).slice().sort(d3.descending),
21
+ g = d3.select(this);
22
+
23
+ // Compute the new x-scale.
24
+ var x1 = d3.scale.linear()
25
+ .domain([0, Math.max(rangez[0], markerz[0], measurez[0])])
26
+ .range(reverse ? [width, 0] : [0, width]);
27
+
28
+ // Retrieve the old x-scale, if this is an update.
29
+ var x0 = this.__chart__ || d3.scale.linear()
30
+ .domain([0, Infinity])
31
+ .range(x1.range());
32
+
33
+ // Stash the new scale.
34
+ this.__chart__ = x1;
35
+
36
+ // Derive width-scales from the x-scales.
37
+ var w0 = d3_chart_bulletWidth(x0),
38
+ w1 = d3_chart_bulletWidth(x1);
39
+
40
+ // Update the range rects.
41
+ var range = g.selectAll("rect.range")
42
+ .data(rangez);
43
+
44
+ range.enter().append("svg:rect")
45
+ .attr("class", function(d, i) { return "range s" + i; })
46
+ .attr("width", w0)
47
+ .attr("height", height)
48
+ .attr("x", reverse ? x0 : 0)
49
+ .transition()
50
+ .duration(duration)
51
+ .attr("width", w1)
52
+ .attr("x", reverse ? x1 : 0);
53
+
54
+ range.transition()
55
+ .duration(duration)
56
+ .attr("x", reverse ? x1 : 0)
57
+ .attr("width", w1)
58
+ .attr("height", height);
59
+
60
+ // Update the measure rects.
61
+ var measure = g.selectAll("rect.measure")
62
+ .data(measurez);
63
+
64
+ measure.enter().append("svg:rect")
65
+ .attr("class", function(d, i) { return "measure s" + i; })
66
+ .attr("width", w0)
67
+ .attr("height", height / 3)
68
+ .attr("x", reverse ? x0 : 0)
69
+ .attr("y", height / 3)
70
+ .transition()
71
+ .duration(duration)
72
+ .attr("width", w1)
73
+ .attr("x", reverse ? x1 : 0);
74
+
75
+ measure.transition()
76
+ .duration(duration)
77
+ .attr("width", w1)
78
+ .attr("height", height / 3)
79
+ .attr("x", reverse ? x1 : 0)
80
+ .attr("y", height / 3);
81
+
82
+ // Update the marker lines.
83
+ var marker = g.selectAll("line.marker")
84
+ .data(markerz);
85
+
86
+ marker.enter().append("svg:line")
87
+ .attr("class", "marker")
88
+ .attr("x1", x0)
89
+ .attr("x2", x0)
90
+ .attr("y1", height / 6)
91
+ .attr("y2", height * 5 / 6)
92
+ .transition()
93
+ .duration(duration)
94
+ .attr("x1", x1)
95
+ .attr("x2", x1);
96
+
97
+ marker.transition()
98
+ .duration(duration)
99
+ .attr("x1", x1)
100
+ .attr("x2", x1)
101
+ .attr("y1", height / 6)
102
+ .attr("y2", height * 5 / 6);
103
+
104
+ // Compute the tick format.
105
+ var format = tickFormat || x1.tickFormat(8);
106
+
107
+ // Update the tick groups.
108
+ var tick = g.selectAll("g.tick")
109
+ .data(x1.ticks(8), function(d) {
110
+ return this.textContent || format(d);
111
+ });
112
+
113
+ // Initialize the ticks with the old scale, x0.
114
+ var tickEnter = tick.enter().append("svg:g")
115
+ .attr("class", "tick")
116
+ .attr("transform", d3_chart_bulletTranslate(x0))
117
+ .style("opacity", 1e-6);
118
+
119
+ tickEnter.append("svg:line")
120
+ .attr("y1", height)
121
+ .attr("y2", height * 7 / 6);
122
+
123
+ tickEnter.append("svg:text")
124
+ .attr("text-anchor", "middle")
125
+ .attr("dy", "1em")
126
+ .attr("y", height * 7 / 6)
127
+ .text(format);
128
+
129
+ // Transition the entering ticks to the new scale, x1.
130
+ tickEnter.transition()
131
+ .duration(duration)
132
+ .attr("transform", d3_chart_bulletTranslate(x1))
133
+ .style("opacity", 1);
134
+
135
+ // Transition the updating ticks to the new scale, x1.
136
+ var tickUpdate = tick.transition()
137
+ .duration(duration)
138
+ .attr("transform", d3_chart_bulletTranslate(x1))
139
+ .style("opacity", 1);
140
+
141
+ tickUpdate.select("line")
142
+ .attr("y1", height)
143
+ .attr("y2", height * 7 / 6);
144
+
145
+ tickUpdate.select("text")
146
+ .attr("y", height * 7 / 6);
147
+
148
+ // Transition the exiting ticks to the new scale, x1.
149
+ tick.exit().transition()
150
+ .duration(duration)
151
+ .attr("transform", d3_chart_bulletTranslate(x1))
152
+ .style("opacity", 1e-6)
153
+ .remove();
154
+ });
155
+ d3.timer.flush();
156
+ }
157
+
158
+ // left, right, top, bottom
159
+ bullet.orient = function(x) {
160
+ if (!arguments.length) return orient;
161
+ orient = x;
162
+ reverse = orient == "right" || orient == "bottom";
163
+ return bullet;
164
+ };
165
+
166
+ // ranges (bad, satisfactory, good)
167
+ bullet.ranges = function(x) {
168
+ if (!arguments.length) return ranges;
169
+ ranges = x;
170
+ return bullet;
171
+ };
172
+
173
+ // markers (previous, goal)
174
+ bullet.markers = function(x) {
175
+ if (!arguments.length) return markers;
176
+ markers = x;
177
+ return bullet;
178
+ };
179
+
180
+ // measures (actual, forecast)
181
+ bullet.measures = function(x) {
182
+ if (!arguments.length) return measures;
183
+ measures = x;
184
+ return bullet;
185
+ };
186
+
187
+ bullet.width = function(x) {
188
+ if (!arguments.length) return width;
189
+ width = x;
190
+ return bullet;
191
+ };
192
+
193
+ bullet.height = function(x) {
194
+ if (!arguments.length) return height;
195
+ height = x;
196
+ return bullet;
197
+ };
198
+
199
+ bullet.tickFormat = function(x) {
200
+ if (!arguments.length) return tickFormat;
201
+ tickFormat = x;
202
+ return bullet;
203
+ };
204
+
205
+ bullet.duration = function(x) {
206
+ if (!arguments.length) return duration;
207
+ duration = x;
208
+ return bullet;
209
+ };
210
+
211
+ return bullet;
212
+ };
213
+
214
+ function d3_chart_bulletRanges(d) {
215
+ return d.ranges;
216
+ }
217
+
218
+ function d3_chart_bulletMarkers(d) {
219
+ return d.markers;
220
+ }
221
+
222
+ function d3_chart_bulletMeasures(d) {
223
+ return d.measures;
224
+ }
225
+
226
+ function d3_chart_bulletTranslate(x) {
227
+ return function(d) {
228
+ return "translate(" + x(d) + ",0)";
229
+ };
230
+ }
231
+
232
+ function d3_chart_bulletWidth(x) {
233
+ var x0 = x(0);
234
+ return function(d) {
235
+ return Math.abs(x(d) - x0);
236
+ };
237
+ }