Skip to content

Commit d828853

Browse files
authored
Merge pull request #6743 from plotly/fix6742-partial-range-interact
Fix range interactions affecting partial ranges in other subplots
2 parents 724bab1 + 3cc3c42 commit d828853

File tree

5 files changed

+155
-50
lines changed

5 files changed

+155
-50
lines changed

draftlogs/6743_fix.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Fix range interactions affecting partial ranges in other subplots [[#6743](https://github.com/plotly/plotly.js/pull/6743)]

src/plot_api/plot_api.js

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ var PlotSchema = require('./plot_schema');
1515
var Plots = require('../plots/plots');
1616

1717
var Axes = require('../plots/cartesian/axes');
18+
var handleRangeDefaults = require('../plots/cartesian/range_defaults');
19+
20+
var cartesianLayoutAttributes = require('../plots/cartesian/layout_attributes');
1821
var Drawing = require('../components/drawing');
1922
var Color = require('../components/color');
2023
var initInteractions = require('../plots/cartesian/graph_interact').initInteractions;
@@ -1838,26 +1841,19 @@ function axRangeSupplyDefaultsByPass(gd, flags, specs) {
18381841
if(k !== 'axrange' && flags[k]) return false;
18391842
}
18401843

1844+
var axIn, axOut;
1845+
var coerce = function(attr, dflt) {
1846+
return Lib.coerce(axIn, axOut, cartesianLayoutAttributes, attr, dflt);
1847+
};
1848+
1849+
var options = {}; // passing empty options for now!
1850+
18411851
for(var axId in specs.rangesAltered) {
18421852
var axName = Axes.id2name(axId);
1843-
var axIn = gd.layout[axName];
1844-
var axOut = fullLayout[axName];
1845-
axOut.autorange = axIn.autorange;
1853+
axIn = gd.layout[axName];
1854+
axOut = fullLayout[axName];
18461855

1847-
var r0 = axOut._rangeInitial0;
1848-
var r1 = axOut._rangeInitial1;
1849-
// partial range needs supplyDefaults
1850-
if(
1851-
(r0 === undefined && r1 !== undefined) ||
1852-
(r0 !== undefined && r1 === undefined)
1853-
) {
1854-
return false;
1855-
}
1856-
1857-
if(axIn.range) {
1858-
axOut.range = axIn.range.slice();
1859-
}
1860-
axOut.cleanRange();
1856+
handleRangeDefaults(axIn, axOut, coerce, options);
18611857

18621858
if(axOut._matchGroup) {
18631859
for(var axId2 in axOut._matchGroup) {

src/plots/cartesian/axis_defaults.js

Lines changed: 2 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ var handleTickLabelDefaults = require('./tick_label_defaults');
1515
var handlePrefixSuffixDefaults = require('./prefix_suffix_defaults');
1616
var handleCategoryOrderDefaults = require('./category_order_defaults');
1717
var handleLineGridDefaults = require('./line_grid_defaults');
18-
var handleAutorangeOptionsDefaults = require('./autorange_options_defaults');
18+
var handleRangeDefaults = require('./range_defaults');
1919
var setConvert = require('./set_convert');
2020

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

9393
setConvert(containerOut, layoutOut);
9494

95-
coerce('minallowed');
96-
coerce('maxallowed');
97-
var range = coerce('range');
98-
var autorangeDflt = containerOut.getAutorangeDflt(range, options);
99-
var autorange = coerce('autorange', autorangeDflt);
100-
101-
var shouldAutorange;
102-
103-
// validate range and set autorange true for invalid partial ranges
104-
if(range && (
105-
(range[0] === null && range[1] === null) ||
106-
((range[0] === null || range[1] === null) && (autorange === 'reversed' || autorange === true)) ||
107-
(range[0] !== null && (autorange === 'min' || autorange === 'max reversed')) ||
108-
(range[1] !== null && (autorange === 'max' || autorange === 'min reversed'))
109-
)) {
110-
range = undefined;
111-
delete containerOut.range;
112-
containerOut.autorange = true;
113-
shouldAutorange = true;
114-
}
115-
116-
if(!shouldAutorange) {
117-
autorangeDflt = containerOut.getAutorangeDflt(range, options);
118-
autorange = coerce('autorange', autorangeDflt);
119-
}
120-
121-
if(autorange) {
122-
handleAutorangeOptionsDefaults(coerce, autorange, range);
123-
if(axType === 'linear' || axType === '-') coerce('rangemode');
124-
}
125-
126-
containerOut.cleanRange();
95+
handleRangeDefaults(containerIn, containerOut, coerce, options);
12796

12897
handleCategoryOrderDefaults(containerIn, containerOut, coerce, options);
12998

src/plots/cartesian/range_defaults.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
'use strict';
2+
3+
var handleAutorangeOptionsDefaults = require('./autorange_options_defaults');
4+
5+
module.exports = function handleRangeDefaults(containerIn, containerOut, coerce, options) {
6+
var axTemplate = containerOut._template || {};
7+
var axType = containerOut.type || axTemplate.type || '-';
8+
9+
coerce('minallowed');
10+
coerce('maxallowed');
11+
12+
var range = coerce('range');
13+
var autorangeDflt = containerOut.getAutorangeDflt(range, options);
14+
var autorange = coerce('autorange', autorangeDflt);
15+
16+
var shouldAutorange;
17+
18+
// validate range and set autorange true for invalid partial ranges
19+
if(range && (
20+
(range[0] === null && range[1] === null) ||
21+
((range[0] === null || range[1] === null) && (autorange === 'reversed' || autorange === true)) ||
22+
(range[0] !== null && (autorange === 'min' || autorange === 'max reversed')) ||
23+
(range[1] !== null && (autorange === 'max' || autorange === 'min reversed'))
24+
)) {
25+
range = undefined;
26+
delete containerOut.range;
27+
containerOut.autorange = true;
28+
shouldAutorange = true;
29+
}
30+
31+
if(!shouldAutorange) {
32+
autorangeDflt = containerOut.getAutorangeDflt(range, options);
33+
autorange = coerce('autorange', autorangeDflt);
34+
}
35+
36+
if(autorange) {
37+
handleAutorangeOptionsDefaults(coerce, autorange, range);
38+
if(axType === 'linear' || axType === '-') coerce('rangemode');
39+
}
40+
41+
containerOut.cleanRange();
42+
};

test/jasmine/tests/axes_test.js

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1581,6 +1581,103 @@ describe('Test axes', function() {
15811581
.then(done, done.fail);
15821582
});
15831583

1584+
it('can relayout one partial range without affecting other subplots', function(done) {
1585+
var rangeX2;
1586+
var rangeX3;
1587+
var rangeX4;
1588+
var autorangeX2;
1589+
var autorangeX3;
1590+
var autorangeX4;
1591+
1592+
Plotly.newPlot(gd, {
1593+
data: [
1594+
{
1595+
xaxis: 'x',
1596+
yaxis: 'y',
1597+
y: [1000, 10, 100, 1],
1598+
},
1599+
{
1600+
xaxis: 'x2',
1601+
yaxis: 'y2',
1602+
y: [1000, 10, 100, 1],
1603+
},
1604+
{
1605+
xaxis: 'x3',
1606+
yaxis: 'y3',
1607+
y: [1000, 10, 100, 1],
1608+
},
1609+
{
1610+
xaxis: 'x4',
1611+
yaxis: 'y4',
1612+
y: [1000, 10, 100, 1],
1613+
},
1614+
],
1615+
layout: {
1616+
xaxis: {
1617+
range: [-1, null],
1618+
anchor: 'y',
1619+
domain: [0, 0.45],
1620+
},
1621+
yaxis: {
1622+
anchor: 'x',
1623+
domain: [0, 0.45],
1624+
side: 'right',
1625+
},
1626+
xaxis2: {
1627+
range: [null, 4],
1628+
anchor: 'y2',
1629+
domain: [0, 0.45],
1630+
},
1631+
yaxis2: {
1632+
anchor: 'x2',
1633+
domain: [0.55, 1],
1634+
side: 'left',
1635+
},
1636+
xaxis3: {
1637+
range: [null, -1],
1638+
autorange: 'max reversed',
1639+
anchor: 'y3',
1640+
domain: [0.55, 1],
1641+
},
1642+
yaxis3: {
1643+
anchor: 'x3',
1644+
domain: [0, 0.45],
1645+
side: 'left',
1646+
},
1647+
xaxis4: {
1648+
range: [4, null],
1649+
autorange: 'min reversed',
1650+
anchor: 'y4',
1651+
domain: [0.55, 1],
1652+
},
1653+
yaxis4: {
1654+
anchor: 'x4',
1655+
domain: [0.55, 1],
1656+
side: 'right',
1657+
}
1658+
}
1659+
}).then(function() {
1660+
rangeX2 = gd._fullLayout.xaxis2.range.slice();
1661+
rangeX3 = gd._fullLayout.xaxis3.range.slice();
1662+
rangeX4 = gd._fullLayout.xaxis4.range.slice();
1663+
1664+
autorangeX2 = gd._fullLayout.xaxis2.autorange;
1665+
autorangeX3 = gd._fullLayout.xaxis3.autorange;
1666+
autorangeX4 = gd._fullLayout.xaxis4.autorange;
1667+
1668+
return Plotly.relayout(gd, 'xaxis.range', [1, 2]);
1669+
}).then(function() {
1670+
expect(gd._fullLayout.xaxis2.range).toEqual(rangeX2);
1671+
expect(gd._fullLayout.xaxis3.range).toEqual(rangeX3);
1672+
expect(gd._fullLayout.xaxis4.range).toEqual(rangeX4);
1673+
1674+
expect(gd._fullLayout.xaxis2.autorange).toEqual(autorangeX2);
1675+
expect(gd._fullLayout.xaxis3.autorange).toEqual(autorangeX3);
1676+
expect(gd._fullLayout.xaxis4.autorange).toEqual(autorangeX4);
1677+
})
1678+
.then(done, done.fail);
1679+
});
1680+
15841681
it('should make room for the inside labels of the counter axes', function(done) {
15851682
Plotly.newPlot(gd, {
15861683
data: [{

0 commit comments

Comments
 (0)