Commit df18a153 authored by Mike Bostock's avatar Mike Bostock
Browse files

Merge branch 'fix-axis-no-ticks' into 3.2.4

parents 09b020f6 58187894
......@@ -7051,6 +7051,10 @@ d3 = function() {
scale.quantiles = function() {
return thresholds;
};
scale.invertExtent = function(y) {
y = range.indexOf(y);
return y < 0 ? [ NaN, NaN ] : [ y > 0 ? thresholds[y - 1] : domain[0], y < thresholds.length ? thresholds[y] : domain[domain.length - 1] ];
};
scale.copy = function() {
return d3_scale_quantile(domain, range);
};
......@@ -7080,14 +7084,14 @@ d3 = function() {
range = x;
return rescale();
};
scale.copy = function() {
return d3_scale_quantize(x0, x1, range);
};
scale.invertExtent = function(y) {
y = range.indexOf(y);
y = y < 0 ? NaN : y / kx + x0;
return [ y, y + 1 / kx ];
};
scale.copy = function() {
return d3_scale_quantize(x0, x1, range);
};
return rescale();
}
d3.scale.threshold = function() {
......@@ -7801,19 +7805,19 @@ d3 = function() {
break;
}
}
if (scale.ticks) {
if (scale.rangeBand) {
var dx = scale1.rangeBand() / 2, x = function(d) {
return scale1(d) + dx;
};
tickEnter.call(tickTransform, x);
tickUpdate.call(tickTransform, x);
} else {
tickEnter.call(tickTransform, scale0);
tickUpdate.call(tickTransform, scale1);
tickExit.call(tickTransform, scale1);
subtickEnter.call(tickTransform, scale0);
subtickUpdate.call(tickTransform, scale1);
subtickExit.call(tickTransform, scale1);
} else {
var dx = scale1.rangeBand() / 2, x = function(d) {
return scale1(d) + dx;
};
tickEnter.call(tickTransform, x);
tickUpdate.call(tickTransform, x);
}
});
}
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -38,6 +38,14 @@ function d3_scale_quantile(domain, range) {
return thresholds;
};
scale.invertExtent = function(y) {
y = range.indexOf(y);
return y < 0 ? [NaN, NaN] : [
y > 0 ? thresholds[y - 1] : domain[0],
y < thresholds.length ? thresholds[y] : domain[domain.length - 1]
];
};
scale.copy = function() {
return d3_scale_quantile(domain, range); // copy on write!
};
......
......@@ -30,15 +30,15 @@ function d3_scale_quantize(x0, x1, range) {
return rescale();
};
scale.copy = function() {
return d3_scale_quantize(x0, x1, range); // copy on write
};
scale.invertExtent = function(y) {
y = range.indexOf(y);
y = y < 0 ? NaN : y / kx + x0;
return [y, y + 1 / kx];
};
scale.copy = function() {
return d3_scale_quantize(x0, x1, range); // copy on write
};
return rescale();
}
......@@ -108,10 +108,20 @@ d3.svg.axis = function() {
}
}
// For ordinal scales:
// - any entering ticks are undefined in the old scale
// - any exiting ticks are undefined in the new scale
// Therefore, we only need to transition updating ticks.
if (scale.rangeBand) {
var dx = scale1.rangeBand() / 2, x = function(d) { return scale1(d) + dx; };
tickEnter.call(tickTransform, x);
tickUpdate.call(tickTransform, x);
}
// For quantitative scales:
// - enter new ticks from the old scale
// - exit old ticks to the new scale
if (scale.ticks) {
else {
tickEnter.call(tickTransform, scale0);
tickUpdate.call(tickTransform, scale1);
tickExit.call(tickTransform, scale1);
......@@ -119,16 +129,6 @@ d3.svg.axis = function() {
subtickUpdate.call(tickTransform, scale1);
subtickExit.call(tickTransform, scale1);
}
// For ordinal scales:
// - any entering ticks are undefined in the old scale
// - any exiting ticks are undefined in the new scale
// Therefore, we only need to transition updating ticks.
else {
var dx = scale1.rangeBand() / 2, x = function(d) { return scale1(d) + dx; };
tickEnter.call(tickTransform, x);
tickUpdate.call(tickTransform, x);
}
});
}
......
......@@ -57,6 +57,33 @@ suite.addBatch({
"returns undefined if the input value is NaN": function(quantile) {
var x = quantile().domain([3, 6, 7, 8, 8, 10, 13, 15, 16, 20]).range([0, 1, 2, 3]);
assert.isUndefined(x(NaN));
},
"invertExtent": {
"maps a value in the range to a domain extent": function(quantile) {
var x = quantile().domain([3, 6, 7, 8, 8, 10, 13, 15, 16, 20]).range([0, 1, 2, 3]);
assert.deepEqual(x.invertExtent(0), [3, 7.25]);
assert.deepEqual(x.invertExtent(1), [7.25, 9]);
assert.deepEqual(x.invertExtent(2), [9, 14.5]);
assert.deepEqual(x.invertExtent(3), [14.5, 20]);
},
"allows arbitrary range values": function(quantile) {
var a = {}, b = {}, x = quantile().domain([3, 6, 7, 8, 8, 10, 13, 15, 16, 20]).range([a, b]);
assert.deepEqual(x.invertExtent(a), [3, 9]);
assert.deepEqual(x.invertExtent(b), [9, 20]);
},
"returns [NaN, NaN] when the given value is not in the range": function(quantile) {
var x = quantile().domain([3, 6, 7, 8, 8, 10, 13, 15, 16, 20]);
assert.ok(x.invertExtent(-1).every(isNaN));
assert.ok(x.invertExtent(.5).every(isNaN));
assert.ok(x.invertExtent(2).every(isNaN));
assert.ok(x.invertExtent('a').every(isNaN));
},
"returns the first match if duplicate values exist in the range": function(quantile) {
var x = quantile().domain([3, 6, 7, 8, 8, 10, 13, 15, 16, 20]).range([0, 1, 2, 0]);
assert.deepEqual(x.invertExtent(0), [3, 7.25]);
assert.deepEqual(x.invertExtent(1), [7.25, 9]);
assert.deepEqual(x.invertExtent(2), [9, 14.5]);
}
}
}
});
......
......@@ -11,32 +11,67 @@ suite.addBatch({
"scale": {
"defaults to a linear scale": function(d3) {
var a = d3.svg.axis(), x = a.scale();
var a = d3.svg.axis(),
x = a.scale();
assert.deepEqual(x.domain(), [0, 1]);
assert.deepEqual(x.range(), [0, 1]);
assert.equal(x(0.5), 0.5);
},
"can be defined as a scale object": function(d3) {
var x = _.scale.linear(), a = d3.svg.axis().scale(x);
var x = _.scale.linear(),
a = d3.svg.axis().scale(x);
assert.equal(a.scale(), x);
},
"can be a polylinear scale": function(d3) {
var a = d3.svg.axis().scale(_.scale.linear().domain([0, 1, 10]).range([2, 20, 200])),
g = d3.select("body").html("").append("svg:g").call(a),
var x = _.scale.linear().domain([0, 1, 10]).range([2, 20, 200]),
a = d3.svg.axis().scale(x),
g = d3.select("body").html("").append("g").call(a),
path = g.selectAll("path");
assert.inDelta(g.selectAll(".tick").data(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 1e-4);
assert.inDelta(g.selectAll(".tick").data().map(x), [2, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200], 1e-4);
assert.equal(path.attr("d"), "M2,6V0H200V6");
},
"can be an ordinal scale": function(d3) {
var a = d3.svg.axis().scale(_.scale.ordinal().domain(["A", "B", "C"]).rangeBands([10, 90])),
g = d3.select("body").html("").append("svg:g").call(a),
var x = _.scale.ordinal().domain(["A", "B", "C"]).rangeBands([10, 90]),
a = d3.svg.axis().scale(x),
g = d3.select("body").html("").append("g").call(a),
path = g.selectAll("path");
assert.deepEqual(g.selectAll(".tick").data(), ["A", "B", "C"]);
assert.inDelta(g.selectAll(".tick").data().map(x), [10, 36.6667, 63.3333], 1e-4);
assert.equal(path.attr("d"), "M10,6V0H90V6");
},
"can be an ordinal scale with explicit range": function(d3) {
var a = d3.svg.axis().scale(_.scale.ordinal().domain(["A", "B", "C"]).range([10, 50, 90])),
g = d3.select("body").html("").append("svg:g").call(a),
var x = _.scale.ordinal().domain(["A", "B", "C"]).range([10, 50, 90]),
a = d3.svg.axis().scale(x),
g = d3.select("body").html("").append("g").call(a),
path = g.selectAll("path");
assert.deepEqual(g.selectAll(".tick").data(), ["A", "B", "C"]);
assert.deepEqual(g.selectAll(".tick").data().map(x), [10, 50, 90]);
assert.equal(path.attr("d"), "M10,6V0H90V6");
},
"can be a quantize scale": function(d3) {
var x = _.scale.quantize().domain([0, 10]).range([10, 50, 90]),
a = d3.svg.axis().scale(x),
g = d3.select("body").html("").append("g").call(a);
assert.inDelta(g.selectAll(".tick").data(), [0, 10], 1e-4);
assert.deepEqual(g.selectAll(".tick").data().map(x), [10, 90]);
assert.equal(g.select("path").attr("d"), "M10,6V0H90V6");
},
"can be a quantile scale": function(d3) {
var x = _.scale.quantile().domain([6, 3, 5, 2, 7, 8, 4, 0, 1, 9]).range([10, 50, 90]),
a = d3.svg.axis().scale(x),
g = d3.select("body").html("").append("g").call(a);
assert.inDelta(g.selectAll(".tick").data(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 1e-4);
assert.inDelta(g.selectAll(".tick").data().map(x), [10, 10, 10, 50, 50, 50, 90, 90, 90, 90], 1e-4);
assert.equal(g.select("path").attr("d"), "M10,6V0H90V6");
},
"can be a threshold scale": function(d3) {
var x = _.scale.threshold().domain([4, 5, 6]).range([0, 30, 60, 90]),
a = d3.svg.axis().scale(x),
g = d3.select("body").html("").append("g").call(a);
assert.inDelta(g.selectAll(".tick").data(), [4, 5, 6], 1e-4);
assert.inDelta(g.selectAll(".tick").data().map(x), [30, 60, 90], 1e-4);
assert.equal(g.select("path").attr("d"), "M0,6V0H90V6");
}
},
......@@ -55,7 +90,7 @@ suite.addBatch({
},
"supports top orientation": function(d3) {
var a = d3.svg.axis().orient("top"),
g = d3.select("body").html("").append("svg:g").call(a),
g = d3.select("body").html("").append("g").call(a),
tick = g.select("g:nth-child(3)"),
text = tick.select("text"),
line = tick.select("line"),
......@@ -70,7 +105,7 @@ suite.addBatch({
},
"supports right orientation": function(d3) {
var a = d3.svg.axis().orient("right"),
g = d3.select("body").html("").append("svg:g").call(a),
g = d3.select("body").html("").append("g").call(a),
tick = g.select("g:nth-child(3)"),
text = tick.select("text"),
line = tick.select("line"),
......@@ -85,7 +120,7 @@ suite.addBatch({
},
"supports bottom orientation": function(d3) {
var a = d3.svg.axis().orient("bottom"),
g = d3.select("body").html("").append("svg:g").call(a),
g = d3.select("body").html("").append("g").call(a),
tick = g.select("g:nth-child(3)"),
text = tick.select("text"),
line = tick.select("line"),
......@@ -100,7 +135,7 @@ suite.addBatch({
},
"supports left orientation": function(d3) {
var a = d3.svg.axis().orient("left"),
g = d3.select("body").html("").append("svg:g").call(a),
g = d3.select("body").html("").append("g").call(a),
tick = g.select("g:nth-child(3)"),
text = tick.select("text"),
line = tick.select("line"),
......@@ -130,13 +165,13 @@ suite.addBatch({
},
"affects the generated domain path": function(d3) {
var a = d3.svg.axis().tickSize(3),
g = d3.select("body").html("").append("svg:g").call(a),
g = d3.select("body").html("").append("g").call(a),
path = g.select("path.domain");
assert.equal(path.attr("d"), "M0,3V0H1V3");
},
"affects the generated tick lines": function(d3) {
var a = d3.svg.axis().tickSize(3),
g = d3.select("body").html("").append("svg:g").call(a),
g = d3.select("body").html("").append("g").call(a),
line = g.selectAll("g line");
line.each(function() {
assert.equal(d3.select(this).attr("y2"), 3);
......@@ -144,7 +179,7 @@ suite.addBatch({
},
"if negative, labels are placed on the opposite end": function(d3) {
var a = d3.svg.axis().tickSize(-80),
g = d3.select("body").html("").append("svg:g").call(a),
g = d3.select("body").html("").append("g").call(a),
line = g.selectAll("g line"),
text = g.selectAll("g text");
line.each(function() {
......@@ -156,13 +191,13 @@ suite.addBatch({
},
"with two arguments, specifies end tick size": function(d3) {
var a = d3.svg.axis().tickSize(6, 3),
g = d3.select("body").html("").append("svg:g").call(a),
g = d3.select("body").html("").append("g").call(a),
path = g.selectAll("path");
assert.equal(path.attr("d"), "M0,3V0H1V3");
},
"with three arguments, specifies end and minor tick sizes": function(d3) {
var a = d3.svg.axis().tickSubdivide(3).tickSize(6, 3, 9),
g = d3.select("body").html("").append("svg:g").call(a),
g = d3.select("body").html("").append("g").call(a),
path = g.selectAll("path"),
line = g.select(".minor");
assert.equal(path.attr("d"), "M0,9V0H1V9");
......@@ -185,7 +220,7 @@ suite.addBatch({
},
"affects the generated tick labels": function(d3) {
var a = d3.svg.axis().tickSize(2).tickPadding(7),
g = d3.select("body").html("").append("svg:g").call(a),
g = d3.select("body").html("").append("g").call(a),
text = g.selectAll("g text");
text.each(function() {
assert.equal(d3.select(this).attr("y"), 9);
......@@ -206,7 +241,7 @@ suite.addBatch({
},
"passes any arguments to the scale's ticks function": function(d3) {
var x = _.scale.linear(), b = {}, a = d3.svg.axis().ticks(b, "%").scale(x), aa = [],
g = d3.select("body").html("").append("svg:g");
g = d3.select("body").html("").append("g");
x.ticks = function() { aa.push(arguments); return [42]; };
g.call(a);
assert.equal(aa.length, 1);
......@@ -218,7 +253,7 @@ suite.addBatch({
var b = {},
x = _.scale.linear(),
a = d3.svg.axis().scale(x).ticks(b, "%"),
g = d3.select("body").html("").append("svg:g"),
g = d3.select("body").html("").append("g"),
aa = [];
x.tickFormat = function() {
......@@ -234,14 +269,14 @@ suite.addBatch({
},
"affects the generated ticks": function(d3) {
var a = d3.svg.axis().ticks(20, "%"),
g = d3.select("body").html("").append("svg:g").call(a),
g = d3.select("body").html("").append("g").call(a),
t = g.selectAll("g");
assert.equal(t[0].length, 21);
assert.equal(t[0][0].textContent, "0%");
},
"only substitutes precision if not specified": function(d3) {
var a = d3.svg.axis().ticks(20, ".5%"),
g = d3.select("body").html("").append("svg:g").call(a),
g = d3.select("body").html("").append("g").call(a),
t = g.selectAll("g");
assert.equal(t[0].length, 21);
assert.equal(t[0][0].textContent, "0.00000%");
......@@ -267,7 +302,7 @@ suite.addBatch({
"does not change the arguments passed to the scale's tickFormat function": function(d3) {
var x = _.scale.linear(),
a = d3.svg.axis().scale(x).ticks(10).tickValues([1, 2, 3]),
g = d3.select("body").html("").append("svg:g"),
g = d3.select("body").html("").append("g"),
aa = [];
x.tickFormat = function() {
......@@ -282,7 +317,7 @@ suite.addBatch({
},
"affects the generated ticks": function(d3) {
var a = d3.svg.axis().ticks(20),
g = d3.select("body").html("").append("svg:g").call(a),
g = d3.select("body").html("").append("g").call(a),
t = g.selectAll("g");
assert.equal(t[0].length, 21);
}
......@@ -298,12 +333,12 @@ suite.addBatch({
assert.strictEqual(a.tickSubdivide(), 1);
},
"does not generate minor ticks when zero": function(d3) {
var g = d3.select("body").html("").append("svg:g").call(d3.svg.axis());
var g = d3.select("body").html("").append("g").call(d3.svg.axis());
assert.isTrue(g.selectAll(".minor").empty());
},
"affects the generated minor ticks": function(d3) {
var a = d3.svg.axis().tickSubdivide(3),
g = d3.select("body").html("").append("svg:g").call(a),
g = d3.select("body").html("").append("g").call(a),
t = g.selectAll("line.tick.minor");
assert.equal(t[0].length, 30);
assert.equal(t[0][1].getAttribute("transform"), "translate(0.05,0)");
......@@ -317,7 +352,7 @@ suite.addBatch({
},
"when null, uses the scale's tick format": function(d3) {
var x = _.scale.linear(), a = d3.svg.axis().scale(x),
g = d3.select("body").html("").append("svg:g");
g = d3.select("body").html("").append("g");
x.tickFormat = function() {
return function(d) {
......@@ -331,19 +366,19 @@ suite.addBatch({
},
"affects the generated tick labels": function(d3) {
var a = d3.svg.axis().tickFormat(d3.format("+.2%")),
g = d3.select("body").html("").append("svg:g").call(a),
g = d3.select("body").html("").append("g").call(a),
t = g.selectAll("g text");
assert.equal(t.text(), "+0.00%");
},
"can be set to a constant": function(d3) {
var a = d3.svg.axis().tickFormat("I'm a tick!"),
g = d3.select("body").html("").append("svg:g").call(a),
g = d3.select("body").html("").append("g").call(a),
t = g.selectAll("g text");
assert.equal(t.text(), "I'm a tick!");
},
"can be set to a falsey constant": function(d3) {
var a = d3.svg.axis().tickFormat(""),
g = d3.select("body").html("").append("svg:g").call(a),
g = d3.select("body").html("").append("g").call(a),
t = g.selectAll("g text");
assert.equal(t.text(), "");
}
......@@ -352,7 +387,7 @@ suite.addBatch({
"enter": {
"generates a new domain path": function(d3) {
var a = d3.svg.axis(),
g = d3.select("body").html("").append("svg:g").call(a),
g = d3.select("body").html("").append("g").call(a),
path = g.selectAll("path.domain");
assert.equal(path[0].length, 1);
assert.equal(path.attr("d"), "M0,6V0H1V6");
......@@ -360,7 +395,7 @@ suite.addBatch({
},
"generates new tick marks with labels": function(d3) {
var a = d3.svg.axis(),
g = d3.select("body").html("").append("svg:g").call(a),
g = d3.select("body").html("").append("g").call(a),
x = _.scale.linear(),
tick = g.selectAll("g"),
ticks = x.ticks(10),
......@@ -378,7 +413,7 @@ suite.addBatch({
"update": {
"updates the domain path": function(d3) {
var a = d3.svg.axis(),
g = d3.select("body").html("").append("svg:g").call(a);
g = d3.select("body").html("").append("g").call(a);
a.scale().domain([0, 2]).range([1, 2]);
a.tickSize(3);
g.call(a);
......@@ -389,7 +424,7 @@ suite.addBatch({
},
"enters, exits and updates tick marks": function(d3) {
var a = d3.svg.axis(),
g = d3.select("body").html("").append("svg:g").call(a),
g = d3.select("body").html("").append("g").call(a),
x = d3.scale.linear().domain([1, 1.5]);
a.scale().domain(x.domain());
a.tickSize(3).tickPadding(9);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment