Skip to content
Merged
47 changes: 47 additions & 0 deletions src/plot_api/subroutines.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ exports.lsInner = function(gd) {
ax._mainMirrorPosition = (ax.mirror && counterAx) ?
getLinePosition(ax, counterAx,
alignmentConstants.OPPOSITE_SIDE[ax.side]) : null;

// Figure out which subplot to draw ticks, labels, & axis lines on
// do this as a separate loop so we already have all the
// _mainAxis and _anchorAxis links set
ax._mainSubplot = findMainSubplot(ax, fullLayout);
}

fullLayout._paperdiv
Expand Down Expand Up @@ -324,6 +329,48 @@ exports.lsInner = function(gd) {
return gd._promises.length && Promise.all(gd._promises);
};

function findMainSubplot(ax, fullLayout) {
Copy link
Contributor Author

@etpinard etpinard May 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alexcjohnson I didn't bother making the "find main subplot" algo faster as you proposed in #2549 (comment), I was happy enough with skipping this whole thing except for sploms with showlowerhalf: false with c947b2c

var subplotList = fullLayout._subplots;
var ids = subplotList.cartesian.concat(subplotList.gl2d || []);
var mockGd = {_fullLayout: fullLayout};

var isX = ax._id.charAt(0) === 'x';
var anchorAx = ax._mainAxis._anchorAxis;
var mainSubplotID = '';
var nextBestMainSubplotID = '';
var anchorID = '';

// First try the main ID with the anchor
if(anchorAx) {
anchorID = anchorAx._mainAxis._id;
mainSubplotID = isX ? (ax._id + anchorID) : (anchorID + ax._id);
}

// Then look for a subplot with the counteraxis overlaying the anchor
// If that fails just use the first subplot including this axis
if(!mainSubplotID || !fullLayout._plots[mainSubplotID]) {
mainSubplotID = '';

for(var j = 0; j < ids.length; j++) {
var id = ids[j];
var yIndex = id.indexOf('y');
var idPart = isX ? id.substr(0, yIndex) : id.substr(yIndex);
var counterPart = isX ? id.substr(yIndex) : id.substr(0, yIndex);

if(idPart === ax._id) {
if(!nextBestMainSubplotID) nextBestMainSubplotID = id;
var counterAx = Axes.getFromId(mockGd, counterPart);
if(anchorID && counterAx.overlaying === anchorID) {
mainSubplotID = id;
break;
}
}
}
}

return mainSubplotID || nextBestMainSubplotID;
}

function shouldShowLinesOrTicks(ax, subplot) {
return (ax.ticks || ax.showline) &&
(subplot === ax._mainSubplot || ax.mirror === 'all' || ax.mirror === 'allticks');
Expand Down
37 changes: 0 additions & 37 deletions src/plots/plots.js
Original file line number Diff line number Diff line change
Expand Up @@ -801,43 +801,6 @@ plots.linkSubplots = function(newFullData, newFullLayout, oldFullData, oldFullLa
null :
axisIDs.getFromId(mockGd, ax.anchor);
}

for(i = 0; i < axList.length; i++) {
// Figure out which subplot to draw ticks, labels, & axis lines on
// do this as a separate loop so we already have all the
// _mainAxis and _anchorAxis links set
ax = axList[i];
var isX = ax._id.charAt(0) === 'x';
var anchorAx = ax._mainAxis._anchorAxis;
var mainSubplotID = '';
var nextBestMainSubplotID = '';
var anchorID = '';
// First try the main ID with the anchor
if(anchorAx) {
anchorID = anchorAx._mainAxis._id;
mainSubplotID = isX ? (ax._id + anchorID) : (anchorID + ax._id);
}
// Then look for a subplot with the counteraxis overlaying the anchor
// If that fails just use the first subplot including this axis
if(!mainSubplotID || !newSubplots[mainSubplotID]) {
mainSubplotID = '';
for(j = 0; j < ids.length; j++) {
id = ids[j];
var yIndex = id.indexOf('y');
var idPart = isX ? id.substr(0, yIndex) : id.substr(yIndex);
var counterPart = isX ? id.substr(yIndex) : id.substr(0, yIndex);
if(idPart === ax._id) {
if(!nextBestMainSubplotID) nextBestMainSubplotID = id;
var counterAx = axisIDs.getFromId(mockGd, counterPart);
if(anchorID && counterAx.overlaying === anchorID) {
mainSubplotID = id;
break;
}
}
}
}
ax._mainSubplot = mainSubplotID || nextBestMainSubplotID;
}
};

// This function clears any trace attributes with valType: color and
Expand Down
35 changes: 25 additions & 10 deletions test/jasmine/tests/plot_api_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -643,30 +643,27 @@ describe('Test plot api', function() {
});
}

var trace = {y: [1, 2, 1]};

var specs = [
['relayout', ['xaxis.range[0]', 0]],
['relayout', ['xaxis.range[1]', 3]],
['relayout', ['xaxis.range', [-1, 5]]],
['update', [{}, {'xaxis.range': [-1, 10]}]],
['react', [[trace], {xaxis: {range: [0, 1]}}]]
['update', [{}, {'xaxis.range': [-1, 10]}]]
];

specs.forEach(function(s) {
// create 'real' div for Plotly.react to work
gd = createGraphDiv();
Plotly.plot(gd, [trace], {xaxis: {range: [1, 2]}});
mock(gd);
gd = mock({
data: [{y: [1, 2, 1]}],
layout: {
xaxis: {range: [1, 2]}
}
});

Plotly[s[0]](gd, s[1][0], s[1][1]);

_assert([
'Plotly.', s[0],
'(gd, ', JSON.stringify(s[1][0]), ', ', JSON.stringify(s[1][1]), ')'
].join(''));

destroyGraphDiv();
});
});

Expand Down Expand Up @@ -2773,6 +2770,24 @@ describe('Test plot api', function() {
.then(done);
});

it('picks up minimal sequence for cartesian axis range updates', function(done) {
var data = [{y: [1, 2, 1]}];
var layout = {xaxis: {range: [1, 2]}};
var layout2 = {xaxis: {range: [0, 1]}};

Plotly.newPlot(gd, data, layout)
.then(countPlots)
.then(function() {
return Plotly.react(gd, data, layout2);
})
.then(function() {
expect(subroutines.doTicksRelayout).toHaveBeenCalledTimes(1);
expect(subroutines.layoutStyles).not.toHaveBeenCalled();
})
.catch(failTest)
.then(done);
});

it('redraws annotations one at a time', function(done) {
var data = [{y: [1, 2, 3], mode: 'markers'}];
var layout = {};
Expand Down