Skip to content

Commit f1cda60

Browse files
committed
add bar stack visible -> autorange test & move 'b' init to setPositions
- Bar.setPositions mutate 'b' in bar trace calcdate, we need to reinit 'b' during setPositions so that we can skip calc on visible edits
1 parent d0699c0 commit f1cda60

File tree

3 files changed

+96
-54
lines changed

3 files changed

+96
-54
lines changed

src/traces/bar/calc.js

+2-43
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,8 @@
66
* LICENSE file in the root directory of this source tree.
77
*/
88

9-
109
'use strict';
1110

12-
var isNumeric = require('fast-isnumeric');
13-
var isArrayOrTypedArray = require('../../lib').isArrayOrTypedArray;
14-
1511
var Axes = require('../../plots/cartesian/axes');
1612
var hasColorscale = require('../../components/colorscale/has_colorscale');
1713
var colorscaleCalc = require('../../components/colorscale/calc');
@@ -27,24 +23,14 @@ module.exports = function calc(gd, trace) {
2723
var xa = Axes.getFromId(gd, trace.xaxis || 'x'),
2824
ya = Axes.getFromId(gd, trace.yaxis || 'y'),
2925
orientation = trace.orientation || ((trace.x && !trace.y) ? 'h' : 'v'),
30-
sa, pos, size, i, scalendar;
26+
pos, size, i;
3127

3228
if(orientation === 'h') {
33-
sa = xa;
3429
size = xa.makeCalcdata(trace, 'x');
3530
pos = ya.makeCalcdata(trace, 'y');
36-
37-
// not sure if it really makes sense to have dates for bar size data...
38-
// ideally if we want to make gantt charts or something we'd treat
39-
// the actual size (trace.x or y) as time delta but base as absolute
40-
// time. But included here for completeness.
41-
scalendar = trace.xcalendar;
42-
}
43-
else {
44-
sa = ya;
31+
} else {
4532
size = ya.makeCalcdata(trace, 'y');
4633
pos = xa.makeCalcdata(trace, 'x');
47-
scalendar = trace.ycalendar;
4834
}
4935

5036
// create the "calculated data" to plot
@@ -60,33 +46,6 @@ module.exports = function calc(gd, trace) {
6046
}
6147
}
6248

