├── src ├── 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 │ ├── transverse-mercator.js │ ├── index.js │ ├── conic-equal-area.js │ ├── conic-equidistant.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 ├── end.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 │ ├── trigonometry.js │ └── adder.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 │ ├── filter.js │ ├── enter-select.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 ├── format │ ├── collapse.js │ ├── index.js │ ├── round.js │ ├── requote.js │ ├── format-localized.js │ ├── format-locale.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 │ ├── bisect.js │ ├── set.js │ └── map.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 ├── time │ ├── index.js │ ├── format-locale.js │ ├── month.js │ ├── year.js │ ├── minute.js │ ├── second.js │ ├── hour.js │ ├── format-iso.js │ ├── day.js │ ├── format-localized.js │ ├── format-utc.js │ ├── week.js │ └── scale-utc.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 │ ├── random-test.js │ └── 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 ├── 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 ├── load.js └── XMLHttpRequest.js ├── .gitignore ├── .npmignore ├── .travis.yml ├── index-browserify.js ├── bin ├── start ├── component ├── bower ├── uglify └── locale ├── 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 ├── README.md ├── index.js ├── Makefile ├── package.json └── LICENSE /src/geo/geo.js: -------------------------------------------------------------------------------- 1 | d3.geo = {}; 2 | -------------------------------------------------------------------------------- /src/svg/svg.js: -------------------------------------------------------------------------------- 1 | d3.svg = {}; 2 | -------------------------------------------------------------------------------- /src/end.js: -------------------------------------------------------------------------------- 1 | return d3; 2 | })(); 3 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | examples/ 2 | test/ 3 | lib/ 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/behavior/index.js: -------------------------------------------------------------------------------- 1 | import "behavior"; 2 | import "drag"; 3 | import "zoom"; 4 | -------------------------------------------------------------------------------- /src/start.js: -------------------------------------------------------------------------------- 1 | d3 = (function(){ 2 | var d3 = {version: "3.3.9"}; // semver 3 | -------------------------------------------------------------------------------- /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/format/collapse.js: -------------------------------------------------------------------------------- 1 | function d3_collapse(s) { 2 | return s.trim().replace(/\s+/g, " "); 3 | } 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 | -------------------------------------------------------------------------------- /index-browserify.js: -------------------------------------------------------------------------------- 1 | require("./d3"); 2 | module.exports = d3; 3 | (function () { delete this.d3; })(); // unset global 4 | -------------------------------------------------------------------------------- /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/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/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("d3 = (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/format/format-localized.js: -------------------------------------------------------------------------------- 1 | var d3_format_decimalPoint = ".", 2 | d3_format_thousandsSeparator = ",", 3 | d3_format_grouping = [3, 3], 4 | d3_format_currencySymbol = "$"; 5 | 6 | -------------------------------------------------------------------------------- /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/format/format-locale.js: -------------------------------------------------------------------------------- 1 | var d3_format_decimalPoint = {decimal_point}, 2 | d3_format_thousandsSeparator = {thousands_sep}, 3 | d3_format_grouping = {grouping}, 4 | d3_format_currencySymbol = {currency_symbol}; 5 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/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/time/index.js: -------------------------------------------------------------------------------- 1 | import "time"; 2 | import "format-localized"; 3 | import "format"; 4 | import "format-utc"; 5 | import "format-iso"; 6 | import "interval"; 7 | import "second"; 8 | import "minute"; 9 | import "hour"; 10 | import "day"; 11 | import "week"; 12 | import "month"; 13 | import "year"; 14 | import "scale"; 15 | import "scale-utc"; 16 | -------------------------------------------------------------------------------- /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/time/format-locale.js: -------------------------------------------------------------------------------- 1 | // The date and time format (%c), date format (%x) and time format (%X). 2 | var d3_time_formatDateTime = {d_t_fmt}, 3 | d3_time_formatDate = {d_fmt}, 4 | d3_time_formatTime = {t_fmt}; 5 | 6 | // The weekday and month names. 7 | var d3_time_days = {day}, 8 | d3_time_dayAbbreviations = {abday}, 9 | d3_time_months = {mon}, 10 | d3_time_monthAbbreviations = {abmon}; 11 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "d3", 3 | "version": "3.3.9", 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-browserify.js", 18 | "index.js", 19 | "lib", 20 | "node_modules", 21 | "package.json", 22 | "src", 23 | "test" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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.3.9", 14 | "main": "index-browserify.js", 15 | "scripts": [ 16 | "d3.js", 17 | "index-browserify.js" 18 | ], 19 | "dependencies": {}, 20 | "development": {}, 21 | "license": "BSD" 22 | } 23 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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": "index-browserify.js", 13 | "scripts": [ 14 | "d3.js", 15 | "index-browserify.js" 16 | ], 17 | "dependencies": {}, 18 | "development": {}, 19 | "license": package.licenses[0].type 20 | }, null, 2)); 21 | -------------------------------------------------------------------------------- /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-browserify.js", 22 | "index.js", 23 | "lib", 24 | "node_modules", 25 | "package.json", 26 | "src", 27 | "test" 28 | ] 29 | }, null, 2)); 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Data-Driven Documents 2 | 3 | **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. 4 | 5 | Want to learn more? [See the wiki.](https://github.com/mbostock/d3/wiki) 6 | 7 | For examples, [see the gallery](https://github.com/mbostock/d3/wiki/Gallery) and [mbostock’s bl.ocks](http://bl.ocks.org/mbostock). 8 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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)) { 16 | subgroup.push(node); 17 | } 18 | } 19 | } 20 | 21 | return d3_transition(subgroups, this.id); 22 | }; 23 | -------------------------------------------------------------------------------- /src/geo/transverse-mercator.js: -------------------------------------------------------------------------------- 1 | import "../math/trigonometry"; 2 | import "geo"; 3 | import "mercator"; 4 | import "projection"; 5 | 6 | function d3_geo_transverseMercator(λ, φ) { 7 | var B = Math.cos(φ) * Math.sin(λ); 8 | return [ 9 | Math.log((1 + B) / (1 - B)) / 2, 10 | Math.atan2(Math.tan(φ), Math.cos(λ)) 11 | ]; 12 | } 13 | 14 | d3_geo_transverseMercator.invert = function(x, y) { 15 | return [ 16 | Math.atan2(d3_sinh(x), Math.cos(y)), 17 | d3_asin(Math.sin(y) / d3_cosh(x)) 18 | ]; 19 | }; 20 | 21 | (d3.geo.transverseMercator = function() { 22 | return d3_geo_mercatorProjection(d3_geo_transverseMercator); 23 | }).raw = d3_geo_transverseMercator; 24 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/scale/nice.js: -------------------------------------------------------------------------------- 1 | function d3_scale_nice(domain, nice) { 2 | var i0 = 0, 3 | i1 = domain.length - 1, 4 | x0 = domain[i0], 5 | x1 = domain[i1], 6 | dx; 7 | 8 | if (x1 < x0) { 9 | dx = i0, i0 = i1, i1 = dx; 10 | dx = x0, x0 = x1, x1 = dx; 11 | } 12 | 13 | domain[i0] = nice.floor(x0); 14 | domain[i1] = nice.ceil(x1); 15 | return domain; 16 | } 17 | 18 | function d3_scale_niceStep(step) { 19 | return step ? { 20 | floor: function(x) { return Math.floor(x / step) * step; }, 21 | ceil: function(x) { return Math.ceil(x / step) * step; } 22 | } : d3_scale_niceIdentity; 23 | } 24 | 25 | var d3_scale_niceIdentity = { 26 | floor: d3_identity, 27 | ceil: d3_identity 28 | }; 29 | -------------------------------------------------------------------------------- /test/math/transform-null-test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 27 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/time/format-localized.js: -------------------------------------------------------------------------------- 1 | // The date and time format (%c), date format (%x) and time format (%X). 2 | var d3_time_formatDateTime = "%a %b %e %X %Y", 3 | d3_time_formatDate = "%m/%d/%Y", 4 | d3_time_formatTime = "%H:%M:%S"; 5 | 6 | // The weekday and month names. 7 | var d3_time_days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], 8 | d3_time_dayAbbreviations = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], 9 | d3_time_months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], 10 | d3_time_monthAbbreviations = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; 11 | 12 | -------------------------------------------------------------------------------- /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/time/format-utc.js: -------------------------------------------------------------------------------- 1 | import "format"; 2 | import "time"; 3 | 4 | d3_time_format.utc = d3_time_formatUtc; 5 | 6 | function d3_time_formatUtc(template) { 7 | var local = d3_time_format(template); 8 | 9 | function format(date) { 10 | try { 11 | d3_date = d3_date_utc; 12 | var utc = new d3_date(); 13 | utc._ = date; 14 | return local(utc); 15 | } finally { 16 | d3_date = Date; 17 | } 18 | } 19 | 20 | format.parse = function(string) { 21 | try { 22 | d3_date = d3_date_utc; 23 | var date = local.parse(string); 24 | return date && date._; 25 | } finally { 26 | d3_date = Date; 27 | } 28 | }; 29 | 30 | format.toString = local.toString; 31 | 32 | return format; 33 | } 34 | -------------------------------------------------------------------------------- /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/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 | irwinHall: function(m) { 23 | return function() { 24 | for (var s = 0, j = 0; j < m; j++) s += Math.random(); 25 | return s / m; 26 | }; 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /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 | function d3_acos(x) { 14 | return x > 1 ? 0 : x < -1 ? π : Math.acos(x); 15 | } 16 | 17 | function d3_asin(x) { 18 | return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x); 19 | } 20 | 21 | function d3_sinh(x) { 22 | return ((x = Math.exp(x)) - 1 / x) / 2; 23 | } 24 | 25 | function d3_cosh(x) { 26 | return ((x = Math.exp(x)) + 1 / x) / 2; 27 | } 28 | 29 | function d3_tanh(x) { 30 | return ((x = Math.exp(2 * x)) - 1) / (x + 1); 31 | } 32 | 33 | function d3_haversin(x) { 34 | return (x = Math.sin(x / 2)) * x; 35 | } 36 | -------------------------------------------------------------------------------- /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/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)) { 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 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var fs = require("fs"), 2 | path = require("path"), 3 | document = require("jsdom").jsdom(""), 4 | window = document.createWindow(); 5 | 6 | // https://github.com/chad3814/CSSStyleDeclaration/issues/3 7 | var CSSStyleDeclaration_prototype = window.CSSStyleDeclaration.prototype, 8 | CSSStyleDeclaration_setProperty = CSSStyleDeclaration_prototype.setProperty; 9 | CSSStyleDeclaration_prototype.setProperty = function(name, value, priority) { 10 | return CSSStyleDeclaration_setProperty.call(this, name + "", value == null ? null : value + "", priority == null ? null : priority + ""); 11 | }; 12 | 13 | module.exports = (new Function("window", "document", 14 | "return " + fs.readFileSync(path.join(__dirname, "d3.js"), "utf-8")) 15 | )(window, document); 16 | -------------------------------------------------------------------------------- /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/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/format/formatPrefix.js: -------------------------------------------------------------------------------- 1 | import "format"; 2 | import "../math/abs"; 3 | 4 | var d3_formatPrefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"].map(d3_formatPrefix); 5 | 6 | d3.formatPrefix = function(value, precision) { 7 | var i = 0; 8 | if (value) { 9 | if (value < 0) value *= -1; 10 | if (precision) value = d3.round(value, d3_format_precision(value, precision)); 11 | i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10); 12 | i = Math.max(-24, Math.min(24, Math.floor((i <= 0 ? i + 1 : i - 1) / 3) * 3)); 13 | } 14 | return d3_formatPrefixes[8 + i / 3]; 15 | }; 16 | 17 | function d3_formatPrefix(d, i) { 18 | var k = Math.pow(10, abs(8 - i) * 3); 19 | return { 20 | scale: i > 8 ? function(d) { return d / k; } : function(d) { return d * k; }, 21 | symbol: d 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/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 | -------------------------------------------------------------------------------- /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: function(value) { 14 | return d3_map_prefix + value in this; 15 | }, 16 | add: function(value) { 17 | this[d3_map_prefix + value] = true; 18 | return value; 19 | }, 20 | remove: function(value) { 21 | value = d3_map_prefix + value; 22 | return value in this && delete this[value]; 23 | }, 24 | values: function() { 25 | var values = []; 26 | this.forEach(function(value) { 27 | values.push(value); 28 | }); 29 | return values; 30 | }, 31 | forEach: function(f) { 32 | for (var value in this) { 33 | if (value.charCodeAt(0) === d3_map_prefixCode) { 34 | f.call(this, value.substring(1)); 35 | } 36 | } 37 | } 38 | }); 39 | -------------------------------------------------------------------------------- /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/math/random-test.js: -------------------------------------------------------------------------------- 1 | var vows = require("vows"), 2 | load = require("../load"), 3 | assert = require("../assert"); 4 | 5 | var suite = vows.describe("d3.random"); 6 | 7 | suite.addBatch({ 8 | "random": { 9 | topic: load("math/random").expression("d3.random"), 10 | "normal": { 11 | "topic": function(random) { 12 | return random.normal(); 13 | }, 14 | "returns a number": function(r) { 15 | assert.typeOf(r(), "number"); 16 | } 17 | }, 18 | "logNormal": { 19 | "topic": function(random) { 20 | return random.logNormal(); 21 | }, 22 | "returns a number": function(r) { 23 | assert.typeOf(r(), "number"); 24 | } 25 | }, 26 | "irwinHall": { 27 | "topic": function(random) { 28 | return random.irwinHall(10); 29 | }, 30 | "returns a number": function(r) { 31 | assert.typeOf(r(), "number"); 32 | } 33 | } 34 | } 35 | }); 36 | 37 | suite.export(module); 38 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /bin/locale: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var fs = require("fs"), 4 | puts = require("util").puts, 5 | formats = {}, 6 | kvRe = /=/, 7 | valueRe = /;/g, 8 | quotedRe = /"([^"]*?)"/g, 9 | data = []; 10 | 11 | process.stdin.resume(); 12 | process.stdin.setEncoding("utf8"); 13 | process.stdin.on("data", function(chunk) { data.push(chunk); }); 14 | process.stdin.on("end", write); 15 | 16 | function write() { 17 | data.join("\n").split(/\n/g).forEach(function(line) { 18 | var i = line.match(kvRe); 19 | if (i && (i = i.index)) { 20 | var value = line.substring(i + 1).replace(quotedRe, "$1").split(valueRe); 21 | formats[line.substring(0, i)] = value; 22 | } 23 | }); 24 | 25 | puts(fs.readFileSync(process.argv[2], "utf8").replace(/\{([a-z_]+)\}/g, function(d, k) { 26 | d = formats[k]; 27 | return k === "grouping" 28 | ? d === "127" || d === "0" ? null : "[" + d.map(Number).join(", ") + "]" 29 | : d == null ? null : d.length > 1 ? "[" + d.map(quote).join(", ") + "]" : quote(d[0]); 30 | })); 31 | } 32 | 33 | function quote(d) { return '"' + d + '"'; } 34 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/time/week.js: -------------------------------------------------------------------------------- 1 | import "day"; 2 | import "interval"; 3 | import "time"; 4 | import "year"; 5 | 6 | d3_time_daySymbols.forEach(function(day, i) { 7 | day = day.toLowerCase(); 8 | i = 7 - i; 9 | 10 | var interval = d3_time[day] = d3_time_interval(function(date) { 11 | (date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7); 12 | return date; 13 | }, function(date, offset) { 14 | date.setDate(date.getDate() + Math.floor(offset) * 7); 15 | }, function(date) { 16 | var day = d3_time.year(date).getDay(); 17 | return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i); 18 | }); 19 | 20 | d3_time[day + "s"] = interval.range; 21 | d3_time[day + "s"].utc = interval.utc.range; 22 | 23 | d3_time[day + "OfYear"] = function(date) { 24 | var day = d3_time.year(date).getDay(); 25 | return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7); 26 | }; 27 | }); 28 | 29 | d3_time.week = d3_time.sunday; 30 | d3_time.weeks = d3_time.sunday.range; 31 | d3_time.weeks.utc = d3_time.sunday.utc.range; 32 | d3_time.weekOfYear = d3_time.sundayOfYear; 33 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | LOCALE ?= en_US 2 | 3 | GENERATED_FILES = \ 4 | d3.js \ 5 | d3.min.js \ 6 | src/format/format-localized.js \ 7 | src/time/format-localized.js \ 8 | bower.json \ 9 | component.json 10 | 11 | all: $(GENERATED_FILES) 12 | 13 | .PHONY: clean all test 14 | 15 | test: 16 | @npm test 17 | 18 | src/format/format-localized.js: bin/locale src/format/format-locale.js 19 | LC_NUMERIC=$(LOCALE) LC_MONETARY=$(LOCALE) locale -ck LC_NUMERIC LC_MONETARY | bin/locale src/format/format-locale.js > $@ 20 | 21 | src/time/format-localized.js: bin/locale src/time/format-locale.js 22 | LC_TIME=$(LOCALE) locale -ck LC_TIME | bin/locale src/time/format-locale.js > $@ 23 | 24 | src/start.js: package.json bin/start 25 | bin/start > $@ 26 | 27 | d3.js: $(shell node_modules/.bin/smash --list src/d3.js) package.json 28 | @rm -f $@ 29 | node_modules/.bin/smash src/d3.js | node_modules/.bin/uglifyjs - -b indent-level=2 -o $@ 30 | @chmod a-w $@ 31 | 32 | d3.min.js: d3.js bin/uglify 33 | @rm -f $@ 34 | bin/uglify $< > $@ 35 | 36 | %.json: bin/% package.json 37 | @rm -f $@ 38 | bin/$* > $@ 39 | @chmod a-w $@ 40 | 41 | clean: 42 | rm -f -- $(GENERATED_FILES) 43 | -------------------------------------------------------------------------------- /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/time/scale-utc.js: -------------------------------------------------------------------------------- 1 | import "../core/true"; 2 | import "../scale/linear"; 3 | import "format"; 4 | import "format-utc"; 5 | import "scale"; 6 | 7 | var d3_time_scaleUTCMethods = d3_time_scaleLocalMethods.map(function(m) { 8 | return [m[0].utc, m[1]]; 9 | }); 10 | 11 | var d3_time_scaleUTCFormats = [ 12 | [d3_time_formatUtc("%Y"), d3_true], 13 | [d3_time_formatUtc("%B"), function(d) { return d.getUTCMonth(); }], 14 | [d3_time_formatUtc("%b %d"), function(d) { return d.getUTCDate() != 1; }], 15 | [d3_time_formatUtc("%a %d"), function(d) { return d.getUTCDay() && d.getUTCDate() != 1; }], 16 | [d3_time_formatUtc("%I %p"), function(d) { return d.getUTCHours(); }], 17 | [d3_time_formatUtc("%I:%M"), function(d) { return d.getUTCMinutes(); }], 18 | [d3_time_formatUtc(":%S"), function(d) { return d.getUTCSeconds(); }], 19 | [d3_time_formatUtc(".%L"), function(d) { return d.getUTCMilliseconds(); }] 20 | ]; 21 | 22 | var d3_time_scaleUTCFormat = d3_time_scaleFormat(d3_time_scaleUTCFormats); 23 | 24 | d3_time_scaleUTCMethods.year = d3_time.year.utc; 25 | 26 | d3_time.scale.utc = function() { 27 | return d3_time_scale(d3.scale.linear(), d3_time_scaleUTCMethods, d3_time_scaleUTCFormat); 28 | }; 29 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "d3", 3 | "version": "3.3.9", 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": "index-browserify.js", 30 | "jam": { 31 | "main": "d3.js", 32 | "shim": { 33 | "exports": "d3" 34 | } 35 | }, 36 | "dependencies": { 37 | "jsdom": "0.5.7" 38 | }, 39 | "devDependencies": { 40 | "smash": "0.0.11", 41 | "uglify-js": "2.4.0", 42 | "vows": "0.7.0" 43 | }, 44 | "scripts": { 45 | "test": "node_modules/.bin/vows" 46 | }, 47 | "licenses": [ 48 | { 49 | "type": "BSD", 50 | "url": "https://github.com/mbostock/d3/blob/master/LICENSE" 51 | } 52 | ] 53 | } 54 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, 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 | -------------------------------------------------------------------------------- /src/arrays/map.js: -------------------------------------------------------------------------------- 1 | import "../core/class"; 2 | 3 | d3.map = function(object) { 4 | var map = new d3_Map; 5 | if (object instanceof d3_Map) object.forEach(function(key, value) { map.set(key, value); }); 6 | else for (var key in object) map.set(key, object[key]); 7 | return map; 8 | }; 9 | 10 | function d3_Map() {} 11 | 12 | d3_class(d3_Map, { 13 | has: function(key) { 14 | return d3_map_prefix + key in this; 15 | }, 16 | get: function(key) { 17 | return this[d3_map_prefix + key]; 18 | }, 19 | set: function(key, value) { 20 | return this[d3_map_prefix + key] = value; 21 | }, 22 | remove: function(key) { 23 | key = d3_map_prefix + key; 24 | return key in this && delete this[key]; 25 | }, 26 | keys: function() { 27 | var keys = []; 28 | this.forEach(function(key) { keys.push(key); }); 29 | return keys; 30 | }, 31 | values: function() { 32 | var values = []; 33 | this.forEach(function(key, value) { values.push(value); }); 34 | return values; 35 | }, 36 | entries: function() { 37 | var entries = []; 38 | this.forEach(function(key, value) { entries.push({key: key, value: value}); }); 39 | return entries; 40 | }, 41 | forEach: function(f) { 42 | for (var key in this) { 43 | if (key.charCodeAt(0) === d3_map_prefixCode) { 44 | f.call(this, key.substring(1), this[key]); 45 | } 46 | } 47 | } 48 | }); 49 | 50 | var d3_map_prefix = "\0", // prevent collision with built-ins 51 | d3_map_prefixCode = d3_map_prefix.charCodeAt(0); 52 | -------------------------------------------------------------------------------- /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/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.document = function(_) { 30 | var document = jsdom.jsdom(""); 31 | 32 | // Monkey-patch createRange support to JSDOM. 33 | document.createRange = function() { 34 | return { 35 | selectNode: function() {}, 36 | createContextualFragment: jsdom.jsdom 37 | }; 38 | }; 39 | 40 | sandbox = { 41 | console: console, 42 | XMLHttpRequest: XMLHttpRequest, 43 | document: document, 44 | window: document.createWindow(), 45 | setTimeout: setTimeout, 46 | clearTimeout: clearTimeout, 47 | Date: Date // so we can override Date.now in tests, and use deepEqual 48 | }; 49 | 50 | return topic; 51 | }; 52 | 53 | return topic; 54 | }; 55 | 56 | process.on("uncaughtException", function(e) { 57 | console.trace(e.stack); 58 | }); 59 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------