diff --git a/src/traces/funnel/plot.js b/src/traces/funnel/plot.js index 31aa1e8f17e..9d10435090e 100644 --- a/src/traces/funnel/plot.js +++ b/src/traces/funnel/plot.js @@ -11,6 +11,7 @@ var d3 = require('d3'); var Lib = require('../../lib'); var Drawing = require('../../components/drawing'); +var BADNUM = require('../../constants/numerical').BADNUM; var barPlot = require('../bar/plot'); var clearMinTextSize = require('../bar/uniform_text').clearMinTextSize; @@ -66,7 +67,12 @@ function plotConnectorRegions(gd, plotinfo, cdModule, traceLayer) { var shape = ''; - if(x[3] !== undefined && y[3] !== undefined) { + if( + x[0] !== BADNUM && y[0] !== BADNUM && + x[1] !== BADNUM && y[1] !== BADNUM && + x[2] !== BADNUM && y[2] !== BADNUM && + x[3] !== BADNUM && y[3] !== BADNUM + ) { if(isHorizontal) { shape += 'M' + x[0] + ',' + y[1] + 'L' + x[2] + ',' + y[2] + 'H' + x[3] + 'L' + x[1] + ',' + y[1] + 'Z'; } else { @@ -74,6 +80,8 @@ function plotConnectorRegions(gd, plotinfo, cdModule, traceLayer) { } } + if(shape === '') shape = 'M0,0Z'; + Lib.ensureSingle(d3.select(this), 'path') .attr('d', shape) .call(Drawing.setClipUrl, plotinfo.layerClipId, gd); diff --git a/src/traces/waterfall/plot.js b/src/traces/waterfall/plot.js index 006bc9e93aa..065ff77bb0a 100644 --- a/src/traces/waterfall/plot.js +++ b/src/traces/waterfall/plot.js @@ -11,6 +11,7 @@ var d3 = require('d3'); var Lib = require('../../lib'); var Drawing = require('../../components/drawing'); +var BADNUM = require('../../constants/numerical').BADNUM; var barPlot = require('../bar/plot'); var clearMinTextSize = require('../bar/uniform_text').clearMinTextSize; @@ -66,31 +67,36 @@ function plotConnectors(gd, plotinfo, cdModule, traceLayer) { var shape = ''; - if(mode === 'spanning') { - if(!di.isSum && i > 0) { - if(isHorizontal) { - shape += 'M' + x[0] + ',' + y[1] + 'V' + y[0]; - } else { - shape += 'M' + x[1] + ',' + y[0] + 'H' + x[0]; + if( + x[0] !== BADNUM && y[0] !== BADNUM && + x[1] !== BADNUM && y[1] !== BADNUM + ) { + if(mode === 'spanning') { + if(!di.isSum && i > 0) { + if(isHorizontal) { + shape += 'M' + x[0] + ',' + y[1] + 'V' + y[0]; + } else { + shape += 'M' + x[1] + ',' + y[0] + 'H' + x[0]; + } } } - } - if(mode !== 'between') { - if(di.isSum || i < len - 1) { - if(isHorizontal) { - shape += 'M' + x[1] + ',' + y[0] + 'V' + y[1]; - } else { - shape += 'M' + x[0] + ',' + y[1] + 'H' + x[1]; + if(mode !== 'between') { + if(di.isSum || i < len - 1) { + if(isHorizontal) { + shape += 'M' + x[1] + ',' + y[0] + 'V' + y[1]; + } else { + shape += 'M' + x[0] + ',' + y[1] + 'H' + x[1]; + } } } - } - if(x[2] !== undefined && y[2] !== undefined) { - if(isHorizontal) { - shape += 'M' + x[1] + ',' + y[1] + 'V' + y[2]; - } else { - shape += 'M' + x[1] + ',' + y[1] + 'H' + x[2]; + if(x[2] !== BADNUM && y[2] !== BADNUM) { + if(isHorizontal) { + shape += 'M' + x[1] + ',' + y[1] + 'V' + y[2]; + } else { + shape += 'M' + x[1] + ',' + y[1] + 'H' + x[2]; + } } } diff --git a/test/jasmine/tests/bar_test.js b/test/jasmine/tests/bar_test.js index 39cc38d4d04..d7198a5ebf6 100644 --- a/test/jasmine/tests/bar_test.js +++ b/test/jasmine/tests/bar_test.js @@ -2932,7 +2932,7 @@ describe('bar tweening', function() { .then(done); }); - it('handle NaN positions on vertical bars', function(done) { + it('handle BADNUM positions on vertical bars', function(done) { var y1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; var y2 = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]; var mockCopy = { diff --git a/test/jasmine/tests/funnel_test.js b/test/jasmine/tests/funnel_test.js index 3a49a70e2c5..347c494a9ac 100644 --- a/test/jasmine/tests/funnel_test.js +++ b/test/jasmine/tests/funnel_test.js @@ -17,6 +17,7 @@ var rgb = color.rgb; var customAssertions = require('../assets/custom_assertions'); var assertHoverLabelContent = customAssertions.assertHoverLabelContent; var checkTextTemplate = require('../assets/check_texttemplate'); +var checkTransition = require('../assets/check_transitions'); var Fx = require('@src/components/fx'); var d3 = require('d3'); @@ -1033,6 +1034,54 @@ describe('A funnel plot', function() { .then(done); }); + it('handle BADNUM positions', function(done) { + var x1 = [11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]; + var x2 = x1; // no transition now + var mockCopy = { + data: [ + { + type: 'funnel', + y: [ + 0, + 1, + '', + 'NaN', + NaN, + Infinity, + -Infinity, + undefined, + null, + 9, + 10 + ], + x: x1 + } + ], + layout: { + width: 800, + height: 600 + } + }; + + var barTests = [ + [0, '.point path', 'attr', 'd', ['M245,4V34H395V4Z', 'M251,42V73H389V42Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M306,347V378H334V347Z', 'M313,386V416H327V386Z']] + ]; + + var connectorTests = [ + [0, '.regions path', 'attr', 'd', ['M245,34L251,42H389L395,34Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M306,378L313,386H327L334,378Z', 'M0,0Z']] + ]; + + var animateOpts = {data: [{x: x2}]}; + var transitionOpts = false; // use default + + checkTransition(gd, mockCopy, animateOpts, transitionOpts, barTests) + .then(function() { + return checkTransition(gd, mockCopy, animateOpts, transitionOpts, connectorTests); + }) + .catch(failTest) + .then(done); + }); + it('should be able to deal with transform that empty out the data coordinate arrays', function(done) { Plotly.plot(gd, { data: [{ diff --git a/test/jasmine/tests/waterfall_test.js b/test/jasmine/tests/waterfall_test.js index c9877e655c7..6e20e81a9d4 100644 --- a/test/jasmine/tests/waterfall_test.js +++ b/test/jasmine/tests/waterfall_test.js @@ -17,6 +17,7 @@ var rgb = color.rgb; var customAssertions = require('../assets/custom_assertions'); var assertHoverLabelContent = customAssertions.assertHoverLabelContent; var checkTextTemplate = require('../assets/check_texttemplate'); +var checkTransition = require('../assets/check_transitions'); var Fx = require('@src/components/fx'); var d3 = require('d3'); @@ -977,6 +978,54 @@ describe('A waterfall plot', function() { .then(done); }); + it('handle BADNUM positions', function(done) { + var y1 = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; + var y2 = y1; // no transition now + var mockCopy = { + data: [ + { + type: 'waterfall', + x: [ + 0, + 1, + '', + 'NaN', + NaN, + Infinity, + -Infinity, + undefined, + null, + 9, + 10 + ], + y: y1 + } + ], + layout: { + width: 400, + height: 300 + } + }; + + var barTests = [ + [0, '.point path', 'attr', 'd', ['M2,121V109H20V121Z', 'M24,111V98H41V111Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M199,28V15H216V28Z', 'M220,17V5H238V17Z']] + ]; + + var connectorTests = [ + [0, '.line path', 'attr', 'd', ['M20,110H24', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M0,0Z', 'M216,16H220', 'M0,0Z']] + ]; + + var animateOpts = {data: [{y: y2}]}; + var transitionOpts = false; // use default + + checkTransition(gd, mockCopy, animateOpts, transitionOpts, barTests) + .then(function() { + return checkTransition(gd, mockCopy, animateOpts, transitionOpts, connectorTests); + }) + .catch(failTest) + .then(done); + }); + it('should be able to deal with transform that empty out the data coordinate arrays', function(done) { Plotly.plot(gd, { data: [{