Merge remote-tracking branch 'origin/map' into 2.10.0
Conflicts: src/core/transition-attr.js src/core/transition-style.js
This commit is contained in:
Коммит
15ba641fa3
|
@ -373,7 +373,7 @@
|
|||
return d == null;
|
||||
}
|
||||
function d3_collapse(s) {
|
||||
return s.replace(/^\s+|\s+$/g, "").replace(/\s+/g, " ");
|
||||
return s.trim().replace(/\s+/g, " ");
|
||||
}
|
||||
d3.range = function(start, stop, step) {
|
||||
if (arguments.length < 3) {
|
||||
|
@ -958,8 +958,8 @@
|
|||
};
|
||||
};
|
||||
var d3_interpolate_number = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;
|
||||
function d3_interpolateByName(n) {
|
||||
return n == "transform" ? d3.interpolateTransform : d3.interpolate;
|
||||
function d3_interpolateByName(name) {
|
||||
return name == "transform" ? d3.interpolateTransform : d3.interpolate;
|
||||
}
|
||||
d3.interpolators = [ d3.interpolateObject, function(a, b) {
|
||||
return b instanceof Array && d3.interpolateArray(a, b);
|
||||
|
@ -1329,11 +1329,19 @@
|
|||
};
|
||||
}
|
||||
d3_selectionPrototype.attr = function(name, value) {
|
||||
name = d3.ns.qualify(name);
|
||||
if (arguments.length < 2) {
|
||||
if (typeof name === "string") {
|
||||
var node = this.node();
|
||||
name = d3.ns.qualify(name);
|
||||
return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name);
|
||||
}
|
||||
for (value in name) this.each(d3_selection_attr(value, name[value]));
|
||||
return this;
|
||||
}
|
||||
return this.each(d3_selection_attr(name, value));
|
||||
};
|
||||
function d3_selection_attr(name, value) {
|
||||
name = d3.ns.qualify(name);
|
||||
function attrNull() {
|
||||
this.removeAttribute(name);
|
||||
}
|
||||
|
@ -1354,52 +1362,73 @@
|
|||
var x = value.apply(this, arguments);
|
||||
if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x);
|
||||
}
|
||||
return this.each(value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant);
|
||||
};
|
||||
return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant;
|
||||
}
|
||||
d3_selectionPrototype.classed = function(name, value) {
|
||||
var names = d3_collapse(name).split(" "), n = names.length, i = -1;
|
||||
if (arguments.length > 1) {
|
||||
while (++i < n) d3_selection_classed.call(this, names[i], value);
|
||||
return this;
|
||||
if (arguments.length < 2) {
|
||||
if (typeof name === "string") {
|
||||
var node = this.node(), n = (name = name.trim().split(/^|\s+/g)).length, i = -1;
|
||||
if (value = node.classList) {
|
||||
while (++i < n) if (!value.contains(name[i])) return false;
|
||||
} else {
|
||||
while (++i < n) if (!d3_selection_classed.call(this, names[i])) return false;
|
||||
value = node.className;
|
||||
if (value.baseVal != null) value = value.baseVal;
|
||||
while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
function d3_selection_classed(name, value) {
|
||||
var re = new RegExp("(^|\\s+)" + d3.requote(name) + "(\\s+|$)", "g");
|
||||
if (arguments.length < 2) {
|
||||
var node = this.node();
|
||||
if (c = node.classList) return c.contains(name);
|
||||
var c = node.className;
|
||||
re.lastIndex = 0;
|
||||
return re.test(c.baseVal != null ? c.baseVal : c);
|
||||
for (value in name) this.each(d3_selection_classed(value, name[value]));
|
||||
return this;
|
||||
}
|
||||
function classedAdd() {
|
||||
if (c = this.classList) return c.add(name);
|
||||
var c = this.className, cb = c.baseVal != null, cv = cb ? c.baseVal : c;
|
||||
return this.each(d3_selection_classed(name, value));
|
||||
};
|
||||
function d3_selection_classedRe(name) {
|
||||
return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g");
|
||||
}
|
||||
function d3_selection_classed(name, value) {
|
||||
name = name.trim().split(/\s+/).map(d3_selection_classedName);
|
||||
var n = name.length;
|
||||
function classedConstant() {
|
||||
var i = -1;
|
||||
while (++i < n) name[i](this, value);
|
||||
}
|
||||
function classedFunction() {
|
||||
var i = -1, x = value.apply(this, arguments);
|
||||
while (++i < n) name[i](this, x);
|
||||
}
|
||||
return typeof value === "function" ? classedFunction : classedConstant;
|
||||
}
|
||||
function d3_selection_classedName(name) {
|
||||
var re = d3_selection_classedRe(name);
|
||||
return function(node, value) {
|
||||
if (c = node.classList) return value ? c.add(name) : c.remove(name);
|
||||
var c = node.className, cb = c.baseVal != null, cv = cb ? c.baseVal : c;
|
||||
if (value) {
|
||||
re.lastIndex = 0;
|
||||
if (!re.test(cv)) {
|
||||
cv = d3_collapse(cv + " " + name);
|
||||
if (cb) c.baseVal = cv; else this.className = cv;
|
||||
if (cb) c.baseVal = cv; else node.className = cv;
|
||||
}
|
||||
}
|
||||
function classedRemove() {
|
||||
if (c = this.classList) return c.remove(name);
|
||||
var c = this.className, cb = c.baseVal != null, cv = cb ? c.baseVal : c;
|
||||
if (cv) {
|
||||
} else if (cv) {
|
||||
cv = d3_collapse(cv.replace(re, " "));
|
||||
if (cb) c.baseVal = cv; else this.className = cv;
|
||||
if (cb) c.baseVal = cv; else node.className = cv;
|
||||
}
|
||||
}
|
||||
function classedFunction() {
|
||||
(value.apply(this, arguments) ? classedAdd : classedRemove).call(this);
|
||||
}
|
||||
return this.each(typeof value === "function" ? classedFunction : value ? classedAdd : classedRemove);
|
||||
};
|
||||
}
|
||||
d3_selectionPrototype.style = function(name, value, priority) {
|
||||
if (arguments.length < 3) priority = "";
|
||||
if (arguments.length < 2) return window.getComputedStyle(this.node(), null).getPropertyValue(name);
|
||||
var n = arguments.length;
|
||||
if (n < 3) {
|
||||
if (typeof name !== "string") {
|
||||
if (n < 2) value = "";
|
||||
for (priority in name) this.each(d3_selection_style(priority, name[priority], value));
|
||||
return this;
|
||||
}
|
||||
if (n < 2) return window.getComputedStyle(this.node(), null).getPropertyValue(name);
|
||||
priority = "";
|
||||
}
|
||||
return this.each(d3_selection_style(name, value, priority));
|
||||
};
|
||||
function d3_selection_style(name, value, priority) {
|
||||
function styleNull() {
|
||||
this.style.removeProperty(name);
|
||||
}
|
||||
|
@ -1410,10 +1439,17 @@
|
|||
var x = value.apply(this, arguments);
|
||||
if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority);
|
||||
}
|
||||
return this.each(value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant);
|
||||
};
|
||||
return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant;
|
||||
}
|
||||
d3_selectionPrototype.property = function(name, value) {
|
||||
if (arguments.length < 2) return this.node()[name];
|
||||
if (arguments.length < 2) {
|
||||
if (typeof name === "string") return this.node()[name];
|
||||
for (value in name) this.each(d3_selection_property(value, name[value]));
|
||||
return this;
|
||||
}
|
||||
return this.each(d3_selection_property(name, value));
|
||||
};
|
||||
function d3_selection_property(name, value) {
|
||||
function propertyNull() {
|
||||
delete this[name];
|
||||
}
|
||||
|
@ -1424,8 +1460,8 @@
|
|||
var x = value.apply(this, arguments);
|
||||
if (x == null) delete this[name]; else this[name] = x;
|
||||
}
|
||||
return this.each(value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant);
|
||||
};
|
||||
return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant;
|
||||
}
|
||||
d3_selectionPrototype.text = function(value) {
|
||||
return arguments.length < 1 ? this.node().textContent : this.each(typeof value === "function" ? function() {
|
||||
var v = value.apply(this, arguments);
|
||||
|
@ -1609,21 +1645,34 @@
|
|||
};
|
||||
}
|
||||
d3_selectionPrototype.on = function(type, listener, capture) {
|
||||
if (arguments.length < 3) capture = false;
|
||||
var n = arguments.length;
|
||||
if (n < 3) {
|
||||
if (typeof type !== "string") {
|
||||
if (n < 2) listener = false;
|
||||
for (capture in type) this.each(d3_selection_on(capture, type[capture], listener));
|
||||
return this;
|
||||
}
|
||||
if (n < 2) return (n = this.node()["__on" + type]) && n._;
|
||||
capture = false;
|
||||
}
|
||||
return this.each(d3_selection_on(type, listener, capture));
|
||||
};
|
||||
function d3_selection_on(type, listener, capture) {
|
||||
var name = "__on" + type, i = type.indexOf(".");
|
||||
if (i > 0) type = type.substring(0, i);
|
||||
if (arguments.length < 2) return (i = this.node()[name]) && i._;
|
||||
return this.each(function() {
|
||||
var node = this, args = arguments, o = node[name];
|
||||
if (o) {
|
||||
node.removeEventListener(type, o, o.$);
|
||||
delete node[name];
|
||||
function onRemove() {
|
||||
var wrapper = this[name];
|
||||
if (wrapper) {
|
||||
this.removeEventListener(type, wrapper, wrapper.$);
|
||||
delete this[name];
|
||||
}
|
||||
if (listener) {
|
||||
node.addEventListener(type, node[name] = l, l.$ = capture);
|
||||
l._ = listener;
|
||||
}
|
||||
function l(e) {
|
||||
function onAdd() {
|
||||
var node = this, args = arguments;
|
||||
onRemove.call(this);
|
||||
this.addEventListener(type, this[name] = wrapper, wrapper.$ = capture);
|
||||
wrapper._ = listener;
|
||||
function wrapper(e) {
|
||||
var o = d3.event;
|
||||
d3.event = e;
|
||||
args[0] = node.__data__;
|
||||
|
@ -1633,8 +1682,9 @@
|
|||
d3.event = o;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
return listener ? onAdd : onRemove;
|
||||
}
|
||||
d3_selectionPrototype.each = function(callback) {
|
||||
return d3_selection_each(this, function(node, i, j) {
|
||||
callback.call(node, node.__data__, i, j);
|
||||
|
@ -1836,7 +1886,11 @@
|
|||
return d3_transition(subgroups, this.id, this.time).ease(this.ease());
|
||||
};
|
||||
d3_transitionPrototype.attr = function(name, value) {
|
||||
return this.attrTween(name, d3.tween(value, d3_interpolateByName(name)));
|
||||
if (arguments.length < 2) {
|
||||
for (value in name) this.attrTween(value, d3_tweenByName(name[value], value));
|
||||
return this;
|
||||
}
|
||||
return this.attrTween(name, d3_tweenByName(value, name));
|
||||
};
|
||||
d3_transitionPrototype.attrTween = function(nameNS, tween) {
|
||||
var name = d3.ns.qualify(nameNS);
|
||||
|
@ -1855,8 +1909,16 @@
|
|||
return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween);
|
||||
};
|
||||
d3_transitionPrototype.style = function(name, value, priority) {
|
||||
if (arguments.length < 3) priority = "";
|
||||
return this.styleTween(name, d3.tween(value, d3_interpolateByName(name)), priority);
|
||||
var n = arguments.length;
|
||||
if (n < 3) {
|
||||
if (typeof name !== "string") {
|
||||
if (n < 2) value = "";
|
||||
for (priority in name) this.styleTween(priority, d3_tweenByName(name[priority], priority), value);
|
||||
return this;
|
||||
}
|
||||
priority = "";
|
||||
}
|
||||
return this.styleTween(name, d3_tweenByName(value, name), priority);
|
||||
};
|
||||
d3_transitionPrototype.styleTween = function(name, tween, priority) {
|
||||
if (arguments.length < 3) priority = "";
|
||||
|
@ -1924,6 +1986,9 @@
|
|||
function d3_tweenNull(d, i, a) {
|
||||
return a != "" && d3_tweenRemove;
|
||||
}
|
||||
function d3_tweenByName(b, name) {
|
||||
return d3.tween(b, d3_interpolateByName(name));
|
||||
}
|
||||
var d3_timer_queue = null, d3_timer_interval, d3_timer_timeout;
|
||||
d3.timer = function(callback, delay, then) {
|
||||
var found = false, t0, t1 = d3_timer_queue;
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1,3 +1,3 @@
|
|||
function d3_collapse(s) {
|
||||
return s.replace(/^\s+|\s+$/g, "").replace(/\s+/g, " ");
|
||||
return s.trim().replace(/\s+/g, " ");
|
||||
}
|
||||
|
|
|
@ -217,8 +217,8 @@ d3.interpolateObject = function(a, b) {
|
|||
|
||||
var d3_interpolate_number = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;
|
||||
|
||||
function d3_interpolateByName(n) {
|
||||
return n == "transform"
|
||||
function d3_interpolateByName(name) {
|
||||
return name == "transform"
|
||||
? d3.interpolateTransform
|
||||
: d3.interpolate;
|
||||
}
|
||||
|
|
|
@ -1,44 +1,59 @@
|
|||
d3_selectionPrototype.attr = function(name, value) {
|
||||
name = d3.ns.qualify(name);
|
||||
|
||||
// If no value is specified, return the first value.
|
||||
if (arguments.length < 2) {
|
||||
|
||||
// For attr(string), return the attribute value for the first node.
|
||||
if (typeof name === "string") {
|
||||
var node = this.node();
|
||||
name = d3.ns.qualify(name);
|
||||
return name.local
|
||||
? node.getAttributeNS(name.space, name.local)
|
||||
: node.getAttribute(name);
|
||||
}
|
||||
|
||||
// For attr(object), the object specifies the names and values of the
|
||||
// attributes to set or remove. The values may be functions that are
|
||||
// evaluated for each element.
|
||||
for (value in name) this.each(d3_selection_attr(value, name[value]));
|
||||
return this;
|
||||
}
|
||||
|
||||
return this.each(d3_selection_attr(name, value));
|
||||
};
|
||||
|
||||
function d3_selection_attr(name, value) {
|
||||
name = d3.ns.qualify(name);
|
||||
|
||||
// For attr(string, null), remove the attribute with the specified name.
|
||||
function attrNull() {
|
||||
this.removeAttribute(name);
|
||||
}
|
||||
|
||||
function attrNullNS() {
|
||||
this.removeAttributeNS(name.space, name.local);
|
||||
}
|
||||
|
||||
// For attr(string, string), set the attribute with the specified name.
|
||||
function attrConstant() {
|
||||
this.setAttribute(name, value);
|
||||
}
|
||||
|
||||
function attrConstantNS() {
|
||||
this.setAttributeNS(name.space, name.local, value);
|
||||
}
|
||||
|
||||
// For attr(string, function), evaluate the function for each element, and set
|
||||
// or remove the attribute as appropriate.
|
||||
function attrFunction() {
|
||||
var x = value.apply(this, arguments);
|
||||
if (x == null) this.removeAttribute(name);
|
||||
else this.setAttribute(name, x);
|
||||
}
|
||||
|
||||
function attrFunctionNS() {
|
||||
var x = value.apply(this, arguments);
|
||||
if (x == null) this.removeAttributeNS(name.space, name.local);
|
||||
else this.setAttributeNS(name.space, name.local, x);
|
||||
}
|
||||
|
||||
return this.each(value == null
|
||||
return value == null
|
||||
? (name.local ? attrNullNS : attrNull) : (typeof value === "function"
|
||||
? (name.local ? attrFunctionNS : attrFunction)
|
||||
: (name.local ? attrConstantNS : attrConstant)));
|
||||
};
|
||||
: (name.local ? attrConstantNS : attrConstant));
|
||||
}
|
||||
|
|
|
@ -1,61 +1,77 @@
|
|||
d3_selectionPrototype.classed = function(name, value) {
|
||||
var names = d3_collapse(name).split(" "),
|
||||
n = names.length,
|
||||
if (arguments.length < 2) {
|
||||
|
||||
// For classed(string), return true only if the first node has the specified
|
||||
// class or classes. Note that even if the browser supports DOMTokenList, it
|
||||
// probably doesn't support it on SVG elements (which can be animated).
|
||||
if (typeof name === "string") {
|
||||
var node = this.node(),
|
||||
n = (name = name.trim().split(/^|\s+/g)).length,
|
||||
i = -1;
|
||||
if (arguments.length > 1) {
|
||||
while (++i < n) d3_selection_classed.call(this, names[i], value);
|
||||
return this;
|
||||
if (value = node.classList) {
|
||||
while (++i < n) if (!value.contains(name[i])) return false;
|
||||
} else {
|
||||
while (++i < n) if (!d3_selection_classed.call(this, names[i])) return false;
|
||||
value = node.className;
|
||||
if (value.baseVal != null) value = value.baseVal;
|
||||
while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
function d3_selection_classed(name, value) {
|
||||
var re = new RegExp("(^|\\s+)" + d3.requote(name) + "(\\s+|$)", "g");
|
||||
|
||||
// If no value is specified, return the first value.
|
||||
if (arguments.length < 2) {
|
||||
var node = this.node();
|
||||
if (c = node.classList) return c.contains(name);
|
||||
var c = node.className;
|
||||
re.lastIndex = 0;
|
||||
return re.test(c.baseVal != null ? c.baseVal : c);
|
||||
// For classed(object), the object specifies the names of classes to add or
|
||||
// remove. The values may be functions that are evaluated for each element.
|
||||
for (value in name) this.each(d3_selection_classed(value, name[value]));
|
||||
return this;
|
||||
}
|
||||
|
||||
function classedAdd() {
|
||||
if (c = this.classList) return c.add(name);
|
||||
var c = this.className,
|
||||
// Otherwise, both a name and a value are specified, and are handled as below.
|
||||
return this.each(d3_selection_classed(name, value));
|
||||
};
|
||||
|
||||
function d3_selection_classedRe(name) {
|
||||
return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g");
|
||||
}
|
||||
|
||||
// Multiple class names are allowed (e.g., "foo bar").
|
||||
function d3_selection_classed(name, value) {
|
||||
name = name.trim().split(/\s+/).map(d3_selection_classedName);
|
||||
var n = name.length;
|
||||
|
||||
function classedConstant() {
|
||||
var i = -1;
|
||||
while (++i < n) name[i](this, value);
|
||||
}
|
||||
|
||||
// When the value is a function, the function is still evaluated only once per
|
||||
// element even if there are multiple class names.
|
||||
function classedFunction() {
|
||||
var i = -1, x = value.apply(this, arguments);
|
||||
while (++i < n) name[i](this, x);
|
||||
}
|
||||
|
||||
return typeof value === "function"
|
||||
? classedFunction
|
||||
: classedConstant;
|
||||
}
|
||||
|
||||
function d3_selection_classedName(name) {
|
||||
var re = d3_selection_classedRe(name);
|
||||
return function(node, value) {
|
||||
if (c = node.classList) return value ? c.add(name) : c.remove(name);
|
||||
var c = node.className,
|
||||
cb = c.baseVal != null,
|
||||
cv = cb ? c.baseVal : c;
|
||||
if (value) {
|
||||
re.lastIndex = 0;
|
||||
if (!re.test(cv)) {
|
||||
cv = d3_collapse(cv + " " + name);
|
||||
if (cb) c.baseVal = cv;
|
||||
else this.className = cv;
|
||||
else node.className = cv;
|
||||
}
|
||||
}
|
||||
|
||||
function classedRemove() {
|
||||
if (c = this.classList) return c.remove(name);
|
||||
var c = this.className,
|
||||
cb = c.baseVal != null,
|
||||
cv = cb ? c.baseVal : c;
|
||||
if (cv) {
|
||||
} else if (cv) {
|
||||
cv = d3_collapse(cv.replace(re, " "));
|
||||
if (cb) c.baseVal = cv;
|
||||
else this.className = cv;
|
||||
else node.className = cv;
|
||||
}
|
||||
}
|
||||
|
||||
function classedFunction() {
|
||||
(value.apply(this, arguments)
|
||||
? classedAdd
|
||||
: classedRemove).call(this);
|
||||
}
|
||||
|
||||
return this.each(typeof value === "function"
|
||||
? classedFunction : value
|
||||
? classedAdd
|
||||
: classedRemove);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,35 +1,48 @@
|
|||
// type can be namespaced, e.g., "click.foo"
|
||||
// listener can be null for removal
|
||||
d3_selectionPrototype.on = function(type, listener, capture) {
|
||||
if (arguments.length < 3) capture = false;
|
||||
var n = arguments.length;
|
||||
if (n < 3) {
|
||||
|
||||
// parse the type specifier
|
||||
// For on(object) or on(object, boolean), the object specifies the event
|
||||
// types and listeners to add or remove. The optional boolean specifies
|
||||
// whether the listener captures events.
|
||||
if (typeof type !== "string") {
|
||||
if (n < 2) listener = false;
|
||||
for (capture in type) this.each(d3_selection_on(capture, type[capture], listener));
|
||||
return this;
|
||||
}
|
||||
|
||||
// For on(string), return the listener for the first node.
|
||||
if (n < 2) return (n = this.node()["__on" + type]) && n._;
|
||||
|
||||
// For on(string, function), use the default capture.
|
||||
capture = false;
|
||||
}
|
||||
|
||||
// Otherwise, a type, listener and capture are specified, and handled as below.
|
||||
return this.each(d3_selection_on(type, listener, capture));
|
||||
};
|
||||
|
||||
function d3_selection_on(type, listener, capture) {
|
||||
var name = "__on" + type, i = type.indexOf(".");
|
||||
if (i > 0) type = type.substring(0, i);
|
||||
|
||||
// if called with only one argument, return the current listener
|
||||
if (arguments.length < 2) return (i = this.node()[name]) && i._;
|
||||
function onRemove() {
|
||||
var wrapper = this[name];
|
||||
if (wrapper) {
|
||||
this.removeEventListener(type, wrapper, wrapper.$);
|
||||
delete this[name];
|
||||
}
|
||||
}
|
||||
|
||||
// remove the old event listener, and add the new event listener
|
||||
return this.each(function() {
|
||||
function onAdd() {
|
||||
var node = this,
|
||||
args = arguments,
|
||||
o = node[name];
|
||||
args = arguments;
|
||||
|
||||
// remove the old listener, if any (using the previously-set capture)
|
||||
if (o) {
|
||||
node.removeEventListener(type, o, o.$);
|
||||
delete node[name];
|
||||
}
|
||||
onRemove.call(this);
|
||||
this.addEventListener(type, this[name] = wrapper, wrapper.$ = capture);
|
||||
wrapper._ = listener;
|
||||
|
||||
// add the new listener, if any (remembering the capture flag)
|
||||
if (listener) {
|
||||
node.addEventListener(type, node[name] = l, l.$ = capture);
|
||||
l._ = listener; // stash the unwrapped listener for get
|
||||
}
|
||||
|
||||
// wrapped event listener that propagates data changes
|
||||
function l(e) {
|
||||
function wrapper(e) {
|
||||
var o = d3.event; // Events can be reentrant (e.g., focus).
|
||||
d3.event = e;
|
||||
args[0] = node.__data__;
|
||||
|
@ -39,5 +52,7 @@ d3_selectionPrototype.on = function(type, listener, capture) {
|
|||
d3.event = o;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
return listener ? onAdd : onRemove;
|
||||
}
|
||||
|
|
|
@ -1,23 +1,41 @@
|
|||
d3_selectionPrototype.property = function(name, value) {
|
||||
if (arguments.length < 2) {
|
||||
|
||||
// If no value is specified, return the first value.
|
||||
if (arguments.length < 2) return this.node()[name];
|
||||
// For property(string), return the property value for the first node.
|
||||
if (typeof name === "string") return this.node()[name];
|
||||
|
||||
// For property(object), the object specifies the names and values of the
|
||||
// properties to set or remove. The values may be functions that are
|
||||
// evaluated for each element.
|
||||
for (value in name) this.each(d3_selection_property(value, name[value]));
|
||||
return this;
|
||||
}
|
||||
|
||||
// Otherwise, both a name and a value are specified, and are handled as below.
|
||||
return this.each(d3_selection_property(name, value));
|
||||
};
|
||||
|
||||
function d3_selection_property(name, value) {
|
||||
|
||||
// For property(name, null), remove the property with the specified name.
|
||||
function propertyNull() {
|
||||
delete this[name];
|
||||
}
|
||||
|
||||
// For property(name, string), set the property with the specified name.
|
||||
function propertyConstant() {
|
||||
this[name] = value;
|
||||
}
|
||||
|
||||
// For property(name, function), evaluate the function for each element, and
|
||||
// set or remove the property as appropriate.
|
||||
function propertyFunction() {
|
||||
var x = value.apply(this, arguments);
|
||||
if (x == null) delete this[name];
|
||||
else this[name] = x;
|
||||
}
|
||||
|
||||
return this.each(value == null
|
||||
return value == null
|
||||
? propertyNull : (typeof value === "function"
|
||||
? propertyFunction : propertyConstant));
|
||||
};
|
||||
? propertyFunction : propertyConstant);
|
||||
}
|
||||
|
|
|
@ -1,26 +1,55 @@
|
|||
d3_selectionPrototype.style = function(name, value, priority) {
|
||||
if (arguments.length < 3) priority = "";
|
||||
var n = arguments.length;
|
||||
if (n < 3) {
|
||||
|
||||
// If no value is specified, return the first value.
|
||||
if (arguments.length < 2) return window
|
||||
// For style(object) or style(object, string), the object specifies the
|
||||
// names and values of the attributes to set or remove. The values may be
|
||||
// functions that are evaluated for each element. The optional string
|
||||
// specifies the priority.
|
||||
if (typeof name !== "string") {
|
||||
if (n < 2) value = "";
|
||||
for (priority in name) this.each(d3_selection_style(priority, name[priority], value));
|
||||
return this;
|
||||
}
|
||||
|
||||
// For style(string), return the computed style value for the first node.
|
||||
if (n < 2) return window
|
||||
.getComputedStyle(this.node(), null)
|
||||
.getPropertyValue(name);
|
||||
|
||||
// For style(string, string) or style(string, function), use the default
|
||||
// priority. The priority is ignored for style(string, null).
|
||||
priority = "";
|
||||
}
|
||||
|
||||
// Otherwise, a name, value and priority are specified, and handled as below.
|
||||
return this.each(d3_selection_style(name, value, priority));
|
||||
};
|
||||
|
||||
function d3_selection_style(name, value, priority) {
|
||||
|
||||
// For style(name, null) or style(name, null, priority), remove the style
|
||||
// property with the specified name. The priority is ignored.
|
||||
function styleNull() {
|
||||
this.style.removeProperty(name);
|
||||
}
|
||||
|
||||
// For style(name, string) or style(name, string, priority), set the style
|
||||
// property with the specified name, using the specified priority.
|
||||
function styleConstant() {
|
||||
this.style.setProperty(name, value, priority);
|
||||
}
|
||||
|
||||
// For style(name, function) or style(name, function, priority), evaluate the
|
||||
// function for each element, and set or remove the style property as
|
||||
// appropriate. When setting, use the specified priority.
|
||||
function styleFunction() {
|
||||
var x = value.apply(this, arguments);
|
||||
if (x == null) this.style.removeProperty(name);
|
||||
else this.style.setProperty(name, x, priority);
|
||||
}
|
||||
|
||||
return this.each(value == null
|
||||
return value == null
|
||||
? styleNull : (typeof value === "function"
|
||||
? styleFunction : styleConstant));
|
||||
};
|
||||
? styleFunction : styleConstant);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,14 @@
|
|||
d3_transitionPrototype.attr = function(name, value) {
|
||||
return this.attrTween(name, d3.tween(value, d3_interpolateByName(name)));
|
||||
if (arguments.length < 2) {
|
||||
|
||||
// For attr(object), the object specifies the names and values of the
|
||||
// attributes to transition. The values may be functions that are
|
||||
// evaluated for each element.
|
||||
for (value in name) this.attrTween(value, d3_tweenByName(name[value], value));
|
||||
return this;
|
||||
}
|
||||
|
||||
return this.attrTween(name, d3_tweenByName(value, name));
|
||||
};
|
||||
|
||||
d3_transitionPrototype.attrTween = function(nameNS, tween) {
|
||||
|
|
|
@ -1,6 +1,24 @@
|
|||
d3_transitionPrototype.style = function(name, value, priority) {
|
||||
if (arguments.length < 3) priority = "";
|
||||
return this.styleTween(name, d3.tween(value, d3_interpolateByName(name)), priority);
|
||||
var n = arguments.length;
|
||||
if (n < 3) {
|
||||
|
||||
// For style(object) or style(object, string), the object specifies the
|
||||
// names and values of the attributes to set or remove. The values may be
|
||||
// functions that are evaluated for each element. The optional string
|
||||
// specifies the priority.
|
||||
if (typeof name !== "string") {
|
||||
if (n < 2) value = "";
|
||||
for (priority in name) this.styleTween(priority, d3_tweenByName(name[priority], priority), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
// For style(string, string) or style(string, function), use the default
|
||||
// priority. The priority is ignored for style(string, null).
|
||||
priority = "";
|
||||
}
|
||||
|
||||
// Otherwise, a name, value and priority are specified, and handled as below.
|
||||
return this.styleTween(name, d3_tweenByName(value, name), priority);
|
||||
};
|
||||
|
||||
d3_transitionPrototype.styleTween = function(name, tween, priority) {
|
||||
|
|
|
@ -21,3 +21,7 @@ var d3_tweenRemove = {};
|
|||
function d3_tweenNull(d, i, a) {
|
||||
return a != "" && d3_tweenRemove;
|
||||
}
|
||||
|
||||
function d3_tweenByName(b, name) {
|
||||
return d3.tween(b, d3_interpolateByName(name));
|
||||
}
|
||||
|
|
|
@ -38,6 +38,15 @@ suite.addBatch({
|
|||
body.data(["orange"]).attr("xlink:href", function(d, i) { return d + "-" + i; });
|
||||
assert.equal(document.body.getAttributeNS("http://www.w3.org/1999/xlink", "href"), "orange-0");
|
||||
},
|
||||
"sets attributes as a map of constants": function(body) {
|
||||
body.attr({bgcolor: "white", "xlink:href": "url.png"});
|
||||
assert.equal(document.body.getAttribute("bgcolor"), "white");
|
||||
assert.equal(document.body.getAttributeNS("http://www.w3.org/1999/xlink", "href"), "url.png");
|
||||
},
|
||||
"sets attributes as a map of functions": function(body) {
|
||||
body.data(["orange"]).attr({"xlink:href": function(d, i) { return d + "-" + i + ".png"; }});
|
||||
assert.equal(document.body.getAttributeNS("http://www.w3.org/1999/xlink", "href"), "orange-0.png");
|
||||
},
|
||||
"gets an attribute value": function(body) {
|
||||
document.body.setAttribute("bgcolor", "yellow");
|
||||
assert.equal(body.attr("bgcolor"), "yellow");
|
||||
|
@ -62,6 +71,20 @@ suite.addBatch({
|
|||
body.attr("xlink:href", "url").attr("xlink:href", function() { return null; });
|
||||
assert.equal(body.attr("xlink:href"), "");
|
||||
},
|
||||
"removes attributes as a map of null": function(body) {
|
||||
document.body.setAttribute("bgcolor", "white");
|
||||
document.body.setAttributeNS("http://www.w3.org/1999/xlink", "href", "foo.png");
|
||||
body.attr({bgcolor: null, "xlink:href": null});
|
||||
assert.equal(document.body.getAttribute("bgcolor"), "");
|
||||
assert.equal(document.body.getAttributeNS("http://www.w3.org/1999/xlink", "href"), "");
|
||||
},
|
||||
"removes attribtues as a map of functions that return null": function(body) {
|
||||
document.body.setAttribute("bgcolor", "white");
|
||||
document.body.setAttributeNS("http://www.w3.org/1999/xlink", "href", "foo.png");
|
||||
body.attr({bgcolor: function() {}, "xlink:href": function() {}});
|
||||
assert.equal(document.body.getAttribute("bgcolor"), "");
|
||||
assert.equal(document.body.getAttributeNS("http://www.w3.org/1999/xlink", "href"), "");
|
||||
},
|
||||
"returns the current selection": function(body) {
|
||||
assert.isTrue(body.attr("foo", "bar") === body);
|
||||
}
|
||||
|
|
|
@ -17,13 +17,6 @@ suite.addBatch({
|
|||
body.classed("bar", true);
|
||||
assert.equal(document.body.className, "foo bar");
|
||||
},
|
||||
"adds a missing class as a function": function(body) {
|
||||
body.attr("class", null);
|
||||
body.classed("foo", function() { return true; });
|
||||
assert.equal(document.body.className, "foo");
|
||||
body.classed("bar", function() { return true; });
|
||||
assert.equal(document.body.className, "foo bar");
|
||||
},
|
||||
"removes an existing class as false": function(body) {
|
||||
body.attr("class", "bar foo");
|
||||
body.classed("foo", false);
|
||||
|
@ -31,13 +24,6 @@ suite.addBatch({
|
|||
body.classed("bar", false);
|
||||
assert.equal(document.body.className, "");
|
||||
},
|
||||
"removes an existing class as a function": function(body) {
|
||||
body.attr("class", "bar foo");
|
||||
body.classed("foo", function() { return false; });
|
||||
assert.equal(document.body.className, "bar");
|
||||
body.classed("bar", function() { return false; });
|
||||
assert.equal(document.body.className, "");
|
||||
},
|
||||
"preserves an existing class as true": function(body) {
|
||||
body.attr("class", "bar foo");
|
||||
body.classed("foo", true);
|
||||
|
@ -45,13 +31,6 @@ suite.addBatch({
|
|||
body.classed("bar", true);
|
||||
assert.equal(document.body.className, "bar foo");
|
||||
},
|
||||
"preserves an existing class as a function": function(body) {
|
||||
body.attr("class", "bar foo");
|
||||
body.classed("foo", function() { return true; });
|
||||
assert.equal(document.body.className, "bar foo");
|
||||
body.classed("bar", function() { return true; });
|
||||
assert.equal(document.body.className, "bar foo");
|
||||
},
|
||||
"preserves a missing class as false": function(body) {
|
||||
body.attr("class", "baz");
|
||||
body.classed("foo", false);
|
||||
|
@ -60,14 +39,6 @@ suite.addBatch({
|
|||
body.classed("bar", false);
|
||||
assert.equal(document.body.className, "");
|
||||
},
|
||||
"preserves a missing class as a function": function(body) {
|
||||
body.attr("class", "baz");
|
||||
body.classed("foo", function() { return false; });
|
||||
assert.equal(document.body.className, "baz");
|
||||
body.attr("class", null);
|
||||
body.classed("bar", function() { return false; });
|
||||
assert.equal(document.body.className, "");
|
||||
},
|
||||
"gets an existing class": function(body) {
|
||||
body.attr("class", " foo\tbar baz");
|
||||
assert.isTrue(body.classed("foo"));
|
||||
|
@ -80,27 +51,101 @@ suite.addBatch({
|
|||
assert.isFalse(body.classed("bare"));
|
||||
assert.isFalse(body.classed("rbaz"));
|
||||
},
|
||||
"returns the current selection": function(body) {
|
||||
assert.isTrue(body.classed("foo", true) === body);
|
||||
"accepts a name with whitespace, collapsing it": function(body) {
|
||||
body.attr("class", null);
|
||||
body.classed(" foo\t", true);
|
||||
assert.equal(document.body.className, "foo");
|
||||
body.classed("\tfoo ", false);
|
||||
assert.equal(document.body.className, "");
|
||||
},
|
||||
"adds missing classes as true": function(body) {
|
||||
"accepts a name with multiple classes separated by whitespace": function(body) {
|
||||
body.attr("class", null);
|
||||
body.classed("foo bar", true);
|
||||
assert.equal(document.body.className, "foo bar");
|
||||
},
|
||||
"gets existing classes": function(body) {
|
||||
body.attr("class", " foo\tbar baz");
|
||||
assert.isTrue(body.classed("foo"));
|
||||
assert.isTrue(body.classed("foo bar"));
|
||||
assert.isTrue(body.classed("bar baz"));
|
||||
assert.isTrue(body.classed("foo bar baz"));
|
||||
},
|
||||
"does not get missing classes": function(body) {
|
||||
body.attr("class", " foo\tbar baz");
|
||||
assert.isFalse(body.classed("foob"));
|
||||
assert.isTrue(body.classed("bar foo"));
|
||||
assert.isFalse(body.classed("foo bar baz"));
|
||||
assert.isFalse(body.classed("foob bar"));
|
||||
assert.isFalse(body.classed("bar baz blah"));
|
||||
assert.isFalse(body.classed("foo bar baz moo"));
|
||||
body.classed("bar foo", false);
|
||||
assert.equal(document.body.className, "");
|
||||
},
|
||||
"accepts a silly class name with unsafe characters": function(body) {
|
||||
body.attr("class", null);
|
||||
body.classed("foo.bar", true);
|
||||
assert.equal(document.body.className, "foo.bar");
|
||||
assert.isTrue(body.classed("foo.bar"));
|
||||
assert.isFalse(body.classed("foo"));
|
||||
assert.isFalse(body.classed("bar"));
|
||||
body.classed("bar.foo", false);
|
||||
assert.equal(document.body.className, "foo.bar");
|
||||
body.classed("foo.bar", false);
|
||||
assert.equal(document.body.className, "");
|
||||
},
|
||||
"accepts a name with duplicate classes, ignoring them": function(body) {
|
||||
body.attr("class", null);
|
||||
body.classed(" foo\tfoo ", true);
|
||||
assert.equal(document.body.className, "foo");
|
||||
body.classed("\tfoo foo ", false);
|
||||
assert.equal(document.body.className, "");
|
||||
},
|
||||
"accepts a value function returning true or false": function(body) {
|
||||
body.attr("class", null);
|
||||
body.classed("foo", function() { return true; });
|
||||
assert.equal(document.body.className, "foo");
|
||||
body.classed("foo bar", function() { return true; });
|
||||
assert.equal(document.body.className, "foo bar");
|
||||
body.classed("foo", function() { return false; });
|
||||
assert.equal(document.body.className, "bar");
|
||||
},
|
||||
"accepts a name object containing true or false": function(body) {
|
||||
body.attr("class", null);
|
||||
body.classed({foo: true});
|
||||
assert.equal(document.body.className, "foo");
|
||||
body.classed({bar: true, foo: false});
|
||||
assert.equal(document.body.className, "bar");
|
||||
},
|
||||
"accepts a name object containing a function returning true or false": function(body) {
|
||||
body.attr("class", null);
|
||||
body.classed({foo: function() { return true; }});
|
||||
assert.equal(document.body.className, "foo");
|
||||
},
|
||||
"accepts a name object containing a mix of functions and non-functions": function(body) {
|
||||
body.attr("class", "foo");
|
||||
body.classed({foo: false, bar: function() { return true; }});
|
||||
assert.equal(document.body.className, "bar");
|
||||
},
|
||||
"the value may be truthy or falsey": function(body) {
|
||||
body.attr("class", "foo");
|
||||
body.classed({foo: null, bar: function() { return 1; }});
|
||||
assert.equal(document.body.className, "bar");
|
||||
},
|
||||
"keys in the name object may contain whitespace": function(body) {
|
||||
body.attr("class", null);
|
||||
body.classed({" foo\t": function() { return true; }});
|
||||
assert.equal(document.body.className, "foo");
|
||||
body.attr("class", null);
|
||||
},
|
||||
"keys in the name object may reference multiple classes": function(body) {
|
||||
body.attr("class", null);
|
||||
body.classed({"foo bar": function() { return true; }});
|
||||
assert.equal(document.body.className, "foo bar");
|
||||
body.attr("class", null);
|
||||
},
|
||||
"keys in the name object may contain duplicates": function(body) {
|
||||
body.attr("class", null);
|
||||
body.classed({"foo foo": function() { return true; }});
|
||||
assert.equal(document.body.className, "foo");
|
||||
body.attr("class", null);
|
||||
},
|
||||
"value functions are only evaluated once when used for multiple classes": function(body) {
|
||||
var count = 0;
|
||||
body.attr("class", null);
|
||||
body.classed({"foo bar": function() { return ++count; }});
|
||||
assert.equal(document.body.className, "foo bar");
|
||||
assert.equal(count, 1);
|
||||
},
|
||||
"returns the current selection": function(body) {
|
||||
assert.isTrue(body.classed("foo", true) === body);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -48,11 +48,21 @@ suite.addBatch({
|
|||
"observes the specified namespace": function(body) {
|
||||
var form = body.append("form"), foo = 0, bar = 0;
|
||||
form.on("submit.foo", function() { ++foo; });
|
||||
form.on("submit.bar", function() { ++bar; });
|
||||
form.on({"submit.bar": function() { ++bar; }});
|
||||
form.append("input").attr("type", "submit").node().click();
|
||||
assert.equal(foo, 1);
|
||||
assert.equal(bar, 1);
|
||||
},
|
||||
"can register listeners as a map": function(body) {
|
||||
var form = body.append("form"), count = 0, fail = 0;
|
||||
form.on({submit: function() { ++fail; }});
|
||||
form.on({submit: function() { ++count; }});
|
||||
form.append("input").attr("type", "submit").node().click();
|
||||
assert.equal(count, 1);
|
||||
assert.equal(fail, 0);
|
||||
form.on({submit: null});
|
||||
assert.isUndefined(form.on("submit"));
|
||||
},
|
||||
/* Not really sure how to test this one…
|
||||
"observes the specified capture flag": function(body) {
|
||||
},
|
||||
|
|
|
@ -22,6 +22,16 @@ suite.addBatch({
|
|||
body.property("bgcolor", function() { return "orange"; });
|
||||
assert.equal(document.body.bgcolor, "orange");
|
||||
},
|
||||
"sets properties as a map of constants": function(body) {
|
||||
body.property({bgcolor: "purple", opacity: .41});
|
||||
assert.equal(document.body.bgcolor, "purple");
|
||||
assert.equal(document.body.opacity, .41);
|
||||
},
|
||||
"sets properties as a map of functions": function(body) {
|
||||
body.data(["cyan"]).property({bgcolor: String, opacity: function(d, i) { return i; }});
|
||||
assert.equal(document.body.bgcolor, "cyan");
|
||||
assert.equal(document.body.opacity, 0);
|
||||
},
|
||||
"gets a property value": function(body) {
|
||||
document.body.bgcolor = "yellow";
|
||||
assert.equal(body.property("bgcolor"), "yellow");
|
||||
|
@ -34,6 +44,16 @@ suite.addBatch({
|
|||
body.property("bgcolor", "yellow").property("bgcolor", function() { return null });
|
||||
assert.isFalse("bgcolor" in document.body);
|
||||
},
|
||||
"removes properties as a map of nulls": function(body) {
|
||||
document.body.bgcolor = "red";
|
||||
body.property({bgcolor: null});
|
||||
assert.isFalse("bgcolor" in document.body);
|
||||
},
|
||||
"removes properties as a map of functions that return null": function(body) {
|
||||
document.body.bgcolor = "red";
|
||||
body.property({bgcolor: function() {}});
|
||||
assert.isFalse("bgcolor" in document.body);
|
||||
},
|
||||
"returns the current selection": function(body) {
|
||||
assert.isTrue(body.property("bgcolor", "yellow") === body);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,16 @@ suite.addBatch({
|
|||
body.style("background-color", function() { return "orange"; });
|
||||
assert.equal(document.body.style["background-color"], "orange");
|
||||
},
|
||||
"sets properties as a map of constants": function(body) {
|
||||
body.style({"background-color": "white", opacity: .42});
|
||||
assert.equal(document.body.style["background-color"], "white");
|
||||
assert.equal(document.body.style["opacity"], "0.42");
|
||||
},
|
||||
"sets properties as a map of functions": function(body) {
|
||||
body.data(["orange"]).style({"background-color": String, opacity: function(d, i) { return i; }});
|
||||
assert.equal(document.body.style["background-color"], "orange");
|
||||
assert.equal(document.body.style["opacity"], "0");
|
||||
},
|
||||
"gets a property value": function(body) {
|
||||
document.body.style.setProperty("background-color", "yellow", "");
|
||||
assert.equal(body.style("background-color"), "yellow");
|
||||
|
@ -29,6 +39,10 @@ suite.addBatch({
|
|||
"observes the specified priority": function(body) {
|
||||
body.style("background-color", "green", "important");
|
||||
assert.equal(document.body.style.getPropertyPriority("background-color"), "important");
|
||||
body.style({opacity: .52}, "important");
|
||||
assert.equal(document.body.style.getPropertyPriority("opacity"), "important");
|
||||
body.style({visibility: function() { return "visible"; }}, "important");
|
||||
assert.equal(document.body.style.getPropertyPriority("visibility"), "important");
|
||||
},
|
||||
"removes a property as null": function(body) {
|
||||
body.style("background-color", "green").style("background-color", null);
|
||||
|
@ -38,6 +52,16 @@ suite.addBatch({
|
|||
body.style("background-color", "green").style("background-color", function() { return null; });
|
||||
assert.equal(body.style("background-color"), "");
|
||||
},
|
||||
"removes properties as a map of nulls": function(body) {
|
||||
document.body.style.setProperty("background-color", "purple");
|
||||
body.style({"background-color": null});
|
||||
assert.equal(body.style("background-color"), "");
|
||||
},
|
||||
"removes properties as a map of functions that return null": function(body) {
|
||||
document.body.style.setProperty("background-color", "purple");
|
||||
body.style({"background-color": function() {}});
|
||||
assert.equal(body.style("background-color"), "");
|
||||
},
|
||||
"returns the current selection": function(body) {
|
||||
assert.isTrue(body.style("background-color", "green") === body);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче