2010-09-28 22:26:55 +04:00
|
|
|
if (!Date.now) Date.now = function() {
|
|
|
|
return +new Date();
|
|
|
|
};
|
|
|
|
if (!Object.create) Object.create = function(o) {
|
|
|
|
/** @constructor */ function f() {}
|
|
|
|
f.prototype = o;
|
|
|
|
return new f();
|
|
|
|
};
|
|
|
|
(function(_) {
|
|
|
|
var d3 = _.d3 = {};
|
|
|
|
d3.version = "0.0.0"; // semver
|
2010-10-21 02:22:22 +04:00
|
|
|
/**
|
|
|
|
* @param {number} start
|
|
|
|
* @param {number=} stop
|
|
|
|
* @param {number=} step
|
|
|
|
*/
|
|
|
|
d3.range = function(start, stop, step) {
|
|
|
|
if (arguments.length == 1) { stop = start; start = 0; }
|
|
|
|
if (step == null) step = 1;
|
|
|
|
if ((stop - start) / step == Infinity) throw new Error("infinite range");
|
|
|
|
var range = [],
|
|
|
|
i = -1,
|
|
|
|
j;
|
|
|
|
if (step < 0) while ((j = start + step * ++i) > stop) range.push(j);
|
|
|
|
else while ((j = start + step * ++i) < stop) range.push(j);
|
|
|
|
return range;
|
|
|
|
};
|
2010-09-28 22:26:55 +04:00
|
|
|
var ns = {
|
|
|
|
|
|
|
|
prefix: {
|
|
|
|
svg: "http://www.w3.org/2000/svg",
|
|
|
|
xhtml: "http://www.w3.org/1999/xhtml",
|
|
|
|
xlink: "http://www.w3.org/1999/xlink",
|
|
|
|
xml: "http://www.w3.org/XML/1998/namespace",
|
|
|
|
xmlns: "http://www.w3.org/2000/xmlns/"
|
|
|
|
},
|
|
|
|
|
|
|
|
resolve: function(prefix) {
|
|
|
|
return ns.prefix[prefix] || null;
|
|
|
|
},
|
|
|
|
|
|
|
|
qualify: function(name) {
|
|
|
|
var i = name.indexOf(":");
|
|
|
|
return i < 0 ? name : {
|
|
|
|
space: ns.prefix[name.substring(0, i)],
|
|
|
|
local: name.substring(i + 1)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
d3.dispatch = function(that) {
|
|
|
|
var types = {};
|
|
|
|
|
|
|
|
that.on = function(type, handler) {
|
|
|
|
var listeners = types[type] || (types[type] = []);
|
|
|
|
for (var i = 0; i < listeners.length; i++) {
|
|
|
|
if (listeners[i].handler == handler) return that; // already registered
|
|
|
|
}
|
|
|
|
listeners.push({handler: handler, on: true});
|
|
|
|
return that;
|
|
|
|
};
|
|
|
|
|
|
|
|
that.off = function(type, handler) {
|
|
|
|
var listeners = types[type];
|
|
|
|
if (listeners) for (var i = 0; i < listeners.length; i++) {
|
|
|
|
var l = listeners[i];
|
|
|
|
if (l.handler == handler) {
|
|
|
|
l.on = false;
|
|
|
|
listeners.splice(i, 1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return that;
|
|
|
|
};
|
|
|
|
|
|
|
|
that.dispatch = function(event) {
|
|
|
|
var listeners = types[event.type];
|
|
|
|
if (!listeners) return;
|
|
|
|
listeners = listeners.slice(); // defensive copy
|
|
|
|
for (var i = 0; i < listeners.length; i++) {
|
|
|
|
var l = listeners[i];
|
|
|
|
if (l.on) l.handler.call(that, event);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
return that;
|
|
|
|
};
|
|
|
|
/*
|
|
|
|
* TERMS OF USE - EASING EQUATIONS
|
|
|
|
*
|
|
|
|
* Open source under the BSD License.
|
|
|
|
*
|
|
|
|
* Copyright 2001 Robert Penner
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are met:
|
|
|
|
*
|
|
|
|
* - Redistributions of source code must retain the above copyright notice, this
|
|
|
|
* list of conditions and the following disclaimer.
|
|
|
|
*
|
|
|
|
* - Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
|
|
* and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* - Neither the name of the author nor the names of contributors may be used to
|
|
|
|
* endorse or promote products derived from this software without specific
|
|
|
|
* prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
var quad = poly(2),
|
|
|
|
cubic = poly(3);
|
|
|
|
|
|
|
|
var ease = {
|
|
|
|
"linear": function() { return linear; },
|
|
|
|
"poly": poly,
|
|
|
|
"quad": function() { return quad; },
|
|
|
|
"cubic": function() { return cubic; },
|
|
|
|
"sin": function() { return sin; },
|
|
|
|
"exp": function() { return exp; },
|
|
|
|
"circle": function() { return circle; },
|
|
|
|
"elastic": elastic,
|
|
|
|
"back": back,
|
|
|
|
"bounce": function() { return bounce; }
|
|
|
|
};
|
|
|
|
|
|
|
|
var mode = {
|
|
|
|
"in": function(f) { return f; },
|
|
|
|
"out": reverse,
|
|
|
|
"in-out": reflect,
|
|
|
|
"out-int": function(f) { return reflect(reverse(f)); }
|
|
|
|
};
|
|
|
|
|
|
|
|
d3.ease = function(name) {
|
|
|
|
var i = name.indexOf("-"),
|
|
|
|
t = i >= 0 ? name.substring(0, i) : name,
|
|
|
|
m = i >= 0 ? name.substring(i + 1) : "in";
|
|
|
|
return mode[m](ease[t].apply(null, Array.prototype.slice.call(arguments, 1)));
|
|
|
|
};
|
|
|
|
|
|
|
|
function reverse(f) {
|
|
|
|
return function(t) {
|
|
|
|
return 1 - f(1 - t);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function reflect(f) {
|
|
|
|
return function(t) {
|
|
|
|
return .5 * (t < .5 ? f(2 * t) : (2 - f(2 - 2 * t)));
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function linear(t) {
|
|
|
|
return t;
|
|
|
|
}
|
|
|
|
|
|
|
|
function poly(e) {
|
|
|
|
return function(t) {
|
|
|
|
return Math.pow(t, e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function sin(t) {
|
|
|
|
return 1 - Math.cos(t * Math.PI / 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
function exp(t) {
|
|
|
|
return t ? Math.pow(2, 10 * (t - 1)) - 1e-3 : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
function circle(t) {
|
|
|
|
return 1 - Math.sqrt(1 - t * t);
|
|
|
|
}
|
|
|
|
|
|
|
|
function elastic(a, p) {
|
|
|
|
var s;
|
|
|
|
if (arguments.length < 2) p = 0.45;
|
|
|
|
if (arguments.length < 1) { a = 1; s = p / 4; }
|
|
|
|
else s = p / (2 * Math.PI) * Math.asin(1 / a);
|
|
|
|
return function(t) {
|
|
|
|
return 1 + a * Math.pow(2, 10 * -t) * Math.sin(-(t + s) * 2 * Math.PI / p);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function back(s) {
|
|
|
|
if (!s) s = 1.70158;
|
|
|
|
return function(t) {
|
|
|
|
return t * t * ((s + 1) * t - s);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function bounce(t) {
|
|
|
|
return t < 1 / 2.75 ? 7.5625 * t * t
|
|
|
|
: t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75
|
|
|
|
: t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375
|
|
|
|
: 7.5625 * (t -= 2.625 / 2.75) * t + .984375;
|
|
|
|
}
|
|
|
|
d3.interpolate = function(a, b) {
|
|
|
|
if (typeof b == "number") return d3.interpolateNumber(+a, b);
|
2010-10-20 22:07:42 +04:00
|
|
|
if (typeof b == "string") {
|
|
|
|
return (b in d3_rgb_names) || /^(#|rgb\(|hsl\()/.test(b)
|
|
|
|
? d3.interpolateRgb(String(a), b)
|
|
|
|
: d3.interpolateString(String(a), b);
|
|
|
|
}
|
2010-09-28 22:26:55 +04:00
|
|
|
if (b instanceof Array) return d3.interpolateArray(a, b);
|
|
|
|
return d3.interpolateObject(a, b);
|
|
|
|
};
|
|
|
|
|
|
|
|
d3.interpolateNumber = function(a, b) {
|
|
|
|
b -= a;
|
|
|
|
return function(t) { return a + b * t; };
|
|
|
|
};
|
|
|
|
|
|
|
|
d3.interpolateString = function(a, b) {
|
|
|
|
var m, // current match
|
|
|
|
i, // current index
|
|
|
|
j, // current index (for coallescing)
|
|
|
|
s0 = 0, // start index of current string prefix
|
|
|
|
s1 = 0, // end index of current string prefix
|
|
|
|
s = [], // string constants and placeholders
|
|
|
|
q = [], // number interpolators
|
|
|
|
n, // q.length
|
|
|
|
o;
|
|
|
|
|
|
|
|
// Find all numbers in b.
|
|
|
|
for (i = 0; m = d3_interpolate_number.exec(b); ++i) {
|
|
|
|
if (m.index) s.push(b.substring(s0, s1 = m.index));
|
|
|
|
q.push({i: s.length, x: m[0]});
|
|
|
|
s.push(null);
|
|
|
|
s0 = d3_interpolate_number.lastIndex;
|
|
|
|
}
|
|
|
|
if (s0 < b.length) s.push(b.substring(s0));
|
|
|
|
|
|
|
|
// Find all numbers in a.
|
|
|
|
for (i = 0, n = q.length; (m = d3_interpolate_number.exec(a)) && i < n; ++i) {
|
|
|
|
o = q[i];
|
|
|
|
if (o.x == m[0]) { // The numbers match, so coallesce.
|
|
|
|
if (o.i) {
|
|
|
|
if (s[o.i + 1] == null) { // This match is followed by another number.
|
|
|
|
s[o.i - 1] += o.x;
|
|
|
|
s.splice(o.i, 1);
|
|
|
|
for (j = i + 1; j < n; ++j) q[j].i--;
|
|
|
|
} else { // This match is followed by a string, so coallesce twice.
|
|
|
|
s[o.i - 1] += o.x + s[o.i + 1];
|
|
|
|
s.splice(o.i, 2);
|
|
|
|
for (j = i + 1; j < n; ++j) q[j].i -= 2;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (s[o.i + 1] == null) { // This match is followed by another number.
|
|
|
|
s[o.i] = o.x;
|
|
|
|
} else { // This match is followed by a string, so coallesce twice.
|
|
|
|
s[o.i] = o.x + s[o.i + 1];
|
|
|
|
s.splice(o.i + 1, 1);
|
|
|
|
for (j = i + 1; j < n; ++j) q[j].i--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
q.splice(i, 1);
|
|
|
|
n--;
|
|
|
|
i--;
|
|
|
|
} else {
|
|
|
|
o.x = d3.interpolateNumber(parseFloat(m[0]), parseFloat(o.x));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove any numbers in b not found in a.
|
|
|
|
while (i < n) {
|
|
|
|
o = q.pop();
|
|
|
|
if (s[o.i + 1] == null) { // This match is followed by another number.
|
|
|
|
s[o.i] = o.x;
|
|
|
|
} else { // This match is followed by a string, so coallesce twice.
|
|
|
|
s[o.i] = o.x + s[o.i + 1];
|
|
|
|
s.splice(o.i + 1, 1);
|
|
|
|
}
|
|
|
|
n--;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Special optimization for only a single match.
|
|
|
|
if (s.length == 1) {
|
|
|
|
return s[0] == null ? q[0].x : function() { return b; };
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, interpolate each of the numbers and rejoin the string.
|
|
|
|
return function(t) {
|
|
|
|
for (i = 0; i < n; ++i) s[(o = q[i]).i] = o.x(t);
|
|
|
|
return s.join("");
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
d3.interpolateRgb = function(a, b) {
|
|
|
|
a = d3_rgb(a);
|
|
|
|
b = d3_rgb(b);
|
|
|
|
var ar = a.r,
|
|
|
|
ag = a.g,
|
|
|
|
ab = a.b,
|
|
|
|
br = b.r - ar,
|
|
|
|
bg = b.g - ag,
|
|
|
|
bb = b.b - ab;
|
|
|
|
return function(t) {
|
|
|
|
return "rgb(" + Math.round(ar + br * t)
|
|
|
|
+ "," + Math.round(ag + bg * t)
|
|
|
|
+ "," + Math.round(ab + bb * t)
|
|
|
|
+ ")";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
d3.interpolateArray = function(a, b) {
|
|
|
|
var x = [],
|
|
|
|
c = [],
|
|
|
|
na = a.length,
|
|
|
|
nb = b.length,
|
|
|
|
n0 = Math.min(a.length, b.length),
|
|
|
|
i;
|
|
|
|
for (i = 0; i < n0; ++i) x.push(d3.interpolate(a[i], b[i]));
|
|
|
|
for (; i < na; ++i) c[i] = a[i];
|
|
|
|
for (; i < nb; ++i) c[i] = b[i];
|
|
|
|
return function(t) {
|
|
|
|
for (i = 0; i < n0; ++i) c[i] = x[i](t);
|
|
|
|
return c;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
d3.interpolateObject = function(a, b) {
|
|
|
|
var i = {},
|
|
|
|
c = {},
|
|
|
|
k;
|
|
|
|
for (k in a) {
|
|
|
|
if (k in b) {
|
|
|
|
i[k] = d3_interpolateByName(k)(a[k], b[k]);
|
|
|
|
} else {
|
|
|
|
c[k] = a[k];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (k in b) {
|
|
|
|
if (!(k in a)) {
|
|
|
|
c[k] = b[k];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return function(t) {
|
|
|
|
for (k in i) c[k] = i[k](t);
|
|
|
|
return c;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
var d3_interpolate_number = /[-+]?(?:\d+\.\d+|\d+\.|\.\d+|\d+)(?:[eE][-]?\d+)?/g,
|
|
|
|
d3_interpolate_digits = /[-+]?\d*\.?\d*(?:[eE][-]?\d+)?(.*)/,
|
|
|
|
d3_interpolate_rgb = {background: 1, fill: 1, stroke: 1};
|
|
|
|
|
|
|
|
function d3_interpolateByName(n) {
|
|
|
|
return n in d3_interpolate_rgb || /\bcolor\b/.test(n)
|
|
|
|
? d3.interpolateRgb
|
|
|
|
: d3.interpolate;
|
|
|
|
}
|
2010-09-29 10:18:51 +04:00
|
|
|
d3.tween = function(v) {
|
|
|
|
return {
|
|
|
|
bind: typeof v == "function" ? function() {
|
|
|
|
var a = this.value,
|
|
|
|
n = this.name,
|
|
|
|
b = v.apply(this, arguments),
|
|
|
|
i = (n in d3_interpolate_rgb || /\bcolor\b/.test(n)
|
|
|
|
? d3.interpolateRgb
|
|
|
|
: d3.interpolate)(a, b);
|
|
|
|
return function() {
|
|
|
|
return i(d3.time);
|
|
|
|
};
|
|
|
|
} : function() {
|
|
|
|
var a = this.value,
|
|
|
|
n = this.name,
|
|
|
|
i = (n in d3_interpolate_rgb || /\bcolor\b/.test(n)
|
|
|
|
? d3.interpolateRgb
|
|
|
|
: d3.interpolate)(a, v);
|
|
|
|
return function() {
|
|
|
|
return i(d3.time);
|
|
|
|
};
|
|
|
|
}
|
2010-09-28 22:26:55 +04:00
|
|
|
};
|
2010-09-29 10:18:51 +04:00
|
|
|
};
|
2010-09-28 22:26:55 +04:00
|
|
|
function d3_rgb(format) {
|
|
|
|
var r, // red channel; int in [0, 255]
|
|
|
|
g, // green channel; int in [0, 255]
|
|
|
|
b, // blue channel; int in [0, 255]
|
|
|
|
m1, // CSS color specification match
|
|
|
|
m2, // CSS color specification type (e.g., rgb)
|
|
|
|
name;
|
|
|
|
|
|
|
|
/* Handle hsl, rgb. */
|
|
|
|
m1 = /([a-z]+)\((.*)\)/i.exec(format);
|
|
|
|
if (m1) {
|
|
|
|
m2 = m1[2].split(",");
|
|
|
|
switch (m1[1]) {
|
|
|
|
case "hsl": {
|
|
|
|
return d3_rgb_hsl(
|
|
|
|
parseFloat(m2[0]), // degrees
|
|
|
|
parseFloat(m2[1]) / 100, // percentage
|
|
|
|
parseFloat(m2[2]) / 100); // percentage
|
|
|
|
}
|
|
|
|
case "rgb": {
|
|
|
|
return {
|
|
|
|
r: d3_rgb_parse(m2[0]),
|
|
|
|
g: d3_rgb_parse(m2[1]),
|
|
|
|
b: d3_rgb_parse(m2[2])
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Named colors. */
|
|
|
|
if (name = d3_rgb_names[format]) return name;
|
|
|
|
|
|
|
|
/* Null or undefined. */
|
|
|
|
if (format == null) return d3_rgb_names.black;
|
|
|
|
|
|
|
|
/* Hexadecimal colors: #rgb and #rrggbb. */
|
|
|
|
if (format.charAt(0) == "#") {
|
|
|
|
if (format.length == 4) {
|
|
|
|
r = format.charAt(1); r += r;
|
|
|
|
g = format.charAt(2); g += g;
|
|
|
|
b = format.charAt(3); b += b;
|
|
|
|
} else if (format.length == 7) {
|
|
|
|
r = format.substring(1, 3);
|
|
|
|
g = format.substring(3, 5);
|
|
|
|
b = format.substring(5, 7);
|
|
|
|
}
|
|
|
|
r = parseInt(r, 16);
|
|
|
|
g = parseInt(g, 16);
|
|
|
|
b = parseInt(b, 16);
|
|
|
|
}
|
|
|
|
|
|
|
|
return {r: r, g: g, b: b};
|
|
|
|
};
|
|
|
|
|
|
|
|
function d3_rgb_hsl(h, s, l) {
|
|
|
|
var m1,
|
|
|
|
m2;
|
|
|
|
|
|
|
|
/* Some simple corrections for h, s and l. */
|
|
|
|
h = h % 360; if (h < 0) h += 360;
|
|
|
|
s = s < 0 ? 0 : s > 1 ? 1 : s;
|
|
|
|
l = l < 0 ? 0 : l > 1 ? 1 : l;
|
|
|
|
|
|
|
|
/* From FvD 13.37, CSS Color Module Level 3 */
|
|
|
|
m2 = l <= .5 ? l * (1 + s) : l + s - l * s;
|
|
|
|
m1 = 2 * l - m2;
|
|
|
|
|
|
|
|
function v(h) {
|
|
|
|
if (h > 360) h -= 360;
|
|
|
|
else if (h < 0) h += 360;
|
|
|
|
if (h < 60) return m1 + (m2 - m1) * h / 60;
|
|
|
|
if (h < 180) return m2;
|
|
|
|
if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60;
|
|
|
|
return m1;
|
|
|
|
}
|
|
|
|
|
|
|
|
function vv(h) {
|
|
|
|
return Math.round(v(h) * 255);
|
|
|
|
}
|
|
|
|
|
|
|
|
return {r: vv(h + 120), g: vv(h), b: vv(h - 120)};
|
|
|
|
}
|
|
|
|
|
|
|
|
function d3_rgb_parse(c) { // either integer or percentage
|
|
|
|
var f = parseFloat(c);
|
|
|
|
return c.charAt(c.length - 1) == "%" ? Math.round(f * 2.55) : f;
|
|
|
|
}
|
|
|
|
|
|
|
|
var d3_rgb_names = {
|
|
|
|
aliceblue: "#f0f8ff",
|
|
|
|
antiquewhite: "#faebd7",
|
|
|
|
aqua: "#00ffff",
|
|
|
|
aquamarine: "#7fffd4",
|
|
|
|
azure: "#f0ffff",
|
|
|
|
beige: "#f5f5dc",
|
|
|
|
bisque: "#ffe4c4",
|
|
|
|
black: "#000000",
|
|
|
|
blanchedalmond: "#ffebcd",
|
|
|
|
blue: "#0000ff",
|
|
|
|
blueviolet: "#8a2be2",
|
|
|
|
brown: "#a52a2a",
|
|
|
|
burlywood: "#deb887",
|
|
|
|
cadetblue: "#5f9ea0",
|
|
|
|
chartreuse: "#7fff00",
|
|
|
|
chocolate: "#d2691e",
|
|
|
|
coral: "#ff7f50",
|
|
|
|
cornflowerblue: "#6495ed",
|
|
|
|
cornsilk: "#fff8dc",
|
|
|
|
crimson: "#dc143c",
|
|
|
|
cyan: "#00ffff",
|
|
|
|
darkblue: "#00008b",
|
|
|
|
darkcyan: "#008b8b",
|
|
|
|
darkgoldenrod: "#b8860b",
|
|
|
|
darkgray: "#a9a9a9",
|
|
|
|
darkgreen: "#006400",
|
|
|
|
darkgrey: "#a9a9a9",
|
|
|
|
darkkhaki: "#bdb76b",
|
|
|
|
darkmagenta: "#8b008b",
|
|
|
|
darkolivegreen: "#556b2f",
|
|
|
|
darkorange: "#ff8c00",
|
|
|
|
darkorchid: "#9932cc",
|
|
|
|
darkred: "#8b0000",
|
|
|
|
darksalmon: "#e9967a",
|
|
|
|
darkseagreen: "#8fbc8f",
|
|
|
|
darkslateblue: "#483d8b",
|
|
|
|
darkslategray: "#2f4f4f",
|
|
|
|
darkslategrey: "#2f4f4f",
|
|
|
|
darkturquoise: "#00ced1",
|
|
|
|
darkviolet: "#9400d3",
|
|
|
|
deeppink: "#ff1493",
|
|
|
|
deepskyblue: "#00bfff",
|
|
|
|
dimgray: "#696969",
|
|
|
|
dimgrey: "#696969",
|
|
|
|
dodgerblue: "#1e90ff",
|
|
|
|
firebrick: "#b22222",
|
|
|
|
floralwhite: "#fffaf0",
|
|
|
|
forestgreen: "#228b22",
|
|
|
|
fuchsia: "#ff00ff",
|
|
|
|
gainsboro: "#dcdcdc",
|
|
|
|
ghostwhite: "#f8f8ff",
|
|
|
|
gold: "#ffd700",
|
|
|
|
goldenrod: "#daa520",
|
|
|
|
gray: "#808080",
|
|
|
|
green: "#008000",
|
|
|
|
greenyellow: "#adff2f",
|
|
|
|
grey: "#808080",
|
|
|
|
honeydew: "#f0fff0",
|
|
|
|
hotpink: "#ff69b4",
|
|
|
|
indianred: "#cd5c5c",
|
|
|
|
indigo: "#4b0082",
|
|
|
|
ivory: "#fffff0",
|
|
|
|
khaki: "#f0e68c",
|
|
|
|
lavender: "#e6e6fa",
|
|
|
|
lavenderblush: "#fff0f5",
|
|
|
|
lawngreen: "#7cfc00",
|
|
|
|
lemonchiffon: "#fffacd",
|
|
|
|
lightblue: "#add8e6",
|
|
|
|
lightcoral: "#f08080",
|
|
|
|
lightcyan: "#e0ffff",
|
|
|
|
lightgoldenrodyellow: "#fafad2",
|
|
|
|
lightgray: "#d3d3d3",
|
|
|
|
lightgreen: "#90ee90",
|
|
|
|
lightgrey: "#d3d3d3",
|
|
|
|
lightpink: "#ffb6c1",
|
|
|
|
lightsalmon: "#ffa07a",
|
|
|
|
lightseagreen: "#20b2aa",
|
|
|
|
lightskyblue: "#87cefa",
|
|
|
|
lightslategray: "#778899",
|
|
|
|
lightslategrey: "#778899",
|
|
|
|
lightsteelblue: "#b0c4de",
|
|
|
|
lightyellow: "#ffffe0",
|
|
|
|
lime: "#00ff00",
|
|
|
|
limegreen: "#32cd32",
|
|
|
|
linen: "#faf0e6",
|
|
|
|
magenta: "#ff00ff",
|
|
|
|
maroon: "#800000",
|
|
|
|
mediumaquamarine: "#66cdaa",
|
|
|
|
mediumblue: "#0000cd",
|
|
|
|
mediumorchid: "#ba55d3",
|
|
|
|
mediumpurple: "#9370db",
|
|
|
|
mediumseagreen: "#3cb371",
|
|
|
|
mediumslateblue: "#7b68ee",
|
|
|
|
mediumspringgreen: "#00fa9a",
|
|
|
|
mediumturquoise: "#48d1cc",
|
|
|
|
mediumvioletred: "#c71585",
|
|
|
|
midnightblue: "#191970",
|
|
|
|
mintcream: "#f5fffa",
|
|
|
|
mistyrose: "#ffe4e1",
|
|
|
|
moccasin: "#ffe4b5",
|
|
|
|
navajowhite: "#ffdead",
|
|
|
|
navy: "#000080",
|
|
|
|
oldlace: "#fdf5e6",
|
|
|
|
olive: "#808000",
|
|
|
|
olivedrab: "#6b8e23",
|
|
|
|
orange: "#ffa500",
|
|
|
|
orangered: "#ff4500",
|
|
|
|
orchid: "#da70d6",
|
|
|
|
palegoldenrod: "#eee8aa",
|
|
|
|
palegreen: "#98fb98",
|
|
|
|
paleturquoise: "#afeeee",
|
|
|
|
palevioletred: "#db7093",
|
|
|
|
papayawhip: "#ffefd5",
|
|
|
|
peachpuff: "#ffdab9",
|
|
|
|
peru: "#cd853f",
|
|
|
|
pink: "#ffc0cb",
|
|
|
|
plum: "#dda0dd",
|
|
|
|
powderblue: "#b0e0e6",
|
|
|
|
purple: "#800080",
|
|
|
|
red: "#ff0000",
|
|
|
|
rosybrown: "#bc8f8f",
|
|
|
|
royalblue: "#4169e1",
|
|
|
|
saddlebrown: "#8b4513",
|
|
|
|
salmon: "#fa8072",
|
|
|
|
sandybrown: "#f4a460",
|
|
|
|
seagreen: "#2e8b57",
|
|
|
|
seashell: "#fff5ee",
|
|
|
|
sienna: "#a0522d",
|
|
|
|
silver: "#c0c0c0",
|
|
|
|
skyblue: "#87ceeb",
|
|
|
|
slateblue: "#6a5acd",
|
|
|
|
slategray: "#708090",
|
|
|
|
slategrey: "#708090",
|
|
|
|
snow: "#fffafa",
|
|
|
|
springgreen: "#00ff7f",
|
|
|
|
steelblue: "#4682b4",
|
|
|
|
tan: "#d2b48c",
|
|
|
|
teal: "#008080",
|
|
|
|
thistle: "#d8bfd8",
|
|
|
|
tomato: "#ff6347",
|
|
|
|
turquoise: "#40e0d0",
|
|
|
|
violet: "#ee82ee",
|
|
|
|
wheat: "#f5deb3",
|
|
|
|
white: "#ffffff",
|
|
|
|
whitesmoke: "#f5f5f5",
|
|
|
|
yellow: "#ffff00",
|
|
|
|
yellowgreen: "#9acd32"
|
|
|
|
};
|
|
|
|
|
|
|
|
for (var x in d3_rgb_names) d3_rgb_names[x] = d3_rgb(d3_rgb_names[x]);
|
2010-10-07 02:20:38 +04:00
|
|
|
d3.hsl = function(h, s, l) {
|
|
|
|
var c = d3_rgb_hsl(h, s, l);
|
|
|
|
return "rgb(" + c.r + "," + c.g + "," + c.b + ")";
|
|
|
|
};
|
2010-10-20 22:07:42 +04:00
|
|
|
d3.linear = function() {
|
|
|
|
var x0 = 0,
|
|
|
|
x1 = 1,
|
|
|
|
y0 = 0,
|
|
|
|
y1 = 1,
|
|
|
|
k = 1 / (x1 - x0),
|
|
|
|
i = d3.interpolate(y0, y1);
|
|
|
|
|
|
|
|
function scale(x) {
|
|
|
|
return i((x - x0) * k);
|
|
|
|
}
|
|
|
|
|
|
|
|
scale.invert = function(x) {
|
|
|
|
return (x - y0) / k + x0; // TODO assumes number?
|
|
|
|
};
|
|
|
|
|
|
|
|
/** @param {*=} x */
|
|
|
|
scale.domain = function(x) {
|
|
|
|
if (!arguments.length) return [x0, x1];
|
|
|
|
x0 = x[0];
|
|
|
|
x1 = x[1];
|
|
|
|
k = 1 / (x1 - x0);
|
|
|
|
return scale;
|
|
|
|
};
|
|
|
|
|
|
|
|
/** @param {*=} x */
|
|
|
|
scale.range = function(x) {
|
|
|
|
if (!arguments.length) return [y0, y1];
|
|
|
|
y0 = x[0];
|
|
|
|
y1 = x[1];
|
|
|
|
i = d3.interpolate(y0, y1); // TODO allow override?
|
|
|
|
return scale;
|
|
|
|
};
|
|
|
|
|
|
|
|
return scale;
|
|
|
|
};
|
|
|
|
d3.log = function() {
|
|
|
|
var linear = d3.linear();
|
|
|
|
|
|
|
|
function scale(x) {
|
|
|
|
return linear(Math.log(x));
|
|
|
|
}
|
|
|
|
|
|
|
|
scale.invert = function(x) {
|
|
|
|
return Math.exp(linear.invert(x));
|
|
|
|
};
|
|
|
|
|
|
|
|
/** @param {*=} x */
|
|
|
|
scale.domain = function(x) {
|
|
|
|
if (!arguments.length) return linear.domain().map(Math.exp);
|
|
|
|
linear.domain(x.map(Math.log));
|
|
|
|
return scale;
|
|
|
|
};
|
|
|
|
|
|
|
|
scale.range = function() {
|
|
|
|
var x = linear.range.apply(linear, arguments);
|
|
|
|
return arguments.length ? scale : x;
|
|
|
|
};
|
|
|
|
|
|
|
|
return scale;
|
|
|
|
};
|
|
|
|
d3.pow = function() {
|
|
|
|
var linear = d3.linear(),
|
|
|
|
p = 1,
|
|
|
|
b = 1 / p;
|
|
|
|
|
|
|
|
function powp(x) {
|
|
|
|
return Math.pow(x, p);
|
|
|
|
}
|
|
|
|
|
|
|
|
function powb(x) {
|
|
|
|
return Math.pow(x, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
function scale(x) {
|
|
|
|
return linear(powp(x));
|
|
|
|
}
|
|
|
|
|
|
|
|
scale.invert = function(x) {
|
|
|
|
return powb(linear.invert(x));
|
|
|
|
};
|
|
|
|
|
|
|
|
/** @param {*=} x */
|
|
|
|
scale.domain = function(x) {
|
|
|
|
if (!arguments.length) return linear.domain().map(powb);
|
|
|
|
linear.domain(x.map(powp));
|
|
|
|
return scale;
|
|
|
|
};
|
|
|
|
|
|
|
|
scale.range = function() {
|
|
|
|
var x = linear.range.apply(linear, arguments);
|
|
|
|
return arguments.length ? scale : x;
|
|
|
|
};
|
|
|
|
|
|
|
|
scale.exponent = function(x) {
|
|
|
|
if (!arguments.length) return p;
|
|
|
|
var domain = scale.domain();
|
|
|
|
p = x;
|
|
|
|
b = 1 / x;
|
|
|
|
return scale.domain(domain);
|
|
|
|
};
|
|
|
|
|
|
|
|
return scale;
|
|
|
|
};
|
|
|
|
d3.sqrt = function() {
|
|
|
|
return d3.pow().exponent(.5);
|
|
|
|
};
|
2010-10-21 02:22:22 +04:00
|
|
|
d3.ordinal = function() {
|
|
|
|
var domain = [],
|
|
|
|
index = {},
|
|
|
|
range = [],
|
|
|
|
rangeBand = 0;
|
|
|
|
|
|
|
|
function scale(x) {
|
|
|
|
var i = x in index ? index[x] : (index[x] = domain.push(x) - 1);
|
|
|
|
return range[i % range.length];
|
|
|
|
}
|
|
|
|
|
|
|
|
scale.domain = function(x) {
|
|
|
|
if (!arguments.length) return domain;
|
|
|
|
domain = x;
|
|
|
|
index = {};
|
|
|
|
var i = -1, j = -1, n = domain.length; while (++i < n) {
|
|
|
|
x = domain[i];
|
|
|
|
if (!(x in index)) index[x] = ++j;
|
|
|
|
}
|
|
|
|
return scale;
|
|
|
|
};
|
|
|
|
|
|
|
|
scale.range = function(x) {
|
|
|
|
if (!arguments.length) return range;
|
|
|
|
range = x;
|
|
|
|
return scale;
|
|
|
|
};
|
|
|
|
|
|
|
|
scale.rangePoints = function(x, padding) {
|
|
|
|
if (arguments.length < 2) padding = 0;
|
|
|
|
var start = x[0],
|
|
|
|
stop = x[1],
|
|
|
|
step = (stop - start) / (domain.length - 1 + padding);
|
|
|
|
range = domain.length == 1
|
|
|
|
? [(start + stop) / 2]
|
|
|
|
: d3.range(start + step * padding / 2, stop + step / 2, step);
|
|
|
|
rangeBand = 0;
|
|
|
|
return scale;
|
|
|
|
};
|
|
|
|
|
|
|
|
scale.rangeBands = function(x, padding) {
|
|
|
|
if (arguments.length < 2) padding = 0;
|
|
|
|
var start = x[0],
|
|
|
|
stop = x[1],
|
|
|
|
step = (stop - start) / (domain.length + padding);
|
|
|
|
range = d3.range(start + step * padding, stop, step);
|
|
|
|
rangeBand = step * (1 - padding);
|
|
|
|
return scale;
|
|
|
|
};
|
|
|
|
|
|
|
|
scale.rangeBand = function() {
|
|
|
|
return rangeBand;
|
|
|
|
};
|
|
|
|
|
|
|
|
return scale;
|
|
|
|
};
|
2010-09-28 22:26:55 +04:00
|
|
|
var d3_transform_stack = [];
|
|
|
|
|
|
|
|
function d3_transform() {
|
|
|
|
var transform = {},
|
|
|
|
actions = [];
|
|
|
|
|
|
|
|
// TODO reorder elements
|
|
|
|
// convenience method for replacing elements?
|
|
|
|
// how to insert new element at a given location?
|
|
|
|
// how to move elements around, sort, reverse or reorder?
|
|
|
|
|
|
|
|
// TODO value transforms
|
|
|
|
// how to inspect current attr/style/text value from transform?
|
|
|
|
// perhaps push/pop values for temporary change (e.g., :hover)?
|
|
|
|
// this.value retrieves current attr / style / text? or this.value()?
|
|
|
|
|
|
|
|
// TODO extensibility
|
|
|
|
// register hooks for transform extensibility outside the library?
|
|
|
|
// how to encapsulate higher level logic (e.g., bars, wedges, charts)?
|
|
|
|
// virtual nodes? map to canvas?
|
|
|
|
|
|
|
|
// TODO composition
|
|
|
|
// transform.apply(nodes) to transform specific nodes? (set root context)
|
|
|
|
// transform.transform(transform) to chain transforms?
|
|
|
|
|
|
|
|
// TODO selectors
|
|
|
|
// allow select / selectAll argument to be function
|
|
|
|
// allow select / selectAll argument to be node / nodes
|
|
|
|
// allow select / selectAll argument to be xpath
|
|
|
|
// allow selectParent?
|
|
|
|
// allow selectFirstChild, selectLastChild, selectChildren?
|
|
|
|
// allow selectNext, selectPrevious?
|
|
|
|
|
|
|
|
// TODO performance
|
|
|
|
// dispatch to different impl based on ns.qualify, typeof v === "function", etc.
|
|
|
|
|
|
|
|
// TODO transitions
|
|
|
|
// how to do staggered transition on line control points? (virtual nodes?)
|
|
|
|
|
|
|
|
function transform_scope(parent, actions) {
|
|
|
|
var scope = Object.create(transform);
|
|
|
|
|
|
|
|
scope.pop = parent;
|
|
|
|
|
|
|
|
scope.data = function(v) {
|
|
|
|
var subscope, action = {
|
|
|
|
impl: d3_transform_data,
|
2010-09-29 10:18:51 +04:00
|
|
|
bind: d3_transform_data_bind,
|
2010-09-28 22:26:55 +04:00
|
|
|
value: v,
|
|
|
|
actions: [],
|
|
|
|
enterActions: [],
|
|
|
|
exitActions: []
|
|
|
|
};
|
|
|
|
actions.push(action);
|
|
|
|
subscope = transform_scope(scope, action.actions);
|
|
|
|
subscope.enter = transform_scope(scope, action.enterActions);
|
|
|
|
subscope.exit = transform_scope(scope, action.exitActions);
|
|
|
|
subscope.key = function(n, v) {
|
|
|
|
action.key = {name: ns.qualify(n), value: v};
|
|
|
|
return subscope;
|
|
|
|
};
|
|
|
|
return subscope;
|
|
|
|
};
|
|
|
|
|
|
|
|
scope.attr = function(n, v) {
|
|
|
|
actions.push({
|
|
|
|
impl: d3_transform_attr,
|
2010-09-29 10:18:51 +04:00
|
|
|
bind: d3_transform_attr_bind,
|
2010-09-28 22:26:55 +04:00
|
|
|
name: ns.qualify(n),
|
|
|
|
value: v
|
|
|
|
});
|
|
|
|
return scope;
|
|
|
|
};
|
|
|
|
|
|
|
|
scope.style = function(n, v, p) {
|
|
|
|
actions.push({
|
|
|
|
impl: d3_transform_style,
|
2010-09-29 10:18:51 +04:00
|
|
|
bind: d3_transform_style_bind,
|
2010-09-28 22:26:55 +04:00
|
|
|
name: n,
|
|
|
|
value: v,
|
|
|
|
priority: arguments.length < 3 ? null : p
|
|
|
|
});
|
|
|
|
return scope;
|
|
|
|
};
|
|
|
|
|
2010-10-02 22:00:31 +04:00
|
|
|
scope.append = function(n, v) {
|
2010-09-28 22:26:55 +04:00
|
|
|
var action = {
|
2010-10-02 22:00:31 +04:00
|
|
|
impl: d3_transform_append,
|
2010-09-28 22:26:55 +04:00
|
|
|
name: ns.qualify(n),
|
|
|
|
value: v,
|
|
|
|
actions: []
|
|
|
|
};
|
|
|
|
actions.push(action);
|
|
|
|
return transform_scope(scope, action.actions);
|
|
|
|
};
|
|
|
|
|
|
|
|
scope.remove = function(s) {
|
|
|
|
actions.push({
|
|
|
|
impl: d3_transform_remove,
|
|
|
|
selector: s
|
|
|
|
});
|
|
|
|
return scope;
|
|
|
|
};
|
|
|
|
|
|
|
|
scope.text = function(v) {
|
|
|
|
actions.push({
|
|
|
|
impl: d3_transform_text,
|
|
|
|
value: v
|
|
|
|
});
|
|
|
|
return scope;
|
|
|
|
};
|
|
|
|
|
|
|
|
scope.on = function(t) {
|
|
|
|
var action = {
|
|
|
|
impl: d3_transform_on,
|
|
|
|
type: t,
|
|
|
|
actions: []
|
|
|
|
};
|
|
|
|
actions.push(action);
|
|
|
|
return transform_scope(scope, action.actions);
|
|
|
|
};
|
|
|
|
|
2010-10-21 23:53:56 +04:00
|
|
|
scope.bind = function(t, f) {
|
|
|
|
actions.push({
|
|
|
|
impl: d3_transform_bind,
|
|
|
|
type: t,
|
|
|
|
listener: f
|
|
|
|
});
|
|
|
|
return scope;
|
|
|
|
};
|
|
|
|
|
2010-09-28 22:26:55 +04:00
|
|
|
scope.filter = function(f) {
|
|
|
|
var action = {
|
|
|
|
impl: d3_transform_filter,
|
2010-09-29 10:18:51 +04:00
|
|
|
bind: d3_transform_filter, // TODO is this right?
|
2010-09-28 22:26:55 +04:00
|
|
|
filter: f,
|
|
|
|
actions: []
|
|
|
|
};
|
|
|
|
actions.push(action);
|
|
|
|
return transform_scope(scope, action.actions);
|
|
|
|
};
|
|
|
|
|
|
|
|
scope.select = function(s) {
|
|
|
|
var action = {
|
|
|
|
impl: d3_transform_select,
|
2010-09-29 10:18:51 +04:00
|
|
|
bind: d3_transform_select_bind,
|
2010-09-28 22:26:55 +04:00
|
|
|
selector: s,
|
|
|
|
actions: []
|
|
|
|
};
|
|
|
|
actions.push(action);
|
|
|
|
return transform_scope(scope, action.actions);
|
|
|
|
};
|
|
|
|
|
|
|
|
scope.selectAll = function(s) {
|
|
|
|
var action = {
|
2010-10-02 22:38:50 +04:00
|
|
|
impl: d3_transform_selectAll,
|
|
|
|
bind: d3_transform_selectAll_bind,
|
2010-09-28 22:26:55 +04:00
|
|
|
selector: s,
|
|
|
|
actions: []
|
|
|
|
};
|
|
|
|
actions.push(action);
|
|
|
|
return transform_scope(scope, action.actions);
|
|
|
|
};
|
|
|
|
|
|
|
|
scope.transition = function() {
|
|
|
|
var subscope, action = {
|
|
|
|
impl: d3_transform_transition,
|
|
|
|
actions: [],
|
|
|
|
endActions: [],
|
|
|
|
ease: d3.ease("cubic-in-out"),
|
|
|
|
delay: 0,
|
|
|
|
duration: 250
|
|
|
|
};
|
|
|
|
actions.push(action);
|
|
|
|
subscope = transform_scope(scope, action.actions);
|
|
|
|
subscope.end = transform_scope(scope, action.endActions);
|
|
|
|
subscope.ease = function(x) {
|
|
|
|
action.ease = typeof x == "string" ? d3.ease(x) : x;
|
|
|
|
return subscope;
|
|
|
|
};
|
|
|
|
subscope.delay = function(x) {
|
|
|
|
action.delay = x;
|
|
|
|
return subscope;
|
|
|
|
};
|
|
|
|
subscope.duration = function(x) {
|
|
|
|
action.duration = x;
|
|
|
|
return subscope;
|
|
|
|
};
|
|
|
|
return subscope;
|
|
|
|
};
|
|
|
|
|
|
|
|
return scope;
|
|
|
|
}
|
|
|
|
|
|
|
|
transform.select = function(s) {
|
|
|
|
var action = {
|
|
|
|
impl: d3_transform_select,
|
|
|
|
selector: s,
|
|
|
|
actions: []
|
|
|
|
};
|
|
|
|
actions.push(action);
|
|
|
|
return transform_scope(transform, action.actions);
|
|
|
|
};
|
|
|
|
|
|
|
|
transform.selectAll = function(s) {
|
|
|
|
var action = {
|
2010-10-02 22:38:50 +04:00
|
|
|
impl: d3_transform_selectAll,
|
2010-09-28 22:26:55 +04:00
|
|
|
selector: s,
|
|
|
|
actions: []
|
|
|
|
};
|
|
|
|
actions.push(action);
|
|
|
|
return transform_scope(transform, action.actions);
|
|
|
|
};
|
|
|
|
|
|
|
|
transform.apply = function() {
|
|
|
|
d3_transform_stack.unshift(null);
|
|
|
|
d3_transform_impl(actions, [{node: document, index: 0}]);
|
|
|
|
d3_transform_stack.shift();
|
|
|
|
return transform;
|
|
|
|
};
|
|
|
|
|
|
|
|
return transform;
|
|
|
|
}
|
|
|
|
|
|
|
|
function d3_transform_impl(actions, nodes) {
|
|
|
|
var n = actions.length,
|
|
|
|
i; // current index
|
|
|
|
for (i = 0; i < n; ++i) actions[i].impl(nodes, d3_transform_impl);
|
|
|
|
}
|
2010-10-02 22:00:31 +04:00
|
|
|
function d3_transform_append(nodes, pass) {
|
2010-09-28 22:26:55 +04:00
|
|
|
var m = nodes.length,
|
|
|
|
n = this.name,
|
|
|
|
childNodes = [],
|
|
|
|
i, // current index
|
|
|
|
o, // current node
|
|
|
|
c; // current child
|
|
|
|
if (n.local) {
|
|
|
|
for (i = 0; i < m; ++i) {
|
|
|
|
childNodes.push(c = Object.create(o = nodes[i]));
|
2010-09-29 10:18:51 +04:00
|
|
|
c.node = (c.parent = o).node.appendChild(document.createElementNS(n.space, n.local));
|
2010-09-28 22:26:55 +04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (i = 0; i < m; ++i) {
|
|
|
|
childNodes.push(c = Object.create(o = nodes[i]));
|
2010-09-29 10:18:51 +04:00
|
|
|
c.node = (c.parent = o).node.appendChild(document.createElement(n));
|
2010-09-28 22:26:55 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
pass(this.actions, childNodes);
|
|
|
|
}
|
|
|
|
function d3_transform_attr(nodes) {
|
|
|
|
var m = nodes.length,
|
|
|
|
n = this.name,
|
|
|
|
v = this.value,
|
|
|
|
i, // current index
|
|
|
|
o, // current node
|
|
|
|
x; // current value (for value functions)
|
|
|
|
if (n.local) {
|
|
|
|
if (v == null) {
|
|
|
|
for (i = 0; i < m; ++i) {
|
|
|
|
nodes[i].node.removeAttributeNS(n.space, n.local);
|
|
|
|
}
|
|
|
|
} else if (typeof v == "function") {
|
|
|
|
for (i = 0; i < m; ++i) {
|
|
|
|
d3_transform_stack[0] = (o = nodes[i]).data;
|
|
|
|
x = v.apply(o, d3_transform_stack);
|
|
|
|
x == null
|
|
|
|
? o.node.removeAttributeNS(n.space, n.local)
|
|
|
|
: o.node.setAttributeNS(n.space, n.local, x);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (i = 0; i < m; ++i) {
|
|
|
|
nodes[i].node.setAttributeNS(n.space, n.local, v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (v == null) {
|
|
|
|
for (i = 0; i < m; ++i) {
|
|
|
|
nodes[i].node.removeAttribute(n);
|
|
|
|
}
|
|
|
|
} else if (typeof v == "function") {
|
|
|
|
for (i = 0; i < m; ++i) {
|
|
|
|
d3_transform_stack[0] = (o = nodes[i]).data;
|
|
|
|
x = v.apply(o, d3_transform_stack);
|
|
|
|
x == null
|
|
|
|
? o.node.removeAttribute(n)
|
|
|
|
: o.node.setAttribute(n, x);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (i = 0; i < m; ++i) {
|
|
|
|
nodes[i].node.setAttribute(n, v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-29 10:18:51 +04:00
|
|
|
function d3_transform_attr_bind(nodes) {
|
2010-09-28 22:26:55 +04:00
|
|
|
var m = nodes.length,
|
|
|
|
n = this.name,
|
2010-09-29 10:18:51 +04:00
|
|
|
v = this.bound || (this.bound = this.value),
|
|
|
|
b = "attr." + (n.local ? n.space + ":" + n.local : n),
|
2010-09-28 22:26:55 +04:00
|
|
|
i, // current index
|
2010-09-29 10:18:51 +04:00
|
|
|
o, // current node
|
|
|
|
x; // current value (for value functions)
|
|
|
|
if (v && v.bind) {
|
|
|
|
if (n.local) {
|
2010-09-28 22:26:55 +04:00
|
|
|
for (i = 0; i < m; ++i) {
|
2010-09-29 10:18:51 +04:00
|
|
|
(o = nodes[i]).value = o.node.getAttributeNS(n.space, n.local);
|
|
|
|
o.name = n.space + ":" + n.local;
|
|
|
|
d3_transform_stack[0] = o.data;
|
|
|
|
o[b] = v.bind.apply(o, d3_transform_stack);
|
|
|
|
delete o.value;
|
|
|
|
delete o.name;
|
2010-09-28 22:26:55 +04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (i = 0; i < m; ++i) {
|
2010-09-29 10:18:51 +04:00
|
|
|
(o = nodes[i]).value = o.node.getAttribute(n);
|
|
|
|
o.name = n;
|
|
|
|
d3_transform_stack[0] = o.data;
|
|
|
|
o[b] = v.bind.apply(o, d3_transform_stack);
|
|
|
|
delete o.value;
|
|
|
|
delete o.name;
|
2010-09-28 22:26:55 +04:00
|
|
|
}
|
|
|
|
}
|
2010-09-29 10:18:51 +04:00
|
|
|
this.value = function() {
|
|
|
|
return this[b].apply(this, arguments);
|
|
|
|
};
|
2010-09-28 22:26:55 +04:00
|
|
|
}
|
|
|
|
}
|
2010-10-21 23:53:56 +04:00
|
|
|
function d3_transform_bind(nodes) {
|
|
|
|
var m = nodes.length,
|
|
|
|
t = "on" + this.type,
|
|
|
|
l = this.listener,
|
|
|
|
i = 0, // current node index
|
|
|
|
o, // curent node
|
|
|
|
stack = d3_transform_stack.slice(); // stack snapshot
|
|
|
|
|
|
|
|
// TODO this overwrites any actions registered with .on!
|
|
|
|
// TODO using namespaced event handlers could fix this ^ issue.
|
|
|
|
if (l) {
|
|
|
|
for (; i < m; ++i) {
|
|
|
|
o = nodes[i];
|
|
|
|
o.node[t] = bind(o, o.data);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (; i < m; ++i) {
|
|
|
|
nodes[i].node[t] = null; // clear any previously-registered actions
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function bind(o, d) {
|
|
|
|
return function(e) {
|
|
|
|
var s = d3_transform_stack;
|
|
|
|
try {
|
|
|
|
d3.event = e;
|
|
|
|
stack[0] = d;
|
|
|
|
l.apply(o, d3_transform_stack = stack);
|
|
|
|
} finally {
|
|
|
|
delete d3.event;
|
|
|
|
d3_transform_stack = s;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
2010-09-28 22:26:55 +04:00
|
|
|
function d3_transform_data(nodes, pass) {
|
|
|
|
var data = this.value,
|
|
|
|
m = nodes.length,
|
|
|
|
n, // data length
|
|
|
|
key = this.key,
|
|
|
|
kn, // key name
|
|
|
|
kv, // key value
|
|
|
|
k, // current key
|
|
|
|
i, // current index
|
|
|
|
j, // current index
|
|
|
|
d, // current datum
|
|
|
|
o, // current node
|
|
|
|
enterNodes = [],
|
|
|
|
updateNodes = [],
|
|
|
|
exitNodes = [],
|
|
|
|
nodesByKey, // map key -> node
|
|
|
|
dataByKey, // map key -> data
|
|
|
|
indexesByKey; // map key -> index
|
|
|
|
|
|
|
|
if (typeof data == "function") {
|
|
|
|
d = d3_transform_stack.shift();
|
|
|
|
data = data.apply(null, d3_transform_stack);
|
|
|
|
d3_transform_stack.unshift(d);
|
|
|
|
}
|
|
|
|
|
|
|
|
n = data.length;
|
|
|
|
|
|
|
|
if (key) {
|
|
|
|
kn = key.name;
|
|
|
|
kv = key.value;
|
|
|
|
nodesByKey = {};
|
|
|
|
dataByKey = {};
|
|
|
|
indexesByKey = {};
|
|
|
|
|
|
|
|
// compute map from key -> node
|
|
|
|
if (kn.local) {
|
|
|
|
for (i = 0; i < m; ++i) {
|
|
|
|
o = nodes[i].node;
|
|
|
|
if (o) {
|
|
|
|
k = o.getAttributeNS(kn.space, kn.local);
|
|
|
|
if (k != null) nodesByKey[k] = o;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (i = 0; i < m; ++i) {
|
|
|
|
o = nodes[i].node;
|
|
|
|
if (o) {
|
|
|
|
k = o.getAttribute(kn);
|
|
|
|
if (k != null) nodesByKey[k] = o;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// compute map from key -> data
|
|
|
|
for (i = 0; i < n; ++i) {
|
|
|
|
d3_transform_stack[0] = d = data[i];
|
|
|
|
k = kv.apply(null, d3_transform_stack);
|
|
|
|
if (k != null) {
|
|
|
|
dataByKey[k] = d;
|
|
|
|
indexesByKey[k] = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// compute entering and updating nodes
|
|
|
|
for (k in dataByKey) {
|
|
|
|
d = dataByKey[k];
|
|
|
|
i = indexesByKey[k];
|
|
|
|
if (o = nodesByKey[k]) {
|
|
|
|
updateNodes.push({
|
|
|
|
node: o,
|
|
|
|
data: d,
|
|
|
|
key: k,
|
|
|
|
index: i
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
enterNodes.push({
|
2010-09-29 10:18:51 +04:00
|
|
|
node: nodes.parent.node,
|
2010-09-28 22:26:55 +04:00
|
|
|
data: d,
|
|
|
|
key: k,
|
|
|
|
index: i
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// compute exiting nodes
|
|
|
|
for (k in nodesByKey) {
|
|
|
|
if (!(k in dataByKey)) {
|
|
|
|
exitNodes.push({node: nodesByKey[k]});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
k = n < m ? n : m;
|
|
|
|
|
|
|
|
// compute updating nodes
|
|
|
|
for (i = 0; i < k; ++i) {
|
|
|
|
(o = nodes[i]).data = data[i];
|
|
|
|
if (o.node) {
|
|
|
|
updateNodes.push(o);
|
|
|
|
} else {
|
2010-09-29 10:18:51 +04:00
|
|
|
o.node = o.parent.node;
|
2010-09-28 22:26:55 +04:00
|
|
|
enterNodes.push(o);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// compute entering nodes
|
|
|
|
for (j = i; j < n; ++j) {
|
|
|
|
enterNodes.push({
|
2010-09-29 10:18:51 +04:00
|
|
|
node: nodes.parent.node,
|
2010-09-28 22:26:55 +04:00
|
|
|
data: data[j],
|
|
|
|
index: j
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// compute exiting nodes
|
|
|
|
for (j = i; j < m; ++j) {
|
|
|
|
exitNodes.push(nodes[j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pass(this.enterActions, enterNodes);
|
|
|
|
pass(this.actions, updateNodes);
|
|
|
|
pass(this.exitActions, exitNodes);
|
|
|
|
}
|
|
|
|
|
2010-09-29 10:18:51 +04:00
|
|
|
function d3_transform_data_bind(nodes, pass) {
|
2010-09-28 22:26:55 +04:00
|
|
|
var m = nodes.length,
|
2010-09-29 10:18:51 +04:00
|
|
|
n = this.name,
|
|
|
|
v = this.bound || (this.bound = this.value),
|
|
|
|
d, // bound data
|
2010-09-28 22:26:55 +04:00
|
|
|
i, // current index
|
2010-09-29 10:18:51 +04:00
|
|
|
o, // current node
|
|
|
|
x; // current value (for value functions)
|
|
|
|
if (v && v.bind) {
|
|
|
|
d = [];
|
2010-09-28 22:26:55 +04:00
|
|
|
for (i = 0; i < m; ++i) {
|
2010-09-29 10:18:51 +04:00
|
|
|
d3_transform_stack[0] = (o = nodes[i]).data;
|
|
|
|
o.value = o.data;
|
|
|
|
o.data_ = v.bind.apply(o, d3_transform_stack);
|
|
|
|
delete o.value;
|
2010-09-28 22:26:55 +04:00
|
|
|
}
|
2010-09-29 10:18:51 +04:00
|
|
|
this.value = function() {
|
|
|
|
d3_transform_stack.unshift(null);
|
|
|
|
for (i = 0; i < m; ++i) {
|
|
|
|
d3_transform_stack[0] = (o = nodes[i]).data;
|
|
|
|
d[i] = o.data_.apply(o, d3_transform_stack);
|
|
|
|
}
|
|
|
|
d3_transform_stack.shift();
|
|
|
|
return d;
|
|
|
|
};
|
2010-09-28 22:26:55 +04:00
|
|
|
} else {
|
2010-09-29 10:18:51 +04:00
|
|
|
d3_transform_data.call(this, nodes, pass);
|
2010-09-28 22:26:55 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
function d3_transform_remove(nodes) {
|
|
|
|
var m = nodes.length,
|
|
|
|
s = this.selector,
|
|
|
|
r, // the selected nodes (for selectors)
|
|
|
|
i, // current node index
|
|
|
|
j, // current selector index
|
|
|
|
k, // current selector length
|
|
|
|
o; // current node to remove
|
|
|
|
if (s == null) {
|
|
|
|
for (i = 0; i < m; ++i) {
|
|
|
|
o = nodes[i].node;
|
|
|
|
o.parentNode.removeChild(o);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (i = 0; i < m; ++i) {
|
|
|
|
r = nodes[i].node.querySelectorAll(s);
|
|
|
|
for (j = 0, k = r.length; j < k; j++) {
|
|
|
|
o = r[j];
|
|
|
|
o.parentNode.removeChild(o);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function d3_transform_on(nodes) {
|
|
|
|
var actions = this.actions,
|
|
|
|
n = actions.length,
|
|
|
|
m = nodes.length,
|
|
|
|
t = "on" + this.type,
|
|
|
|
i = 0, // current index
|
|
|
|
o, // curent node
|
|
|
|
stack = d3_transform_stack.slice(); // stack snapshot
|
|
|
|
|
2010-10-21 23:53:56 +04:00
|
|
|
// TODO this overwrites any actions registered with .bind!
|
|
|
|
// TODO using namespaced event handlers could fix this ^ issue.
|
2010-09-28 22:26:55 +04:00
|
|
|
if (n) {
|
|
|
|
for (; i < m; ++i) {
|
|
|
|
o = nodes[i];
|
|
|
|
o.node[t] = bind([o]);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (; i < m; ++i) {
|
2010-10-21 23:53:56 +04:00
|
|
|
nodes[i].node[t] = null; // clear any previously-registered actions
|
2010-09-28 22:26:55 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function bind(o) {
|
|
|
|
return function(e) {
|
|
|
|
var s = d3_transform_stack;
|
|
|
|
try {
|
|
|
|
d3_transform_stack = stack;
|
|
|
|
d3.event = e;
|
|
|
|
for (i = 0; i < n; ++i) actions[i].impl(o, d3_transform_impl);
|
|
|
|
} finally {
|
|
|
|
delete d3.event;
|
|
|
|
d3_transform_stack = s;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function d3_transform_filter(nodes, pass) {
|
|
|
|
var filteredNodes = [],
|
|
|
|
m = nodes.length,
|
|
|
|
f = this.filter,
|
|
|
|
i, // the node index
|
|
|
|
o; // current item
|
|
|
|
for (i = 0; i < m; ++i) {
|
|
|
|
d3_transform_stack[0] = (o = nodes[i]).data;
|
|
|
|
if (f.apply(o, d3_transform_stack)) filteredNodes.push(o);
|
|
|
|
}
|
|
|
|
pass(this.actions, filteredNodes);
|
|
|
|
}
|
|
|
|
d3.select = function(s) {
|
|
|
|
return d3_transform().select(s);
|
|
|
|
};
|
|
|
|
|
|
|
|
function d3_transform_select(nodes, pass) {
|
|
|
|
var selectedNodes = [],
|
|
|
|
m = nodes.length,
|
|
|
|
s = this.selector,
|
|
|
|
i, // the node index
|
|
|
|
o, // current item
|
|
|
|
p, // current node
|
|
|
|
c, // current selected item
|
|
|
|
e; // current selected node
|
|
|
|
for (i = 0; i < m; ++i) {
|
|
|
|
e = (p = (o = nodes[i]).node).querySelector(s);
|
|
|
|
selectedNodes.push(c = Object.create(o));
|
2010-09-29 10:18:51 +04:00
|
|
|
c.parent = o;
|
2010-09-28 22:26:55 +04:00
|
|
|
c.node = e;
|
|
|
|
}
|
|
|
|
pass(this.actions, selectedNodes);
|
|
|
|
}
|
2010-09-29 10:18:51 +04:00
|
|
|
|
|
|
|
function d3_transform_select_bind(nodes, pass) {
|
|
|
|
var action = this;
|
|
|
|
d3_transform_select.call(this, nodes, function(actions, selectedNodes) {
|
|
|
|
pass(actions, selectedNodes);
|
|
|
|
action.impl = function(nodes, pass) {
|
|
|
|
pass(actions, selectedNodes);
|
|
|
|
};
|
|
|
|
});
|
|
|
|
}
|
2010-09-28 22:26:55 +04:00
|
|
|
d3.selectAll = function(s) {
|
|
|
|
return d3_transform().selectAll(s);
|
|
|
|
};
|
|
|
|
|
2010-10-02 22:38:50 +04:00
|
|
|
function d3_transform_selectAll(nodes, pass) {
|
2010-09-28 22:26:55 +04:00
|
|
|
var m = nodes.length,
|
|
|
|
s = this.selector,
|
|
|
|
i, // the node index
|
2010-09-29 10:18:51 +04:00
|
|
|
o; // the current node
|
2010-09-28 22:26:55 +04:00
|
|
|
d3_transform_stack.unshift(null);
|
|
|
|
for (i = 0; i < m; ++i) {
|
|
|
|
d3_transform_stack[1] = (o = nodes[i]).data;
|
2010-09-29 10:18:51 +04:00
|
|
|
pass(this.actions, d3_transform_nodes(o.node.querySelectorAll(s), o));
|
2010-09-28 22:26:55 +04:00
|
|
|
}
|
|
|
|
d3_transform_stack.shift();
|
|
|
|
}
|
|
|
|
|
2010-10-02 22:38:50 +04:00
|
|
|
function d3_transform_selectAll_bind(nodes, pass) {
|
2010-09-29 10:18:51 +04:00
|
|
|
var m = nodes.length,
|
|
|
|
i, // the node index
|
|
|
|
o; // the current node
|
2010-10-02 22:38:50 +04:00
|
|
|
d3_transform_selectAll.call(this, nodes, function(actions, nodes) {
|
2010-09-29 10:18:51 +04:00
|
|
|
pass(actions, nodes.parent.selectAll = nodes);
|
|
|
|
});
|
|
|
|
this.impl = function(nodes, pass) {
|
|
|
|
d3_transform_stack.unshift(null);
|
|
|
|
for (i = 0, m = nodes.length; i < m; ++i) {
|
|
|
|
d3_transform_stack[1] = (o = nodes[i]).data;
|
|
|
|
pass(this.actions, o.selectAll);
|
|
|
|
}
|
|
|
|
d3_transform_stack.shift();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function d3_transform_nodes(x, o) {
|
2010-09-28 22:26:55 +04:00
|
|
|
var nodes = [],
|
|
|
|
i = 0,
|
|
|
|
n = x.length;
|
2010-09-29 10:18:51 +04:00
|
|
|
nodes.parent = o;
|
2010-09-28 22:26:55 +04:00
|
|
|
for (; i < n; i++) nodes.push({node: x[i], index: i});
|
|
|
|
return nodes;
|
|
|
|
}
|
|
|
|
function d3_transform_style(nodes) {
|
|
|
|
var m = nodes.length,
|
|
|
|
n = this.name,
|
|
|
|
v = this.value,
|
|
|
|
p = this.priority,
|
|
|
|
i, // current index
|
|
|
|
o, // current node
|
|
|
|
x; // current value (for value functions)
|
|
|
|
if (v == null) {
|
|
|
|
for (i = 0; i < m; ++i) {
|
|
|
|
nodes[i].node.style.removeProperty(n);
|
|
|
|
}
|
|
|
|
} else if (typeof v == "function") {
|
|
|
|
for (i = 0; i < m; ++i) {
|
|
|
|
o = nodes[i];
|
|
|
|
d3_transform_stack[0] = o.data;
|
|
|
|
x = v.apply(o, d3_transform_stack);
|
|
|
|
x == null
|
|
|
|
? o.node.style.removeProperty(n)
|
|
|
|
: o.node.style.setProperty(n, x, p);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (i = 0; i < m; ++i) {
|
|
|
|
nodes[i].node.style.setProperty(n, v, p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-29 10:18:51 +04:00
|
|
|
function d3_transform_style_bind(nodes) {
|
2010-09-28 22:26:55 +04:00
|
|
|
var m = nodes.length,
|
|
|
|
n = this.name,
|
2010-09-29 10:18:51 +04:00
|
|
|
v = this.bound || (this.bound = this.value),
|
|
|
|
b = "style." + n,
|
2010-09-28 22:26:55 +04:00
|
|
|
i, // current index
|
2010-09-29 10:18:51 +04:00
|
|
|
o, // current node
|
|
|
|
x; // current value (for value functions)
|
|
|
|
if (v && v.bind) {
|
2010-09-28 22:26:55 +04:00
|
|
|
for (i = 0; i < m; ++i) {
|
2010-09-29 10:18:51 +04:00
|
|
|
(o = nodes[i]).value = o.node.style.getPropertyValue(n);
|
|
|
|
o.name = n;
|
|
|
|
d3_transform_stack[0] = o.data;
|
|
|
|
o[b] = v.bind.apply(o, d3_transform_stack);
|
|
|
|
delete o.value;
|
|
|
|
delete o.name;
|
2010-09-28 22:26:55 +04:00
|
|
|
}
|
2010-09-29 10:18:51 +04:00
|
|
|
this.value = function() {
|
|
|
|
return this[b].apply(this, arguments);
|
|
|
|
};
|
2010-09-28 22:26:55 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
function d3_transform_text(nodes) {
|
|
|
|
var m = nodes.length,
|
|
|
|
v = this.value,
|
|
|
|
i, // current node index
|
|
|
|
o, // current node
|
|
|
|
x; // current value (for value functions)
|
|
|
|
if (typeof v == "function") {
|
|
|
|
for (i = 0; i < m; ++i) {
|
|
|
|
o = nodes[i];
|
|
|
|
d3_transform_stack[0] = o.data;
|
|
|
|
x = v.apply(o, d3_transform_stack);
|
|
|
|
o = o.node;
|
|
|
|
while (o.lastChild) o.removeChild(o.lastChild);
|
|
|
|
o.appendChild(document.createTextNode(x));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (i = 0; i < m; ++i) {
|
|
|
|
o = nodes[i].node;
|
|
|
|
while (o.lastChild) o.removeChild(o.lastChild);
|
|
|
|
o.appendChild(document.createTextNode(v));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function d3_transform_transition(nodes) {
|
|
|
|
var actions = this.actions,
|
|
|
|
endActions = this.endActions,
|
|
|
|
start = Date.now(),
|
|
|
|
delay = this.delay,
|
|
|
|
minDelay = Infinity,
|
|
|
|
duration = this.duration,
|
|
|
|
ease = this.ease,
|
|
|
|
interval,
|
|
|
|
n = actions.length,
|
|
|
|
k = endActions.length,
|
|
|
|
m = nodes.length,
|
|
|
|
i, // current index
|
|
|
|
j, // current index
|
|
|
|
o, // curent node
|
|
|
|
x, // current value
|
|
|
|
stack = d3_transform_stack.slice(); // stack snapshot
|
|
|
|
|
|
|
|
// If delay is a function, transition each node separately.
|
|
|
|
if (typeof delay == "function") {
|
|
|
|
for (i = 0; i < m; ++i) {
|
|
|
|
d3_transform_stack[0] = (o = nodes[i]).data;
|
|
|
|
x = o.delay = delay.apply(o, d3_transform_stack);
|
|
|
|
if (x < minDelay) minDelay = x;
|
|
|
|
}
|
|
|
|
setTimeout(function() {
|
|
|
|
bind(interval = setInterval(tickOne, 24));
|
|
|
|
}, minDelay);
|
|
|
|
} else {
|
|
|
|
setTimeout(function() {
|
|
|
|
bind(interval = setInterval(tickAll, 24));
|
|
|
|
}, delay);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bind the active transition to the node.
|
|
|
|
function bind(interval) {
|
|
|
|
var s = d3_transform_stack;
|
|
|
|
for (i = 0; i < m; ++i) {
|
|
|
|
(o = nodes[i]).node.interval = interval;
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
d3.time = 0;
|
|
|
|
d3_transform_stack = stack;
|
|
|
|
d3_transform_transition_bind(actions, nodes);
|
|
|
|
} finally {
|
|
|
|
delete d3.time;
|
|
|
|
d3_transform_stack = s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function tickOne() {
|
|
|
|
var s = d3_transform_stack,
|
|
|
|
a = nodes.filter(function(o) { return o.node.interval == interval; }),
|
|
|
|
m = a.length,
|
|
|
|
q = Date.now(),
|
|
|
|
t,
|
|
|
|
d = true;
|
|
|
|
try {
|
|
|
|
d3_transform_stack = stack;
|
|
|
|
for (i = 0; i < m; ++i) {
|
|
|
|
o = a[i];
|
|
|
|
t = (q - start - o.delay) / duration;
|
|
|
|
if (t < 0) continue;
|
|
|
|
if (t > 1) t = 1;
|
|
|
|
else d = false;
|
|
|
|
d3.time = ease(t);
|
|
|
|
for (j = 0; j < n; ++j) actions[j].impl([o], d3_transform_impl);
|
|
|
|
if (t == 1) {
|
|
|
|
for (j = 0; j < k; ++j) endActions[j].impl([o], d3_transform_impl);
|
|
|
|
o.delay = Infinity; // stop transitioning this node
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
delete d3.time;
|
|
|
|
d3_transform_stack = s;
|
|
|
|
}
|
|
|
|
if (d) clearInterval(interval);
|
|
|
|
}
|
|
|
|
|
|
|
|
function tickAll() {
|
|
|
|
var s = d3_transform_stack,
|
|
|
|
t = (Date.now() - start - delay) / duration,
|
|
|
|
a = nodes.filter(function(o) { return o.node.interval == interval; });
|
|
|
|
try {
|
|
|
|
d3_transform_stack = stack;
|
|
|
|
d3.time = ease(t < 0 ? 0 : t > 1 ? 1 : t);
|
|
|
|
for (i = 0; i < n; ++i) actions[i].impl(a, d3_transform_impl);
|
|
|
|
} finally {
|
|
|
|
delete d3.time;
|
|
|
|
d3_transform_stack = s;
|
|
|
|
}
|
|
|
|
if (t >= 1) {
|
|
|
|
clearInterval(interval);
|
|
|
|
try {
|
|
|
|
d3_transform_stack = stack;
|
|
|
|
for (i = 0; i < k; ++i) endActions[i].impl(a, d3_transform_impl);
|
|
|
|
} finally {
|
|
|
|
d3_transform_stack = s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function d3_transform_transition_bind(actions, nodes) {
|
|
|
|
var n = actions.length,
|
|
|
|
m = nodes.length,
|
|
|
|
a, // current action
|
|
|
|
i; // current index
|
|
|
|
for (i = 0; i < n; ++i) {
|
|
|
|
a = actions[i];
|
2010-09-29 10:18:51 +04:00
|
|
|
if (a.bind) a.bind(nodes, d3_transform_transition_bind);
|
2010-09-28 22:26:55 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
})(this);
|