├── .gitmodules ├── src ├── end.js ├── start.js ├── svg │ ├── svg.js │ ├── mouse.js │ ├── touches.js │ ├── area-radial.js │ ├── line-radial.js │ ├── diagonal-radial.js │ └── diagonal.js ├── geom │ ├── geom.js │ └── delaunay.js ├── core │ ├── noop.js │ ├── core.js │ ├── this.js │ ├── true.js │ ├── identity.js │ ├── number.js │ ├── selection-empty.js │ ├── transpose.js │ ├── merge.js │ ├── ascending.js │ ├── collapse.js │ ├── descending.js │ ├── transition-transition.js │ ├── keys.js │ ├── round.js │ ├── values.js │ ├── functor.js │ ├── requote.js │ ├── entries.js │ ├── json.js │ ├── permute.js │ ├── median.js │ ├── selection-datum.js │ ├── transition-remove.js │ ├── transition-text.js │ ├── xml.js │ ├── text.js │ ├── quantile.js │ ├── selection-remove.js │ ├── selection-node.js │ ├── first.js │ ├── last.js │ ├── transition-delay.js │ ├── class.js │ ├── touches.js │ ├── uninterpolate.js │ ├── sum.js │ ├── transition-duration.js │ ├── html.js │ ├── selection-html.js │ ├── zip.js │ ├── mean.js │ ├── selection-text.js │ ├── selection-order.js │ ├── random.js │ ├── selection-sort.js │ ├── selection-append.js │ ├── selection-each.js │ ├── split.js │ ├── max.js │ ├── min.js │ ├── selection-call.js │ ├── selection-transition.js │ ├── xhr.js │ ├── selection-enter.js │ ├── selection-root.js │ ├── transition-filter.js │ ├── selection-insert.js │ ├── extent.js │ ├── ns.js │ ├── rebind.js │ ├── transition-each.js │ ├── selection-property.js │ ├── transition-style.js │ ├── range.js │ ├── selection-selectAll.js │ ├── selection-enter-select.js │ ├── selection-filter.js │ ├── formatPrefix.js │ ├── transition-selectAll.js │ ├── transition-select.js │ ├── selection-style.js │ ├── bisect.js │ ├── array.js │ ├── selection-select.js │ ├── transition-attr.js │ ├── selection.js │ ├── mouse.js │ ├── map.js │ ├── selection-attr.js │ └── selection-on.js ├── layout │ ├── layout.js │ └── partition.js ├── behavior │ └── behavior.js ├── geo │ ├── greatCircle.js │ ├── geo.js │ ├── type.js │ ├── equirectangular.js │ └── mercator.js ├── compat │ ├── date.js │ └── style.js ├── scale │ ├── sqrt.js │ ├── bilinear.js │ ├── scale.js │ ├── nice.js │ ├── polylinear.js │ ├── identity.js │ ├── quantize.js │ ├── quantile.js │ └── pow.js ├── csv │ ├── csv.js │ └── format.js ├── time │ ├── month.js │ ├── year.js │ ├── minute.js │ ├── second.js │ ├── hour.js │ ├── format-iso.js │ ├── day.js │ ├── format-utc.js │ └── week.js └── package.js ├── examples ├── data │ ├── sample.txt │ ├── sample.csv │ ├── sample.json │ ├── sample.html │ ├── sample.xml │ ├── README.md │ ├── faithful.json │ ├── us-borders.json │ └── morley.csv ├── stream │ ├── stream.css │ ├── stack.css │ ├── stream.html │ ├── stack.html │ ├── stream_layers.js │ └── stream.js ├── sort │ ├── sort.css │ └── sort.html ├── bubble │ ├── bubble.css │ └── bubble.html ├── kde │ ├── kde.css │ └── kde.html ├── cartogram │ ├── demers.css │ ├── dorling.css │ ├── cartogram.css │ ├── demers.html │ ├── dorling.html │ └── cartogram.html ├── horizon │ ├── horizon.css │ ├── horizon.html │ └── unemployment.json ├── force │ ├── force.css │ ├── force.html │ ├── README │ └── force.js ├── bundle │ ├── bundle-radial.css │ ├── bundle-treemap.css │ ├── bundle-radial.html │ ├── bundle-treemap.html │ └── packages.js ├── chord │ ├── chord.css │ └── chord.html ├── treemap │ ├── treemap.css │ ├── treemap-svg.html │ ├── treemap.html │ └── treemap-svg.js ├── box │ ├── box.css │ └── box.html ├── tree │ ├── tree.css │ ├── tree.html │ ├── tree-radial.html │ ├── tree.js │ └── tree-radial.js ├── voroboids │ ├── voroboids.css │ └── voroboids.html ├── calendar │ ├── calendar.css │ ├── dji.html │ └── vix.html ├── cluster │ ├── cluster.css │ ├── cluster.html │ ├── cluster-radial.html │ ├── cluster.js │ └── cluster-radial.js ├── voronoi │ ├── voronoi.css │ ├── voronoi.html │ └── voronoi.js ├── pack │ ├── pack.css │ ├── pack.html │ └── pack.js ├── choropleth │ ├── choropleth.css │ ├── choropleth.html │ ├── choropleth.js │ ├── choropleth-bounds.html │ └── choropleth-area.html ├── qq │ ├── qq.css │ ├── qq.html │ └── stats.js ├── azimuthal │ ├── azimuthal.css │ └── azimuthal.js ├── clock │ ├── clock.css │ └── clock.html ├── population │ ├── population.html │ └── population.css ├── splom │ ├── splom.html │ └── splom.css ├── bullet │ ├── bullet.css │ ├── bullet.html │ └── bullets.json ├── spline │ ├── spline.css │ └── spline.html ├── hello-world │ ├── selectAll-enter-add.html │ ├── hello-order.html │ ├── hello-node-key.html │ ├── select-enter-add.html │ ├── hello-transition-undefined.html │ ├── hello-transition.html │ ├── hello-transform.html │ ├── hello-data.html │ └── hello-event.html ├── crimea │ └── crimea.csv ├── transform │ ├── null.html │ └── null-matrix.html ├── partition │ ├── partition-sunburst.html │ └── partition-icicle.html ├── sizzle │ └── sizzle.html ├── mouse │ └── mouse-html.html ├── bar │ └── sample-data.csv ├── histogram │ └── histogram.html ├── button.css ├── line │ ├── line-radial.html │ └── line-radial-defined.html ├── delaunay │ └── delaunay.html ├── drag │ └── drag.html ├── marimekko │ └── marimekko.json ├── axis │ ├── axis-explicit-ticks.html │ └── axis-alternating.html ├── moire │ └── moire.html ├── area │ └── area-radial.html └── pie │ └── pie.html ├── .gitignore ├── .npmignore ├── index-browserify.js ├── lib ├── jquery-ui │ ├── images │ │ ├── ui-icons_222222_256x240.png │ │ ├── ui-icons_228ef1_256x240.png │ │ ├── ui-icons_ef8c08_256x240.png │ │ ├── ui-icons_ffd27a_256x240.png │ │ ├── ui-icons_ffffff_256x240.png │ │ ├── ui-bg_flat_10_000000_40x100.png │ │ ├── ui-bg_glass_100_f6f6f6_1x400.png │ │ ├── ui-bg_glass_100_fdf5ce_1x400.png │ │ ├── ui-bg_glass_65_ffffff_1x400.png │ │ ├── ui-bg_gloss-wave_35_f6a828_500x100.png │ │ ├── ui-bg_highlight-soft_75_ffe45c_1x100.png │ │ ├── ui-bg_diagonals-thick_18_b81900_40x40.png │ │ ├── ui-bg_diagonals-thick_20_666666_40x40.png │ │ └── ui-bg_highlight-soft_100_eeeeee_1x100.png │ └── LICENSE ├── science │ ├── science.lin.min.js │ └── science.lin.js └── jquery │ └── LICENSE ├── test ├── env-fragment.js ├── core │ ├── version-test.js │ ├── transition-test-id.js │ ├── merge-test.js │ ├── functor-test.js │ ├── selection-enter-test.js │ ├── keys-test.js │ ├── transition-test-text.js │ ├── values-test.js │ ├── zip-test.js │ ├── json-test.js │ ├── selection-order-test.js │ ├── html-test.js │ ├── transition-test-call.js │ ├── transpose-test.js │ ├── transition-test-time.js │ ├── selection-test.js │ ├── entries-test.js │ ├── selection-remove-test.js │ ├── select-test.js │ ├── ascending-test.js │ ├── text-test.js │ ├── descending-test.js │ ├── split-test.js │ └── selection-node-test.js ├── env.js ├── time │ ├── dayOfYear-test.js │ └── time.js ├── layout │ ├── pie-test.js │ ├── hierarchy-test.js │ ├── tree-test.js │ └── cluster-test.js ├── geo │ ├── path-test.js │ ├── greatArc-test.js │ └── circle-test.js └── csv │ ├── csv-test.js │ └── format-test.js ├── README.md ├── index.js ├── package.json └── LICENSE /.gitmodules: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/end.js: -------------------------------------------------------------------------------- 1 | })(); 2 | -------------------------------------------------------------------------------- /src/start.js: -------------------------------------------------------------------------------- 1 | (function(){ -------------------------------------------------------------------------------- /src/svg/svg.js: -------------------------------------------------------------------------------- 1 | d3.svg = {}; 2 | -------------------------------------------------------------------------------- /src/geom/geom.js: -------------------------------------------------------------------------------- 1 | d3.geom = {}; 2 | -------------------------------------------------------------------------------- /examples/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/behavior/behavior.js: -------------------------------------------------------------------------------- 1 | d3.behavior = {}; 2 | -------------------------------------------------------------------------------- /src/svg/mouse.js: -------------------------------------------------------------------------------- 1 | d3.svg.mouse = d3.mouse; 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | _site 2 | node_modules 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /src/svg/touches.js: -------------------------------------------------------------------------------- 1 | d3.svg.touches = d3.touches; 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | examples/ 2 | test/ 3 | lib/ 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /examples/data/sample.csv: -------------------------------------------------------------------------------- 1 | Hello,World 2 | 42,"""fish""" 3 | -------------------------------------------------------------------------------- /src/core/core.js: -------------------------------------------------------------------------------- 1 | d3 = {version: "2.9.7"}; // semver 2 | -------------------------------------------------------------------------------- /examples/data/sample.json: -------------------------------------------------------------------------------- 1 | [{"Hello":42,"World":"\"fish\""}] 2 | -------------------------------------------------------------------------------- /index-browserify.js: -------------------------------------------------------------------------------- 1 | require("./d3.v2"); 2 | module.exports = d3; -------------------------------------------------------------------------------- /src/geo/greatCircle.js: -------------------------------------------------------------------------------- 1 | d3.geo.greatCircle = d3.geo.circle; 2 | -------------------------------------------------------------------------------- /src/core/this.js: -------------------------------------------------------------------------------- 1 | function d3_this() { 2 | return this; 3 | } 4 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /examples/stream/stream.css: -------------------------------------------------------------------------------- 1 | #chart { 2 | font: 10px sans-serif; 3 | } 4 | -------------------------------------------------------------------------------- /src/geo/geo.js: -------------------------------------------------------------------------------- 1 | d3.geo = {}; 2 | 3 | var d3_geo_radians = Math.PI / 180; 4 | -------------------------------------------------------------------------------- /examples/sort/sort.css: -------------------------------------------------------------------------------- 1 | line { 2 | stroke: #000; 3 | stroke-width: 1.5px; 4 | } 5 | -------------------------------------------------------------------------------- /src/compat/date.js: -------------------------------------------------------------------------------- 1 | if (!Date.now) Date.now = function() { 2 | return +new Date; 3 | }; 4 | -------------------------------------------------------------------------------- /src/core/number.js: -------------------------------------------------------------------------------- 1 | function d3_number(x) { 2 | return x != null && !isNaN(x); 3 | } 4 | -------------------------------------------------------------------------------- /src/scale/sqrt.js: -------------------------------------------------------------------------------- 1 | d3.scale.sqrt = function() { 2 | return d3.scale.pow().exponent(.5); 3 | }; 4 | -------------------------------------------------------------------------------- /src/core/selection-empty.js: -------------------------------------------------------------------------------- 1 | d3_selectionPrototype.empty = function() { 2 | return !this.node(); 3 | }; 4 | -------------------------------------------------------------------------------- /src/core/transpose.js: -------------------------------------------------------------------------------- 1 | d3.transpose = function(matrix) { 2 | return d3.zip.apply(d3, matrix); 3 | }; 4 | -------------------------------------------------------------------------------- /src/core/merge.js: -------------------------------------------------------------------------------- 1 | d3.merge = function(arrays) { 2 | return Array.prototype.concat.apply([], arrays); 3 | }; 4 | -------------------------------------------------------------------------------- /examples/data/sample.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

Hello & world!

5 | 6 | -------------------------------------------------------------------------------- /examples/stream/stack.css: -------------------------------------------------------------------------------- 1 | #chart { 2 | font: 10px sans-serif; 3 | } 4 | 5 | line { 6 | stroke: black; 7 | } 8 | -------------------------------------------------------------------------------- /examples/data/sample.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/core/ascending.js: -------------------------------------------------------------------------------- 1 | d3.ascending = function(a, b) { 2 | return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; 3 | }; 4 | -------------------------------------------------------------------------------- /src/core/collapse.js: -------------------------------------------------------------------------------- 1 | function d3_collapse(s) { 2 | return s.replace(/^\s+|\s+$/g, "").replace(/\s+/g, " "); 3 | } 4 | -------------------------------------------------------------------------------- /src/core/descending.js: -------------------------------------------------------------------------------- 1 | d3.descending = function(a, b) { 2 | return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; 3 | }; 4 | -------------------------------------------------------------------------------- /src/core/transition-transition.js: -------------------------------------------------------------------------------- 1 | d3_transitionPrototype.transition = function() { 2 | return this.select(d3_this); 3 | }; 4 | -------------------------------------------------------------------------------- /src/core/keys.js: -------------------------------------------------------------------------------- 1 | d3.keys = function(map) { 2 | var keys = []; 3 | for (var key in map) keys.push(key); 4 | return keys; 5 | }; 6 | -------------------------------------------------------------------------------- /examples/bubble/bubble.css: -------------------------------------------------------------------------------- 1 | circle { 2 | stroke: #fff; 3 | stroke-width: 1.5px; 4 | } 5 | 6 | text { 7 | font: 10px sans-serif; 8 | } 9 | -------------------------------------------------------------------------------- /lib/jquery-ui/images/ui-icons_222222_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/html/d3/master/lib/jquery-ui/images/ui-icons_222222_256x240.png -------------------------------------------------------------------------------- /lib/jquery-ui/images/ui-icons_228ef1_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/html/d3/master/lib/jquery-ui/images/ui-icons_228ef1_256x240.png -------------------------------------------------------------------------------- /lib/jquery-ui/images/ui-icons_ef8c08_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/html/d3/master/lib/jquery-ui/images/ui-icons_ef8c08_256x240.png -------------------------------------------------------------------------------- /lib/jquery-ui/images/ui-icons_ffd27a_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/html/d3/master/lib/jquery-ui/images/ui-icons_ffd27a_256x240.png -------------------------------------------------------------------------------- /lib/jquery-ui/images/ui-icons_ffffff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/html/d3/master/lib/jquery-ui/images/ui-icons_ffffff_256x240.png -------------------------------------------------------------------------------- /lib/jquery-ui/images/ui-bg_flat_10_000000_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/html/d3/master/lib/jquery-ui/images/ui-bg_flat_10_000000_40x100.png -------------------------------------------------------------------------------- /lib/jquery-ui/images/ui-bg_glass_100_f6f6f6_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/html/d3/master/lib/jquery-ui/images/ui-bg_glass_100_f6f6f6_1x400.png -------------------------------------------------------------------------------- /lib/jquery-ui/images/ui-bg_glass_100_fdf5ce_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/html/d3/master/lib/jquery-ui/images/ui-bg_glass_100_fdf5ce_1x400.png -------------------------------------------------------------------------------- /lib/jquery-ui/images/ui-bg_glass_65_ffffff_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/html/d3/master/lib/jquery-ui/images/ui-bg_glass_65_ffffff_1x400.png -------------------------------------------------------------------------------- /src/core/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 | -------------------------------------------------------------------------------- /src/core/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/functor.js: -------------------------------------------------------------------------------- 1 | function d3_functor(v) { 2 | return typeof v === "function" ? v : function() { return v; }; 3 | } 4 | 5 | d3.functor = d3_functor; 6 | -------------------------------------------------------------------------------- /examples/kde/kde.css: -------------------------------------------------------------------------------- 1 | body { 2 | font: 10px sans-serif; 3 | } 4 | 5 | path { 6 | stroke: #000; 7 | stroke-width: 1.5px; 8 | fill: none; 9 | } 10 | -------------------------------------------------------------------------------- /lib/jquery-ui/images/ui-bg_gloss-wave_35_f6a828_500x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/html/d3/master/lib/jquery-ui/images/ui-bg_gloss-wave_35_f6a828_500x100.png -------------------------------------------------------------------------------- /examples/cartogram/demers.css: -------------------------------------------------------------------------------- 1 | #chart { 2 | width: 960px; 3 | height: 500px; 4 | } 5 | 6 | rect { 7 | stroke: #000; 8 | stroke-width: .5px; 9 | } 10 | -------------------------------------------------------------------------------- /lib/jquery-ui/images/ui-bg_highlight-soft_75_ffe45c_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/html/d3/master/lib/jquery-ui/images/ui-bg_highlight-soft_75_ffe45c_1x100.png -------------------------------------------------------------------------------- /src/core/requote.js: -------------------------------------------------------------------------------- 1 | d3.requote = function(s) { 2 | return s.replace(d3_requote_re, "\\$&"); 3 | }; 4 | 5 | var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; 6 | -------------------------------------------------------------------------------- /src/csv/csv.js: -------------------------------------------------------------------------------- 1 | d3.csv = function(url, callback) { 2 | d3.text(url, "text/csv", function(text) { 3 | callback(text && d3.csv.parse(text)); 4 | }); 5 | }; 6 | -------------------------------------------------------------------------------- /examples/cartogram/dorling.css: -------------------------------------------------------------------------------- 1 | #chart { 2 | width: 960px; 3 | height: 500px; 4 | } 5 | 6 | circle { 7 | stroke: #000; 8 | stroke-width: .5px; 9 | } 10 | -------------------------------------------------------------------------------- /examples/horizon/horizon.css: -------------------------------------------------------------------------------- 1 | #controls { 2 | position: relative; 3 | width: 960px; 4 | } 5 | 6 | #bands { 7 | position: absolute; 8 | right: 0; 9 | } 10 | -------------------------------------------------------------------------------- /lib/jquery-ui/images/ui-bg_diagonals-thick_18_b81900_40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/html/d3/master/lib/jquery-ui/images/ui-bg_diagonals-thick_18_b81900_40x40.png -------------------------------------------------------------------------------- /lib/jquery-ui/images/ui-bg_diagonals-thick_20_666666_40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/html/d3/master/lib/jquery-ui/images/ui-bg_diagonals-thick_20_666666_40x40.png -------------------------------------------------------------------------------- /lib/jquery-ui/images/ui-bg_highlight-soft_100_eeeeee_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/html/d3/master/lib/jquery-ui/images/ui-bg_highlight-soft_100_eeeeee_1x100.png -------------------------------------------------------------------------------- /examples/force/force.css: -------------------------------------------------------------------------------- 1 | circle.node { 2 | stroke: #fff; 3 | stroke-width: 1.5px; 4 | } 5 | 6 | line.link { 7 | stroke: #999; 8 | stroke-opacity: .6; 9 | } 10 | -------------------------------------------------------------------------------- /src/core/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 | -------------------------------------------------------------------------------- /examples/bundle/bundle-radial.css: -------------------------------------------------------------------------------- 1 | .node { 2 | font: 10px sans-serif; 3 | } 4 | 5 | .link { 6 | stroke: steelblue; 7 | stroke-opacity: .4; 8 | fill: none; 9 | } 10 | -------------------------------------------------------------------------------- /examples/chord/chord.css: -------------------------------------------------------------------------------- 1 | #chart { 2 | font: 10px sans-serif; 3 | } 4 | 5 | .chord path { 6 | fill-opacity: .67; 7 | stroke: #000; 8 | stroke-width: .5px; 9 | } 10 | -------------------------------------------------------------------------------- /src/core/json.js: -------------------------------------------------------------------------------- 1 | d3.json = function(url, callback) { 2 | d3.text(url, "application/json", function(text) { 3 | callback(text ? JSON.parse(text) : null); 4 | }); 5 | }; 6 | -------------------------------------------------------------------------------- /examples/treemap/treemap.css: -------------------------------------------------------------------------------- 1 | .cell { 2 | border: solid 1px white; 3 | font: 10px sans-serif; 4 | line-height: 12px; 5 | overflow: hidden; 6 | position: absolute; 7 | text-indent: 2px; 8 | } 9 | -------------------------------------------------------------------------------- /src/geo/type.js: -------------------------------------------------------------------------------- 1 | function d3_geo_type(types, defaultValue) { 2 | return function(object) { 3 | return object && types.hasOwnProperty(object.type) ? types[object.type](object) : defaultValue; 4 | }; 5 | } 6 | -------------------------------------------------------------------------------- /src/core/permute.js: -------------------------------------------------------------------------------- 1 | d3.permute = function(array, indexes) { 2 | var permutes = [], 3 | i = -1, 4 | n = indexes.length; 5 | while (++i < n) permutes[i] = array[indexes[i]]; 6 | return permutes; 7 | }; 8 | -------------------------------------------------------------------------------- /examples/box/box.css: -------------------------------------------------------------------------------- 1 | .box { font: 10px sans-serif; } 2 | .box line, .box rect, .box circle { stroke: #000; stroke-width: 1.5px; fill: #fff; } 3 | .box .center { stroke-dasharray: 3 3; } 4 | .box .outlier { stroke: #ccc; fill: none; } 5 | -------------------------------------------------------------------------------- /src/core/median.js: -------------------------------------------------------------------------------- 1 | d3.median = function(array, f) { 2 | if (arguments.length > 1) array = array.map(f); 3 | array = array.filter(d3_number); 4 | return array.length ? d3.quantile(array.sort(d3.ascending), .5) : undefined; 5 | }; 6 | -------------------------------------------------------------------------------- /src/core/selection-datum.js: -------------------------------------------------------------------------------- 1 | d3_selectionPrototype.datum = 2 | d3_selectionPrototype.map = function(value) { 3 | return arguments.length < 1 4 | ? this.property("__data__") 5 | : this.property("__data__", value); 6 | }; 7 | -------------------------------------------------------------------------------- /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/core/transition-remove.js: -------------------------------------------------------------------------------- 1 | d3_transitionPrototype.remove = function() { 2 | return this.each("end.transition", function() { 3 | var p; 4 | if (!this.__transition__ && (p = this.parentNode)) p.removeChild(this); 5 | }); 6 | }; 7 | -------------------------------------------------------------------------------- /test/env-fragment.js: -------------------------------------------------------------------------------- 1 | var jsdom = require("jsdom"); 2 | 3 | document.createRange = function() { 4 | return { 5 | selectNode: function() {}, 6 | createContextualFragment: function(html) { return jsdom.jsdom(html); } 7 | }; 8 | }; 9 | -------------------------------------------------------------------------------- /src/core/transition-text.js: -------------------------------------------------------------------------------- 1 | d3_transitionPrototype.text = function(value) { 2 | return this.tween("text", function(d, i) { 3 | this.textContent = typeof value === "function" 4 | ? value.call(this, d, i) 5 | : value; 6 | }); 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 | -------------------------------------------------------------------------------- /examples/tree/tree.css: -------------------------------------------------------------------------------- 1 | .node circle { 2 | fill: #fff; 3 | stroke: steelblue; 4 | stroke-width: 1.5px; 5 | } 6 | 7 | .node { 8 | font: 10px sans-serif; 9 | } 10 | 11 | .link { 12 | fill: none; 13 | stroke: #ccc; 14 | stroke-width: 1.5px; 15 | } 16 | -------------------------------------------------------------------------------- /examples/voroboids/voroboids.css: -------------------------------------------------------------------------------- 1 | svg { 2 | display: block; 3 | border: solid 1px #666; 4 | overflow: hidden; 5 | } 6 | 7 | path { 8 | stroke: #000; 9 | stroke-width: .5px; 10 | } 11 | 12 | circle { 13 | fill: none; 14 | stroke: #fff; 15 | } 16 | -------------------------------------------------------------------------------- /examples/calendar/calendar.css: -------------------------------------------------------------------------------- 1 | #chart { 2 | font: 10px sans-serif; 3 | shape-rendering: crispEdges; 4 | } 5 | 6 | .day { 7 | fill: #fff; 8 | stroke: #ccc; 9 | } 10 | 11 | .month { 12 | fill: none; 13 | stroke: #000; 14 | stroke-width: 2px; 15 | } 16 | -------------------------------------------------------------------------------- /src/core/xml.js: -------------------------------------------------------------------------------- 1 | d3.xml = function(url, mime, callback) { 2 | function ready(req) { 3 | callback(req && req.responseXML); 4 | } 5 | if (arguments.length < 3) { 6 | callback = mime; 7 | mime = null; 8 | } 9 | d3.xhr(url, mime, ready); 10 | }; 11 | -------------------------------------------------------------------------------- /examples/cluster/cluster.css: -------------------------------------------------------------------------------- 1 | .node circle { 2 | fill: #fff; 3 | stroke: steelblue; 4 | stroke-width: 1.5px; 5 | } 6 | 7 | .node { 8 | font: 10px sans-serif; 9 | } 10 | 11 | .link { 12 | fill: none; 13 | stroke: #ccc; 14 | stroke-width: 1.5px; 15 | } 16 | -------------------------------------------------------------------------------- /src/core/text.js: -------------------------------------------------------------------------------- 1 | d3.text = function(url, mime, callback) { 2 | function ready(req) { 3 | callback(req && req.responseText); 4 | } 5 | if (arguments.length < 3) { 6 | callback = mime; 7 | mime = null; 8 | } 9 | d3.xhr(url, mime, ready); 10 | }; 11 | -------------------------------------------------------------------------------- /examples/voronoi/voronoi.css: -------------------------------------------------------------------------------- 1 | svg { 2 | border: solid 1px #666; 3 | overflow: hidden; 4 | } 5 | 6 | path { 7 | fill: yellow; 8 | stroke: #000; 9 | stroke-width: .5px; 10 | } 11 | 12 | circle { 13 | fill: #ccc; 14 | stroke: #000; 15 | pointer-events: none; 16 | } 17 | -------------------------------------------------------------------------------- /src/core/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 | -------------------------------------------------------------------------------- /examples/pack/pack.css: -------------------------------------------------------------------------------- 1 | circle { 2 | fill: rgb(31, 119, 180); 3 | fill-opacity: .25; 4 | stroke: rgb(31, 119, 180); 5 | stroke-width: 1px; 6 | } 7 | 8 | .leaf circle { 9 | fill: #ff7f0e; 10 | fill-opacity: 1; 11 | } 12 | 13 | text { 14 | font: 10px sans-serif; 15 | } 16 | -------------------------------------------------------------------------------- /examples/choropleth/choropleth.css: -------------------------------------------------------------------------------- 1 | svg { 2 | background: #eee; 3 | width: 960px; 4 | height: 500px; 5 | } 6 | 7 | #counties path { 8 | stroke: #fff; 9 | stroke-width: .25px; 10 | } 11 | 12 | #states path { 13 | fill: none; 14 | stroke: #fff; 15 | stroke-width: 1.5px; 16 | } 17 | -------------------------------------------------------------------------------- /examples/bundle/bundle-treemap.css: -------------------------------------------------------------------------------- 1 | .cell { 2 | border: solid 1px white; 3 | font: 10px sans-serif; 4 | line-height: 12px; 5 | overflow: hidden; 6 | position: absolute; 7 | text-indent: 2px; 8 | } 9 | 10 | .link { 11 | stroke: #000; 12 | stroke-opacity: .5; 13 | fill: none; 14 | } 15 | -------------------------------------------------------------------------------- /src/core/selection-remove.js: -------------------------------------------------------------------------------- 1 | // TODO remove(selector)? 2 | // TODO remove(node)? 3 | // TODO remove(function)? 4 | d3_selectionPrototype.remove = function() { 5 | return this.each(function() { 6 | var parent = this.parentNode; 7 | if (parent) parent.removeChild(this); 8 | }); 9 | }; 10 | -------------------------------------------------------------------------------- /src/core/selection-node.js: -------------------------------------------------------------------------------- 1 | d3_selectionPrototype.node = function(callback) { 2 | for (var j = 0, m = this.length; j < m; j++) { 3 | for (var group = this[j], i = 0, n = group.length; i < n; i++) { 4 | var node = group[i]; 5 | if (node) return node; 6 | } 7 | } 8 | return null; 9 | }; 10 | -------------------------------------------------------------------------------- /src/core/first.js: -------------------------------------------------------------------------------- 1 | d3.first = function(array, f) { 2 | var i = 0, 3 | n = array.length, 4 | a = array[0], 5 | b; 6 | if (arguments.length === 1) f = d3.ascending; 7 | while (++i < n) { 8 | if (f.call(array, a, b = array[i]) > 0) { 9 | a = b; 10 | } 11 | } 12 | return a; 13 | }; 14 | -------------------------------------------------------------------------------- /src/core/last.js: -------------------------------------------------------------------------------- 1 | d3.last = function(array, f) { 2 | var i = 0, 3 | n = array.length, 4 | a = array[0], 5 | b; 6 | if (arguments.length === 1) f = d3.ascending; 7 | while (++i < n) { 8 | if (f.call(array, a, b = array[i]) <= 0) { 9 | a = b; 10 | } 11 | } 12 | return a; 13 | }; 14 | -------------------------------------------------------------------------------- /src/core/transition-delay.js: -------------------------------------------------------------------------------- 1 | d3_transitionPrototype.delay = function(value) { 2 | return d3_selection_each(this, typeof value === "function" 3 | ? function(node, i, j) { node.delay = value.call(node = node.node, node.__data__, i, j) | 0; } 4 | : (value = value | 0, function(node) { node.delay = value; })); 5 | }; 6 | -------------------------------------------------------------------------------- /examples/cartogram/cartogram.css: -------------------------------------------------------------------------------- 1 | #chart { 2 | width: 960px; 3 | height: 500px; 4 | } 5 | 6 | .black path { 7 | fill: none; 8 | stroke: #ccc; 9 | stroke-width: 3px; 10 | } 11 | 12 | .white path { 13 | fill: #fff; 14 | stroke: #fff; 15 | } 16 | 17 | .grey path { 18 | fill: #ccc; 19 | stroke: #666; 20 | } 21 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /examples/qq/qq.css: -------------------------------------------------------------------------------- 1 | #chart { 2 | font: 10px sans-serif; 3 | width: 960px; 4 | height: 310px; 5 | } 6 | 7 | .qq .box, .qq .tick line, .qq .quantile, .qq .diagonal { 8 | stroke: #aaa; 9 | fill: none; 10 | } 11 | 12 | .qq .quantile { 13 | stroke: #000; 14 | } 15 | 16 | .qq g + g .y.tick { 17 | display: none; 18 | } 19 | -------------------------------------------------------------------------------- /src/core/touches.js: -------------------------------------------------------------------------------- 1 | d3.touches = function(container, touches) { 2 | if (arguments.length < 2) touches = d3_eventSource().touches; 3 | return touches ? d3_array(touches).map(function(touch) { 4 | var point = d3_mousePoint(container, touch); 5 | point.identifier = touch.identifier; 6 | return point; 7 | }) : []; 8 | }; 9 | -------------------------------------------------------------------------------- /src/core/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/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/core/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 | -------------------------------------------------------------------------------- /src/core/transition-duration.js: -------------------------------------------------------------------------------- 1 | d3_transitionPrototype.duration = function(value) { 2 | return d3_selection_each(this, typeof value === "function" 3 | ? function(node, i, j) { node.duration = Math.max(1, value.call(node = node.node, node.__data__, i, j) | 0); } 4 | : (value = Math.max(1, value | 0), function(node) { node.duration = value; })); 5 | }; 6 | -------------------------------------------------------------------------------- /src/core/html.js: -------------------------------------------------------------------------------- 1 | d3.html = function(url, callback) { 2 | d3.text(url, "text/html", function(text) { 3 | if (text != null) { // Treat empty string as valid HTML. 4 | var range = document.createRange(); 5 | range.selectNode(document.body); 6 | text = range.createContextualFragment(text); 7 | } 8 | callback(text); 9 | }); 10 | }; 11 | -------------------------------------------------------------------------------- /src/csv/format.js: -------------------------------------------------------------------------------- 1 | d3.csv.format = function(rows) { 2 | return rows.map(d3_csv_formatRow).join("\n"); 3 | }; 4 | 5 | function d3_csv_formatRow(row) { 6 | return row.map(d3_csv_formatValue).join(","); 7 | } 8 | 9 | function d3_csv_formatValue(text) { 10 | return /[",\n]/.test(text) 11 | ? "\"" + text.replace(/\"/g, "\"\"") + "\"" 12 | : text; 13 | } 14 | -------------------------------------------------------------------------------- /examples/azimuthal/azimuthal.css: -------------------------------------------------------------------------------- 1 | @import url("../../lib/jquery-ui/jquery-ui.css"); 2 | 3 | body, .ui-widget { 4 | font: 14px Helvetica Neue; 5 | } 6 | 7 | svg { 8 | width: 960px; 9 | height: 500px; 10 | border: solid 1px #ccc; 11 | background: #eee; 12 | } 13 | 14 | path { 15 | fill: #ccc; 16 | stroke: #fff; 17 | } 18 | 19 | div { 20 | width: 960px; 21 | } 22 | -------------------------------------------------------------------------------- /examples/sort/sort.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Merge Sort 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/time/month.js: -------------------------------------------------------------------------------- 1 | d3.time.month = d3_time_interval(function(date) { 2 | date = d3.time.day(date); 3 | date.setDate(1); 4 | return date; 5 | }, function(date, offset) { 6 | date.setMonth(date.getMonth() + offset); 7 | }, function(date) { 8 | return date.getMonth(); 9 | }); 10 | 11 | d3.time.months = d3.time.month.range; 12 | d3.time.months.utc = d3.time.month.utc.range; 13 | -------------------------------------------------------------------------------- /src/time/year.js: -------------------------------------------------------------------------------- 1 | d3.time.year = d3_time_interval(function(date) { 2 | date = d3.time.day(date); 3 | date.setMonth(0, 1); 4 | return date; 5 | }, function(date, offset) { 6 | date.setFullYear(date.getFullYear() + offset); 7 | }, function(date) { 8 | return date.getFullYear(); 9 | }); 10 | 11 | d3.time.years = d3.time.year.range; 12 | d3.time.years.utc = d3.time.year.utc.range; 13 | -------------------------------------------------------------------------------- /examples/force/force.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Force-Directed Layout 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/core/selection-html.js: -------------------------------------------------------------------------------- 1 | d3_selectionPrototype.html = function(value) { 2 | return arguments.length < 1 3 | ? this.node().innerHTML : this.each(typeof value === "function" 4 | ? function() { var v = value.apply(this, arguments); this.innerHTML = v == null ? "" : v; } : value == null 5 | ? function() { this.innerHTML = ""; } 6 | : function() { this.innerHTML = value; }); 7 | }; 8 | -------------------------------------------------------------------------------- /src/core/zip.js: -------------------------------------------------------------------------------- 1 | d3.zip = function() { 2 | if (!(n = arguments.length)) return []; 3 | for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m;) { 4 | for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n;) { 5 | zip[j] = arguments[j][i]; 6 | } 7 | } 8 | return zips; 9 | }; 10 | 11 | function d3_zipLength(d) { 12 | return d.length; 13 | } 14 | -------------------------------------------------------------------------------- /src/compat/style.js: -------------------------------------------------------------------------------- 1 | try { 2 | document.createElement("div").style.setProperty("opacity", 0, ""); 3 | } catch (error) { 4 | var d3_style_prototype = CSSStyleDeclaration.prototype, 5 | d3_style_setProperty = d3_style_prototype.setProperty; 6 | d3_style_prototype.setProperty = function(name, value, priority) { 7 | d3_style_setProperty.call(this, name, value + "", priority); 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /examples/clock/clock.css: -------------------------------------------------------------------------------- 1 | #clock { 2 | position: relative; 3 | background: #222; 4 | width: 960px; 5 | height: 700px; 6 | } 7 | 8 | #clock div { 9 | position: absolute; 10 | right: 4px; 11 | bottom: 4px; 12 | color: #ddd; 13 | font: 10px sans-serif; 14 | } 15 | 16 | #clock a { 17 | color: #fff; 18 | font-weight: bold; 19 | } 20 | 21 | text { 22 | font: bold 13px sans-serif; 23 | } 24 | -------------------------------------------------------------------------------- /src/core/mean.js: -------------------------------------------------------------------------------- 1 | d3.mean = function(array, f) { 2 | var n = array.length, 3 | a, 4 | m = 0, 5 | i = -1, 6 | j = 0; 7 | if (arguments.length === 1) { 8 | while (++i < n) if (d3_number(a = array[i])) m += (a - m) / ++j; 9 | } else { 10 | while (++i < n) if (d3_number(a = f.call(array, array[i], i))) m += (a - m) / ++j; 11 | } 12 | return j ? m : undefined; 13 | }; 14 | -------------------------------------------------------------------------------- /src/core/selection-text.js: -------------------------------------------------------------------------------- 1 | d3_selectionPrototype.text = function(value) { 2 | return arguments.length < 1 3 | ? this.node().textContent : this.each(typeof value === "function" 4 | ? function() { var v = value.apply(this, arguments); this.textContent = v == null ? "" : v; } : value == null 5 | ? function() { this.textContent = ""; } 6 | : function() { this.textContent = value; }); 7 | }; 8 | -------------------------------------------------------------------------------- /examples/population/population.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | U.S. Population 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/svg/area-radial.js: -------------------------------------------------------------------------------- 1 | d3.svg.area.radial = function() { 2 | var area = d3_svg_area(d3_svg_lineRadial); 3 | area.radius = area.x, delete area.x; 4 | area.innerRadius = area.x0, delete area.x0; 5 | area.outerRadius = area.x1, delete area.x1; 6 | area.angle = area.y, delete area.y; 7 | area.startAngle = area.y0, delete area.y0; 8 | area.endAngle = area.y1, delete area.y1; 9 | return area; 10 | }; 11 | -------------------------------------------------------------------------------- /src/time/minute.js: -------------------------------------------------------------------------------- 1 | d3.time.minute = d3_time_interval(function(date) { 2 | return new d3_time(Math.floor(date / 6e4) * 6e4); 3 | }, function(date, offset) { 4 | date.setTime(date.getTime() + Math.floor(offset) * 6e4); // DST breaks setMinutes 5 | }, function(date) { 6 | return date.getMinutes(); 7 | }); 8 | 9 | d3.time.minutes = d3.time.minute.range; 10 | d3.time.minutes.utc = d3.time.minute.utc.range; 11 | -------------------------------------------------------------------------------- /src/time/second.js: -------------------------------------------------------------------------------- 1 | d3.time.second = d3_time_interval(function(date) { 2 | return new d3_time(Math.floor(date / 1e3) * 1e3); 3 | }, function(date, offset) { 4 | date.setTime(date.getTime() + Math.floor(offset) * 1e3); // DST breaks setSeconds 5 | }, function(date) { 6 | return date.getSeconds(); 7 | }); 8 | 9 | d3.time.seconds = d3.time.second.range; 10 | d3.time.seconds.utc = d3.time.second.utc.range; 11 | -------------------------------------------------------------------------------- /src/core/selection-order.js: -------------------------------------------------------------------------------- 1 | d3_selectionPrototype.order = function() { 2 | for (var j = -1, m = this.length; ++j < m;) { 3 | for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0;) { 4 | if (node = group[i]) { 5 | if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next); 6 | next = node; 7 | } 8 | } 9 | } 10 | return this; 11 | }; 12 | -------------------------------------------------------------------------------- /test/core/version-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("d3.version"); 7 | 8 | suite.addBatch({ 9 | "semantic versioning": { 10 | topic: d3.version, 11 | "has the form major.minor.patch": function(version) { 12 | assert.match(version, /^[0-9]+\.[0-9]+\.[0-9]+$/); 13 | } 14 | } 15 | }); 16 | 17 | suite.export(module); 18 | -------------------------------------------------------------------------------- /examples/treemap/treemap-svg.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /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.](/mbostock/d3/wiki) 6 | -------------------------------------------------------------------------------- /examples/pack/pack.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Circle Packing 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/tree/tree.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Node-Link Tree 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/voroboids/voroboids.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Voroboids 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/env.js: -------------------------------------------------------------------------------- 1 | document = require("jsdom").jsdom(""); 2 | window = document.createWindow(); 3 | navigator = window.navigator; 4 | CSSStyleDeclaration = window.CSSStyleDeclaration; 5 | 6 | require("../lib/sizzle/sizzle"); 7 | Sizzle = window.Sizzle; 8 | 9 | process.env.TZ = "America/Los_Angeles"; 10 | 11 | require("./env-assert"); 12 | require("./env-xhr"); 13 | require("./env-fragment"); 14 | 15 | require("../d3.v2"); 16 | -------------------------------------------------------------------------------- /examples/bubble/bubble.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Bubble Chart 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/chord/chord.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Chord Diagram 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/splom/splom.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Scatterplot Matrix 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/calendar/dji.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | DJI 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/calendar/vix.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | VIX 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/cartogram/demers.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Demers Cartogram 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/cartogram/dorling.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Dorling Cartogram 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/cluster/cluster.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Flare Dendrogram 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/time/hour.js: -------------------------------------------------------------------------------- 1 | d3.time.hour = d3_time_interval(function(date) { 2 | var timezone = date.getTimezoneOffset() / 60; 3 | return new d3_time((Math.floor(date / 36e5 - timezone) + timezone) * 36e5); 4 | }, function(date, offset) { 5 | date.setTime(date.getTime() + Math.floor(offset) * 36e5); // DST breaks setHours 6 | }, function(date) { 7 | return date.getHours(); 8 | }); 9 | 10 | d3.time.hours = d3.time.hour.range; 11 | d3.time.hours.utc = d3.time.hour.utc.range; 12 | -------------------------------------------------------------------------------- /src/core/random.js: -------------------------------------------------------------------------------- 1 | d3.random = { 2 | normal: function(mean, deviation) { 3 | if (arguments.length < 2) deviation = 1; 4 | if (arguments.length < 1) mean = 0; 5 | return function() { 6 | var x, y, r; 7 | do { 8 | x = Math.random() * 2 - 1; 9 | y = Math.random() * 2 - 1; 10 | r = x * x + y * y; 11 | } while (!r || r > 1); 12 | return mean + deviation * x * Math.sqrt(-2 * Math.log(r) / r); 13 | }; 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /src/core/selection-sort.js: -------------------------------------------------------------------------------- 1 | d3_selectionPrototype.sort = function(comparator) { 2 | comparator = d3_selection_sortComparator.apply(this, arguments); 3 | for (var j = -1, m = this.length; ++j < m;) this[j].sort(comparator); 4 | return this.order(); 5 | }; 6 | 7 | function d3_selection_sortComparator(comparator) { 8 | if (!arguments.length) comparator = d3.ascending; 9 | return function(a, b) { 10 | return comparator(a && a.__data__, b && b.__data__); 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /examples/bullet/bullet.css: -------------------------------------------------------------------------------- 1 | .bullet { font: 10px sans-serif; } 2 | .bullet .marker { stroke: #000; stroke-width: 2px; } 3 | .bullet .tick line { stroke: #666; stroke-width: .5px; } 4 | .bullet .range.s0 { fill: #eee; } 5 | .bullet .range.s1 { fill: #ddd; } 6 | .bullet .range.s2 { fill: #ccc; } 7 | .bullet .measure.s0 { fill: lightsteelblue; } 8 | .bullet .measure.s1 { fill: steelblue; } 9 | .bullet .title { font-size: 14px; font-weight: bold; } 10 | .bullet .subtitle { fill: #999; } 11 | -------------------------------------------------------------------------------- /examples/tree/tree-radial.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Node-Link Tree (Radial) 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/core/selection-append.js: -------------------------------------------------------------------------------- 1 | // TODO append(node)? 2 | // TODO append(function)? 3 | d3_selectionPrototype.append = function(name) { 4 | name = d3.ns.qualify(name); 5 | 6 | function append() { 7 | return this.appendChild(document.createElementNS(this.namespaceURI, name)); 8 | } 9 | 10 | function appendNS() { 11 | return this.appendChild(document.createElementNS(name.space, name.local)); 12 | } 13 | 14 | return this.select(name.local ? appendNS : append); 15 | }; 16 | -------------------------------------------------------------------------------- /examples/cartogram/cartogram.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Non-Contiguous Cartogram 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/cluster/cluster-radial.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Flare Dendrogram 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/population/population.css: -------------------------------------------------------------------------------- 1 | svg { 2 | font: 10px sans-serif; 3 | } 4 | 5 | text.title { 6 | font: 300 78px Helvetica Neue; 7 | fill: #666; 8 | } 9 | 10 | .rule line { 11 | stroke: #fff; 12 | stroke-opacity: .2; 13 | shape-rendering: crispEdges; 14 | } 15 | 16 | .rule:first-child line { 17 | stroke: #000; 18 | stroke-opacity: 1; 19 | } 20 | 21 | rect { 22 | fill-opacity: .6; 23 | fill: #e377c2; 24 | } 25 | 26 | rect:first-child { 27 | fill: #1f77b4; 28 | } 29 | -------------------------------------------------------------------------------- /examples/spline/spline.css: -------------------------------------------------------------------------------- 1 | body { 2 | font: 13px sans-serif; 3 | } 4 | 5 | #chart svg { 6 | width: 960px; 7 | height: 500px; 8 | border: solid 1px #ccc; 9 | } 10 | 11 | rect { 12 | fill: #fff; 13 | } 14 | 15 | circle, .line { 16 | fill: none; 17 | stroke: steelblue; 18 | stroke-width: 1.5px; 19 | } 20 | 21 | circle { 22 | fill: #fff; 23 | fill-opacity: .2; 24 | cursor: move; 25 | } 26 | 27 | circle.selected { 28 | fill: #ff7f0e; 29 | stroke: #ff7f0e; 30 | } 31 | -------------------------------------------------------------------------------- /examples/spline/spline.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Spline Editor 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/core/selection-each.js: -------------------------------------------------------------------------------- 1 | d3_selectionPrototype.each = function(callback) { 2 | return d3_selection_each(this, function(node, i, j) { 3 | callback.call(node, node.__data__, i, j); 4 | }); 5 | }; 6 | 7 | function d3_selection_each(groups, callback) { 8 | for (var j = 0, m = groups.length; j < m; j++) { 9 | for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) { 10 | if (node = group[i]) callback(node, i, j); 11 | } 12 | } 13 | return groups; 14 | } 15 | -------------------------------------------------------------------------------- /src/time/format-iso.js: -------------------------------------------------------------------------------- 1 | var d3_time_formatIso = d3.time.format.utc("%Y-%m-%dT%H:%M:%S.%LZ"); 2 | 3 | d3.time.format.iso = Date.prototype.toISOString ? d3_time_formatIsoNative : d3_time_formatIso; 4 | 5 | function d3_time_formatIsoNative(date) { 6 | return date.toISOString(); 7 | } 8 | 9 | d3_time_formatIsoNative.parse = function(string) { 10 | var date = new Date(string); 11 | return isNaN(date) ? null : date; 12 | }; 13 | 14 | d3_time_formatIsoNative.toString = d3_time_formatIso.toString; 15 | -------------------------------------------------------------------------------- /examples/clock/clock.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Polar Clock 5 | 6 | 7 | 8 | 9 |
10 |
11 | Inspired by pixelbreaker. 12 |
13 |
14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/core/split.js: -------------------------------------------------------------------------------- 1 | d3.split = function(array, f) { 2 | var arrays = [], 3 | values = [], 4 | value, 5 | i = -1, 6 | n = array.length; 7 | if (arguments.length < 2) f = d3_splitter; 8 | while (++i < n) { 9 | if (f.call(values, value = array[i], i)) { 10 | values = []; 11 | } else { 12 | if (!values.length) arrays.push(values); 13 | values.push(value); 14 | } 15 | } 16 | return arrays; 17 | }; 18 | 19 | function d3_splitter(d) { 20 | return d == null; 21 | } 22 | -------------------------------------------------------------------------------- /src/core/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/core/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/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 | if (dx = x1 - x0) { 14 | nice = nice(dx); 15 | domain[i0] = nice.floor(x0); 16 | domain[i1] = nice.ceil(x1); 17 | } 18 | 19 | return domain; 20 | } 21 | 22 | function d3_scale_niceDefault() { 23 | return Math; 24 | } 25 | -------------------------------------------------------------------------------- /examples/kde/kde.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Kernel Density Estimation 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/hello-world/selectAll-enter-add.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Test - selectAll > enter > append 5 | 6 | 7 | 8 | 9 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/core/selection-call.js: -------------------------------------------------------------------------------- 1 | // 2 | // Note: assigning to the arguments array simultaneously changes the value of 3 | // the corresponding argument! 4 | // 5 | // TODO The `this` argument probably shouldn't be the first argument to the 6 | // callback, anyway, since it's redundant. However, that will require a major 7 | // version bump due to backwards compatibility, so I'm not changing it right 8 | // away. 9 | // 10 | d3_selectionPrototype.call = function(callback) { 11 | callback.apply(this, (arguments[0] = this, arguments)); 12 | return this; 13 | }; 14 | -------------------------------------------------------------------------------- /src/core/selection-transition.js: -------------------------------------------------------------------------------- 1 | d3_selectionPrototype.transition = function() { 2 | var subgroups = [], 3 | subgroup, 4 | node; 5 | 6 | for (var j = -1, m = this.length; ++j < m;) { 7 | subgroups.push(subgroup = []); 8 | for (var group = this[j], i = -1, n = group.length; ++i < n;) { 9 | subgroup.push((node = group[i]) ? {node: node, delay: d3_transitionDelay, duration: d3_transitionDuration} : null); 10 | } 11 | } 12 | 13 | return d3_transition(subgroups, d3_transitionId || ++d3_transitionNextId, Date.now()); 14 | }; 15 | -------------------------------------------------------------------------------- /src/core/xhr.js: -------------------------------------------------------------------------------- 1 | d3.xhr = function(url, mime, callback) { 2 | var req = new XMLHttpRequest; 3 | if (arguments.length < 3) callback = mime, mime = null; 4 | else if (mime && req.overrideMimeType) req.overrideMimeType(mime); 5 | req.open("GET", url, true); 6 | if (mime) req.setRequestHeader("Accept", mime); 7 | req.onreadystatechange = function() { 8 | if (req.readyState === 4) { 9 | var s = req.status; 10 | callback(!s && req.response || s >= 200 && s < 300 || s === 304 ? req : null); 11 | } 12 | }; 13 | req.send(null); 14 | }; 15 | -------------------------------------------------------------------------------- /examples/box/box.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Box Plot Charts 5 | 6 | 7 | 8 | 9 | 10 |
11 |

14 |

15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/voronoi/voronoi.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Voronoi Tesselation 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/bullet/bullet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Bullet Charts 5 | 6 | 7 | 8 | 9 | 10 |
11 |

14 |

15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /test/time/dayOfYear-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"), 5 | time = require("./time"), 6 | local = time.local, 7 | utc = time.utc; 8 | 9 | var suite = vows.describe("d3.time.dayOfYear"); 10 | 11 | suite.addBatch({ 12 | "dayOfYear": { 13 | topic: function() { 14 | return d3.time.dayOfYear; 15 | }, 16 | "no floating-point rounding error": function(dayOfYear) { 17 | assert.equal(dayOfYear(new Date(2011, 4, 9)), 128); 18 | } 19 | } 20 | }); 21 | 22 | suite.export(module); 23 | -------------------------------------------------------------------------------- /examples/bullet/bullets.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"title":"Revenue","subtitle":"US$, in thousands","ranges":[150,225,300],"measures":[220,270],"markers":[250]}, 3 | {"title":"Profit","subtitle":"%","ranges":[20,25,30],"measures":[21,23],"markers":[26]}, 4 | {"title":"Order Size","subtitle":"US$, average","ranges":[350,500,600],"measures":[100,320],"markers":[550]}, 5 | {"title":"New Customers","subtitle":"count","ranges":[1400,2000,2500],"measures":[1000,1650],"markers":[2100]}, 6 | {"title":"Satisfaction","subtitle":"out of 5","ranges":[3.5,4.25,5],"measures":[3.2,4.7],"markers":[4.4]} 7 | ] 8 | -------------------------------------------------------------------------------- /examples/bundle/bundle-radial.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hierarchical Edge Bundling (Radial Tree) 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/crimea/crimea.csv: -------------------------------------------------------------------------------- 1 | date,wounds,other,disease 2 | 5/1854,0,95,105 3 | 6/1854,0,40,95 4 | 7/1854,0,140,520 5 | 8/1854,20,150,800 6 | 9/1854,220,230,740 7 | 10/1854,305,310,600 8 | 11/1854,480,290,820 9 | 12/1854,295,310,1100 10 | 1/1855,230,460,1440 11 | 2/1855,180,520,1270 12 | 3/1855,155,350,935 13 | 4/1855,195,195,560 14 | 5/1855,180,155,550 15 | 6/1855,330,130,650 16 | 7/1855,260,130,430 17 | 8/1855,290,110,490 18 | 9/1855,355,100,290 19 | 10/1855,135,95,245 20 | 11/1855,100,140,325 21 | 12/1855,40,120,215 22 | 1/1856,0,160,160 23 | 2/1856,0,100,100 24 | 3/1856,0,125,90 25 | -------------------------------------------------------------------------------- /src/svg/line-radial.js: -------------------------------------------------------------------------------- 1 | d3.svg.line.radial = function() { 2 | var line = d3_svg_line(d3_svg_lineRadial); 3 | line.radius = line.x, delete line.x; 4 | line.angle = line.y, delete line.y; 5 | return line; 6 | }; 7 | 8 | function d3_svg_lineRadial(points) { 9 | var point, 10 | i = -1, 11 | n = points.length, 12 | r, 13 | a; 14 | while (++i < n) { 15 | point = points[i]; 16 | r = point[0]; 17 | a = point[1] + d3_svg_arcOffset; 18 | point[0] = r * Math.cos(a); 19 | point[1] = r * Math.sin(a); 20 | } 21 | return points; 22 | } 23 | -------------------------------------------------------------------------------- /examples/choropleth/choropleth.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | U.S. Unemployment by County 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/transform/null.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 23 | -------------------------------------------------------------------------------- /examples/transform/null-matrix.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 23 | -------------------------------------------------------------------------------- /src/core/selection-enter.js: -------------------------------------------------------------------------------- 1 | function d3_selection_enter(selection) { 2 | d3_arraySubclass(selection, d3_selection_enterPrototype); 3 | return selection; 4 | } 5 | 6 | var d3_selection_enterPrototype = []; 7 | 8 | d3.selection.enter = d3_selection_enter; 9 | d3.selection.enter.prototype = d3_selection_enterPrototype; 10 | 11 | d3_selection_enterPrototype.append = d3_selectionPrototype.append; 12 | d3_selection_enterPrototype.insert = d3_selectionPrototype.insert; 13 | d3_selection_enterPrototype.empty = d3_selectionPrototype.empty; 14 | d3_selection_enterPrototype.node = d3_selectionPrototype.node; 15 | -------------------------------------------------------------------------------- /src/time/day.js: -------------------------------------------------------------------------------- 1 | d3.time.day = d3_time_interval(function(date) { 2 | var day = new d3_time(0, date.getMonth(), date.getDate()); 3 | day.setFullYear(date.getFullYear()); 4 | return day; 5 | }, function(date, offset) { 6 | date.setDate(date.getDate() + offset); 7 | }, function(date) { 8 | return date.getDate() - 1; 9 | }); 10 | 11 | d3.time.days = d3.time.day.range; 12 | d3.time.days.utc = d3.time.day.utc.range; 13 | 14 | d3.time.dayOfYear = function(date) { 15 | var year = d3.time.year(date); 16 | return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5); 17 | }; 18 | -------------------------------------------------------------------------------- /test/core/transition-test-id.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var assert = require("assert"); 4 | 5 | module.exports = { 6 | topic: function() { 7 | return d3.select("body").append("div").transition(); 8 | }, 9 | "has a positive integer id": function(transition) { 10 | var id = transition.id; 11 | assert.isTrue(id > 0); 12 | assert.equal(~~id, id); 13 | }, 14 | "increases monotonically across transitions": function(transition) { 15 | var t0 = d3.select("body").append("div").transition(), 16 | t1 = d3.select("body").append("div").transition(); 17 | assert.isTrue(t1.id > t0.id); 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /src/core/selection-root.js: -------------------------------------------------------------------------------- 1 | var d3_selectionRoot = d3_selection([[document]]); 2 | 3 | d3_selectionRoot[0].parentNode = d3_selectRoot; 4 | 5 | // TODO fast singleton implementation! 6 | // TODO select(function) 7 | d3.select = function(selector) { 8 | return typeof selector === "string" 9 | ? d3_selectionRoot.select(selector) 10 | : d3_selection([[selector]]); // assume node 11 | }; 12 | 13 | // TODO selectAll(function) 14 | d3.selectAll = function(selector) { 15 | return typeof selector === "string" 16 | ? d3_selectionRoot.selectAll(selector) 17 | : d3_selection([d3_array(selector)]); // assume node[] 18 | }; 19 | -------------------------------------------------------------------------------- /examples/stream/stream.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Streamgraph 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |

15 |

16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/core/transition-filter.js: -------------------------------------------------------------------------------- 1 | d3_transitionPrototype.filter = function(filter) { 2 | var subgroups = [], 3 | subgroup, 4 | group, 5 | node; 6 | 7 | if (typeof filter !== "function") filter = d3_selection_filter(filter); 8 | 9 | for (var j = 0, m = this.length; j < m; j++) { 10 | subgroups.push(subgroup = []); 11 | for (var group = this[j], i = 0, n = group.length; i < n; i++) { 12 | if ((node = group[i]) && filter.call(node.node, node.node.__data__, i)) { 13 | subgroup.push(node); 14 | } 15 | } 16 | } 17 | 18 | return d3_transition(subgroups, this.id, this.time).ease(this.ease()); 19 | }; 20 | -------------------------------------------------------------------------------- /src/core/selection-insert.js: -------------------------------------------------------------------------------- 1 | // TODO insert(node, function)? 2 | // TODO insert(function, string)? 3 | // TODO insert(function, function)? 4 | d3_selectionPrototype.insert = function(name, before) { 5 | name = d3.ns.qualify(name); 6 | 7 | function insert() { 8 | return this.insertBefore( 9 | document.createElementNS(this.namespaceURI, name), 10 | d3_select(before, this)); 11 | } 12 | 13 | function insertNS() { 14 | return this.insertBefore( 15 | document.createElementNS(name.space, name.local), 16 | d3_select(before, this)); 17 | } 18 | 19 | return this.select(name.local ? insertNS : insert); 20 | }; 21 | -------------------------------------------------------------------------------- /src/scale/polylinear.js: -------------------------------------------------------------------------------- 1 | function d3_scale_polylinear(domain, range, uninterpolate, interpolate) { 2 | var u = [], 3 | i = [], 4 | j = 0, 5 | k = Math.min(domain.length, range.length) - 1; 6 | 7 | // Handle descending domains. 8 | if (domain[k] < domain[0]) { 9 | domain = domain.slice().reverse(); 10 | range = range.slice().reverse(); 11 | } 12 | 13 | while (++j <= k) { 14 | u.push(uninterpolate(domain[j - 1], domain[j])); 15 | i.push(interpolate(range[j - 1], range[j])); 16 | } 17 | 18 | return function(x) { 19 | var j = d3.bisect(domain, x, 1, k) - 1; 20 | return i[j](u[j](x)); 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /src/time/format-utc.js: -------------------------------------------------------------------------------- 1 | d3.time.format.utc = function(template) { 2 | var local = d3.time.format(template); 3 | 4 | function format(date) { 5 | try { 6 | d3_time = d3_time_utc; 7 | var utc = new d3_time(); 8 | utc._ = date; 9 | return local(utc); 10 | } finally { 11 | d3_time = Date; 12 | } 13 | } 14 | 15 | format.parse = function(string) { 16 | try { 17 | d3_time = d3_time_utc; 18 | var date = local.parse(string); 19 | return date && date._; 20 | } finally { 21 | d3_time = Date; 22 | } 23 | }; 24 | 25 | format.toString = local.toString; 26 | 27 | return format; 28 | }; 29 | -------------------------------------------------------------------------------- /examples/bundle/bundle-treemap.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hierarchical Edge Bundling (Treemap) 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /examples/force/README: -------------------------------------------------------------------------------- 1 | The miserables.json file contains the weighted network of coappearances of 2 | characters in Victor Hugo's novel /Les Miserables/. Nodes represent characters 3 | as indicated by the labels, and edges connect any pair of characters that 4 | appear in the same chapter of the book. The values on the edges are the number 5 | of such coappearances. The data on coappearances were taken from D. E. Knuth, 6 | "The Stanford GraphBase: A Platform for Combinatorial Computing", 7 | Addison-Wesley, Reading, MA (1993). 8 | 9 | The group labels were transcribed from "Finding and evaluating community 10 | structure in networks" by M. E. J. Newman and M. Girvan. 11 | -------------------------------------------------------------------------------- /src/core/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/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 | -------------------------------------------------------------------------------- /examples/hello-world/hello-order.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /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 arguments.length ? target : value; 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /src/core/transition-each.js: -------------------------------------------------------------------------------- 1 | function d3_transition_each(callback) { 2 | var id = d3_transitionId, 3 | ease = d3_transitionEase, 4 | delay = d3_transitionDelay, 5 | duration = d3_transitionDuration; 6 | 7 | d3_transitionId = this.id; 8 | d3_transitionEase = this.ease(); 9 | d3_selection_each(this, function(node, i, j) { 10 | d3_transitionDelay = node.delay; 11 | d3_transitionDuration = node.duration; 12 | callback.call(node = node.node, node.__data__, i, j); 13 | }); 14 | 15 | d3_transitionId = id; 16 | d3_transitionEase = ease; 17 | d3_transitionDelay = delay; 18 | d3_transitionDuration = duration; 19 | return this; 20 | } 21 | -------------------------------------------------------------------------------- /examples/partition/partition-sunburst.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Partition - Sunburst 6 | 7 | 8 | 9 | 10 |
11 |

17 |

18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/core/selection-property.js: -------------------------------------------------------------------------------- 1 | d3_selectionPrototype.property = function(name, value) { 2 | 3 | // If no value is specified, return the first value. 4 | if (arguments.length < 2) return this.node()[name]; 5 | 6 | function propertyNull() { 7 | delete this[name]; 8 | } 9 | 10 | function propertyConstant() { 11 | this[name] = value; 12 | } 13 | 14 | function propertyFunction() { 15 | var x = value.apply(this, arguments); 16 | if (x == null) delete this[name]; 17 | else this[name] = x; 18 | } 19 | 20 | return this.each(value == null 21 | ? propertyNull : (typeof value === "function" 22 | ? propertyFunction : propertyConstant)); 23 | }; 24 | -------------------------------------------------------------------------------- /test/layout/pie-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("d3.layout.pie"); 7 | 8 | suite.addBatch({ 9 | "pie": { 10 | topic: d3.layout.pie, 11 | "arcs are in same order as original data": function(pie) { 12 | assert.deepEqual(pie([5, 30, 15]).map(function(d) { return d.data; }), [ 13 | 5, 30, 15 14 | ]); 15 | assert.deepEqual(pie([ 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 | -------------------------------------------------------------------------------- /examples/sizzle/sizzle.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Sizzle 5 | 6 | 7 | 16 | 17 | 18 | Sizzle.js disabled. 19 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/core/transition-style.js: -------------------------------------------------------------------------------- 1 | d3_transitionPrototype.style = function(name, value, priority) { 2 | if (arguments.length < 3) priority = ""; 3 | return this.styleTween(name, d3_transitionTween(name, value), priority); 4 | }; 5 | 6 | d3_transitionPrototype.styleTween = function(name, tween, priority) { 7 | if (arguments.length < 3) priority = ""; 8 | return this.tween("style." + name, function(d, i) { 9 | var f = tween.call(this, d, i, window.getComputedStyle(this, null).getPropertyValue(name)); 10 | return f === d3_transitionRemove 11 | ? (this.style.removeProperty(name), null) 12 | : f && function(t) { this.style.setProperty(name, f(t), priority); }; 13 | }); 14 | }; 15 | -------------------------------------------------------------------------------- /src/svg/diagonal-radial.js: -------------------------------------------------------------------------------- 1 | d3.svg.diagonal.radial = function() { 2 | var diagonal = d3.svg.diagonal(), 3 | projection = d3_svg_diagonalProjection, 4 | projection_ = diagonal.projection; 5 | 6 | diagonal.projection = function(x) { 7 | return arguments.length 8 | ? projection_(d3_svg_diagonalRadialProjection(projection = x)) 9 | : projection; 10 | }; 11 | 12 | return diagonal; 13 | }; 14 | 15 | function d3_svg_diagonalRadialProjection(projection) { 16 | return function() { 17 | var d = projection.apply(this, arguments), 18 | r = d[0], 19 | a = d[1] + d3_svg_arcOffset; 20 | return [r * Math.cos(a), r * Math.sin(a)]; 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /examples/mouse/mouse-html.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | HTML Mouse Test 5 | 6 | 7 | 8 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /examples/hello-world/hello-node-key.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hello, node! 5 | 6 | 7 | 8 | Your lucky numbers are:
9 | 10 | 11 | 12 | 13 | 14 | 15 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /examples/splom/splom.css: -------------------------------------------------------------------------------- 1 | svg { 2 | font: 10px sans-serif; 3 | } 4 | 5 | .axis { 6 | shape-rendering: crispEdges; 7 | } 8 | 9 | .axis line { 10 | stroke: #ddd; 11 | stroke-width: .5px; 12 | } 13 | 14 | .axis path { 15 | display: none; 16 | } 17 | 18 | rect.extent { 19 | fill: #000; 20 | fill-opacity: .125; 21 | stroke: #fff; 22 | } 23 | 24 | rect.frame { 25 | fill: #fff; 26 | fill-opacity: .7; 27 | stroke: #aaa; 28 | } 29 | 30 | circle { 31 | fill: #ccc; 32 | fill-opacity: .5; 33 | } 34 | 35 | .cell text { 36 | pointer-events: none; 37 | } 38 | 39 | .setosa { 40 | fill: #800; 41 | } 42 | 43 | .versicolor { 44 | fill: #080; 45 | } 46 | 47 | .virginica { 48 | fill: #008; 49 | } 50 | -------------------------------------------------------------------------------- /examples/treemap/treemap.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Treemap 6 | 7 | 8 | 9 | 10 | 11 |
12 |

18 |

19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var self = this, 2 | globals = ["document", "window", "navigator", "CSSStyleDeclaration", "d3", "Sizzle"], 3 | globalValues = {}; 4 | 5 | globals.forEach(function(global) { 6 | if (global in self) globalValues[global] = self[global]; 7 | }); 8 | 9 | document = require("jsdom").jsdom(""); 10 | window = document.createWindow(); 11 | navigator = window.navigator; 12 | CSSStyleDeclaration = window.CSSStyleDeclaration; 13 | 14 | Sizzle = require("sizzle"); 15 | 16 | require("./d3.v2"); 17 | 18 | module.exports = d3; 19 | 20 | globals.forEach(function(global) { 21 | if (global in globalValues) self[global] = globalValues[global]; 22 | else delete self[global]; 23 | }); 24 | -------------------------------------------------------------------------------- /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/core/range.js: -------------------------------------------------------------------------------- 1 | d3.range = function(start, stop, step) { 2 | if (arguments.length < 3) { 3 | step = 1; 4 | if (arguments.length < 2) { 5 | stop = start; 6 | start = 0; 7 | } 8 | } 9 | if ((stop - start) / step === Infinity) throw new Error("infinite range"); 10 | var range = [], 11 | k = d3_range_integerScale(Math.abs(step)), 12 | i = -1, 13 | j; 14 | start *= k, stop *= k, step *= k; 15 | if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); 16 | else while ((j = start + step * ++i) < stop) range.push(j / k); 17 | return range; 18 | }; 19 | 20 | function d3_range_integerScale(x) { 21 | var k = 1; 22 | while (x * k % 1) k *= 10; 23 | return k; 24 | } 25 | -------------------------------------------------------------------------------- /src/scale/identity.js: -------------------------------------------------------------------------------- 1 | d3.scale.identity = function() { 2 | return d3_scale_identity([0, 1]); 3 | }; 4 | 5 | function d3_scale_identity(domain) { 6 | 7 | function identity(x) { return +x; } 8 | 9 | identity.invert = identity; 10 | 11 | identity.domain = identity.range = function(x) { 12 | if (!arguments.length) return domain; 13 | domain = x.map(identity); 14 | return identity; 15 | }; 16 | 17 | identity.ticks = function(m) { 18 | return d3_scale_linearTicks(domain, m); 19 | }; 20 | 21 | identity.tickFormat = function(m) { 22 | return d3_scale_linearTickFormat(domain, m); 23 | }; 24 | 25 | identity.copy = function() { 26 | return d3_scale_identity(domain); 27 | }; 28 | 29 | return identity; 30 | } 31 | -------------------------------------------------------------------------------- /src/core/selection-selectAll.js: -------------------------------------------------------------------------------- 1 | d3_selectionPrototype.selectAll = function(selector) { 2 | var subgroups = [], 3 | subgroup, 4 | node; 5 | 6 | if (typeof selector !== "function") selector = d3_selection_selectorAll(selector); 7 | 8 | for (var j = -1, m = this.length; ++j < m;) { 9 | for (var group = this[j], i = -1, n = group.length; ++i < n;) { 10 | if (node = group[i]) { 11 | subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i))); 12 | subgroup.parentNode = node; 13 | } 14 | } 15 | } 16 | 17 | return d3_selection(subgroups); 18 | }; 19 | 20 | function d3_selection_selectorAll(selector) { 21 | return function() { 22 | return d3_selectAll(selector, this); 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /src/core/selection-enter-select.js: -------------------------------------------------------------------------------- 1 | d3_selection_enterPrototype.select = function(selector) { 2 | var subgroups = [], 3 | subgroup, 4 | subnode, 5 | upgroup, 6 | group, 7 | node; 8 | 9 | for (var j = -1, m = this.length; ++j < m;) { 10 | upgroup = (group = this[j]).update; 11 | subgroups.push(subgroup = []); 12 | subgroup.parentNode = group.parentNode; 13 | for (var i = -1, n = group.length; ++i < n;) { 14 | if (node = group[i]) { 15 | subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i)); 16 | subnode.__data__ = node.__data__; 17 | } else { 18 | subgroup.push(null); 19 | } 20 | } 21 | } 22 | 23 | return d3_selection(subgroups); 24 | }; 25 | -------------------------------------------------------------------------------- /examples/stream/stack.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Stacked Bar Chart 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |

