From 6aa17d5207bd95380fa8875af4b1c54c300f01c0 Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Tue, 30 Apr 2024 14:45:08 +0200 Subject: [PATCH 01/21] shape.layer = "between": Add support for xref/yref paper Previously, it fell back to "below" for paper refs --- src/components/shapes/draw.js | 4 +- src/plot_api/plot_api.js | 7 +- src/plot_api/subroutines.js | 3 +- src/plots/cartesian/index.js | 124 +++++++++++------- .../mocks/shapes_layer_below_traces.json | 21 ++- 5 files changed, 104 insertions(+), 55 deletions(-) diff --git a/src/components/shapes/draw.js b/src/components/shapes/draw.js index 417c884c3f2..784fa1360bc 100644 --- a/src/components/shapes/draw.js +++ b/src/components/shapes/draw.js @@ -93,10 +93,10 @@ function drawOne(gd, index) { if(options.layer === 'above') { drawShape(gd._fullLayout._shapeUpperLayer); + } else if(options.layer === 'between') { + drawShape(gd._fullLayout.shapeLayerBetween); } else if(options.xref === 'paper' || options.yref === 'paper') { drawShape(gd._fullLayout._shapeLowerLayer); - } else if(options.layer === 'between') { - drawShape(plotinfo.shapelayerBetween); } else { if(plotinfo._hadPlotinfo) { var mainPlot = plotinfo.mainplotinfo || plotinfo; diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index a104e88bb11..d72f5c751fa 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -3782,8 +3782,11 @@ function makePlotFramework(gd) { .classed('shapelayer', true); // single cartesian layer for the whole plot - fullLayout._cartesianlayer = fullLayout._paper.append('g').classed('cartesianlayer', true); - + fullLayout._cartesianlayerBelow = fullLayout._paper.append('g').classed('cartesianlayer-below', true); + var layerBetween = fullLayout._paper.append('g').classed('layer-between', true); + fullLayout.imageLayerBetween = layerBetween.append('g').classed('imagelayer', true); + fullLayout.shapeLayerBetween = layerBetween.append('g').classed('shapelayer', true); + fullLayout._cartesianlayerAbove = fullLayout._paper.append('g').classed('cartesianlayer-above', true); // single polar layer for the whole plot fullLayout._polarlayer = fullLayout._paper.append('g').classed('polarlayer', true); diff --git a/src/plot_api/subroutines.js b/src/plot_api/subroutines.js index 487decf74f9..586bdf9b6da 100644 --- a/src/plot_api/subroutines.js +++ b/src/plot_api/subroutines.js @@ -133,8 +133,7 @@ function lsInner(gd) { } else { var xDomain = plotinfo.xaxis.domain; var yDomain = plotinfo.yaxis.domain; - var plotgroup = plotinfo.plotgroup; - + var plotgroup = plotinfo.plotgroup[0]; if(overlappingDomain(xDomain, yDomain, lowerDomains)) { var pgNode = plotgroup.node(); var plotgroupBg = plotinfo.bg = Lib.ensureSingle(plotgroup, 'rect', 'bg'); diff --git a/src/plots/cartesian/index.js b/src/plots/cartesian/index.js index 2a52d2628e0..722cf95ba82 100644 --- a/src/plots/cartesian/index.js +++ b/src/plots/cartesian/index.js @@ -353,8 +353,8 @@ exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) if(hadCartesian && !hasCartesian) { // if we've gotten rid of all cartesian traces, remove all the subplot svg items - - purgeSubplotLayers(oldFullLayout._cartesianlayer.selectAll('.subplot'), oldFullLayout); + purgeSubplotLayers(oldFullLayout._cartesianlayerBelow.selectAll('.subplot'), oldFullLayout); + purgeSubplotLayers(oldFullLayout._cartesianlayerAbove.selectAll('.subplot'), oldFullLayout); oldFullLayout._defs.selectAll('.axesclip').remove(); delete oldFullLayout._axisConstraintGroups; delete oldFullLayout._axisMatchGroups; @@ -365,7 +365,8 @@ exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) var oldSubplotId = oldSubplotList.cartesian[i]; if(!newPlots[oldSubplotId]) { var selector = '.' + oldSubplotId + ',.' + oldSubplotId + '-x,.' + oldSubplotId + '-y'; - oldFullLayout._cartesianlayer.selectAll(selector).remove(); + oldFullLayout._cartesianlayerAbove.selectAll(selector).remove(); + oldFullLayout._cartesianlayerBelow.selectAll(selector).remove(); removeSubplotExtras(oldSubplotId, oldFullLayout); } } @@ -376,23 +377,39 @@ exports.drawFramework = function(gd) { var fullLayout = gd._fullLayout; var subplotData = makeSubplotData(gd); - var subplotLayers = fullLayout._cartesianlayer.selectAll('.subplot') + var subplotLayersAbove = fullLayout._cartesianlayerAbove.selectAll('.subplot') .data(subplotData, String); + subplotLayersAbove.enter().append('g') + .attr('class', function(d) { return 'subplot ' + d[0] + '-above'; }); + subplotLayersAbove.order(); + subplotLayersAbove.exit() + .call(purgeSubplotLayers, fullLayout); - subplotLayers.enter().append('g') - .attr('class', function(d) { return 'subplot ' + d[0]; }); - - subplotLayers.order(); - - subplotLayers.exit() + var subplotLayersBelow = fullLayout._cartesianlayerBelow.selectAll('.subplot') + .data(subplotData, String); + subplotLayersBelow.enter().append('g') + .attr('class', function(d) { return 'subplot ' + d[0] + '-below'; }); + subplotLayersBelow.order(); + subplotLayersBelow.exit() .call(purgeSubplotLayers, fullLayout); - subplotLayers.each(function(d) { + subplotLayersBelow.each(function(d) { var id = d[0]; var plotinfo = fullLayout._plots[id]; - plotinfo.plotgroup = d3.select(this); - makeSubplotLayer(gd, plotinfo); + plotinfo.plotgroup = [d3.select(this)]; + makeSubplotLayerBelow(gd, plotinfo); + + // make separate drag layers for each subplot, + // but append them to paper rather than the plot groups, + // so they end up on top of the rest + plotinfo.draglayer = ensureSingle(fullLayout._draggers, 'g', id); + }); + subplotLayersAbove.each(function(d) { + var id = d[0]; + var plotinfo = fullLayout._plots[id]; + plotinfo.plotgroup = plotinfo.plotgroup.concat([d3.select(this)]); + makeSubplotLayerAbove(gd, plotinfo); // make separate drag layers for each subplot, // but append them to paper rather than the plot groups, @@ -402,7 +419,8 @@ exports.drawFramework = function(gd) { }; exports.rangePlot = function(gd, plotinfo, cdSubplot) { - makeSubplotLayer(gd, plotinfo); + makeSubplotLayerBelow(gd, plotinfo); + makeSubplotLayerAbove(gd, plotinfo); plotOne(gd, plotinfo, cdSubplot); Plots.style(gd); }; @@ -468,8 +486,50 @@ function makeSubplotData(gd) { return subplotData; } -function makeSubplotLayer(gd, plotinfo) { - var plotgroup = plotinfo.plotgroup; +function makeSubplotLayerBelow(gd, plotinfo) { + var plotgroup = plotinfo.plotgroup[0]; + var hasOnlyLargeSploms = gd._fullLayout._hasOnlyLargeSploms; + + if(!plotinfo.mainplot) { + var backLayer = ensureSingle(plotgroup, 'g', 'layer-subplot'); + plotinfo.shapelayer = ensureSingle(backLayer, 'g', 'shapelayer'); + plotinfo.imagelayer = ensureSingle(backLayer, 'g', 'imagelayer'); + + plotinfo.minorGridlayer = ensureSingle(plotgroup, 'g', 'minor-gridlayer'); + plotinfo.gridlayer = ensureSingle(plotgroup, 'g', 'gridlayer'); + plotinfo.zerolinelayer = ensureSingle(plotgroup, 'g', 'zerolinelayer'); + } else { + var mainplotinfo = plotinfo.mainplotinfo; + + // now make the components of overlaid subplots + // overlays don't have backgrounds, and append all + // their other components to the corresponding + // extra groups of their main plots. + + plotinfo.minorGridlayer = mainplotinfo.minorGridlayer; + plotinfo.gridlayer = mainplotinfo.gridlayer; + plotinfo.zerolinelayer = mainplotinfo.zerolinelayer; + } + + // common attributes for all subplots, overlays or not + + if(!hasOnlyLargeSploms) { + ensureSingleAndAddDatum(plotinfo.minorGridlayer, 'g', plotinfo.xaxis._id); + ensureSingleAndAddDatum(plotinfo.minorGridlayer, 'g', plotinfo.yaxis._id); + plotinfo.minorGridlayer.selectAll('g') + .map(function(d) { return d[0]; }) + .sort(axisIds.idSort); + + ensureSingleAndAddDatum(plotinfo.gridlayer, 'g', plotinfo.xaxis._id); + ensureSingleAndAddDatum(plotinfo.gridlayer, 'g', plotinfo.yaxis._id); + plotinfo.gridlayer.selectAll('g') + .map(function(d) { return d[0]; }) + .sort(axisIds.idSort); + } +} + +function makeSubplotLayerAbove(gd, plotinfo) { + var plotgroup = plotinfo.plotgroup[1]; var id = plotinfo.id; var xLayer = constants.layerValue2layerClass[plotinfo.xaxis.layer]; var yLayer = constants.layerValue2layerClass[plotinfo.yaxis.layer]; @@ -487,18 +547,6 @@ function makeSubplotLayer(gd, plotinfo) { plotinfo.xaxislayer = ensureSingle(plotgroup, 'g', 'xaxislayer-above'); plotinfo.yaxislayer = ensureSingle(plotgroup, 'g', 'yaxislayer-above'); } else { - var backLayer = ensureSingle(plotgroup, 'g', 'layer-subplot'); - plotinfo.shapelayer = ensureSingle(backLayer, 'g', 'shapelayer'); - plotinfo.imagelayer = ensureSingle(backLayer, 'g', 'imagelayer'); - - plotinfo.minorGridlayer = ensureSingle(plotgroup, 'g', 'minor-gridlayer'); - plotinfo.gridlayer = ensureSingle(plotgroup, 'g', 'gridlayer'); - plotinfo.zerolinelayer = ensureSingle(plotgroup, 'g', 'zerolinelayer'); - - var betweenLayer = ensureSingle(plotgroup, 'g', 'layer-between'); - plotinfo.shapelayerBetween = ensureSingle(betweenLayer, 'g', 'shapelayer'); - plotinfo.imagelayerBetween = ensureSingle(betweenLayer, 'g', 'imagelayer'); - ensureSingle(plotgroup, 'path', 'xlines-below'); ensureSingle(plotgroup, 'path', 'ylines-below'); plotinfo.overlinesBelow = ensureSingle(plotgroup, 'g', 'overlines-below'); @@ -526,7 +574,7 @@ function makeSubplotLayer(gd, plotinfo) { } } else { var mainplotinfo = plotinfo.mainplotinfo; - var mainplotgroup = mainplotinfo.plotgroup; + var mainplotgroup = mainplotinfo.plotgroup[1]; var xId = id + '-x'; var yId = id + '-y'; @@ -535,10 +583,6 @@ function makeSubplotLayer(gd, plotinfo) { // their other components to the corresponding // extra groups of their main plots. - plotinfo.minorGridlayer = mainplotinfo.minorGridlayer; - plotinfo.gridlayer = mainplotinfo.gridlayer; - plotinfo.zerolinelayer = mainplotinfo.zerolinelayer; - ensureSingle(mainplotinfo.overlinesBelow, 'path', xId); ensureSingle(mainplotinfo.overlinesBelow, 'path', yId); ensureSingle(mainplotinfo.overaxesBelow, 'g', xId); @@ -560,20 +604,6 @@ function makeSubplotLayer(gd, plotinfo) { // common attributes for all subplots, overlays or not - if(!hasOnlyLargeSploms) { - ensureSingleAndAddDatum(plotinfo.minorGridlayer, 'g', plotinfo.xaxis._id); - ensureSingleAndAddDatum(plotinfo.minorGridlayer, 'g', plotinfo.yaxis._id); - plotinfo.minorGridlayer.selectAll('g') - .map(function(d) { return d[0]; }) - .sort(axisIds.idSort); - - ensureSingleAndAddDatum(plotinfo.gridlayer, 'g', plotinfo.xaxis._id); - ensureSingleAndAddDatum(plotinfo.gridlayer, 'g', plotinfo.yaxis._id); - plotinfo.gridlayer.selectAll('g') - .map(function(d) { return d[0]; }) - .sort(axisIds.idSort); - } - plotinfo.xlines .style('fill', 'none') .classed('crisp', true); diff --git a/test/image/mocks/shapes_layer_below_traces.json b/test/image/mocks/shapes_layer_below_traces.json index 4f198489920..08e1c577aec 100644 --- a/test/image/mocks/shapes_layer_below_traces.json +++ b/test/image/mocks/shapes_layer_below_traces.json @@ -40,6 +40,20 @@ ], "layout": { "shapes": [ + { + "layer": "between", + "name": "my zeroline", + "line": { + "color": "yellow", + "width": 3.0 + }, + "x0": 0, + "x1": 1, + "xref": "paper", + "y0": 0, + "y1": 0, + "yref": "y" + }, { "name": "dashdot line", "fillcolor": "rgba(179,179,179,1)", @@ -125,12 +139,15 @@ "0", "215" ], - "type": "linear" + "type": "linear", + "zerolinewidth": 6, + "zerolinecolor": "rgba(128,128,128,05)" }, "yaxis2": { "gridwidth": 2, "side": "right", - "overlaying": "y" + "overlaying": "y", + "zeroline": false } } From 6722977d33b93a19c405f2746c1b06367e9d4380 Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Tue, 30 Apr 2024 16:48:29 +0200 Subject: [PATCH 02/21] Don't draw cartesianLayerBelow in rangesliders. --- src/components/rangeslider/draw.js | 2 +- src/plots/cartesian/index.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/rangeslider/draw.js b/src/components/rangeslider/draw.js index 3f9049070e8..1f2e3bf8b45 100644 --- a/src/components/rangeslider/draw.js +++ b/src/components/rangeslider/draw.js @@ -504,7 +504,7 @@ function drawRangePlot(rangeSlider, gd, axisOpts, opts) { var plotinfo = { id: id, - plotgroup: plotgroup, + plotgroup: [undefined, plotgroup], xaxis: xa, yaxis: ya, isRangePlot: true diff --git a/src/plots/cartesian/index.js b/src/plots/cartesian/index.js index 722cf95ba82..61600e54832 100644 --- a/src/plots/cartesian/index.js +++ b/src/plots/cartesian/index.js @@ -419,7 +419,6 @@ exports.drawFramework = function(gd) { }; exports.rangePlot = function(gd, plotinfo, cdSubplot) { - makeSubplotLayerBelow(gd, plotinfo); makeSubplotLayerAbove(gd, plotinfo); plotOne(gd, plotinfo, cdSubplot); Plots.style(gd); From 822a89ede0dbf54f64592641c1c560ed7cae4098 Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Tue, 30 Apr 2024 16:52:43 +0200 Subject: [PATCH 03/21] Add draftlog for PR 6989 --- draftlogs/6989_fix.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 draftlogs/6989_fix.md diff --git a/draftlogs/6989_fix.md b/draftlogs/6989_fix.md new file mode 100644 index 00000000000..7e28efa12c9 --- /dev/null +++ b/draftlogs/6989_fix.md @@ -0,0 +1 @@ + - Add support for xref and yref "paper" for shapes with layer "between" [[#6989](https://github.com/plotly/plotly.js/pull/6989)] \ No newline at end of file From eea649ff3aef9ca70f3e9373cbd6d59f9755c62c Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Wed, 1 May 2024 17:00:19 +0200 Subject: [PATCH 04/21] Indicate imageLayerBetween and shapeLayerBetween as private by prepending underscore --- src/components/shapes/draw.js | 2 +- src/plot_api/plot_api.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/shapes/draw.js b/src/components/shapes/draw.js index 784fa1360bc..15279f8fb13 100644 --- a/src/components/shapes/draw.js +++ b/src/components/shapes/draw.js @@ -94,7 +94,7 @@ function drawOne(gd, index) { if(options.layer === 'above') { drawShape(gd._fullLayout._shapeUpperLayer); } else if(options.layer === 'between') { - drawShape(gd._fullLayout.shapeLayerBetween); + drawShape(gd._fullLayout._shapeLayerBetween); } else if(options.xref === 'paper' || options.yref === 'paper') { drawShape(gd._fullLayout._shapeLowerLayer); } else { diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index d72f5c751fa..39a5bd9895c 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -3784,8 +3784,8 @@ function makePlotFramework(gd) { // single cartesian layer for the whole plot fullLayout._cartesianlayerBelow = fullLayout._paper.append('g').classed('cartesianlayer-below', true); var layerBetween = fullLayout._paper.append('g').classed('layer-between', true); - fullLayout.imageLayerBetween = layerBetween.append('g').classed('imagelayer', true); - fullLayout.shapeLayerBetween = layerBetween.append('g').classed('shapelayer', true); + fullLayout._imageLayerBetween = layerBetween.append('g').classed('imagelayer', true); + fullLayout._shapeLayerBetween = layerBetween.append('g').classed('shapelayer', true); fullLayout._cartesianlayerAbove = fullLayout._paper.append('g').classed('cartesianlayer-above', true); // single polar layer for the whole plot fullLayout._polarlayer = fullLayout._paper.append('g').classed('polarlayer', true); From 6414991db9be23c47fc52cbeaf1dd635543f6c40 Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Wed, 1 May 2024 17:20:41 +0200 Subject: [PATCH 05/21] Fix clear after large splom graph --- src/plots/cartesian/index.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/plots/cartesian/index.js b/src/plots/cartesian/index.js index 61600e54832..dec3c69a173 100644 --- a/src/plots/cartesian/index.js +++ b/src/plots/cartesian/index.js @@ -322,7 +322,11 @@ exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) if(oldFullLayout._hasOnlyLargeSploms && !newFullLayout._hasOnlyLargeSploms) { for(k in oldPlots) { plotinfo = oldPlots[k]; - if(plotinfo.plotgroup) plotinfo.plotgroup.remove(); + if(plotinfo.plotgroup) { + for(var idx = 0; idx < plotinfo.plotgroup.length; idx++) { + plotinfo.plotgroup[idx].remove(); + } + } } } From cd3c00256e90ccfbb873260200a9ae1a186bfc77 Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Thu, 2 May 2024 13:05:08 +0200 Subject: [PATCH 06/21] Update baseline shapes_layer_below_traces --- ...s.png => zz_shapes_layer_below_traces.png} | Bin 28866 -> 29036 bytes ...json => zz_shapes_layer_below_traces.json} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename test/image/baselines/{shapes_layer_below_traces.png => zz_shapes_layer_below_traces.png} (86%) rename test/image/mocks/{shapes_layer_below_traces.json => zz_shapes_layer_below_traces.json} (100%) diff --git a/test/image/baselines/shapes_layer_below_traces.png b/test/image/baselines/zz_shapes_layer_below_traces.png similarity index 86% rename from test/image/baselines/shapes_layer_below_traces.png rename to test/image/baselines/zz_shapes_layer_below_traces.png index d6e05eb6f0f2d21bd56d6d9fd5d0fb53f7e3484e..eff4ab9c2af28ce6a457be60401e960b010d4e69 100644 GIT binary patch delta 3968 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 delta 3797 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 Date: Thu, 2 May 2024 17:57:04 +0200 Subject: [PATCH 07/21] don't change cartesian layer CSS class name --- src/plot_api/plot_api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plot_api/plot_api.js b/src/plot_api/plot_api.js index 39a5bd9895c..b8aa201653c 100644 --- a/src/plot_api/plot_api.js +++ b/src/plot_api/plot_api.js @@ -3786,7 +3786,7 @@ function makePlotFramework(gd) { var layerBetween = fullLayout._paper.append('g').classed('layer-between', true); fullLayout._imageLayerBetween = layerBetween.append('g').classed('imagelayer', true); fullLayout._shapeLayerBetween = layerBetween.append('g').classed('shapelayer', true); - fullLayout._cartesianlayerAbove = fullLayout._paper.append('g').classed('cartesianlayer-above', true); + fullLayout._cartesianlayerAbove = fullLayout._paper.append('g').classed('cartesianlayer', true); // single polar layer for the whole plot fullLayout._polarlayer = fullLayout._paper.append('g').classed('polarlayer', true); From bf1167d735df7eb50136eadbced68c5a6913aa2d Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Thu, 2 May 2024 18:48:27 +0200 Subject: [PATCH 08/21] don't change xy CSS class name --- src/plots/cartesian/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plots/cartesian/index.js b/src/plots/cartesian/index.js index dec3c69a173..44f2870b557 100644 --- a/src/plots/cartesian/index.js +++ b/src/plots/cartesian/index.js @@ -384,7 +384,7 @@ exports.drawFramework = function(gd) { var subplotLayersAbove = fullLayout._cartesianlayerAbove.selectAll('.subplot') .data(subplotData, String); subplotLayersAbove.enter().append('g') - .attr('class', function(d) { return 'subplot ' + d[0] + '-above'; }); + .attr('class', function(d) { return 'subplot ' + d[0]; }); subplotLayersAbove.order(); subplotLayersAbove.exit() .call(purgeSubplotLayers, fullLayout); From d5d0d343d6298d4b4865c400f04d0cf1c53aa639 Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Fri, 3 May 2024 15:46:53 +0200 Subject: [PATCH 09/21] Adjust number of sublots in plot_interact_test there are now always 2 cartesian subplots where there was 1 before (one for background and one for foreground) --- test/jasmine/tests/plot_interact_test.js | 48 ++++++++++++------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/test/jasmine/tests/plot_interact_test.js b/test/jasmine/tests/plot_interact_test.js index e091148b807..8498e5007ca 100644 --- a/test/jasmine/tests/plot_interact_test.js +++ b/test/jasmine/tests/plot_interact_test.js @@ -58,8 +58,8 @@ describe('Test plot structure', function() { Plotly.newPlot(gd, mockData, mockLayout).then(done); }); - it('has one *subplot xy* node', function() { - expect(countSubplots()).toEqual(1); + it('has two *subplot xy* nodes', function() { + expect(countSubplots()).toEqual(2); }); it('has four clip paths', function() { @@ -101,19 +101,19 @@ describe('Test plot structure', function() { it('should be able to get deleted', function(done) { expect(countScatterTraces()).toEqual(mock.data.length); - expect(countSubplots()).toEqual(1); + expect(countSubplots()).toEqual(2); Plotly.deleteTraces(gd, [0]).then(function() { expect(countScatterTraces()).toEqual(0); - expect(countSubplots()).toEqual(1); + expect(countSubplots()).toEqual(2); expect(countClipPaths()).toEqual(4); expect(countDraggers()).toEqual(1); return Plotly.relayout(gd, {xaxis: null, yaxis: null}); }).then(function() { expect(countScatterTraces()).toEqual(0); - // we still make one empty cartesian subplot if no other subplots are described - expect(countSubplots()).toEqual(1); + // we still make two empty cartesian subplots (bg and fg) if no other subplots are described + expect(countSubplots()).toEqual(2); expect(countClipPaths()).toEqual(4); expect(countDraggers()).toEqual(1); }) @@ -122,40 +122,40 @@ describe('Test plot structure', function() { it('should restore layout axes when they get deleted', function(done) { expect(countScatterTraces()).toEqual(mock.data.length); - expect(countSubplots()).toEqual(1); + expect(countSubplots()).toEqual(2); Plotly.relayout(gd, {xaxis: null, yaxis: null}) .then(function() { expect(countScatterTraces()).toEqual(1); - expect(countSubplots()).toEqual(1); + expect(countSubplots()).toEqual(2); expect(gd.layout.xaxis.range).toBeCloseToArray([-4.79980, 74.48580], 4); expect(gd.layout.yaxis.range).toBeCloseToArray([-1.2662, 17.67023], 4); return Plotly.relayout(gd, 'xaxis', null); }).then(function() { expect(countScatterTraces()).toEqual(1); - expect(countSubplots()).toEqual(1); + expect(countSubplots()).toEqual(2); expect(gd.layout.xaxis.range).toBeCloseToArray([-4.79980, 74.48580], 4); expect(gd.layout.yaxis.range).toBeCloseToArray([-1.2662, 17.67023], 4); return Plotly.relayout(gd, 'xaxis', {}); }).then(function() { expect(countScatterTraces()).toEqual(1); - expect(countSubplots()).toEqual(1); + expect(countSubplots()).toEqual(2); expect(gd.layout.xaxis.range).toBeCloseToArray([-4.79980, 74.48580], 4); expect(gd.layout.yaxis.range).toBeCloseToArray([-1.2662, 17.67023], 4); return Plotly.relayout(gd, 'yaxis', null); }).then(function() { expect(countScatterTraces()).toEqual(1); - expect(countSubplots()).toEqual(1); + expect(countSubplots()).toEqual(2); expect(gd.layout.xaxis.range).toBeCloseToArray([-4.79980, 74.48580], 4); expect(gd.layout.yaxis.range).toBeCloseToArray([-1.2662, 17.67023], 4); return Plotly.relayout(gd, 'yaxis', {}); }).then(function() { expect(countScatterTraces()).toEqual(1); - expect(countSubplots()).toEqual(1); + expect(countSubplots()).toEqual(2); expect(gd.layout.xaxis.range).toBeCloseToArray([-4.79980, 74.48580], 4); expect(gd.layout.yaxis.range).toBeCloseToArray([-1.2662, 17.67023], 4); }) @@ -202,8 +202,8 @@ describe('Test plot structure', function() { .then(done); }); - it('has four *subplot* nodes', function() { - expect(countSubplots()).toEqual(4); + it('has eight *subplot* nodes', function() { + expect(countSubplots()).toEqual(8); expect(countClipPaths()).toEqual(12); expect(countDraggers()).toEqual(4); }); @@ -245,8 +245,8 @@ describe('Test plot structure', function() { .then(done); }); - it('has four *subplot* nodes', function() { - expect(countSubplots()).toEqual(4); + it('has eight *subplot* nodes', function() { + expect(countSubplots()).toEqual(8); expect(countClipPaths()).toEqual(12); expect(countDraggers()).toEqual(4); }); @@ -285,7 +285,7 @@ describe('Test plot structure', function() { } it('should be removed of traces in sequence', function(done) { - expect(countSubplots()).toEqual(4); + expect(countSubplots()).toEqual(8); assertHeatmapNodes(4); assertContourNodes(2); expect(countColorBars()).toEqual(1); @@ -298,7 +298,7 @@ describe('Test plot structure', function() { }); Plotly.deleteTraces(gd, [0]).then(function() { - expect(countSubplots()).toEqual(3); + expect(countSubplots()).toEqual(6); expect(countClipPaths()).toEqual(11); expect(countDraggers()).toEqual(3); assertHeatmapNodes(3); @@ -314,7 +314,7 @@ describe('Test plot structure', function() { return Plotly.deleteTraces(gd, [0]); }).then(function() { - expect(countSubplots()).toEqual(2); + expect(countSubplots()).toEqual(4); expect(countClipPaths()).toEqual(7); expect(countDraggers()).toEqual(2); assertHeatmapNodes(2); @@ -330,7 +330,7 @@ describe('Test plot structure', function() { return Plotly.deleteTraces(gd, [0]); }).then(function() { - expect(countSubplots()).toEqual(1); + expect(countSubplots()).toEqual(2); expect(countClipPaths()).toEqual(4); expect(countDraggers()).toEqual(1); assertHeatmapNodes(1); @@ -346,7 +346,7 @@ describe('Test plot structure', function() { return Plotly.deleteTraces(gd, [0]); }).then(function() { - expect(countSubplots()).toEqual(1); + expect(countSubplots()).toEqual(2); expect(countClipPaths()).toEqual(4); expect(countDraggers()).toEqual(1); assertHeatmapNodes(0); @@ -369,7 +369,7 @@ describe('Test plot structure', function() { return Plotly.relayout(gd, update); }).then(function() { - expect(countSubplots()).toEqual(1); + expect(countSubplots()).toEqual(2); expect(countClipPaths()).toEqual(4); expect(countDraggers()).toEqual(1); assertHeatmapNodes(0); @@ -438,7 +438,7 @@ describe('Test plot structure', function() { Plotly.deleteTraces(gd, [0]).then(function() { expect(countPieTraces()).toEqual(0); - expect(countSubplots()).toEqual(1); + expect(countSubplots()).toEqual(2); }) .then(done, done.fail); }); @@ -451,7 +451,7 @@ describe('Test plot structure', function() { Plotly.restyle(gd, 'type', 'bar').then(function() { expect(countPieTraces()).toEqual(0); expect(countBarTraces()).toEqual(1); - expect(countSubplots()).toEqual(1); + expect(countSubplots()).toEqual(2); return Plotly.restyle(gd, 'type', 'pie'); }).then(function() { From 0a1a5a32270c4eab822b92cd3d200a0f9cf59982 Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Fri, 3 May 2024 17:21:50 +0200 Subject: [PATCH 10/21] Update cartesian_tests --- test/jasmine/tests/cartesian_test.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/jasmine/tests/cartesian_test.js b/test/jasmine/tests/cartesian_test.js index b31d331d998..0dfbebdb809 100644 --- a/test/jasmine/tests/cartesian_test.js +++ b/test/jasmine/tests/cartesian_test.js @@ -436,7 +436,7 @@ describe('subplot creation / deletion:', function() { function checkBGLayers(behindCount, x2y2Count, subplots) { expect(gd.querySelectorAll('.bglayer rect.bg').length).toBe(behindCount); - expect(gd.querySelectorAll('.subplot.x2y2 rect.bg').length).toBe(x2y2Count); + expect(gd.querySelectorAll('.subplot.x2y2-below rect.bg').length).toBe(x2y2Count); // xy is the first subplot, so it never gets put in front of others expect(gd.querySelectorAll('.subplot.xy rect.bg').length).toBe(0); @@ -445,7 +445,7 @@ describe('subplot creation / deletion:', function() { expect(gd.querySelectorAll('.subplot.xy3 rect.bg').length).toBe(0); // verify that these are *all* the subplots and backgrounds we have - expect(gd.querySelectorAll('.subplot').length).toBe(subplots.length); + expect(gd.querySelectorAll('.subplot').length).toBe(subplots.length * 2); subplots.forEach(function(subplot) { expect(gd.querySelectorAll('.subplot.' + subplot).length).toBe(1); }); @@ -791,14 +791,15 @@ describe('subplot creation / deletion:', function() { it('clear axis ticks, labels and title when relayout an axis to `*visible:false*', function(done) { function _assert(xaxis, yaxis) { var g = d3Select('.subplot.xy'); + var gBelow = d3Select('.subplot.xy-below'); var info = d3Select('.infolayer'); expect(g.selectAll('.xtick').size()).toBe(xaxis[0], 'x tick cnt'); - expect(g.selectAll('.gridlayer .xgrid').size()).toBe(xaxis[1], 'x gridline cnt'); + expect(gBelow.selectAll('.gridlayer .xgrid').size()).toBe(xaxis[1], 'x gridline cnt'); expect(info.selectAll('.g-xtitle').size()).toBe(xaxis[2], 'x title cnt'); expect(g.selectAll('.ytick').size()).toBe(yaxis[0], 'y tick cnt'); - expect(g.selectAll('.gridlayer .ygrid').size()).toBe(yaxis[1], 'y gridline cnt'); + expect(gBelow.selectAll('.gridlayer .ygrid').size()).toBe(yaxis[1], 'y gridline cnt'); expect(info.selectAll('.g-ytitle').size()).toBe(yaxis[2], 'y title cnt'); } From 5514c8c07888902ec9dafae43db3e86ed189f74d Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Sat, 4 May 2024 15:32:54 +0200 Subject: [PATCH 11/21] splom_test: Remove test that ensures that xaxislayer-above comes after gridlayer Gridlayer is now in cartesianlayer-below, so it is below xaxislayer-above anyways. --- test/jasmine/tests/splom_test.js | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/test/jasmine/tests/splom_test.js b/test/jasmine/tests/splom_test.js index 1702d63e2f5..e6ecadbfc66 100644 --- a/test/jasmine/tests/splom_test.js +++ b/test/jasmine/tests/splom_test.js @@ -830,23 +830,6 @@ describe('Test splom interactions:', function() { bgCnt: 0 }); - // make sure 'new' subplot layers are in order - var gridIndex = -1; - var xaxisIndex = -1; - var subplot0 = d3Select('g.cartesianlayer > g.subplot').node(); - for(var i in subplot0.children) { - var cl = subplot0.children[i].classList; - if(cl) { - if(cl.contains('gridlayer')) gridIndex = +i; - else if(cl.contains('xaxislayer-above')) xaxisIndex = +i; - } - } - // from large -> small splom: - // grid layer would be above xaxis layer, - // if we didn't clear subplot children. - expect(gridIndex).toBe(2, ' index'); - expect(xaxisIndex).toBe(16, ' index'); - return Plotly.restyle(gd, 'dimensions', [dimsLarge]); }) .then(function() { From 5cd2fecef7665473728eb08dfefe9b57a6bc349d Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Sat, 4 May 2024 16:25:22 +0200 Subject: [PATCH 12/21] splom_test: update test on how many inner nodes are expected in cartesian subplots --- test/jasmine/tests/splom_test.js | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/test/jasmine/tests/splom_test.js b/test/jasmine/tests/splom_test.js index e6ecadbfc66..42a073b3a2d 100644 --- a/test/jasmine/tests/splom_test.js +++ b/test/jasmine/tests/splom_test.js @@ -766,17 +766,27 @@ describe('Test splom interactions:', function() { var msg = ' - call #' + cnt; var gd3 = d3Select(gd); var subplots = gd3.selectAll('g.cartesianlayer > g.subplot'); + var subplotsBelow = gd3.selectAll('g.cartesianlayer-below > g.subplot'); var bgs = gd3.selectAll('.bglayer > rect.bg'); expect(subplots.size()) - .toBe(exp.subplotCnt, '# of ' + msg); + .toBe(exp.subplotCnt, '# of ' + msg); var failedSubplots = []; subplots.each(function(d, i) { var actual = this.children.length; var expected = typeof exp.innerSubplotNodeCnt === 'function' ? - exp.innerSubplotNodeCnt(d[0], i) : - exp.innerSubplotNodeCnt; + exp.innerSubplotNodeCnt(d[0], i) : + exp.innerSubplotNodeCnt; + if(actual !== expected) { + failedSubplots.push([d, actual, 'vs', expected].join(' ')); + } + }); + subplotsBelow.each(function(d, i) { + var actual = this.children.length; + var expected = typeof exp.innerSubplotNodeCntBelow === 'function' ? + exp.innerSubplotNodeCntBelow(d[0], i) : + exp.innerSubplotNodeCntBelow; if(actual !== expected) { failedSubplots.push([d, actual, 'vs', expected].join(' ')); } @@ -795,6 +805,7 @@ describe('Test splom interactions:', function() { _newPlot(gd, figLarge).then(function() { _assert({ subplotCnt: 400, + innerSubplotNodeCntBelow: 4, innerSubplotNodeCnt: 4, hasSplomGrid: true, bgCnt: 0 @@ -805,6 +816,7 @@ describe('Test splom interactions:', function() { .then(function() { _assert({ subplotCnt: 400, + innerSubplotNodeCntBelow: 4, innerSubplotNodeCnt: 4, hasSplomGrid: true, bgCnt: 400 @@ -815,6 +827,7 @@ describe('Test splom interactions:', function() { .then(function() { _assert({ subplotCnt: 400, + innerSubplotNodeCntBelow: 4, innerSubplotNodeCnt: 4, hasSplomGrid: true, bgCnt: 0 @@ -825,7 +838,8 @@ describe('Test splom interactions:', function() { .then(function() { _assert({ subplotCnt: 25, - innerSubplotNodeCnt: 19, + innerSubplotNodeCntBelow: 4, + innerSubplotNodeCnt: 14, hasSplomGrid: false, bgCnt: 0 }); @@ -838,9 +852,10 @@ describe('Test splom interactions:', function() { // from small -> large splom: // no need to clear subplots children in existing subplots, // new subplots though have reduced number of children. + innerSubplotNodeCntBelow: 4, innerSubplotNodeCnt: function(d) { var p = d.match(SUBPLOT_PATTERN); - return (p[1] > 5 || p[2] > 5) ? 4 : 19; + return (p[1] > 5 || p[2] > 5) ? 4 : 14; }, hasSplomGrid: true, bgCnt: 0 From ae69416805ebebeb88109d217ee837e830d495e0 Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Fri, 10 May 2024 12:14:53 +0200 Subject: [PATCH 13/21] Add comment explaining why rangeslider's plotinfo has plotgroup: [undefined, plotgroup] --- src/components/rangeslider/draw.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/rangeslider/draw.js b/src/components/rangeslider/draw.js index 1f2e3bf8b45..da87679683e 100644 --- a/src/components/rangeslider/draw.js +++ b/src/components/rangeslider/draw.js @@ -504,7 +504,7 @@ function drawRangePlot(rangeSlider, gd, axisOpts, opts) { var plotinfo = { id: id, - plotgroup: [undefined, plotgroup], + plotgroup: [undefined, plotgroup], // ragenslider has no background layer xaxis: xa, yaxis: ya, isRangePlot: true From bad1bcf5ff3883bc8e77cf8413223f86c9d385fc Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Fri, 10 May 2024 12:18:49 +0200 Subject: [PATCH 14/21] reverse for loop for clearing in cartesian plot. --- src/plots/cartesian/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plots/cartesian/index.js b/src/plots/cartesian/index.js index 44f2870b557..d13838e4e8d 100644 --- a/src/plots/cartesian/index.js +++ b/src/plots/cartesian/index.js @@ -323,7 +323,7 @@ exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) for(k in oldPlots) { plotinfo = oldPlots[k]; if(plotinfo.plotgroup) { - for(var idx = 0; idx < plotinfo.plotgroup.length; idx++) { + for(var idx = plotinfo.plotgroup.length; idx >= 0; idx--) { plotinfo.plotgroup[idx].remove(); } } From b9ec442c23d9a3a9a64a559c6972f0d5bf58a7c3 Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Fri, 10 May 2024 12:34:52 +0200 Subject: [PATCH 15/21] plot_interact_test: replace countSubplots with countSubplotsBackground and countSublotsForeground --- test/jasmine/tests/plot_interact_test.js | 83 +++++++++++++++--------- 1 file changed, 54 insertions(+), 29 deletions(-) diff --git a/test/jasmine/tests/plot_interact_test.js b/test/jasmine/tests/plot_interact_test.js index 8498e5007ca..5ed4754495c 100644 --- a/test/jasmine/tests/plot_interact_test.js +++ b/test/jasmine/tests/plot_interact_test.js @@ -25,10 +25,12 @@ describe('Test plot structure', function() { afterEach(destroyGraphDiv); describe('cartesian plots', function() { - function countSubplots() { - return d3SelectAll('g.subplot').size(); + function countSubplotsBackground() { + return d3SelectAll('g.cartesianlayer-below g.subplot').size(); + } + function countSubplotsForeground() { + return d3SelectAll('g.cartesianlayer g.subplot').size(); } - function countScatterTraces() { return d3SelectAll('g.trace.scatter').size(); } @@ -58,8 +60,9 @@ describe('Test plot structure', function() { Plotly.newPlot(gd, mockData, mockLayout).then(done); }); - it('has two *subplot xy* nodes', function() { - expect(countSubplots()).toEqual(2); + it('has one *subplot xy* node each in background and foreground', function() { + expect(countSubplotsBackground()).toEqual(1); + expect(countSubplotsForeground()).toEqual(1); }); it('has four clip paths', function() { @@ -101,11 +104,13 @@ describe('Test plot structure', function() { it('should be able to get deleted', function(done) { expect(countScatterTraces()).toEqual(mock.data.length); - expect(countSubplots()).toEqual(2); + expect(countSubplotsBackground()).toEqual(1); + expect(countSubplotsForeground()).toEqual(1); Plotly.deleteTraces(gd, [0]).then(function() { expect(countScatterTraces()).toEqual(0); - expect(countSubplots()).toEqual(2); + expect(countSubplotsBackground()).toEqual(1); + expect(countSubplotsForeground()).toEqual(1); expect(countClipPaths()).toEqual(4); expect(countDraggers()).toEqual(1); @@ -113,7 +118,8 @@ describe('Test plot structure', function() { }).then(function() { expect(countScatterTraces()).toEqual(0); // we still make two empty cartesian subplots (bg and fg) if no other subplots are described - expect(countSubplots()).toEqual(2); + expect(countSubplotsBackground()).toEqual(1); + expect(countSubplotsForeground()).toEqual(1); expect(countClipPaths()).toEqual(4); expect(countDraggers()).toEqual(1); }) @@ -122,40 +128,46 @@ describe('Test plot structure', function() { it('should restore layout axes when they get deleted', function(done) { expect(countScatterTraces()).toEqual(mock.data.length); - expect(countSubplots()).toEqual(2); + expect(countSubplotsBackground()).toEqual(1); + expect(countSubplotsForeground()).toEqual(1); Plotly.relayout(gd, {xaxis: null, yaxis: null}) .then(function() { expect(countScatterTraces()).toEqual(1); - expect(countSubplots()).toEqual(2); + expect(countSubplotsBackground()).toEqual(1); + expect(countSubplotsForeground()).toEqual(1); expect(gd.layout.xaxis.range).toBeCloseToArray([-4.79980, 74.48580], 4); expect(gd.layout.yaxis.range).toBeCloseToArray([-1.2662, 17.67023], 4); return Plotly.relayout(gd, 'xaxis', null); }).then(function() { expect(countScatterTraces()).toEqual(1); - expect(countSubplots()).toEqual(2); + expect(countSubplotsBackground()).toEqual(1); + expect(countSubplotsForeground()).toEqual(1); expect(gd.layout.xaxis.range).toBeCloseToArray([-4.79980, 74.48580], 4); expect(gd.layout.yaxis.range).toBeCloseToArray([-1.2662, 17.67023], 4); return Plotly.relayout(gd, 'xaxis', {}); }).then(function() { expect(countScatterTraces()).toEqual(1); - expect(countSubplots()).toEqual(2); + expect(countSubplotsBackground()).toEqual(1); + expect(countSubplotsForeground()).toEqual(1); expect(gd.layout.xaxis.range).toBeCloseToArray([-4.79980, 74.48580], 4); expect(gd.layout.yaxis.range).toBeCloseToArray([-1.2662, 17.67023], 4); return Plotly.relayout(gd, 'yaxis', null); }).then(function() { expect(countScatterTraces()).toEqual(1); - expect(countSubplots()).toEqual(2); + expect(countSubplotsBackground()).toEqual(1); + expect(countSubplotsForeground()).toEqual(1); expect(gd.layout.xaxis.range).toBeCloseToArray([-4.79980, 74.48580], 4); expect(gd.layout.yaxis.range).toBeCloseToArray([-1.2662, 17.67023], 4); return Plotly.relayout(gd, 'yaxis', {}); }).then(function() { expect(countScatterTraces()).toEqual(1); - expect(countSubplots()).toEqual(2); + expect(countSubplotsBackground()).toEqual(1); + expect(countSubplotsForeground()).toEqual(1); expect(gd.layout.xaxis.range).toBeCloseToArray([-4.79980, 74.48580], 4); expect(gd.layout.yaxis.range).toBeCloseToArray([-1.2662, 17.67023], 4); }) @@ -202,8 +214,9 @@ describe('Test plot structure', function() { .then(done); }); - it('has eight *subplot* nodes', function() { - expect(countSubplots()).toEqual(8); + it('has four *subplot* nodes', function() { + expect(countSubplotsBackground()).toEqual(4); + expect(countSubplotsForeground()).toEqual(4); expect(countClipPaths()).toEqual(12); expect(countDraggers()).toEqual(4); }); @@ -245,8 +258,9 @@ describe('Test plot structure', function() { .then(done); }); - it('has eight *subplot* nodes', function() { - expect(countSubplots()).toEqual(8); + it('has 4 *subplot* nodes', function() { + expect(countSubplotsBackground()).toEqual(4); + expect(countSubplotsForeground()).toEqual(4); expect(countClipPaths()).toEqual(12); expect(countDraggers()).toEqual(4); }); @@ -285,7 +299,8 @@ describe('Test plot structure', function() { } it('should be removed of traces in sequence', function(done) { - expect(countSubplots()).toEqual(8); + expect(countSubplotsBackground()).toEqual(4); + expect(countSubplotsForeground()).toEqual(4); assertHeatmapNodes(4); assertContourNodes(2); expect(countColorBars()).toEqual(1); @@ -298,7 +313,8 @@ describe('Test plot structure', function() { }); Plotly.deleteTraces(gd, [0]).then(function() { - expect(countSubplots()).toEqual(6); + expect(countSubplotsBackground()).toEqual(3); + expect(countSubplotsForeground()).toEqual(3); expect(countClipPaths()).toEqual(11); expect(countDraggers()).toEqual(3); assertHeatmapNodes(3); @@ -314,7 +330,8 @@ describe('Test plot structure', function() { return Plotly.deleteTraces(gd, [0]); }).then(function() { - expect(countSubplots()).toEqual(4); + expect(countSubplotsBackground()).toEqual(2); + expect(countSubplotsForeground()).toEqual(2); expect(countClipPaths()).toEqual(7); expect(countDraggers()).toEqual(2); assertHeatmapNodes(2); @@ -330,7 +347,8 @@ describe('Test plot structure', function() { return Plotly.deleteTraces(gd, [0]); }).then(function() { - expect(countSubplots()).toEqual(2); + expect(countSubplotsBackground()).toEqual(1); + expect(countSubplotsForeground()).toEqual(1); expect(countClipPaths()).toEqual(4); expect(countDraggers()).toEqual(1); assertHeatmapNodes(1); @@ -346,7 +364,8 @@ describe('Test plot structure', function() { return Plotly.deleteTraces(gd, [0]); }).then(function() { - expect(countSubplots()).toEqual(2); + expect(countSubplotsBackground()).toEqual(1); + expect(countSubplotsForeground()).toEqual(1); expect(countClipPaths()).toEqual(4); expect(countDraggers()).toEqual(1); assertHeatmapNodes(0); @@ -369,7 +388,8 @@ describe('Test plot structure', function() { return Plotly.relayout(gd, update); }).then(function() { - expect(countSubplots()).toEqual(2); + expect(countSubplotsBackground()).toEqual(1); + expect(countSubplotsForeground()).toEqual(1); expect(countClipPaths()).toEqual(4); expect(countDraggers()).toEqual(1); assertHeatmapNodes(0); @@ -434,11 +454,13 @@ describe('Test plot structure', function() { it('should be able to get deleted', function(done) { expect(countPieTraces()).toEqual(1); - expect(countSubplots()).toEqual(0); + expect(countSubplotsBackground()).toEqual(0); + expect(countSubplotsForeground()).toEqual(0); Plotly.deleteTraces(gd, [0]).then(function() { expect(countPieTraces()).toEqual(0); - expect(countSubplots()).toEqual(2); + expect(countSubplotsBackground()).toEqual(1); + expect(countSubplotsForeground()).toEqual(1); }) .then(done, done.fail); }); @@ -446,18 +468,21 @@ describe('Test plot structure', function() { it('should be able to be restyled to a bar chart and back', function(done) { expect(countPieTraces()).toEqual(1); expect(countBarTraces()).toEqual(0); - expect(countSubplots()).toEqual(0); + expect(countSubplotsBackground()).toEqual(0); + expect(countSubplotsForeground()).toEqual(0); Plotly.restyle(gd, 'type', 'bar').then(function() { expect(countPieTraces()).toEqual(0); expect(countBarTraces()).toEqual(1); - expect(countSubplots()).toEqual(2); + expect(countSubplotsBackground()).toEqual(1); + expect(countSubplotsForeground()).toEqual(1); return Plotly.restyle(gd, 'type', 'pie'); }).then(function() { expect(countPieTraces()).toEqual(1); expect(countBarTraces()).toEqual(0); - expect(countSubplots()).toEqual(0); + expect(countSubplotsBackground()).toEqual(0); + expect(countSubplotsForeground()).toEqual(0); }) .then(done, done.fail); }); From dcc77e5db257179b209f78b32988b2221037b275 Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Fri, 10 May 2024 13:43:12 +0200 Subject: [PATCH 16/21] Revert changes to shapes_layer_below_traces and move those changes into a new mock --- ...aces.png => shapes_layer_below_traces.png} | Bin 29036 -> 28866 bytes ...es.json => shapes_layer_below_traces.json} | 21 +--------- .../zz_shapes_layer_between_xref_paper.json | 36 ++++++++++++++++++ 3 files changed, 38 insertions(+), 19 deletions(-) rename test/image/baselines/{zz_shapes_layer_below_traces.png => shapes_layer_below_traces.png} (86%) rename test/image/mocks/{zz_shapes_layer_below_traces.json => shapes_layer_below_traces.json} (85%) create mode 100644 test/image/mocks/zz_shapes_layer_between_xref_paper.json diff --git a/test/image/baselines/zz_shapes_layer_below_traces.png b/test/image/baselines/shapes_layer_below_traces.png similarity index 86% rename from test/image/baselines/zz_shapes_layer_below_traces.png rename to test/image/baselines/shapes_layer_below_traces.png index eff4ab9c2af28ce6a457be60401e960b010d4e69..d6e05eb6f0f2d21bd56d6d9fd5d0fb53f7e3484e 100644 GIT binary patch delta 3797 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 diff --git a/test/image/mocks/zz_shapes_layer_below_traces.json b/test/image/mocks/shapes_layer_below_traces.json similarity index 85% rename from test/image/mocks/zz_shapes_layer_below_traces.json rename to test/image/mocks/shapes_layer_below_traces.json index 08e1c577aec..4f198489920 100644 --- a/test/image/mocks/zz_shapes_layer_below_traces.json +++ b/test/image/mocks/shapes_layer_below_traces.json @@ -40,20 +40,6 @@ ], "layout": { "shapes": [ - { - "layer": "between", - "name": "my zeroline", - "line": { - "color": "yellow", - "width": 3.0 - }, - "x0": 0, - "x1": 1, - "xref": "paper", - "y0": 0, - "y1": 0, - "yref": "y" - }, { "name": "dashdot line", "fillcolor": "rgba(179,179,179,1)", @@ -139,15 +125,12 @@ "0", "215" ], - "type": "linear", - "zerolinewidth": 6, - "zerolinecolor": "rgba(128,128,128,05)" + "type": "linear" }, "yaxis2": { "gridwidth": 2, "side": "right", - "overlaying": "y", - "zeroline": false + "overlaying": "y" } } diff --git a/test/image/mocks/zz_shapes_layer_between_xref_paper.json b/test/image/mocks/zz_shapes_layer_between_xref_paper.json new file mode 100644 index 00000000000..b538ecdb432 --- /dev/null +++ b/test/image/mocks/zz_shapes_layer_between_xref_paper.json @@ -0,0 +1,36 @@ +{ + "data": [ + { + "x": [ + 1, 2, 3, 4, 5, 6, 7 + ], + "y": [ + -1000, 0, 1000, 2000, 3000, 4000, 5000 + ] + } + ], + "layout": { + "shapes": [ + + { + "layer": "between", + "name": "my zeroline y2", + "line": { + "color": "yellow", + "width": 3.0 + }, + "x0": 0, + "x1": 1, + "xref": "paper", + "y0": 0, + "y1": 0, + "yref": "y" + } + ], + "yaxis": { + "ticklabelposition": "inside top", + "zeroline": false + } + + } +} From 21c3ea32bd1ed0c33260783d5bb58d2fc6aa4af9 Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Fri, 10 May 2024 15:04:06 +0200 Subject: [PATCH 17/21] Fix for loop start index for clearing subplots --- src/plots/cartesian/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plots/cartesian/index.js b/src/plots/cartesian/index.js index d13838e4e8d..45331ac6970 100644 --- a/src/plots/cartesian/index.js +++ b/src/plots/cartesian/index.js @@ -323,7 +323,7 @@ exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) for(k in oldPlots) { plotinfo = oldPlots[k]; if(plotinfo.plotgroup) { - for(var idx = plotinfo.plotgroup.length; idx >= 0; idx--) { + for(var idx = plotinfo.plotgroup.length - 1; idx >= 0; idx--) { plotinfo.plotgroup[idx].remove(); } } From 6c2164a5f91cf7301c18cbfc3641c04fc16fcddf Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Fri, 10 May 2024 15:31:56 +0200 Subject: [PATCH 18/21] Add baseline image for mock zz_shapes_layer_between_xref_paper --- .../zz_shapes_layer_between_xref_paper.png | Bin 0 -> 26945 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/image/baselines/zz_shapes_layer_between_xref_paper.png diff --git a/test/image/baselines/zz_shapes_layer_between_xref_paper.png b/test/image/baselines/zz_shapes_layer_between_xref_paper.png new file mode 100644 index 0000000000000000000000000000000000000000..480e71cc96a30ea8d2c716fbc85466c1efa4d21a GIT binary patch literal 26945 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

JCO2i=Yq&14-;fbzjmp!drvmqyH6;n`T>g$TBB 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 literal 0 HcmV?d00001 From cb495d3a58525091e5a927e074864ca2064503d2 Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Thu, 27 Jun 2024 16:00:39 +0200 Subject: [PATCH 19/21] Update leftover property name _cartesianlayer -> _cartesianlayerAbove --- src/plots/cartesian/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plots/cartesian/index.js b/src/plots/cartesian/index.js index 735fafb20e7..b06d1021bd3 100644 --- a/src/plots/cartesian/index.js +++ b/src/plots/cartesian/index.js @@ -159,7 +159,7 @@ exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) { idWithZ += zindexSeparator + (z + 1); subplotInfo = Lib.extendFlat({}, subplotInfo, { id: idWithZ, - plot: fullLayout._cartesianlayer.selectAll('.subplot').select('.' + idWithZ) + plot: fullLayout._cartesianlayerAbove.selectAll('.subplot').select('.' + idWithZ) }); } From bed5ca4f2dea10a375e8b1cf22586d7c9f531338 Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Fri, 8 Nov 2024 13:11:54 +0100 Subject: [PATCH 20/21] Fix drawFramework after merging zorder changes. For shapes.layer "between" feature, this branch changed plotinfo.plotgroup from one single layer to an array of 2 layers ("below" and "above"). The zorder feature conflicted with this section and was solved incorrectly in the merge commit, leading to 3 layers in the plotgroups with z indices ("below", "above without z", "above with z"). In makeSubplotLayerAbove, traces were drawn into plotgroup[1], effectively discarding the zorder information. --- src/plots/cartesian/index.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plots/cartesian/index.js b/src/plots/cartesian/index.js index 22c31d284b9..1820bc27a4e 100644 --- a/src/plots/cartesian/index.js +++ b/src/plots/cartesian/index.js @@ -470,18 +470,20 @@ exports.drawFramework = function(gd) { id; var plotinfo = fullLayout._plots[id]; - if(!plotinfo) { + if(plotinfo) { + plotinfo.plotgroup = plotinfo.plotgroup.concat([d3.select(this)]); + } else { // repurpose plotinfo from plot without z plotinfo = Lib.extendFlat({}, fullLayout._plots[idWithoutZ]); if(plotinfo) { plotinfo.id = id; fullLayout._plots[id] = plotinfo; fullLayout._subplots.cartesian.push(id); + plotinfo.plotgroup[1] = d3.select(this); } } if(plotinfo) { - plotinfo.plotgroup = plotinfo.plotgroup.concat([d3.select(this)]); makeSubplotLayerAbove(gd, plotinfo); if(!hasZ) { From 68441e0c25d75b8563b52f53232dbbaad8f04204 Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Wed, 13 Nov 2024 11:31:43 +0100 Subject: [PATCH 21/21] Fix expected number of subplots in splom_test sploms have less layers. --- test/jasmine/tests/splom_test.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/test/jasmine/tests/splom_test.js b/test/jasmine/tests/splom_test.js index f6eb5f5fb9d..1bdc9c9646b 100644 --- a/test/jasmine/tests/splom_test.js +++ b/test/jasmine/tests/splom_test.js @@ -779,7 +779,7 @@ describe('Test splom interactions:', function() { _newPlot(gd, figLarge).then(function() { _assert({ subplotCnt: 400, - innerSubplotNodeCntBelow: 4, + innerSubplotNodeCntBelow: 0, innerSubplotNodeCnt: 4, hasSplomGrid: true, bgCnt: 0 @@ -790,7 +790,7 @@ describe('Test splom interactions:', function() { .then(function() { _assert({ subplotCnt: 400, - innerSubplotNodeCntBelow: 4, + innerSubplotNodeCntBelow: 0, innerSubplotNodeCnt: 4, hasSplomGrid: true, bgCnt: 400 @@ -801,7 +801,7 @@ describe('Test splom interactions:', function() { .then(function() { _assert({ subplotCnt: 400, - innerSubplotNodeCntBelow: 4, + innerSubplotNodeCntBelow: 0, innerSubplotNodeCnt: 4, hasSplomGrid: true, bgCnt: 0 @@ -826,7 +826,10 @@ describe('Test splom interactions:', function() { // from small -> large splom: // no need to clear subplots children in existing subplots, // new subplots though have reduced number of children. - innerSubplotNodeCntBelow: 4, + innerSubplotNodeCntBelow: function(d) { + var p = d.match(SUBPLOT_PATTERN); + return (p[1] > 5 || p[2] > 5) ? 0 : 4; + }, innerSubplotNodeCnt: function(d) { var p = d.match(SUBPLOT_PATTERN); return (p[1] > 5 || p[2] > 5) ? 4 : 13;