diff --git a/src/plots/plots.js b/src/plots/plots.js index 3d51e37fa20..a1d853d40ef 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -1921,8 +1921,9 @@ plots.transition = function(gd, data, layout, traces, frameOpts, transitionOpts) plots.doCalcdata = function(gd, traces) { var axList = Plotly.Axes.list(gd), fullData = gd._fullData, - fullLayout = gd._fullLayout, - i, j; + fullLayout = gd._fullLayout; + + var trace, _module, i, j; // XXX: Is this correct? Needs a closer look so that *some* traces can be recomputed without // *all* needing doCalcdata: @@ -1951,46 +1952,57 @@ plots.doCalcdata = function(gd, traces) { axList[i]._categories = axList[i]._initialCategories.slice(); } + // If traces were specified and this trace was not included, + // then transfer it over from the old calcdata: for(i = 0; i < fullData.length; i++) { - // If traces were specified and this trace was not included, then transfer it over from - // the old calcdata: if(Array.isArray(traces) && traces.indexOf(i) === -1) { calcdata[i] = oldCalcdata[i]; continue; } + } - var trace = fullData[i], - cd = []; - - // If traces were specified and this trace was not included, then transfer it over from - // the old calcdata: - if(Array.isArray(traces) && traces.indexOf(i) === -1) { - calcdata[i] = oldCalcdata[i]; - continue; - } + var hasCalcTransform = false; - var _module; - if(trace.visible === true) { + // transform loop + for(i = 0; i < fullData.length; i++) { + trace = fullData[i]; - // call calcTransform method if any - if(trace.transforms) { + if(trace.visible === true && trace.transforms) { + _module = trace._module; - // we need one round of trace module calc before - // the calc transform to 'fill in' the categories list - // used for example in the data-to-coordinate method - _module = trace._module; - if(_module && _module.calc) _module.calc(gd, trace); + // we need one round of trace module calc before + // the calc transform to 'fill in' the categories list + // used for example in the data-to-coordinate method + if(_module && _module.calc) _module.calc(gd, trace); - for(j = 0; j < trace.transforms.length; j++) { - var transform = trace.transforms[j]; + for(j = 0; j < trace.transforms.length; j++) { + var transform = trace.transforms[j]; - _module = transformsRegistry[transform.type]; - if(_module && _module.calcTransform) { - _module.calcTransform(gd, trace, transform); - } + _module = transformsRegistry[transform.type]; + if(_module && _module.calcTransform) { + hasCalcTransform = true; + _module.calcTransform(gd, trace, transform); } } + } + } + + // clear stuff that should recomputed in 'regular' loop + if(hasCalcTransform) { + for(i = 0; i < axList.length; i++) { + axList[i]._min = []; + axList[i]._max = []; + axList[i]._categories = []; + } + } + + // 'regular' loop + for(i = 0; i < fullData.length; i++) { + var cd = []; + trace = fullData[i]; + + if(trace.visible === true) { _module = trace._module; if(_module && _module.calc) cd = _module.calc(gd, trace); } diff --git a/test/jasmine/tests/transform_filter_test.js b/test/jasmine/tests/transform_filter_test.js index 09ddd936810..9bbea9678c6 100644 --- a/test/jasmine/tests/transform_filter_test.js +++ b/test/jasmine/tests/transform_filter_test.js @@ -8,6 +8,7 @@ var createGraphDiv = require('../assets/create_graph_div'); var destroyGraphDiv = require('../assets/destroy_graph_div'); var assertDims = require('../assets/assert_dims'); var assertStyle = require('../assets/assert_style'); +var customMatchers = require('../assets/custom_matchers'); describe('filter transforms defaults:', function() { @@ -844,6 +845,10 @@ describe('filter transforms calc:', function() { describe('filter transforms interactions', function() { 'use strict'; + beforeAll(function() { + jasmine.addMatchers(customMatchers); + }); + var mockData0 = [{ x: [-2, -1, -2, 0, 1, 2, 3], y: [1, 2, 3, 1, 2, 3, 1], @@ -900,6 +905,9 @@ describe('filter transforms interactions', function() { assertUid(gd); assertStyle(dims, ['rgb(255, 0, 0)'], [1]); + expect(gd._fullLayout.xaxis.range).toBeCloseToArray([0.87, 3.13]); + expect(gd._fullLayout.yaxis.range).toBeCloseToArray([0.85, 3.15]); + return Plotly.restyle(gd, 'marker.color', 'blue'); }).then(function() { expect(gd._fullData[0].marker.color).toEqual('blue'); @@ -917,6 +925,9 @@ describe('filter transforms interactions', function() { assertUid(gd); assertStyle([1], ['rgb(255, 0, 0)'], [1]); + expect(gd._fullLayout.xaxis.range).toBeCloseToArray([2, 4]); + expect(gd._fullLayout.yaxis.range).toBeCloseToArray([0, 2]); + done(); }); }); @@ -1016,4 +1027,48 @@ describe('filter transforms interactions', function() { }) .then(done); }); + + it('should update axis categories', function(done) { + var data = [{ + type: 'bar', + x: ['a', 'b', 'c', 'd', 'e', 'f', 'g'], + y: [1, 10, 100, 25, 50, -25, 100], + transforms: [{ + type: 'filter', + operation: '<', + value: 10, + target: [1, 10, 100, 25, 50, -25, 100] + }] + }]; + + var gd = createGraphDiv(); + + Plotly.plot(gd, data).then(function() { + expect(gd._fullLayout.xaxis._categories).toEqual(['a', 'f']); + expect(gd._fullLayout.yaxis._categories).toEqual([]); + + return Plotly.addTraces(gd, [{ + type: 'bar', + x: ['h', 'i'], + y: [2, 1], + transforms: [{ + type: 'filter', + operation: '=', + value: 'i' + }] + }]); + }) + .then(function() { + expect(gd._fullLayout.xaxis._categories).toEqual(['a', 'f', 'i']); + expect(gd._fullLayout.yaxis._categories).toEqual([]); + + return Plotly.deleteTraces(gd, [0]); + }) + .then(function() { + expect(gd._fullLayout.xaxis._categories).toEqual(['i']); + expect(gd._fullLayout.yaxis._categories).toEqual([]); + }) + .then(done); + }); + });