18 |

19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /examples/hello-world/select-enter-add.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Test - select > enter > append 5 | 6 | 7 | 8 | 9 | 10 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /examples/qq/qq.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Q-Q Plots 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 16 |
17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/core/selection-filter.js: -------------------------------------------------------------------------------- 1 | d3_selectionPrototype.filter = function(filter) { 2 | var subgroups = [], 3 | subgroup, 4 | group, 5 | node; 6 | 7 | if (typeof filter !== "function") filter = d3_selection_filter(filter); 8 | 9 | for (var j = 0, m = this.length; j < m; j++) { 10 | subgroups.push(subgroup = []); 11 | subgroup.parentNode = (group = this[j]).parentNode; 12 | for (var i = 0, n = group.length; i < n; i++) { 13 | if ((node = group[i]) && filter.call(node, node.__data__, i)) { 14 | subgroup.push(node); 15 | } 16 | } 17 | } 18 | 19 | return d3_selection(subgroups); 20 | }; 21 | 22 | function d3_selection_filter(selector) { 23 | return function() { 24 | return d3_selectMatches(this, selector); 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /src/core/formatPrefix.js: -------------------------------------------------------------------------------- 1 | var d3_formatPrefixes = ["y","z","a","f","p","n","μ","m","","k","M","G","T","P","E","Z","Y"].map(d3_formatPrefix); 2 | 3 | d3.formatPrefix = function(value, precision) { 4 | var i = 0; 5 | if (value) { 6 | if (value < 0) value *= -1; 7 | if (precision) value = d3.round(value, d3_format_precision(value, precision)); 8 | i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10); 9 | i = Math.max(-24, Math.min(24, Math.floor((i <= 0 ? i + 1 : i - 1) / 3) * 3)); 10 | } 11 | return d3_formatPrefixes[8 + i / 3]; 12 | }; 13 | 14 | function d3_formatPrefix(d, i) { 15 | var k = Math.pow(10, Math.abs(8 - i) * 3); 16 | return { 17 | scale: i > 8 ? function(d) { return d / k; } : function(d) { return d * k; }, 18 | symbol: d 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /test/core/merge-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("d3.merge"); 7 | 8 | suite.addBatch({ 9 | "merge": { 10 | "merges an array of arrays": function() { 11 | var a = {}, b = {}, c = {}, d = {}, e = {}, f = {}; 12 | assert.deepEqual(d3.merge([[a], [b, c], [d, e, f]]), [a, b, c, d, e, f]); 13 | }, 14 | "returns a new array": function() { 15 | var input = [[1, 2, 3], [4, 5], [6]]; 16 | assert.isFalse(d3.merge(input) === input); 17 | }, 18 | "does not modify the input arrays": function() { 19 | var input = [[1, 2, 3], [4, 5], [6]]; 20 | d3.merge(input); 21 | assert.deepEqual(input, [[1, 2, 3], [4, 5], [6]]); 22 | } 23 | } 24 | }); 25 | 26 | suite.export(module); 27 | -------------------------------------------------------------------------------- /src/core/transition-selectAll.js: -------------------------------------------------------------------------------- 1 | d3_transitionPrototype.selectAll = function(selector) { 2 | var subgroups = [], 3 | subgroup, 4 | subnodes, 5 | node; 6 | 7 | if (typeof selector !== "function") selector = d3_selection_selectorAll(selector); 8 | 9 | for (var j = -1, m = this.length; ++j < m;) { 10 | for (var group = this[j], i = -1, n = group.length; ++i < n;) { 11 | if (node = group[i]) { 12 | subnodes = selector.call(node.node, node.node.__data__, i); 13 | subgroups.push(subgroup = []); 14 | for (var k = -1, o = subnodes.length; ++k < o;) { 15 | subgroup.push({node: subnodes[k], delay: node.delay, duration: node.duration}); 16 | } 17 | } 18 | } 19 | } 20 | 21 | return d3_transition(subgroups, this.id, this.time).ease(this.ease()); 22 | }; 23 | -------------------------------------------------------------------------------- /examples/bar/sample-data.csv: -------------------------------------------------------------------------------- 1 | name,value 2 | AL,4708708 3 | AK,698473 4 | AZ,6595778 5 | AR,2889450 6 | CA,36961664 7 | CO,5024748 8 | CT,3518288 9 | DE,885122 10 | DC,599657 11 | FL,18537969 12 | GA,9829211 13 | HI,1295178 14 | ID,1545801 15 | IL,12910409 16 | IN,6423113 17 | IA,3007856 18 | KS,2818747 19 | KY,4314113 20 | LA,4492076 21 | ME,1318301 22 | MD,5699478 23 | MA,6593587 24 | MI,9969727 25 | MN,5266214 26 | MS,2951996 27 | MO,5987580 28 | MT,974989 29 | NE,1796619 30 | NV,2643085 31 | NH,1324575 32 | NJ,8707739 33 | NM,2009671 34 | NY,19541453 35 | NC,9380884 36 | ND,646844 37 | OH,11542645 38 | OK,3687050 39 | OR,3825657 40 | PA,12604767 41 | RI,1053209 42 | SC,4561242 43 | SD,812383 44 | TN,6296254 45 | TX,24782302 46 | UT,2784572 47 | VT,621760 48 | VA,7882590 49 | WA,6664195 50 | WV,1819777 51 | WI,5654774 52 | WY,544270 53 | PR,3967288 54 | -------------------------------------------------------------------------------- /test/core/functor-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("d3.functor"); 7 | 8 | suite.addBatch({ 9 | "functor": { 10 | topic: function() { 11 | return d3.functor; 12 | }, 13 | "when passed a function, returns the function": function(functor) { 14 | function foo() {} 15 | assert.strictEqual(functor(foo), foo); 16 | }, 17 | "when passed a non-function, returns a wrapper function": function(functor) { 18 | var a = {}; 19 | assert.isNull(functor(null)()); 20 | assert.isUndefined(functor(undefined)()); 21 | assert.strictEqual(functor(a)(), a); 22 | assert.strictEqual(functor(1)(), 1); 23 | assert.deepEqual(functor([1])(), [1]); 24 | } 25 | } 26 | }); 27 | 28 | suite.export(module); 29 | -------------------------------------------------------------------------------- /src/core/transition-select.js: -------------------------------------------------------------------------------- 1 | d3_transitionPrototype.select = function(selector) { 2 | var subgroups = [], 3 | subgroup, 4 | subnode, 5 | node; 6 | 7 | if (typeof selector !== "function") selector = d3_selection_selector(selector); 8 | 9 | for (var j = -1, m = this.length; ++j < m;) { 10 | subgroups.push(subgroup = []); 11 | for (var group = this[j], i = -1, n = group.length; ++i < n;) { 12 | if ((node = group[i]) && (subnode = selector.call(node.node, node.node.__data__, i))) { 13 | if ("__data__" in node.node) subnode.__data__ = node.node.__data__; 14 | subgroup.push({node: subnode, delay: node.delay, duration: node.duration}); 15 | } else { 16 | subgroup.push(null); 17 | } 18 | } 19 | } 20 | 21 | return d3_transition(subgroups, this.id, this.time).ease(this.ease()); 22 | }; 23 | -------------------------------------------------------------------------------- /src/core/selection-style.js: -------------------------------------------------------------------------------- 1 | d3_selectionPrototype.style = function(name, value, priority) { 2 | if (arguments.length < 3) priority = ""; 3 | 4 | // If no value is specified, return the first value. 5 | if (arguments.length < 2) return window 6 | .getComputedStyle(this.node(), null) 7 | .getPropertyValue(name); 8 | 9 | function styleNull() { 10 | this.style.removeProperty(name); 11 | } 12 | 13 | function styleConstant() { 14 | this.style.setProperty(name, value, priority); 15 | } 16 | 17 | function styleFunction() { 18 | var x = value.apply(this, arguments); 19 | if (x == null) this.style.removeProperty(name); 20 | else this.style.setProperty(name, x, priority); 21 | } 22 | 23 | return this.each(value == null 24 | ? styleNull : (typeof value === "function" 25 | ? styleFunction : styleConstant)); 26 | }; 27 | -------------------------------------------------------------------------------- /test/core/selection-enter-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("selection.enter"); 7 | 8 | suite.addBatch({ 9 | "selectAll(div)": { 10 | topic: function() { 11 | return d3.select("body").html("").selectAll("div").data(d3.range(2)).enter(); 12 | }, 13 | "is an instanceof d3.selection.enter": function(enter) { 14 | assert.instanceOf(enter, d3.selection.enter); 15 | }, 16 | "selection prototype can be extended": function(enter) { 17 | d3.selection.enter.prototype.foo = function() { return this.append("foo"); }; 18 | var selection = enter.foo(); 19 | assert.equal(document.body.innerHTML, ""); 20 | delete d3.selection.enter.prototype.foo; 21 | } 22 | } 23 | }); 24 | 25 | suite.export(module); 26 | -------------------------------------------------------------------------------- /test/core/keys-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("d3.keys"); 7 | 8 | suite.addBatch({ 9 | "keys": { 10 | topic: function() { 11 | return d3.keys; 12 | }, 13 | "enumerates every defined key": function(keys) { 14 | assert.deepEqual(keys({a: 1, b: 1}), ["a", "b"]); 15 | }, 16 | "includes keys defined on prototypes": function(keys) { 17 | function abc() { 18 | this.a = 1; 19 | this.b = 2; 20 | } 21 | abc.prototype.c = 3; 22 | assert.deepEqual(keys(new abc()), ["a", "b", "c"]); 23 | }, 24 | "includes keys with null or undefined values": function(keys) { 25 | assert.deepEqual(keys({a: undefined, b: null, c: NaN}), ["a", "b", "c"]); 26 | } 27 | } 28 | }); 29 | 30 | suite.export(module); 31 | -------------------------------------------------------------------------------- /examples/horizon/horizon.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Horizon Chart 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 | 14 | 16 | 17 | 18 | 20 | 21 |
22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /examples/data/README.md: -------------------------------------------------------------------------------- 1 | ## World Boundaries 2 | 3 | These are derived from the public domain [Natural Earth](http://www.naturalearthdata.com/downloads/) cultural vector files, 110m resolution. Then, ogr2ogr was used to convert to GeoJSON. Lastly, the data was cleaned up slightly, removing extra properties and a degenerate edge from Antarctica. 4 | 5 | collection.features.forEach(function(d, i) { 6 | d.id = d.properties.ISO_A3; 7 | d.properties = {name: d.properties.SOVEREIGNT}; 8 | }); 9 | 10 | ## United States Boundaries 11 | 12 | These are derived from the cartographic boundary files from the 2000 [U.S. Census](http://www.census.gov/geo/www/cob/bdy_files.html 13 | ). Then, MapShaper was used to simplify the geometry, and ogr2ogr to convert the shapefiles to GeoJSON. Some additional work was done to preserve the FIPS codes, which are dropped from the shapefiles by MapShaper. 14 | -------------------------------------------------------------------------------- /src/core/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/scale/quantize.js: -------------------------------------------------------------------------------- 1 | d3.scale.quantize = function() { 2 | return d3_scale_quantize(0, 1, [0, 1]); 3 | }; 4 | 5 | function d3_scale_quantize(x0, x1, range) { 6 | var kx, i; 7 | 8 | function scale(x) { 9 | return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))]; 10 | } 11 | 12 | function rescale() { 13 | kx = range.length / (x1 - x0); 14 | i = range.length - 1; 15 | return scale; 16 | } 17 | 18 | scale.domain = function(x) { 19 | if (!arguments.length) return [x0, x1]; 20 | x0 = +x[0]; 21 | x1 = +x[x.length - 1]; 22 | return rescale(); 23 | }; 24 | 25 | scale.range = function(x) { 26 | if (!arguments.length) return range; 27 | range = x; 28 | return rescale(); 29 | }; 30 | 31 | scale.copy = function() { 32 | return d3_scale_quantize(x0, x1, range); // copy on write 33 | }; 34 | 35 | return rescale(); 36 | } 37 | -------------------------------------------------------------------------------- /examples/qq/stats.js: -------------------------------------------------------------------------------- 1 | // Sample from a normal distribution with mean 0, stddev 1. 2 | function normal() { 3 | var x = 0, y = 0, rds, c; 4 | do { 5 | x = Math.random() * 2 - 1; 6 | y = Math.random() * 2 - 1; 7 | rds = x * x + y * y; 8 | } while (rds == 0 || rds > 1); 9 | c = Math.sqrt(-2 * Math.log(rds) / rds); // Box-Muller transform 10 | return x * c; // throw away extra sample y * c 11 | } 12 | 13 | // Simple 1D Gaussian (normal) distribution 14 | function normal1(mean, deviation) { 15 | return function() { 16 | return mean + deviation * normal(); 17 | }; 18 | } 19 | 20 | // Gaussian Mixture Model (k=3) fit using E-M algorithm 21 | function normal3(dd) { 22 | return function() { 23 | var r = Math.random(), 24 | i = r < dd[0][2] ? 0 : r < dd[0][2] + dd[1][2] ? 1 : 2, 25 | d = dd[i]; 26 | return d[0] + Math.sqrt(d[1]) * normal(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/package.js: -------------------------------------------------------------------------------- 1 | require("./core/core"); 2 | 3 | require("util").puts(JSON.stringify({ 4 | "name": "d3", 5 | "version": d3.version, 6 | "description": "A small, free JavaScript library for manipulating documents based on data.", 7 | "keywords": ["dom", "w3c", "visualization", "svg", "animation", "canvas"], 8 | "homepage": "http://mbostock.github.com/d3/", 9 | "author": {"name": "Mike Bostock", "url": "http://bost.ocks.org/mike"}, 10 | "repository": {"type": "git", "url": "http://github.com/mbostock/d3.git"}, 11 | "main": "index.js", 12 | "browserify" : "index-browserify.js", 13 | "dependencies": { 14 | "jsdom": "0.2.14", 15 | "sizzle": "1.1.x" 16 | }, 17 | "devDependencies": { 18 | "uglify-js": "1.2.3", 19 | "vows": "0.6.x", 20 | "canvas": "0.12.1" // for node-canvas example 21 | }, 22 | "scripts": {"test": "./node_modules/vows/bin/vows"} 23 | }, null, 2)); 24 | -------------------------------------------------------------------------------- /src/core/array.js: -------------------------------------------------------------------------------- 1 | var d3_array = d3_arraySlice; // conversion for NodeLists 2 | 3 | function d3_arrayCopy(pseudoarray) { 4 | var i = -1, n = pseudoarray.length, array = []; 5 | while (++i < n) array.push(pseudoarray[i]); 6 | return array; 7 | } 8 | 9 | function d3_arraySlice(pseudoarray) { 10 | return Array.prototype.slice.call(pseudoarray); 11 | } 12 | 13 | try { 14 | d3_array(document.documentElement.childNodes)[0].nodeType; 15 | } catch(e) { 16 | d3_array = d3_arrayCopy; 17 | } 18 | 19 | var d3_arraySubclass = [].__proto__? 20 | 21 | // Until ECMAScript supports array subclassing, prototype injection works well. 22 | function(array, prototype) { 23 | array.__proto__ = prototype; 24 | }: 25 | 26 | // And if your browser doesn't support __proto__, we'll use direct extension. 27 | function(array, prototype) { 28 | for (var property in prototype) array[property] = prototype[property]; 29 | }; 30 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "d3", 3 | "version": "2.9.7", 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://mbostock.github.com/d3/", 14 | "author": { 15 | "name": "Mike Bostock", 16 | "url": "http://bost.ocks.org/mike" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "http://github.com/mbostock/d3.git" 21 | }, 22 | "main": "index.js", 23 | "browserify": "index-browserify.js", 24 | "dependencies": { 25 | "jsdom": "0.2.14", 26 | "sizzle": "1.1.x" 27 | }, 28 | "devDependencies": { 29 | "uglify-js": "1.2.3", 30 | "vows": "0.6.x", 31 | "canvas": "0.12.1" 32 | }, 33 | "scripts": { 34 | "test": "./node_modules/vows/bin/vows" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /examples/histogram/histogram.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 20 | 21 | 22 | 23 | 43 | -------------------------------------------------------------------------------- /src/core/selection-select.js: -------------------------------------------------------------------------------- 1 | d3_selectionPrototype.select = function(selector) { 2 | var subgroups = [], 3 | subgroup, 4 | subnode, 5 | group, 6 | node; 7 | 8 | if (typeof selector !== "function") selector = d3_selection_selector(selector); 9 | 10 | for (var j = -1, m = this.length; ++j < m;) { 11 | subgroups.push(subgroup = []); 12 | subgroup.parentNode = (group = this[j]).parentNode; 13 | for (var i = -1, n = group.length; ++i < n;) { 14 | if (node = group[i]) { 15 | subgroup.push(subnode = selector.call(node, node.__data__, i)); 16 | if (subnode && "__data__" in node) subnode.__data__ = node.__data__; 17 | } else { 18 | subgroup.push(null); 19 | } 20 | } 21 | } 22 | 23 | return d3_selection(subgroups); 24 | }; 25 | 26 | function d3_selection_selector(selector) { 27 | return function() { 28 | return d3_select(selector, this); 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /test/core/transition-test-text.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var assert = require("assert"); 4 | 5 | module.exports = { 6 | topic: function() { 7 | return d3.select("body").append("div").text("foo").transition().text("bar"); 8 | }, 9 | "sets the text tween": function(div) { 10 | assert.typeOf(div.tween("text"), "function"); 11 | }, 12 | "start": { 13 | topic: function(div) { 14 | var cb = this.callback, 15 | tween = div.tween("text"); 16 | div.tween("text", function() { 17 | var result = tween.apply(this, arguments); 18 | cb(null, {transition: div, tween: result}); 19 | return result; 20 | }); 21 | }, 22 | "sets the text content as a string": function(result) { 23 | assert.equal(result.transition[0][0].node.textContent, "bar"); 24 | }, 25 | "does not interpolate text": function(result) { 26 | assert.isTrue(!result.tween); 27 | } 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /src/core/transition-attr.js: -------------------------------------------------------------------------------- 1 | d3_transitionPrototype.attr = function(name, value) { 2 | return this.attrTween(name, d3_transitionTween(name, value)); 3 | }; 4 | 5 | d3_transitionPrototype.attrTween = function(nameNS, tween) { 6 | var name = d3.ns.qualify(nameNS); 7 | 8 | function attrTween(d, i) { 9 | var f = tween.call(this, d, i, this.getAttribute(name)); 10 | return f === d3_transitionRemove 11 | ? (this.removeAttribute(name), null) 12 | : f && function(t) { this.setAttribute(name, f(t)); }; 13 | } 14 | 15 | function attrTweenNS(d, i) { 16 | var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local)); 17 | return f === d3_transitionRemove 18 | ? (this.removeAttributeNS(name.space, name.local), null) 19 | : f && function(t) { this.setAttributeNS(name.space, name.local, f(t)); }; 20 | } 21 | 22 | return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween); 23 | }; 24 | -------------------------------------------------------------------------------- /test/core/values-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("d3.values"); 7 | 8 | suite.addBatch({ 9 | "values": { 10 | topic: function() { 11 | return d3.values; 12 | }, 13 | "enumerates every value": function(values) { 14 | assert.deepEqual(values({a: 1, b: 2}), [1, 2]); 15 | }, 16 | "includes values defined on prototypes": function(values) { 17 | function abc() { 18 | this.a = 1; 19 | this.b = 2; 20 | } 21 | abc.prototype.c = 3; 22 | assert.deepEqual(values(new abc()), [1, 2, 3]); 23 | }, 24 | "includes null or undefined values": function(values) { 25 | var v = values({a: undefined, b: null, c: NaN}); 26 | assert.isUndefined(v[0]); 27 | assert.isNull(v[1]); 28 | assert.isNaN(v[2]); 29 | assert.equal(v.length, 3); 30 | } 31 | } 32 | }); 33 | 34 | suite.export(module); 35 | -------------------------------------------------------------------------------- /src/geo/equirectangular.js: -------------------------------------------------------------------------------- 1 | d3.geo.equirectangular = function() { 2 | var scale = 500, 3 | translate = [480, 250]; 4 | 5 | function equirectangular(coordinates) { 6 | var x = coordinates[0] / 360, 7 | y = -coordinates[1] / 360; 8 | return [ 9 | scale * x + translate[0], 10 | scale * y + translate[1] 11 | ]; 12 | } 13 | 14 | equirectangular.invert = function(coordinates) { 15 | var x = (coordinates[0] - translate[0]) / scale, 16 | y = (coordinates[1] - translate[1]) / scale; 17 | return [ 18 | 360 * x, 19 | -360 * y 20 | ]; 21 | }; 22 | 23 | equirectangular.scale = function(x) { 24 | if (!arguments.length) return scale; 25 | scale = +x; 26 | return equirectangular; 27 | }; 28 | 29 | equirectangular.translate = function(x) { 30 | if (!arguments.length) return translate; 31 | translate = [+x[0], +x[1]]; 32 | return equirectangular; 33 | }; 34 | 35 | return equirectangular; 36 | }; 37 | -------------------------------------------------------------------------------- /test/geo/path-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("d3.geo.path"); 7 | 8 | suite.addBatch({ 9 | "path": { 10 | topic: d3.geo.path, 11 | "Polygon": function(path) { 12 | assert.equal(path({ 13 | type: "Feature", 14 | geometry: { 15 | type: "Polygon", 16 | coordinates: [[[-63.03, 18.02], [-63.14, 18.06], [-63.01, 18.07], [-63.03, 18.02]]] 17 | }, 18 | }), "M984.5652086349427,468.99159422596244L981.8396467935554,467.9114977057422L985.0785139575695,467.688661596079Z"); 19 | }, 20 | "bogus type name": function(path) { 21 | assert.isNull(path({ 22 | type: "Feature", 23 | geometry: { 24 | type: "__proto__", 25 | coordinates: [[[-63.03, 18.02], [-63.14, 18.06], [-63.01, 18.07], [-63.03, 18.02]]] 26 | }, 27 | })); 28 | } 29 | } 30 | }); 31 | 32 | suite.export(module); 33 | -------------------------------------------------------------------------------- /src/geom/delaunay.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param vertices [[x1, y1], [x2, y2], …] 3 | * @returns triangles [[[x1, y1], [x2, y2], [x3, y3]], …] 4 | */ 5 | d3.geom.delaunay = function(vertices) { 6 | var edges = vertices.map(function() { return []; }), 7 | triangles = []; 8 | 9 | // Use the Voronoi tessellation to determine Delaunay edges. 10 | d3_voronoi_tessellate(vertices, function(e) { 11 | edges[e.region.l.index].push(vertices[e.region.r.index]); 12 | }); 13 | 14 | // Reconnect the edges into counterclockwise triangles. 15 | edges.forEach(function(edge, i) { 16 | var v = vertices[i], 17 | cx = v[0], 18 | cy = v[1]; 19 | edge.forEach(function(v) { 20 | v.angle = Math.atan2(v[0] - cx, v[1] - cy); 21 | }); 22 | edge.sort(function(a, b) { 23 | return a.angle - b.angle; 24 | }); 25 | for (var j = 0, m = edge.length - 1; j < m; j++) { 26 | triangles.push([v, edge[j], edge[j + 1]]); 27 | } 28 | }); 29 | 30 | return triangles; 31 | }; 32 | -------------------------------------------------------------------------------- /test/layout/hierarchy-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("d3.layout.hierarchy"); 7 | 8 | suite.addBatch({ 9 | "hierarchy": { 10 | topic: function() { 11 | return d3.layout.treemap(); // hierarchy is abstract, so test a subclass 12 | }, 13 | "doesn't overwrite the value of a node that has an empty children array": function(hierarchy) { 14 | var nodes = hierarchy.sticky(true).nodes({value: 1, children: []}); 15 | assert.equal(nodes[0].value, 1); 16 | hierarchy.nodes(nodes[0]); 17 | assert.equal(nodes[0].value, 1); 18 | }, 19 | "a valueless node that has an empty children array gets a value of 0": function(hierarchy) { 20 | var nodes = hierarchy.sticky(true).nodes({children: []}); 21 | assert.equal(nodes[0].value, 0); 22 | hierarchy.nodes(nodes[0]); 23 | assert.equal(nodes[0].value, 0); 24 | } 25 | } 26 | }); 27 | 28 | suite.export(module); 29 | -------------------------------------------------------------------------------- /src/time/week.js: -------------------------------------------------------------------------------- 1 | d3_time_weekdays.forEach(function(day, i) { 2 | day = day.toLowerCase(); 3 | i = 7 - i; 4 | 5 | var interval = d3.time[day] = d3_time_interval(function(date) { 6 | (date = d3.time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7); 7 | return date; 8 | }, function(date, offset) { 9 | date.setDate(date.getDate() + Math.floor(offset) * 7); 10 | }, function(date) { 11 | var day = d3.time.year(date).getDay(); 12 | return Math.floor((d3.time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i); 13 | }); 14 | 15 | d3.time[day + "s"] = interval.range; 16 | d3.time[day + "s"].utc = interval.utc.range; 17 | 18 | d3.time[day + "OfYear"] = function(date) { 19 | var day = d3.time.year(date).getDay(); 20 | return Math.floor((d3.time.dayOfYear(date) + (day + i) % 7) / 7); 21 | }; 22 | }); 23 | 24 | d3.time.week = d3.time.sunday; 25 | d3.time.weeks = d3.time.sunday.range; 26 | d3.time.weeks.utc = d3.time.sunday.utc.range; 27 | d3.time.weekOfYear = d3.time.sundayOfYear; 28 | -------------------------------------------------------------------------------- /examples/choropleth/choropleth.js: -------------------------------------------------------------------------------- 1 | var data; // loaded asynchronously 2 | 3 | var path = d3.geo.path(); 4 | 5 | var svg = d3.select("#chart") 6 | .append("svg"); 7 | 8 | var counties = svg.append("g") 9 | .attr("id", "counties") 10 | .attr("class", "Blues"); 11 | 12 | var states = svg.append("g") 13 | .attr("id", "states"); 14 | 15 | d3.json("../data/us-counties.json", function(json) { 16 | counties.selectAll("path") 17 | .data(json.features) 18 | .enter().append("path") 19 | .attr("class", data ? quantize : null) 20 | .attr("d", path); 21 | }); 22 | 23 | d3.json("../data/us-states.json", function(json) { 24 | states.selectAll("path") 25 | .data(json.features) 26 | .enter().append("path") 27 | .attr("d", path); 28 | }); 29 | 30 | d3.json("unemployment.json", function(json) { 31 | data = json; 32 | counties.selectAll("path") 33 | .attr("class", quantize); 34 | }); 35 | 36 | function quantize(d) { 37 | return "q" + Math.min(8, ~~(data[d.id] * 9 / 12)) + "-9"; 38 | } 39 | -------------------------------------------------------------------------------- /examples/hello-world/hello-transition-undefined.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hello, transition undefined! 5 | 6 | 21 | 22 | 23 | Your lucky number is:
24 |
hello
25 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /examples/choropleth/choropleth-bounds.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 19 | 20 | 21 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /test/core/zip-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("d3.zip"); 7 | 8 | suite.addBatch({ 9 | "zip": { 10 | topic: function() { 11 | return d3.zip; 12 | }, 13 | "transposes a square matrix": function(zip) { 14 | assert.deepEqual(d3.zip([1, 2], [3, 4]), [[1, 3], [2, 4]]); 15 | }, 16 | "transposes a non-square matrix": function(zip) { 17 | assert.deepEqual(d3.zip([1, 2, 3, 4, 5], [2, 4, 6, 8, 10]), [[1, 2], [2, 4], [3, 6], [4, 8], [5, 10]]); 18 | }, 19 | "transposes a single-row matrix": function(zip) { 20 | assert.deepEqual(d3.zip([1, 2, 3, 4, 5]), [[1], [2], [3], [4], [5]]); 21 | }, 22 | "transposes an empty matrix": function(zip) { 23 | assert.deepEqual(d3.zip(), []); 24 | }, 25 | "ignores extra elements given an irregular matrix": function(zip) { 26 | assert.deepEqual(d3.zip([1, 2], [3, 4], [5, 6, 7]), [[1, 3, 5], [2, 4, 6]]); 27 | } 28 | } 29 | }); 30 | 31 | suite.export(module); 32 | -------------------------------------------------------------------------------- /test/csv/csv-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("d3.csv"); 7 | 8 | suite.addBatch({ 9 | "csv": { 10 | topic: function() { 11 | var cb = this.callback; 12 | return d3.csv("examples/data/sample.csv", function(csv) { 13 | cb(null, csv); 14 | }); 15 | }, 16 | "invokes the callback with the parsed CSV": function(csv) { 17 | assert.deepEqual(csv, [{"Hello":42,"World":"\"fish\""}]); 18 | }, 19 | "overrides the mime type to text/csv": function(csv) { 20 | assert.equal(XMLHttpRequest._last._info.mimeType, "text/csv"); 21 | }, 22 | "": { 23 | topic: function() { 24 | var cb = this.callback; 25 | return d3.csv("//does/not/exist.csv", function(csv) { 26 | cb(null, csv); 27 | }); 28 | }, 29 | "invokes the callback with null when an error occurs": function(csv) { 30 | assert.isNull(csv); 31 | } 32 | } 33 | } 34 | }); 35 | 36 | suite.export(module); 37 | -------------------------------------------------------------------------------- /src/core/selection.js: -------------------------------------------------------------------------------- 1 | function d3_selection(groups) { 2 | d3_arraySubclass(groups, d3_selectionPrototype); 3 | return groups; 4 | } 5 | 6 | var d3_select = function(s, n) { return n.querySelector(s); }, 7 | d3_selectAll = function(s, n) { return n.querySelectorAll(s); }, 8 | d3_selectRoot = document.documentElement, 9 | d3_selectMatcher = d3_selectRoot.matchesSelector || d3_selectRoot.webkitMatchesSelector || d3_selectRoot.mozMatchesSelector || d3_selectRoot.msMatchesSelector || d3_selectRoot.oMatchesSelector, 10 | d3_selectMatches = function(n, s) { return d3_selectMatcher.call(n, s); }; 11 | 12 | // Prefer Sizzle, if available. 13 | if (typeof Sizzle === "function") { 14 | d3_select = function(s, n) { return Sizzle(s, n)[0] || null; }; 15 | d3_selectAll = function(s, n) { return Sizzle.uniqueSort(Sizzle(s, n)); }; 16 | d3_selectMatches = Sizzle.matchesSelector; 17 | } 18 | 19 | var d3_selectionPrototype = []; 20 | 21 | d3.selection = function() { 22 | return d3_selectionRoot; 23 | }; 24 | 25 | d3.selection.prototype = d3_selectionPrototype; 26 | -------------------------------------------------------------------------------- /examples/stream/stream_layers.js: -------------------------------------------------------------------------------- 1 | /* Inspired by Lee Byron's test data generator. */ 2 | function stream_layers(n, m, o) { 3 | if (arguments.length < 3) o = 0; 4 | function bump(a) { 5 | var x = 1 / (.1 + Math.random()), 6 | y = 2 * Math.random() - .5, 7 | z = 10 / (.1 + Math.random()); 8 | for (var i = 0; i < m; i++) { 9 | var w = (i / m - y) * z; 10 | a[i] += x * Math.exp(-w * w); 11 | } 12 | } 13 | return d3.range(n).map(function() { 14 | var a = [], i; 15 | for (i = 0; i < m; i++) a[i] = o + o * Math.random(); 16 | for (i = 0; i < 5; i++) bump(a); 17 | return a.map(stream_index); 18 | }); 19 | } 20 | 21 | /* Another layer generator using gamma distributions. */ 22 | function stream_waves(n, m) { 23 | return d3.range(n).map(function(i) { 24 | return d3.range(m).map(function(j) { 25 | var x = 20 * j / m - i / 3; 26 | return 2 * x * Math.exp(-.5 * x); 27 | }).map(stream_index); 28 | }); 29 | } 30 | 31 | function stream_index(d, i) { 32 | return {x: i, y: Math.max(0, d)}; 33 | } 34 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /examples/azimuthal/azimuthal.js: -------------------------------------------------------------------------------- 1 | var xy = d3.geo.azimuthal().scale(240).mode("stereographic"), 2 | circle = d3.geo.greatCircle(), 3 | path = d3.geo.path().projection(xy), 4 | svg = d3.select("body").append("svg"); 5 | 6 | d3.json("../data/world-countries.json", function(collection) { 7 | svg.selectAll("path") 8 | .data(collection.features) 9 | .enter().append("path") 10 | .attr("d", function(d) { return path(circle.clip(d)); }) 11 | .append("title") 12 | .text(function(d) { return d.properties.name; }); 13 | }); 14 | 15 | function refresh(duration) { 16 | var p = svg.selectAll("path"); 17 | if (duration) p = p.transition().duration(duration); 18 | p.attr("d", function(d) { return path(circle.clip(d)); }); 19 | d3.select("#lon span") 20 | .text(xy.origin()[0]); 21 | d3.select("#lat span") 22 | .text(xy.origin()[1]); 23 | d3.select("#scale span") 24 | .text(xy.scale()); 25 | d3.select("#translate-x span") 26 | .text(xy.translate()[0]); 27 | d3.select("#translate-y span") 28 | .text(xy.translate()[1]); 29 | } 30 | -------------------------------------------------------------------------------- /src/svg/diagonal.js: -------------------------------------------------------------------------------- 1 | d3.svg.diagonal = function() { 2 | var source = d3_svg_chordSource, 3 | target = d3_svg_chordTarget, 4 | projection = d3_svg_diagonalProjection; 5 | 6 | function diagonal(d, i) { 7 | var p0 = source.call(this, d, i), 8 | p3 = target.call(this, d, i), 9 | m = (p0.y + p3.y) / 2, 10 | p = [p0, {x: p0.x, y: m}, {x: p3.x, y: m}, p3]; 11 | p = p.map(projection); 12 | return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3]; 13 | } 14 | 15 | diagonal.source = function(x) { 16 | if (!arguments.length) return source; 17 | source = d3_functor(x); 18 | return diagonal; 19 | }; 20 | 21 | diagonal.target = function(x) { 22 | if (!arguments.length) return target; 23 | target = d3_functor(x); 24 | return diagonal; 25 | }; 26 | 27 | diagonal.projection = function(x) { 28 | if (!arguments.length) return projection; 29 | projection = x; 30 | return diagonal; 31 | }; 32 | 33 | return diagonal; 34 | }; 35 | 36 | function d3_svg_diagonalProjection(d) { 37 | return [d.x, d.y]; 38 | } 39 | -------------------------------------------------------------------------------- /examples/button.css: -------------------------------------------------------------------------------- 1 | button { 2 | font: 14px Helvetica Neue; 3 | background-color: #222; 4 | background-image: -moz-linear-gradient(top, rgba(255,255,255,.25), rgba(255,255,255,.11)); 5 | background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, rgba(255,255,255,.25)),color-stop(1, rgba(255,255,255,.11))); 6 | background-image: -webkit-linear-gradient(rgba(255,255,255,.25), rgba(255,255,255,.11)); 7 | color: #fff; 8 | text-rendering: optimizeLegibility; 9 | text-shadow: 0 -1px 1px #222; 10 | padding: 6px 10px 6px 10px; 11 | border: 0; 12 | border-radius: 0; 13 | border-bottom: 1px solid #222; 14 | margin: 0; 15 | -moz-box-shadow: 0 1px 3px #999; 16 | -webkit-box-shadow: 0 1px 3px #999; 17 | } 18 | 19 | button.first { 20 | border-top-left-radius: 5px; 21 | border-bottom-left-radius: 5px; 22 | } 23 | 24 | button.last { 25 | border-top-right-radius: 5px; 26 | border-bottom-right-radius: 5px; 27 | } 28 | 29 | button.active { 30 | background-color: rgb(65,102,133); 31 | } 32 | 33 | button:hover { 34 | background-color: steelblue; 35 | } 36 | -------------------------------------------------------------------------------- /src/geo/mercator.js: -------------------------------------------------------------------------------- 1 | d3.geo.mercator = function() { 2 | var scale = 500, 3 | translate = [480, 250]; 4 | 5 | function mercator(coordinates) { 6 | var x = coordinates[0] / 360, 7 | y = -(Math.log(Math.tan(Math.PI / 4 + coordinates[1] * d3_geo_radians / 2)) / d3_geo_radians) / 360; 8 | return [ 9 | scale * x + translate[0], 10 | scale * Math.max(-.5, Math.min(.5, y)) + translate[1] 11 | ]; 12 | } 13 | 14 | mercator.invert = function(coordinates) { 15 | var x = (coordinates[0] - translate[0]) / scale, 16 | y = (coordinates[1] - translate[1]) / scale; 17 | return [ 18 | 360 * x, 19 | 2 * Math.atan(Math.exp(-360 * y * d3_geo_radians)) / d3_geo_radians - 90 20 | ]; 21 | }; 22 | 23 | mercator.scale = function(x) { 24 | if (!arguments.length) return scale; 25 | scale = +x; 26 | return mercator; 27 | }; 28 | 29 | mercator.translate = function(x) { 30 | if (!arguments.length) return translate; 31 | translate = [+x[0], +x[1]]; 32 | return mercator; 33 | }; 34 | 35 | return mercator; 36 | }; 37 | -------------------------------------------------------------------------------- /test/core/json-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("d3.json"); 7 | 8 | suite.addBatch({ 9 | "json": { 10 | topic: function() { 11 | var cb = this.callback; 12 | return d3.json("examples/data/sample.json", function(json) { 13 | cb(null, json); 14 | }); 15 | }, 16 | "invokes the callback with the loaded JSON": function(json) { 17 | assert.deepEqual(json, [{"Hello":42,"World":"\"fish\""}]); 18 | }, 19 | "overrides the mime type to application/json": function(json) { 20 | assert.equal(XMLHttpRequest._last._info.mimeType, "application/json"); 21 | }, 22 | "": { 23 | topic: function() { 24 | var cb = this.callback; 25 | return d3.json("//does/not/exist.json", function(json) { 26 | cb(null, json); 27 | }); 28 | }, 29 | "invokes the callback with null when an error occurs": function(json) { 30 | assert.isNull(json); 31 | } 32 | } 33 | } 34 | }); 35 | 36 | suite.export(module); 37 | -------------------------------------------------------------------------------- /test/core/selection-order-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("selection.order"); 7 | 8 | suite.addBatch({ 9 | "selectAll(div)": { 10 | topic: function() { 11 | return d3.select("body").html("").selectAll("div") 12 | .data([1, 2, 10, 20]) 13 | .enter().append("div") 14 | .attr("id", String); 15 | }, 16 | "orders elements by data": function(div) { 17 | div = div.data([1, 10, 20, 2], String).order(); 18 | assert.domNull(div[0][0].previousSibling); 19 | assert.domEqual(div[0][1].previousSibling, div[0][0]); 20 | assert.domEqual(div[0][2].previousSibling, div[0][1]); 21 | assert.domEqual(div[0][3].previousSibling, div[0][2]); 22 | assert.domNull(div[0][3].nextSibling); 23 | }, 24 | "returns the current selection": function(span) { 25 | span = d3.select("body"); // https://github.com/tmpvar/jsdom/issues/277 26 | assert.isTrue(span.order() === span); 27 | } 28 | } 29 | }); 30 | 31 | suite.export(module); 32 | -------------------------------------------------------------------------------- /examples/hello-world/hello-transition.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hello, transition! 5 | 6 | 23 | 24 | 25 | Your lucky number is:
26 |
27 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/scale/quantile.js: -------------------------------------------------------------------------------- 1 | d3.scale.quantile = function() { 2 | return d3_scale_quantile([], []); 3 | }; 4 | 5 | function d3_scale_quantile(domain, range) { 6 | var thresholds; 7 | 8 | function rescale() { 9 | var k = 0, 10 | n = domain.length, 11 | q = range.length; 12 | thresholds = []; 13 | while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q); 14 | return scale; 15 | } 16 | 17 | function scale(x) { 18 | if (isNaN(x = +x)) return NaN; 19 | return range[d3.bisect(thresholds, x)]; 20 | } 21 | 22 | scale.domain = function(x) { 23 | if (!arguments.length) return domain; 24 | domain = x.filter(function(d) { return !isNaN(d); }).sort(d3.ascending); 25 | return rescale(); 26 | }; 27 | 28 | scale.range = function(x) { 29 | if (!arguments.length) return range; 30 | range = x; 31 | return rescale(); 32 | }; 33 | 34 | scale.quantiles = function() { 35 | return thresholds; 36 | }; 37 | 38 | scale.copy = function() { 39 | return d3_scale_quantile(domain, range); // copy on write! 40 | }; 41 | 42 | return rescale(); 43 | } 44 | -------------------------------------------------------------------------------- /examples/data/faithful.json: -------------------------------------------------------------------------------- 1 | [ 2 | 79, 54, 74, 62, 85, 55, 88, 85, 51, 85, 54, 84, 78, 47, 83, 52, 62, 84, 52, 79, 51, 47, 78, 69, 74, 83, 55, 76, 78, 79, 73, 77, 66, 80, 74, 52, 48, 80, 59, 90, 80, 58, 84, 58, 73, 83, 64, 53, 3 | 82, 59, 75, 90, 54, 80, 54, 83, 71, 64, 77, 81, 59, 84, 48, 82, 60, 92, 78, 78, 65, 73, 82, 56, 79, 71, 62, 76, 60, 78, 76, 83, 75, 82, 70, 65, 73, 88, 76, 80, 48, 86, 60, 90, 50, 78, 63, 72, 4 | 84, 75, 51, 82, 62, 88, 49, 83, 81, 47, 84, 52, 86, 81, 75, 59, 89, 79, 59, 81, 50, 85, 59, 87, 53, 69, 77, 56, 88, 81, 45, 82, 55, 90, 45, 83, 56, 89, 46, 82, 51, 86, 53, 79, 81, 60, 82, 77, 5 | 76, 59, 80, 49, 96, 53, 77, 77, 65, 81, 71, 70, 81, 93, 53, 89, 45, 86, 58, 78, 66, 76, 63, 88, 52, 93, 49, 57, 77, 68, 81, 81, 73, 50, 85, 74, 55, 77, 83, 83, 51, 78, 84, 46, 83, 55, 81, 57, 6 | 76, 84, 77, 81, 87, 77, 51, 78, 60, 82, 91, 53, 78, 46, 77, 84, 49, 83, 71, 80, 49, 75, 64, 76, 53, 94, 55, 76, 50, 82, 54, 75, 78, 79, 78, 78, 70, 79, 70, 54, 86, 50, 90, 54, 54, 77, 79, 64, 7 | 75, 47, 86, 63, 85, 82, 57, 82, 67, 74, 54, 83, 73, 73, 88, 80, 71, 83, 56, 79, 78, 84, 58, 83, 43, 60, 75, 81, 46, 90, 46, 74 8 | ] 9 | -------------------------------------------------------------------------------- /test/core/html-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("d3.html"); 7 | 8 | suite.addBatch({ 9 | "html": { 10 | topic: function() { 11 | var cb = this.callback; 12 | return d3.html("examples/data/sample.html", function(document) { 13 | cb(null, document); 14 | }); 15 | }, 16 | "invokes the callback with the loaded html": function(document) { 17 | assert.equal(document.getElementsByTagName("H1")[0].textContent, "Hello & world!"); 18 | }, 19 | "override the mime type to text/html": function(xml) { 20 | assert.equal(XMLHttpRequest._last._info.mimeType, "text/html"); 21 | }, 22 | "": { 23 | topic: function() { 24 | var cb = this.callback; 25 | return d3.html("//does/not/exist.html", function(document) { 26 | cb(null, document); 27 | }); 28 | }, 29 | "invokes the callback with null when an error occurs": function(document) { 30 | assert.isNull(document); 31 | } 32 | } 33 | } 34 | }); 35 | 36 | suite.export(module); 37 | -------------------------------------------------------------------------------- /test/core/transition-test-call.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var assert = require("assert"); 4 | 5 | module.exports = { 6 | topic: function() { 7 | return d3.select("body").append("div").transition(); 8 | }, 9 | "calls the function once": function(transition) { 10 | var count = 0; 11 | transition.call(function() { ++count; }); 12 | assert.equal(count, 1); 13 | }, 14 | "passes any optional arguments": function(transition) { 15 | var abc; 16 | transition.call(function(selection, a, b, c) { abc = [a, b, c]; }, "a", "b", "c"); 17 | assert.deepEqual(abc, ["a", "b", "c"]); 18 | }, 19 | "passes the transition as the first argument": function(transition) { 20 | var t; 21 | transition.call(function(x) { t = x; }); 22 | assert.isTrue(t === transition); 23 | }, 24 | "uses the transition as the context": function(transition) { 25 | var t; 26 | transition.call(function() { t = this; }); 27 | assert.isTrue(t === transition); 28 | }, 29 | "returns the current transition": function(transition) { 30 | assert.isTrue(transition.call(function() {}) === transition); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /examples/line/line-radial.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | 14 | 48 | -------------------------------------------------------------------------------- /test/core/transpose-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("d3.transpose"); 7 | 8 | suite.addBatch({ 9 | "transpose": { 10 | topic: function() { 11 | return d3.transpose; 12 | }, 13 | "transposes a square matrix": function(transpose) { 14 | assert.deepEqual(d3.transpose([[1, 2], [3, 4]]), [[1, 3], [2, 4]]); 15 | }, 16 | "transposes a non-square matrix": function(transpose) { 17 | assert.deepEqual(d3.transpose([[1, 2, 3, 4, 5], [2, 4, 6, 8, 10]]), [[1, 2], [2, 4], [3, 6], [4, 8], [5, 10]]); 18 | }, 19 | "transposes a single-row matrix": function(transpose) { 20 | assert.deepEqual(d3.transpose([[1, 2, 3, 4, 5]]), [[1], [2], [3], [4], [5]]); 21 | }, 22 | "transposes an empty matrix": function(transpose) { 23 | assert.deepEqual(d3.transpose([]), []); 24 | }, 25 | "ignores extra elements given an irregular matrix": function(transpose) { 26 | assert.deepEqual(d3.transpose([[1, 2], [3, 4], [5, 6, 7]]), [[1, 3, 5], [2, 4, 6]]); 27 | } 28 | } 29 | }); 30 | 31 | suite.export(module); 32 | -------------------------------------------------------------------------------- /lib/jquery/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 John Resig, http://jquery.com/ 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /examples/voronoi/voronoi.js: -------------------------------------------------------------------------------- 1 | var width = 960, 2 | height = 500; 3 | 4 | var vertices = d3.range(100).map(function(d) { 5 | return [Math.random() * width, Math.random() * height]; 6 | }); 7 | 8 | var svg = d3.select("#chart") 9 | .append("svg") 10 | .attr("width", width) 11 | .attr("height", height) 12 | .attr("class", "PiYG") 13 | .on("mousemove", update); 14 | 15 | svg.selectAll("path") 16 | .data(d3.geom.voronoi(vertices)) 17 | .enter().append("path") 18 | .attr("class", function(d, i) { return i ? "q" + (i % 9) + "-9" : null; }) 19 | .attr("d", function(d) { return "M" + d.join("L") + "Z"; }); 20 | 21 | svg.selectAll("circle") 22 | .data(vertices.slice(1)) 23 | .enter().append("circle") 24 | .attr("transform", function(d) { return "translate(" + d + ")"; }) 25 | .attr("r", 2); 26 | 27 | function update() { 28 | vertices[0] = d3.mouse(this); 29 | svg.selectAll("path") 30 | .data(d3.geom.voronoi(vertices) 31 | .map(function(d) { return "M" + d.join("L") + "Z"; })) 32 | .filter(function(d) { return this.getAttribute("d") != d; }) 33 | .attr("d", function(d) { return d; }); 34 | } 35 | -------------------------------------------------------------------------------- /examples/delaunay/delaunay.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Delaunay Triangulation 6 | 7 | 17 | 18 | 19 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /examples/hello-world/hello-transform.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hello, world! 5 | 6 | 7 | 8 | Your lucky numbers are:
9 | 10 | 11 | 12 | 13 | 14 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /examples/drag/drag.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 13 | 14 | 15 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /test/core/transition-test-time.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var assert = require("assert"); 4 | 5 | module.exports = { 6 | topic: function() { 7 | return d3.select("body").append("div").transition(); 8 | }, 9 | "is approximately equal to now": function(transition) { 10 | var time = transition.time; 11 | assert.inDelta(time, Date.now(), 20); 12 | }, 13 | "increases monotonically across transitions": function(transition) { 14 | var now = Date.now, then = Date.now(); 15 | try { 16 | Date.now = function() { return ++then; }; 17 | var t0 = d3.select("body").append("div").transition(), 18 | t1 = d3.select("body").append("div").transition(); 19 | assert.isTrue(t1.time > t0.time); 20 | } finally { 21 | Date.now = now; 22 | } 23 | }, 24 | "is inherited by subtransitions": function(transition) { 25 | var now = Date.now, then = Date.now(); 26 | try { 27 | Date.now = function() { return ++then; }; 28 | var t0 = d3.select("body").append("div").transition(), 29 | t1 = t0.transition(); 30 | assert.equal(t1.time, t0.time); 31 | } finally { 32 | Date.now = now; 33 | } 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /examples/pack/pack.js: -------------------------------------------------------------------------------- 1 | var width = 960, 2 | height = 960, 3 | format = d3.format(",d"); 4 | 5 | var pack = d3.layout.pack() 6 | .size([width - 4, height - 4]) 7 | .value(function(d) { return d.size; }); 8 | 9 | var vis = d3.select("#chart").append("svg") 10 | .attr("width", width) 11 | .attr("height", height) 12 | .attr("class", "pack") 13 | .append("g") 14 | .attr("transform", "translate(2, 2)"); 15 | 16 | d3.json("../data/flare.json", function(json) { 17 | var node = vis.data([json]).selectAll("g.node") 18 | .data(pack.nodes) 19 | .enter().append("g") 20 | .attr("class", function(d) { return d.children ? "node" : "leaf node"; }) 21 | .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); 22 | 23 | node.append("title") 24 | .text(function(d) { return d.name + (d.children ? "" : ": " + format(d.size)); }); 25 | 26 | node.append("circle") 27 | .attr("r", function(d) { return d.r; }); 28 | 29 | node.filter(function(d) { return !d.children; }).append("text") 30 | .attr("text-anchor", "middle") 31 | .attr("dy", ".3em") 32 | .text(function(d) { return d.name.substring(0, d.r / 3); }); 33 | }); 34 | -------------------------------------------------------------------------------- /examples/marimekko/marimekko.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"market": "Auburn, AL", "segment": "Almond lovers", "value": 3840}, 3 | {"market": "Auburn, AL", "segment": "Berry buyers", "value": 1920}, 4 | {"market": "Auburn, AL", "segment": "Carrots-n-more", "value": 960}, 5 | {"market": "Auburn, AL", "segment": "Delicious-n-new", "value": 400}, 6 | {"market": "Birmingham, AL", "segment": "Almond lovers", "value": 1600}, 7 | {"market": "Birmingham, AL", "segment": "Berry buyers", "value": 1440}, 8 | {"market": "Birmingham, AL", "segment": "Carrots-n-more", "value": 960}, 9 | {"market": "Birmingham, AL", "segment": "Delicious-n-new", "value": 400}, 10 | {"market": "Gainesville, FL", "segment": "Almond lovers", "value": 640}, 11 | {"market": "Gainesville, FL", "segment": "Berry buyers", "value": 960}, 12 | {"market": "Gainesville, FL", "segment": "Carrots-n-more", "value": 640}, 13 | {"market": "Gainesville, FL", "segment": "Delicious-n-new", "value": 400}, 14 | {"market": "Durham, NC", "segment": "Almond lovers", "value": 320}, 15 | {"market": "Durham, NC", "segment": "Berry buyers", "value": 480}, 16 | {"market": "Durham, NC", "segment": "Carrots-n-more", "value": 640}, 17 | {"market": "Durham, NC", "segment": "Delicious-n-new", "value": 400} 18 | ] 19 | -------------------------------------------------------------------------------- /test/core/selection-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("d3.selection"); 7 | 8 | suite.addBatch({ 9 | "selection": { 10 | topic: function() { 11 | return d3.selection(); 12 | }, 13 | "selects the document": function(selection) { 14 | assert.equal(selection.length, 1); 15 | assert.equal(selection[0].length, 1); 16 | assert.equal(selection[0][0], document); 17 | }, 18 | "is an instanceof d3.selection": function(selection) { 19 | assert.instanceOf(selection, d3.selection); 20 | }, 21 | "subselections are also instanceof d3.selection": function(selection) { 22 | assert.instanceOf(selection.select("body"), d3.selection); 23 | assert.instanceOf(selection.selectAll("body"), d3.selection); 24 | }, 25 | "selection prototype can be extended": function(selection) { 26 | d3.selection.prototype.foo = function(v) { return this.attr("foo", v); }; 27 | selection.select("body").foo(42); 28 | assert.equal(document.body.getAttribute("foo"), "42"); 29 | delete d3.selection.prototype.foo; 30 | } 31 | } 32 | }); 33 | 34 | suite.export(module); 35 | -------------------------------------------------------------------------------- /test/layout/tree-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("d3.layout.tree"); 7 | 8 | suite.addBatch({ 9 | "tree": { 10 | topic: d3.layout.tree, 11 | "can handle an empty children array": function(tree) { 12 | assert.deepEqual(tree.nodes({children: []}).map(layout), [ 13 | {depth: 0, x: 0.5, y: 0} 14 | ]); 15 | assert.deepEqual(tree.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 | assert.deepEqual(tree.nodes({value: 0}).map(layout), [ 30 | {depth: 0, x: 0.5, y: 0} 31 | ]); 32 | } 33 | } 34 | }); 35 | 36 | function layout(node) { 37 | return { 38 | depth: node.depth, 39 | x: node.x, 40 | y: node.y 41 | }; 42 | } 43 | 44 | suite.export(module); 45 | -------------------------------------------------------------------------------- /examples/line/line-radial-defined.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | 14 | 51 | -------------------------------------------------------------------------------- /examples/choropleth/choropleth-area.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 15 | 16 | 17 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /examples/tree/tree.js: -------------------------------------------------------------------------------- 1 | var width = 960, 2 | height = 2000; 3 | 4 | var tree = d3.layout.tree() 5 | .size([height, width - 160]); 6 | 7 | var diagonal = d3.svg.diagonal() 8 | .projection(function(d) { return [d.y, d.x]; }); 9 | 10 | var vis = d3.select("#chart").append("svg") 11 | .attr("width", width) 12 | .attr("height", height) 13 | .append("g") 14 | .attr("transform", "translate(40, 0)"); 15 | 16 | d3.json("../data/flare.json", function(json) { 17 | var nodes = tree.nodes(json); 18 | 19 | var link = vis.selectAll("path.link") 20 | .data(tree.links(nodes)) 21 | .enter().append("path") 22 | .attr("class", "link") 23 | .attr("d", diagonal); 24 | 25 | var node = vis.selectAll("g.node") 26 | .data(nodes) 27 | .enter().append("g") 28 | .attr("class", "node") 29 | .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; }) 30 | 31 | node.append("circle") 32 | .attr("r", 4.5); 33 | 34 | node.append("text") 35 | .attr("dx", function(d) { return d.children ? -8 : 8; }) 36 | .attr("dy", 3) 37 | .attr("text-anchor", function(d) { return d.children ? "end" : "start"; }) 38 | .text(function(d) { return d.name; }); 39 | }); 40 | -------------------------------------------------------------------------------- /examples/treemap/treemap-svg.js: -------------------------------------------------------------------------------- 1 | var width = 960, 2 | height = 500, 3 | color = d3.scale.category20c(); 4 | 5 | var treemap = d3.layout.treemap() 6 | .padding(4) 7 | .size([width, height]) 8 | .value(function(d) { return d.size; }); 9 | 10 | var svg = d3.select("body").append("svg") 11 | .attr("width", width) 12 | .attr("height", height) 13 | .append("g") 14 | .attr("transform", "translate(-.5,-.5)"); 15 | 16 | d3.json("../data/flare.json", function(json) { 17 | var cell = svg.data([json]).selectAll("g") 18 | .data(treemap) 19 | .enter().append("g") 20 | .attr("class", "cell") 21 | .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); 22 | 23 | cell.append("rect") 24 | .attr("width", function(d) { return d.dx; }) 25 | .attr("height", function(d) { return d.dy; }) 26 | .style("fill", function(d) { return d.children ? color(d.data.name) : null; }); 27 | 28 | cell.append("text") 29 | .attr("x", function(d) { return d.dx / 2; }) 30 | .attr("y", function(d) { return d.dy / 2; }) 31 | .attr("dy", ".35em") 32 | .attr("text-anchor", "middle") 33 | .text(function(d) { return d.children ? null : d.data.name; }); 34 | }); 35 | -------------------------------------------------------------------------------- /test/geo/greatArc-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("d3.geo.greatArc"); 7 | 8 | suite.addBatch({ 9 | "greatArc": { 10 | topic: function() { 11 | return d3.geo.greatArc(); 12 | }, 13 | "distance": function(arc) { 14 | assert.equal(arc.distance({source: [0, 0], target: [0, 0]}), 0); 15 | assert.inDelta(arc.distance({ 16 | source: [118 + 24 / 60, 33 + 57 / 60], 17 | target: [ 73 + 47 / 60, 40 + 38 / 60] 18 | }), 3973 / 6371, .5); 19 | }, 20 | "geodesic": function(arc) { 21 | assert.inDelta(arc.precision(7.2)({source: [5, 52], target: [-120, 37]}).coordinates, [ 22 | [ 5, 52 ], 23 | [ -3.805036, 57.05083], 24 | [ -15.122869, 61.30118], 25 | [ -29.396213, 64.34584], 26 | [ -46.132729, 65.72409], 27 | [ -63.394401, 65.15597], 28 | [ -78.854311, 62.76337], 29 | [ -91.401599, 58.96701], 30 | [-101.190927, 54.21333], 31 | [-108.843633, 48.83586], 32 | [-114.961152, 43.05231], 33 | [-120, 37 ] 34 | ], .5); 35 | } 36 | } 37 | }); 38 | 39 | suite.export(module); 40 | -------------------------------------------------------------------------------- /examples/cluster/cluster.js: -------------------------------------------------------------------------------- 1 | var width = 960, 2 | height = 2200; 3 | 4 | var cluster = d3.layout.cluster() 5 | .size([height, width - 160]); 6 | 7 | var diagonal = d3.svg.diagonal() 8 | .projection(function(d) { return [d.y, d.x]; }); 9 | 10 | var vis = d3.select("#chart").append("svg") 11 | .attr("width", width) 12 | .attr("height", height) 13 | .append("g") 14 | .attr("transform", "translate(40, 0)"); 15 | 16 | d3.json("../data/flare.json", function(json) { 17 | var nodes = cluster.nodes(json); 18 | 19 | var link = vis.selectAll("path.link") 20 | .data(cluster.links(nodes)) 21 | .enter().append("path") 22 | .attr("class", "link") 23 | .attr("d", diagonal); 24 | 25 | var node = vis.selectAll("g.node") 26 | .data(nodes) 27 | .enter().append("g") 28 | .attr("class", "node") 29 | .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; }) 30 | 31 | node.append("circle") 32 | .attr("r", 4.5); 33 | 34 | node.append("text") 35 | .attr("dx", function(d) { return d.children ? -8 : 8; }) 36 | .attr("dy", 3) 37 | .attr("text-anchor", function(d) { return d.children ? "end" : "start"; }) 38 | .text(function(d) { return d.name; }); 39 | }); 40 | -------------------------------------------------------------------------------- /src/core/mouse.js: -------------------------------------------------------------------------------- 1 | d3.mouse = function(container) { 2 | return d3_mousePoint(container, d3_eventSource()); 3 | }; 4 | 5 | // https://bugs.webkit.org/show_bug.cgi?id=44083 6 | var d3_mouse_bug44083 = /WebKit/.test(navigator.userAgent) ? -1 : 0; 7 | 8 | function d3_mousePoint(container, e) { 9 | var svg = container.ownerSVGElement || container; 10 | if (svg.createSVGPoint) { 11 | var point = svg.createSVGPoint(); 12 | if ((d3_mouse_bug44083 < 0) && (window.scrollX || window.scrollY)) { 13 | svg = d3.select(document.body) 14 | .append("svg") 15 | .style("position", "absolute") 16 | .style("top", 0) 17 | .style("left", 0); 18 | var ctm = svg[0][0].getScreenCTM(); 19 | d3_mouse_bug44083 = !(ctm.f || ctm.e); 20 | svg.remove(); 21 | } 22 | if (d3_mouse_bug44083) { 23 | point.x = e.pageX; 24 | point.y = e.pageY; 25 | } else { 26 | point.x = e.clientX; 27 | point.y = e.clientY; 28 | } 29 | point = point.matrixTransform(container.getScreenCTM().inverse()); 30 | return [point.x, point.y]; 31 | } 32 | var rect = container.getBoundingClientRect(); 33 | return [e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop]; 34 | }; 35 | -------------------------------------------------------------------------------- /test/core/entries-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("d3.entries"); 7 | 8 | suite.addBatch({ 9 | "entries": { 10 | topic: function() { 11 | return d3.entries; 12 | }, 13 | "enumerates every entry": function(entries) { 14 | assert.deepEqual(entries({a: 1, b: 2}), [ 15 | {key: "a", value: 1}, 16 | {key: "b", value: 2} 17 | ]); 18 | }, 19 | "includes entries defined on prototypes": function(entries) { 20 | function abc() { 21 | this.a = 1; 22 | this.b = 2; 23 | } 24 | abc.prototype.c = 3; 25 | assert.deepEqual(entries(new abc()), [ 26 | {key: "a", value: 1}, 27 | {key: "b", value: 2}, 28 | {key: "c", value: 3} 29 | ]); 30 | }, 31 | "includes null or undefined values": function(entries) { 32 | var v = entries({a: undefined, b: null, c: NaN}); 33 | assert.equal(v.length, 3); 34 | assert.deepEqual(v[0], {key: "a", value: undefined}); 35 | assert.deepEqual(v[1], {key: "b", value: null}); 36 | assert.equal(v[2].key, "c"); 37 | assert.isNaN(v[2].value); 38 | } 39 | } 40 | }); 41 | 42 | suite.export(module); 43 | -------------------------------------------------------------------------------- /examples/hello-world/hello-data.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hello, data! 5 | 6 | 7 | 8 | Your lucky numbers are:
9 | 10 | 11 | 12 | 13 | 14 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /test/core/selection-remove-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("selection.remove"); 7 | 8 | suite.addBatch({ 9 | "select(body)": { 10 | topic: function() { 11 | return d3.select("body"); 12 | }, 13 | "removes the matching elements": function(body) { 14 | var div = body.append("div"); 15 | div.remove(); 16 | assert.domNull(div[0][0].parentNode); 17 | }, 18 | "does not remove non-matching elements": function(body) { 19 | var div1 = body.append("div"), div2 = body.append("div"); 20 | div1.remove(); 21 | assert.domEqual(div2[0][0].parentNode, document.body); 22 | }, 23 | "ignores null nodes": function(body) { 24 | var div = body.html("").selectAll("div").data([0, 1]).enter().append("div"), 25 | some = d3.selectAll("div"); 26 | some[0][0] = null; 27 | some.remove(); 28 | assert.domEqual(div[0][0].parentNode, document.body); 29 | assert.domNull(div[0][1].parentNode); 30 | }, 31 | "returns the current selection": function(body) { 32 | var div = body.append("div"); 33 | assert.isTrue(div.remove() === div); 34 | } 35 | } 36 | }); 37 | 38 | suite.export(module); 39 | -------------------------------------------------------------------------------- /test/csv/format-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("d3.csv.format"); 7 | 8 | suite.addBatch({ 9 | "format": { 10 | topic: function() { 11 | return d3.csv.format; 12 | }, 13 | "takes an array of arrays as input": function(format) { 14 | assert.equal(format([["a", "b", "c"], ["1", "2", "3"]]), "a,b,c\n1,2,3"); 15 | }, 16 | "separates lines using unix newline": function(format) { 17 | assert.equal(format([[], []]), "\n"); 18 | }, 19 | "does not strip whitespace": function(format) { 20 | assert.equal(format([["a ", " b", "c"], ["1", "2", "3 "]]), "a , b,c\n1,2,3 "); 21 | }, 22 | "does not quote simple values": function(format) { 23 | assert.equal(format([["a"], [1]]), "a\n1"); 24 | }, 25 | "escapes double quotes": function(format) { 26 | assert.equal(format([["\"fish\""]]), "\"\"\"fish\"\"\""); 27 | }, 28 | "escapes unix newlines": function(format) { 29 | assert.equal(format([["new\nline"]]), "\"new\nline\""); 30 | }, 31 | "escapes commas": function(format) { 32 | assert.equal(format([["oxford,comma"]]), "\"oxford,comma\""); 33 | } 34 | } 35 | }); 36 | 37 | suite.export(module); 38 | -------------------------------------------------------------------------------- /examples/axis/axis-explicit-ticks.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 18 | 19 | 20 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /test/geo/circle-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("d3.geo.circle"); 7 | 8 | suite.addBatch({ 9 | "circle": { 10 | "clip": { 11 | topic: function() { 12 | return d3.geo.circle().origin([-71.03, -42.37]).clip; 13 | }, 14 | "grid component": function(clip) { 15 | var yStepsBig = d3.range(-90, 90, 10); 16 | assert.inDelta(clip({type: "LineString", coordinates: yStepsBig.map(function(y) { return [110, y]; })}).coordinates, [ 17 | [110, -90], 18 | [110, -84], 19 | [110, -80], 20 | [110, -74], 21 | [110, -70], 22 | [110, -64], 23 | [110, -60], 24 | [110, -54], 25 | [110, -50], 26 | [110, -47.63539018933809] 27 | ], 1e-6); 28 | }, 29 | "can completely clip a LineString": function(clip) { 30 | assert.isNull(clip({type: "LineString", coordinates: [[90.0, -42.37], [95.0, -42.37], [90.0, -42.37]]})); 31 | }, 32 | "doesn't insert a duplicate point": function(clip) { 33 | assert.inDelta(clip({type: "LineString", coordinates: [[0, 0]]}).coordinates, [[0, 0]], 1e-6); 34 | } 35 | } 36 | } 37 | }); 38 | 39 | suite.export(module); 40 | -------------------------------------------------------------------------------- /examples/partition/partition-icicle.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Partition - Icicle 6 | 7 | 14 | 15 | 16 |
17 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /examples/stream/stream.js: -------------------------------------------------------------------------------- 1 | var n = 20, // number of layers 2 | m = 200, // number of samples per layer 3 | data0 = d3.layout.stack().offset("wiggle")(stream_layers(n, m)), 4 | data1 = d3.layout.stack().offset("wiggle")(stream_layers(n, m)), 5 | color = d3.interpolateRgb("#aad", "#556"); 6 | 7 | var width = 960, 8 | height = 500, 9 | mx = m - 1, 10 | my = d3.max(data0.concat(data1), function(d) { 11 | return d3.max(d, function(d) { 12 | return d.y0 + d.y; 13 | }); 14 | }); 15 | 16 | var area = d3.svg.area() 17 | .x(function(d) { return d.x * width / mx; }) 18 | .y0(function(d) { return height - d.y0 * height / my; }) 19 | .y1(function(d) { return height - (d.y + d.y0) * height / my; }); 20 | 21 | var vis = d3.select("#chart") 22 | .append("svg") 23 | .attr("width", width) 24 | .attr("height", height); 25 | 26 | vis.selectAll("path") 27 | .data(data0) 28 | .enter().append("path") 29 | .style("fill", function() { return color(Math.random()); }) 30 | .attr("d", area); 31 | 32 | function transition() { 33 | d3.selectAll("path") 34 | .data(function() { 35 | var d = data1; 36 | data1 = data0; 37 | return data0 = d; 38 | }) 39 | .transition() 40 | .duration(2500) 41 | .attr("d", area); 42 | } 43 | -------------------------------------------------------------------------------- /src/layout/partition.js: -------------------------------------------------------------------------------- 1 | d3.layout.partition = function() { 2 | var hierarchy = d3.layout.hierarchy(), 3 | size = [1, 1]; // width, height 4 | 5 | function position(node, x, dx, dy) { 6 | var children = node.children; 7 | node.x = x; 8 | node.y = node.depth * dy; 9 | node.dx = dx; 10 | node.dy = dy; 11 | if (children && (n = children.length)) { 12 | var i = -1, 13 | n, 14 | c, 15 | d; 16 | dx = node.value ? dx / node.value : 0; 17 | while (++i < n) { 18 | position(c = children[i], x, d = c.value * dx, dy); 19 | x += d; 20 | } 21 | } 22 | } 23 | 24 | function depth(node) { 25 | var children = node.children, 26 | d = 0; 27 | if (children && (n = children.length)) { 28 | var i = -1, 29 | n; 30 | while (++i < n) d = Math.max(d, depth(children[i])); 31 | } 32 | return 1 + d; 33 | } 34 | 35 | function partition(d, i) { 36 | var nodes = hierarchy.call(this, d, i); 37 | position(nodes[0], 0, size[0], size[1] / depth(nodes[0])); 38 | return nodes; 39 | } 40 | 41 | partition.size = function(x) { 42 | if (!arguments.length) return size; 43 | size = x; 44 | return partition; 45 | }; 46 | 47 | return d3_layout_hierarchyRebind(partition, hierarchy); 48 | }; 49 | -------------------------------------------------------------------------------- /test/layout/cluster-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("d3.layout.cluster"); 7 | 8 | suite.addBatch({ 9 | "cluster": { 10 | topic: d3.layout.cluster, 11 | "can handle an empty children array": function(cluster) { 12 | assert.deepEqual(cluster.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 | assert.deepEqual(cluster.nodes({value: 0, children: [{value: 0}, {value: 1}]}).map(layout), [ 20 | {value: 0, depth: 0, x: 0.5, y: 0}, 21 | {value: 0, depth: 1, x: 0.25, y: 1}, 22 | {value: 1, depth: 1, x: 0.75, y: 1} 23 | ]); 24 | }, 25 | "can handle a single node": function(cluster) { 26 | assert.deepEqual(cluster.nodes({value: 0}).map(layout), [ 27 | {value: 0, depth: 0, x: 0.5, y: 0} 28 | ]); 29 | } 30 | } 31 | }); 32 | 33 | function layout(node) { 34 | return { 35 | value: node.value, 36 | depth: node.depth, 37 | x: node.x, 38 | y: node.y 39 | }; 40 | } 41 | 42 | suite.export(module); 43 | -------------------------------------------------------------------------------- /examples/horizon/unemployment.json: -------------------------------------------------------------------------------- 1 | {"year":[2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2001,2001,2001,2001,2001,2001,2001,2001,2001,2001,2001,2001,2002,2002,2002,2002,2002,2002,2002,2002,2002,2002,2002,2002,2003,2003,2003,2003,2003,2003,2003,2003,2003,2003,2003,2003,2004,2004,2004,2004,2004,2004,2004,2004,2004,2004,2004,2004,2005,2005,2005,2005,2005,2005,2005,2005,2005,2005,2005,2005,2006,2006,2006,2006,2006,2006,2006,2006,2006,2006,2006,2006,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2007,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2008,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2009,2010,2010],"month":[1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12,1,2],"rate":[4.5,4.4,4.3,3.7,3.8,4.1,4.2,4.1,3.8,3.6,3.7,3.7,4.7,4.6,4.5,4.2,4.1,4.7,4.7,4.9,4.7,5,5.3,5.4,6.3,6.1,6.1,5.7,5.5,6,5.9,5.7,5.4,5.3,5.6,5.7,6.5,6.4,6.2,5.8,5.8,6.5,6.3,6,5.8,5.6,5.6,5.4,6.3,6,6,5.4,5.3,5.8,5.7,5.4,5.1,5.1,5.2,5.1,5.7,5.8,5.4,4.9,4.9,5.2,5.2,4.9,4.8,4.6,4.8,4.6,5.1,5.1,4.8,4.5,4.4,4.8,5,4.6,4.4,4.1,4.3,4.3,5,4.9,4.5,4.3,4.3,4.7,4.9,4.6,4.5,4.4,4.5,4.8,5.4,5.2,5.2,4.8,5.2,5.7,6,6.1,6,6.1,6.5,7.1,8.5,8.9,9,8.6,9.1,9.7,9.7,9.6,9.5,9.5,9.4,9.7,10.6,10.4]} -------------------------------------------------------------------------------- /src/core/map.js: -------------------------------------------------------------------------------- 1 | d3.map = function(object) { 2 | var map = new d3_Map; 3 | for (var key in object) map.set(key, object[key]); 4 | return map; 5 | }; 6 | 7 | function d3_Map() {} 8 | 9 | d3_class(d3_Map, { 10 | has: function(key) { 11 | return d3_map_prefix + key in this; 12 | }, 13 | get: function(key) { 14 | return this[d3_map_prefix + key]; 15 | }, 16 | set: function(key, value) { 17 | return this[d3_map_prefix + key] = value; 18 | }, 19 | remove: function(key) { 20 | key = d3_map_prefix + key; 21 | return key in this && delete this[key]; 22 | }, 23 | keys: function() { 24 | var keys = []; 25 | this.forEach(function(key) { keys.push(key); }); 26 | return keys; 27 | }, 28 | values: function() { 29 | var values = []; 30 | this.forEach(function(key, value) { values.push(value); }); 31 | return values; 32 | }, 33 | entries: function() { 34 | var entries = []; 35 | this.forEach(function(key, value) { entries.push({key: key, value: value}); }); 36 | return entries; 37 | }, 38 | forEach: function(f) { 39 | for (var key in this) { 40 | if (key.charCodeAt(0) === d3_map_prefixCode) { 41 | f.call(this, key.substring(1), this[key]); 42 | } 43 | } 44 | } 45 | }); 46 | 47 | var d3_map_prefix = "\0", // prevent collision with built-ins 48 | d3_map_prefixCode = d3_map_prefix.charCodeAt(0); 49 | -------------------------------------------------------------------------------- /test/core/select-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("d3.select"); 7 | 8 | suite.addBatch({ 9 | "select": { 10 | topic: function() { 11 | var body = d3.select("body").html(""); 12 | body.append("span").attr("class", "f00").attr("id", "b4r").attr("name", "b4z"); 13 | body.append("div").attr("class", "foo").attr("id", "bar").attr("name", "baz"); 14 | return body; 15 | }, 16 | "selects by element name": function() { 17 | var div = d3.select("div"); 18 | assert.equal(div[0][0].tagName, "DIV"); 19 | }, 20 | "selects by class name": function() { 21 | var div = d3.select(".foo"); 22 | assert.equal(div[0][0].className, "foo"); 23 | }, 24 | "selects by id": function() { 25 | var div = d3.select("div#bar"); 26 | assert.equal(div[0][0].id, "bar"); 27 | }, 28 | "selects by attribute value": function() { 29 | var div = d3.select("[name=baz]"); 30 | assert.equal(div[0][0].getAttribute("name"), "baz"); 31 | }, 32 | "selects by node": function() { 33 | var div = d3.select(document.body.lastChild); 34 | assert.isTrue(div[0][0] === document.body.lastChild); 35 | assert.lengthOf(div, 1); 36 | assert.lengthOf(div[0], 1); 37 | } 38 | } 39 | }); 40 | 41 | suite.export(module); 42 | -------------------------------------------------------------------------------- /examples/hello-world/hello-event.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hello, world! 5 | 6 | 7 | 8 | Your lucky numbers are:
9 | 10 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /examples/cluster/cluster-radial.js: -------------------------------------------------------------------------------- 1 | var radius = 960 / 2; 2 | 3 | var cluster = d3.layout.cluster() 4 | .size([360, radius - 120]); 5 | 6 | var diagonal = d3.svg.diagonal.radial() 7 | .projection(function(d) { return [d.y, d.x / 180 * Math.PI]; }); 8 | 9 | var vis = d3.select("#chart").append("svg") 10 | .attr("width", radius * 2) 11 | .attr("height", radius * 2) 12 | .append("g") 13 | .attr("transform", "translate(" + radius + "," + radius + ")"); 14 | 15 | d3.json("../data/flare.json", function(json) { 16 | var nodes = cluster.nodes(json); 17 | 18 | var link = vis.selectAll("path.link") 19 | .data(cluster.links(nodes)) 20 | .enter().append("path") 21 | .attr("class", "link") 22 | .attr("d", diagonal); 23 | 24 | var node = vis.selectAll("g.node") 25 | .data(nodes) 26 | .enter().append("g") 27 | .attr("class", "node") 28 | .attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; }) 29 | 30 | node.append("circle") 31 | .attr("r", 4.5); 32 | 33 | node.append("text") 34 | .attr("dx", function(d) { return d.x < 180 ? 8 : -8; }) 35 | .attr("dy", ".31em") 36 | .attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; }) 37 | .attr("transform", function(d) { return d.x < 180 ? null : "rotate(180)"; }) 38 | .text(function(d) { return d.name; }); 39 | }); 40 | -------------------------------------------------------------------------------- /src/core/selection-attr.js: -------------------------------------------------------------------------------- 1 | d3_selectionPrototype.attr = function(name, value) { 2 | name = d3.ns.qualify(name); 3 | 4 | // If no value is specified, return the first value. 5 | if (arguments.length < 2) { 6 | var node = this.node(); 7 | return name.local 8 | ? node.getAttributeNS(name.space, name.local) 9 | : node.getAttribute(name); 10 | } 11 | 12 | function attrNull() { 13 | this.removeAttribute(name); 14 | } 15 | 16 | function attrNullNS() { 17 | this.removeAttributeNS(name.space, name.local); 18 | } 19 | 20 | function attrConstant() { 21 | this.setAttribute(name, value); 22 | } 23 | 24 | function attrConstantNS() { 25 | this.setAttributeNS(name.space, name.local, value); 26 | } 27 | 28 | function attrFunction() { 29 | var x = value.apply(this, arguments); 30 | if (x == null) this.removeAttribute(name); 31 | else this.setAttribute(name, x); 32 | } 33 | 34 | function attrFunctionNS() { 35 | var x = value.apply(this, arguments); 36 | if (x == null) this.removeAttributeNS(name.space, name.local); 37 | else this.setAttributeNS(name.space, name.local, x); 38 | } 39 | 40 | return this.each(value == null 41 | ? (name.local ? attrNullNS : attrNull) : (typeof value === "function" 42 | ? (name.local ? attrFunctionNS : attrFunction) 43 | : (name.local ? attrConstantNS : attrConstant))); 44 | }; 45 | -------------------------------------------------------------------------------- /examples/data/us-borders.json: -------------------------------------------------------------------------------- 1 | {"30":["38","46","56","16"],"51":["24","37","47","21","54"],"45":["37","13"],"50":["33","25","36"],"19":["27","55","17","29","31","46"],"26":["39","18","55"],"35":["08","40","48","04"],"41":["53","16","32","06"],"04":["35","49","32","06"],"02":[],"25":["33","44","09","36"],"23":["33"],"01":["28","13","12","47"],"06":["41","32","04"],"21":["39","54","51","47","29","17","18"],"22":["05","28","48"],"05":["28","22","48","40","29","47"],"46":["38","27","19","31","56","30"],"47":["21","51","37","13","01","28","05","29"],"08":["35","49","56","31","20","40"],"09":["25","44","36"],"42":["36","34","10","24","54","39"],"29":["19","17","21","47","05","40","20","31"],"40":["20","29","05","48","35","08"],"18":["26","39","21","17"],"27":["55","19","46","38"],"28":["47","01","22","05"],"24":["10","42","54","51","11"],"39":["42","54","21","18","26"],"38":["68","46","30"],"20":["31","29","40","08"],"11":["24","51"],"10":["34","42","24"],"13":["12","01","47","37","45"],"12":["13","01"],"15":[],"48":["27","40","05","22"],"17":["18","21","29","19","55"],"16":["30","56","49","32","41","53"],"55":["26","17","19","27"],"54":["42","24","51","21","39"],"31":["46","19","29","20","08","56"],"56":["30","46","31","08","49","16"],"37":["51","45","13","47"],"36":["50","25","09","34","42"],"53":["16","41"],"34":["36","10","42"],"33":["23","25","50"],"32":["16","49","04","06","41"],"49":["16","56","08","04","32"],"44":["25","09"]} 2 | -------------------------------------------------------------------------------- /lib/jquery-ui/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 Paul Bakaus, http://jqueryui.com/ 2 | 3 | This software consists of voluntary contributions made by many 4 | individuals (AUTHORS.txt, http://jqueryui.com/about) For exact 5 | contribution history, see the revision history and logs, available 6 | at http://jquery-ui.googlecode.com/svn/ 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining 9 | a copy of this software and associated documentation files (the 10 | "Software"), to deal in the Software without restriction, including 11 | without limitation the rights to use, copy, modify, merge, publish, 12 | distribute, sublicense, and/or sell copies of the Software, and to 13 | permit persons to whom the Software is furnished to do so, subject to 14 | the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be 17 | included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 23 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /examples/bundle/packages.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | packages = { 3 | 4 | // Lazily construct the package hierarchy from class names. 5 | root: function(classes) { 6 | var map = {}; 7 | 8 | function find(name, data) { 9 | var node = map[name], i; 10 | if (!node) { 11 | node = map[name] = data || {name: name, children: []}; 12 | if (name.length) { 13 | node.parent = find(name.substring(0, i = name.lastIndexOf("."))); 14 | node.parent.children.push(node); 15 | node.key = name.substring(i + 1); 16 | } 17 | } 18 | return node; 19 | } 20 | 21 | classes.forEach(function(d) { 22 | find(d.name, d); 23 | }); 24 | 25 | return map[""]; 26 | }, 27 | 28 | // Return a list of imports for the given array of nodes. 29 | imports: function(nodes) { 30 | var map = {}, 31 | imports = []; 32 | 33 | // Compute a map from name to node. 34 | nodes.forEach(function(d) { 35 | map[d.name] = d; 36 | }); 37 | 38 | // For each import, construct a link from the source to target node. 39 | nodes.forEach(function(d) { 40 | if (d.imports) d.imports.forEach(function(i) { 41 | imports.push({source: map[d.name], target: map[i]}); 42 | }); 43 | }); 44 | 45 | return imports; 46 | } 47 | 48 | }; 49 | })(); 50 | -------------------------------------------------------------------------------- /examples/moire/moire.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Moiré Patterns 6 | 7 | 15 | 16 | 17 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /examples/area/area-radial.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | 17 | 18 | 62 | -------------------------------------------------------------------------------- /examples/data/morley.csv: -------------------------------------------------------------------------------- 1 | Expt,Run,Speed 2 | 1,1,850 3 | 1,2,740 4 | 1,3,900 5 | 1,4,1070 6 | 1,5,930 7 | 1,6,850 8 | 1,7,950 9 | 1,8,980 10 | 1,9,980 11 | 1,10,880 12 | 1,11,1000 13 | 1,12,980 14 | 1,13,930 15 | 1,14,650 16 | 1,15,760 17 | 1,16,810 18 | 1,17,1000 19 | 1,18,1000 20 | 1,19,960 21 | 1,20,960 22 | 2,1,960 23 | 2,2,940 24 | 2,3,960 25 | 2,4,940 26 | 2,5,880 27 | 2,6,800 28 | 2,7,850 29 | 2,8,880 30 | 2,9,900 31 | 2,10,840 32 | 2,11,830 33 | 2,12,790 34 | 2,13,810 35 | 2,14,880 36 | 2,15,880 37 | 2,16,830 38 | 2,17,800 39 | 2,18,790 40 | 2,19,760 41 | 2,20,800 42 | 3,1,880 43 | 3,2,880 44 | 3,3,880 45 | 3,4,860 46 | 3,5,720 47 | 3,6,720 48 | 3,7,620 49 | 3,8,860 50 | 3,9,970 51 | 3,10,950 52 | 3,11,880 53 | 3,12,910 54 | 3,13,850 55 | 3,14,870 56 | 3,15,840 57 | 3,16,840 58 | 3,17,850 59 | 3,18,840 60 | 3,19,840 61 | 3,20,840 62 | 4,1,890 63 | 4,2,810 64 | 4,3,810 65 | 4,4,820 66 | 4,5,800 67 | 4,6,770 68 | 4,7,760 69 | 4,8,740 70 | 4,9,750 71 | 4,10,760 72 | 4,11,910 73 | 4,12,920 74 | 4,13,890 75 | 4,14,860 76 | 4,15,880 77 | 4,16,720 78 | 4,17,840 79 | 4,18,850 80 | 4,19,850 81 | 4,20,780 82 | 5,1,890 83 | 5,2,840 84 | 5,3,780 85 | 5,4,810 86 | 5,5,760 87 | 5,6,810 88 | 5,7,790 89 | 5,8,810 90 | 5,9,820 91 | 5,10,850 92 | 5,11,870 93 | 5,12,870 94 | 5,13,810 95 | 5,14,740 96 | 5,15,810 97 | 5,16,940 98 | 5,17,950 99 | 5,18,800 100 | 5,19,810 101 | 5,20,870 102 | -------------------------------------------------------------------------------- /examples/force/force.js: -------------------------------------------------------------------------------- 1 | var width = 960, 2 | height = 500; 3 | 4 | var color = d3.scale.category20(); 5 | 6 | var force = d3.layout.force() 7 | .charge(-120) 8 | .linkDistance(30) 9 | .size([width, height]); 10 | 11 | var svg = d3.select("#chart").append("svg") 12 | .attr("width", width) 13 | .attr("height", height); 14 | 15 | d3.json("miserables.json", function(json) { 16 | force 17 | .nodes(json.nodes) 18 | .links(json.links) 19 | .start(); 20 | 21 | var link = svg.selectAll("line.link") 22 | .data(json.links) 23 | .enter().append("line") 24 | .attr("class", "link") 25 | .style("stroke-width", function(d) { return Math.sqrt(d.value); }); 26 | 27 | var node = svg.selectAll("circle.node") 28 | .data(json.nodes) 29 | .enter().append("circle") 30 | .attr("class", "node") 31 | .attr("r", 5) 32 | .style("fill", function(d) { return color(d.group); }) 33 | .call(force.drag); 34 | 35 | node.append("title") 36 | .text(function(d) { return d.name; }); 37 | 38 | force.on("tick", function() { 39 | link.attr("x1", function(d) { return d.source.x; }) 40 | .attr("y1", function(d) { return d.source.y; }) 41 | .attr("x2", function(d) { return d.target.x; }) 42 | .attr("y2", function(d) { return d.target.y; }); 43 | 44 | node.attr("cx", function(d) { return d.x; }) 45 | .attr("cy", function(d) { return d.y; }); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /test/core/ascending-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("d3.ascending"); 7 | 8 | suite.addBatch({ 9 | "numbers": { 10 | "returns a negative number if a < b": function() { 11 | assert.isTrue(d3.ascending(0, 1) < 0); 12 | }, 13 | "returns a positive number if a > b": function() { 14 | assert.isTrue(d3.ascending(1, 0) > 0); 15 | }, 16 | "returns zero if a == b": function() { 17 | assert.equal(d3.ascending(0, 0), 0); 18 | }, 19 | "returns NaN if a or b is undefined": function() { 20 | assert.isNaN(d3.ascending(0, undefined)); 21 | assert.isNaN(d3.ascending(undefined, 0)); 22 | assert.isNaN(d3.ascending(undefined, undefined)); 23 | }, 24 | "returns NaN if a or b is NaN": function() { 25 | assert.isNaN(d3.ascending(0, NaN)); 26 | assert.isNaN(d3.ascending(NaN, 0)); 27 | assert.isNaN(d3.ascending(NaN, NaN)); 28 | } 29 | } 30 | }); 31 | 32 | suite.addBatch({ 33 | "strings": { 34 | "returns a negative number if a < b": function() { 35 | assert.isTrue(d3.ascending("a", "b") < 0); 36 | }, 37 | "returns a positive number if a > b": function() { 38 | assert.isTrue(d3.ascending("b", "a") > 0); 39 | }, 40 | "returns zero if a == b": function() { 41 | assert.equal(d3.ascending("a", "a"), 0); 42 | } 43 | } 44 | }); 45 | 46 | suite.export(module); 47 | -------------------------------------------------------------------------------- /test/core/text-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("d3.text"); 7 | 8 | suite.addBatch({ 9 | "text": { 10 | topic: function() { 11 | var cb = this.callback; 12 | return d3.text("examples/data/sample.txt", function(text) { 13 | cb(null, text); 14 | }); 15 | }, 16 | "invokes the callback with the loaded text": function(text) { 17 | assert.equal(text, "Hello, world!\n"); 18 | }, 19 | "does not override the mime type by default": function(text) { 20 | assert.isUndefined(XMLHttpRequest._last._info.mimeType); 21 | }, 22 | "": { 23 | topic: function() { 24 | var cb = this.callback; 25 | return d3.text("examples/data/sample.txt", "text/plain+sample", function(text) { 26 | cb(null, text); 27 | }); 28 | }, 29 | "observes the optional mime type": function(text) { 30 | assert.equal(XMLHttpRequest._last._info.mimeType, "text/plain+sample"); 31 | } 32 | }, 33 | " ": { 34 | topic: function() { 35 | var cb = this.callback; 36 | return d3.text("//does/not/exist.txt", function(text) { 37 | cb(null, text); 38 | }); 39 | }, 40 | "invokes the callback with null when an error occurs": function(text) { 41 | assert.isNull(text); 42 | } 43 | } 44 | } 45 | }); 46 | 47 | suite.export(module); 48 | -------------------------------------------------------------------------------- /examples/axis/axis-alternating.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 22 | 23 | 24 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /test/core/descending-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("d3.descending"); 7 | 8 | suite.addBatch({ 9 | "numbers": { 10 | "returns a negative number if a > b": function() { 11 | assert.isTrue(d3.descending(1, 0) < 0); 12 | }, 13 | "returns a positive number if a < b": function() { 14 | assert.isTrue(d3.descending(0, 1) > 0); 15 | }, 16 | "returns zero if a == b": function() { 17 | assert.equal(d3.descending(0, 0), 0); 18 | }, 19 | "returns NaN if a or b is undefined": function() { 20 | assert.isNaN(d3.descending(0, undefined)); 21 | assert.isNaN(d3.descending(undefined, 0)); 22 | assert.isNaN(d3.descending(undefined, undefined)); 23 | }, 24 | "returns NaN if a or b is NaN": function() { 25 | assert.isNaN(d3.descending(0, NaN)); 26 | assert.isNaN(d3.descending(NaN, 0)); 27 | assert.isNaN(d3.descending(NaN, NaN)); 28 | } 29 | } 30 | }); 31 | 32 | suite.addBatch({ 33 | "strings": { 34 | "returns a negative number if a > b": function() { 35 | assert.isTrue(d3.descending("b", "a") < 0); 36 | }, 37 | "returns a positive number if a < b": function() { 38 | assert.isTrue(d3.descending("a", "b") > 0); 39 | }, 40 | "returns zero if a == b": function() { 41 | assert.equal(d3.descending("a", "a"), 0); 42 | } 43 | } 44 | }); 45 | 46 | suite.export(module); 47 | -------------------------------------------------------------------------------- /examples/tree/tree-radial.js: -------------------------------------------------------------------------------- 1 | var radius = 960 / 2; 2 | 3 | var tree = d3.layout.tree() 4 | .size([360, radius - 120]) 5 | .separation(function(a, b) { return (a.parent == b.parent ? 1 : 2) / a.depth; }); 6 | 7 | var diagonal = d3.svg.diagonal.radial() 8 | .projection(function(d) { return [d.y, d.x / 180 * Math.PI]; }); 9 | 10 | var vis = d3.select("#chart").append("svg") 11 | .attr("width", radius * 2) 12 | .attr("height", radius * 2 - 150) 13 | .append("g") 14 | .attr("transform", "translate(" + radius + "," + radius + ")"); 15 | 16 | d3.json("../data/flare.json", function(json) { 17 | var nodes = tree.nodes(json); 18 | 19 | var link = vis.selectAll("path.link") 20 | .data(tree.links(nodes)) 21 | .enter().append("path") 22 | .attr("class", "link") 23 | .attr("d", diagonal); 24 | 25 | var node = vis.selectAll("g.node") 26 | .data(nodes) 27 | .enter().append("g") 28 | .attr("class", "node") 29 | .attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; }) 30 | 31 | node.append("circle") 32 | .attr("r", 4.5); 33 | 34 | node.append("text") 35 | .attr("dx", function(d) { return d.x < 180 ? 8 : -8; }) 36 | .attr("dy", ".31em") 37 | .attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; }) 38 | .attr("transform", function(d) { return d.x < 180 ? null : "rotate(180)"; }) 39 | .text(function(d) { return d.name; }); 40 | }); 41 | -------------------------------------------------------------------------------- /test/core/split-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("d3.split"); 7 | 8 | suite.addBatch({ 9 | "split": { 10 | topic: function() { 11 | return d3.split; 12 | }, 13 | "splits an array into arrays": function(split) { 14 | var a = {}, b = {}, c = {}, d = {}, e = {}, f = {}; 15 | assert.deepEqual(d3.split([a, null, b, c, undefined, d, e, f]), [[a], [b, c], [d, e, f]]); 16 | }, 17 | "splits using the specified function": function(split) { 18 | assert.deepEqual(d3.split([1, 0, 2, 3, -1, 4, 5, 6], function(d) { return d <= 0; }), [[1], [2, 3], [4, 5, 6]]); 19 | assert.deepEqual(d3.split([1, 0, 2, 3, -1, 4, 5, 6], function(d, i) { return i & 1; }), [[1], [2], [-1], [5]]); 20 | }, 21 | "ignores delimiters at the start or end": function(split) { 22 | var a = {}, b = {}, c = {}; 23 | assert.deepEqual(d3.split([null, a, b, null, c]), [[a, b], [c]]); 24 | assert.deepEqual(d3.split([a, b, null, c, null]), [[a, b], [c]]); 25 | assert.deepEqual(d3.split([null, a, b, null, c, null]), [[a, b], [c]]); 26 | assert.deepEqual(d3.split([undefined, a, b, undefined, c]), [[a, b], [c]]); 27 | assert.deepEqual(d3.split([a, b, undefined, c, undefined]), [[a, b], [c]]); 28 | assert.deepEqual(d3.split([undefined, a, b, undefined, c, undefined]), [[a, b], [c]]); 29 | } 30 | } 31 | }); 32 | 33 | suite.export(module); 34 | -------------------------------------------------------------------------------- /src/scale/pow.js: -------------------------------------------------------------------------------- 1 | d3.scale.pow = function() { 2 | return d3_scale_pow(d3.scale.linear(), 1); 3 | }; 4 | 5 | function d3_scale_pow(linear, exponent) { 6 | var powp = d3_scale_powPow(exponent), 7 | powb = d3_scale_powPow(1 / exponent); 8 | 9 | function scale(x) { 10 | return linear(powp(x)); 11 | } 12 | 13 | scale.invert = function(x) { 14 | return powb(linear.invert(x)); 15 | }; 16 | 17 | scale.domain = function(x) { 18 | if (!arguments.length) return linear.domain().map(powb); 19 | linear.domain(x.map(powp)); 20 | return scale; 21 | }; 22 | 23 | scale.ticks = function(m) { 24 | return d3_scale_linearTicks(scale.domain(), m); 25 | }; 26 | 27 | scale.tickFormat = function(m) { 28 | return d3_scale_linearTickFormat(scale.domain(), m); 29 | }; 30 | 31 | scale.nice = function() { 32 | return scale.domain(d3_scale_nice(scale.domain(), d3_scale_linearNice)); 33 | }; 34 | 35 | scale.exponent = function(x) { 36 | if (!arguments.length) return exponent; 37 | var domain = scale.domain(); 38 | powp = d3_scale_powPow(exponent = x); 39 | powb = d3_scale_powPow(1 / exponent); 40 | return scale.domain(domain); 41 | }; 42 | 43 | scale.copy = function() { 44 | return d3_scale_pow(linear.copy(), exponent); 45 | }; 46 | 47 | return d3_scale_linearRebind(scale, linear); 48 | } 49 | 50 | function d3_scale_powPow(e) { 51 | return function(x) { 52 | return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e); 53 | }; 54 | } 55 | -------------------------------------------------------------------------------- /src/core/selection-on.js: -------------------------------------------------------------------------------- 1 | // type can be namespaced, e.g., "click.foo" 2 | // listener can be null for removal 3 | d3_selectionPrototype.on = function(type, listener, capture) { 4 | if (arguments.length < 3) capture = false; 5 | 6 | // parse the type specifier 7 | var name = "__on" + type, i = type.indexOf("."); 8 | if (i > 0) type = type.substring(0, i); 9 | 10 | // if called with only one argument, return the current listener 11 | if (arguments.length < 2) return (i = this.node()[name]) && i._; 12 | 13 | // remove the old event listener, and add the new event listener 14 | return this.each(function() { 15 | var node = this, 16 | args = arguments, 17 | o = node[name]; 18 | 19 | // remove the old listener, if any (using the previously-set capture) 20 | if (o) { 21 | node.removeEventListener(type, o, o.$); 22 | delete node[name]; 23 | } 24 | 25 | // add the new listener, if any (remembering the capture flag) 26 | if (listener) { 27 | node.addEventListener(type, node[name] = l, l.$ = capture); 28 | l._ = listener; // stash the unwrapped listener for get 29 | } 30 | 31 | // wrapped event listener that propagates data changes 32 | function l(e) { 33 | var o = d3.event; // Events can be reentrant (e.g., focus). 34 | d3.event = e; 35 | args[0] = node.__data__; 36 | try { 37 | listener.apply(node, args); 38 | } finally { 39 | d3.event = o; 40 | } 41 | } 42 | }); 43 | }; 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012, 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 | -------------------------------------------------------------------------------- /examples/pie/pie.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Pie Chart 5 | 6 | 13 | 14 | 15 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /test/core/selection-node-test.js: -------------------------------------------------------------------------------- 1 | require("../env"); 2 | 3 | var vows = require("vows"), 4 | assert = require("assert"); 5 | 6 | var suite = vows.describe("selection.node"); 7 | 8 | suite.addBatch({ 9 | "select(body)": { 10 | topic: function() { 11 | return d3.select("body").html(""); 12 | }, 13 | "returns null for empty selections": function(body) { 14 | assert.isNull(body.select("foo").node()); 15 | }, 16 | "returns the first element for non-empty selections": function(body) { 17 | assert.isTrue(body.node() === document.body); 18 | }, 19 | "ignores null nodes": function(body) { 20 | var some = d3.select("body"); 21 | some[0][0] = null; 22 | assert.isNull(some.node()); 23 | } 24 | } 25 | }); 26 | 27 | suite.addBatch({ 28 | "selectAll(div)": { 29 | topic: function() { 30 | var body = d3.select("body").html(""); 31 | body.append("div").append("span"); 32 | body.append("div"); 33 | return body.selectAll("div"); 34 | }, 35 | "returns null for empty selections": function(div) { 36 | assert.isNull(div.select("foo").node()); 37 | }, 38 | "returns the first element for non-empty selections": function(div) { 39 | assert.isTrue(div.node() === div[0][0]); 40 | }, 41 | "ignores null nodes": function(div) { 42 | var some = d3.selectAll("div"); 43 | some[0][0] = null; 44 | assert.isTrue(some.node() === div[0][1]); 45 | } 46 | } 47 | }); 48 | 49 | suite.export(module); 50 | --------------------------------------------------------------------------------