diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index 9804f2d50ff..faa1887dd59 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -2362,6 +2362,7 @@ function diffData(gd, oldFullData, newFullData, immutable) { for(i = 0; i < oldFullData.length; i++) { trace = newFullData[i]._fullInput; + if(Plots.hasMakesDataTransform(trace)) trace = newFullData[i]; if(seenUIDs[trace.uid]) continue; seenUIDs[trace.uid] = 1; diff --git a/src/plots/plots.js b/src/plots/plots.js index 908289fa72c..046429402fb 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -1188,17 +1188,20 @@ plots.supplyTraceDefaults = function(traceIn, traceOut, colorIndex, layout, trac * parameters? If so, we should still keep going with supplyDefaults * even if the trace is invisible, which may just be because it has no data yet. */ -function hasMakesDataTransform(traceIn) { - var transformsIn = traceIn.transforms; - if(Array.isArray(transformsIn) && transformsIn.length) { - for(var i = 0; i < transformsIn.length; i++) { - var _module = transformsRegistry[transformsIn[i].type]; +function hasMakesDataTransform(trace) { + var transforms = trace.transforms; + if(Array.isArray(transforms) && transforms.length) { + for(var i = 0; i < transforms.length; i++) { + var ti = transforms[i]; + var _module = ti._module || transformsRegistry[ti.type]; if(_module && _module.makesData) return true; } } return false; } +plots.hasMakesDataTransform = hasMakesDataTransform; + plots.supplyTransformDefaults = function(traceIn, traceOut, layout) { // For now we only allow transforms on 1D traces, ie those that specify a _length. // If we were to implement 2D transforms, we'd need to have each transform diff --git a/test/jasmine/tests/transform_multi_test.js b/test/jasmine/tests/transform_multi_test.js index f834135c0eb..0a8226df907 100644 --- a/test/jasmine/tests/transform_multi_test.js +++ b/test/jasmine/tests/transform_multi_test.js @@ -207,6 +207,7 @@ describe('general transforms:', function() { describe('user-defined transforms:', function() { 'use strict'; + afterEach(destroyGraphDiv); it('should pass correctly arguments to transform methods', function() { var transformIn = { type: 'fake' }; @@ -283,7 +284,7 @@ describe('user-defined transforms:', function() { expect(calledSupplyLayoutDefaults).toBe(1); }); - it('handles `makesData` transforms when the incoming trace has no data', function() { + it('handles `makesData` transforms when the incoming trace has no data', function(done) { var transformIn = {type: 'linemaker', x0: 3, y0: 2, x1: 5, y1: 10, n: 3}; var dataIn = [{transforms: [transformIn], mode: 'lines+markers'}]; var fullData = []; @@ -317,7 +318,7 @@ describe('user-defined transforms:', function() { expect(trace.marker).toBeUndefined(); // just put the input trace back in here, it'll get coerced again after the transform - var traceOut = Lib.extendFlat(trace._input, {x: x, y: y}); + var traceOut = Lib.extendFlat({}, trace._input, {x: x, y: y}); return [traceOut]; } @@ -325,7 +326,6 @@ describe('user-defined transforms:', function() { Plotly.register(lineMakerModule); Plots.supplyDataDefaults(dataIn, fullData, layout, fullLayout); - delete Plots.transformsRegistry.linemaker; expect(fullData.length).toBe(1); var traceOut = fullData[0]; @@ -336,6 +336,34 @@ describe('user-defined transforms:', function() { expect(traceOut.mode).toBe('lines+markers'); expect(traceOut.line).toBeDefined(); expect(traceOut.marker).toBeDefined(); + + // make sure plot is really drawn, and changes in the base trace + // are propagated correctly on an edit (either restyle or react) + var gd = createGraphDiv(); + function getLineWidth() { + var line = gd.querySelector('.js-line'); + return line && parseFloat(line.style.strokeWidth); + } + Plotly.newPlot(gd, [{transforms: [transformIn], mode: 'lines+markers'}], layout) + .then(function() { + expect(getLineWidth()).toBe(2); + + return Plotly.restyle(gd, 'line.width', 7); + }) + .then(function() { + expect(getLineWidth()).toBe(7); + + var data2 = [{transforms: [transformIn], mode: 'lines+markers', line: {width: 4}}]; + return Plotly.react(gd, data2, layout); + }) + .then(function() { + expect(getLineWidth()).toBe(4); + }) + .catch(failTest) + .then(function() { + delete Plots.transformsRegistry.linemaker; + }) + .then(done); }); });