63-
// set base
64-
var base = trace.base,
65-
b;
66-
67-
if(isArrayOrTypedArray(base)) {
68-
for(i = 0; i < Math.min(base.length, cd.length); i++) {
69-
b = sa.d2c(base[i], 0, scalendar);
70-
if(isNumeric(b)) {
71-
cd[i].b = +b;
72-
cd[i].hasB = 1;
73-
}
74-
else cd[i].b = 0;
75-
}
76-
for(; i < cd.length; i++) {
77-
cd[i].b = 0;
78-
}
79-
}
80-
else {
81-
b = sa.d2c(base, 0, scalendar);
82-
var hasBase = isNumeric(b);
83-
b = hasBase ? b : 0;
84-
for(i = 0; i < cd.length; i++) {
85-
cd[i].b = b;
86-
if(hasBase) cd[i].hasB = 1;
87-
}
88-
}
89-
9049
// auto-z and autocolorscale if applicable
9150
if(hasColorscale(trace, 'marker')) {
9251
colorscaleCalc(trace, trace.marker.color, 'marker', 'c');

src/traces/bar/set_positions.js

+41
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ function setGroupPositions(gd, pa, sa, calcTraces) {
6565
included,
6666
i, calcTrace, fullTrace;
6767

68+
initBase(gd, pa, sa, calcTraces);
69+
6870
if(overlay) {
6971
setGroupPositionsInOverlayMode(gd, pa, sa, calcTraces);
7072
}
@@ -110,6 +112,45 @@ function setGroupPositions(gd, pa, sa, calcTraces) {
110112
collectExtents(calcTraces, pa);
111113
}
112114

115+
function initBase(gd, pa, sa, calcTraces) {
116+
var i, j;
117+
118+
for(i = 0; i < calcTraces.length; i++) {
119+
var cd = calcTraces[i];
120+
var trace = cd[0].trace;
121+
var base = trace.base;
122+
var b;
123+
124+
// not sure if it really makes sense to have dates for bar size data...
125+
// ideally if we want to make gantt charts or something we'd treat
126+
// the actual size (trace.x or y) as time delta but base as absolute
127+
// time. But included here for completeness.
128+
var scalendar = trace.orientation === 'h' ? trace.xcalendar : trace.ycalendar;
129+
130+
if(isArrayOrTypedArray(base)) {
131+
for(j = 0; j < Math.min(base.length, cd.length); j++) {
132+
b = sa.d2c(base[j], 0, scalendar);
133+
if(isNumeric(b)) {
134+
cd[j].b = +b;
135+
cd[j].hasB = 1;
136+
}
137+
else cd[j].b = 0;
138+
}
139+
for(; j < cd.length; j++) {
140+
cd[j].b = 0;
141+
}
142+
} else {
143+
b = sa.d2c(base, 0, scalendar);
144+
var hasBase = isNumeric(b);
145+
b = hasBase ? b : 0;
146+
for(j = 0; j < cd.length; j++) {
147+
cd[j].b = b;
148+
if(hasBase) cd[j].hasB = 1;
149+
}
150+
}
151+
}
152+
}
153+
113154

114155
function setGroupPositionsInOverlayMode(gd, pa, sa, calcTraces) {
115156
var barnorm = gd._fullLayout.barnorm,

test/jasmine/tests/bar_test.js

+53-11
Original file line numberDiff line numberDiff line change
@@ -1331,22 +1331,34 @@ describe('A bar plot', function() {
13311331
.catch(failTest)
13321332
.then(done);
13331333
});
1334+
});
1335+
1336+
describe('bar visibility toggling:', function() {
1337+
var gd;
1338+
1339+
beforeEach(function() {
1340+
gd = createGraphDiv();
1341+
});
1342+
1343+
afterEach(destroyGraphDiv);
1344+
1345+
function _assert(msg, xrng, yrng, calls) {
1346+
var fullLayout = gd._fullLayout;
1347+
expect(fullLayout.xaxis.range).toBeCloseToArray(xrng, 2, msg + ' xrng');
1348+
expect(fullLayout.yaxis.range).toBeCloseToArray(yrng, 2, msg + ' yrng');
13341349

1335-
it('should update axis range according to visible edits', function(done) {
1350+
var setPositions = gd._fullData[0]._module.setPositions;
1351+
expect(setPositions).toHaveBeenCalledTimes(calls);
1352+
setPositions.calls.reset();
1353+
}
1354+
1355+
it('should have the correct edit type', function() {
13361356
var schema = Plotly.PlotSchema.get();
13371357
expect(schema.traces.bar.attributes.visible.editType)
13381358
.toBe('plot', 'visible editType');
1359+
});
13391360

1340-
function _assert(msg, xrng, yrng, calls) {
1341-
var fullLayout = gd._fullLayout;
1342-
expect(fullLayout.xaxis.range).toBeCloseToArray(xrng, 2, msg + ' xrng');
1343-
expect(fullLayout.yaxis.range).toBeCloseToArray(yrng, 2, msg + ' yrng');
1344-
1345-
var setPositions = gd._fullData[0]._module.setPositions;
1346-
expect(setPositions).toHaveBeenCalledTimes(calls);
1347-
setPositions.calls.reset();
1348-
}
1349-
1361+
it('should update axis range according to visible edits (group case)', function(done) {
13501362
Plotly.plot(gd, [
13511363
{type: 'bar', x: [1, 2, 3], y: [1, 2, 1]},
13521364
{type: 'bar', x: [1, 2, 3], y: [-1, -2, -1]}
@@ -1375,6 +1387,36 @@ describe('A bar plot', function() {
13751387
.catch(failTest)
13761388
.then(done);
13771389
});
1390+
1391+
it('should update axis range according to visible edits (stack case)', function(done) {
1392+
Plotly.plot(gd, [
1393+
{type: 'bar', x: [1, 2, 3], y: [1, 2, 1]},
1394+
{type: 'bar', x: [1, 2, 3], y: [2, 3, 2]}
1395+
], {barmode: 'stack'})
1396+
.then(function() {
1397+
spyOn(gd._fullData[0]._module, 'setPositions').and.callThrough();
1398+
1399+
_assert('base', [0.5, 3.5], [0, 5.263], 0);
1400+
return Plotly.restyle(gd, 'visible', false, [1]);
1401+
})
1402+
.then(function() {
1403+
_assert('visible [true,false]', [0.5, 3.5], [0, 2.105], 1);
1404+
return Plotly.restyle(gd, 'visible', false, [0]);
1405+
})
1406+
.then(function() {
1407+
_assert('both invisible', [0.5, 3.5], [0, 2.105], 0);
1408+
return Plotly.restyle(gd, 'visible', true, [1]);
1409+
})
1410+
.then(function() {
1411+
_assert('visible [false,true]', [0.5, 3.5], [0, 3.157], 1);
1412+
return Plotly.restyle(gd, 'visible', true);
1413+
})
1414+
.then(function() {
1415+
_assert('back to both visible', [0.5, 3.5], [0, 5.263], 1);
1416+
})
1417+
.catch(failTest)
1418+
.then(done);
1419+
});
13781420
});
13791421

13801422
describe('bar hover', function() {

0 commit comments

Comments
 (0)