Skip to content

Commit

Permalink
Merge pull request #6743 from plotly/fix6742-partial-range-interact
Browse files Browse the repository at this point in the history
Fix range interactions affecting partial ranges in other subplots
  • Loading branch information
archmoj authored Oct 4, 2023
2 parents 724bab1 + 3cc3c42 commit d828853
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 50 deletions.
1 change: 1 addition & 0 deletions draftlogs/6743_fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Fix range interactions affecting partial ranges in other subplots [[#6743](https://github.com/plotly/plotly.js/pull/6743)]
30 changes: 13 additions & 17 deletions src/plot_api/plot_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ var PlotSchema = require('./plot_schema');
var Plots = require('../plots/plots');

var Axes = require('../plots/cartesian/axes');
var handleRangeDefaults = require('../plots/cartesian/range_defaults');

var cartesianLayoutAttributes = require('../plots/cartesian/layout_attributes');
var Drawing = require('../components/drawing');
var Color = require('../components/color');
var initInteractions = require('../plots/cartesian/graph_interact').initInteractions;
Expand Down Expand Up @@ -1838,26 +1841,19 @@ function axRangeSupplyDefaultsByPass(gd, flags, specs) {
if(k !== 'axrange' && flags[k]) return false;
}

var axIn, axOut;
var coerce = function(attr, dflt) {
return Lib.coerce(axIn, axOut, cartesianLayoutAttributes, attr, dflt);
};

var options = {}; // passing empty options for now!

for(var axId in specs.rangesAltered) {
var axName = Axes.id2name(axId);
var axIn = gd.layout[axName];
var axOut = fullLayout[axName];
axOut.autorange = axIn.autorange;
axIn = gd.layout[axName];
axOut = fullLayout[axName];

var r0 = axOut._rangeInitial0;
var r1 = axOut._rangeInitial1;
// partial range needs supplyDefaults
if(
(r0 === undefined && r1 !== undefined) ||
(r0 !== undefined && r1 === undefined)
) {
return false;
}

if(axIn.range) {
axOut.range = axIn.range.slice();
}
axOut.cleanRange();
handleRangeDefaults(axIn, axOut, coerce, options);

if(axOut._matchGroup) {
for(var axId2 in axOut._matchGroup) {
Expand Down
35 changes: 2 additions & 33 deletions src/plots/cartesian/axis_defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ var handleTickLabelDefaults = require('./tick_label_defaults');
var handlePrefixSuffixDefaults = require('./prefix_suffix_defaults');
var handleCategoryOrderDefaults = require('./category_order_defaults');
var handleLineGridDefaults = require('./line_grid_defaults');
var handleAutorangeOptionsDefaults = require('./autorange_options_defaults');
var handleRangeDefaults = require('./range_defaults');
var setConvert = require('./set_convert');

var DAY_OF_WEEK = require('./constants').WEEKDAY_PATTERN;
Expand Down Expand Up @@ -92,38 +92,7 @@ module.exports = function handleAxisDefaults(containerIn, containerOut, coerce,

setConvert(containerOut, layoutOut);

coerce('minallowed');
coerce('maxallowed');
var range = coerce('range');
var autorangeDflt = containerOut.getAutorangeDflt(range, options);
var autorange = coerce('autorange', autorangeDflt);

var shouldAutorange;

// validate range and set autorange true for invalid partial ranges
if(range && (
(range[0] === null && range[1] === null) ||
((range[0] === null || range[1] === null) && (autorange === 'reversed' || autorange === true)) ||
(range[0] !== null && (autorange === 'min' || autorange === 'max reversed')) ||
(range[1] !== null && (autorange === 'max' || autorange === 'min reversed'))
)) {
range = undefined;
delete containerOut.range;
containerOut.autorange = true;
shouldAutorange = true;
}

if(!shouldAutorange) {
autorangeDflt = containerOut.getAutorangeDflt(range, options);
autorange = coerce('autorange', autorangeDflt);
}

if(autorange) {
handleAutorangeOptionsDefaults(coerce, autorange, range);
if(axType === 'linear' || axType === '-') coerce('rangemode');
}

containerOut.cleanRange();
handleRangeDefaults(containerIn, containerOut, coerce, options);

handleCategoryOrderDefaults(containerIn, containerOut, coerce, options);

Expand Down
42 changes: 42 additions & 0 deletions src/plots/cartesian/range_defaults.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use strict';

var handleAutorangeOptionsDefaults = require('./autorange_options_defaults');

module.exports = function handleRangeDefaults(containerIn, containerOut, coerce, options) {
var axTemplate = containerOut._template || {};
var axType = containerOut.type || axTemplate.type || '-';

coerce('minallowed');
coerce('maxallowed');

var range = coerce('range');
var autorangeDflt = containerOut.getAutorangeDflt(range, options);
var autorange = coerce('autorange', autorangeDflt);

var shouldAutorange;

// validate range and set autorange true for invalid partial ranges
if(range && (
(range[0] === null && range[1] === null) ||
((range[0] === null || range[1] === null) && (autorange === 'reversed' || autorange === true)) ||
(range[0] !== null && (autorange === 'min' || autorange === 'max reversed')) ||
(range[1] !== null && (autorange === 'max' || autorange === 'min reversed'))
)) {
range = undefined;
delete containerOut.range;
containerOut.autorange = true;
shouldAutorange = true;
}

if(!shouldAutorange) {
autorangeDflt = containerOut.getAutorangeDflt(range, options);
autorange = coerce('autorange', autorangeDflt);
}

if(autorange) {
handleAutorangeOptionsDefaults(coerce, autorange, range);
if(axType === 'linear' || axType === '-') coerce('rangemode');
}

containerOut.cleanRange();
};
97 changes: 97 additions & 0 deletions test/jasmine/tests/axes_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1581,6 +1581,103 @@ describe('Test axes', function() {
.then(done, done.fail);
});

it('can relayout one partial range without affecting other subplots', function(done) {
var rangeX2;
var rangeX3;
var rangeX4;
var autorangeX2;
var autorangeX3;
var autorangeX4;

Plotly.newPlot(gd, {
data: [
{
xaxis: 'x',
yaxis: 'y',
y: [1000, 10, 100, 1],
},
{
xaxis: 'x2',
yaxis: 'y2',
y: [1000, 10, 100, 1],
},
{
xaxis: 'x3',
yaxis: 'y3',
y: [1000, 10, 100, 1],
},
{
xaxis: 'x4',
yaxis: 'y4',
y: [1000, 10, 100, 1],
},
],
layout: {
xaxis: {
range: [-1, null],
anchor: 'y',
domain: [0, 0.45],
},
yaxis: {
anchor: 'x',
domain: [0, 0.45],
side: 'right',
},
xaxis2: {
range: [null, 4],
anchor: 'y2',
domain: [0, 0.45],
},
yaxis2: {
anchor: 'x2',
domain: [0.55, 1],
side: 'left',
},
xaxis3: {
range: [null, -1],
autorange: 'max reversed',
anchor: 'y3',
domain: [0.55, 1],
},
yaxis3: {
anchor: 'x3',
domain: [0, 0.45],
side: 'left',
},
xaxis4: {
range: [4, null],
autorange: 'min reversed',
anchor: 'y4',
domain: [0.55, 1],
},
yaxis4: {
anchor: 'x4',
domain: [0.55, 1],
side: 'right',
}
}
}).then(function() {
rangeX2 = gd._fullLayout.xaxis2.range.slice();
rangeX3 = gd._fullLayout.xaxis3.range.slice();
rangeX4 = gd._fullLayout.xaxis4.range.slice();

autorangeX2 = gd._fullLayout.xaxis2.autorange;
autorangeX3 = gd._fullLayout.xaxis3.autorange;
autorangeX4 = gd._fullLayout.xaxis4.autorange;

return Plotly.relayout(gd, 'xaxis.range', [1, 2]);
}).then(function() {
expect(gd._fullLayout.xaxis2.range).toEqual(rangeX2);
expect(gd._fullLayout.xaxis3.range).toEqual(rangeX3);
expect(gd._fullLayout.xaxis4.range).toEqual(rangeX4);

expect(gd._fullLayout.xaxis2.autorange).toEqual(autorangeX2);
expect(gd._fullLayout.xaxis3.autorange).toEqual(autorangeX3);
expect(gd._fullLayout.xaxis4.autorange).toEqual(autorangeX4);
})
.then(done, done.fail);
});

it('should make room for the inside labels of the counter axes', function(done) {
Plotly.newPlot(gd, {
data: [{
Expand Down

0 comments on commit d828853

Please sign in to comment.