Skip to content

Remove internal option layout.autosize='initial' (Fixes #537) #576

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 15 additions & 106 deletions src/plot_api/plot_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -414,10 +414,6 @@ function plotPolar(gd, data, layout) {
if(layout) gd.layout = layout;
Plotly.micropolar.manager.fillLayout(gd);

if(gd._fullLayout.autosize === 'initial' && gd._context.autosizable) {
plotAutoSize(gd, {});
gd._fullLayout.autosize = layout.autosize = true;
}
// resize canvas
paperDiv.style({
width: gd._fullLayout.width + 'px',
Expand Down Expand Up @@ -2158,8 +2154,6 @@ Plotly.relayout = function relayout(gd, astr, val) {
return (fullLayout[axName] || {}).autorange;
}

var hw = ['height', 'width'];

// alter gd.layout
for(var ai in aobj) {
var p = Lib.nestedProperty(layout, ai),
Expand All @@ -2182,14 +2176,8 @@ Plotly.relayout = function relayout(gd, astr, val) {
// op and has no flag.
undoit[ai] = (pleaf === 'reverse') ? vi : p.get();

// check autosize or autorange vs size and range
if(hw.indexOf(ai) !== -1) {
doextra('autosize', false);
}
else if(ai === 'autosize') {
doextra(hw, undefined);
}
else if(pleafPlus.match(/^[xyz]axis[0-9]*\.range(\[[0|1]\])?$/)) {
// check autorange vs range
if(pleafPlus.match(/^[xyz]axis[0-9]*\.range(\[[0|1]\])?$/)) {
doextra(ptrunk + '.autorange', false);
}
else if(pleafPlus.match(/^[xyz]axis[0-9]*\.autorange$/)) {
Expand Down Expand Up @@ -2367,11 +2355,20 @@ Plotly.relayout = function relayout(gd, astr, val) {
Queue.add(gd, relayout, [gd, undoit], relayout, [gd, redoit]);
}

// calculate autosizing - if size hasn't changed,
// will remove h&w so we don't need to redraw
if(aobj.autosize) aobj = plotAutoSize(gd, aobj);
var oldWidth = gd._fullLayout.width,
oldHeight = gd._fullLayout.height;

if(aobj.height || aobj.width || aobj.autosize) docalc = true;
// coerce the updated layout
Plots.supplyDefaults(gd);

// calculate autosizing
if(gd.layout.autosize) Plots.plotAutoSize(gd, gd.layout, gd._fullLayout);

// avoid unnecessary redraws
var changed = aobj.height || aobj.width ||
(gd._fullLayout.width !== oldWidth) ||
(gd._fullLayout.height !== oldHeight);
if(changed) docalc = true;

// redraw
// first check if there's still anything to do
Expand All @@ -2392,7 +2389,6 @@ Plotly.relayout = function relayout(gd, astr, val) {
}
else if(ak.length) {
// if we didn't need to redraw entirely, just do the needed parts
Plots.supplyDefaults(gd);
fullLayout = gd._fullLayout;

if(dolegend) {
Expand Down Expand Up @@ -2500,86 +2496,6 @@ Plotly.purge = function purge(gd) {
return gd;
};

/**
* Reduce all reserved margin objects to a single required margin reservation.
*
* @param {Object} margins
* @returns {{left: number, right: number, bottom: number, top: number}}
*/
function calculateReservedMargins(margins) {
var resultingMargin = {left: 0, right: 0, bottom: 0, top: 0},
marginName;

if(margins) {
for(marginName in margins) {
if(margins.hasOwnProperty(marginName)) {
resultingMargin.left += margins[marginName].left || 0;
resultingMargin.right += margins[marginName].right || 0;
resultingMargin.bottom += margins[marginName].bottom || 0;
resultingMargin.top += margins[marginName].top || 0;
}
}
}
return resultingMargin;
}

function plotAutoSize(gd, aobj) {
var fullLayout = gd._fullLayout,
context = gd._context,
computedStyle;

var newHeight, newWidth;

gd.emit('plotly_autosize');

// embedded in an iframe - just take the full iframe size
// if we get to this point, with no aspect ratio restrictions
if(gd._context.fillFrame) {
newWidth = window.innerWidth;
newHeight = window.innerHeight;

// somehow we get a few extra px height sometimes...
// just hide it
document.body.style.overflow = 'hidden';
}
else if(isNumeric(context.frameMargins) && context.frameMargins > 0) {
var reservedMargins = calculateReservedMargins(gd._boundingBoxMargins),
reservedWidth = reservedMargins.left + reservedMargins.right,
reservedHeight = reservedMargins.bottom + reservedMargins.top,
gdBB = fullLayout._container.node().getBoundingClientRect(),
factor = 1 - 2 * context.frameMargins;

newWidth = Math.round(factor * (gdBB.width - reservedWidth));
newHeight = Math.round(factor * (gdBB.height - reservedHeight));
}
else {
// plotly.js - let the developers do what they want, either
// provide height and width for the container div,
// specify size in layout, or take the defaults,
// but don't enforce any ratio restrictions
computedStyle = window.getComputedStyle(gd);
newHeight = parseFloat(computedStyle.height) || fullLayout.height;
newWidth = parseFloat(computedStyle.width) || fullLayout.width;
}

if(Math.abs(fullLayout.width - newWidth) > 1 ||
Math.abs(fullLayout.height - newHeight) > 1) {
fullLayout.height = gd.layout.height = newHeight;
fullLayout.width = gd.layout.width = newWidth;
}
// if there's no size change, update layout but
// delete the autosize attr so we don't redraw
// but can't call layoutStyles for initial autosize
else if(fullLayout.autosize !== 'initial') {
delete(aobj.autosize);
fullLayout.autosize = gd.layout.autosize = true;
}

Plots.sanitizeMargins(fullLayout);

return aobj;
}

// -------------------------------------------------------
// makePlotFramework: Create the plot container and axes
// -------------------------------------------------------
Expand All @@ -2599,13 +2515,6 @@ function makePlotFramework(gd) {
.classed('svg-container', true)
.style('position', 'relative');

// Initial autosize
if(fullLayout.autosize === 'initial') {
plotAutoSize(gd, {});
fullLayout.autosize = true;
gd.layout.autosize = true;
}

// Make the graph containers
// start fresh each time we get here, so we know the order comes out
// right, rather than enter/exit which can muck up the order
Expand Down
13 changes: 9 additions & 4 deletions src/plots/layout_attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,16 @@ module.exports = {
autosize: {
valType: 'enumerated',
role: 'info',
// TODO: better handling of 'initial'
values: [true, false, 'initial'],
values: [false, true],
dflt: false,
description: [
'Determines whether or not the dimensions of the figure are',
'computed as a function of the display size.'
'Determines whether or not a layout width or height',
'that has been left undefined by the user',
'is initialized on each relayout.',

'Note that, regardless of this attribute,',
'an undefined layout width or height',
'is always initialized on the first call to plot.'
].join(' ')
},
width: {
Expand Down
135 changes: 121 additions & 14 deletions src/plots/plots.js
Original file line number Diff line number Diff line change
Expand Up @@ -287,17 +287,26 @@ plots.resize = function(gd) {
if(gd._redrawTimer) clearTimeout(gd._redrawTimer);

gd._redrawTimer = setTimeout(function() {
if((gd._fullLayout || {}).autosize) {
// autosizing doesn't count as a change that needs saving
var oldchanged = gd.changed;
// return if there is nothing to resize
if(gd.layout.width && gd.layout.height) {
resolve(gd);
return;
}

delete gd._fullLayout._initialAutoSizeIsDone;
if(!gd.layout.width) delete (gd._fullLayout || {}).width;
if(!gd.layout.height) delete (gd._fullLayout || {}).height;

// nor should it be included in the undo queue
gd.autoplay = true;
// autosizing doesn't count as a change that needs saving
var oldchanged = gd.changed;

Plotly.relayout(gd, { autosize: true });
// nor should it be included in the undo queue
gd.autoplay = true;

Plotly.plot(gd).then(function() {
gd.changed = oldchanged;
resolve(gd);
}
});
}, 100);
});
};
Expand Down Expand Up @@ -455,7 +464,7 @@ plots.sendDataToCloud = function(gd) {
plots.supplyDefaults = function(gd) {
var oldFullLayout = gd._fullLayout || {},
newFullLayout = gd._fullLayout = {},
newLayout = gd.layout || {};
layout = gd.layout || {};

var oldFullData = gd._fullData || [],
newFullData = gd._fullData = [],
Expand All @@ -468,7 +477,27 @@ plots.supplyDefaults = function(gd) {

// first fill in what we can of layout without looking at data
// because fullData needs a few things from layout
plots.supplyLayoutGlobalDefaults(newLayout, newFullLayout);

if(oldFullLayout._initialAutoSizeIsDone) {
// coerce the updated layout while preserving width and height
var oldWidth = oldFullLayout.width,
oldHeight = oldFullLayout.height;

plots.supplyLayoutGlobalDefaults(layout, newFullLayout);

if(!layout.width) newFullLayout.width = oldWidth;
if(!layout.height) newFullLayout.height = oldHeight;
}
else {
// coerce the updated layout and autosize if needed
plots.supplyLayoutGlobalDefaults(layout, newFullLayout);

if(!layout.width || !layout.height) {
plots.plotAutoSize(gd, layout, newFullLayout);
}
}

newFullLayout._initialAutoSizeIsDone = true;

// keep track of how many traces are inputted
newFullLayout._dataLength = newData.length;
Expand Down Expand Up @@ -505,7 +534,7 @@ plots.supplyDefaults = function(gd) {
}

// finally, fill in the pieces of layout that may need to look at data
plots.supplyLayoutModuleDefaults(newLayout, newFullLayout, newFullData);
plots.supplyLayoutModuleDefaults(layout, newFullLayout, newFullData);

// TODO remove in v2.0.0
// add has-plot-type refs to fullLayout for backward compatibility
Expand All @@ -522,6 +551,7 @@ plots.supplyDefaults = function(gd) {
// relink functions and _ attributes to promote consistency between plots
relinkPrivateKeys(newFullLayout, oldFullLayout);

// TODO may return a promise
plots.doAutoMargin(gd);

// can't quite figure out how to get rid of this... each axis needs
Expand Down Expand Up @@ -730,11 +760,9 @@ plots.supplyLayoutGlobalDefaults = function(layoutIn, layoutOut) {
color: globalFont.color
});

var autosize = coerce('autosize',
(layoutIn.width && layoutIn.height) ? false : 'initial');
coerce('autosize');
coerce('width');
coerce('height');

coerce('margin.l');
coerce('margin.r');
coerce('margin.t');
Expand All @@ -743,7 +771,7 @@ plots.supplyLayoutGlobalDefaults = function(layoutIn, layoutOut) {
coerce('margin.autoexpand');

// called in plotAutoSize otherwise
if(autosize !== 'initial') plots.sanitizeMargins(layoutOut);
if(layoutOut.width && layoutOut.height) plots.sanitizeMargins(layoutOut);

coerce('paper_bgcolor');

Expand All @@ -752,6 +780,85 @@ plots.supplyLayoutGlobalDefaults = function(layoutIn, layoutOut) {
coerce('smith');
};

plots.plotAutoSize = function plotAutoSize(gd, layout, fullLayout) {
var context = gd._context || {},
frameMargins = context.frameMargins,
newWidth,
newHeight;

if(typeof gd.emit === 'function') gd.emit('plotly_autosize');

// embedded in an iframe - just take the full iframe size
// if we get to this point, with no aspect ratio restrictions
if(context.fillFrame) {
newWidth = window.innerWidth;
newHeight = window.innerHeight;

// somehow we get a few extra px height sometimes...
// just hide it
document.body.style.overflow = 'hidden';
}
else if(isNumeric(frameMargins) && frameMargins > 0) {
var reservedMargins = calculateReservedMargins(gd._boundingBoxMargins),
reservedWidth = reservedMargins.left + reservedMargins.right,
reservedHeight = reservedMargins.bottom + reservedMargins.top,
gdBB = fullLayout._container.node().getBoundingClientRect(),
factor = 1 - 2 * frameMargins;

newWidth = Math.round(factor * (gdBB.width - reservedWidth));
newHeight = Math.round(factor * (gdBB.height - reservedHeight));
}
else {
// plotly.js - let the developers do what they want, either
// provide height and width for the container div,
// specify size in layout, or take the defaults,
// but don't enforce any ratio restrictions
var computedStyle;
try {
computedStyle = window.getComputedStyle(gd);
} catch(err) {
computedStyle = {};
}
newWidth = parseFloat(computedStyle.width) || fullLayout.width;
newHeight = parseFloat(computedStyle.height) || fullLayout.height;
}

var widthHasChanged = !layout.width &&
(Math.abs(fullLayout.width - newWidth) > 1),
heightHasChanged = !layout.height &&
(Math.abs(fullLayout.height - newHeight) > 1);

if(heightHasChanged || widthHasChanged) {
if(widthHasChanged) fullLayout.width = newWidth;
if(heightHasChanged) fullLayout.height = newHeight;

plots.sanitizeMargins(fullLayout);
}
};

/**
* Reduce all reserved margin objects to a single required margin reservation.
*
* @param {Object} margins
* @returns {{left: number, right: number, bottom: number, top: number}}
*/
function calculateReservedMargins(margins) {
var resultingMargin = {left: 0, right: 0, bottom: 0, top: 0},
marginName;

if(margins) {
for(marginName in margins) {
if(margins.hasOwnProperty(marginName)) {
resultingMargin.left += margins[marginName].left || 0;
resultingMargin.right += margins[marginName].right || 0;
resultingMargin.bottom += margins[marginName].bottom || 0;
resultingMargin.top += margins[marginName].top || 0;
}
}
}
return resultingMargin;
}

plots.supplyLayoutModuleDefaults = function(layoutIn, layoutOut, fullData) {
var i, _module;

Expand Down
Binary file modified test/image/baselines/ternary_simple.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 1 addition & 2 deletions test/image/mocks/ternary_simple.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
"bgcolor": "#eee"
},
"height": 450,
"width": 700,
"autosize": true
"width": 700
}
}
Loading