@@ -409,6 +409,10 @@ function plotPolar(gd, data, layout) {
409
409
if ( layout ) gd . layout = layout ;
410
410
Plotly . micropolar . manager . fillLayout ( gd ) ;
411
411
412
+ if ( gd . _fullLayout . autosize === 'initial' && gd . _context . autosizable ) {
413
+ plotAutoSize ( gd , { } ) ;
414
+ gd . _fullLayout . autosize = layout . autosize = true ;
415
+ }
412
416
// resize canvas
413
417
paperDiv . style ( {
414
418
width : gd . _fullLayout . width + 'px' ,
@@ -2144,6 +2148,8 @@ Plotly.relayout = function relayout(gd, astr, val) {
2144
2148
return ( fullLayout [ axName ] || { } ) . autorange ;
2145
2149
}
2146
2150
2151
+ var hw = [ 'height' , 'width' ] ;
2152
+
2147
2153
// alter gd.layout
2148
2154
for ( var ai in aobj ) {
2149
2155
var p = Lib . nestedProperty ( layout , ai ) ,
@@ -2166,8 +2172,14 @@ Plotly.relayout = function relayout(gd, astr, val) {
2166
2172
// op and has no flag.
2167
2173
undoit [ ai ] = ( pleaf === 'reverse' ) ? vi : p . get ( ) ;
2168
2174
2169
- // check autorange vs range
2170
- if ( pleafPlus . match ( / ^ [ x y z ] a x i s [ 0 - 9 ] * \. r a n g e ( \[ [ 0 | 1 ] \] ) ? $ / ) ) {
2175
+ // check autosize or autorange vs size and range
2176
+ if ( hw . indexOf ( ai ) !== - 1 ) {
2177
+ doextra ( 'autosize' , false ) ;
2178
+ }
2179
+ else if ( ai === 'autosize' ) {
2180
+ doextra ( hw , undefined ) ;
2181
+ }
2182
+ else if ( pleafPlus . match ( / ^ [ x y z ] a x i s [ 0 - 9 ] * \. r a n g e ( \[ [ 0 | 1 ] \] ) ? $ / ) ) {
2171
2183
doextra ( ptrunk + '.autorange' , false ) ;
2172
2184
}
2173
2185
else if ( pleafPlus . match ( / ^ [ x y z ] a x i s [ 0 - 9 ] * \. a u t o r a n g e $ / ) ) {
@@ -2346,20 +2358,11 @@ Plotly.relayout = function relayout(gd, astr, val) {
2346
2358
Queue . add ( gd , relayout , [ gd , undoit ] , relayout , [ gd , redoit ] ) ;
2347
2359
}
2348
2360
2349
- var oldWidth = gd . _fullLayout . width ,
2350
- oldHeight = gd . _fullLayout . height ;
2361
+ // calculate autosizing - if size hasn't changed,
2362
+ // will remove h&w so we don't need to redraw
2363
+ if ( aobj . autosize ) aobj = plotAutoSize ( gd , aobj ) ;
2351
2364
2352
- // coerce the updated layout
2353
- Plots . supplyDefaults ( gd ) ;
2354
-
2355
- // calculate autosizing
2356
- if ( gd . layout . autosize ) Plots . plotAutoSize ( gd , gd . layout , gd . _fullLayout ) ;
2357
-
2358
- // avoid unnecessary redraws
2359
- var changed = aobj . height || aobj . width ||
2360
- ( gd . _fullLayout . width !== oldWidth ) ||
2361
- ( gd . _fullLayout . height !== oldHeight ) ;
2362
- if ( changed ) docalc = true ;
2365
+ if ( aobj . height || aobj . width || aobj . autosize ) docalc = true ;
2363
2366
2364
2367
// redraw
2365
2368
// first check if there's still anything to do
@@ -2380,6 +2383,7 @@ Plotly.relayout = function relayout(gd, astr, val) {
2380
2383
}
2381
2384
else if ( ak . length ) {
2382
2385
// if we didn't need to redraw entirely, just do the needed parts
2386
+ Plots . supplyDefaults ( gd ) ;
2383
2387
fullLayout = gd . _fullLayout ;
2384
2388
2385
2389
if ( dolegend ) {
@@ -2488,6 +2492,86 @@ Plotly.purge = function purge(gd) {
2488
2492
return gd ;
2489
2493
} ;
2490
2494
2495
+ /**
2496
+ * Reduce all reserved margin objects to a single required margin reservation.
2497
+ *
2498
+ * @param {Object } margins
2499
+ * @returns {{left: number, right: number, bottom: number, top: number} }
2500
+ */
2501
+ function calculateReservedMargins ( margins ) {
2502
+ var resultingMargin = { left : 0 , right : 0 , bottom : 0 , top : 0 } ,
2503
+ marginName ;
2504
+
2505
+ if ( margins ) {
2506
+ for ( marginName in margins ) {
2507
+ if ( margins . hasOwnProperty ( marginName ) ) {
2508
+ resultingMargin . left += margins [ marginName ] . left || 0 ;
2509
+ resultingMargin . right += margins [ marginName ] . right || 0 ;
2510
+ resultingMargin . bottom += margins [ marginName ] . bottom || 0 ;
2511
+ resultingMargin . top += margins [ marginName ] . top || 0 ;
2512
+ }
2513
+ }
2514
+ }
2515
+ return resultingMargin ;
2516
+ }
2517
+
2518
+ function plotAutoSize ( gd , aobj ) {
2519
+ var fullLayout = gd . _fullLayout ,
2520
+ context = gd . _context ,
2521
+ computedStyle ;
2522
+
2523
+ var newHeight , newWidth ;
2524
+
2525
+ gd . emit ( 'plotly_autosize' ) ;
2526
+
2527
+ // embedded in an iframe - just take the full iframe size
2528
+ // if we get to this point, with no aspect ratio restrictions
2529
+ if ( gd . _context . fillFrame ) {
2530
+ newWidth = window . innerWidth ;
2531
+ newHeight = window . innerHeight ;
2532
+
2533
+ // somehow we get a few extra px height sometimes...
2534
+ // just hide it
2535
+ document . body . style . overflow = 'hidden' ;
2536
+ }
2537
+ else if ( isNumeric ( context . frameMargins ) && context . frameMargins > 0 ) {
2538
+ var reservedMargins = calculateReservedMargins ( gd . _boundingBoxMargins ) ,
2539
+ reservedWidth = reservedMargins . left + reservedMargins . right ,
2540
+ reservedHeight = reservedMargins . bottom + reservedMargins . top ,
2541
+ gdBB = fullLayout . _container . node ( ) . getBoundingClientRect ( ) ,
2542
+ factor = 1 - 2 * context . frameMargins ;
2543
+
2544
+ newWidth = Math . round ( factor * ( gdBB . width - reservedWidth ) ) ;
2545
+ newHeight = Math . round ( factor * ( gdBB . height - reservedHeight ) ) ;
2546
+ }
2547
+ else {
2548
+ // plotly.js - let the developers do what they want, either
2549
+ // provide height and width for the container div,
2550
+ // specify size in layout, or take the defaults,
2551
+ // but don't enforce any ratio restrictions
2552
+ computedStyle = window . getComputedStyle ( gd ) ;
2553
+ newHeight = parseFloat ( computedStyle . height ) || fullLayout . height ;
2554
+ newWidth = parseFloat ( computedStyle . width ) || fullLayout . width ;
2555
+ }
2556
+
2557
+ if ( Math . abs ( fullLayout . width - newWidth ) > 1 ||
2558
+ Math . abs ( fullLayout . height - newHeight ) > 1 ) {
2559
+ fullLayout . height = gd . layout . height = newHeight ;
2560
+ fullLayout . width = gd . layout . width = newWidth ;
2561
+ }
2562
+ // if there's no size change, update layout but
2563
+ // delete the autosize attr so we don't redraw
2564
+ // but can't call layoutStyles for initial autosize
2565
+ else if ( fullLayout . autosize !== 'initial' ) {
2566
+ delete ( aobj . autosize ) ;
2567
+ fullLayout . autosize = gd . layout . autosize = true ;
2568
+ }
2569
+
2570
+ Plots . sanitizeMargins ( fullLayout ) ;
2571
+
2572
+ return aobj ;
2573
+ }
2574
+
2491
2575
// -------------------------------------------------------
2492
2576
// makePlotFramework: Create the plot container and axes
2493
2577
// -------------------------------------------------------
@@ -2507,6 +2591,13 @@ function makePlotFramework(gd) {
2507
2591
. classed ( 'svg-container' , true )
2508
2592
. style ( 'position' , 'relative' ) ;
2509
2593
2594
+ // Initial autosize
2595
+ if ( fullLayout . autosize === 'initial' ) {
2596
+ plotAutoSize ( gd , { } ) ;
2597
+ fullLayout . autosize = true ;
2598
+ gd . layout . autosize = true ;
2599
+ }
2600
+
2510
2601
// Make the graph containers
2511
2602
// start fresh each time we get here, so we know the order comes out
2512
2603
// right, rather than enter/exit which can muck up the order
0 commit comments