Skip to content

Commit fc6dfe1

Browse files
authored
Merge pull request #1260 from plotly/transform-calc-loops
Ensure axis autorange is computed after transform operations
2 parents 43d3710 + c9044fa commit fc6dfe1

File tree

2 files changed

+95
-28
lines changed

2 files changed

+95
-28
lines changed

src/plots/plots.js

+40-28
Original file line numberDiff line numberDiff line change
@@ -1921,8 +1921,9 @@ plots.transition = function(gd, data, layout, traces, frameOpts, transitionOpts)
19211921
plots.doCalcdata = function(gd, traces) {
19221922
var axList = Plotly.Axes.list(gd),
19231923
fullData = gd._fullData,
1924-
fullLayout = gd._fullLayout,
1925-
i, j;
1924+
fullLayout = gd._fullLayout;
1925+
1926+
var trace, _module, i, j;
19261927

19271928
// XXX: Is this correct? Needs a closer look so that *some* traces can be recomputed without
19281929
// *all* needing doCalcdata:
@@ -1951,46 +1952,57 @@ plots.doCalcdata = function(gd, traces) {
19511952
axList[i]._categories = axList[i]._initialCategories.slice();
19521953
}
19531954

1955+
// If traces were specified and this trace was not included,
1956+
// then transfer it over from the old calcdata:
19541957
for(i = 0; i < fullData.length; i++) {
1955-
// If traces were specified and this trace was not included, then transfer it over from
1956-
// the old calcdata:
19571958
if(Array.isArray(traces) && traces.indexOf(i) === -1) {
19581959
calcdata[i] = oldCalcdata[i];
19591960
continue;
19601961
}
1962+
}
19611963

1962-
var trace = fullData[i],
1963-
cd = [];
1964-
1965-
// If traces were specified and this trace was not included, then transfer it over from
1966-
// the old calcdata:
1967-
if(Array.isArray(traces) && traces.indexOf(i) === -1) {
1968-
calcdata[i] = oldCalcdata[i];
1969-
continue;
1970-
}
1964+
var hasCalcTransform = false;
19711965

1972-
var _module;
1973-
if(trace.visible === true) {
1966+
// transform loop
1967+
for(i = 0; i < fullData.length; i++) {
1968+
trace = fullData[i];
19741969

1975-
// call calcTransform method if any
1976-
if(trace.transforms) {
1970+
if(trace.visible === true && trace.transforms) {
1971+
_module = trace._module;
19771972

1978-
// we need one round of trace module calc before
1979-
// the calc transform to 'fill in' the categories list
1980-
// used for example in the data-to-coordinate method
1981-
_module = trace._module;
1982-
if(_module && _module.calc) _module.calc(gd, trace);
1973+
// we need one round of trace module calc before
1974+
// the calc transform to 'fill in' the categories list
1975+
// used for example in the data-to-coordinate method
1976+
if(_module && _module.calc) _module.calc(gd, trace);
19831977

1984-
for(j = 0; j < trace.transforms.length; j++) {
1985-
var transform = trace.transforms[j];
1978+
for(j = 0; j < trace.transforms.length; j++) {
1979+
var transform = trace.transforms[j];
19861980

1987-
_module = transformsRegistry[transform.type];
1988-
if(_module && _module.calcTransform) {
1989-
_module.calcTransform(gd, trace, transform);
1990-
}
1981+
_module = transformsRegistry[transform.type];
1982+
if(_module && _module.calcTransform) {
1983+
hasCalcTransform = true;
1984+
_module.calcTransform(gd, trace, transform);
19911985
}
19921986
}
1987+
}
1988+
}
1989+
1990+
// clear stuff that should recomputed in 'regular' loop
1991+
if(hasCalcTransform) {
1992+
for(i = 0; i < axList.length; i++) {
1993+
axList[i]._min = [];
1994+
axList[i]._max = [];
1995+
axList[i]._categories = [];
1996+
}
1997+
}
1998+
1999+
// 'regular' loop
2000+
for(i = 0; i < fullData.length; i++) {
2001+
var cd = [];
19932002

2003+
trace = fullData[i];
2004+
2005+
if(trace.visible === true) {
19942006
_module = trace._module;
19952007
if(_module && _module.calc) cd = _module.calc(gd, trace);
19962008
}

test/jasmine/tests/transform_filter_test.js

+55
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ var createGraphDiv = require('../assets/create_graph_div');
88
var destroyGraphDiv = require('../assets/destroy_graph_div');
99
var assertDims = require('../assets/assert_dims');
1010
var assertStyle = require('../assets/assert_style');
11+
var customMatchers = require('../assets/custom_matchers');
1112

1213
describe('filter transforms defaults:', function() {
1314

@@ -844,6 +845,10 @@ describe('filter transforms calc:', function() {
844845
describe('filter transforms interactions', function() {
845846
'use strict';
846847

848+
beforeAll(function() {
849+
jasmine.addMatchers(customMatchers);
850+
});
851+
847852
var mockData0 = [{
848853
x: [-2, -1, -2, 0, 1, 2, 3],
849854
y: [1, 2, 3, 1, 2, 3, 1],
@@ -900,6 +905,9 @@ describe('filter transforms interactions', function() {
900905
assertUid(gd);
901906
assertStyle(dims, ['rgb(255, 0, 0)'], [1]);
902907

908+
expect(gd._fullLayout.xaxis.range).toBeCloseToArray([0.87, 3.13]);
909+
expect(gd._fullLayout.yaxis.range).toBeCloseToArray([0.85, 3.15]);
910+
903911
return Plotly.restyle(gd, 'marker.color', 'blue');
904912
}).then(function() {
905913
expect(gd._fullData[0].marker.color).toEqual('blue');
@@ -917,6 +925,9 @@ describe('filter transforms interactions', function() {
917925
assertUid(gd);
918926
assertStyle([1], ['rgb(255, 0, 0)'], [1]);
919927

928+
expect(gd._fullLayout.xaxis.range).toBeCloseToArray([2, 4]);
929+
expect(gd._fullLayout.yaxis.range).toBeCloseToArray([0, 2]);
930+
920931
done();
921932
});
922933
});
@@ -1016,4 +1027,48 @@ describe('filter transforms interactions', function() {
10161027
})
10171028
.then(done);
10181029
});
1030+
1031+
it('should update axis categories', function(done) {
1032+
var data = [{
1033+
type: 'bar',
1034+
x: ['a', 'b', 'c', 'd', 'e', 'f', 'g'],
1035+
y: [1, 10, 100, 25, 50, -25, 100],
1036+
transforms: [{
1037+
type: 'filter',
1038+
operation: '<',
1039+
value: 10,
1040+
target: [1, 10, 100, 25, 50, -25, 100]
1041+
}]
1042+
}];
1043+
1044+
var gd = createGraphDiv();
1045+
1046+
Plotly.plot(gd, data).then(function() {
1047+
expect(gd._fullLayout.xaxis._categories).toEqual(['a', 'f']);
1048+
expect(gd._fullLayout.yaxis._categories).toEqual([]);
1049+
1050+
return Plotly.addTraces(gd, [{
1051+
type: 'bar',
1052+
x: ['h', 'i'],
1053+
y: [2, 1],
1054+
transforms: [{
1055+
type: 'filter',
1056+
operation: '=',
1057+
value: 'i'
1058+
}]
1059+
}]);
1060+
})
1061+
.then(function() {
1062+
expect(gd._fullLayout.xaxis._categories).toEqual(['a', 'f', 'i']);
1063+
expect(gd._fullLayout.yaxis._categories).toEqual([]);
1064+
1065+
return Plotly.deleteTraces(gd, [0]);
1066+
})
1067+
.then(function() {
1068+
expect(gd._fullLayout.xaxis._categories).toEqual(['i']);
1069+
expect(gd._fullLayout.yaxis._categories).toEqual([]);
1070+
})
1071+
.then(done);
1072+
});
1073+
10191074
});

0 commit comments

Comments
 (0)