├── src
├── locale
│ ├── time-scale.js
│ ├── locale.js
│ ├── zh-CN.js
│ ├── en-US.js
│ └── ru-RU.js
├── geo
│ ├── geo.js
│ ├── albers.js
│ ├── compose.js
│ ├── equirectangular.js
│ ├── gnomonic.js
│ ├── orthographic.js
│ ├── spherical.js
│ ├── stereographic.js
│ ├── azimuthal-equal-area.js
│ ├── conic.js
│ ├── azimuthal-equidistant.js
│ ├── distance.js
│ ├── path-bounds.js
│ ├── azimuthal.js
│ ├── index.js
│ ├── conic-equal-area.js
│ ├── conic-equidistant.js
│ ├── transverse-mercator.js
│ ├── cartesian.js
│ ├── conic-conformal.js
│ ├── transform.js
│ ├── path-area.js
│ ├── greatArc.js
│ ├── interpolate.js
│ ├── path-context.js
│ ├── length.js
│ ├── mercator.js
│ └── path-buffer.js
├── svg
│ ├── svg.js
│ ├── index.js
│ ├── area-radial.js
│ ├── line-radial.js
│ ├── diagonal-radial.js
│ └── diagonal.js
├── geom
│ ├── geom.js
│ ├── point.js
│ ├── index.js
│ ├── delaunay.js
│ └── clip-line.js
├── core
│ ├── noop.js
│ ├── true.js
│ ├── identity.js
│ ├── index.js
│ ├── source.js
│ ├── target.js
│ ├── array.js
│ ├── functor.js
│ ├── class.js
│ ├── subclass.js
│ ├── vendor.js
│ ├── document.js
│ ├── ns.js
│ └── rebind.js
├── layout
│ ├── layout.js
│ ├── index.js
│ └── partition.js
├── math
│ ├── abs.js
│ ├── index.js
│ ├── number.js
│ ├── random.js
│ ├── adder.js
│ └── trigonometry.js
├── behavior
│ ├── behavior.js
│ └── index.js
├── selection
│ ├── index.js
│ ├── empty.js
│ ├── size.js
│ ├── datum.js
│ ├── call.js
│ ├── interrupt.js
│ ├── remove.js
│ ├── node.js
│ ├── insert.js
│ ├── html.js
│ ├── order.js
│ ├── text.js
│ ├── each.js
│ ├── sort.js
│ ├── append.js
│ ├── enter-insert.js
│ ├── transition.js
│ ├── enter.js
│ ├── enter-select.js
│ ├── filter.js
│ ├── selectAll.js
│ ├── select.js
│ └── property.js
├── transition
│ ├── index.js
│ ├── remove.js
│ ├── text.js
│ ├── delay.js
│ ├── ease.js
│ ├── duration.js
│ ├── filter.js
│ ├── subtransition.js
│ ├── each.js
│ ├── tween.js
│ ├── select.js
│ └── selectAll.js
├── compat
│ ├── index.js
│ ├── date.js
│ └── style.js
├── dsv
│ ├── index.js
│ ├── csv.js
│ └── tsv.js
├── start.js
├── time
│ ├── format-utc.js
│ ├── format.js
│ ├── index.js
│ ├── month.js
│ ├── year.js
│ ├── minute.js
│ ├── second.js
│ ├── hour.js
│ ├── format-iso.js
│ ├── day.js
│ ├── scale-utc.js
│ └── week.js
├── format
│ ├── collapse.js
│ ├── format.js
│ ├── index.js
│ ├── precision.js
│ ├── round.js
│ ├── requote.js
│ └── formatPrefix.js
├── xhr
│ ├── index.js
│ ├── xml.js
│ ├── text.js
│ ├── json.js
│ └── html.js
├── arrays
│ ├── ascending.js
│ ├── descending.js
│ ├── transpose.js
│ ├── keys.js
│ ├── values.js
│ ├── entries.js
│ ├── permute.js
│ ├── pairs.js
│ ├── shuffle.js
│ ├── quantile.js
│ ├── median.js
│ ├── sum.js
│ ├── zip.js
│ ├── mean.js
│ ├── merge.js
│ ├── index.js
│ ├── max.js
│ ├── min.js
│ ├── extent.js
│ ├── range.js
│ ├── set.js
│ └── bisect.js
├── event
│ ├── index.js
│ ├── touches.js
│ ├── drag.js
│ └── mouse.js
├── color
│ ├── index.js
│ ├── color.js
│ ├── xyz.js
│ ├── hcl.js
│ └── hsl.js
├── scale
│ ├── sqrt.js
│ ├── bilinear.js
│ ├── index.js
│ ├── scale.js
│ ├── polylinear.js
│ ├── nice.js
│ ├── identity.js
│ ├── threshold.js
│ ├── quantize.js
│ ├── quantile.js
│ ├── pow.js
│ └── category.js
├── interpolate
│ ├── number.js
│ ├── round.js
│ ├── index.js
│ ├── uninterpolate.js
│ ├── lab.js
│ ├── rgb.js
│ ├── object.js
│ ├── array.js
│ ├── hcl.js
│ ├── hsl.js
│ ├── interpolate.js
│ └── zoom.js
├── end.js
└── d3.js
├── test
├── data
│ ├── sample.txt
│ ├── sample.csv
│ ├── sample.tsv
│ ├── sample.json
│ ├── sample.html
│ └── sample.xml
├── geo
│ ├── area-benchmark.js
│ ├── point-in-polygon-mock.js
│ ├── distance-test.js
│ ├── interpolate-test.js
│ ├── projection-test-suite.js
│ ├── greatArc-test.js
│ ├── rotation-test.js
│ ├── albers-usa-test.js
│ └── albers-test.js
├── core
│ ├── version-test.js
│ └── functor-test.js
├── time
│ ├── dayOfYear-test.js
│ ├── time.js
│ └── format-iso-test.js
├── interpolate
│ ├── round-test.js
│ ├── number-test.js
│ ├── array-test.js
│ ├── rgb-test.js
│ └── lab-test.js
├── event
│ ├── mouse-test.html
│ └── touch-test.html
├── geom
│ └── voronoi-benchmark
├── math
│ ├── transform-null-test.html
│ ├── transform-null-matrix-test.html
│ └── transform-rotate-origin-test.html
├── layout
│ ├── pie-test.js
│ ├── tree-test.js
│ ├── hierarchy-test.js
│ ├── cluster-test.js
│ └── partition-test.js
├── transition
│ ├── transition-test-id.js
│ ├── transition-test-text.js
│ ├── transition-test-call.js
│ ├── transition-test-size.js
│ ├── transition-test-node.js
│ ├── transition-test-time.js
│ └── transition-test-transition.js
├── arrays
│ ├── keys-test.js
│ ├── values-test.js
│ ├── zip-test.js
│ ├── pairs-test.js
│ ├── transpose-test.js
│ ├── entries-test.js
│ ├── mean-test.js
│ ├── ascending-test.js
│ ├── sum-test.js
│ ├── descending-test.js
│ └── median-test.js
├── selection
│ ├── enter-test.js
│ ├── order-test.js
│ ├── remove-test.js
│ ├── interrupt-test.js
│ ├── selection-test.js
│ ├── size-test.js
│ └── empty-test.js
├── xhr
│ ├── html-test.js
│ ├── text-test.js
│ └── xml-test.js
├── format
│ └── requote-test.js
├── XMLHttpRequest.js
└── load.js
├── .gitignore
├── .travis.yml
├── .npmignore
├── bin
├── start
├── component
├── bower
└── uglify
├── lib
├── science
│ ├── science.lin.min.js
│ ├── science.lin.js
│ └── LICENSE
├── geographiclib
│ └── LICENSE
├── rhill-voronoi
│ └── LICENSE
├── polymaps
│ └── LICENSE
├── protovis
│ └── LICENSE
└── penner
│ └── LICENSE
├── bower.json
├── component.json
├── composer.json
├── Makefile
├── README.md
├── index.js
├── package.json
└── LICENSE
/src/locale/time-scale.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/geo/geo.js:
--------------------------------------------------------------------------------
1 | d3.geo = {};
2 |
--------------------------------------------------------------------------------
/src/svg/svg.js:
--------------------------------------------------------------------------------
1 | d3.svg = {};
2 |
--------------------------------------------------------------------------------
/src/geom/geom.js:
--------------------------------------------------------------------------------
1 | d3.geom = {};
2 |
--------------------------------------------------------------------------------
/test/data/sample.txt:
--------------------------------------------------------------------------------
1 | Hello, world!
2 |
--------------------------------------------------------------------------------
/src/core/noop.js:
--------------------------------------------------------------------------------
1 | function d3_noop() {}
2 |
--------------------------------------------------------------------------------
/src/layout/layout.js:
--------------------------------------------------------------------------------
1 | d3.layout = {};
2 |
--------------------------------------------------------------------------------
/src/math/abs.js:
--------------------------------------------------------------------------------
1 | var abs = Math.abs;
2 |
--------------------------------------------------------------------------------
/src/behavior/behavior.js:
--------------------------------------------------------------------------------
1 | d3.behavior = {};
2 |
--------------------------------------------------------------------------------
/src/selection/index.js:
--------------------------------------------------------------------------------
1 | import "selection";
2 |
--------------------------------------------------------------------------------
/src/transition/index.js:
--------------------------------------------------------------------------------
1 | import "transition";
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | _site
2 | node_modules
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/src/compat/index.js:
--------------------------------------------------------------------------------
1 | import "date";
2 | import "style";
3 |
--------------------------------------------------------------------------------
/test/data/sample.csv:
--------------------------------------------------------------------------------
1 | Hello,World
2 | 42,"""fish"""
3 |
--------------------------------------------------------------------------------
/test/data/sample.tsv:
--------------------------------------------------------------------------------
1 | Hello World
2 | 42 """fish"""
3 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - 0.10
4 |
--------------------------------------------------------------------------------
/src/math/index.js:
--------------------------------------------------------------------------------
1 | import "random";
2 | import "transform";
3 |
--------------------------------------------------------------------------------
/test/data/sample.json:
--------------------------------------------------------------------------------
1 | [{"Hello": 42, "World": "\"fish\""}]
2 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | examples/
2 | test/
3 | lib/
4 | .DS_Store
5 | _site
6 |
--------------------------------------------------------------------------------
/src/core/true.js:
--------------------------------------------------------------------------------
1 | function d3_true() {
2 | return true;
3 | }
4 |
--------------------------------------------------------------------------------
/src/core/identity.js:
--------------------------------------------------------------------------------
1 | function d3_identity(d) {
2 | return d;
3 | }
4 |
--------------------------------------------------------------------------------
/src/dsv/index.js:
--------------------------------------------------------------------------------
1 | import "dsv";
2 | import "csv";
3 | import "tsv";
4 |
--------------------------------------------------------------------------------
/src/core/index.js:
--------------------------------------------------------------------------------
1 | import "functor";
2 | import "ns";
3 | import "rebind";
4 |
--------------------------------------------------------------------------------
/src/core/source.js:
--------------------------------------------------------------------------------
1 | function d3_source(d) {
2 | return d.source;
3 | }
4 |
--------------------------------------------------------------------------------
/src/core/target.js:
--------------------------------------------------------------------------------
1 | function d3_target(d) {
2 | return d.target;
3 | }
4 |
--------------------------------------------------------------------------------
/src/dsv/csv.js:
--------------------------------------------------------------------------------
1 | import "dsv";
2 |
3 | d3.csv = d3.dsv(",", "text/csv");
4 |
--------------------------------------------------------------------------------
/src/start.js:
--------------------------------------------------------------------------------
1 | !function(){
2 | var d3 = {version: "3.4.3"}; // semver
3 |
--------------------------------------------------------------------------------
/src/behavior/index.js:
--------------------------------------------------------------------------------
1 | import "behavior";
2 | import "drag";
3 | import "zoom";
4 |
--------------------------------------------------------------------------------
/src/compat/date.js:
--------------------------------------------------------------------------------
1 | if (!Date.now) Date.now = function() {
2 | return +new Date;
3 | };
4 |
--------------------------------------------------------------------------------
/src/dsv/tsv.js:
--------------------------------------------------------------------------------
1 | import "dsv";
2 |
3 | d3.tsv = d3.dsv("\t", "text/tab-separated-values");
4 |
--------------------------------------------------------------------------------
/src/math/number.js:
--------------------------------------------------------------------------------
1 | function d3_number(x) {
2 | return x != null && !isNaN(x);
3 | }
4 |
--------------------------------------------------------------------------------
/src/time/format-utc.js:
--------------------------------------------------------------------------------
1 | import "format";
2 |
3 | var d3_time_formatUtc = d3_time_format.utc;
4 |
--------------------------------------------------------------------------------
/src/format/collapse.js:
--------------------------------------------------------------------------------
1 | function d3_collapse(s) {
2 | return s.trim().replace(/\s+/g, " ");
3 | }
4 |
--------------------------------------------------------------------------------
/src/format/format.js:
--------------------------------------------------------------------------------
1 | import "../locale/en-US";
2 |
3 | d3.format = d3_locale_enUS.numberFormat;
4 |
--------------------------------------------------------------------------------
/src/format/index.js:
--------------------------------------------------------------------------------
1 | import "format";
2 | import "formatPrefix";
3 | import "requote";
4 | import "round";
5 |
--------------------------------------------------------------------------------
/src/xhr/index.js:
--------------------------------------------------------------------------------
1 | import "xhr";
2 | import "text";
3 | import "json";
4 | import "html";
5 | import "xml";
6 |
--------------------------------------------------------------------------------
/test/data/sample.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Hello & world!
5 |
6 |
--------------------------------------------------------------------------------
/test/data/sample.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/arrays/ascending.js:
--------------------------------------------------------------------------------
1 | d3.ascending = function(a, b) {
2 | return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
3 | };
4 |
--------------------------------------------------------------------------------
/src/event/index.js:
--------------------------------------------------------------------------------
1 | import "dispatch";
2 | import "event";
3 | import "mouse";
4 | import "touches";
5 | import "timer";
6 |
--------------------------------------------------------------------------------
/src/xhr/xml.js:
--------------------------------------------------------------------------------
1 | import "xhr";
2 |
3 | d3.xml = d3_xhrType(function(request) {
4 | return request.responseXML;
5 | });
6 |
--------------------------------------------------------------------------------
/src/arrays/descending.js:
--------------------------------------------------------------------------------
1 | d3.descending = function(a, b) {
2 | return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
3 | };
4 |
--------------------------------------------------------------------------------
/src/color/index.js:
--------------------------------------------------------------------------------
1 | import "color";
2 | import "rgb";
3 | import "hsl";
4 | import "hcl";
5 | import "lab";
6 | import "xyz";
7 |
--------------------------------------------------------------------------------
/src/xhr/text.js:
--------------------------------------------------------------------------------
1 | import "xhr";
2 |
3 | d3.text = d3_xhrType(function(request) {
4 | return request.responseText;
5 | });
6 |
--------------------------------------------------------------------------------
/src/arrays/transpose.js:
--------------------------------------------------------------------------------
1 | import "zip";
2 |
3 | d3.transpose = function(matrix) {
4 | return d3.zip.apply(d3, matrix);
5 | };
6 |
--------------------------------------------------------------------------------
/src/format/precision.js:
--------------------------------------------------------------------------------
1 | function d3_format_precision(x, p) {
2 | return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1);
3 | }
4 |
--------------------------------------------------------------------------------
/src/selection/empty.js:
--------------------------------------------------------------------------------
1 | import "selection";
2 |
3 | d3_selectionPrototype.empty = function() {
4 | return !this.node();
5 | };
6 |
--------------------------------------------------------------------------------
/src/arrays/keys.js:
--------------------------------------------------------------------------------
1 | d3.keys = function(map) {
2 | var keys = [];
3 | for (var key in map) keys.push(key);
4 | return keys;
5 | };
6 |
--------------------------------------------------------------------------------
/src/color/color.js:
--------------------------------------------------------------------------------
1 | function d3_Color() {}
2 |
3 | d3_Color.prototype.toString = function() {
4 | return this.rgb() + "";
5 | };
6 |
--------------------------------------------------------------------------------
/src/geom/point.js:
--------------------------------------------------------------------------------
1 | function d3_geom_pointX(d) {
2 | return d[0];
3 | }
4 |
5 | function d3_geom_pointY(d) {
6 | return d[1];
7 | }
8 |
--------------------------------------------------------------------------------
/src/scale/sqrt.js:
--------------------------------------------------------------------------------
1 | import "pow";
2 | import "scale";
3 |
4 | d3.scale.sqrt = function() {
5 | return d3.scale.pow().exponent(.5);
6 | };
7 |
--------------------------------------------------------------------------------
/src/time/format.js:
--------------------------------------------------------------------------------
1 | import "../locale/en-US";
2 | import "time";
3 |
4 | var d3_time_format = d3_time.format = d3_locale_enUS.timeFormat;
5 |
--------------------------------------------------------------------------------
/src/geom/index.js:
--------------------------------------------------------------------------------
1 | import "geom";
2 | import "hull";
3 | import "polygon";
4 | import "voronoi";
5 | import "delaunay";
6 | import "quadtree";
7 |
--------------------------------------------------------------------------------
/src/arrays/values.js:
--------------------------------------------------------------------------------
1 | d3.values = function(map) {
2 | var values = [];
3 | for (var key in map) values.push(map[key]);
4 | return values;
5 | };
6 |
--------------------------------------------------------------------------------
/src/core/array.js:
--------------------------------------------------------------------------------
1 | var d3_arraySlice = [].slice,
2 | d3_array = function(list) { return d3_arraySlice.call(list); }; // conversion for NodeLists
3 |
--------------------------------------------------------------------------------
/src/core/functor.js:
--------------------------------------------------------------------------------
1 | function d3_functor(v) {
2 | return typeof v === "function" ? v : function() { return v; };
3 | }
4 |
5 | d3.functor = d3_functor;
6 |
--------------------------------------------------------------------------------
/src/format/round.js:
--------------------------------------------------------------------------------
1 | d3.round = function(x, n) {
2 | return n
3 | ? Math.round(x * (n = Math.pow(10, n))) / n
4 | : Math.round(x);
5 | };
6 |
--------------------------------------------------------------------------------
/bin/start:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | console.log("!function(){\n var d3 = {version: " + JSON.stringify(require("../package.json").version) + "}; // semver");
4 |
--------------------------------------------------------------------------------
/src/format/requote.js:
--------------------------------------------------------------------------------
1 | d3.requote = function(s) {
2 | return s.replace(d3_requote_re, "\\$&");
3 | };
4 |
5 | var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
6 |
--------------------------------------------------------------------------------
/src/arrays/entries.js:
--------------------------------------------------------------------------------
1 | d3.entries = function(map) {
2 | var entries = [];
3 | for (var key in map) entries.push({key: key, value: map[key]});
4 | return entries;
5 | };
6 |
--------------------------------------------------------------------------------
/src/selection/size.js:
--------------------------------------------------------------------------------
1 | import "selection";
2 |
3 | d3_selectionPrototype.size = function() {
4 | var n = 0;
5 | this.each(function() { ++n; });
6 | return n;
7 | };
8 |
--------------------------------------------------------------------------------
/src/interpolate/number.js:
--------------------------------------------------------------------------------
1 | d3.interpolateNumber = d3_interpolateNumber;
2 |
3 | function d3_interpolateNumber(a, b) {
4 | b -= a = +a;
5 | return function(t) { return a + b * t; };
6 | }
7 |
--------------------------------------------------------------------------------
/src/interpolate/round.js:
--------------------------------------------------------------------------------
1 | d3.interpolateRound = d3_interpolateRound;
2 |
3 | function d3_interpolateRound(a, b) {
4 | b -= a;
5 | return function(t) { return Math.round(a + b * t); };
6 | }
7 |
--------------------------------------------------------------------------------
/src/arrays/permute.js:
--------------------------------------------------------------------------------
1 | d3.permute = function(array, indexes) {
2 | var i = indexes.length, permutes = new Array(i);
3 | while (i--) permutes[i] = array[indexes[i]];
4 | return permutes;
5 | };
6 |
--------------------------------------------------------------------------------
/src/geom/delaunay.js:
--------------------------------------------------------------------------------
1 | import "geom";
2 |
3 | // @deprecated; use d3.geom.voronoi triangles instead.
4 | d3.geom.delaunay = function(vertices) {
5 | return d3.geom.voronoi().triangles(vertices);
6 | };
7 |
--------------------------------------------------------------------------------
/src/selection/datum.js:
--------------------------------------------------------------------------------
1 | import "selection";
2 |
3 | d3_selectionPrototype.datum = function(value) {
4 | return arguments.length
5 | ? this.property("__data__", value)
6 | : this.property("__data__");
7 | };
8 |
--------------------------------------------------------------------------------
/src/arrays/pairs.js:
--------------------------------------------------------------------------------
1 | d3.pairs = function(array) {
2 | var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n < 0 ? 0 : n);
3 | while (i < n) pairs[i] = [p0 = p1, p1 = array[++i]];
4 | return pairs;
5 | };
6 |
--------------------------------------------------------------------------------
/src/arrays/shuffle.js:
--------------------------------------------------------------------------------
1 | d3.shuffle = function(array) {
2 | var m = array.length, t, i;
3 | while (m) {
4 | i = Math.random() * m-- | 0;
5 | t = array[m], array[m] = array[i], array[i] = t;
6 | }
7 | return array;
8 | };
9 |
--------------------------------------------------------------------------------
/src/end.js:
--------------------------------------------------------------------------------
1 | if (typeof define === "function" && define.amd) {
2 | define(d3);
3 | } else if (typeof module === "object" && module.exports) {
4 | module.exports = d3;
5 | } else {
6 | this.d3 = d3;
7 | }
8 | }();
9 |
--------------------------------------------------------------------------------
/lib/science/science.lin.min.js:
--------------------------------------------------------------------------------
1 | (function(){science.lin={},science.lin.tridag=function(a,b,c,d,e,f){var g,h;for(g=1;g=0;g--)e[g]=(d[g]-c[g]*e[g+1])/b[g]}})()
--------------------------------------------------------------------------------
/src/selection/call.js:
--------------------------------------------------------------------------------
1 | import "../core/array";
2 | import "selection";
3 |
4 | d3_selectionPrototype.call = function(callback) {
5 | var args = d3_array(arguments);
6 | callback.apply(args[0] = this, args);
7 | return this;
8 | };
9 |
--------------------------------------------------------------------------------
/src/xhr/json.js:
--------------------------------------------------------------------------------
1 | import "xhr";
2 |
3 | d3.json = function(url, callback) {
4 | return d3_xhr(url, "application/json", d3_json, callback);
5 | };
6 |
7 | function d3_json(request) {
8 | return JSON.parse(request.responseText);
9 | }
10 |
--------------------------------------------------------------------------------
/src/locale/locale.js:
--------------------------------------------------------------------------------
1 | import "number-format";
2 | import "time-format";
3 |
4 | d3.locale = function(locale) {
5 | return {
6 | numberFormat: d3_locale_numberFormat(locale),
7 | timeFormat: d3_locale_timeFormat(locale)
8 | };
9 | };
10 |
--------------------------------------------------------------------------------
/src/color/xyz.js:
--------------------------------------------------------------------------------
1 | function d3_xyz_lab(x) {
2 | return x > 0.008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29;
3 | }
4 |
5 | function d3_xyz_rgb(r) {
6 | return Math.round(255 * (r <= 0.00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - 0.055));
7 | }
8 |
--------------------------------------------------------------------------------
/src/scale/bilinear.js:
--------------------------------------------------------------------------------
1 | function d3_scale_bilinear(domain, range, uninterpolate, interpolate) {
2 | var u = uninterpolate(domain[0], domain[1]),
3 | i = interpolate(range[0], range[1]);
4 | return function(x) {
5 | return i(u(x));
6 | };
7 | }
8 |
--------------------------------------------------------------------------------
/src/scale/index.js:
--------------------------------------------------------------------------------
1 | import "scale";
2 | import "linear";
3 | import "log";
4 | import "pow";
5 | import "sqrt";
6 | import "ordinal";
7 | import "category";
8 | import "quantile";
9 | import "quantize";
10 | import "threshold";
11 | import "identity";
12 |
--------------------------------------------------------------------------------
/src/transition/remove.js:
--------------------------------------------------------------------------------
1 | import "transition";
2 |
3 | d3_transitionPrototype.remove = function() {
4 | return this.each("end.transition", function() {
5 | var p;
6 | if (this.__transition__.count < 2 && (p = this.parentNode)) p.removeChild(this);
7 | });
8 | };
9 |
--------------------------------------------------------------------------------
/src/svg/index.js:
--------------------------------------------------------------------------------
1 | import "svg";
2 | import "arc";
3 | import "line";
4 | import "line-radial";
5 | import "area";
6 | import "area-radial";
7 | import "chord";
8 | import "diagonal";
9 | import "diagonal-radial";
10 | import "symbol";
11 | import "axis";
12 | import "brush";
13 |
--------------------------------------------------------------------------------
/src/arrays/quantile.js:
--------------------------------------------------------------------------------
1 | // R-7 per
2 | d3.quantile = function(values, p) {
3 | var H = (values.length - 1) * p + 1,
4 | h = Math.floor(H),
5 | v = +values[h - 1],
6 | e = H - h;
7 | return e ? v + e * (values[h] - v) : v;
8 | };
9 |
--------------------------------------------------------------------------------
/src/geo/albers.js:
--------------------------------------------------------------------------------
1 | import "conic-equal-area";
2 | import "geo";
3 |
4 | // ESRI:102003
5 | d3.geo.albers = function() {
6 | return d3.geo.conicEqualArea()
7 | .rotate([96, 0])
8 | .center([-.6, 38.7])
9 | .parallels([29.5, 45.5])
10 | .scale(1070);
11 | };
12 |
--------------------------------------------------------------------------------
/src/layout/index.js:
--------------------------------------------------------------------------------
1 | import "layout";
2 | import "bundle";
3 | import "chord";
4 | import "force";
5 | import "partition";
6 | import "pie";
7 | import "stack";
8 | import "histogram";
9 | import "hierarchy";
10 | import "pack";
11 | import "cluster";
12 | import "tree";
13 | import "treemap";
14 |
--------------------------------------------------------------------------------
/src/time/index.js:
--------------------------------------------------------------------------------
1 | import "time";
2 | import "format";
3 | import "format-utc";
4 | import "format-iso";
5 | import "interval";
6 | import "second";
7 | import "minute";
8 | import "hour";
9 | import "day";
10 | import "week";
11 | import "month";
12 | import "year";
13 | import "scale";
14 | import "scale-utc";
15 |
--------------------------------------------------------------------------------
/src/arrays/median.js:
--------------------------------------------------------------------------------
1 | import "../math/number";
2 | import "ascending";
3 | import "quantile";
4 |
5 | d3.median = function(array, f) {
6 | if (arguments.length > 1) array = array.map(f);
7 | array = array.filter(d3_number);
8 | return array.length ? d3.quantile(array.sort(d3.ascending), .5) : undefined;
9 | };
10 |
--------------------------------------------------------------------------------
/src/geo/compose.js:
--------------------------------------------------------------------------------
1 | function d3_geo_compose(a, b) {
2 |
3 | function compose(x, y) {
4 | return x = a(x, y), b(x[0], x[1]);
5 | }
6 |
7 | if (a.invert && b.invert) compose.invert = function(x, y) {
8 | return x = b.invert(x, y), x && a.invert(x[0], x[1]);
9 | };
10 |
11 | return compose;
12 | }
13 |
--------------------------------------------------------------------------------
/src/geo/equirectangular.js:
--------------------------------------------------------------------------------
1 | import "geo";
2 | import "projection";
3 |
4 | function d3_geo_equirectangular(λ, φ) {
5 | return [λ, φ];
6 | }
7 |
8 | (d3.geo.equirectangular = function() {
9 | return d3_geo_projection(d3_geo_equirectangular);
10 | }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular;
11 |
--------------------------------------------------------------------------------
/src/interpolate/index.js:
--------------------------------------------------------------------------------
1 | import "array";
2 | import "ease";
3 | import "hcl";
4 | import "hsl";
5 | import "interpolate";
6 | import "lab";
7 | import "number";
8 | import "object";
9 | import "rgb";
10 | import "round";
11 | import "string";
12 | import "transform";
13 | import "uninterpolate";
14 | import "zoom";
15 |
--------------------------------------------------------------------------------
/src/core/class.js:
--------------------------------------------------------------------------------
1 | function d3_class(ctor, properties) {
2 | try {
3 | for (var key in properties) {
4 | Object.defineProperty(ctor.prototype, key, {
5 | value: properties[key],
6 | enumerable: false
7 | });
8 | }
9 | } catch (e) {
10 | ctor.prototype = properties;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/selection/interrupt.js:
--------------------------------------------------------------------------------
1 | // import "../transition/transition";
2 | import "selection";
3 |
4 | d3_selectionPrototype.interrupt = function() {
5 | return this.each(d3_selection_interrupt);
6 | };
7 |
8 | function d3_selection_interrupt() {
9 | var lock = this.__transition__;
10 | if (lock) ++lock.active;
11 | }
12 |
--------------------------------------------------------------------------------
/src/selection/remove.js:
--------------------------------------------------------------------------------
1 | import "selection";
2 |
3 | // TODO remove(selector)?
4 | // TODO remove(node)?
5 | // TODO remove(function)?
6 | d3_selectionPrototype.remove = function() {
7 | return this.each(function() {
8 | var parent = this.parentNode;
9 | if (parent) parent.removeChild(this);
10 | });
11 | };
12 |
--------------------------------------------------------------------------------
/src/geo/gnomonic.js:
--------------------------------------------------------------------------------
1 | import "azimuthal";
2 | import "geo";
3 | import "projection";
4 |
5 | var d3_geo_gnomonic = d3_geo_azimuthal(
6 | function(cosλcosφ) { return 1 / cosλcosφ; },
7 | Math.atan
8 | );
9 |
10 | (d3.geo.gnomonic = function() {
11 | return d3_geo_projection(d3_geo_gnomonic);
12 | }).raw = d3_geo_gnomonic;
13 |
--------------------------------------------------------------------------------
/src/geo/orthographic.js:
--------------------------------------------------------------------------------
1 | import "azimuthal";
2 | import "geo";
3 | import "projection";
4 |
5 | var d3_geo_orthographic = d3_geo_azimuthal(
6 | function() { return 1; },
7 | Math.asin
8 | );
9 |
10 | (d3.geo.orthographic = function() {
11 | return d3_geo_projection(d3_geo_orthographic);
12 | }).raw = d3_geo_orthographic;
13 |
--------------------------------------------------------------------------------
/src/selection/node.js:
--------------------------------------------------------------------------------
1 | import "selection";
2 |
3 | d3_selectionPrototype.node = function() {
4 | for (var j = 0, m = this.length; j < m; j++) {
5 | for (var group = this[j], i = 0, n = group.length; i < n; i++) {
6 | var node = group[i];
7 | if (node) return node;
8 | }
9 | }
10 | return null;
11 | };
12 |
--------------------------------------------------------------------------------
/src/transition/text.js:
--------------------------------------------------------------------------------
1 | import "transition";
2 | import "tween";
3 |
4 | d3_transitionPrototype.text = function(value) {
5 | return d3_transition_tween(this, "text", value, d3_transition_text);
6 | };
7 |
8 | function d3_transition_text(b) {
9 | if (b == null) b = "";
10 | return function() { this.textContent = b; };
11 | }
12 |
--------------------------------------------------------------------------------
/src/scale/scale.js:
--------------------------------------------------------------------------------
1 | d3.scale = {};
2 |
3 | function d3_scaleExtent(domain) {
4 | var start = domain[0], stop = domain[domain.length - 1];
5 | return start < stop ? [start, stop] : [stop, start];
6 | }
7 |
8 | function d3_scaleRange(scale) {
9 | return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range());
10 | }
11 |
--------------------------------------------------------------------------------
/src/interpolate/uninterpolate.js:
--------------------------------------------------------------------------------
1 | function d3_uninterpolateNumber(a, b) {
2 | b = b - (a = +a) ? 1 / (b - a) : 0;
3 | return function(x) { return (x - a) * b; };
4 | }
5 |
6 | function d3_uninterpolateClamp(a, b) {
7 | b = b - (a = +a) ? 1 / (b - a) : 0;
8 | return function(x) { return Math.max(0, Math.min(1, (x - a) * b)); };
9 | }
10 |
--------------------------------------------------------------------------------
/src/geo/spherical.js:
--------------------------------------------------------------------------------
1 | import "../math/abs";
2 | import "../math/trigonometry";
3 |
4 | function d3_geo_spherical(cartesian) {
5 | return [
6 | Math.atan2(cartesian[1], cartesian[0]),
7 | d3_asin(cartesian[2])
8 | ];
9 | }
10 |
11 | function d3_geo_sphericalEqual(a, b) {
12 | return abs(a[0] - b[0]) < ε && abs(a[1] - b[1]) < ε;
13 | }
14 |
--------------------------------------------------------------------------------
/src/selection/insert.js:
--------------------------------------------------------------------------------
1 | import "selection";
2 |
3 | d3_selectionPrototype.insert = function(name, before) {
4 | name = d3_selection_creator(name);
5 | before = d3_selection_selector(before);
6 | return this.select(function() {
7 | return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null);
8 | });
9 | };
10 |
--------------------------------------------------------------------------------
/src/arrays/sum.js:
--------------------------------------------------------------------------------
1 | d3.sum = function(array, f) {
2 | var s = 0,
3 | n = array.length,
4 | a,
5 | i = -1;
6 |
7 | if (arguments.length === 1) {
8 | while (++i < n) if (!isNaN(a = +array[i])) s += a;
9 | } else {
10 | while (++i < n) if (!isNaN(a = +f.call(array, array[i], i))) s += a;
11 | }
12 |
13 | return s;
14 | };
15 |
--------------------------------------------------------------------------------
/test/geo/area-benchmark.js:
--------------------------------------------------------------------------------
1 | var d3 = require("../../");
2 |
3 | var formatNumber = d3.format(",.02r"),
4 | o = d3.geo.circle().angle(30).precision(.1)(),
5 | n = 1e3,
6 | then = Date.now();
7 |
8 | for (var i = 0; i < n; i++) {
9 | d3.geo.area(o);
10 | }
11 |
12 | console.log("circle.angle(30°): " + formatNumber((Date.now() - then) / i) + "ms/op.");
13 |
--------------------------------------------------------------------------------
/src/xhr/html.js:
--------------------------------------------------------------------------------
1 | import "../core/document";
2 | import "xhr";
3 |
4 | d3.html = function(url, callback) {
5 | return d3_xhr(url, "text/html", d3_html, callback);
6 | };
7 |
8 | function d3_html(request) {
9 | var range = d3_document.createRange();
10 | range.selectNode(d3_document.body);
11 | return range.createContextualFragment(request.responseText);
12 | }
13 |
--------------------------------------------------------------------------------
/src/geo/stereographic.js:
--------------------------------------------------------------------------------
1 | import "azimuthal";
2 | import "geo";
3 | import "projection";
4 |
5 | var d3_geo_stereographic = d3_geo_azimuthal(
6 | function(cosλcosφ) { return 1 / (1 + cosλcosφ); },
7 | function(ρ) { return 2 * Math.atan(ρ); }
8 | );
9 |
10 | (d3.geo.stereographic = function() {
11 | return d3_geo_projection(d3_geo_stereographic);
12 | }).raw = d3_geo_stereographic;
13 |
--------------------------------------------------------------------------------
/src/event/touches.js:
--------------------------------------------------------------------------------
1 | import "../core/array";
2 | import "event";
3 | import "mouse";
4 |
5 | d3.touches = function(container, touches) {
6 | if (arguments.length < 2) touches = d3_eventSource().touches;
7 | return touches ? d3_array(touches).map(function(touch) {
8 | var point = d3_mousePoint(container, touch);
9 | point.identifier = touch.identifier;
10 | return point;
11 | }) : [];
12 | };
13 |
--------------------------------------------------------------------------------
/src/arrays/zip.js:
--------------------------------------------------------------------------------
1 | import "min";
2 |
3 | d3.zip = function() {
4 | if (!(n = arguments.length)) return [];
5 | for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m;) {
6 | for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n;) {
7 | zip[j] = arguments[j][i];
8 | }
9 | }
10 | return zips;
11 | };
12 |
13 | function d3_zipLength(d) {
14 | return d.length;
15 | }
16 |
--------------------------------------------------------------------------------
/src/core/subclass.js:
--------------------------------------------------------------------------------
1 | var d3_subclass = {}.__proto__?
2 |
3 | // Until ECMAScript supports array subclassing, prototype injection works well.
4 | function(object, prototype) {
5 | object.__proto__ = prototype;
6 | }:
7 |
8 | // And if your browser doesn't support __proto__, we'll use direct extension.
9 | function(object, prototype) {
10 | for (var property in prototype) object[property] = prototype[property];
11 | };
12 |
--------------------------------------------------------------------------------
/src/transition/delay.js:
--------------------------------------------------------------------------------
1 | import "../selection/each";
2 | import "transition";
3 |
4 | d3_transitionPrototype.delay = function(value) {
5 | var id = this.id;
6 | return d3_selection_each(this, typeof value === "function"
7 | ? function(node, i, j) { node.__transition__[id].delay = +value.call(node, node.__data__, i, j); }
8 | : (value = +value, function(node) { node.__transition__[id].delay = value; }));
9 | };
10 |
--------------------------------------------------------------------------------
/src/geo/azimuthal-equal-area.js:
--------------------------------------------------------------------------------
1 | import "azimuthal";
2 | import "geo";
3 | import "projection";
4 |
5 | var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(
6 | function(cosλcosφ) { return Math.sqrt(2 / (1 + cosλcosφ)); },
7 | function(ρ) { return 2 * Math.asin(ρ / 2); }
8 | );
9 |
10 | (d3.geo.azimuthalEqualArea = function() {
11 | return d3_geo_projection(d3_geo_azimuthalEqualArea);
12 | }).raw = d3_geo_azimuthalEqualArea;
13 |
--------------------------------------------------------------------------------
/src/interpolate/lab.js:
--------------------------------------------------------------------------------
1 | import "../color/lab";
2 |
3 | d3.interpolateLab = d3_interpolateLab;
4 |
5 | function d3_interpolateLab(a, b) {
6 | a = d3.lab(a);
7 | b = d3.lab(b);
8 | var al = a.l,
9 | aa = a.a,
10 | ab = a.b,
11 | bl = b.l - al,
12 | ba = b.a - aa,
13 | bb = b.b - ab;
14 | return function(t) {
15 | return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + "";
16 | };
17 | }
18 |
--------------------------------------------------------------------------------
/src/selection/html.js:
--------------------------------------------------------------------------------
1 | import "selection";
2 |
3 | d3_selectionPrototype.html = function(value) {
4 | return arguments.length
5 | ? this.each(typeof value === "function"
6 | ? function() { var v = value.apply(this, arguments); this.innerHTML = v == null ? "" : v; } : value == null
7 | ? function() { this.innerHTML = ""; }
8 | : function() { this.innerHTML = value; })
9 | : this.node().innerHTML;
10 | };
11 |
--------------------------------------------------------------------------------
/src/arrays/mean.js:
--------------------------------------------------------------------------------
1 | import "../math/number";
2 |
3 | d3.mean = function(array, f) {
4 | var n = array.length,
5 | a,
6 | m = 0,
7 | i = -1,
8 | j = 0;
9 | if (arguments.length === 1) {
10 | while (++i < n) if (d3_number(a = array[i])) m += (a - m) / ++j;
11 | } else {
12 | while (++i < n) if (d3_number(a = f.call(array, array[i], i))) m += (a - m) / ++j;
13 | }
14 | return j ? m : undefined;
15 | };
16 |
--------------------------------------------------------------------------------
/src/geo/conic.js:
--------------------------------------------------------------------------------
1 | import "../math/trigonometry";
2 | import "projection";
3 |
4 | function d3_geo_conic(projectAt) {
5 | var φ0 = 0,
6 | φ1 = π / 3,
7 | m = d3_geo_projectionMutator(projectAt),
8 | p = m(φ0, φ1);
9 |
10 | p.parallels = function(_) {
11 | if (!arguments.length) return [φ0 / π * 180, φ1 / π * 180];
12 | return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180);
13 | };
14 |
15 | return p;
16 | }
17 |
--------------------------------------------------------------------------------
/src/arrays/merge.js:
--------------------------------------------------------------------------------
1 | d3.merge = function(arrays) {
2 | var n = arrays.length,
3 | m,
4 | i = -1,
5 | j = 0,
6 | merged,
7 | array;
8 |
9 | while (++i < n) j += arrays[i].length;
10 | merged = new Array(j);
11 |
12 | while (--n >= 0) {
13 | array = arrays[n];
14 | m = array.length;
15 | while (--m >= 0) {
16 | merged[--j] = array[m];
17 | }
18 | }
19 |
20 | return merged;
21 | };
22 |
--------------------------------------------------------------------------------
/src/selection/order.js:
--------------------------------------------------------------------------------
1 | import "selection";
2 |
3 | d3_selectionPrototype.order = function() {
4 | for (var j = -1, m = this.length; ++j < m;) {
5 | for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0;) {
6 | if (node = group[i]) {
7 | if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);
8 | next = node;
9 | }
10 | }
11 | }
12 | return this;
13 | };
14 |
--------------------------------------------------------------------------------
/src/selection/text.js:
--------------------------------------------------------------------------------
1 | import "selection";
2 |
3 | d3_selectionPrototype.text = function(value) {
4 | return arguments.length
5 | ? this.each(typeof value === "function"
6 | ? function() { var v = value.apply(this, arguments); this.textContent = v == null ? "" : v; } : value == null
7 | ? function() { this.textContent = ""; }
8 | : function() { this.textContent = value; })
9 | : this.node().textContent;
10 | };
11 |
--------------------------------------------------------------------------------
/src/transition/ease.js:
--------------------------------------------------------------------------------
1 | import "../interpolate/ease";
2 | import "../selection/each";
3 | import "transition";
4 |
5 | d3_transitionPrototype.ease = function(value) {
6 | var id = this.id;
7 | if (arguments.length < 1) return this.node().__transition__[id].ease;
8 | if (typeof value !== "function") value = d3.ease.apply(d3, arguments);
9 | return d3_selection_each(this, function(node) { node.__transition__[id].ease = value; });
10 | };
11 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "d3",
3 | "version": "3.4.3",
4 | "main": "d3.js",
5 | "scripts": [
6 | "d3.js"
7 | ],
8 | "ignore": [
9 | ".DS_Store",
10 | ".git",
11 | ".gitignore",
12 | ".npmignore",
13 | ".travis.yml",
14 | "Makefile",
15 | "bin",
16 | "component.json",
17 | "index.js",
18 | "lib",
19 | "node_modules",
20 | "package.json",
21 | "src",
22 | "test"
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/src/core/vendor.js:
--------------------------------------------------------------------------------
1 | import "document";
2 |
3 | function d3_vendorSymbol(object, name) {
4 | if (name in object) return name;
5 | name = name.charAt(0).toUpperCase() + name.substring(1);
6 | for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) {
7 | var prefixName = d3_vendorPrefixes[i] + name;
8 | if (prefixName in object) return prefixName;
9 | }
10 | }
11 |
12 | var d3_vendorPrefixes = ["webkit", "ms", "moz", "Moz", "o", "O"];
13 |
--------------------------------------------------------------------------------
/src/time/month.js:
--------------------------------------------------------------------------------
1 | import "day";
2 | import "interval";
3 | import "time";
4 |
5 | d3_time.month = d3_time_interval(function(date) {
6 | date = d3_time.day(date);
7 | date.setDate(1);
8 | return date;
9 | }, function(date, offset) {
10 | date.setMonth(date.getMonth() + offset);
11 | }, function(date) {
12 | return date.getMonth();
13 | });
14 |
15 | d3_time.months = d3_time.month.range;
16 | d3_time.months.utc = d3_time.month.utc.range;
17 |
--------------------------------------------------------------------------------
/src/time/year.js:
--------------------------------------------------------------------------------
1 | import "day";
2 | import "interval";
3 | import "time";
4 |
5 | d3_time.year = d3_time_interval(function(date) {
6 | date = d3_time.day(date);
7 | date.setMonth(0, 1);
8 | return date;
9 | }, function(date, offset) {
10 | date.setFullYear(date.getFullYear() + offset);
11 | }, function(date) {
12 | return date.getFullYear();
13 | });
14 |
15 | d3_time.years = d3_time.year.range;
16 | d3_time.years.utc = d3_time.year.utc.range;
17 |
--------------------------------------------------------------------------------
/test/core/version-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.version");
6 |
7 | suite.addBatch({
8 | "version": {
9 | topic: load().expression("d3.version"),
10 | "has the form major.minor.patch": function(version) {
11 | assert.match(version, /^[0-9]+\.[0-9]+\.[0-9]+/);
12 | }
13 | }
14 | });
15 |
16 | suite.export(module);
17 |
--------------------------------------------------------------------------------
/src/geo/azimuthal-equidistant.js:
--------------------------------------------------------------------------------
1 | import "../core/identity";
2 | import "azimuthal";
3 | import "geo";
4 | import "projection";
5 |
6 | var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(
7 | function(cosλcosφ) { var c = Math.acos(cosλcosφ); return c && c / Math.sin(c); },
8 | d3_identity
9 | );
10 |
11 | (d3.geo.azimuthalEquidistant = function() {
12 | return d3_geo_projection(d3_geo_azimuthalEquidistant);
13 | }).raw = d3_geo_azimuthalEquidistant;
14 |
--------------------------------------------------------------------------------
/src/time/minute.js:
--------------------------------------------------------------------------------
1 | import "interval";
2 | import "time";
3 |
4 | d3_time.minute = d3_time_interval(function(date) {
5 | return new d3_date(Math.floor(date / 6e4) * 6e4);
6 | }, function(date, offset) {
7 | date.setTime(date.getTime() + Math.floor(offset) * 6e4); // DST breaks setMinutes
8 | }, function(date) {
9 | return date.getMinutes();
10 | });
11 |
12 | d3_time.minutes = d3_time.minute.range;
13 | d3_time.minutes.utc = d3_time.minute.utc.range;
14 |
--------------------------------------------------------------------------------
/src/time/second.js:
--------------------------------------------------------------------------------
1 | import "interval";
2 | import "time";
3 |
4 | d3_time.second = d3_time_interval(function(date) {
5 | return new d3_date(Math.floor(date / 1e3) * 1e3);
6 | }, function(date, offset) {
7 | date.setTime(date.getTime() + Math.floor(offset) * 1e3); // DST breaks setSeconds
8 | }, function(date) {
9 | return date.getSeconds();
10 | });
11 |
12 | d3_time.seconds = d3_time.second.range;
13 | d3_time.seconds.utc = d3_time.second.utc.range;
14 |
--------------------------------------------------------------------------------
/src/transition/duration.js:
--------------------------------------------------------------------------------
1 | import "../selection/each";
2 | import "transition";
3 |
4 | d3_transitionPrototype.duration = function(value) {
5 | var id = this.id;
6 | return d3_selection_each(this, typeof value === "function"
7 | ? function(node, i, j) { node.__transition__[id].duration = Math.max(1, value.call(node, node.__data__, i, j)); }
8 | : (value = Math.max(1, value), function(node) { node.__transition__[id].duration = value; }));
9 | };
10 |
--------------------------------------------------------------------------------
/src/d3.js:
--------------------------------------------------------------------------------
1 | import "start";
2 | import "compat/";
3 |
4 | import "arrays/";
5 | import "behavior/";
6 | import "color/";
7 | import "core/";
8 | import "dsv/";
9 | import "event/";
10 | import "format/";
11 | import "geo/";
12 | import "geom/";
13 | import "interpolate/";
14 | import "layout/";
15 | import "math/";
16 | import "scale/";
17 | import "selection/";
18 | import "svg/";
19 | import "time/";
20 | import "transition/";
21 | import "xhr/";
22 |
23 | import "end";
24 |
--------------------------------------------------------------------------------
/component.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "d3",
3 | "repo": "mbostock/d3",
4 | "description": "A small, free JavaScript library for manipulating documents based on data.",
5 | "keywords": [
6 | "dom",
7 | "w3c",
8 | "visualization",
9 | "svg",
10 | "animation",
11 | "canvas"
12 | ],
13 | "version": "3.4.3",
14 | "main": "d3.js",
15 | "scripts": [
16 | "d3.js"
17 | ],
18 | "dependencies": {},
19 | "development": {},
20 | "license": "BSD"
21 | }
22 |
--------------------------------------------------------------------------------
/src/svg/area-radial.js:
--------------------------------------------------------------------------------
1 | import "area";
2 | import "svg";
3 | import "line-radial";
4 |
5 | d3.svg.area.radial = function() {
6 | var area = d3_svg_area(d3_svg_lineRadial);
7 | area.radius = area.x, delete area.x;
8 | area.innerRadius = area.x0, delete area.x0;
9 | area.outerRadius = area.x1, delete area.x1;
10 | area.angle = area.y, delete area.y;
11 | area.startAngle = area.y0, delete area.y0;
12 | area.endAngle = area.y1, delete area.y1;
13 | return area;
14 | };
15 |
--------------------------------------------------------------------------------
/test/time/dayOfYear-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.time.dayOfYear");
6 |
7 | suite.addBatch({
8 | "dayOfYear": {
9 | topic: load("time/day").expression("d3.time.dayOfYear"),
10 | "no floating-point rounding error": function(dayOfYear) {
11 | assert.equal(dayOfYear(new Date(2011, 4, 9)), 128);
12 | }
13 | }
14 | });
15 |
16 | suite.export(module);
17 |
--------------------------------------------------------------------------------
/bin/component:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | var fs = require("fs"),
4 | package = require("../package.json");
5 |
6 | console.log(JSON.stringify({
7 | "name": "d3",
8 | "repo": "mbostock/d3",
9 | "description": package.description,
10 | "keywords": package.keywords,
11 | "version": package.version,
12 | "main": "d3.js",
13 | "scripts": [
14 | "d3.js"
15 | ],
16 | "dependencies": {},
17 | "development": {},
18 | "license": package.licenses[0].type
19 | }, null, 2));
20 |
--------------------------------------------------------------------------------
/src/core/document.js:
--------------------------------------------------------------------------------
1 | import "array";
2 |
3 | var d3_document = document,
4 | d3_documentElement = d3_document.documentElement,
5 | d3_window = window;
6 |
7 | // Redefine d3_array if the browser doesn’t support slice-based conversion.
8 | try {
9 | d3_array(d3_documentElement.childNodes)[0].nodeType;
10 | } catch(e) {
11 | d3_array = function(list) {
12 | var i = list.length, array = new Array(i);
13 | while (i--) array[i] = list[i];
14 | return array;
15 | };
16 | }
17 |
--------------------------------------------------------------------------------
/src/arrays/index.js:
--------------------------------------------------------------------------------
1 | import "ascending";
2 | import "descending";
3 | import "min";
4 | import "max";
5 | import "extent";
6 | import "sum";
7 | import "mean";
8 | import "median";
9 | import "quantile";
10 | import "bisect";
11 | import "shuffle";
12 | import "permute";
13 | import "pairs";
14 | import "zip";
15 | import "transpose";
16 | import "keys";
17 | import "values";
18 | import "entries";
19 | import "merge";
20 | import "range";
21 | import "nest";
22 | import "map";
23 | import "set";
24 |
--------------------------------------------------------------------------------
/src/selection/each.js:
--------------------------------------------------------------------------------
1 | import "selection";
2 |
3 | d3_selectionPrototype.each = function(callback) {
4 | return d3_selection_each(this, function(node, i, j) {
5 | callback.call(node, node.__data__, i, j);
6 | });
7 | };
8 |
9 | function d3_selection_each(groups, callback) {
10 | for (var j = 0, m = groups.length; j < m; j++) {
11 | for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) {
12 | if (node = group[i]) callback(node, i, j);
13 | }
14 | }
15 | return groups;
16 | }
17 |
--------------------------------------------------------------------------------
/src/time/hour.js:
--------------------------------------------------------------------------------
1 | import "interval";
2 | import "time";
3 |
4 | d3_time.hour = d3_time_interval(function(date) {
5 | var timezone = date.getTimezoneOffset() / 60;
6 | return new d3_date((Math.floor(date / 36e5 - timezone) + timezone) * 36e5);
7 | }, function(date, offset) {
8 | date.setTime(date.getTime() + Math.floor(offset) * 36e5); // DST breaks setHours
9 | }, function(date) {
10 | return date.getHours();
11 | });
12 |
13 | d3_time.hours = d3_time.hour.range;
14 | d3_time.hours.utc = d3_time.hour.utc.range;
15 |
--------------------------------------------------------------------------------
/src/arrays/max.js:
--------------------------------------------------------------------------------
1 | d3.max = function(array, f) {
2 | var i = -1,
3 | n = array.length,
4 | a,
5 | b;
6 | if (arguments.length === 1) {
7 | while (++i < n && !((a = array[i]) != null && a <= a)) a = undefined;
8 | while (++i < n) if ((b = array[i]) != null && b > a) a = b;
9 | } else {
10 | while (++i < n && !((a = f.call(array, array[i], i)) != null && a <= a)) a = undefined;
11 | while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b;
12 | }
13 | return a;
14 | };
15 |
--------------------------------------------------------------------------------
/src/arrays/min.js:
--------------------------------------------------------------------------------
1 | d3.min = function(array, f) {
2 | var i = -1,
3 | n = array.length,
4 | a,
5 | b;
6 | if (arguments.length === 1) {
7 | while (++i < n && !((a = array[i]) != null && a <= a)) a = undefined;
8 | while (++i < n) if ((b = array[i]) != null && a > b) a = b;
9 | } else {
10 | while (++i < n && !((a = f.call(array, array[i], i)) != null && a <= a)) a = undefined;
11 | while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b;
12 | }
13 | return a;
14 | };
15 |
--------------------------------------------------------------------------------
/src/interpolate/rgb.js:
--------------------------------------------------------------------------------
1 | import "../color/rgb";
2 |
3 | d3.interpolateRgb = d3_interpolateRgb;
4 |
5 | function d3_interpolateRgb(a, b) {
6 | a = d3.rgb(a);
7 | b = d3.rgb(b);
8 | var ar = a.r,
9 | ag = a.g,
10 | ab = a.b,
11 | br = b.r - ar,
12 | bg = b.g - ag,
13 | bb = b.b - ab;
14 | return function(t) {
15 | return "#"
16 | + d3_rgb_hex(Math.round(ar + br * t))
17 | + d3_rgb_hex(Math.round(ag + bg * t))
18 | + d3_rgb_hex(Math.round(ab + bb * t));
19 | };
20 | }
21 |
--------------------------------------------------------------------------------
/src/interpolate/object.js:
--------------------------------------------------------------------------------
1 | import "interpolate";
2 |
3 | d3.interpolateObject = d3_interpolateObject;
4 |
5 | function d3_interpolateObject(a, b) {
6 | var i = {},
7 | c = {},
8 | k;
9 | for (k in a) {
10 | if (k in b) {
11 | i[k] = d3_interpolate(a[k], b[k]);
12 | } else {
13 | c[k] = a[k];
14 | }
15 | }
16 | for (k in b) {
17 | if (!(k in a)) {
18 | c[k] = b[k];
19 | }
20 | }
21 | return function(t) {
22 | for (k in i) c[k] = i[k](t);
23 | return c;
24 | };
25 | }
26 |
--------------------------------------------------------------------------------
/test/geo/point-in-polygon-mock.js:
--------------------------------------------------------------------------------
1 | import "../../src/geo/point-in-polygon";
2 | import "../../src/math/trigonometry";
3 |
4 | d3.geo.pointInPolygon = function(polygon) {
5 | polygon = polygon.map(function(ring) {
6 | ring = ring.map(pointRadians);
7 | ring.pop();
8 | return ring;
9 | });
10 |
11 | return function(point) {
12 | return d3_geo_pointInPolygon(pointRadians(point), polygon);
13 | };
14 |
15 | function pointRadians(point) {
16 | return [point[0] * d3_radians, point[1] * d3_radians];
17 | }
18 | };
19 |
--------------------------------------------------------------------------------
/src/interpolate/array.js:
--------------------------------------------------------------------------------
1 | import "interpolate";
2 |
3 | d3.interpolateArray = d3_interpolateArray;
4 |
5 | function d3_interpolateArray(a, b) {
6 | var x = [],
7 | c = [],
8 | na = a.length,
9 | nb = b.length,
10 | n0 = Math.min(a.length, b.length),
11 | i;
12 | for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i]));
13 | for (; i < na; ++i) c[i] = a[i];
14 | for (; i < nb; ++i) c[i] = b[i];
15 | return function(t) {
16 | for (i = 0; i < n0; ++i) c[i] = x[i](t);
17 | return c;
18 | };
19 | }
20 |
--------------------------------------------------------------------------------
/src/selection/sort.js:
--------------------------------------------------------------------------------
1 | import "../arrays/ascending";
2 | import "selection";
3 |
4 | d3_selectionPrototype.sort = function(comparator) {
5 | comparator = d3_selection_sortComparator.apply(this, arguments);
6 | for (var j = -1, m = this.length; ++j < m;) this[j].sort(comparator);
7 | return this.order();
8 | };
9 |
10 | function d3_selection_sortComparator(comparator) {
11 | if (!arguments.length) comparator = d3.ascending;
12 | return function(a, b) {
13 | return a && b ? comparator(a.__data__, b.__data__) : !a - !b;
14 | };
15 | }
16 |
--------------------------------------------------------------------------------
/test/interpolate/round-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.interpolateRound");
6 |
7 | suite.addBatch({
8 | "interpolateRound": {
9 | topic: load("interpolate/round").expression("d3.interpolateRound"),
10 | "interpolates integers": function(interpolate) {
11 | assert.strictEqual(interpolate(2, 12)(.456), 7);
12 | assert.strictEqual(interpolate(2, 12)(.678), 9);
13 | }
14 | }
15 | });
16 |
17 | suite.export(module);
18 |
--------------------------------------------------------------------------------
/test/event/mouse-test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | HTML Mouse Test
4 |
5 |
6 |
23 |
--------------------------------------------------------------------------------
/bin/bower:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | var fs = require("fs");
4 |
5 | console.log(JSON.stringify({
6 | "name": "d3",
7 | "version": require("../package.json").version,
8 | "main": "d3.js",
9 | "scripts": [
10 | "d3.js"
11 | ],
12 | "ignore": [
13 | ".DS_Store",
14 | ".git",
15 | ".gitignore",
16 | ".npmignore",
17 | ".travis.yml",
18 | "Makefile",
19 | "bin",
20 | "component.json",
21 | "index.js",
22 | "lib",
23 | "node_modules",
24 | "package.json",
25 | "src",
26 | "test"
27 | ]
28 | }, null, 2));
29 |
--------------------------------------------------------------------------------
/src/locale/zh-CN.js:
--------------------------------------------------------------------------------
1 | import "locale";
2 |
3 | var d3_locale_zhCN = d3.locale({
4 | decimal: ".",
5 | thousands: ",",
6 | grouping: [3],
7 | currency: ["¥", ""],
8 | dateTime: "%a %b %e %X %Y",
9 | date: "%Y/%-m/%-d",
10 | time: "%H:%M:%S",
11 | periods: ["上午", "下午"],
12 | days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
13 | shortDays: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
14 | months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
15 | shortMonths: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"]
16 | });
17 |
--------------------------------------------------------------------------------
/src/geo/distance.js:
--------------------------------------------------------------------------------
1 | import "../math/trigonometry";
2 | import "geo";
3 |
4 | // Length returned in radians; multiply by radius for distance.
5 | d3.geo.distance = function(a, b) {
6 | var Δλ = (b[0] - a[0]) * d3_radians,
7 | φ0 = a[1] * d3_radians, φ1 = b[1] * d3_radians,
8 | sinΔλ = Math.sin(Δλ), cosΔλ = Math.cos(Δλ),
9 | sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0),
10 | sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1),
11 | t;
12 | return Math.atan2(Math.sqrt((t = cosφ1 * sinΔλ) * t + (t = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * t), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ);
13 | };
14 |
--------------------------------------------------------------------------------
/src/interpolate/hcl.js:
--------------------------------------------------------------------------------
1 | import "../color/hcl";
2 |
3 | d3.interpolateHcl = d3_interpolateHcl;
4 |
5 | function d3_interpolateHcl(a, b) {
6 | a = d3.hcl(a);
7 | b = d3.hcl(b);
8 | var ah = a.h,
9 | ac = a.c,
10 | al = a.l,
11 | bh = b.h - ah,
12 | bc = b.c - ac,
13 | bl = b.l - al;
14 | if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac;
15 | if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah;
16 | else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; // shortest path
17 | return function(t) {
18 | return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + "";
19 | };
20 | }
21 |
--------------------------------------------------------------------------------
/src/interpolate/hsl.js:
--------------------------------------------------------------------------------
1 | import "../color/hsl";
2 |
3 | d3.interpolateHsl = d3_interpolateHsl;
4 |
5 | function d3_interpolateHsl(a, b) {
6 | a = d3.hsl(a);
7 | b = d3.hsl(b);
8 | var ah = a.h,
9 | as = a.s,
10 | al = a.l,
11 | bh = b.h - ah,
12 | bs = b.s - as,
13 | bl = b.l - al;
14 | if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as;
15 | if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah;
16 | else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; // shortest path
17 | return function(t) {
18 | return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + "";
19 | };
20 | }
21 |
--------------------------------------------------------------------------------
/src/time/format-iso.js:
--------------------------------------------------------------------------------
1 | import "format";
2 | import "format-utc";
3 | import "time";
4 |
5 | var d3_time_formatIso = d3_time_formatUtc("%Y-%m-%dT%H:%M:%S.%LZ");
6 |
7 | d3_time_format.iso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z")
8 | ? d3_time_formatIsoNative
9 | : d3_time_formatIso;
10 |
11 | function d3_time_formatIsoNative(date) {
12 | return date.toISOString();
13 | }
14 |
15 | d3_time_formatIsoNative.parse = function(string) {
16 | var date = new Date(string);
17 | return isNaN(date) ? null : date;
18 | };
19 |
20 | d3_time_formatIsoNative.toString = d3_time_formatIso.toString;
21 |
--------------------------------------------------------------------------------
/src/selection/append.js:
--------------------------------------------------------------------------------
1 | import "../core/document";
2 | import "../core/ns";
3 | import "selection";
4 |
5 | d3_selectionPrototype.append = function(name) {
6 | name = d3_selection_creator(name);
7 | return this.select(function() {
8 | return this.appendChild(name.apply(this, arguments));
9 | });
10 | };
11 |
12 | function d3_selection_creator(name) {
13 | return typeof name === "function" ? name
14 | : (name = d3.ns.qualify(name)).local ? function() { return this.ownerDocument.createElementNS(name.space, name.local); }
15 | : function() { return this.ownerDocument.createElementNS(this.namespaceURI, name); };
16 | }
17 |
--------------------------------------------------------------------------------
/src/selection/enter-insert.js:
--------------------------------------------------------------------------------
1 | import "selection";
2 | import "enter";
3 |
4 | d3_selection_enterPrototype.insert = function(name, before) {
5 | if (arguments.length < 2) before = d3_selection_enterInsertBefore(this);
6 | return d3_selectionPrototype.insert.call(this, name, before);
7 | };
8 |
9 | function d3_selection_enterInsertBefore(enter) {
10 | var i0, j0;
11 | return function(d, i, j) {
12 | var group = enter[j].update,
13 | n = group.length,
14 | node;
15 | if (j != j0) j0 = j, i0 = 0;
16 | if (i >= i0) i0 = i + 1;
17 | while (!(node = group[i0]) && ++i0 < n);
18 | return node;
19 | };
20 | }
21 |
--------------------------------------------------------------------------------
/src/svg/line-radial.js:
--------------------------------------------------------------------------------
1 | import "arc";
2 | import "line";
3 | import "svg";
4 |
5 | d3.svg.line.radial = function() {
6 | var line = d3_svg_line(d3_svg_lineRadial);
7 | line.radius = line.x, delete line.x;
8 | line.angle = line.y, delete line.y;
9 | return line;
10 | };
11 |
12 | function d3_svg_lineRadial(points) {
13 | var point,
14 | i = -1,
15 | n = points.length,
16 | r,
17 | a;
18 | while (++i < n) {
19 | point = points[i];
20 | r = point[0];
21 | a = point[1] + d3_svg_arcOffset;
22 | point[0] = r * Math.cos(a);
23 | point[1] = r * Math.sin(a);
24 | }
25 | return points;
26 | }
27 |
--------------------------------------------------------------------------------
/src/geo/path-bounds.js:
--------------------------------------------------------------------------------
1 | import "../core/noop";
2 |
3 | var d3_geo_pathBoundsX0,
4 | d3_geo_pathBoundsY0,
5 | d3_geo_pathBoundsX1,
6 | d3_geo_pathBoundsY1;
7 |
8 | var d3_geo_pathBounds = {
9 | point: d3_geo_pathBoundsPoint,
10 | lineStart: d3_noop,
11 | lineEnd: d3_noop,
12 | polygonStart: d3_noop,
13 | polygonEnd: d3_noop
14 | };
15 |
16 | function d3_geo_pathBoundsPoint(x, y) {
17 | if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x;
18 | if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x;
19 | if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y;
20 | if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y;
21 | }
22 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mbostock/d3",
3 | "description": "A small, free JavaScript library for manipulating documents based on data.",
4 | "keywords": ["dom", "svg", "visualization", "js", "canvas"],
5 | "homepage": "http://d3js.org/",
6 | "license": "BSD-3-Clause",
7 | "authors": [
8 | {
9 | "name": "Mike Bostock",
10 | "homepage": "http://bost.ocks.org/mike"
11 | }
12 | ],
13 | "support": {
14 | "issues": "https://github.com/mbostock/d3/issues",
15 | "wiki": "https://github.com/mbostock/d3/wiki",
16 | "API": "https://github.com/mbostock/d3/wiki/API-Reference",
17 | "source": "https://github.com/mbostock/d3"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/core/ns.js:
--------------------------------------------------------------------------------
1 | var d3_nsPrefix = {
2 | svg: "http://www.w3.org/2000/svg",
3 | xhtml: "http://www.w3.org/1999/xhtml",
4 | xlink: "http://www.w3.org/1999/xlink",
5 | xml: "http://www.w3.org/XML/1998/namespace",
6 | xmlns: "http://www.w3.org/2000/xmlns/"
7 | };
8 |
9 | d3.ns = {
10 | prefix: d3_nsPrefix,
11 | qualify: function(name) {
12 | var i = name.indexOf(":"),
13 | prefix = name;
14 | if (i >= 0) {
15 | prefix = name.substring(0, i);
16 | name = name.substring(i + 1);
17 | }
18 | return d3_nsPrefix.hasOwnProperty(prefix)
19 | ? {space: d3_nsPrefix[prefix], local: name}
20 | : name;
21 | }
22 | };
23 |
--------------------------------------------------------------------------------
/src/geo/azimuthal.js:
--------------------------------------------------------------------------------
1 | // Abstract azimuthal projection.
2 | function d3_geo_azimuthal(scale, angle) {
3 | function azimuthal(λ, φ) {
4 | var cosλ = Math.cos(λ),
5 | cosφ = Math.cos(φ),
6 | k = scale(cosλ * cosφ);
7 | return [
8 | k * cosφ * Math.sin(λ),
9 | k * Math.sin(φ)
10 | ];
11 | }
12 |
13 | azimuthal.invert = function(x, y) {
14 | var ρ = Math.sqrt(x * x + y * y),
15 | c = angle(ρ),
16 | sinc = Math.sin(c),
17 | cosc = Math.cos(c);
18 | return [
19 | Math.atan2(x * sinc, ρ * cosc),
20 | Math.asin(ρ && y * sinc / ρ)
21 | ];
22 | };
23 |
24 | return azimuthal;
25 | }
26 |
--------------------------------------------------------------------------------
/src/arrays/extent.js:
--------------------------------------------------------------------------------
1 | d3.extent = function(array, f) {
2 | var i = -1,
3 | n = array.length,
4 | a,
5 | b,
6 | c;
7 | if (arguments.length === 1) {
8 | while (++i < n && !((a = c = array[i]) != null && a <= a)) a = c = undefined;
9 | while (++i < n) if ((b = array[i]) != null) {
10 | if (a > b) a = b;
11 | if (c < b) c = b;
12 | }
13 | } else {
14 | while (++i < n && !((a = c = f.call(array, array[i], i)) != null && a <= a)) a = undefined;
15 | while (++i < n) if ((b = f.call(array, array[i], i)) != null) {
16 | if (a > b) a = b;
17 | if (c < b) c = b;
18 | }
19 | }
20 | return [a, c];
21 | };
22 |
--------------------------------------------------------------------------------
/src/core/rebind.js:
--------------------------------------------------------------------------------
1 | // Copies a variable number of methods from source to target.
2 | d3.rebind = function(target, source) {
3 | var i = 1, n = arguments.length, method;
4 | while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]);
5 | return target;
6 | };
7 |
8 | // Method is assumed to be a standard D3 getter-setter:
9 | // If passed with no arguments, gets the value.
10 | // If passed with arguments, sets the value and returns the target.
11 | function d3_rebind(target, source, method) {
12 | return function() {
13 | var value = method.apply(source, arguments);
14 | return value === source ? target : value;
15 | };
16 | }
17 |
--------------------------------------------------------------------------------
/src/transition/filter.js:
--------------------------------------------------------------------------------
1 | import "../selection/filter";
2 | import "transition";
3 |
4 | d3_transitionPrototype.filter = function(filter) {
5 | var subgroups = [],
6 | subgroup,
7 | group,
8 | node;
9 |
10 | if (typeof filter !== "function") filter = d3_selection_filter(filter);
11 |
12 | for (var j = 0, m = this.length; j < m; j++) {
13 | subgroups.push(subgroup = []);
14 | for (var group = this[j], i = 0, n = group.length; i < n; i++) {
15 | if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {
16 | subgroup.push(node);
17 | }
18 | }
19 | }
20 |
21 | return d3_transition(subgroups, this.id);
22 | };
23 |
--------------------------------------------------------------------------------
/src/locale/en-US.js:
--------------------------------------------------------------------------------
1 | import "locale";
2 |
3 | var d3_locale_enUS = d3.locale({
4 | decimal: ".",
5 | thousands: ",",
6 | grouping: [3],
7 | currency: ["$", ""],
8 | dateTime: "%a %b %e %X %Y",
9 | date: "%m/%d/%Y",
10 | time: "%H:%M:%S",
11 | periods: ["AM", "PM"],
12 | days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
13 | shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
14 | months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
15 | shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
16 | });
17 |
--------------------------------------------------------------------------------
/src/locale/ru-RU.js:
--------------------------------------------------------------------------------
1 | import "locale";
2 |
3 | d3.locale.ru_RU = d3.locale({
4 | decimal: ",",
5 | thousands: "\xa0",
6 | grouping: [3],
7 | currency: ["", " руб."],
8 | dateTime: "%A, %e %B %Y г. %X",
9 | date: "%d.%m.%Y",
10 | time: "%H:%M:%S",
11 | periods: ["AM", "PM"],
12 | days: ["воскресенье", "понедельник", "вторник", "среда", "четверг", "пятница", "суббота"],
13 | shortDays: ["вс", "пн", "вт", "ср", "чт", "пт", "сб"],
14 | months: ["января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентября", "октября", "ноября", "декабря"],
15 | shortMonths: ["янв", "фев", "мар", "апр", "май", "июн", "июл", "авг", "сен", "окт", "ноя", "дек"]
16 | });
17 |
--------------------------------------------------------------------------------
/src/scale/polylinear.js:
--------------------------------------------------------------------------------
1 | import "../arrays/bisect";
2 |
3 | function d3_scale_polylinear(domain, range, uninterpolate, interpolate) {
4 | var u = [],
5 | i = [],
6 | j = 0,
7 | k = Math.min(domain.length, range.length) - 1;
8 |
9 | // Handle descending domains.
10 | if (domain[k] < domain[0]) {
11 | domain = domain.slice().reverse();
12 | range = range.slice().reverse();
13 | }
14 |
15 | while (++j <= k) {
16 | u.push(uninterpolate(domain[j - 1], domain[j]));
17 | i.push(interpolate(range[j - 1], range[j]));
18 | }
19 |
20 | return function(x) {
21 | var j = d3.bisect(domain, x, 1, k) - 1;
22 | return i[j](u[j](x));
23 | };
24 | }
25 |
--------------------------------------------------------------------------------
/test/interpolate/number-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.interpolateNumber");
6 |
7 | suite.addBatch({
8 | "interpolateNumber": {
9 | topic: load("interpolate/number").expression("d3.interpolateNumber"),
10 | "interpolates numbers": function(interpolate) {
11 | assert.strictEqual(interpolate(2, 12)(.4), 6);
12 | assert.strictEqual(interpolate(2, 12)(.6), 8);
13 | },
14 | "coerces strings to numbers": function(interpolate) {
15 | assert.strictEqual(interpolate("2", "12")(.4), 6);
16 | }
17 | }
18 | });
19 |
20 | suite.export(module);
21 |
--------------------------------------------------------------------------------
/src/time/day.js:
--------------------------------------------------------------------------------
1 | import "interval";
2 | import "time";
3 | import "year";
4 |
5 | d3_time.day = d3_time_interval(function(date) {
6 | var day = new d3_date(2000, 0);
7 | day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
8 | return day;
9 | }, function(date, offset) {
10 | date.setDate(date.getDate() + offset);
11 | }, function(date) {
12 | return date.getDate() - 1;
13 | });
14 |
15 | d3_time.days = d3_time.day.range;
16 | d3_time.days.utc = d3_time.day.utc.range;
17 |
18 | d3_time.dayOfYear = function(date) {
19 | var year = d3_time.year(date);
20 | return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5);
21 | };
22 |
--------------------------------------------------------------------------------
/test/geo/distance-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("assert");
4 |
5 | var suite = vows.describe("d3.geo.distance");
6 |
7 | suite.addBatch({
8 | "distance": {
9 | topic: load("geo/distance").expression("d3.geo.distance"),
10 | "computes the great-arc distance": function(distance) {
11 | assert.equal(distance([0, 0], [0, 0]), 0);
12 | assert.inDelta(distance([118 + 24 / 60, 33 + 57 / 60], [ 73 + 47 / 60, 40 + 38 / 60]), 3973 / 6371, .5);
13 | },
14 | "small distance": function(distance) {
15 | assert.isTrue(distance([0, 0], [0, 1e-12]) > 0);
16 | }
17 | }
18 | });
19 |
20 | suite.export(module);
21 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | GENERATED_FILES = \
2 | d3.js \
3 | d3.min.js \
4 | bower.json \
5 | component.json
6 |
7 | all: $(GENERATED_FILES)
8 |
9 | .PHONY: clean all test
10 |
11 | test:
12 | @npm test
13 |
14 | src/start.js: package.json bin/start
15 | bin/start > $@
16 |
17 | d3.js: $(shell node_modules/.bin/smash --ignore-missing --list src/d3.js) package.json
18 | @rm -f $@
19 | node_modules/.bin/smash src/d3.js | node_modules/.bin/uglifyjs - -b indent-level=2 -o $@
20 | @chmod a-w $@
21 |
22 | d3.min.js: d3.js bin/uglify
23 | @rm -f $@
24 | bin/uglify $< > $@
25 |
26 | %.json: bin/% package.json
27 | @rm -f $@
28 | bin/$* > $@
29 | @chmod a-w $@
30 |
31 | clean:
32 | rm -f -- $(GENERATED_FILES)
33 |
--------------------------------------------------------------------------------
/test/geom/voronoi-benchmark:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | var d3 = require("../../");
4 |
5 | var width = 960,
6 | height = 500;
7 |
8 | var points = d3.range(10000).map(function() {
9 | return [Math.random() * width, Math.random() * height];
10 | });
11 |
12 | var voronoi = d3.geom.voronoi()
13 | .clipExtent([[0, 0], [width, height]]);
14 |
15 | var observations = d3.range(20).map(function() {
16 | process.stdout.write(".");
17 | var start = process.hrtime();
18 | voronoi(points);
19 | var elapsed = process.hrtime(start);
20 | return elapsed[0] * 1e3 + elapsed[1] / 1e6;
21 | });
22 |
23 | console.log("");
24 | console.log(Math.round(d3.mean(observations)) + "ms for 10,000 points.");
25 |
--------------------------------------------------------------------------------
/test/math/transform-null-test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Data-Driven Documents
2 |
3 |
4 |
5 | **D3.js** is a JavaScript library for manipulating documents based on data. **D3** helps you bring data to life using HTML, SVG and CSS. D3’s emphasis on web standards gives you the full capabilities of modern browsers without tying yourself to a proprietary framework, combining powerful visualization components and a data-driven approach to DOM manipulation.
6 |
7 | Want to learn more? [See the wiki.](https://github.com/mbostock/d3/wiki)
8 |
9 | For examples, [see the gallery](https://github.com/mbostock/d3/wiki/Gallery) and [mbostock’s bl.ocks](http://bl.ocks.org/mbostock).
10 |
--------------------------------------------------------------------------------
/lib/science/science.lin.js:
--------------------------------------------------------------------------------
1 | (function(){science.lin = {};
2 | /**
3 | * Solves tridiagonal systems of linear equations.
4 | *
5 | * Source: http://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm
6 | *
7 | * @param {number[]} a
8 | * @param {number[]} b
9 | * @param {number[]} c
10 | * @param {number[]} d
11 | * @param {number[]} x
12 | * @param {number} n
13 | */
14 | science.lin.tridag = function(a, b, c, d, x, n) {
15 | var i,
16 | m;
17 | for (i = 1; i < n; i++) {
18 | m = a[i] / b[i - 1];
19 | b[i] -= m * c[i - 1];
20 | d[i] -= m * d[i - 1];
21 | }
22 | x[n - 1] = d[n - 1] / b[n - 1];
23 | for (i = n - 2; i >= 0; i--) {
24 | x[i] = (d[i] - c[i] * x[i + 1]) / b[i];
25 | }
26 | };
27 | })()
--------------------------------------------------------------------------------
/src/selection/transition.js:
--------------------------------------------------------------------------------
1 | // import "../transition/transition";
2 | import "selection";
3 |
4 | d3_selectionPrototype.transition = function() {
5 | var id = d3_transitionInheritId || ++d3_transitionId,
6 | subgroups = [],
7 | subgroup,
8 | node,
9 | transition = d3_transitionInherit || {time: Date.now(), ease: d3_ease_cubicInOut, delay: 0, duration: 250};
10 |
11 | for (var j = -1, m = this.length; ++j < m;) {
12 | subgroups.push(subgroup = []);
13 | for (var group = this[j], i = -1, n = group.length; ++i < n;) {
14 | if (node = group[i]) d3_transitionNode(node, i, id, transition);
15 | subgroup.push(node);
16 | }
17 | }
18 |
19 | return d3_transition(subgroups, id);
20 | };
21 |
--------------------------------------------------------------------------------
/test/math/transform-null-matrix-test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
27 |
--------------------------------------------------------------------------------
/test/layout/pie-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.layout.pie");
6 |
7 | suite.addBatch({
8 | "pie": {
9 | topic: load("layout/pie").expression("d3.layout.pie"),
10 | "arcs are in same order as original data": function(pie) {
11 | var p = pie();
12 | assert.deepEqual(p([5, 30, 15]).map(function(d) { return d.data; }), [
13 | 5, 30, 15
14 | ]);
15 | assert.deepEqual(p([
16 | 84, 90, 48, 61, 58, 8, 6, 31, 45, 18
17 | ]).map(function(d) { return d.data; }), [
18 | 84, 90, 48, 61, 58, 8, 6, 31, 45, 18
19 | ]);
20 | }
21 | }
22 | });
23 |
24 | suite.export(module);
25 |
--------------------------------------------------------------------------------
/src/scale/nice.js:
--------------------------------------------------------------------------------
1 | import "../core/identity";
2 |
3 | function d3_scale_nice(domain, nice) {
4 | var i0 = 0,
5 | i1 = domain.length - 1,
6 | x0 = domain[i0],
7 | x1 = domain[i1],
8 | dx;
9 |
10 | if (x1 < x0) {
11 | dx = i0, i0 = i1, i1 = dx;
12 | dx = x0, x0 = x1, x1 = dx;
13 | }
14 |
15 | domain[i0] = nice.floor(x0);
16 | domain[i1] = nice.ceil(x1);
17 | return domain;
18 | }
19 |
20 | function d3_scale_niceStep(step) {
21 | return step ? {
22 | floor: function(x) { return Math.floor(x / step) * step; },
23 | ceil: function(x) { return Math.ceil(x / step) * step; }
24 | } : d3_scale_niceIdentity;
25 | }
26 |
27 | var d3_scale_niceIdentity = {
28 | floor: d3_identity,
29 | ceil: d3_identity
30 | };
31 |
--------------------------------------------------------------------------------
/src/svg/diagonal-radial.js:
--------------------------------------------------------------------------------
1 | import "arc";
2 | import "diagonal";
3 | import "svg";
4 |
5 | d3.svg.diagonal.radial = function() {
6 | var diagonal = d3.svg.diagonal(),
7 | projection = d3_svg_diagonalProjection,
8 | projection_ = diagonal.projection;
9 |
10 | diagonal.projection = function(x) {
11 | return arguments.length
12 | ? projection_(d3_svg_diagonalRadialProjection(projection = x))
13 | : projection;
14 | };
15 |
16 | return diagonal;
17 | };
18 |
19 | function d3_svg_diagonalRadialProjection(projection) {
20 | return function() {
21 | var d = projection.apply(this, arguments),
22 | r = d[0],
23 | a = d[1] + d3_svg_arcOffset;
24 | return [r * Math.cos(a), r * Math.sin(a)];
25 | };
26 | }
27 |
--------------------------------------------------------------------------------
/src/arrays/range.js:
--------------------------------------------------------------------------------
1 | import "../math/abs";
2 |
3 | d3.range = function(start, stop, step) {
4 | if (arguments.length < 3) {
5 | step = 1;
6 | if (arguments.length < 2) {
7 | stop = start;
8 | start = 0;
9 | }
10 | }
11 | if ((stop - start) / step === Infinity) throw new Error("infinite range");
12 | var range = [],
13 | k = d3_range_integerScale(abs(step)),
14 | i = -1,
15 | j;
16 | start *= k, stop *= k, step *= k;
17 | if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k);
18 | else while ((j = start + step * ++i) < stop) range.push(j / k);
19 | return range;
20 | };
21 |
22 | function d3_range_integerScale(x) {
23 | var k = 1;
24 | while (x * k % 1) k *= 10;
25 | return k;
26 | }
27 |
--------------------------------------------------------------------------------
/src/transition/subtransition.js:
--------------------------------------------------------------------------------
1 | import "transition";
2 |
3 | d3_transitionPrototype.transition = function() {
4 | var id0 = this.id,
5 | id1 = ++d3_transitionId,
6 | subgroups = [],
7 | subgroup,
8 | group,
9 | node,
10 | transition;
11 |
12 | for (var j = 0, m = this.length; j < m; j++) {
13 | subgroups.push(subgroup = []);
14 | for (var group = this[j], i = 0, n = group.length; i < n; i++) {
15 | if (node = group[i]) {
16 | transition = Object.create(node.__transition__[id0]);
17 | transition.delay += transition.duration;
18 | d3_transitionNode(node, i, id1, transition);
19 | }
20 | subgroup.push(node);
21 | }
22 | }
23 |
24 | return d3_transition(subgroups, id1);
25 | };
26 |
--------------------------------------------------------------------------------
/test/transition/transition-test-id.js:
--------------------------------------------------------------------------------
1 | var assert = require("../assert");
2 |
3 | module.exports = {
4 | topic: function(d3) {
5 | return d3; // bug in vows where topic is not propagated automatically
6 | },
7 | "on a new transition": {
8 | topic: function(d3) {
9 | return d3.select("body").append("div").transition();
10 | },
11 | "has a positive integer id": function(transition) {
12 | var id = transition.id;
13 | assert.isTrue(id > 0);
14 | assert.equal(~~id, id);
15 | }
16 | },
17 | "increases monotonically across transitions": function(d3) {
18 | var t0 = d3.select("body").append("div").transition(),
19 | t1 = d3.select("body").append("div").transition();
20 | assert.isTrue(t1.id > t0.id);
21 | }
22 | };
23 |
--------------------------------------------------------------------------------
/src/selection/enter.js:
--------------------------------------------------------------------------------
1 | import "../core/subclass";
2 | import "selection";
3 |
4 | function d3_selection_enter(selection) {
5 | d3_subclass(selection, d3_selection_enterPrototype);
6 | return selection;
7 | }
8 |
9 | var d3_selection_enterPrototype = [];
10 |
11 | d3.selection.enter = d3_selection_enter;
12 | d3.selection.enter.prototype = d3_selection_enterPrototype;
13 |
14 | d3_selection_enterPrototype.append = d3_selectionPrototype.append;
15 | d3_selection_enterPrototype.empty = d3_selectionPrototype.empty;
16 | d3_selection_enterPrototype.node = d3_selectionPrototype.node;
17 | d3_selection_enterPrototype.call = d3_selectionPrototype.call;
18 | d3_selection_enterPrototype.size = d3_selectionPrototype.size;
19 |
20 | import "enter-select";
21 | import "enter-insert";
22 |
--------------------------------------------------------------------------------
/src/arrays/set.js:
--------------------------------------------------------------------------------
1 | import "../core/class";
2 | import "map";
3 |
4 | d3.set = function(array) {
5 | var set = new d3_Set;
6 | if (array) for (var i = 0, n = array.length; i < n; ++i) set.add(array[i]);
7 | return set;
8 | };
9 |
10 | function d3_Set() {}
11 |
12 | d3_class(d3_Set, {
13 | has: d3_map_has,
14 | add: function(value) {
15 | this[d3_map_prefix + value] = true;
16 | return value;
17 | },
18 | remove: function(value) {
19 | value = d3_map_prefix + value;
20 | return value in this && delete this[value];
21 | },
22 | values: d3_map_keys,
23 | size: d3_map_size,
24 | empty: d3_map_empty,
25 | forEach: function(f) {
26 | for (var value in this) if (value.charCodeAt(0) === d3_map_prefixCode) f.call(this, value.substring(1));
27 | }
28 | });
29 |
--------------------------------------------------------------------------------
/test/geo/interpolate-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.geo.interpolate");
6 |
7 | suite.addBatch({
8 | "interpolate": {
9 | topic: load("geo/interpolate").expression("d3.geo.interpolate"),
10 | "zero distance": function(interpolate) {
11 | assert.deepEqual(interpolate([140.63289, -29.95101], [140.63289, -29.95101])(.5), [140.63289, -29.95101]);
12 | },
13 | "equator": function(interpolate) {
14 | assert.inDelta(interpolate([10, 0], [20, 0])(.5), [15, 0], 1e-6);
15 | },
16 | "meridian": function(interpolate) {
17 | assert.inDelta(interpolate([10, -20], [10, 40])(.5), [10, 10], 1e-6);
18 | }
19 | }
20 | });
21 |
22 | suite.export(module);
23 |
--------------------------------------------------------------------------------
/src/interpolate/interpolate.js:
--------------------------------------------------------------------------------
1 | import "../color/color";
2 | import "../color/rgb";
3 | import "rgb";
4 | import "object";
5 | import "array";
6 | import "number";
7 | import "string";
8 |
9 | d3.interpolate = d3_interpolate;
10 |
11 | function d3_interpolate(a, b) {
12 | var i = d3.interpolators.length, f;
13 | while (--i >= 0 && !(f = d3.interpolators[i](a, b)));
14 | return f;
15 | }
16 |
17 | d3.interpolators = [
18 | function(a, b) {
19 | var t = typeof b;
20 | return (t === "string" ? (d3_rgb_names.has(b) || /^(#|rgb\(|hsl\()/.test(b) ? d3_interpolateRgb : d3_interpolateString)
21 | : b instanceof d3_Color ? d3_interpolateRgb
22 | : t === "object" ? (Array.isArray(b) ? d3_interpolateArray : d3_interpolateObject)
23 | : d3_interpolateNumber)(a, b);
24 | }
25 | ];
26 |
--------------------------------------------------------------------------------
/src/scale/identity.js:
--------------------------------------------------------------------------------
1 | import "linear";
2 | import "scale";
3 |
4 | d3.scale.identity = function() {
5 | return d3_scale_identity([0, 1]);
6 | };
7 |
8 | function d3_scale_identity(domain) {
9 |
10 | function identity(x) { return +x; }
11 |
12 | identity.invert = identity;
13 |
14 | identity.domain = identity.range = function(x) {
15 | if (!arguments.length) return domain;
16 | domain = x.map(identity);
17 | return identity;
18 | };
19 |
20 | identity.ticks = function(m) {
21 | return d3_scale_linearTicks(domain, m);
22 | };
23 |
24 | identity.tickFormat = function(m, format) {
25 | return d3_scale_linearTickFormat(domain, m, format);
26 | };
27 |
28 | identity.copy = function() {
29 | return d3_scale_identity(domain);
30 | };
31 |
32 | return identity;
33 | }
34 |
--------------------------------------------------------------------------------
/src/selection/enter-select.js:
--------------------------------------------------------------------------------
1 | import "selection";
2 | import "enter";
3 |
4 | d3_selection_enterPrototype.select = function(selector) {
5 | var subgroups = [],
6 | subgroup,
7 | subnode,
8 | upgroup,
9 | group,
10 | node;
11 |
12 | for (var j = -1, m = this.length; ++j < m;) {
13 | upgroup = (group = this[j]).update;
14 | subgroups.push(subgroup = []);
15 | subgroup.parentNode = group.parentNode;
16 | for (var i = -1, n = group.length; ++i < n;) {
17 | if (node = group[i]) {
18 | subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j));
19 | subnode.__data__ = node.__data__;
20 | } else {
21 | subgroup.push(null);
22 | }
23 | }
24 | }
25 |
26 | return d3_selection(subgroups);
27 | };
28 |
--------------------------------------------------------------------------------
/src/selection/filter.js:
--------------------------------------------------------------------------------
1 | import "selection";
2 |
3 | d3_selectionPrototype.filter = function(filter) {
4 | var subgroups = [],
5 | subgroup,
6 | group,
7 | node;
8 |
9 | if (typeof filter !== "function") filter = d3_selection_filter(filter);
10 |
11 | for (var j = 0, m = this.length; j < m; j++) {
12 | subgroups.push(subgroup = []);
13 | subgroup.parentNode = (group = this[j]).parentNode;
14 | for (var i = 0, n = group.length; i < n; i++) {
15 | if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {
16 | subgroup.push(node);
17 | }
18 | }
19 | }
20 |
21 | return d3_selection(subgroups);
22 | };
23 |
24 | function d3_selection_filter(selector) {
25 | return function() {
26 | return d3_selectMatches(this, selector);
27 | };
28 | }
29 |
--------------------------------------------------------------------------------
/src/selection/selectAll.js:
--------------------------------------------------------------------------------
1 | import "../core/array";
2 | import "selection";
3 |
4 | d3_selectionPrototype.selectAll = function(selector) {
5 | var subgroups = [],
6 | subgroup,
7 | node;
8 |
9 | selector = d3_selection_selectorAll(selector);
10 |
11 | for (var j = -1, m = this.length; ++j < m;) {
12 | for (var group = this[j], i = -1, n = group.length; ++i < n;) {
13 | if (node = group[i]) {
14 | subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j)));
15 | subgroup.parentNode = node;
16 | }
17 | }
18 | }
19 |
20 | return d3_selection(subgroups);
21 | };
22 |
23 | function d3_selection_selectorAll(selector) {
24 | return typeof selector === "function" ? selector : function() {
25 | return d3_selectAll(selector, this);
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/src/transition/each.js:
--------------------------------------------------------------------------------
1 | import "../selection/each";
2 | import "transition";
3 |
4 | d3_transitionPrototype.each = function(type, listener) {
5 | var id = this.id;
6 | if (arguments.length < 2) {
7 | var inherit = d3_transitionInherit,
8 | inheritId = d3_transitionInheritId;
9 | d3_transitionInheritId = id;
10 | d3_selection_each(this, function(node, i, j) {
11 | d3_transitionInherit = node.__transition__[id];
12 | type.call(node, node.__data__, i, j);
13 | });
14 | d3_transitionInherit = inherit;
15 | d3_transitionInheritId = inheritId;
16 | } else {
17 | d3_selection_each(this, function(node) {
18 | var transition = node.__transition__[id];
19 | (transition.event || (transition.event = d3.dispatch("start", "end"))).on(type, listener);
20 | });
21 | }
22 | return this;
23 | };
24 |
--------------------------------------------------------------------------------
/src/scale/threshold.js:
--------------------------------------------------------------------------------
1 | import "../arrays/bisect";
2 | import "scale";
3 |
4 | d3.scale.threshold = function() {
5 | return d3_scale_threshold([.5], [0, 1]);
6 | };
7 |
8 | function d3_scale_threshold(domain, range) {
9 |
10 | function scale(x) {
11 | if (x <= x) return range[d3.bisect(domain, x)];
12 | }
13 |
14 | scale.domain = function(_) {
15 | if (!arguments.length) return domain;
16 | domain = _;
17 | return scale;
18 | };
19 |
20 | scale.range = function(_) {
21 | if (!arguments.length) return range;
22 | range = _;
23 | return scale;
24 | };
25 |
26 | scale.invertExtent = function(y) {
27 | y = range.indexOf(y);
28 | return [domain[y - 1], domain[y]];
29 | };
30 |
31 | scale.copy = function() {
32 | return d3_scale_threshold(domain, range);
33 | };
34 |
35 | return scale;
36 | };
37 |
--------------------------------------------------------------------------------
/test/core/functor-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.functor");
6 |
7 | suite.addBatch({
8 | "functor": {
9 | topic: load("core/functor").expression("d3.functor"),
10 | "when passed a function, returns the function": function(functor) {
11 | function foo() {}
12 | assert.strictEqual(functor(foo), foo);
13 | },
14 | "when passed a non-function, returns a wrapper function": function(functor) {
15 | var a = {};
16 | assert.isNull(functor(null)());
17 | assert.isUndefined(functor(undefined)());
18 | assert.strictEqual(functor(a)(), a);
19 | assert.strictEqual(functor(1)(), 1);
20 | assert.deepEqual(functor([1])(), [1]);
21 | }
22 | }
23 | });
24 |
25 | suite.export(module);
26 |
--------------------------------------------------------------------------------
/src/geo/index.js:
--------------------------------------------------------------------------------
1 | import "geo";
2 | import "area";
3 | import "bounds";
4 | import "centroid";
5 | import "circle";
6 | import "distance";
7 | import "graticule";
8 | import "greatArc";
9 | import "interpolate";
10 | import "length";
11 | import "path";
12 | import "path-area";
13 | import "path-buffer";
14 | import "path-centroid";
15 | import "path-context";
16 | import "projection";
17 | import "rotation";
18 | import "stream";
19 | import "transform";
20 | import "albers";
21 | import "albers-usa";
22 | import "azimuthal";
23 | import "azimuthal-equal-area";
24 | import "azimuthal-equidistant";
25 | import "conic-conformal";
26 | import "conic-equal-area";
27 | import "conic-equidistant";
28 | import "equirectangular";
29 | import "gnomonic";
30 | import "mercator";
31 | import "orthographic";
32 | import "stereographic";
33 | import "transverse-mercator";
34 |
--------------------------------------------------------------------------------
/src/transition/tween.js:
--------------------------------------------------------------------------------
1 | import "../selection/each";
2 | import "transition";
3 |
4 | d3_transitionPrototype.tween = function(name, tween) {
5 | var id = this.id;
6 | if (arguments.length < 2) return this.node().__transition__[id].tween.get(name);
7 | return d3_selection_each(this, tween == null
8 | ? function(node) { node.__transition__[id].tween.remove(name); }
9 | : function(node) { node.__transition__[id].tween.set(name, tween); });
10 | };
11 |
12 | function d3_transition_tween(groups, name, value, tween) {
13 | var id = groups.id;
14 | return d3_selection_each(groups, typeof value === "function"
15 | ? function(node, i, j) { node.__transition__[id].tween.set(name, tween(value.call(node, node.__data__, i, j))); }
16 | : (value = tween(value), function(node) { node.__transition__[id].tween.set(name, value); }));
17 | }
18 |
--------------------------------------------------------------------------------
/src/format/formatPrefix.js:
--------------------------------------------------------------------------------
1 | import "precision";
2 | import "round";
3 | import "../math/abs";
4 |
5 | var d3_formatPrefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"].map(d3_formatPrefix);
6 |
7 | d3.formatPrefix = function(value, precision) {
8 | var i = 0;
9 | if (value) {
10 | if (value < 0) value *= -1;
11 | if (precision) value = d3.round(value, d3_format_precision(value, precision));
12 | i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10);
13 | i = Math.max(-24, Math.min(24, Math.floor((i <= 0 ? i + 1 : i - 1) / 3) * 3));
14 | }
15 | return d3_formatPrefixes[8 + i / 3];
16 | };
17 |
18 | function d3_formatPrefix(d, i) {
19 | var k = Math.pow(10, abs(8 - i) * 3);
20 | return {
21 | scale: i > 8 ? function(d) { return d / k; } : function(d) { return d * k; },
22 | symbol: d
23 | };
24 | }
25 |
--------------------------------------------------------------------------------
/test/arrays/keys-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.keys");
6 |
7 | suite.addBatch({
8 | "keys": {
9 | topic: load("arrays/keys").expression("d3.keys"),
10 | "enumerates every defined key": function(keys) {
11 | assert.deepEqual(keys({a: 1, b: 1}), ["a", "b"]);
12 | },
13 | "includes keys defined on prototypes": function(keys) {
14 | function abc() {
15 | this.a = 1;
16 | this.b = 2;
17 | }
18 | abc.prototype.c = 3;
19 | assert.deepEqual(keys(new abc()), ["a", "b", "c"]);
20 | },
21 | "includes keys with null or undefined values": function(keys) {
22 | assert.deepEqual(keys({a: undefined, b: null, c: NaN}), ["a", "b", "c"]);
23 | }
24 | }
25 | });
26 |
27 | suite.export(module);
28 |
--------------------------------------------------------------------------------
/src/transition/select.js:
--------------------------------------------------------------------------------
1 | import "../selection/select";
2 | import "transition";
3 |
4 | d3_transitionPrototype.select = function(selector) {
5 | var id = this.id,
6 | subgroups = [],
7 | subgroup,
8 | subnode,
9 | node;
10 |
11 | selector = d3_selection_selector(selector);
12 |
13 | for (var j = -1, m = this.length; ++j < m;) {
14 | subgroups.push(subgroup = []);
15 | for (var group = this[j], i = -1, n = group.length; ++i < n;) {
16 | if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i, j))) {
17 | if ("__data__" in node) subnode.__data__ = node.__data__;
18 | d3_transitionNode(subnode, i, id, node.__transition__[id]);
19 | subgroup.push(subnode);
20 | } else {
21 | subgroup.push(null);
22 | }
23 | }
24 | }
25 |
26 | return d3_transition(subgroups, id);
27 | };
28 |
--------------------------------------------------------------------------------
/src/arrays/bisect.js:
--------------------------------------------------------------------------------
1 | d3.bisector = function(f) {
2 | return {
3 | left: function(a, x, lo, hi) {
4 | if (arguments.length < 3) lo = 0;
5 | if (arguments.length < 4) hi = a.length;
6 | while (lo < hi) {
7 | var mid = lo + hi >>> 1;
8 | if (f.call(a, a[mid], mid) < x) lo = mid + 1;
9 | else hi = mid;
10 | }
11 | return lo;
12 | },
13 | right: function(a, x, lo, hi) {
14 | if (arguments.length < 3) lo = 0;
15 | if (arguments.length < 4) hi = a.length;
16 | while (lo < hi) {
17 | var mid = lo + hi >>> 1;
18 | if (x < f.call(a, a[mid], mid)) hi = mid;
19 | else lo = mid + 1;
20 | }
21 | return lo;
22 | }
23 | };
24 | };
25 |
26 | var d3_bisector = d3.bisector(function(d) { return d; });
27 | d3.bisectLeft = d3_bisector.left;
28 | d3.bisect = d3.bisectRight = d3_bisector.right;
29 |
--------------------------------------------------------------------------------
/src/geo/conic-equal-area.js:
--------------------------------------------------------------------------------
1 | import "../math/trigonometry";
2 | import "geo";
3 | import "conic";
4 | import "projection";
5 |
6 | function d3_geo_conicEqualArea(φ0, φ1) {
7 | var sinφ0 = Math.sin(φ0),
8 | n = (sinφ0 + Math.sin(φ1)) / 2,
9 | C = 1 + sinφ0 * (2 * n - sinφ0),
10 | ρ0 = Math.sqrt(C) / n;
11 |
12 | function forward(λ, φ) {
13 | var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n;
14 | return [
15 | ρ * Math.sin(λ *= n),
16 | ρ0 - ρ * Math.cos(λ)
17 | ];
18 | }
19 |
20 | forward.invert = function(x, y) {
21 | var ρ0_y = ρ0 - y;
22 | return [
23 | Math.atan2(x, ρ0_y) / n,
24 | d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n))
25 | ];
26 | };
27 |
28 | return forward;
29 | }
30 |
31 | (d3.geo.conicEqualArea = function() {
32 | return d3_geo_conic(d3_geo_conicEqualArea);
33 | }).raw = d3_geo_conicEqualArea;
34 |
--------------------------------------------------------------------------------
/test/transition/transition-test-text.js:
--------------------------------------------------------------------------------
1 | var assert = require("../assert");
2 |
3 | module.exports = {
4 | topic: function(d3) {
5 | return d3.select("body").append("div").text("foo").transition().text("bar");
6 | },
7 | "sets the text tween": function(div) {
8 | assert.typeOf(div.tween("text"), "function");
9 | },
10 | "start": {
11 | topic: function(div) {
12 | var cb = this.callback,
13 | tween = div.tween("text");
14 | div.tween("text", function() {
15 | var result = tween.apply(this, arguments);
16 | cb(null, {transition: div, tween: result});
17 | return result;
18 | });
19 | },
20 | "sets the text content as a string": function(result) {
21 | assert.equal(result.transition[0][0].textContent, "bar");
22 | },
23 | "does not interpolate text": function(result) {
24 | assert.isTrue(!result.tween);
25 | }
26 | }
27 | };
28 |
--------------------------------------------------------------------------------
/src/math/random.js:
--------------------------------------------------------------------------------
1 | d3.random = {
2 | normal: function(µ, σ) {
3 | var n = arguments.length;
4 | if (n < 2) σ = 1;
5 | if (n < 1) µ = 0;
6 | return function() {
7 | var x, y, r;
8 | do {
9 | x = Math.random() * 2 - 1;
10 | y = Math.random() * 2 - 1;
11 | r = x * x + y * y;
12 | } while (!r || r > 1);
13 | return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r);
14 | };
15 | },
16 | logNormal: function() {
17 | var random = d3.random.normal.apply(d3, arguments);
18 | return function() {
19 | return Math.exp(random());
20 | };
21 | },
22 | bates: function(m) {
23 | var random = d3.random.irwinHall(m);
24 | return function() {
25 | return random() / m;
26 | };
27 | },
28 | irwinHall: function(m) {
29 | return function() {
30 | for (var s = 0, j = 0; j < m; j++) s += Math.random();
31 | return s;
32 | };
33 | }
34 | };
35 |
--------------------------------------------------------------------------------
/src/compat/style.js:
--------------------------------------------------------------------------------
1 | import "../core/document";
2 |
3 | try {
4 | d3_document.createElement("div").style.setProperty("opacity", 0, "");
5 | } catch (error) {
6 | var d3_element_prototype = d3_window.Element.prototype,
7 | d3_element_setAttribute = d3_element_prototype.setAttribute,
8 | d3_element_setAttributeNS = d3_element_prototype.setAttributeNS,
9 | d3_style_prototype = d3_window.CSSStyleDeclaration.prototype,
10 | d3_style_setProperty = d3_style_prototype.setProperty;
11 | d3_element_prototype.setAttribute = function(name, value) {
12 | d3_element_setAttribute.call(this, name, value + "");
13 | };
14 | d3_element_prototype.setAttributeNS = function(space, local, value) {
15 | d3_element_setAttributeNS.call(this, space, local, value + "");
16 | };
17 | d3_style_prototype.setProperty = function(name, value, priority) {
18 | d3_style_setProperty.call(this, name, value + "", priority);
19 | };
20 | }
21 |
--------------------------------------------------------------------------------
/test/selection/enter-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("selection.enter");
6 |
7 | suite.addBatch({
8 | "selectAll(div)": {
9 | topic: load("selection/enter").document(),
10 | "is an instanceof d3.selection.enter": function(d3) {
11 | var enter = d3.select("body").selectAll("div").data([0, 1]).enter();
12 | assert.instanceOf(enter, d3.selection.enter);
13 | },
14 | "selection prototype can be extended": function(d3) {
15 | var enter = d3.select("body").html("").selectAll("div").data([0, 1]).enter();
16 | d3.selection.enter.prototype.foo = function() { return this.append("foo"); };
17 | var selection = enter.foo();
18 | assert.equal(d3.select("body").html(), "");
19 | delete d3.selection.enter.prototype.foo;
20 | }
21 | }
22 | });
23 |
24 | suite.export(module);
25 |
--------------------------------------------------------------------------------
/src/transition/selectAll.js:
--------------------------------------------------------------------------------
1 | import "../selection/select";
2 | import "transition";
3 |
4 | d3_transitionPrototype.selectAll = function(selector) {
5 | var id = this.id,
6 | subgroups = [],
7 | subgroup,
8 | subnodes,
9 | node,
10 | subnode,
11 | transition;
12 |
13 | selector = d3_selection_selectorAll(selector);
14 |
15 | for (var j = -1, m = this.length; ++j < m;) {
16 | for (var group = this[j], i = -1, n = group.length; ++i < n;) {
17 | if (node = group[i]) {
18 | transition = node.__transition__[id];
19 | subnodes = selector.call(node, node.__data__, i, j);
20 | subgroups.push(subgroup = []);
21 | for (var k = -1, o = subnodes.length; ++k < o;) {
22 | if (subnode = subnodes[k]) d3_transitionNode(subnode, k, id, transition);
23 | subgroup.push(subnode);
24 | }
25 | }
26 | }
27 | }
28 |
29 | return d3_transition(subgroups, id);
30 | };
31 |
--------------------------------------------------------------------------------
/src/geo/conic-equidistant.js:
--------------------------------------------------------------------------------
1 | import "../math/abs";
2 | import "../math/trigonometry";
3 | import "conic";
4 | import "equirectangular";
5 | import "geo";
6 | import "projection";
7 |
8 | function d3_geo_conicEquidistant(φ0, φ1) {
9 | var cosφ0 = Math.cos(φ0),
10 | n = φ0 === φ1 ? Math.sin(φ0) : (cosφ0 - Math.cos(φ1)) / (φ1 - φ0),
11 | G = cosφ0 / n + φ0;
12 |
13 | if (abs(n) < ε) return d3_geo_equirectangular;
14 |
15 | function forward(λ, φ) {
16 | var ρ = G - φ;
17 | return [
18 | ρ * Math.sin(n * λ),
19 | G - ρ * Math.cos(n * λ)
20 | ];
21 | }
22 |
23 | forward.invert = function(x, y) {
24 | var ρ0_y = G - y;
25 | return [
26 | Math.atan2(x, ρ0_y) / n,
27 | G - d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y)
28 | ];
29 | };
30 |
31 | return forward;
32 | }
33 |
34 | (d3.geo.conicEquidistant = function() {
35 | return d3_geo_conic(d3_geo_conicEquidistant);
36 | }).raw = d3_geo_conicEquidistant;
37 |
--------------------------------------------------------------------------------
/src/time/scale-utc.js:
--------------------------------------------------------------------------------
1 | import "../core/true";
2 | import "../scale/linear";
3 | import "scale";
4 | import "format-utc";
5 |
6 | var d3_time_scaleUtcMethods = d3_time_scaleLocalMethods.map(function(m) {
7 | return [m[0].utc, m[1]];
8 | });
9 |
10 | var d3_time_scaleUtcFormat = d3_time_formatUtc.multi([
11 | [".%L", function(d) { return d.getUTCMilliseconds(); }],
12 | [":%S", function(d) { return d.getUTCSeconds(); }],
13 | ["%I:%M", function(d) { return d.getUTCMinutes(); }],
14 | ["%I %p", function(d) { return d.getUTCHours(); }],
15 | ["%a %d", function(d) { return d.getUTCDay() && d.getUTCDate() != 1; }],
16 | ["%b %d", function(d) { return d.getUTCDate() != 1; }],
17 | ["%B", function(d) { return d.getUTCMonth(); }],
18 | ["%Y", d3_true]
19 | ]);
20 |
21 | d3_time_scaleUtcMethods.year = d3_time.year.utc;
22 |
23 | d3_time.scale.utc = function() {
24 | return d3_time_scale(d3.scale.linear(), d3_time_scaleUtcMethods, d3_time_scaleUtcFormat);
25 | };
26 |
--------------------------------------------------------------------------------
/src/geo/transverse-mercator.js:
--------------------------------------------------------------------------------
1 | import "../math/trigonometry";
2 | import "geo";
3 | import "mercator";
4 |
5 | function d3_geo_transverseMercator(λ, φ) {
6 | return [Math.log(Math.tan(π / 4 + φ / 2)), -λ];
7 | }
8 |
9 | d3_geo_transverseMercator.invert = function(x, y) {
10 | return [-y, 2 * Math.atan(Math.exp(x)) - halfπ];
11 | };
12 |
13 | (d3.geo.transverseMercator = function() {
14 | var projection = d3_geo_mercatorProjection(d3_geo_transverseMercator),
15 | center = projection.center,
16 | rotate = projection.rotate;
17 |
18 | projection.center = function(_) {
19 | return _
20 | ? center([-_[1], _[0]])
21 | : ((_ = center()), [-_[1], _[0]]);
22 | };
23 |
24 | projection.rotate = function(_) {
25 | return _
26 | ? rotate([_[0], _[1], _.length > 2 ? _[2] + 90 : 90])
27 | : ((_ = rotate()), [_[0], _[1], _[2] - 90]);
28 | };
29 |
30 | return projection.rotate([0, 0]);
31 | }).raw = d3_geo_transverseMercator;
32 |
--------------------------------------------------------------------------------
/src/selection/select.js:
--------------------------------------------------------------------------------
1 | import "selection";
2 |
3 | d3_selectionPrototype.select = function(selector) {
4 | var subgroups = [],
5 | subgroup,
6 | subnode,
7 | group,
8 | node;
9 |
10 | selector = d3_selection_selector(selector);
11 |
12 | for (var j = -1, m = this.length; ++j < m;) {
13 | subgroups.push(subgroup = []);
14 | subgroup.parentNode = (group = this[j]).parentNode;
15 | for (var i = -1, n = group.length; ++i < n;) {
16 | if (node = group[i]) {
17 | subgroup.push(subnode = selector.call(node, node.__data__, i, j));
18 | if (subnode && "__data__" in node) subnode.__data__ = node.__data__;
19 | } else {
20 | subgroup.push(null);
21 | }
22 | }
23 | }
24 |
25 | return d3_selection(subgroups);
26 | };
27 |
28 | function d3_selection_selector(selector) {
29 | return typeof selector === "function" ? selector : function() {
30 | return d3_select(selector, this);
31 | };
32 | }
33 |
--------------------------------------------------------------------------------
/test/arrays/values-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.values");
6 |
7 | suite.addBatch({
8 | "values": {
9 | topic: load("arrays/values").expression("d3.values"),
10 | "enumerates every value": function(values) {
11 | assert.deepEqual(values({a: 1, b: 2}), [1, 2]);
12 | },
13 | "includes values defined on prototypes": function(values) {
14 | function abc() {
15 | this.a = 1;
16 | this.b = 2;
17 | }
18 | abc.prototype.c = 3;
19 | assert.deepEqual(values(new abc()), [1, 2, 3]);
20 | },
21 | "includes null or undefined values": function(values) {
22 | var v = values({a: undefined, b: null, c: NaN});
23 | assert.isUndefined(v[0]);
24 | assert.isNull(v[1]);
25 | assert.isNaN(v[2]);
26 | assert.equal(v.length, 3);
27 | }
28 | }
29 | });
30 |
31 | suite.export(module);
32 |
--------------------------------------------------------------------------------
/test/geo/projection-test-suite.js:
--------------------------------------------------------------------------------
1 | var assert = require("../assert"),
2 | _ = require("../../"),
3 | format = _.format("13.8f");
4 |
5 | module.exports = function(suite, mapping) {
6 |
7 | for (var place in mapping) {
8 | suite[place] = test(mapping[place][0], mapping[place][1]);
9 | }
10 |
11 | function test(location, point) {
12 | return function(projection) {
13 | var actualLocation = projection.invert(point),
14 | actualPoint = projection(location);
15 | try {
16 | assert.inDelta([actualPoint, actualLocation], [point, location], 1e-5);
17 | } catch (e) {
18 | e.message = "project [["
19 | + location.map(format).join(", ") + "], [" + actualPoint.map(format).join(", ")
20 | + "]]\n invert [["
21 | + actualLocation.map(format).join(", ") + "], [" + point.map(format).join(", ")
22 | + "]]";
23 | throw e;
24 | }
25 | };
26 | }
27 |
28 | return suite;
29 | };
30 |
--------------------------------------------------------------------------------
/test/interpolate/array-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.interpolateArray");
6 |
7 | suite.addBatch({
8 | "interpolateArray": {
9 | topic: load("interpolate/array").expression("d3.interpolateArray"),
10 | "interpolates defined elements": function(interpolate) {
11 | assert.deepEqual(interpolate([2, 12], [4, 24])(.5), [3, 18]);
12 | },
13 | "interpolates nested objects and arrays": function(interpolate) {
14 | assert.deepEqual(interpolate([[2, 12]], [[4, 24]])(.5), [[3, 18]]);
15 | assert.deepEqual(interpolate([{foo: [2, 12]}], [{foo: [4, 24]}])(.5), [{foo: [3, 18]}]);
16 | },
17 | "merges non-shared elements": function(interpolate) {
18 | assert.deepEqual(interpolate([2, 12], [4, 24, 12])(.5), [3, 18, 12]);
19 | assert.deepEqual(interpolate([2, 12, 12], [4, 24])(.5), [3, 18, 12]);
20 | }
21 | }
22 | });
23 |
24 | suite.export(module);
25 |
--------------------------------------------------------------------------------
/bin/uglify:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | var fs = require("fs"),
4 | uglify = require("uglify-js");
5 |
6 | var filename = process.argv[2],
7 | toplevel = uglify.parse(fs.readFileSync(filename, "utf8"), {filename: filename}),
8 | output = uglify.OutputStream({ascii_only: true}),
9 | compressor = uglify.Compressor(true),
10 | warn = uglify.AST_Node.warn;
11 |
12 | uglify.AST_Node.warn = function(s, o) {
13 | if (o.msg === "Accidental global?" && o.name === "d3" && o.line === 1 && !o.col) return;
14 | warn.apply(this, arguments);
15 | };
16 |
17 | toplevel.figure_out_scope();
18 | toplevel.scope_warnings({
19 | undeclared: false,
20 | unreferenced: false,
21 | assign_to_global: true,
22 | func_arguments: false,
23 | nested_defuns: false,
24 | eval: false
25 | });
26 |
27 | toplevel = toplevel.transform(compressor);
28 |
29 | toplevel.figure_out_scope();
30 | toplevel.compute_char_frequency(true);
31 | toplevel.mangle_names(true);
32 | toplevel.print(output);
33 |
34 | require("util").print(output.get());
35 |
--------------------------------------------------------------------------------
/test/arrays/zip-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.zip");
6 |
7 | suite.addBatch({
8 | "zip": {
9 | topic: load("arrays/zip").expression("d3.zip"),
10 | "transposes a square matrix": function(zip) {
11 | assert.deepEqual(zip([1, 2], [3, 4]), [[1, 3], [2, 4]]);
12 | },
13 | "transposes a non-square matrix": function(zip) {
14 | assert.deepEqual(zip([1, 2, 3, 4, 5], [2, 4, 6, 8, 10]), [[1, 2], [2, 4], [3, 6], [4, 8], [5, 10]]);
15 | },
16 | "transposes a single-row matrix": function(zip) {
17 | assert.deepEqual(zip([1, 2, 3, 4, 5]), [[1], [2], [3], [4], [5]]);
18 | },
19 | "transposes an empty matrix": function(zip) {
20 | assert.deepEqual(zip(), []);
21 | },
22 | "ignores extra elements given an irregular matrix": function(zip) {
23 | assert.deepEqual(zip([1, 2], [3, 4], [5, 6, 7]), [[1, 3, 5], [2, 4, 6]]);
24 | }
25 | }
26 | });
27 |
28 | suite.export(module);
29 |
--------------------------------------------------------------------------------
/src/scale/quantize.js:
--------------------------------------------------------------------------------
1 | import "scale";
2 |
3 | d3.scale.quantize = function() {
4 | return d3_scale_quantize(0, 1, [0, 1]);
5 | };
6 |
7 | function d3_scale_quantize(x0, x1, range) {
8 | var kx, i;
9 |
10 | function scale(x) {
11 | return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))];
12 | }
13 |
14 | function rescale() {
15 | kx = range.length / (x1 - x0);
16 | i = range.length - 1;
17 | return scale;
18 | }
19 |
20 | scale.domain = function(x) {
21 | if (!arguments.length) return [x0, x1];
22 | x0 = +x[0];
23 | x1 = +x[x.length - 1];
24 | return rescale();
25 | };
26 |
27 | scale.range = function(x) {
28 | if (!arguments.length) return range;
29 | range = x;
30 | return rescale();
31 | };
32 |
33 | scale.invertExtent = function(y) {
34 | y = range.indexOf(y);
35 | y = y < 0 ? NaN : y / kx + x0;
36 | return [y, y + 1 / kx];
37 | };
38 |
39 | scale.copy = function() {
40 | return d3_scale_quantize(x0, x1, range); // copy on write
41 | };
42 |
43 | return rescale();
44 | }
45 |
--------------------------------------------------------------------------------
/test/arrays/pairs-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.pairs");
6 |
7 | suite.addBatch({
8 | "pairs": {
9 | topic: load("arrays/pairs").expression("d3.pairs"),
10 | "returns the empty array if input array has length less than two": function(pairs) {
11 | assert.deepEqual(pairs([]), []);
12 | assert.deepEqual(pairs([1]), []);
13 | },
14 | "returns pairs of adjacent elements in the given array": function(pairs) {
15 | assert.deepEqual(pairs([1, 2]), [[1, 2]]);
16 | assert.deepEqual(pairs([1, 2, 3]), [[1, 2], [2, 3]]);
17 | var a = {}, b = {}, c = {}, d = {};
18 | assert.deepEqual(pairs([a, b, c, d]), [[a, b], [b, c], [c, d]]);
19 | },
20 | "includes null or undefined elements in pairs": function(pairs) {
21 | assert.deepEqual(pairs([1, null, 2]), [[1, null], [null, 2]]);
22 | assert.deepEqual(pairs([1, 2, undefined]), [[1, 2], [2, undefined]]);
23 | }
24 | }
25 | });
26 |
27 | suite.export(module);
28 |
--------------------------------------------------------------------------------
/test/time/time.js:
--------------------------------------------------------------------------------
1 | var offset = 0;
2 |
3 | exports.local = function(year, month, day, hours, minutes, seconds, milliseconds) {
4 | var date = new Date();
5 | date.setFullYear(year, month, day);
6 | date.setHours(hours || 0, offset + (minutes || 0), seconds || 0, milliseconds || 0);
7 | return date;
8 | };
9 |
10 | exports.utc = function(year, month, day, hours, minutes, seconds, milliseconds) {
11 | var date = new Date();
12 | date.setUTCFullYear(year, month, day);
13 | date.setUTCHours(hours || 0, minutes || 0, seconds || 0, milliseconds || 0);
14 | return date;
15 | };
16 |
17 | exports.zone = function(tzOffset, scope) {
18 | return function() {
19 | var o = Date.prototype.getTimezoneOffset;
20 | try {
21 | // Note: assumes the dates are not in DST.
22 | offset = -tzOffset - new Date(0).getTimezoneOffset();
23 | Date.prototype.getTimezoneOffset = function() { return offset; };
24 | scope.apply(this, arguments);
25 | } finally {
26 | offset = 0;
27 | Date.prototype.getTimezoneOffset = o;
28 | }
29 | };
30 | };
31 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | var document = require("jsdom").jsdom(""),
2 | window = document.createWindow(),
3 | globals = {};
4 |
5 | // stash globals
6 | if ("window" in global) globals.window = global.window;
7 | global.window = window;
8 | if ("document" in global) globals.document = global.document;
9 | global.document = document;
10 |
11 | // https://github.com/chad3814/CSSStyleDeclaration/issues/3
12 | var CSSStyleDeclaration_prototype = window.CSSStyleDeclaration.prototype,
13 | CSSStyleDeclaration_setProperty = CSSStyleDeclaration_prototype.setProperty;
14 | CSSStyleDeclaration_prototype.setProperty = function(name, value, priority) {
15 | return CSSStyleDeclaration_setProperty.call(this, name + "", value == null ? null : value + "", priority == null ? null : priority + "");
16 | };
17 |
18 | module.exports = require("./d3");
19 |
20 | // restore globals
21 | if ("window" in globals) global.window = globals.window;
22 | else delete global.window;
23 | if ("document" in globals) global.document = globals.document;
24 | else delete global.document;
25 |
--------------------------------------------------------------------------------
/test/math/transform-rotate-origin-test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
41 |
--------------------------------------------------------------------------------
/src/geo/cartesian.js:
--------------------------------------------------------------------------------
1 | // TODO
2 | // cross and scale return new vectors,
3 | // whereas add and normalize operate in-place
4 |
5 | function d3_geo_cartesian(spherical) {
6 | var λ = spherical[0],
7 | φ = spherical[1],
8 | cosφ = Math.cos(φ);
9 | return [
10 | cosφ * Math.cos(λ),
11 | cosφ * Math.sin(λ),
12 | Math.sin(φ)
13 | ];
14 | }
15 |
16 | function d3_geo_cartesianDot(a, b) {
17 | return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
18 | }
19 |
20 | function d3_geo_cartesianCross(a, b) {
21 | return [
22 | a[1] * b[2] - a[2] * b[1],
23 | a[2] * b[0] - a[0] * b[2],
24 | a[0] * b[1] - a[1] * b[0]
25 | ];
26 | }
27 |
28 | function d3_geo_cartesianAdd(a, b) {
29 | a[0] += b[0];
30 | a[1] += b[1];
31 | a[2] += b[2];
32 | }
33 |
34 | function d3_geo_cartesianScale(vector, k) {
35 | return [
36 | vector[0] * k,
37 | vector[1] * k,
38 | vector[2] * k
39 | ];
40 | }
41 |
42 | function d3_geo_cartesianNormalize(d) {
43 | var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
44 | d[0] /= l;
45 | d[1] /= l;
46 | d[2] /= l;
47 | }
48 |
--------------------------------------------------------------------------------
/src/geo/conic-conformal.js:
--------------------------------------------------------------------------------
1 | import "../math/abs";
2 | import "../math/trigonometry";
3 | import "conic";
4 | import "geo";
5 | import "projection";
6 |
7 | function d3_geo_conicConformal(φ0, φ1) {
8 | var cosφ0 = Math.cos(φ0),
9 | t = function(φ) { return Math.tan(π / 4 + φ / 2); },
10 | n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)),
11 | F = cosφ0 * Math.pow(t(φ0), n) / n;
12 |
13 | if (!n) return d3_geo_mercator;
14 |
15 | function forward(λ, φ) {
16 | var ρ = abs(abs(φ) - halfπ) < ε ? 0 : F / Math.pow(t(φ), n);
17 | return [
18 | ρ * Math.sin(n * λ),
19 | F - ρ * Math.cos(n * λ)
20 | ];
21 | }
22 |
23 | forward.invert = function(x, y) {
24 | var ρ0_y = F - y,
25 | ρ = d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y);
26 | return [
27 | Math.atan2(x, ρ0_y) / n,
28 | 2 * Math.atan(Math.pow(F / ρ, 1 / n)) - halfπ
29 | ];
30 | };
31 |
32 | return forward;
33 | }
34 |
35 | (d3.geo.conicConformal = function() {
36 | return d3_geo_conic(d3_geo_conicConformal);
37 | }).raw = d3_geo_conicConformal;
38 |
--------------------------------------------------------------------------------
/test/transition/transition-test-call.js:
--------------------------------------------------------------------------------
1 | var assert = require("../assert");
2 |
3 | module.exports = {
4 | topic: function(d3) {
5 | return d3.select("body").append("div").transition();
6 | },
7 | "calls the function once": function(transition) {
8 | var count = 0;
9 | transition.call(function() { ++count; });
10 | assert.equal(count, 1);
11 | },
12 | "passes any optional arguments": function(transition) {
13 | var abc;
14 | transition.call(function(selection, a, b, c) { abc = [a, b, c]; }, "a", "b", "c");
15 | assert.deepEqual(abc, ["a", "b", "c"]);
16 | },
17 | "passes the transition as the first argument": function(transition) {
18 | var t;
19 | transition.call(function(x) { t = x; });
20 | assert.isTrue(t === transition);
21 | },
22 | "uses the transition as the context": function(transition) {
23 | var t;
24 | transition.call(function() { t = this; });
25 | assert.isTrue(t === transition);
26 | },
27 | "returns the current transition": function(transition) {
28 | assert.isTrue(transition.call(function() {}) === transition);
29 | }
30 | };
31 |
--------------------------------------------------------------------------------
/src/math/adder.js:
--------------------------------------------------------------------------------
1 | // Adds floating point numbers with twice the normal precision.
2 | // Reference: J. R. Shewchuk, Adaptive Precision Floating-Point Arithmetic and
3 | // Fast Robust Geometric Predicates, Discrete & Computational Geometry 18(3)
4 | // 305–363 (1997).
5 | // Code adapted from GeographicLib by Charles F. F. Karney,
6 | // http://geographiclib.sourceforge.net/
7 | // See lib/geographiclib/LICENSE for details.
8 |
9 | function d3_adder() {}
10 |
11 | d3_adder.prototype = {
12 | s: 0, // rounded value
13 | t: 0, // exact error
14 | add: function(y) {
15 | d3_adderSum(y, this.t, d3_adderTemp);
16 | d3_adderSum(d3_adderTemp.s, this.s, this);
17 | if (this.s) this.t += d3_adderTemp.t;
18 | else this.s = d3_adderTemp.t;
19 | },
20 | reset: function() {
21 | this.s = this.t = 0;
22 | },
23 | valueOf: function() {
24 | return this.s;
25 | }
26 | };
27 |
28 | var d3_adderTemp = new d3_adder;
29 |
30 | function d3_adderSum(a, b, o) {
31 | var x = o.s = a + b, // a + b
32 | bv = x - a, av = x - bv; // b_virtual & a_virtual
33 | o.t = (a - av) + (b - bv); // a_roundoff + b_roundoff
34 | }
35 |
--------------------------------------------------------------------------------
/test/selection/order-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("selection.order");
6 |
7 | suite.addBatch({
8 | "selectAll(div)": {
9 | topic: load("selection/call").document(),
10 | "on a simple page": {
11 | topic: function(d3) {
12 | return d3.select("body").selectAll("div")
13 | .data([1, 2, 10, 20])
14 | .enter().append("div")
15 | .attr("id", String);
16 | },
17 | "orders elements by data": function(div) {
18 | div = div.data([1, 10, 20, 2], String).order();
19 | assert.domNull(div[0][0].previousSibling);
20 | assert.domEqual(div[0][1].previousSibling, div[0][0]);
21 | assert.domEqual(div[0][2].previousSibling, div[0][1]);
22 | assert.domEqual(div[0][3].previousSibling, div[0][2]);
23 | assert.domNull(div[0][3].nextSibling);
24 | },
25 | "returns the current selection": function(span) {
26 | assert.isTrue(span.order() === span);
27 | }
28 | }
29 | }
30 | });
31 |
32 | suite.export(module);
33 |
--------------------------------------------------------------------------------
/src/time/week.js:
--------------------------------------------------------------------------------
1 | import "day";
2 | import "interval";
3 | import "time";
4 | import "year";
5 |
6 | ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"].forEach(function(day, i) {
7 | i = 7 - i;
8 |
9 | var interval = d3_time[day] = d3_time_interval(function(date) {
10 | (date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7);
11 | return date;
12 | }, function(date, offset) {
13 | date.setDate(date.getDate() + Math.floor(offset) * 7);
14 | }, function(date) {
15 | var day = d3_time.year(date).getDay();
16 | return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i);
17 | });
18 |
19 | d3_time[day + "s"] = interval.range;
20 | d3_time[day + "s"].utc = interval.utc.range;
21 |
22 | d3_time[day + "OfYear"] = function(date) {
23 | var day = d3_time.year(date).getDay();
24 | return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7);
25 | };
26 | });
27 |
28 | d3_time.week = d3_time.sunday;
29 | d3_time.weeks = d3_time.sunday.range;
30 | d3_time.weeks.utc = d3_time.sunday.utc.range;
31 | d3_time.weekOfYear = d3_time.sundayOfYear;
32 |
--------------------------------------------------------------------------------
/test/arrays/transpose-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.transpose");
6 |
7 | suite.addBatch({
8 | "transpose": {
9 | topic: load("arrays/transpose").expression("d3.transpose"),
10 | "transposes a square matrix": function(transpose) {
11 | assert.deepEqual(transpose([[1, 2], [3, 4]]), [[1, 3], [2, 4]]);
12 | },
13 | "transposes a non-square matrix": function(transpose) {
14 | assert.deepEqual(transpose([[1, 2, 3, 4, 5], [2, 4, 6, 8, 10]]), [[1, 2], [2, 4], [3, 6], [4, 8], [5, 10]]);
15 | },
16 | "transposes a single-row matrix": function(transpose) {
17 | assert.deepEqual(transpose([[1, 2, 3, 4, 5]]), [[1], [2], [3], [4], [5]]);
18 | },
19 | "transposes an empty matrix": function(transpose) {
20 | assert.deepEqual(transpose([]), []);
21 | },
22 | "ignores extra elements given an irregular matrix": function(transpose) {
23 | assert.deepEqual(transpose([[1, 2], [3, 4], [5, 6, 7]]), [[1, 3, 5], [2, 4, 6]]);
24 | }
25 | }
26 | });
27 |
28 | suite.export(module);
29 |
--------------------------------------------------------------------------------
/test/time/format-iso-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert"),
4 | time = require("./time"),
5 | utc = time.utc;
6 |
7 | var suite = vows.describe("d3.time.format");
8 |
9 | suite.addBatch({
10 | "format.iso": {
11 | topic: load("time/format-iso").expression("d3.time.format.iso"),
12 |
13 | "toString is %Y-%m-%dT%H:%M:%S.%LZ": function(format) {
14 | assert.equal(format + "", "%Y-%m-%dT%H:%M:%S.%LZ");
15 | },
16 |
17 | "formats as ISO 8601": function(format) {
18 | assert.equal(format(utc(1990, 0, 1, 0, 0, 0)), "1990-01-01T00:00:00.000Z");
19 | assert.equal(format(utc(2011, 11, 31, 23, 59, 59)), "2011-12-31T23:59:59.000Z");
20 | },
21 |
22 | "parse": {
23 | "parses as ISO 8601": function(format) {
24 | var p = format.parse;
25 | assert.deepEqual(p("1990-01-01T00:00:00.000Z"), utc(1990, 0, 1, 0, 0, 0));
26 | assert.deepEqual(p("2011-12-31T23:59:59.000Z"), utc(2011, 11, 31, 23, 59, 59));
27 | assert.isNull(p("1990-01-01T00:00:00.000X"));
28 | }
29 | }
30 | }
31 | });
32 |
33 | suite.export(module);
34 |
--------------------------------------------------------------------------------
/test/geo/greatArc-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.geo.greatArc");
6 |
7 | suite.addBatch({
8 | "greatArc": {
9 | topic: load("geo/greatArc").expression("d3.geo.greatArc"),
10 | "distance": function(arc) {
11 | var a = arc();
12 | assert.equal(a.distance({source: [0, 0], target: [0, 0]}), 0);
13 | assert.inDelta(a.distance({
14 | source: [118 + 24 / 60, 33 + 57 / 60],
15 | target: [ 73 + 47 / 60, 40 + 38 / 60]
16 | }), 3973 / 6371, .5);
17 | },
18 | "source and target can be set as constants": function(arc) {
19 | var a = arc().source([5, 52]).target([-120, 37]);
20 | assert.inDelta(a().coordinates, [
21 | [ 5, 52 ],
22 | [-120, 37 ]
23 | ], .5);
24 | },
25 | "geodesic": function(arc) {
26 | var a = arc();
27 | assert.inDelta(a({source: [5, 52], target: [-120, 37]}).coordinates, [
28 | [ 5, 52 ],
29 | [-120, 37 ]
30 | ], .5);
31 | }
32 | }
33 | });
34 |
35 | suite.export(module);
36 |
--------------------------------------------------------------------------------
/src/svg/diagonal.js:
--------------------------------------------------------------------------------
1 | import "../core/functor";
2 | import "../core/source";
3 | import "../core/target";
4 | import "svg";
5 |
6 | d3.svg.diagonal = function() {
7 | var source = d3_source,
8 | target = d3_target,
9 | projection = d3_svg_diagonalProjection;
10 |
11 | function diagonal(d, i) {
12 | var p0 = source.call(this, d, i),
13 | p3 = target.call(this, d, i),
14 | m = (p0.y + p3.y) / 2,
15 | p = [p0, {x: p0.x, y: m}, {x: p3.x, y: m}, p3];
16 | p = p.map(projection);
17 | return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3];
18 | }
19 |
20 | diagonal.source = function(x) {
21 | if (!arguments.length) return source;
22 | source = d3_functor(x);
23 | return diagonal;
24 | };
25 |
26 | diagonal.target = function(x) {
27 | if (!arguments.length) return target;
28 | target = d3_functor(x);
29 | return diagonal;
30 | };
31 |
32 | diagonal.projection = function(x) {
33 | if (!arguments.length) return projection;
34 | projection = x;
35 | return diagonal;
36 | };
37 |
38 | return diagonal;
39 | };
40 |
41 | function d3_svg_diagonalProjection(d) {
42 | return [d.x, d.y];
43 | }
44 |
--------------------------------------------------------------------------------
/src/geo/transform.js:
--------------------------------------------------------------------------------
1 | import "geo";
2 | import "../core/array";
3 |
4 | d3.geo.transform = function(methods) {
5 | return {
6 | stream: function(stream) {
7 | var transform = new d3_geo_transform(stream);
8 | for (var k in methods) transform[k] = methods[k];
9 | return transform;
10 | }
11 | };
12 | };
13 |
14 | function d3_geo_transform(stream) {
15 | this.stream = stream;
16 | }
17 |
18 | d3_geo_transform.prototype = {
19 | point: function(x, y) { this.stream.point(x, y); },
20 | sphere: function() { this.stream.sphere(); },
21 | lineStart: function() { this.stream.lineStart(); },
22 | lineEnd: function() { this.stream.lineEnd(); },
23 | polygonStart: function() { this.stream.polygonStart(); },
24 | polygonEnd: function() { this.stream.polygonEnd(); }
25 | };
26 |
27 | function d3_geo_transformPoint(stream, point) {
28 | return {
29 | point: point,
30 | sphere: function() { stream.sphere(); },
31 | lineStart: function() { stream.lineStart(); },
32 | lineEnd: function() { stream.lineEnd(); },
33 | polygonStart: function() { stream.polygonStart(); },
34 | polygonEnd: function() { stream.polygonEnd(); },
35 | };
36 | }
37 |
--------------------------------------------------------------------------------
/src/event/drag.js:
--------------------------------------------------------------------------------
1 | import "../core/document";
2 | import "../core/vendor";
3 | import "../selection/on";
4 |
5 | var d3_event_dragSelect = "onselectstart" in d3_document ? null : d3_vendorSymbol(d3_documentElement.style, "userSelect"),
6 | d3_event_dragId = 0;
7 |
8 | function d3_event_dragSuppress() {
9 | var name = ".dragsuppress-" + ++d3_event_dragId,
10 | click = "click" + name,
11 | w = d3.select(d3_window)
12 | .on("touchmove" + name, d3_eventPreventDefault)
13 | .on("dragstart" + name, d3_eventPreventDefault)
14 | .on("selectstart" + name, d3_eventPreventDefault);
15 | if (d3_event_dragSelect) {
16 | var style = d3_documentElement.style,
17 | select = style[d3_event_dragSelect];
18 | style[d3_event_dragSelect] = "none";
19 | }
20 | return function(suppressClick) {
21 | w.on(name, null);
22 | if (d3_event_dragSelect) style[d3_event_dragSelect] = select;
23 | if (suppressClick) { // suppress the next click, but only if it’s immediate
24 | function off() { w.on(click, null); }
25 | w.on(click, function() { d3_eventPreventDefault(); off(); }, true);
26 | setTimeout(off, 0);
27 | }
28 | };
29 | }
30 |
--------------------------------------------------------------------------------
/src/geo/path-area.js:
--------------------------------------------------------------------------------
1 | import "../core/noop";
2 | import "../math/abs";
3 |
4 | // TODO Unify this code with d3.geom.polygon area?
5 |
6 | var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = {
7 | point: d3_noop,
8 | lineStart: d3_noop,
9 | lineEnd: d3_noop,
10 |
11 | // Only count area for polygon rings.
12 | polygonStart: function() {
13 | d3_geo_pathAreaPolygon = 0;
14 | d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart;
15 | },
16 | polygonEnd: function() {
17 | d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop;
18 | d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2);
19 | }
20 | };
21 |
22 | function d3_geo_pathAreaRingStart() {
23 | var x00, y00, x0, y0;
24 |
25 | // For the first point, …
26 | d3_geo_pathArea.point = function(x, y) {
27 | d3_geo_pathArea.point = nextPoint;
28 | x00 = x0 = x, y00 = y0 = y;
29 | };
30 |
31 | // For subsequent points, …
32 | function nextPoint(x, y) {
33 | d3_geo_pathAreaPolygon += y0 * x - x0 * y;
34 | x0 = x, y0 = y;
35 | }
36 |
37 | // For the last point, return to the start.
38 | d3_geo_pathArea.lineEnd = function() {
39 | nextPoint(x00, y00);
40 | };
41 | }
42 |
--------------------------------------------------------------------------------
/src/math/trigonometry.js:
--------------------------------------------------------------------------------
1 | var π = Math.PI,
2 | τ = 2 * π,
3 | halfπ = π / 2,
4 | ε = 1e-6,
5 | ε2 = ε * ε,
6 | d3_radians = π / 180,
7 | d3_degrees = 180 / π;
8 |
9 | function d3_sgn(x) {
10 | return x > 0 ? 1 : x < 0 ? -1 : 0;
11 | }
12 |
13 | // Returns the 2D cross product of AB and AC vectors, i.e., the z-component of
14 | // the 3D cross product in a quadrant I Cartesian coordinate system (+x is
15 | // right, +y is up). Returns a positive value if ABC is counter-clockwise,
16 | // negative if clockwise, and zero if the points are collinear.
17 | function d3_cross2d(a, b, c) {
18 | return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
19 | }
20 |
21 | function d3_acos(x) {
22 | return x > 1 ? 0 : x < -1 ? π : Math.acos(x);
23 | }
24 |
25 | function d3_asin(x) {
26 | return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x);
27 | }
28 |
29 | function d3_sinh(x) {
30 | return ((x = Math.exp(x)) - 1 / x) / 2;
31 | }
32 |
33 | function d3_cosh(x) {
34 | return ((x = Math.exp(x)) + 1 / x) / 2;
35 | }
36 |
37 | function d3_tanh(x) {
38 | return ((x = Math.exp(2 * x)) - 1) / (x + 1);
39 | }
40 |
41 | function d3_haversin(x) {
42 | return (x = Math.sin(x / 2)) * x;
43 | }
44 |
--------------------------------------------------------------------------------
/test/geo/rotation-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.geo.rotation");
6 |
7 | suite.addBatch({
8 | "rotation": {
9 | topic: load("geo/rotation").expression("d3.geo.rotation"),
10 | "a rotation of [+90°, 0°]": {
11 | topic: function(rotation) {
12 | return rotation([90, 0]);
13 | },
14 | "only rotates longitude": function(rotation) {
15 | assert.inDelta(rotation([0, 0]), [90, 0], 1e-6);
16 | },
17 | "wraps around when crossing the antimeridian": function(rotation) {
18 | assert.inDelta(rotation([150, 0]), [-120, 0], 1e-6);
19 | }
20 | },
21 | "a rotation of [-45°, -45°]": {
22 | topic: function(rotation) {
23 | return rotation([-45, 45]);
24 | },
25 | "rotates longitude and latitude": function(rotation) {
26 | assert.inDelta(rotation([0, 0]), [-54.73561, 30], 1e-6);
27 | },
28 | "inverse rotation of longitude and latitude": function(rotation) {
29 | assert.inDelta(rotation.invert([-54.73561, 30]), [0, 0], 1e-6);
30 | }
31 | }
32 | }
33 | });
34 |
35 | suite.export(module);
36 |
--------------------------------------------------------------------------------
/lib/geographiclib/LICENSE:
--------------------------------------------------------------------------------
1 | This license applies to GeographicLib, versions 1.12 and later.
2 |
3 | Copyright (c) 2008-2012, Charles Karney
4 |
5 | Permission is hereby granted, free of charge, to any person
6 | obtaining a copy of this software and associated documentation
7 | files (the "Software"), to deal in the Software without
8 | restriction, including without limitation the rights to use, copy,
9 | modify, merge, publish, distribute, sublicense, and/or sell copies
10 | of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 | DEALINGS IN THE SOFTWARE.
24 |
--------------------------------------------------------------------------------
/src/geo/greatArc.js:
--------------------------------------------------------------------------------
1 | import "../core/source";
2 | import "../core/target";
3 | import "geo";
4 | import "distance";
5 |
6 | // @deprecated use {type: "LineString"} or d3.geo.distance instead.
7 | d3.geo.greatArc = function() {
8 | var source = d3_source, source_,
9 | target = d3_target, target_;
10 |
11 | function greatArc() {
12 | return {type: "LineString", coordinates: [
13 | source_ || source.apply(this, arguments),
14 | target_ || target.apply(this, arguments)
15 | ]};
16 | }
17 |
18 | greatArc.distance = function() {
19 | return d3.geo.distance(
20 | source_ || source.apply(this, arguments),
21 | target_ || target.apply(this, arguments)
22 | );
23 | };
24 |
25 | greatArc.source = function(_) {
26 | if (!arguments.length) return source;
27 | source = _, source_ = typeof _ === "function" ? null : _;
28 | return greatArc;
29 | };
30 |
31 | greatArc.target = function(_) {
32 | if (!arguments.length) return target;
33 | target = _, target_ = typeof _ === "function" ? null : _;
34 | return greatArc;
35 | };
36 |
37 | greatArc.precision = function() {
38 | return arguments.length ? greatArc : 0;
39 | };
40 |
41 | return greatArc;
42 | };
43 |
--------------------------------------------------------------------------------
/src/geo/interpolate.js:
--------------------------------------------------------------------------------
1 | import "../math/trigonometry";
2 | import "geo";
3 |
4 | d3.geo.interpolate = function(source, target) {
5 | return d3_geo_interpolate(
6 | source[0] * d3_radians, source[1] * d3_radians,
7 | target[0] * d3_radians, target[1] * d3_radians
8 | );
9 | };
10 |
11 | function d3_geo_interpolate(x0, y0, x1, y1) {
12 | var cy0 = Math.cos(y0),
13 | sy0 = Math.sin(y0),
14 | cy1 = Math.cos(y1),
15 | sy1 = Math.sin(y1),
16 | kx0 = cy0 * Math.cos(x0),
17 | ky0 = cy0 * Math.sin(x0),
18 | kx1 = cy1 * Math.cos(x1),
19 | ky1 = cy1 * Math.sin(x1),
20 | d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))),
21 | k = 1 / Math.sin(d);
22 |
23 | var interpolate = d ? function(t) {
24 | var B = Math.sin(t *= d) * k,
25 | A = Math.sin(d - t) * k,
26 | x = A * kx0 + B * kx1,
27 | y = A * ky0 + B * ky1,
28 | z = A * sy0 + B * sy1;
29 | return [
30 | Math.atan2(y, x) * d3_degrees,
31 | Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees
32 | ];
33 | } : function() { return [x0 * d3_degrees, y0 * d3_degrees]; };
34 |
35 | interpolate.distance = d;
36 |
37 | return interpolate;
38 | };
39 |
--------------------------------------------------------------------------------
/src/geo/path-context.js:
--------------------------------------------------------------------------------
1 | import "../core/noop";
2 | import "../math/trigonometry";
3 |
4 | function d3_geo_pathContext(context) {
5 | var pointRadius = 4.5;
6 |
7 | var stream = {
8 | point: point,
9 |
10 | // While inside a line, override point to moveTo then lineTo.
11 | lineStart: function() { stream.point = pointLineStart; },
12 | lineEnd: lineEnd,
13 |
14 | // While inside a polygon, override lineEnd to closePath.
15 | polygonStart: function() { stream.lineEnd = lineEndPolygon; },
16 | polygonEnd: function() { stream.lineEnd = lineEnd; stream.point = point; },
17 |
18 | pointRadius: function(_) {
19 | pointRadius = _;
20 | return stream;
21 | },
22 |
23 | result: d3_noop
24 | };
25 |
26 | function point(x, y) {
27 | context.moveTo(x, y);
28 | context.arc(x, y, pointRadius, 0, τ);
29 | }
30 |
31 | function pointLineStart(x, y) {
32 | context.moveTo(x, y);
33 | stream.point = pointLine;
34 | }
35 |
36 | function pointLine(x, y) {
37 | context.lineTo(x, y);
38 | }
39 |
40 | function lineEnd() {
41 | stream.point = point;
42 | }
43 |
44 | function lineEndPolygon() {
45 | context.closePath();
46 | }
47 |
48 | return stream;
49 | }
50 |
--------------------------------------------------------------------------------
/test/xhr/html-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.html");
6 |
7 | suite.addBatch({
8 | "html": {
9 | topic: load("xhr/html").expression("d3.html").document(),
10 |
11 | "on a sample file": {
12 | topic: function(html) {
13 | html("test/data/sample.html", this.callback);
14 | },
15 | "invokes the callback with the loaded html": function(document) {
16 | assert.equal(document.getElementsByTagName("H1")[0].textContent, "Hello & world!");
17 | },
18 | "override the mime type to text/html": function(document) {
19 | assert.equal(XMLHttpRequest._last._info.mimeType, "text/html");
20 | }
21 | },
22 |
23 | "on a file that does not exist": {
24 | topic: function(html) {
25 | var callback = this.callback;
26 | html("//does/not/exist.html", function(error, document) {
27 | callback(null, document);
28 | });
29 | },
30 | "invokes the callback with undefined when an error occurs": function(document) {
31 | assert.isUndefined(document);
32 | }
33 | }
34 | }
35 | });
36 |
37 | suite.export(module);
38 |
--------------------------------------------------------------------------------
/src/color/hcl.js:
--------------------------------------------------------------------------------
1 | import "../math/trigonometry";
2 | import "color";
3 | import "lab";
4 | import "rgb";
5 |
6 | d3.hcl = function(h, c, l) {
7 | return arguments.length === 1
8 | ? (h instanceof d3_Hcl ? d3_hcl(h.h, h.c, h.l)
9 | : (h instanceof d3_Lab ? d3_lab_hcl(h.l, h.a, h.b)
10 | : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b)))
11 | : d3_hcl(+h, +c, +l);
12 | };
13 |
14 | function d3_hcl(h, c, l) {
15 | return new d3_Hcl(h, c, l);
16 | }
17 |
18 | function d3_Hcl(h, c, l) {
19 | this.h = h;
20 | this.c = c;
21 | this.l = l;
22 | }
23 |
24 | var d3_hclPrototype = d3_Hcl.prototype = new d3_Color;
25 |
26 | d3_hclPrototype.brighter = function(k) {
27 | return d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)));
28 | };
29 |
30 | d3_hclPrototype.darker = function(k) {
31 | return d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)));
32 | };
33 |
34 | d3_hclPrototype.rgb = function() {
35 | return d3_hcl_lab(this.h, this.c, this.l).rgb();
36 | };
37 |
38 | function d3_hcl_lab(h, c, l) {
39 | if (isNaN(h)) h = 0;
40 | if (isNaN(c)) c = 0;
41 | return d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c);
42 | }
43 |
--------------------------------------------------------------------------------
/test/arrays/entries-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.entries");
6 |
7 | suite.addBatch({
8 | "entries": {
9 | topic: load("arrays/entries").expression("d3.entries"),
10 | "enumerates every entry": function(entries) {
11 | assert.deepEqual(entries({a: 1, b: 2}), [
12 | {key: "a", value: 1},
13 | {key: "b", value: 2}
14 | ]);
15 | },
16 | "includes entries defined on prototypes": function(entries) {
17 | function abc() {
18 | this.a = 1;
19 | this.b = 2;
20 | }
21 | abc.prototype.c = 3;
22 | assert.deepEqual(entries(new abc()), [
23 | {key: "a", value: 1},
24 | {key: "b", value: 2},
25 | {key: "c", value: 3}
26 | ]);
27 | },
28 | "includes null or undefined values": function(entries) {
29 | var v = entries({a: undefined, b: null, c: NaN});
30 | assert.equal(v.length, 3);
31 | assert.deepEqual(v[0], {key: "a", value: undefined});
32 | assert.deepEqual(v[1], {key: "b", value: null});
33 | assert.equal(v[2].key, "c");
34 | assert.isNaN(v[2].value);
35 | }
36 | }
37 | });
38 |
39 | suite.export(module);
40 |
--------------------------------------------------------------------------------
/test/transition/transition-test-size.js:
--------------------------------------------------------------------------------
1 | var assert = require("../assert");
2 |
3 | module.exports = {
4 | "with a single element selected": {
5 | topic: function(d3) {
6 | return d3.select("body").transition();
7 | },
8 | "returns zero for empty subselections": function(body) {
9 | assert.equal(body.select("foo").size(), 0);
10 | },
11 | "returns one for a singleton selection": function(body) {
12 | assert.equal(body.size(), 1);
13 | },
14 | "does not count null nodes": function(body) {
15 | body[0][0] = null;
16 | assert.equal(body.size(), 0);
17 | }
18 | },
19 | "with multiple elements selected": {
20 | topic: function(d3) {
21 | var body = d3.select("body").html(null);
22 | body.append("div").append("span");
23 | body.append("div");
24 | return body.selectAll("div").transition();
25 | },
26 | "returns null for empty selections": function(div) {
27 | assert.equal(div.select("foo").size(), 0);
28 | },
29 | "returns the number of non-null nodes": function(div) {
30 | assert.equal(div.size(), 2);
31 | },
32 | "does not count null nodes": function(div) {
33 | div[0][0] = null;
34 | assert.equal(div.size(), 1);
35 | }
36 | }
37 | };
38 |
--------------------------------------------------------------------------------
/lib/rhill-voronoi/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (C) 2010-2013 Raymond Hill
2 | https://github.com/gorhill/Javascript-Voronoi
3 |
4 | Licensed under The MIT License
5 | http://en.wikipedia.org/wiki/MIT_License
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in
15 | all copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | THE SOFTWARE.
--------------------------------------------------------------------------------
/test/layout/tree-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.layout.tree");
6 |
7 | suite.addBatch({
8 | "tree": {
9 | topic: load("layout/tree").expression("d3.layout.tree"),
10 | "can handle an empty children array": function(tree) {
11 | var t = tree();
12 | assert.deepEqual(t.nodes({children: []}).map(layout), [
13 | {depth: 0, x: 0.5, y: 0}
14 | ]);
15 | assert.deepEqual(t.nodes({children: [
16 | {children: []},
17 | {children: [{}]},
18 | {children: [{}]}
19 | ]}).map(layout), [
20 | {depth: 0, x: .5, y: 0},
21 | {depth: 1, x: .125, y: 0.5},
22 | {depth: 1, x: .375, y: 0.5},
23 | {depth: 2, x: .375, y: 1},
24 | {depth: 1, x: .875, y: 0.5},
25 | {depth: 2, x: .875, y: 1}
26 | ]);
27 | },
28 | "can handle a single node": function(tree) {
29 | var t = tree();
30 | assert.deepEqual(t.nodes({value: 0}).map(layout), [
31 | {depth: 0, x: 0.5, y: 0}
32 | ]);
33 | }
34 | }
35 | });
36 |
37 | function layout(node) {
38 | return {
39 | depth: node.depth,
40 | x: node.x,
41 | y: node.y
42 | };
43 | }
44 |
45 | suite.export(module);
46 |
--------------------------------------------------------------------------------
/src/geo/length.js:
--------------------------------------------------------------------------------
1 | import "../core/noop";
2 | import "../math/abs";
3 | import "../math/trigonometry";
4 | import "geo";
5 | import "stream";
6 |
7 | d3.geo.length = function(object) {
8 | d3_geo_lengthSum = 0;
9 | d3.geo.stream(object, d3_geo_length);
10 | return d3_geo_lengthSum;
11 | };
12 |
13 | var d3_geo_lengthSum;
14 |
15 | var d3_geo_length = {
16 | sphere: d3_noop,
17 | point: d3_noop,
18 | lineStart: d3_geo_lengthLineStart,
19 | lineEnd: d3_noop,
20 | polygonStart: d3_noop,
21 | polygonEnd: d3_noop
22 | };
23 |
24 | function d3_geo_lengthLineStart() {
25 | var λ0, sinφ0, cosφ0;
26 |
27 | d3_geo_length.point = function(λ, φ) {
28 | λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ);
29 | d3_geo_length.point = nextPoint;
30 | };
31 |
32 | d3_geo_length.lineEnd = function() {
33 | d3_geo_length.point = d3_geo_length.lineEnd = d3_noop;
34 | };
35 |
36 | function nextPoint(λ, φ) {
37 | var sinφ = Math.sin(φ *= d3_radians),
38 | cosφ = Math.cos(φ),
39 | t = abs((λ *= d3_radians) - λ0),
40 | cosΔλ = Math.cos(t);
41 | d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ);
42 | λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/interpolate/zoom.js:
--------------------------------------------------------------------------------
1 | import "../math/trigonometry";
2 |
3 | var ρ = Math.SQRT2,
4 | ρ2 = 2,
5 | ρ4 = 4;
6 |
7 | // p0 = [ux0, uy0, w0]
8 | // p1 = [ux1, uy1, w1]
9 | d3.interpolateZoom = function(p0, p1) {
10 | var ux0 = p0[0], uy0 = p0[1], w0 = p0[2],
11 | ux1 = p1[0], uy1 = p1[1], w1 = p1[2];
12 |
13 | var dx = ux1 - ux0,
14 | dy = uy1 - uy0,
15 | d2 = dx * dx + dy * dy,
16 | d1 = Math.sqrt(d2),
17 | b0 = (w1 * w1 - w0 * w0 + ρ4 * d2) / (2 * w0 * ρ2 * d1),
18 | b1 = (w1 * w1 - w0 * w0 - ρ4 * d2) / (2 * w1 * ρ2 * d1),
19 | r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0),
20 | r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1),
21 | dr = r1 - r0,
22 | S = (dr || Math.log(w1 / w0)) / ρ;
23 |
24 | function interpolate(t) {
25 | var s = t * S;
26 | if (dr) {
27 | // General case.
28 | var coshr0 = d3_cosh(r0),
29 | u = w0 / (ρ2 * d1) * (coshr0 * d3_tanh(ρ * s + r0) - d3_sinh(r0));
30 | return [
31 | ux0 + u * dx,
32 | uy0 + u * dy,
33 | w0 * coshr0 / d3_cosh(ρ * s + r0)
34 | ];
35 | }
36 | // Special case for u0 ~= u1.
37 | return [
38 | ux0 + t * dx,
39 | uy0 + t * dy,
40 | w0 * Math.exp(ρ * s)
41 | ];
42 | }
43 |
44 | interpolate.duration = S * 1000;
45 |
46 | return interpolate;
47 | };
48 |
--------------------------------------------------------------------------------
/test/layout/hierarchy-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.layout.hierarchy");
6 |
7 | suite.addBatch({
8 | "hierarchy": {
9 | topic: load("layout/treemap").expression("d3.layout.treemap"), // hierarchy is abstract, so test a subclass
10 | "doesn't overwrite the value of a node that has an empty children array": function(hierarchy) {
11 | var h = hierarchy(),
12 | nodes = h.sticky(true).nodes({value: 1, children: []});
13 | assert.equal(nodes[0].value, 1);
14 | h.nodes(nodes[0]);
15 | assert.equal(nodes[0].value, 1);
16 | },
17 | "a valueless node that has an empty children array gets a value of 0": function(hierarchy) {
18 | var h = hierarchy(),
19 | nodes = h.sticky(true).nodes({children: []});
20 | assert.equal(nodes[0].value, 0);
21 | h.nodes(nodes[0]);
22 | assert.equal(nodes[0].value, 0);
23 | },
24 | "removes the children array for a node that has no children": function(hierarchy) {
25 | var h = hierarchy(),
26 | nodes = h.children(function() { return null; }).nodes({children: [{}]});
27 | assert.equal(nodes[0].value, 0);
28 | assert.isUndefined(nodes[0].children);
29 | }
30 | }
31 | });
32 |
33 | suite.export(module);
34 |
--------------------------------------------------------------------------------
/test/interpolate/rgb-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.interpolateRgb");
6 |
7 | suite.addBatch({
8 | "interpolateRgb": {
9 | topic: load("interpolate/rgb"), // beware instanceof d3_Color
10 | "parses string input": function(d3) {
11 | assert.strictEqual(d3.interpolateRgb("steelblue", "#f00")(.2), "#6b6890");
12 | assert.strictEqual(d3.interpolateRgb("steelblue", "#f00")(.6), "#b53448");
13 | },
14 | "parses d3.rgb input": function(d3) {
15 | assert.strictEqual(d3.interpolateRgb(d3.rgb("steelblue"), "#f00")(.2), "#6b6890");
16 | assert.strictEqual(d3.interpolateRgb("steelblue", d3.rgb(255, 0, 0))(.6), "#b53448");
17 | },
18 | "parses d3.hsl input": function(d3) {
19 | assert.strictEqual(d3.interpolateRgb(d3.hsl("steelblue"), "#f00")(.2), "#6b6890");
20 | assert.strictEqual(d3.interpolateRgb("steelblue", d3.hsl(0, 1, .5))(.6), "#b53448");
21 | },
22 | "interpolates in RGB color space": function(d3) {
23 | assert.strictEqual(d3.interpolateRgb("steelblue", "#f00")(.2), "#6b6890");
24 | },
25 | "outputs an RGB string": function(d3) {
26 | assert.strictEqual(d3.interpolateRgb("steelblue", "#f00")(.2), "#6b6890");
27 | }
28 | }
29 | });
30 |
31 | suite.export(module);
32 |
--------------------------------------------------------------------------------
/test/selection/remove-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("selection.remove");
6 |
7 | suite.addBatch({
8 | "select(body)": {
9 | topic: load("selection/remove").document(),
10 | "removes the matching elements": function(d3) {
11 | var div = d3.select("body").append("div");
12 | div.remove();
13 | assert.domNull(div[0][0].parentNode);
14 | },
15 | "does not remove non-matching elements": function(d3) {
16 | var body = d3.select("body"),
17 | div1 = body.append("div"),
18 | div2 = body.append("div");
19 | div1.remove();
20 | assert.domEqual(div2[0][0].parentNode, body.node());
21 | },
22 | "ignores null nodes": function(d3) {
23 | var div1 = d3.select("body").append("div"),
24 | div2 = div1.selectAll("div").data([0, 1]).enter().append("div"),
25 | node = div2[0][0];
26 | div2[0][0] = null;
27 | div2.remove();
28 | assert.domEqual(node.parentNode, div1.node());
29 | assert.domNull(div2[0][1].parentNode);
30 | },
31 | "returns the current selection": function(d3) {
32 | var div = d3.select("body").append("div");
33 | assert.isTrue(div.remove() === div);
34 | }
35 | }
36 | });
37 |
38 | suite.export(module);
39 |
--------------------------------------------------------------------------------
/src/event/mouse.js:
--------------------------------------------------------------------------------
1 | import "../core/document";
2 |
3 | d3.mouse = function(container) {
4 | return d3_mousePoint(container, d3_eventSource());
5 | };
6 |
7 | // https://bugs.webkit.org/show_bug.cgi?id=44083
8 | var d3_mouse_bug44083 = /WebKit/.test(d3_window.navigator.userAgent) ? -1 : 0;
9 |
10 | function d3_mousePoint(container, e) {
11 | if (e.changedTouches) e = e.changedTouches[0];
12 | var svg = container.ownerSVGElement || container;
13 | if (svg.createSVGPoint) {
14 | var point = svg.createSVGPoint();
15 | if (d3_mouse_bug44083 < 0 && (d3_window.scrollX || d3_window.scrollY)) {
16 | svg = d3.select("body").append("svg").style({
17 | position: "absolute",
18 | top: 0,
19 | left: 0,
20 | margin: 0,
21 | padding: 0,
22 | border: "none"
23 | }, "important");
24 | var ctm = svg[0][0].getScreenCTM();
25 | d3_mouse_bug44083 = !(ctm.f || ctm.e);
26 | svg.remove();
27 | }
28 | if (d3_mouse_bug44083) point.x = e.pageX, point.y = e.pageY;
29 | else point.x = e.clientX, point.y = e.clientY;
30 | point = point.matrixTransform(container.getScreenCTM().inverse());
31 | return [point.x, point.y];
32 | }
33 | var rect = container.getBoundingClientRect();
34 | return [e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop];
35 | };
36 |
--------------------------------------------------------------------------------
/test/interpolate/lab-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.interpolateLab");
6 |
7 | suite.addBatch({
8 | "interpolateLab": {
9 | topic: load("interpolate/lab"), // beware instanceof d3_Color
10 | "parses string input": function(d3) {
11 | assert.strictEqual(d3.interpolateLab("steelblue", "#f00")(.2), "#8a7793");
12 | assert.strictEqual(d3.interpolateLab("steelblue", "#f00")(.6), "#cf5952");
13 | },
14 | "parses d3.hsl input": function(d3) {
15 | assert.strictEqual(d3.interpolateLab(d3.hsl("steelblue"), "#f00")(.2), "#8a7793");
16 | assert.strictEqual(d3.interpolateLab("steelblue", d3.hsl(0, 1, .5))(.6), "#cf5952");
17 | },
18 | "parses d3.rgb input": function(d3) {
19 | assert.strictEqual(d3.interpolateLab(d3.rgb("steelblue"), "#f00")(.2), "#8a7793");
20 | assert.strictEqual(d3.interpolateLab("steelblue", d3.rgb(255, 0, 0))(.6), "#cf5952");
21 | },
22 | "interpolates in HSL color space": function(d3) {
23 | assert.strictEqual(d3.interpolateLab("steelblue", "#f00")(.2), "#8a7793");
24 | },
25 | "returns an instanceof d3.lab": function(d3) {
26 | assert.strictEqual(d3.interpolateLab("steelblue", "#f00")(.2), "#8a7793");
27 | }
28 | }
29 | });
30 |
31 | suite.export(module);
32 |
--------------------------------------------------------------------------------
/src/geo/mercator.js:
--------------------------------------------------------------------------------
1 | import "../math/trigonometry";
2 | import "geo";
3 | import "projection";
4 |
5 | function d3_geo_mercator(λ, φ) {
6 | return [λ, Math.log(Math.tan(π / 4 + φ / 2))];
7 | }
8 |
9 | d3_geo_mercator.invert = function(x, y) {
10 | return [x, 2 * Math.atan(Math.exp(y)) - halfπ];
11 | };
12 |
13 | function d3_geo_mercatorProjection(project) {
14 | var m = d3_geo_projection(project),
15 | scale = m.scale,
16 | translate = m.translate,
17 | clipExtent = m.clipExtent,
18 | clipAuto;
19 |
20 | m.scale = function() {
21 | var v = scale.apply(m, arguments);
22 | return v === m ? (clipAuto ? m.clipExtent(null) : m) : v;
23 | };
24 |
25 | m.translate = function() {
26 | var v = translate.apply(m, arguments);
27 | return v === m ? (clipAuto ? m.clipExtent(null) : m) : v;
28 | };
29 |
30 | m.clipExtent = function(_) {
31 | var v = clipExtent.apply(m, arguments);
32 | if (v === m) {
33 | if (clipAuto = _ == null) {
34 | var k = π * scale(), t = translate();
35 | clipExtent([[t[0] - k, t[1] - k], [t[0] + k, t[1] + k]]);
36 | }
37 | } else if (clipAuto) {
38 | v = null;
39 | }
40 | return v;
41 | };
42 |
43 | return m.clipExtent(null);
44 | }
45 |
46 | (d3.geo.mercator = function() {
47 | return d3_geo_mercatorProjection(d3_geo_mercator);
48 | }).raw = d3_geo_mercator;
49 |
--------------------------------------------------------------------------------
/src/layout/partition.js:
--------------------------------------------------------------------------------
1 | import "layout";
2 | import "hierarchy";
3 |
4 | d3.layout.partition = function() {
5 | var hierarchy = d3.layout.hierarchy(),
6 | size = [1, 1]; // width, height
7 |
8 | function position(node, x, dx, dy) {
9 | var children = node.children;
10 | node.x = x;
11 | node.y = node.depth * dy;
12 | node.dx = dx;
13 | node.dy = dy;
14 | if (children && (n = children.length)) {
15 | var i = -1,
16 | n,
17 | c,
18 | d;
19 | dx = node.value ? dx / node.value : 0;
20 | while (++i < n) {
21 | position(c = children[i], x, d = c.value * dx, dy);
22 | x += d;
23 | }
24 | }
25 | }
26 |
27 | function depth(node) {
28 | var children = node.children,
29 | d = 0;
30 | if (children && (n = children.length)) {
31 | var i = -1,
32 | n;
33 | while (++i < n) d = Math.max(d, depth(children[i]));
34 | }
35 | return 1 + d;
36 | }
37 |
38 | function partition(d, i) {
39 | var nodes = hierarchy.call(this, d, i);
40 | position(nodes[0], 0, size[0], size[1] / depth(nodes[0]));
41 | return nodes;
42 | }
43 |
44 | partition.size = function(x) {
45 | if (!arguments.length) return size;
46 | size = x;
47 | return partition;
48 | };
49 |
50 | return d3_layout_hierarchyRebind(partition, hierarchy);
51 | };
52 |
--------------------------------------------------------------------------------
/test/selection/interrupt-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("selection.interrupt");
6 |
7 | suite.addBatch({
8 | "interrupt": {
9 | topic: load("transition/transition").document(),
10 | "returns the current selection": function(d3) {
11 | var selection = d3.select("body").append("div");
12 | assert.strictEqual(selection.interrupt(), selection);
13 | },
14 | "increments the active transition": function(d3) {
15 | var selection = d3.select("body").append("div"),
16 | transition = selection.transition();
17 | assert.equal(selection.node().__transition__.active, 0); // transition hasn’t yet started
18 | d3.timer.flush();
19 | assert.equal(selection.node().__transition__.active, transition.id); // transition has started
20 | selection.interrupt();
21 | assert.equal(selection.node().__transition__.active, transition.id + 1); // transition was interrupted
22 | },
23 | "does nothing if there is no active transition": function(d3) {
24 | var selection = d3.select("body").append("div");
25 | assert.isUndefined(selection.node().__transition__); // no transition scheduled
26 | selection.interrupt();
27 | assert.isUndefined(selection.node().__transition__); // still no transition scheduled
28 | }
29 | }
30 | });
31 |
32 | suite.export(module);
33 |
--------------------------------------------------------------------------------
/src/scale/quantile.js:
--------------------------------------------------------------------------------
1 | import "../arrays/ascending";
2 | import "../arrays/bisect";
3 | import "../arrays/quantile";
4 | import "scale";
5 |
6 | d3.scale.quantile = function() {
7 | return d3_scale_quantile([], []);
8 | };
9 |
10 | function d3_scale_quantile(domain, range) {
11 | var thresholds;
12 |
13 | function rescale() {
14 | var k = 0,
15 | q = range.length;
16 | thresholds = [];
17 | while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q);
18 | return scale;
19 | }
20 |
21 | function scale(x) {
22 | if (!isNaN(x = +x)) return range[d3.bisect(thresholds, x)];
23 | }
24 |
25 | scale.domain = function(x) {
26 | if (!arguments.length) return domain;
27 | domain = x.filter(function(d) { return !isNaN(d); }).sort(d3.ascending);
28 | return rescale();
29 | };
30 |
31 | scale.range = function(x) {
32 | if (!arguments.length) return range;
33 | range = x;
34 | return rescale();
35 | };
36 |
37 | scale.quantiles = function() {
38 | return thresholds;
39 | };
40 |
41 | scale.invertExtent = function(y) {
42 | y = range.indexOf(y);
43 | return y < 0 ? [NaN, NaN] : [
44 | y > 0 ? thresholds[y - 1] : domain[0],
45 | y < thresholds.length ? thresholds[y] : domain[domain.length - 1]
46 | ];
47 | };
48 |
49 | scale.copy = function() {
50 | return d3_scale_quantile(domain, range); // copy on write!
51 | };
52 |
53 | return rescale();
54 | }
55 |
--------------------------------------------------------------------------------
/test/layout/cluster-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.layout.cluster");
6 |
7 | suite.addBatch({
8 | "cluster": {
9 | topic: load("layout/cluster").expression("d3.layout.cluster"),
10 | "can handle an empty children array": function(cluster) {
11 | var c = cluster();
12 | assert.deepEqual(c.nodes({value: 1, children: [{value: 1, children: []}, {value: 1}]}).map(layout), [
13 | {value: 1, depth: 0, x: 0.5, y: 0},
14 | {value: 1, depth: 1, x: 0.25, y: 1},
15 | {value: 1, depth: 1, x: 0.75, y: 1}
16 | ]);
17 | },
18 | "can handle zero-valued nodes": function(cluster) {
19 | var c = cluster();
20 | assert.deepEqual(c.nodes({value: 0, children: [{value: 0}, {value: 1}]}).map(layout), [
21 | {value: 0, depth: 0, x: 0.5, y: 0},
22 | {value: 0, depth: 1, x: 0.25, y: 1},
23 | {value: 1, depth: 1, x: 0.75, y: 1}
24 | ]);
25 | },
26 | "can handle a single node": function(cluster) {
27 | var c = cluster();
28 | assert.deepEqual(c.nodes({value: 0}).map(layout), [
29 | {value: 0, depth: 0, x: 0.5, y: 0}
30 | ]);
31 | }
32 | }
33 | });
34 |
35 | function layout(node) {
36 | return {
37 | value: node.value,
38 | depth: node.depth,
39 | x: node.x,
40 | y: node.y
41 | };
42 | }
43 |
44 | suite.export(module);
45 |
--------------------------------------------------------------------------------
/test/transition/transition-test-node.js:
--------------------------------------------------------------------------------
1 | var assert = require("../assert");
2 |
3 | module.exports = {
4 | "with a single element selected": {
5 | topic: function(d3) {
6 | return d3.select("body").transition();
7 | },
8 | "returns null for empty subselections": function(body) {
9 | assert.isNull(body.select("foo").node());
10 | },
11 | "returns the selected element": function(body) {
12 | assert.equal(body.node().tagName, "BODY");
13 | },
14 | "returns null if no elements are slected": function(body) {
15 | body[0][0] = null;
16 | assert.isNull(body.node());
17 | }
18 | },
19 | "with multiple elements selected": {
20 | topic: function(d3) {
21 | var body = d3.select("body").html(null);
22 | body.append("div").attr("class", "first").append("span");
23 | body.append("div").attr("class", "second");
24 | return body.selectAll("div").transition();
25 | },
26 | "returns null for empty subselections": function(div) {
27 | assert.isNull(div.select("foo").node());
28 | },
29 | "returns the first selected element": function(div) {
30 | assert.equal(div.node().className, "first");
31 | assert.equal(div.node().tagName, "DIV");
32 | },
33 | "does not count null nodes": function(div) {
34 | div[0][0] = null;
35 | assert.equal(div.node().className, "second");
36 | assert.equal(div.node().tagName, "DIV");
37 | }
38 | }
39 | };
40 |
--------------------------------------------------------------------------------
/test/transition/transition-test-time.js:
--------------------------------------------------------------------------------
1 | var assert = require("../assert");
2 |
3 | module.exports = {
4 | topic: function(d3) {
5 | return d3; // bug in vows where topic is not propagated automatically
6 | },
7 | "on a new transition": {
8 | topic: function(d3) {
9 | return d3.select("body").append("div").transition();
10 | },
11 | "is approximately equal to now": function(transition) {
12 | var time = transition[0][0].__transition__[transition.id].time;
13 | assert.inDelta(time, Date.now(), 20);
14 | }
15 | },
16 | "increases monotonically across transitions": function(d3) {
17 | var now = Date.now, then = Date.now();
18 | try {
19 | Date.now = function() { return ++then; };
20 | var t0 = d3.select("body").append("div").transition(),
21 | t1 = d3.select("body").append("div").transition();
22 | assert.isTrue(t1[0][0].__transition__[t1.id].time > t0[0][0].__transition__[t0.id].time);
23 | } finally {
24 | Date.now = now;
25 | }
26 | },
27 | "is inherited by subtransitions": function(d3) {
28 | var now = Date.now, then = Date.now();
29 | try {
30 | Date.now = function() { return ++then; };
31 | var t0 = d3.select("body").append("div").transition(),
32 | t1 = t0.transition();
33 | assert.equal(t1[0][0].__transition__[t1.id].time, t0[0][0].__transition__[t0.id].time);
34 | } finally {
35 | Date.now = now;
36 | }
37 | }
38 | };
39 |
--------------------------------------------------------------------------------
/test/event/touch-test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
22 |
23 |
24 |
62 |
--------------------------------------------------------------------------------
/test/xhr/text-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.text");
6 |
7 | suite.addBatch({
8 | "text": {
9 | topic: load("xhr/text").expression("d3.text").document(),
10 |
11 | "on a sample file": {
12 | topic: function(text) {
13 | text("test/data/sample.txt", this.callback);
14 | },
15 | "invokes the callback with the loaded text": function(text) {
16 | assert.equal(text, "Hello, world!\n");
17 | },
18 | "does not override the mime type by default": function(text) {
19 | assert.isUndefined(XMLHttpRequest._last._info.mimeType);
20 | }
21 | },
22 |
23 | "with a custom mime type": {
24 | topic: function(text) {
25 | text("test/data/sample.txt", "text/plain+sample", this.callback);
26 | },
27 | "observes the optional mime type": function(text) {
28 | assert.equal(XMLHttpRequest._last._info.mimeType, "text/plain+sample");
29 | }
30 | },
31 |
32 | "on a file that does not exist": {
33 | topic: function(text) {
34 | var callback = this.callback;
35 | text("//does/not/exist.txt", function(error, text) {
36 | callback(null, text);
37 | });
38 | },
39 | "invokes the callback with undefined when an error occurs": function(text) {
40 | assert.isUndefined(text);
41 | }
42 | }
43 | }
44 | });
45 |
46 | suite.export(module);
47 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "d3",
3 | "version": "3.4.3",
4 | "description": "A small, free JavaScript library for manipulating documents based on data.",
5 | "keywords": [
6 | "dom",
7 | "w3c",
8 | "visualization",
9 | "svg",
10 | "animation",
11 | "canvas"
12 | ],
13 | "homepage": "http://d3js.org",
14 | "author": {
15 | "name": "Mike Bostock",
16 | "url": "http://bost.ocks.org/mike"
17 | },
18 | "contributors": [
19 | {
20 | "name": "Jason Davies",
21 | "url": "http://jasondavies.com"
22 | }
23 | ],
24 | "repository": {
25 | "type": "git",
26 | "url": "https://github.com/mbostock/d3.git"
27 | },
28 | "main": "index.js",
29 | "browserify": "d3.js",
30 | "jspm": {
31 | "main": "d3.js",
32 | "shim": {
33 | "d3": {
34 | "exports": "d3"
35 | }
36 | },
37 | "files": [
38 | "d3.js"
39 | ],
40 | "buildConfig": {
41 | "uglify": true
42 | }
43 | },
44 | "jam": {
45 | "main": "d3.js",
46 | "shim": {
47 | "exports": "d3"
48 | }
49 | },
50 | "dependencies": {
51 | "jsdom": "0.5.7"
52 | },
53 | "devDependencies": {
54 | "smash": "~0.0.12",
55 | "uglify-js": "2.4.0",
56 | "vows": "0.7.0",
57 | "seedrandom": "2.3.1"
58 | },
59 | "scripts": {
60 | "test": "vows; echo"
61 | },
62 | "licenses": [
63 | {
64 | "type": "BSD",
65 | "url": "https://github.com/mbostock/d3/blob/master/LICENSE"
66 | }
67 | ]
68 | }
69 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2010-2014, Michael Bostock
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | * The name Michael Bostock may not be used to endorse or promote products
15 | derived from this software without specific prior written permission.
16 |
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
25 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 |
--------------------------------------------------------------------------------
/lib/science/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2011, Jason Davies
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | * The name Jason Davies may not be used to endorse or promote products
15 | derived from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL JASON DAVIES BE LIABLE FOR ANY DIRECT, INDIRECT,
21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 |
--------------------------------------------------------------------------------
/test/selection/selection-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.selection");
6 |
7 | suite.addBatch({
8 | "selection": {
9 | topic: load("selection/selection").document(),
10 | "selects the document element": function(d3) {
11 | var selection = d3.selection();
12 | assert.equal(selection.length, 1);
13 | assert.equal(selection[0].length, 1);
14 | assert.equal(selection[0][0].nodeType, 1);
15 | assert.equal(selection[0][0].tagName, "HTML");
16 | },
17 | "the parentNode is also the document element": function(d3) {
18 | var parentNode = d3.selection()[0].parentNode;
19 | assert.equal(parentNode.nodeType, 1);
20 | assert.equal(parentNode.tagName, "HTML");
21 | },
22 | "is an instanceof d3.selection": function(d3) {
23 | assert.instanceOf(d3.selection(), d3.selection);
24 | },
25 | "subselections are also instanceof d3.selection": function(d3) {
26 | assert.instanceOf(d3.selection().select("body"), d3.selection);
27 | assert.instanceOf(d3.selection().selectAll("body"), d3.selection);
28 | },
29 | "selection prototype can be extended": function(d3) {
30 | d3.selection.prototype.foo = function(v) { return this.attr("foo", v); };
31 | var body = d3.selection().select("body").foo(42);
32 | assert.equal(body.attr("foo"), "42");
33 | delete d3.selection.prototype.foo;
34 | }
35 | }
36 | });
37 |
38 | suite.export(module);
39 |
--------------------------------------------------------------------------------
/src/scale/pow.js:
--------------------------------------------------------------------------------
1 | import "linear";
2 | import "nice";
3 | import "scale";
4 |
5 | d3.scale.pow = function() {
6 | return d3_scale_pow(d3.scale.linear(), 1, [0, 1]);
7 | };
8 |
9 | function d3_scale_pow(linear, exponent, domain) {
10 | var powp = d3_scale_powPow(exponent),
11 | powb = d3_scale_powPow(1 / exponent);
12 |
13 | function scale(x) {
14 | return linear(powp(x));
15 | }
16 |
17 | scale.invert = function(x) {
18 | return powb(linear.invert(x));
19 | };
20 |
21 | scale.domain = function(x) {
22 | if (!arguments.length) return domain;
23 | linear.domain((domain = x.map(Number)).map(powp));
24 | return scale;
25 | };
26 |
27 | scale.ticks = function(m) {
28 | return d3_scale_linearTicks(domain, m);
29 | };
30 |
31 | scale.tickFormat = function(m, format) {
32 | return d3_scale_linearTickFormat(domain, m, format);
33 | };
34 |
35 | scale.nice = function(m) {
36 | return scale.domain(d3_scale_linearNice(domain, m));
37 | };
38 |
39 | scale.exponent = function(x) {
40 | if (!arguments.length) return exponent;
41 | powp = d3_scale_powPow(exponent = x);
42 | powb = d3_scale_powPow(1 / exponent);
43 | linear.domain(domain.map(powp));
44 | return scale;
45 | };
46 |
47 | scale.copy = function() {
48 | return d3_scale_pow(linear.copy(), exponent, domain);
49 | };
50 |
51 | return d3_scale_linearRebind(scale, linear);
52 | }
53 |
54 | function d3_scale_powPow(e) {
55 | return function(x) {
56 | return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e);
57 | };
58 | }
59 |
--------------------------------------------------------------------------------
/src/selection/property.js:
--------------------------------------------------------------------------------
1 | import "selection";
2 |
3 | d3_selectionPrototype.property = function(name, value) {
4 | if (arguments.length < 2) {
5 |
6 | // For property(string), return the property value for the first node.
7 | if (typeof name === "string") return this.node()[name];
8 |
9 | // For property(object), the object specifies the names and values of the
10 | // properties to set or remove. The values may be functions that are
11 | // evaluated for each element.
12 | for (value in name) this.each(d3_selection_property(value, name[value]));
13 | return this;
14 | }
15 |
16 | // Otherwise, both a name and a value are specified, and are handled as below.
17 | return this.each(d3_selection_property(name, value));
18 | };
19 |
20 | function d3_selection_property(name, value) {
21 |
22 | // For property(name, null), remove the property with the specified name.
23 | function propertyNull() {
24 | delete this[name];
25 | }
26 |
27 | // For property(name, string), set the property with the specified name.
28 | function propertyConstant() {
29 | this[name] = value;
30 | }
31 |
32 | // For property(name, function), evaluate the function for each element, and
33 | // set or remove the property as appropriate.
34 | function propertyFunction() {
35 | var x = value.apply(this, arguments);
36 | if (x == null) delete this[name];
37 | else this[name] = x;
38 | }
39 |
40 | return value == null
41 | ? propertyNull : (typeof value === "function"
42 | ? propertyFunction : propertyConstant);
43 | }
44 |
--------------------------------------------------------------------------------
/lib/polymaps/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2010, SimpleGeo and Stamen Design
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | * Neither the name of SimpleGeo nor the names of its contributors may be used
15 | to endorse or promote products derived from this software without specific
16 | prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | DISCLAIMED. IN NO EVENT SHALL SIMPLEGEO 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
26 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
29 |
--------------------------------------------------------------------------------
/test/xhr/xml-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.xml");
6 |
7 | suite.addBatch({
8 | "xml": {
9 | topic: load("xhr/xml").expression("d3.xml").document(),
10 |
11 | "on a sample file": {
12 | topic: function(xml) {
13 | xml("test/data/sample.xml", this.callback);
14 | },
15 | "invokes the callback with the loaded xml": function(xml) {
16 | assert.deepEqual(xml, {_xml: "\n\n \n\n"});
17 | },
18 | "does not override the mime type by default": function(xml) {
19 | assert.isUndefined(XMLHttpRequest._last._info.mimeType);
20 | }
21 | },
22 |
23 | "with a custom mime type": {
24 | topic: function(xml) {
25 | xml("test/data/sample.txt", "application/xml+sample", this.callback);
26 | },
27 | "observes the optional mime type": function(xml) {
28 | assert.equal(XMLHttpRequest._last._info.mimeType, "application/xml+sample");
29 | }
30 | },
31 |
32 | "on a file that does not exist": {
33 | topic: function(xml) {
34 | var callback = this.callback;
35 | xml("//does/not/exist.xml", function(error, xml) {
36 | callback(null, xml);
37 | });
38 | },
39 | "invokes the callback with undefined when an error occurs": function(xml) {
40 | assert.isUndefined(xml);
41 | }
42 | }
43 | }
44 | });
45 |
46 | suite.export(module);
47 |
--------------------------------------------------------------------------------
/test/geo/albers-usa-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert"),
4 | projectionTestSuite = require("./projection-test-suite");
5 |
6 | var suite = vows.describe("d3.geo.albersUsa");
7 |
8 | suite.addBatch({
9 | "albersUsa": {
10 | topic: load("geo/albers-usa").expression("d3.geo.albersUsa"),
11 | "default": projectionTestSuite({
12 | topic: function(projection) { return projection(); },
13 | "has the scale 1070": function(p) {
14 | assert.inDelta(p.scale(), 1070, 1e-6);
15 | }
16 | }, {
17 | "Washington, DC": [[-120.50000000, 47.50000000], [ 181.00023857, 45.12748866]],
18 | "San Francisco, CA": [[-122.42000000, 37.78000000], [ 107.44485839, 214.04820561]],
19 | "Juneau, AK": [[-134.22000000, 58.43000000], [ 224.79015007, 455.65860760]],
20 | "Honolulu, HI": [[-157.82000000, 21.30000000], [ 299.14918225, 451.11762634]]
21 | }),
22 | "translated to 0,0 and at scale 1": projectionTestSuite({
23 | topic: function(projection) { return projection().translate([0, 0]).scale(1); }
24 | }, {
25 | "Washington, DC": [[-120.50000000, 47.50000000], [ -0.27943903, -0.19146964]],
26 | "San Francisco, CA": [[-122.42000000, 37.78000000], [ -0.34818238, -0.03359981]],
27 | "Juneau, AK": [[-134.22000000, 58.43000000], [ -0.23851388, 0.19220431]],
28 | "Honolulu, HI": [[-157.82000000, 21.30000000], [ -0.16901946, 0.18796040]]
29 | })
30 | }
31 | });
32 |
33 | suite.export(module);
34 |
--------------------------------------------------------------------------------
/lib/protovis/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2010, Stanford Visualization Group
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | * Neither the name of Stanford University nor the names of its contributors
15 | may be used to endorse or promote products derived from this software
16 | without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
--------------------------------------------------------------------------------
/src/geo/path-buffer.js:
--------------------------------------------------------------------------------
1 | function d3_geo_pathBuffer() {
2 | var pointCircle = d3_geo_pathBufferCircle(4.5),
3 | buffer = [];
4 |
5 | var stream = {
6 | point: point,
7 |
8 | // While inside a line, override point to moveTo then lineTo.
9 | lineStart: function() { stream.point = pointLineStart; },
10 | lineEnd: lineEnd,
11 |
12 | // While inside a polygon, override lineEnd to closePath.
13 | polygonStart: function() { stream.lineEnd = lineEndPolygon; },
14 | polygonEnd: function() { stream.lineEnd = lineEnd; stream.point = point; },
15 |
16 | pointRadius: function(_) {
17 | pointCircle = d3_geo_pathBufferCircle(_);
18 | return stream;
19 | },
20 |
21 | result: function() {
22 | if (buffer.length) {
23 | var result = buffer.join("");
24 | buffer = [];
25 | return result;
26 | }
27 | }
28 | };
29 |
30 | function point(x, y) {
31 | buffer.push("M", x, ",", y, pointCircle);
32 | }
33 |
34 | function pointLineStart(x, y) {
35 | buffer.push("M", x, ",", y);
36 | stream.point = pointLine;
37 | }
38 |
39 | function pointLine(x, y) {
40 | buffer.push("L", x, ",", y);
41 | }
42 |
43 | function lineEnd() {
44 | stream.point = point;
45 | }
46 |
47 | function lineEndPolygon() {
48 | buffer.push("Z");
49 | }
50 |
51 | return stream;
52 | }
53 |
54 | function d3_geo_pathBufferCircle(radius) {
55 | return "m0," + radius
56 | + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius
57 | + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius
58 | + "z";
59 | }
60 |
--------------------------------------------------------------------------------
/test/selection/size-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("selection.size");
6 |
7 | suite.addBatch({
8 | "select(body)": {
9 | topic: load("selection/size").document(),
10 | "on a simple page": {
11 | topic: function(d3) {
12 | return d3.select("body");
13 | },
14 | "returns zero for empty selections": function(body) {
15 | assert.equal(body.select("foo").size(), 0);
16 | },
17 | "returns one for a singleton selection": function(body) {
18 | assert.equal(body.size(), 1);
19 | },
20 | "does not count null nodes": function(body) {
21 | body[0][0] = null;
22 | assert.equal(body.size(), 0);
23 | }
24 | }
25 | }
26 | });
27 |
28 | suite.addBatch({
29 | "selectAll(div)": {
30 | topic: load("selection/size").document(),
31 | "on a simple page": {
32 | topic: function(d3) {
33 | var body = d3.select("body");
34 | body.append("div").append("span");
35 | body.append("div");
36 | return body.selectAll("div");
37 | },
38 | "returns null for empty selections": function(div) {
39 | assert.equal(div.select("foo").size(), 0);
40 | },
41 | "returns the number of non-null nodes": function(div) {
42 | assert.equal(div.size(), 2);
43 | },
44 | "does not count null nodes": function(div) {
45 | div[0][0] = null;
46 | assert.equal(div.size(), 1);
47 | }
48 | }
49 | }
50 | });
51 |
52 | suite.export(module);
53 |
--------------------------------------------------------------------------------
/test/format/requote-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.requote");
6 |
7 | suite.addBatch({
8 | "requote": {
9 | topic: load("format/requote").expression("d3.requote"),
10 | "quotes backslashes": function(requote) {
11 | assert.equal(requote("\\"), "\\\\");
12 | },
13 | "quotes carets": function(requote) {
14 | assert.equal(requote("^"), "\\^");
15 | },
16 | "quotes dollar signs": function(requote) {
17 | assert.equal(requote("$"), "\\$");
18 | },
19 | "quotes stars": function(requote) {
20 | assert.equal(requote("*"), "\\*");
21 | },
22 | "quotes plusses": function(requote) {
23 | assert.equal(requote("+"), "\\+");
24 | },
25 | "quotes question marks": function(requote) {
26 | assert.equal(requote("?"), "\\?");
27 | },
28 | "quotes periods": function(requote) {
29 | assert.equal(requote("."), "\\.");
30 | },
31 | "quotes parentheses": function(requote) {
32 | assert.equal(requote("("), "\\(");
33 | assert.equal(requote(")"), "\\)");
34 | },
35 | "quotes pipes": function(requote) {
36 | assert.equal(requote("|"), "\\|");
37 | },
38 | "quotes curly braces": function(requote) {
39 | assert.equal(requote("{"), "\\{");
40 | assert.equal(requote("}"), "\\}");
41 | },
42 | "quotes square brackets": function(requote) {
43 | assert.equal(requote("["), "\\[");
44 | assert.equal(requote("]"), "\\]");
45 | }
46 | }
47 | });
48 |
49 | suite.export(module);
50 |
--------------------------------------------------------------------------------
/test/arrays/mean-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.mean");
6 |
7 | suite.addBatch({
8 | "mean": {
9 | topic: load("arrays/mean").expression("d3.mean"),
10 | "returns the mean value for numbers": function(mean) {
11 | assert.equal(mean([1]), 1);
12 | assert.equal(mean([5, 1, 2, 3, 4]), 3);
13 | assert.equal(mean([20, 3]), 11.5);
14 | assert.equal(mean([3, 20]), 11.5);
15 | },
16 | "ignores null, undefined and NaN": function(mean) {
17 | assert.equal(mean([NaN, 1, 2, 3, 4, 5]), 3);
18 | assert.equal(mean([1, 2, 3, 4, 5, NaN]), 3);
19 | assert.equal(mean([10, null, 3, undefined, 5, NaN]), 6);
20 | },
21 | "can handle large numbers without overflowing": function(mean) {
22 | assert.equal(mean([Number.MAX_VALUE, Number.MAX_VALUE]), Number.MAX_VALUE);
23 | assert.equal(mean([-Number.MAX_VALUE, -Number.MAX_VALUE]), -Number.MAX_VALUE);
24 | },
25 | "returns undefined for empty array": function(mean) {
26 | assert.isUndefined(mean([]));
27 | assert.isUndefined(mean([null]));
28 | assert.isUndefined(mean([undefined]));
29 | assert.isUndefined(mean([NaN]));
30 | assert.isUndefined(mean([NaN, NaN]));
31 | },
32 | "applies the optional accessor function": function(mean) {
33 | assert.equal(mean([[1, 2, 3, 4, 5], [2, 4, 6, 8, 10]], function(d) { return mean(d); }), 4.5);
34 | assert.equal(mean([1, 2, 3, 4, 5], function(d, i) { return i; }), 2);
35 | }
36 | }
37 | });
38 |
39 | suite.export(module);
40 |
--------------------------------------------------------------------------------
/src/geom/clip-line.js:
--------------------------------------------------------------------------------
1 | import "../math/trigonometry";
2 |
3 | // Liang–Barsky line clipping.
4 | function d3_geom_clipLine(x0, y0, x1, y1) {
5 | return function(line) {
6 | var a = line.a,
7 | b = line.b,
8 | ax = a.x,
9 | ay = a.y,
10 | bx = b.x,
11 | by = b.y,
12 | t0 = 0,
13 | t1 = 1,
14 | dx = bx - ax,
15 | dy = by - ay,
16 | r;
17 |
18 | r = x0 - ax;
19 | if (!dx && r > 0) return;
20 | r /= dx;
21 | if (dx < 0) {
22 | if (r < t0) return;
23 | if (r < t1) t1 = r;
24 | } else if (dx > 0) {
25 | if (r > t1) return;
26 | if (r > t0) t0 = r;
27 | }
28 |
29 | r = x1 - ax;
30 | if (!dx && r < 0) return;
31 | r /= dx;
32 | if (dx < 0) {
33 | if (r > t1) return;
34 | if (r > t0) t0 = r;
35 | } else if (dx > 0) {
36 | if (r < t0) return;
37 | if (r < t1) t1 = r;
38 | }
39 |
40 | r = y0 - ay;
41 | if (!dy && r > 0) return;
42 | r /= dy;
43 | if (dy < 0) {
44 | if (r < t0) return;
45 | if (r < t1) t1 = r;
46 | } else if (dy > 0) {
47 | if (r > t1) return;
48 | if (r > t0) t0 = r;
49 | }
50 |
51 | r = y1 - ay;
52 | if (!dy && r < 0) return;
53 | r /= dy;
54 | if (dy < 0) {
55 | if (r > t1) return;
56 | if (r > t0) t0 = r;
57 | } else if (dy > 0) {
58 | if (r < t0) return;
59 | if (r < t1) t1 = r;
60 | }
61 |
62 | if (t0 > 0) line.a = {x: ax + t0 * dx, y: ay + t0 * dy};
63 | if (t1 < 1) line.b = {x: ax + t1 * dx, y: ay + t1 * dy};
64 | return line;
65 | };
66 | }
67 |
--------------------------------------------------------------------------------
/test/arrays/ascending-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.ascending");
6 |
7 | suite.addBatch({
8 | "d3.ascending": {
9 | topic: load("arrays/ascending").expression("d3.ascending"),
10 | "numbers": {
11 | "returns a negative number if a < b": function(ascending) {
12 | assert.isTrue(ascending(0, 1) < 0);
13 | },
14 | "returns a positive number if a > b": function(ascending) {
15 | assert.isTrue(ascending(1, 0) > 0);
16 | },
17 | "returns zero if a == b": function(ascending) {
18 | assert.equal(ascending(0, 0), 0);
19 | },
20 | "returns NaN if a or b is undefined": function(ascending) {
21 | assert.isNaN(ascending(0, undefined));
22 | assert.isNaN(ascending(undefined, 0));
23 | assert.isNaN(ascending(undefined, undefined));
24 | },
25 | "returns NaN if a or b is NaN": function(ascending) {
26 | assert.isNaN(ascending(0, NaN));
27 | assert.isNaN(ascending(NaN, 0));
28 | assert.isNaN(ascending(NaN, NaN));
29 | }
30 | },
31 | "strings": {
32 | "returns a negative number if a < b": function(ascending) {
33 | assert.isTrue(ascending("a", "b") < 0);
34 | },
35 | "returns a positive number if a > b": function(ascending) {
36 | assert.isTrue(ascending("b", "a") > 0);
37 | },
38 | "returns zero if a == b": function(ascending) {
39 | assert.equal(ascending("a", "a"), 0);
40 | }
41 | }
42 | }
43 | });
44 |
45 | suite.export(module);
46 |
--------------------------------------------------------------------------------
/test/layout/partition-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.layout.partition");
6 |
7 | suite.addBatch({
8 | "partition": {
9 | topic: load("layout/partition").expression("d3.layout.partition"),
10 | "ignores zero values": function(partition) {
11 | var p = partition().size([3, 3]);
12 | assert.deepEqual(p.nodes({children: [{value: 1}, {value: 0}, {value: 2}, {children: [{value: 0}, {value: 0}]}]}).map(metadata), [
13 | {x: 0, y: 0, dx: 3, dy: 1},
14 | {x: 2, y: 1, dx: 1, dy: 1},
15 | {x: 3, y: 1, dx: 0, dy: 1},
16 | {x: 0, y: 1, dx: 2, dy: 1},
17 | {x: 3, y: 1, dx: 0, dy: 1},
18 | {x: 3, y: 2, dx: 0, dy: 1},
19 | {x: 3, y: 2, dx: 0, dy: 1}
20 | ]);
21 | },
22 | "can handle an empty children array": function(partition) {
23 | var p = partition();
24 | assert.deepEqual(p.nodes({children: []}).map(metadata), [
25 | {x: 0, y: 0, dx: 1, dy: 1}
26 | ]);
27 | assert.deepEqual(p.nodes({children: [{children: []}, {value: 1}]}).map(metadata), [
28 | {x: 0, y: 0, dx: 1, dy: 0.5},
29 | {x: 1, y: 0.5, dx: 0, dy: 0.5},
30 | {x: 0, y: 0.5, dx: 1, dy: 0.5}
31 | ]);
32 | }
33 | }
34 | });
35 |
36 | function metadata(node) {
37 | var metadata = {};
38 | if ("x" in node) metadata.x = node.x;
39 | if ("y" in node) metadata.y = node.y;
40 | if ("dx" in node) metadata.dx = node.dx;
41 | if ("dy" in node) metadata.dy = node.dy;
42 | return metadata;
43 | }
44 |
45 | suite.export(module);
46 |
--------------------------------------------------------------------------------
/test/arrays/sum-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.sum");
6 |
7 | suite.addBatch({
8 | "sum": {
9 | topic: load("arrays/sum").expression("d3.sum"),
10 | "sums numbers": function(sum) {
11 | assert.equal(sum([1]), 1);
12 | assert.equal(sum([5, 1, 2, 3, 4]), 15);
13 | assert.equal(sum([20, 3]), 23);
14 | assert.equal(sum([3, 20]), 23);
15 | },
16 | "sums types that can be coerced to numbers": function(sum) {
17 | assert.equal(sum(["20", "3"]), 23);
18 | assert.equal(sum(["3", "20"]), 23);
19 | assert.equal(sum(["3", 20]), 23);
20 | assert.equal(sum([20, "3"]), 23);
21 | assert.equal(sum([3, "20"]), 23);
22 | assert.equal(sum(["20", 3]), 23);
23 | },
24 | "ignores non-numeric types": function(sum) {
25 | assert.equal(sum(["a", "b", "c"]), 0);
26 | assert.equal(sum(["a", 1, "2"]), 3);
27 | },
28 | "ignores null, undefined and NaN": function(sum) {
29 | assert.equal(sum([NaN, 1, 2, 3, 4, 5]), 15);
30 | assert.equal(sum([1, 2, 3, 4, 5, NaN]), 15);
31 | assert.equal(sum([10, null, 3, undefined, 5, NaN]), 18);
32 | },
33 | "applies the optional acccessor function": function(sum) {
34 | assert.equal(sum([[1, 2, 3, 4, 5], [2, 4, 6, 8, 10]], function(d) { return sum(d); }), 45);
35 | assert.equal(sum([1, 2, 3, 4, 5], function(d, i) { return i; }), 10);
36 | },
37 | "returns zero for the empty array": function(sum) {
38 | assert.equal(sum([]), 0);
39 | }
40 | }
41 | });
42 |
43 | suite.export(module);
44 |
--------------------------------------------------------------------------------
/test/arrays/descending-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.descending");
6 |
7 | suite.addBatch({
8 | "descending": {
9 | topic: load("arrays/descending").expression("d3.descending"),
10 | "numbers": {
11 | "returns a negative number if a > b": function(descending) {
12 | assert.isTrue(descending(1, 0) < 0);
13 | },
14 | "returns a positive number if a < b": function(descending) {
15 | assert.isTrue(descending(0, 1) > 0);
16 | },
17 | "returns zero if a == b": function(descending) {
18 | assert.equal(descending(0, 0), 0);
19 | },
20 | "returns NaN if a or b is undefined": function(descending) {
21 | assert.isNaN(descending(0, undefined));
22 | assert.isNaN(descending(undefined, 0));
23 | assert.isNaN(descending(undefined, undefined));
24 | },
25 | "returns NaN if a or b is NaN": function(descending) {
26 | assert.isNaN(descending(0, NaN));
27 | assert.isNaN(descending(NaN, 0));
28 | assert.isNaN(descending(NaN, NaN));
29 | }
30 | },
31 | "strings": {
32 | "returns a negative number if a > b": function(descending) {
33 | assert.isTrue(descending("b", "a") < 0);
34 | },
35 | "returns a positive number if a < b": function(descending) {
36 | assert.isTrue(descending("a", "b") > 0);
37 | },
38 | "returns zero if a == b": function(descending) {
39 | assert.equal(descending("a", "a"), 0);
40 | }
41 | }
42 | }
43 | });
44 |
45 | suite.export(module);
46 |
--------------------------------------------------------------------------------
/lib/penner/LICENSE:
--------------------------------------------------------------------------------
1 | TERMS OF USE - EASING EQUATIONS
2 |
3 | Open source under the BSD License.
4 |
5 | Copyright 2001 Robert Penner
6 | All rights reserved.
7 |
8 | Redistribution and use in source and binary forms, with or without modification,
9 | are permitted provided that the following conditions are met:
10 |
11 | - Redistributions of source code must retain the above copyright notice, this
12 | list of conditions and the following disclaimer.
13 |
14 | - Redistributions in binary form must reproduce the above copyright notice,
15 | this list of conditions and the following disclaimer in the documentation
16 | and/or other materials provided with the distribution.
17 |
18 | - Neither the name of the author nor the names of contributors may be used to
19 | endorse or promote products derived from this software without specific prior
20 | written permission.
21 |
22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
23 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
26 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
29 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 |
--------------------------------------------------------------------------------
/test/selection/empty-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("selection.empty");
6 |
7 | suite.addBatch({
8 | "select(body)": {
9 | topic: load("selection/empty").document(),
10 | "on a simple page": {
11 | topic: function(d3) {
12 | return d3.select("body");
13 | },
14 | "returns true for empty selections": function(body) {
15 | assert.isTrue(body.select("foo").empty());
16 | },
17 | "returns false for non-empty selections": function(body) {
18 | assert.isFalse(body.empty());
19 | },
20 | "ignores null nodes": function(body) {
21 | body[0][0] = null;
22 | assert.isTrue(body.empty());
23 | }
24 | }
25 | }
26 | });
27 |
28 | suite.addBatch({
29 | "selectAll(div)": {
30 | topic: load("selection/empty").document(),
31 | "on a simple page": {
32 | topic: function(d3) {
33 | var body = d3.select("body");
34 | body.append("div").append("span");
35 | body.append("div");
36 | return body.selectAll("div");
37 | },
38 | "returns true for empty selections": function(div) {
39 | assert.isTrue(div.select("foo").empty());
40 | },
41 | "returns false for non-empty selections": function(div) {
42 | assert.isFalse(div.empty());
43 | assert.isFalse(div.select("span").empty());
44 | },
45 | "ignores null nodes": function(div) {
46 | div[0][0] = null;
47 | assert.isTrue(div.select("span").empty());
48 | }
49 | }
50 | }
51 | });
52 |
53 | suite.export(module);
54 |
--------------------------------------------------------------------------------
/test/arrays/median-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert");
4 |
5 | var suite = vows.describe("d3.median");
6 |
7 | suite.addBatch({
8 | "median": {
9 | topic: load("arrays/median").expression("d3.median"),
10 | "returns the median value for numbers": function(median) {
11 | assert.equal(median([1]), 1);
12 | assert.equal(median([5, 1, 2, 3, 4]), 3);
13 | assert.equal(median([20, 3]), 11.5);
14 | assert.equal(median([3, 20]), 11.5);
15 | },
16 | "ignores null, undefined and NaN": function(median) {
17 | assert.equal(median([NaN, 1, 2, 3, 4, 5]), 3);
18 | assert.equal(median([1, 2, 3, 4, 5, NaN]), 3);
19 | assert.equal(median([10, null, 3, undefined, 5, NaN]), 5);
20 | },
21 | "can handle large numbers without overflowing": function(median) {
22 | assert.equal(median([Number.MAX_VALUE, Number.MAX_VALUE]), Number.MAX_VALUE);
23 | assert.equal(median([-Number.MAX_VALUE, -Number.MAX_VALUE]), -Number.MAX_VALUE);
24 | },
25 | "returns undefined for empty array": function(median) {
26 | assert.isUndefined(median([]));
27 | assert.isUndefined(median([null]));
28 | assert.isUndefined(median([undefined]));
29 | assert.isUndefined(median([NaN]));
30 | assert.isUndefined(median([NaN, NaN]));
31 | },
32 | "applies the optional accessor function": function(median) {
33 | assert.equal(median([[1, 2, 3, 4, 5], [2, 4, 6, 8, 10]], function(d) { return median(d); }), 4.5);
34 | assert.equal(median([1, 2, 3, 4, 5], function(d, i) { return i; }), 2);
35 | }
36 | }
37 | });
38 |
39 | suite.export(module);
40 |
--------------------------------------------------------------------------------
/test/XMLHttpRequest.js:
--------------------------------------------------------------------------------
1 | var fs = require("fs");
2 |
3 | global.XMLHttpRequest = function XMLHttpRequest() {
4 | var self = this,
5 | info = self._info = {},
6 | headers = {},
7 | url;
8 |
9 | // TODO handle file system errors?
10 |
11 | self.readyState = 0;
12 |
13 | self.open = function(m, u, a) {
14 | info.url = u;
15 | info.async = a;
16 | self.readyState = 1;
17 | self.send = a ? read : readSync;
18 | };
19 |
20 | self.setRequestHeader = function(n, v) {
21 | if (/^Accept$/i.test(n)) info.mimeType = v.split(/,/g)[0];
22 | };
23 |
24 | function read() {
25 | self.readyState = 2;
26 | fs.readFile(info.url, "binary", function(e, d) {
27 | if (e) {
28 | self.status = 404; // assumed
29 | } else {
30 | self.status = 200;
31 | self.responseText = d;
32 | self.responseXML = {_xml: d};
33 | headers["Content-Length"] = d.length;
34 | }
35 | self.readyState = 4;
36 | XMLHttpRequest._last = self;
37 | if (self.onreadystatechange) self.onreadystatechange();
38 | });
39 | }
40 |
41 | function readSync() {
42 | self.readyState = 2;
43 | try {
44 | var d = fs.readFileSync(info.url, "binary");
45 | self.status = 200;
46 | self.responseText = d;
47 | self.responseXML = {_xml: d};
48 | headers["Content-Length"] = d.length;
49 | } catch (e) {
50 | self.status = 404; // assumed
51 | }
52 | self.readyState = 4;
53 | XMLHttpRequest._last = self;
54 | if (self.onreadystatechange) self.onreadystatechange();
55 | }
56 |
57 | self.getResponseHeader = function(n) {
58 | return headers[n];
59 | };
60 | };
61 |
--------------------------------------------------------------------------------
/src/color/hsl.js:
--------------------------------------------------------------------------------
1 | import "color";
2 | import "rgb";
3 |
4 | d3.hsl = function(h, s, l) {
5 | return arguments.length === 1
6 | ? (h instanceof d3_Hsl ? d3_hsl(h.h, h.s, h.l)
7 | : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl))
8 | : d3_hsl(+h, +s, +l);
9 | };
10 |
11 | function d3_hsl(h, s, l) {
12 | return new d3_Hsl(h, s, l);
13 | }
14 |
15 | function d3_Hsl(h, s, l) {
16 | this.h = h;
17 | this.s = s;
18 | this.l = l;
19 | }
20 |
21 | var d3_hslPrototype = d3_Hsl.prototype = new d3_Color;
22 |
23 | d3_hslPrototype.brighter = function(k) {
24 | k = Math.pow(0.7, arguments.length ? k : 1);
25 | return d3_hsl(this.h, this.s, this.l / k);
26 | };
27 |
28 | d3_hslPrototype.darker = function(k) {
29 | k = Math.pow(0.7, arguments.length ? k : 1);
30 | return d3_hsl(this.h, this.s, k * this.l);
31 | };
32 |
33 | d3_hslPrototype.rgb = function() {
34 | return d3_hsl_rgb(this.h, this.s, this.l);
35 | };
36 |
37 | function d3_hsl_rgb(h, s, l) {
38 | var m1,
39 | m2;
40 |
41 | /* Some simple corrections for h, s and l. */
42 | h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h;
43 | s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s;
44 | l = l < 0 ? 0 : l > 1 ? 1 : l;
45 |
46 | /* From FvD 13.37, CSS Color Module Level 3 */
47 | m2 = l <= .5 ? l * (1 + s) : l + s - l * s;
48 | m1 = 2 * l - m2;
49 |
50 | function v(h) {
51 | if (h > 360) h -= 360;
52 | else if (h < 0) h += 360;
53 | if (h < 60) return m1 + (m2 - m1) * h / 60;
54 | if (h < 180) return m2;
55 | if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60;
56 | return m1;
57 | }
58 |
59 | function vv(h) {
60 | return Math.round(v(h) * 255);
61 | }
62 |
63 | return d3_rgb(vv(h + 120), vv(h), vv(h - 120));
64 | }
65 |
--------------------------------------------------------------------------------
/src/scale/category.js:
--------------------------------------------------------------------------------
1 | import "../color/rgb";
2 | import "ordinal";
3 | import "scale";
4 |
5 | /*
6 | * This product includes color specifications and designs developed by Cynthia
7 | * Brewer (http://colorbrewer.org/). See lib/colorbrewer for more information.
8 | */
9 |
10 | d3.scale.category10 = function() {
11 | return d3.scale.ordinal().range(d3_category10);
12 | };
13 |
14 | d3.scale.category20 = function() {
15 | return d3.scale.ordinal().range(d3_category20);
16 | };
17 |
18 | d3.scale.category20b = function() {
19 | return d3.scale.ordinal().range(d3_category20b);
20 | };
21 |
22 | d3.scale.category20c = function() {
23 | return d3.scale.ordinal().range(d3_category20c);
24 | };
25 |
26 | var d3_category10 = [
27 | 0x1f77b4, 0xff7f0e, 0x2ca02c, 0xd62728, 0x9467bd,
28 | 0x8c564b, 0xe377c2, 0x7f7f7f, 0xbcbd22, 0x17becf
29 | ].map(d3_rgbString);
30 |
31 | var d3_category20 = [
32 | 0x1f77b4, 0xaec7e8,
33 | 0xff7f0e, 0xffbb78,
34 | 0x2ca02c, 0x98df8a,
35 | 0xd62728, 0xff9896,
36 | 0x9467bd, 0xc5b0d5,
37 | 0x8c564b, 0xc49c94,
38 | 0xe377c2, 0xf7b6d2,
39 | 0x7f7f7f, 0xc7c7c7,
40 | 0xbcbd22, 0xdbdb8d,
41 | 0x17becf, 0x9edae5
42 | ].map(d3_rgbString);
43 |
44 | var d3_category20b = [
45 | 0x393b79, 0x5254a3, 0x6b6ecf, 0x9c9ede,
46 | 0x637939, 0x8ca252, 0xb5cf6b, 0xcedb9c,
47 | 0x8c6d31, 0xbd9e39, 0xe7ba52, 0xe7cb94,
48 | 0x843c39, 0xad494a, 0xd6616b, 0xe7969c,
49 | 0x7b4173, 0xa55194, 0xce6dbd, 0xde9ed6
50 | ].map(d3_rgbString);
51 |
52 | var d3_category20c = [
53 | 0x3182bd, 0x6baed6, 0x9ecae1, 0xc6dbef,
54 | 0xe6550d, 0xfd8d3c, 0xfdae6b, 0xfdd0a2,
55 | 0x31a354, 0x74c476, 0xa1d99b, 0xc7e9c0,
56 | 0x756bb1, 0x9e9ac8, 0xbcbddc, 0xdadaeb,
57 | 0x636363, 0x969696, 0xbdbdbd, 0xd9d9d9
58 | ].map(d3_rgbString);
59 |
--------------------------------------------------------------------------------
/test/geo/albers-test.js:
--------------------------------------------------------------------------------
1 | var vows = require("vows"),
2 | load = require("../load"),
3 | assert = require("../assert"),
4 | projectionTestSuite = require("./projection-test-suite");
5 |
6 | var suite = vows.describe("d3.geo.albers");
7 |
8 | suite.addBatch({
9 | "albers": {
10 | topic: load("geo/albers").expression("d3.geo.albers"),
11 | "default": projectionTestSuite({
12 | topic: function(projection) { return projection(); },
13 | "has the parallels 29.5°, 45.5°": function(p) {
14 | assert.inDelta(p.parallels(), [29.5, 45.5], 1e-6);
15 | },
16 | "has the rotation 96°, 0°": function(p) {
17 | assert.inDelta(p.rotate(), [96, 0, 0], 1e-6);
18 | },
19 | "has the center -0.6°, 38.7°": function(p) {
20 | assert.inDelta(p.center(), [-.6, 38.7], 1e-6);
21 | },
22 | "has the scale 1070": function(p) {
23 | assert.inDelta(p.scale(), 1070, 1e-6);
24 | }
25 | }, {
26 | "Washington, DC": [[-120.50000000, 47.50000000], [ 181.00023857, 45.12748866]],
27 | "San Francisco, CA": [[-122.42000000, 37.78000000], [ 107.44485839, 214.04820561]],
28 | "the North Pole": [[ 0.00000000, 90.00000000], [1062.11670525, -761.71949818]]
29 | }),
30 | "translated to 0,0 and at scale 1": projectionTestSuite({
31 | topic: function(projection) { return projection().translate([0, 0]).scale(1); }
32 | }, {
33 | "Washington, DC": [[-120.50000000, 47.50000000], [ -0.27943903, -0.19146964]],
34 | "San Francisco, CA": [[-122.42000000, 37.78000000], [ -0.34818238, -0.03359981]],
35 | "the North Pole": [[ 0.00000000, 90.00000000], [ 0.54403430, -0.94553224]]
36 | })
37 | }
38 | });
39 |
40 | suite.export(module);
41 |
--------------------------------------------------------------------------------
/test/load.js:
--------------------------------------------------------------------------------
1 | process.env.TZ = "America/Los_Angeles";
2 |
3 | var smash = require("smash"),
4 | jsdom = require("jsdom");
5 |
6 | require("./XMLHttpRequest");
7 |
8 | module.exports = function() {
9 | var files = [].slice.call(arguments).map(function(d) { return "src/" + d; }),
10 | expression = "d3",
11 | sandbox = {console: console, Date: Date}; // so we can use deepEqual in tests
12 |
13 | files.unshift("src/start");
14 | files.push("src/end");
15 |
16 | function topic() {
17 | var callback = this.callback;
18 | smash.load(files, expression, sandbox, function(error, result) {
19 | if (error) console.trace(error.stack);
20 | callback(error, result);
21 | });
22 | }
23 |
24 | topic.expression = function(_) {
25 | expression = _;
26 | return topic;
27 | };
28 |
29 | topic.sandbox = function(_) {
30 | sandbox = _;
31 | return topic;
32 | };
33 |
34 | topic.document = function(_) {
35 | var document = jsdom.jsdom("");
36 |
37 | // Monkey-patch createRange support to JSDOM.
38 | document.createRange = function() {
39 | return {
40 | selectNode: function() {},
41 | createContextualFragment: jsdom.jsdom
42 | };
43 | };
44 |
45 | sandbox = {
46 | console: console,
47 | XMLHttpRequest: XMLHttpRequest,
48 | document: document,
49 | window: document.createWindow(),
50 | setTimeout: setTimeout,
51 | clearTimeout: clearTimeout,
52 | Date: Date // so we can override Date.now in tests, and use deepEqual
53 | };
54 |
55 | return topic;
56 | };
57 |
58 | return topic;
59 | };
60 |
61 | process.on("uncaughtException", function(e) {
62 | console.trace(e.stack);
63 | });
64 |
--------------------------------------------------------------------------------
/test/transition/transition-test-transition.js:
--------------------------------------------------------------------------------
1 | var assert = require("../assert");
2 |
3 | module.exports = {
4 | topic: function(d3) {
5 | return d3.select("body").append("div").transition()
6 | .delay(101)
7 | .duration(152)
8 | .ease("bounce");
9 | },
10 |
11 | "starts immediately after the previous transition ends": function(t1) {
12 | var t2 = t1.transition();
13 | assert.equal(t2[0][0].__transition__[t2.id].delay, 253);
14 | },
15 | "inherits the previous transition's duration": function(t1) {
16 | var t2 = t1.transition();
17 | assert.equal(t2[0][0].__transition__[t2.id].duration, 152);
18 | },
19 | "inherits easing": function(t1) {
20 | // TODO how to test this?
21 | },
22 | "gets a new transition id": function(t1) {
23 | var t2 = t1.transition();
24 | assert.isTrue(t2.id > t1.id);
25 | },
26 |
27 | "while transitioning": {
28 | topic: function(t1) {
29 | var callback = this.callback;
30 | var t2 = t1.transition().each("start", function() {
31 | if (callback) {
32 | callback(null, t2);
33 | callback = null;
34 | }
35 | });
36 | },
37 | "increments the lock's reference count": function(t2) {
38 | assert.isTrue(t2[0][0].__transition__.count > 1);
39 | }
40 | },
41 |
42 | "after transitioning": {
43 | topic: function(t1) {
44 | var cb = this.callback;
45 | var t2 = t1.transition();
46 | t2.each("end", function() {
47 | setTimeout(function() {
48 | cb(null, t2);
49 | return true;
50 | }, 50);
51 | });
52 | },
53 | "decrements the lock's reference count": function(t2) {
54 | assert.isFalse("__transition__" in t2[0][0]);
55 | }
56 | }
57 | };
58 |
--------------------------------------------------------------------------------