d3_rails 0.0.10 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -12,6 +12,10 @@ handle interactivity, and incorporate smooth transitions and staged animations
12
12
  into your pages. You can use D3 as a visualization framework (like Protovis),
13
13
  or you can use it to build dynamic pages (like jQuery).
14
14
 
15
+ # D3 Version
16
+
17
+ The current release of this gem is using **D3 v=2.5.0**
18
+
15
19
  ### Installation
16
20
 
17
21
  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 = "0.0.10"
2
+ VERSION = "0.1.0"
3
3
  end
File without changes
File without changes
@@ -268,6 +268,17 @@ function d3_geom_polygonIntersect(c, d, a, b) {
268
268
  // http://blog.thejit.org/assets/voronoijs/voronoi.js
269
269
  // See lib/jit/LICENSE for details.
270
270
 
271
+ // Notes:
272
+ //
273
+ // This implementation does not clip the returned polygons, so if you want to
274
+ // clip them to a particular shape you will need to do that either in SVG or by
275
+ // post-processing with d3.geom.polygon's clip method.
276
+ //
277
+ // If any vertices are coincident or have NaN positions, the behavior of this
278
+ // method is undefined. Most likely invalid polygons will be returned. You
279
+ // should filter invalid points, and consolidate coincident points, before
280
+ // computing the tessellation.
281
+
271
282
  /**
272
283
  * @param vertices [[x1, y1], [x2, y2], …]
273
284
  * @returns polygons [[[x1, y1], [x2, y2], …], …]
@@ -275,7 +286,6 @@ function d3_geom_polygonIntersect(c, d, a, b) {
275
286
  d3.geom.voronoi = function(vertices) {
276
287
  var polygons = vertices.map(function() { return []; });
277
288
 
278
- // Note: we expect the caller to clip the polygons, if needed.
279
289
  d3_voronoi_tessellate(vertices, function(e) {
280
290
  var s1,
281
291
  s2,
@@ -10,7 +10,7 @@ try {
10
10
  d3_style_setProperty.call(this, name, value + "", priority);
11
11
  };
12
12
  }
13
- d3 = {version: "2.4.6"}; // semver
13
+ d3 = {version: "2.5.0"}; // semver
14
14
  var d3_array = d3_arraySlice; // conversion for NodeLists
15
15
 
16
16
  function d3_arrayCopy(pseudoarray) {
@@ -105,6 +105,42 @@ d3.max = function(array, f) {
105
105
  }
106
106
  return a;
107
107
  };
108
+ d3.extent = function(array, f) {
109
+ var i = -1,
110
+ n = array.length,
111
+ a,
112
+ b,
113
+ c;
114
+ if (arguments.length === 1) {
115
+ while (++i < n && ((a = c = array[i]) == null || a != a)) a = c = undefined;
116
+ while (++i < n) if ((b = array[i]) != null) {
117
+ if (a > b) a = b;
118
+ if (c < b) c = b;
119
+ }
120
+ } else {
121
+ while (++i < n && ((a = c = f.call(array, array[i], i)) == null || a != a)) a = undefined;
122
+ while (++i < n) if ((b = f.call(array, array[i], i)) != null) {
123
+ if (a > b) a = b;
124
+ if (c < b) c = b;
125
+ }
126
+ }
127
+ return [a, c];
128
+ };
129
+ d3.random = {
130
+ normal: function(mean, deviation) {
131
+ if (arguments.length < 2) deviation = 1;
132
+ if (arguments.length < 1) mean = 0;
133
+ return function() {
134
+ var x, y, r;
135
+ do {
136
+ x = Math.random() * 2 - 1;
137
+ y = Math.random() * 2 - 1;
138
+ r = x * x + y * y;
139
+ } while (!r || r > 1);
140
+ return mean + deviation * x * Math.sqrt(-2 * Math.log(r) / r);
141
+ };
142
+ }
143
+ };
108
144
  function d3_number(x) {
109
145
  return x != null && !isNaN(x);
110
146
  }
@@ -438,47 +474,59 @@ d3.ns = {
438
474
  }
439
475
 
440
476
  };
441
- /** @param {...string} types */
442
- d3.dispatch = function(types) {
443
- var dispatch = {},
444
- type;
445
- for (var i = 0, n = arguments.length; i < n; i++) {
446
- type = arguments[i];
447
- dispatch[type] = d3_dispatch(type);
448
- }
477
+ d3.dispatch = function() {
478
+ var dispatch = new d3_dispatch(),
479
+ i = -1,
480
+ n = arguments.length;
481
+ while (++i < n) dispatch[arguments[i]] = d3_dispatch_event();
449
482
  return dispatch;
450
483
  };
451
484
 
452
- function d3_dispatch(type) {
453
- var dispatch = {},
454
- listeners = [];
485
+ function d3_dispatch() {}
455
486
 
456
- dispatch.add = function(listener) {
457
- for (var i = 0; i < listeners.length; i++) {
458
- if (listeners[i].listener == listener) return dispatch; // already registered
459
- }
460
- listeners.push({listener: listener, on: true});
461
- return dispatch;
462
- };
487
+ d3_dispatch.prototype.on = function(type, listener) {
488
+ var i = type.indexOf("."),
489
+ name = "";
463
490
 
464
- dispatch.remove = function(listener) {
465
- for (var i = 0; i < listeners.length; i++) {
466
- var l = listeners[i];
467
- if (l.listener == listener) {
468
- l.on = false;
469
- listeners = listeners.slice(0, i).concat(listeners.slice(i + 1));
470
- break;
471
- }
491
+ // Extract optional namespace, e.g., "click.foo"
492
+ if (i > 0) {
493
+ name = type.substring(i + 1);
494
+ type = type.substring(0, i);
495
+ }
496
+
497
+ this[type].on(name, listener);
498
+ };
499
+
500
+ function d3_dispatch_event() {
501
+ var listeners = [],
502
+ listenerByName = {};
503
+
504
+ function dispatch() {
505
+ var z = listeners, // defensive reference
506
+ i = -1,
507
+ n = z.length,
508
+ l;
509
+ while (++i < n) if ((l = z[i])._on) l.apply(this, arguments);
510
+ }
511
+
512
+ dispatch.on = function(name, listener) {
513
+ var l, i;
514
+
515
+ // remove the old listener, if any
516
+ if (l = listenerByName[name]) {
517
+ l._on = false;
518
+ listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1));
519
+ delete listenerByName[name];
472
520
  }
473
- return dispatch;
474
- };
475
521
 
476
- dispatch.dispatch = function() {
477
- var ls = listeners; // defensive reference
478
- for (var i = 0, n = ls.length; i < n; i++) {
479
- var l = ls[i];
480
- if (l.on) l.listener.apply(this, arguments);
522
+ // add the new listener, if any
523
+ if (listener) {
524
+ listener._on = true;
525
+ listeners.push(listener);
526
+ listenerByName[name] = listener;
481
527
  }
528
+
529
+ return dispatch;
482
530
  };
483
531
 
484
532
  return dispatch;
@@ -732,6 +780,11 @@ function d3_ease_bounce(t) {
732
780
  : 7.5625 * (t -= 2.625 / 2.75) * t + .984375;
733
781
  }
734
782
  d3.event = null;
783
+
784
+ function d3_eventCancel() {
785
+ d3.event.stopPropagation();
786
+ d3.event.preventDefault();
787
+ }
735
788
  d3.interpolate = function(a, b) {
736
789
  var i = d3.interpolators.length, f;
737
790
  while (--i >= 0 && !(f = d3.interpolators[i](a, b)));
@@ -826,6 +879,10 @@ d3.interpolateString = function(a, b) {
826
879
  };
827
880
  };
828
881
 
882
+ d3.interpolateTransform = function(a, b) {
883
+ return d3.interpolateString(d3.transform(a) + "", d3.transform(b) + "");
884
+ };
885
+
829
886
  d3.interpolateRgb = function(a, b) {
830
887
  a = d3.rgb(a);
831
888
  b = d3.rgb(b);
@@ -896,20 +953,19 @@ d3.interpolateObject = function(a, b) {
896
953
  };
897
954
  }
898
955
 
899
- var d3_interpolate_number = /[-+]?(?:\d+\.\d+|\d+\.|\.\d+|\d+)(?:[eE][-]?\d+)?/g,
900
- d3_interpolate_rgb = {background: 1, fill: 1, stroke: 1};
956
+ var d3_interpolate_number = /[-+]?(?:\d*\.?\d+)(?:[eE][-+]?\d+)?/g;
901
957
 
902
958
  function d3_interpolateByName(n) {
903
- return n in d3_interpolate_rgb || /\bcolor\b/.test(n)
904
- ? d3.interpolateRgb
959
+ return n == "transform"
960
+ ? d3.interpolateTransform
905
961
  : d3.interpolate;
906
962
  }
907
963
 
908
964
  d3.interpolators = [
909
965
  d3.interpolateObject,
910
966
  function(a, b) { return (b instanceof Array) && d3.interpolateArray(a, b); },
911
- function(a, b) { return (typeof b === "string") && d3.interpolateString(String(a), b); },
912
- function(a, b) { return (typeof b === "string" ? b in d3_rgb_names || /^(#|rgb\(|hsl\()/.test(b) : b instanceof d3_Rgb || b instanceof d3_Hsl) && d3.interpolateRgb(String(a), b); },
967
+ function(a, b) { return (typeof b === "string") && d3.interpolateString(a + "", b); },
968
+ function(a, b) { return (typeof b === "string" ? b in d3_rgb_names || /^(#|rgb\(|hsl\()/.test(b) : b instanceof d3_Rgb || b instanceof d3_Hsl) && d3.interpolateRgb(a + "", b); },
913
969
  function(a, b) { return (typeof b === "number") && d3.interpolateNumber(+a, b); }
914
970
  ];
915
971
  function d3_uninterpolateNumber(a, b) {
@@ -1871,7 +1927,7 @@ function d3_transition(groups, id, time) {
1871
1927
 
1872
1928
  groups.each = function(type, listener) {
1873
1929
  if (arguments.length < 2) return d3_transition_each.call(groups, type);
1874
- event[type].add(listener);
1930
+ event.on(type, listener);
1875
1931
  return groups;
1876
1932
  };
1877
1933
 
@@ -1897,7 +1953,7 @@ function d3_transition(groups, id, time) {
1897
1953
  }
1898
1954
  }
1899
1955
 
1900
- event.start.dispatch.call(node, d, i);
1956
+ event.start.call(node, d, i);
1901
1957
  if (!tick(elapsed)) d3.timer(tick, 0, time);
1902
1958
  return 1;
1903
1959
  }
@@ -1916,7 +1972,7 @@ function d3_transition(groups, id, time) {
1916
1972
  if (t >= 1) {
1917
1973
  stop();
1918
1974
  d3_transitionInheritId = id;
1919
- event.end.dispatch.call(node, d, i);
1975
+ event.end.call(node, d, i);
1920
1976
  d3_transitionInheritId = 0;
1921
1977
  return 1;
1922
1978
  }
@@ -1939,17 +1995,18 @@ function d3_transitionNull(d, i, a) {
1939
1995
  return a != "" && d3_transitionRemove;
1940
1996
  }
1941
1997
 
1942
- function d3_transitionTween(b) {
1998
+ function d3_transitionTween(name, b) {
1999
+ var interpolate = d3_interpolateByName(name);
1943
2000
 
1944
2001
  function transitionFunction(d, i, a) {
1945
2002
  var v = b.call(this, d, i);
1946
2003
  return v == null
1947
2004
  ? a != "" && d3_transitionRemove
1948
- : a != v && d3.interpolate(a, v);
2005
+ : a != v && interpolate(a, v);
1949
2006
  }
1950
2007
 
1951
2008
  function transitionString(d, i, a) {
1952
- return a != b && d3.interpolate(a, b);
2009
+ return a != b && interpolate(a, b);
1953
2010
  }
1954
2011
 
1955
2012
  return typeof b === "function" ? transitionFunction
@@ -2014,7 +2071,7 @@ d3_transitionPrototype.selectAll = function(selector) {
2014
2071
  return d3_transition(subgroups, this.id, this.time).ease(this.ease());
2015
2072
  };
2016
2073
  d3_transitionPrototype.attr = function(name, value) {
2017
- return this.attrTween(name, d3_transitionTween(value));
2074
+ return this.attrTween(name, d3_transitionTween(name, value));
2018
2075
  };
2019
2076
 
2020
2077
  d3_transitionPrototype.attrTween = function(nameNS, tween) {
@@ -2038,7 +2095,7 @@ d3_transitionPrototype.attrTween = function(nameNS, tween) {
2038
2095
  };
2039
2096
  d3_transitionPrototype.style = function(name, value, priority) {
2040
2097
  if (arguments.length < 3) priority = "";
2041
- return this.styleTween(name, d3_transitionTween(value), priority);
2098
+ return this.styleTween(name, d3_transitionTween(name, value), priority);
2042
2099
  };
2043
2100
 
2044
2101
  d3_transitionPrototype.styleTween = function(name, tween, priority) {
@@ -2191,6 +2248,54 @@ var d3_timer_frame = window.requestAnimationFrame
2191
2248
  || window.oRequestAnimationFrame
2192
2249
  || window.msRequestAnimationFrame
2193
2250
  || function(callback) { setTimeout(callback, 17); };
2251
+ d3.transform = function(string) {
2252
+ d3_transformG.setAttribute("transform", string);
2253
+ return new d3_transform(d3_transformG.transform.baseVal.consolidate().matrix);
2254
+ };
2255
+
2256
+ // Compute x-scale and normalize the first row.
2257
+ // Compute shear and make second row orthogonal to first.
2258
+ // Compute y-scale and normalize the second row.
2259
+ // Finally, compute the rotation.
2260
+ function d3_transform(m) {
2261
+ var r0 = [m.a, m.b],
2262
+ r1 = [m.c, m.d],
2263
+ kx = d3_transformNormalize(r0),
2264
+ kz = d3_transformDot(r0, r1),
2265
+ ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz));
2266
+ this.translate = [m.e, m.f];
2267
+ this.rotate = Math.atan2(m.b, m.a) * d3_transformDegrees;
2268
+ this.scale = [kx, ky || 0];
2269
+ this.skew = ky ? kz / ky * d3_transformDegrees : 0;
2270
+ };
2271
+
2272
+ d3_transform.prototype.toString = function() {
2273
+ return "translate(" + this.translate
2274
+ + ")rotate(" + this.rotate
2275
+ + ")skewX(" + this.skew
2276
+ + ")scale(" + this.scale
2277
+ + ")";
2278
+ };
2279
+
2280
+ function d3_transformDot(a, b) {
2281
+ return a[0] * b[0] + a[1] * b[1];
2282
+ }
2283
+
2284
+ function d3_transformNormalize(a) {
2285
+ var k = Math.sqrt(d3_transformDot(a, a));
2286
+ a[0] /= k;
2287
+ a[1] /= k;
2288
+ return k;
2289
+ }
2290
+
2291
+ function d3_transformCombine(a, b, k) {
2292
+ a[0] += k * b[0];
2293
+ a[1] += k * b[1];
2294
+ return a;
2295
+ }
2296
+
2297
+ var d3_transformG = document.createElementNS(d3.ns.prefix.svg, "g"),
2298
+ d3_transformDegrees = 180 / Math.PI;
2194
2299
  function d3_noop() {}
2195
2300
  d3.scale = {};
2196
2301
 
@@ -2515,6 +2620,10 @@ function d3_scale_ordinal(domain, ranger) {
2515
2620
  return range[((index[x] || (index[x] = domain.push(x))) - 1) % range.length];
2516
2621
  }
2517
2622
 
2623
+ function steps(start, step) {
2624
+ return d3.range(domain.length).map(function(i) { return start + step * i; });
2625
+ }
2626
+
2518
2627
  scale.domain = function(x) {
2519
2628
  if (!arguments.length) return domain;
2520
2629
  domain = [];
@@ -2537,7 +2646,7 @@ function d3_scale_ordinal(domain, ranger) {
2537
2646
  var start = x[0],
2538
2647
  stop = x[1],
2539
2648
  step = (stop - start) / (domain.length - 1 + padding);
2540
- range = domain.length < 2 ? [(start + stop) / 2] : d3.range(start + step * padding / 2, stop + step / 2, step);
2649
+ range = steps(domain.length < 2 ? (start + stop) / 2 : start + step * padding / 2, step);
2541
2650
  rangeBand = 0;
2542
2651
  ranger = {t: "rangePoints", x: x, p: padding};
2543
2652
  return scale;
@@ -2548,7 +2657,7 @@ function d3_scale_ordinal(domain, ranger) {
2548
2657
  var start = x[0],
2549
2658
  stop = x[1],
2550
2659
  step = (stop - start) / (domain.length + padding);
2551
- range = d3.range(start + step * padding, stop, step);
2660
+ range = steps(start + step * padding, step);
2552
2661
  rangeBand = step * (1 - padding);
2553
2662
  ranger = {t: "rangeBands", x: x, p: padding};
2554
2663
  return scale;
@@ -2558,9 +2667,8 @@ function d3_scale_ordinal(domain, ranger) {
2558
2667
  if (arguments.length < 2) padding = 0;
2559
2668
  var start = x[0],
2560
2669
  stop = x[1],
2561
- step = Math.floor((stop - start) / (domain.length + padding)),
2562
- err = stop - start - (domain.length - padding) * step;
2563
- range = d3.range(start + Math.round(err / 2), stop, step);
2670
+ step = Math.floor((stop - start) / (domain.length + padding));
2671
+ range = steps(start + Math.round((stop - start - (domain.length - padding) * step) / 2), step);
2564
2672
  rangeBand = Math.round(step * (1 - padding));
2565
2673
  ranger = {t: "rangeRoundBands", x: x, p: padding};
2566
2674
  return scale;
@@ -3529,8 +3637,9 @@ function d3_svg_mousePoint(container, e) {
3529
3637
  point = point.matrixTransform(container.getScreenCTM().inverse());
3530
3638
  return [point.x, point.y];
3531
3639
  };
3532
- d3.svg.touches = function(container) {
3533
- var touches = d3.event.touches;
3640
+ d3.svg.touches = function(container, touches) {
3641
+ if (arguments.length < 2) touches = d3.event.touches;
3642
+
3534
3643
  return touches ? d3_array(touches).map(function(touch) {
3535
3644
  var point = d3_svg_mousePoint(container, touch);
3536
3645
  point.identifier = touch.identifier;
@@ -3820,6 +3929,341 @@ function d3_svg_axisSubdivide(scale, ticks, m) {
3820
3929
  }
3821
3930
  return subticks;
3822
3931
  }
3932
+ d3.svg.brush = function() {
3933
+ var event = d3.dispatch("brushstart", "brush", "brushend"),
3934
+ x, // x-scale, optional
3935
+ y, // y-scale, optional
3936
+ extent = [[0, 0], [0, 0]]; // [x0, y0], [x1, y1]
3937
+
3938
+ function brush(g) {
3939
+ var resizes = x && y ? ["n", "e", "s", "w", "nw", "ne", "se", "sw"]
3940
+ : x ? ["e", "w"]
3941
+ : y ? ["n", "s"]
3942
+ : [];
3943
+
3944
+ g.each(function() {
3945
+ var g = d3.select(this).on("mousedown.brush", down),
3946
+ bg = g.selectAll(".background").data([,]),
3947
+ fg = g.selectAll(".extent").data([,]),
3948
+ tz = g.selectAll(".resize").data(resizes, String),
3949
+ e;
3950
+
3951
+ // An invisible, mouseable area for starting a new brush.
3952
+ bg.enter().append("svg:rect")
3953
+ .attr("class", "background")
3954
+ .style("visibility", "hidden")
3955
+ .style("pointer-events", "all")
3956
+ .style("cursor", "crosshair");
3957
+
3958
+ // The visible brush extent; style this as you like!
3959
+ fg.enter().append("svg:rect")
3960
+ .attr("class", "extent")
3961
+ .style("cursor", "move");
3962
+
3963
+ // More invisible rects for resizing the extent.
3964
+ tz.enter().append("svg:rect")
3965
+ .attr("class", function(d) { return "resize " + d; })
3966
+ .attr("width", 6)
3967
+ .attr("height", 6)
3968
+ .style("visibility", "hidden")
3969
+ .style("pointer-events", brush.empty() ? "none" : "all")
3970
+ .style("cursor", function(d) { return d3_svg_brushCursor[d]; });
3971
+
3972
+ // Remove any superfluous resizers.
3973
+ tz.exit().remove();
3974
+
3975
+ // Initialize the background to fill the defined range.
3976
+ // If the range isn't defined, you can post-process.
3977
+ if (x) {
3978
+ e = d3_scaleExtent(x.range());
3979
+ bg.attr("x", e[0]).attr("width", e[1] - e[0]);
3980
+ d3_svg_brushRedrawX(g, extent);
3981
+ }
3982
+ if (y) {
3983
+ e = d3_scaleExtent(y.range());
3984
+ bg.attr("y", e[0]).attr("height", e[1] - e[0]);
3985
+ d3_svg_brushRedrawY(g, extent);
3986
+ }
3987
+ });
3988
+ }
3989
+
3990
+ function down() {
3991
+ var target = d3.select(d3.event.target);
3992
+
3993
+ // Store some global state for the duration of the brush gesture.
3994
+ d3_svg_brush = brush;
3995
+ d3_svg_brushTarget = this;
3996
+ d3_svg_brushExtent = extent;
3997
+ d3_svg_brushOffset = d3.svg.mouse(d3_svg_brushTarget);
3998
+
3999
+ // If the extent was clicked on, drag rather than brush;
4000
+ // store the offset between the mouse and extent origin instead.
4001
+ if (d3_svg_brushDrag = target.classed("extent")) {
4002
+ d3_svg_brushOffset[0] = extent[0][0] - d3_svg_brushOffset[0];
4003
+ d3_svg_brushOffset[1] = extent[0][1] - d3_svg_brushOffset[1];
4004
+ }
4005
+
4006
+ // If a resizer was clicked on, record which side is to be resized.
4007
+ // Also, set the offset to the opposite side.
4008
+ else if (target.classed("resize")) {
4009
+ d3_svg_brushResize = d3.event.target.__data__;
4010
+ d3_svg_brushOffset[0] = extent[+/w$/.test(d3_svg_brushResize)][0];
4011
+ d3_svg_brushOffset[1] = extent[+/^n/.test(d3_svg_brushResize)][1];
4012
+ }
4013
+
4014
+ // If the ALT key is down when starting a brush, the center is at the mouse.
4015
+ else if (d3.event.altKey) {
4016
+ d3_svg_brushCenter = d3_svg_brushOffset.slice();
4017
+ }
4018
+
4019
+ // Restrict which dimensions are resized.
4020
+ d3_svg_brushX = !/^(n|s)$/.test(d3_svg_brushResize) && x;
4021
+ d3_svg_brushY = !/^(e|w)$/.test(d3_svg_brushResize) && y;
4022
+
4023
+ // Notify listeners.
4024
+ d3_svg_brushDispatch = dispatcher(this, arguments);
4025
+ d3_svg_brushDispatch("brushstart");
4026
+ d3_svg_brushMove();
4027
+ d3_eventCancel();
4028
+ }
4029
+
4030
+ function dispatcher(that, argumentz) {
4031
+ return function(type) {
4032
+ var e = d3.event;
4033
+ try {
4034
+ d3.event = {type: type, target: brush};
4035
+ event[type].apply(that, argumentz);
4036
+ } finally {
4037
+ d3.event = e;
4038
+ }
4039
+ };
4040
+ }
4041
+
4042
+ brush.x = function(z) {
4043
+ if (!arguments.length) return x;
4044
+ x = z;
4045
+ return brush;
4046
+ };
4047
+
4048
+ brush.y = function(z) {
4049
+ if (!arguments.length) return y;
4050
+ y = z;
4051
+ return brush;
4052
+ };
4053
+
4054
+ brush.extent = function(z) {
4055
+ var x0, x1, y0, y1, t;
4056
+
4057
+ // Invert the pixel extent to data-space.
4058
+ if (!arguments.length) {
4059
+ if (x) {
4060
+ x0 = x.invert(extent[0][0]), x1 = x.invert(extent[1][0]);
4061
+ if (x1 < x0) t = x0, x0 = x1, x1 = t;
4062
+ }
4063
+ if (y) {
4064
+ y0 = y.invert(extent[0][1]), y1 = y.invert(extent[1][1]);
4065
+ if (y1 < y0) t = y0, y0 = y1, y1 = t;
4066
+ }
4067
+ return x && y ? [[x0, y0], [x1, y1]] : x ? [x0, x1] : y && [y0, y1];
4068
+ }
4069
+
4070
+ // Scale the data-space extent to pixels.
4071
+ if (x) {
4072
+ x0 = z[0], x1 = z[1];
4073
+ if (y) x0 = x0[0], x1 = x1[0];
4074
+ x0 = x(x0), x1 = x(x1);
4075
+ if (x1 < x0) t = x0, x0 = x1, x1 = t;
4076
+ extent[0][0] = x0, extent[1][0] = x1;
4077
+ }
4078
+ if (y) {
4079
+ y0 = z[0], y1 = z[1];
4080
+ if (x) y0 = y0[1], y1 = y1[1];
4081
+ y0 = y(y0), y1 = y(y1);
4082
+ if (y1 < y0) t = y0, y0 = y1, y1 = t;
4083
+ extent[0][1] = y0, extent[1][1] = y1;
4084
+ }
4085
+
4086
+ return brush;
4087
+ };
4088
+
4089
+ brush.clear = function() {
4090
+ extent[0][0] =
4091
+ extent[0][1] =
4092
+ extent[1][0] =
4093
+ extent[1][1] = 0;
4094
+ return brush;
4095
+ };
4096
+
4097
+ brush.empty = function() {
4098
+ return (x && extent[0][0] === extent[1][0])
4099
+ || (y && extent[0][1] === extent[1][1]);
4100
+ };
4101
+
4102
+ brush.on = function(type, listener) {
4103
+ event.on(type, listener);
4104
+ return brush;
4105
+ };
4106
+
4107
+ d3.select(window)
4108
+ .on("mousemove.brush", d3_svg_brushMove)
4109
+ .on("mouseup.brush", d3_svg_brushUp)
4110
+ .on("keydown.brush", d3_svg_brushKeydown)
4111
+ .on("keyup.brush", d3_svg_brushKeyup);
4112
+
4113
+ return brush;
4114
+ };
4115
+
4116
+ var d3_svg_brush,
4117
+ d3_svg_brushDispatch,
4118
+ d3_svg_brushTarget,
4119
+ d3_svg_brushX,
4120
+ d3_svg_brushY,
4121
+ d3_svg_brushExtent,
4122
+ d3_svg_brushDrag,
4123
+ d3_svg_brushResize,
4124
+ d3_svg_brushCenter,
4125
+ d3_svg_brushOffset;
4126
+
4127
+ function d3_svg_brushRedrawX(g, extent) {
4128
+ g.select(".extent").attr("x", extent[0][0]);
4129
+ g.selectAll(".n,.s,.w,.nw,.sw").attr("x", extent[0][0] - 2);
4130
+ g.selectAll(".e,.ne,.se").attr("x", extent[1][0] - 3);
4131
+ g.selectAll(".extent,.n,.s").attr("width", extent[1][0] - extent[0][0]);
4132
+ }
4133
+
4134
+ function d3_svg_brushRedrawY(g, extent) {
4135
+ g.select(".extent").attr("y", extent[0][1]);
4136
+ g.selectAll(".n,.e,.w,.nw,.ne").attr("y", extent[0][1] - 3);
4137
+ g.selectAll(".s,.se,.sw").attr("y", extent[1][1] - 4);
4138
+ g.selectAll(".extent,.e,.w").attr("height", extent[1][1] - extent[0][1]);
4139
+ }
4140
+
4141
+ function d3_svg_brushKeydown() {
4142
+ if (d3.event.keyCode == 32 && d3_svg_brushTarget && !d3_svg_brushDrag) {
4143
+ d3_svg_brushCenter = null;
4144
+ d3_svg_brushOffset[0] -= d3_svg_brushExtent[1][0];
4145
+ d3_svg_brushOffset[1] -= d3_svg_brushExtent[1][1];
4146
+ d3_svg_brushDrag = 2;
4147
+ d3_eventCancel();
4148
+ }
4149
+ }
4150
+
4151
+ function d3_svg_brushKeyup() {
4152
+ if (d3.event.keyCode == 32 && d3_svg_brushDrag == 2) {
4153
+ d3_svg_brushOffset[0] += d3_svg_brushExtent[1][0];
4154
+ d3_svg_brushOffset[1] += d3_svg_brushExtent[1][1];
4155
+ d3_svg_brushDrag = 0;
4156
+ d3_eventCancel();
4157
+ }
4158
+ }
4159
+
4160
+ function d3_svg_brushMove() {
4161
+ if (d3_svg_brushOffset) {
4162
+ var mouse = d3.svg.mouse(d3_svg_brushTarget),
4163
+ g = d3.select(d3_svg_brushTarget);
4164
+
4165
+ if (!d3_svg_brushDrag) {
4166
+
4167
+ // If needed, determine the center from the current extent.
4168
+ if (d3.event.altKey) {
4169
+ if (!d3_svg_brushCenter) {
4170
+ d3_svg_brushCenter = [
4171
+ (d3_svg_brushExtent[0][0] + d3_svg_brushExtent[1][0]) / 2,
4172
+ (d3_svg_brushExtent[0][1] + d3_svg_brushExtent[1][1]) / 2
4173
+ ];
4174
+ }
4175
+
4176
+ // Update the offset, for when the ALT key is released.
4177
+ d3_svg_brushOffset[0] = d3_svg_brushExtent[+(mouse[0] < d3_svg_brushCenter[0])][0];
4178
+ d3_svg_brushOffset[1] = d3_svg_brushExtent[+(mouse[1] < d3_svg_brushCenter[1])][1];
4179
+ }
4180
+
4181
+ // When the ALT key is released, we clear the center.
4182
+ else d3_svg_brushCenter = null;
4183
+ }
4184
+
4185
+ // Update the brush extent for each dimension.
4186
+ if (d3_svg_brushX) {
4187
+ d3_svg_brushMove1(mouse, d3_svg_brushX, 0);
4188
+ d3_svg_brushRedrawX(g, d3_svg_brushExtent);
4189
+ }
4190
+ if (d3_svg_brushY) {
4191
+ d3_svg_brushMove1(mouse, d3_svg_brushY, 1);
4192
+ d3_svg_brushRedrawY(g, d3_svg_brushExtent);
4193
+ }
4194
+
4195
+ // Notify listeners.
4196
+ d3_svg_brushDispatch("brush");
4197
+ }
4198
+ }
4199
+
4200
+ function d3_svg_brushMove1(mouse, scale, i) {
4201
+ var range = d3_scaleExtent(scale.range()),
4202
+ offset = d3_svg_brushOffset[i],
4203
+ size = d3_svg_brushExtent[1][i] - d3_svg_brushExtent[0][i],
4204
+ min,
4205
+ max;
4206
+
4207
+ // When dragging, reduce the range by the extent size and offset.
4208
+ if (d3_svg_brushDrag) {
4209
+ range[0] -= offset;
4210
+ range[1] -= size + offset;
4211
+ }
4212
+
4213
+ // Clamp the mouse so that the extent fits within the range extent.
4214
+ min = Math.max(range[0], Math.min(range[1], mouse[i]));
4215
+
4216
+ // Compute the new extent bounds.
4217
+ if (d3_svg_brushDrag) {
4218
+ max = (min += offset) + size;
4219
+ } else {
4220
+
4221
+ // If the ALT key is pressed, then preserve the center of the extent.
4222
+ if (d3_svg_brushCenter) offset = Math.max(range[0], Math.min(range[1], 2 * d3_svg_brushCenter[i] - min));
4223
+
4224
+ // Compute the min and max of the offset and mouse.
4225
+ if (offset < min) {
4226
+ max = min;
4227
+ min = offset;
4228
+ } else {
4229
+ max = offset;
4230
+ }
4231
+ }
4232
+
4233
+ // Update the stored bounds.
4234
+ d3_svg_brushExtent[0][i] = min;
4235
+ d3_svg_brushExtent[1][i] = max;
4236
+ }
4237
+
4238
+ function d3_svg_brushUp() {
4239
+ if (d3_svg_brushOffset) {
4240
+ d3_svg_brushMove();
4241
+ d3.select(d3_svg_brushTarget).selectAll(".resize").style("pointer-events", d3_svg_brush.empty() ? "none" : "all");
4242
+ d3_svg_brushDispatch("brushend");
4243
+ d3_svg_brush =
4244
+ d3_svg_brushDispatch =
4245
+ d3_svg_brushTarget =
4246
+ d3_svg_brushX =
4247
+ d3_svg_brushY =
4248
+ d3_svg_brushExtent =
4249
+ d3_svg_brushDrag =
4250
+ d3_svg_brushResize =
4251
+ d3_svg_brushCenter =
4252
+ d3_svg_brushOffset = null;
4253
+ d3_eventCancel();
4254
+ }
4255
+ }
4256
+
4257
+ var d3_svg_brushCursor = {
4258
+ n: "ns-resize",
4259
+ e: "ew-resize",
4260
+ s: "ns-resize",
4261
+ w: "ew-resize",
4262
+ nw: "nwse-resize",
4263
+ ne: "nesw-resize",
4264
+ se: "nwse-resize",
4265
+ sw: "nesw-resize"
4266
+ };
3823
4267
  d3.behavior = {};
3824
4268
  d3.behavior.drag = function() {
3825
4269
  var event = d3.dispatch("drag", "dragstart", "dragend");
@@ -3852,7 +4296,7 @@ d3.behavior.drag = function() {
3852
4296
  }
3853
4297
 
3854
4298
  drag.on = function(type, listener) {
3855
- event[type].add(listener);
4299
+ event.on(type, listener);
3856
4300
  return drag;
3857
4301
  };
3858
4302
 
@@ -3880,7 +4324,7 @@ function d3_behavior_dragDispatch(type) {
3880
4324
 
3881
4325
  try {
3882
4326
  d3.event = {dx: dx, dy: dy};
3883
- d3_behavior_dragEvent[type].dispatch.apply(d3_behavior_dragTarget, d3_behavior_dragArguments);
4327
+ d3_behavior_dragEvent[type].apply(d3_behavior_dragTarget, d3_behavior_dragArguments);
3884
4328
  } finally {
3885
4329
  d3.event = o;
3886
4330
  }
@@ -3888,10 +4332,10 @@ function d3_behavior_dragDispatch(type) {
3888
4332
  o.preventDefault();
3889
4333
  }
3890
4334
 
3891
- function d3_behavior_dragPoint(container) {
3892
- return d3.event.touches
3893
- ? d3.svg.touches(container)[0]
3894
- : d3.svg.mouse(container);
4335
+ function d3_behavior_dragPoint(container, type) {
4336
+ // TODO Track touch points by identifier.
4337
+ var t = d3.event.changedTouches;
4338
+ return t ? d3.svg.touches(container, t)[0] : d3.svg.mouse(container);
3895
4339
  }
3896
4340
 
3897
4341
  function d3_behavior_dragMove() {
@@ -3902,7 +4346,7 @@ function d3_behavior_dragMove() {
3902
4346
  if (!parent) return d3_behavior_dragUp();
3903
4347
 
3904
4348
  d3_behavior_dragDispatch("drag");
3905
- d3_behavior_dragCancel();
4349
+ d3_eventCancel();
3906
4350
  }
3907
4351
 
3908
4352
  function d3_behavior_dragUp() {
@@ -3914,27 +4358,22 @@ function d3_behavior_dragUp() {
3914
4358
  // Also prevent the subsequent click from propagating (e.g., for anchors).
3915
4359
  if (d3_behavior_dragMoved && d3_behavior_dragEventTarget === d3.event.target) {
3916
4360
  d3_behavior_dragStopClick = true;
3917
- d3_behavior_dragCancel();
4361
+ d3_eventCancel();
3918
4362
  }
3919
4363
  }
3920
4364
 
3921
4365
  function d3_behavior_dragClick() {
3922
4366
  if (d3_behavior_dragStopClick && d3_behavior_dragEventTarget === d3.event.target) {
3923
- d3_behavior_dragCancel();
4367
+ d3_eventCancel();
3924
4368
  d3_behavior_dragStopClick = false;
3925
4369
  d3_behavior_dragEventTarget = null;
3926
4370
  }
3927
4371
  }
3928
-
3929
- function d3_behavior_dragCancel() {
3930
- d3.event.stopPropagation();
3931
- d3.event.preventDefault();
3932
- }
3933
4372
  // TODO unbind zoom behavior?
3934
- // TODO unbind listener?
3935
4373
  d3.behavior.zoom = function() {
3936
4374
  var xyz = [0, 0, 0],
3937
- event = d3.dispatch("zoom");
4375
+ event = d3.dispatch("zoom"),
4376
+ extent = d3_behavior_zoomInfiniteExtent;
3938
4377
 
3939
4378
  function zoom() {
3940
4379
  this
@@ -3955,7 +4394,8 @@ d3.behavior.zoom = function() {
3955
4394
  // snapshot the local context for subsequent dispatch
3956
4395
  function start() {
3957
4396
  d3_behavior_zoomXyz = xyz;
3958
- d3_behavior_zoomDispatch = event.zoom.dispatch;
4397
+ d3_behavior_zoomExtent = extent;
4398
+ d3_behavior_zoomDispatch = event.zoom;
3959
4399
  d3_behavior_zoomEventTarget = d3.event.target;
3960
4400
  d3_behavior_zoomTarget = this;
3961
4401
  d3_behavior_zoomArguments = arguments;
@@ -3994,8 +4434,14 @@ d3.behavior.zoom = function() {
3994
4434
  d3_behavior_zoomLast = now;
3995
4435
  }
3996
4436
 
4437
+ zoom.extent = function(x) {
4438
+ if (!arguments.length) return extent;
4439
+ extent = x == null ? d3_behavior_zoomInfiniteExtent : x;
4440
+ return zoom;
4441
+ };
4442
+
3997
4443
  zoom.on = function(type, listener) {
3998
- event[type].add(listener);
4444
+ event.on(type, listener);
3999
4445
  return zoom;
4000
4446
  };
4001
4447
 
@@ -4008,6 +4454,7 @@ var d3_behavior_zoomDiv,
4008
4454
  d3_behavior_zoomLocations = {}, // identifier -> location
4009
4455
  d3_behavior_zoomLast = 0,
4010
4456
  d3_behavior_zoomXyz,
4457
+ d3_behavior_zoomExtent,
4011
4458
  d3_behavior_zoomDispatch,
4012
4459
  d3_behavior_zoomEventTarget,
4013
4460
  d3_behavior_zoomTarget,
@@ -4118,25 +4565,27 @@ function d3_behavior_zoomClick() {
4118
4565
  }
4119
4566
 
4120
4567
  function d3_behavior_zoomTo(z, x0, x1) {
4121
- var K = Math.pow(2, (d3_behavior_zoomXyz[2] = z) - x1[2]),
4122
- x = d3_behavior_zoomXyz[0] = x0[0] - K * x1[0],
4123
- y = d3_behavior_zoomXyz[1] = x0[1] - K * x1[1],
4124
- o = d3.event, // Events can be reentrant (e.g., focus).
4125
- k = Math.pow(2, z);
4568
+ z = d3_behavior_zoomExtentClamp(z, 2);
4569
+ var j = Math.pow(2, d3_behavior_zoomXyz[2]),
4570
+ k = Math.pow(2, z),
4571
+ K = Math.pow(2, (d3_behavior_zoomXyz[2] = z) - x1[2]),
4572
+ x_ = d3_behavior_zoomXyz[0],
4573
+ y_ = d3_behavior_zoomXyz[1],
4574
+ x = d3_behavior_zoomXyz[0] = d3_behavior_zoomExtentClamp((x0[0] - x1[0] * K), 0, k),
4575
+ y = d3_behavior_zoomXyz[1] = d3_behavior_zoomExtentClamp((x0[1] - x1[1] * K), 1, k),
4576
+ o = d3.event; // Events can be reentrant (e.g., focus).
4126
4577
 
4127
4578
  d3.event = {
4128
4579
  scale: k,
4129
4580
  translate: [x, y],
4130
4581
  transform: function(sx, sy) {
4131
- if (sx) transform(sx, x);
4132
- if (sy) transform(sy, y);
4582
+ if (sx) transform(sx, x_, x);
4583
+ if (sy) transform(sy, y_, y);
4133
4584
  }
4134
4585
  };
4135
4586
 
4136
- function transform(scale, o) {
4137
- var domain = scale.__domain || (scale.__domain = scale.domain()),
4138
- range = scale.range().map(function(v) { return (v - o) / k; });
4139
- scale.domain(domain).domain(range.map(scale.invert));
4587
+ function transform(scale, a, b) {
4588
+ scale.domain(scale.range().map(function(v) { return scale.invert(((v - b) * j) / k + a); }));
4140
4589
  }
4141
4590
 
4142
4591
  try {
@@ -4147,4 +4596,20 @@ function d3_behavior_zoomTo(z, x0, x1) {
4147
4596
 
4148
4597
  o.preventDefault();
4149
4598
  }
4599
+
4600
+ var d3_behavior_zoomInfiniteExtent = [
4601
+ [-Infinity, Infinity],
4602
+ [-Infinity, Infinity],
4603
+ [-Infinity, Infinity]
4604
+ ];
4605
+
4606
+ function d3_behavior_zoomExtentClamp(x, i, k) {
4607
+ var range = d3_behavior_zoomExtent[i],
4608
+ r0 = range[0],
4609
+ r1 = range[1];
4610
+ return arguments.length === 3
4611
+ ? Math.max(r1 * (r1 === Infinity ? -Infinity : 1 / k - 1),
4612
+ Math.min(r0 === -Infinity ? Infinity : r0, x / k)) * k
4613
+ : Math.max(r0, Math.min(r1, x));
4614
+ }
4150
4615
  })();
@@ -113,16 +113,19 @@ d3.layout.chord = function() {
113
113
  k = (2 * Math.PI - padding * n) / k;
114
114
 
115
115
  // Compute the start and end angle for each group and subgroup.
116
+ // Note: Opera has a bug reordering object literal properties!
116
117
  x = 0, i = -1; while (++i < n) {
117
118
  x0 = x, j = -1; while (++j < n) {
118
119
  var di = groupIndex[i],
119
120
  dj = subgroupIndex[di][j],
120
- v = matrix[di][dj];
121
+ v = matrix[di][dj],
122
+ a0 = x,
123
+ a1 = x += v * k;
121
124
  subgroups[di + "-" + dj] = {
122
125
  index: di,
123
126
  subindex: dj,
124
- startAngle: x,
125
- endAngle: x += v * k,
127
+ startAngle: a0,
128
+ endAngle: a1,
126
129
  value: v
127
130
  };
128
131
  }
@@ -315,14 +318,14 @@ d3.layout.force = function() {
315
318
  }
316
319
  }
317
320
 
318
- event.tick.dispatch({type: "tick", alpha: alpha});
321
+ event.tick({type: "tick", alpha: alpha});
319
322
 
320
323
  // simulated annealing, basically
321
324
  return (alpha *= .99) < .005;
322
325
  }
323
326
 
324
327
  force.on = function(type, listener) {
325
- event[type].add(listener);
328
+ event.on(type, listener);
326
329
  return force;
327
330
  };
328
331
 
@@ -602,33 +605,31 @@ d3.layout.partition = function() {
602
605
  };
603
606
  d3.layout.pie = function() {
604
607
  var value = Number,
605
- sort = null,
608
+ sort = d3_layout_pieSortByValue,
606
609
  startAngle = 0,
607
610
  endAngle = 2 * Math.PI;
608
611
 
609
612
  function pie(data, i) {
610
613
 
614
+ // Compute the numeric values for each data element.
615
+ var values = data.map(function(d, i) { return +value.call(pie, d, i); });
616
+
611
617
  // Compute the start angle.
612
618
  var a = +(typeof startAngle === "function"
613
619
  ? startAngle.apply(this, arguments)
614
620
  : startAngle);
615
621
 
616
- // Compute the angular range (end - start).
617
- var k = (typeof endAngle === "function"
622
+ // Compute the angular scale factor: from value to radians.
623
+ var k = ((typeof endAngle === "function"
618
624
  ? endAngle.apply(this, arguments)
619
- : endAngle) - startAngle;
625
+ : endAngle) - startAngle)
626
+ / d3.sum(values);
620
627
 
621
628
  // Optionally sort the data.
622
629
  var index = d3.range(data.length);
623
- if (sort != null) index.sort(function(i, j) {
624
- return sort(data[i], data[j]);
625
- });
626
-
627
- // Compute the numeric values for each data element.
628
- var values = data.map(value);
629
-
630
- // Convert k into a scale factor from value to angle, using the sum.
631
- k /= values.reduce(function(p, d) { return p + d; }, 0);
630
+ if (sort != null) index.sort(sort === d3_layout_pieSortByValue
631
+ ? function(i, j) { return values[j] - values[i]; }
632
+ : function(i, j) { return sort(data[i], data[j]); });
632
633
 
633
634
  // Compute the arcs!
634
635
  var arcs = index.map(function(i) {
@@ -695,6 +696,8 @@ d3.layout.pie = function() {
695
696
 
696
697
  return pie;
697
698
  };
699
+
700
+ var d3_layout_pieSortByValue = {};
698
701
  // data is two-dimensional array of x,y; we populate y0
699
702
  d3.layout.stack = function() {
700
703
  var values = Object,
File without changes
File without changes
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: d3_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.10
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-27 00:00:00.000000000Z
12
+ date: 2011-11-06 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: railties
16
- requirement: &70271918844600 !ruby/object:Gem::Requirement
16
+ requirement: &70232077023480 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 3.1.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70271918844600
24
+ version_requirements: *70232077023480
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: bundler
27
- requirement: &70271918844080 !ruby/object:Gem::Requirement
27
+ requirement: &70232077022480 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 1.0.0
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70271918844080
35
+ version_requirements: *70232077022480
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rails
38
- requirement: &70271918843620 !ruby/object:Gem::Requirement
38
+ requirement: &70232077021620 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: '3.1'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70271918843620
46
+ version_requirements: *70232077021620
47
47
  description: Gem installation of javascript framework for data visualization, D3
48
48
  email:
49
49
  - han@logicallsat.com
@@ -63,7 +63,6 @@ files:
63
63
  - vendor/assets/javascripts/.DS_Store
64
64
  - vendor/assets/javascripts/LICENSE
65
65
  - vendor/assets/javascripts/colorbrewer.js
66
- - vendor/assets/javascripts/d3-csv.js
67
66
  - vendor/assets/javascripts/d3.chart.js
68
67
  - vendor/assets/javascripts/d3.csv.js
69
68
  - vendor/assets/javascripts/d3.geo.js
@@ -72,6 +71,7 @@ files:
72
71
  - vendor/assets/javascripts/d3.layout.js
73
72
  - vendor/assets/javascripts/d3.min.js
74
73
  - vendor/assets/javascripts/d3.time.js
74
+ - vendor/assets/javascripts/d3_csv.js
75
75
  - vendor/assets/javascripts/d3_rails.js
76
76
  - vendor/assets/javascripts/science.js
77
77
  - vendor/assets/javascripts/science.lin.js