@@ -1193,8 +1193,7 @@ Plotly.restyle = function restyle(gd, astr, val, traces) {
11931193 gd = helpers . getGraphDiv ( gd ) ;
11941194 helpers . clearPromiseQueue ( gd ) ;
11951195
1196- var i , fullLayout = gd . _fullLayout ,
1197- aobj = { } ;
1196+ var aobj = { } ;
11981197
11991198 if ( typeof astr === 'string' ) aobj [ astr ] = val ;
12001199 else if ( Lib . isPlainObject ( astr ) ) {
@@ -1208,10 +1207,71 @@ Plotly.restyle = function restyle(gd, astr, val, traces) {
12081207
12091208 if ( Object . keys ( aobj ) . length ) gd . changed = true ;
12101209
1210+ var specs = _restyle ( gd , aobj , traces ) ,
1211+ flags = specs . flags ;
1212+
1213+ // clear calcdata if required
1214+ if ( flags . clearCalc ) gd . calcdata = undefined ;
1215+
1216+ // fill in redraw sequence
1217+ var seq = [ ] ;
1218+
1219+ if ( flags . fullReplot ) {
1220+ seq . push ( Plotly . plot ) ;
1221+ }
1222+ else {
1223+ seq . push ( Plots . previousPromises ) ;
1224+
1225+ Plots . supplyDefaults ( gd ) ;
1226+
1227+ if ( flags . dostyle ) seq . push ( subroutines . doTraceStyle ) ;
1228+ if ( flags . docolorbars ) seq . push ( subroutines . doColorBars ) ;
1229+ }
1230+
1231+ Queue . add ( gd ,
1232+ restyle , [ gd , specs . undoit , specs . traces ] ,
1233+ restyle , [ gd , specs . redoit , specs . traces ]
1234+ ) ;
1235+
1236+ var plotDone = Lib . syncOrAsync ( seq , gd ) ;
1237+ if ( ! plotDone || ! plotDone . then ) plotDone = Promise . resolve ( ) ;
1238+
1239+ return plotDone . then ( function ( ) {
1240+ gd . emit ( 'plotly_restyle' , specs . eventData ) ;
1241+ return gd ;
1242+ } ) ;
1243+ } ;
1244+
1245+ function _restyle ( gd , aobj , traces ) {
1246+ var fullLayout = gd . _fullLayout ,
1247+ fullData = gd . _fullData ,
1248+ data = gd . data ,
1249+ i ;
1250+
1251+ // fill up traces
12111252 if ( isNumeric ( traces ) ) traces = [ traces ] ;
12121253 else if ( ! Array . isArray ( traces ) || ! traces . length ) {
1213- traces = gd . data . map ( function ( v , i ) { return i ; } ) ;
1214- }
1254+ traces = data . map ( function ( _ , i ) { return i ; } ) ;
1255+ }
1256+
1257+ // initialize flags
1258+ var flags = {
1259+ docalc : false ,
1260+ docalcAutorange : false ,
1261+ doplot : false ,
1262+ dostyle : false ,
1263+ docolorbars : false ,
1264+ autorangeOn : false ,
1265+ clearCalc : false ,
1266+ fullReplot : false
1267+ } ;
1268+
1269+ // copies of the change (and previous values of anything affected)
1270+ // for the undo / redo queue
1271+ var redoit = { } ,
1272+ undoit = { } ,
1273+ axlist ,
1274+ flagAxForDelete = { } ;
12151275
12161276 // recalcAttrs attributes need a full regeneration of calcdata
12171277 // as well as a replot, because the right objects may not exist,
@@ -1251,8 +1311,9 @@ Plotly.restyle = function restyle(gd, astr, val, traces) {
12511311 'line.showscale' , 'line.cauto' , 'line.autocolorscale' , 'line.reversescale' ,
12521312 'marker.line.showscale' , 'marker.line.cauto' , 'marker.line.autocolorscale' , 'marker.line.reversescale'
12531313 ] ;
1314+
12541315 for ( i = 0 ; i < traces . length ; i ++ ) {
1255- if ( Registry . traceIs ( gd . _fullData [ traces [ i ] ] , 'box' ) ) {
1316+ if ( Registry . traceIs ( fullData [ traces [ i ] ] , 'box' ) ) {
12561317 recalcAttrs . push ( 'name' ) ;
12571318 break ;
12581319 }
@@ -1266,6 +1327,7 @@ Plotly.restyle = function restyle(gd, astr, val, traces) {
12661327 'marker' , 'marker.size' , 'textfont' ,
12671328 'boxpoints' , 'jitter' , 'pointpos' , 'whiskerwidth' , 'boxmean'
12681329 ] ;
1330+
12691331 // replotAttrs attributes need a replot (because different
12701332 // objects need to be made) but not a recalc
12711333 var replotAttrs = [
@@ -1286,24 +1348,16 @@ Plotly.restyle = function restyle(gd, astr, val, traces) {
12861348 'type' , 'x' , 'y' , 'x0' , 'y0' , 'orientation' , 'xaxis' , 'yaxis'
12871349 ] ;
12881350
1289- // flags for which kind of update we need to do
1290- var docalc = false ,
1291- docalcAutorange = false ,
1292- doplot = false ,
1293- dostyle = false ,
1294- docolorbars = false ;
1295- // copies of the change (and previous values of anything affected)
1296- // for the undo / redo queue
1297- var redoit = { } ,
1298- undoit = { } ,
1299- axlist ,
1300- flagAxForDelete = { } ;
1351+ var zscl = [ 'zmin' , 'zmax' ] ,
1352+ xbins = [ 'xbins.start' , 'xbins.end' , 'xbins.size' ] ,
1353+ ybins = [ 'ybins.start' , 'ybins.end' , 'ybins.size' ] ,
1354+ contourAttrs = [ 'contours.start' , 'contours.end' , 'contours.size' ] ;
13011355
13021356 // At the moment, only cartesian, pie and ternary plot types can afford
13031357 // to not go through a full replot
13041358 var doPlotWhiteList = [ 'cartesian' , 'pie' , 'ternary' ] ;
13051359 fullLayout . _basePlotModules . forEach ( function ( _module ) {
1306- if ( doPlotWhiteList . indexOf ( _module . name ) === - 1 ) docalc = true ;
1360+ if ( doPlotWhiteList . indexOf ( _module . name ) === - 1 ) flags . docalc = true ;
13071361 } ) ;
13081362
13091363 // make a new empty vals array for undoit
@@ -1312,9 +1366,11 @@ Plotly.restyle = function restyle(gd, astr, val, traces) {
13121366 // for autoranging multiple axes
13131367 function addToAxlist ( axid ) {
13141368 var axName = Plotly . Axes . id2name ( axid ) ;
1315- if ( axlist . indexOf ( axName ) === - 1 ) { axlist . push ( axName ) ; }
1369+ if ( axlist . indexOf ( axName ) === - 1 ) axlist . push ( axName ) ;
13161370 }
1371+
13171372 function autorangeAttr ( axName ) { return 'LAYOUT' + axName + '.autorange' ; }
1373+
13181374 function rangeAttr ( axName ) { return 'LAYOUT' + axName + '.range' ; }
13191375
13201376 // for attrs that interact (like scales & autoscales), save the
@@ -1334,7 +1390,7 @@ Plotly.restyle = function restyle(gd, astr, val, traces) {
13341390 if ( attr . substr ( 0 , 6 ) === 'LAYOUT' ) {
13351391 extraparam = Lib . nestedProperty ( gd . layout , attr . replace ( 'LAYOUT' , '' ) ) ;
13361392 } else {
1337- extraparam = Lib . nestedProperty ( gd . data [ traces [ i ] ] , attr ) ;
1393+ extraparam = Lib . nestedProperty ( data [ traces [ i ] ] , attr ) ;
13381394 }
13391395
13401396 if ( ! ( attr in undoit ) ) {
@@ -1347,10 +1403,6 @@ Plotly.restyle = function restyle(gd, astr, val, traces) {
13471403 extraparam . set ( val ) ;
13481404 }
13491405 }
1350- var zscl = [ 'zmin' , 'zmax' ] ,
1351- xbins = [ 'xbins.start' , 'xbins.end' , 'xbins.size' ] ,
1352- ybins = [ 'ybins.start' , 'ybins.end' , 'ybins.size' ] ,
1353- contourAttrs = [ 'contours.start' , 'contours.end' , 'contours.size' ] ;
13541406
13551407 // now make the changes to gd.data (and occasionally gd.layout)
13561408 // and figure out what kind of graphics update we need to do
@@ -1361,6 +1413,7 @@ Plotly.restyle = function restyle(gd, astr, val, traces) {
13611413 param ,
13621414 oldVal ,
13631415 newVal ;
1416+
13641417 redoit [ ai ] = vi ;
13651418
13661419 if ( ai . substr ( 0 , 6 ) === 'LAYOUT' ) {
@@ -1371,18 +1424,18 @@ Plotly.restyle = function restyle(gd, astr, val, traces) {
13711424 param . set ( Array . isArray ( vi ) ? vi [ 0 ] : vi ) ;
13721425 // ironically, the layout attrs in restyle only require replot,
13731426 // not relayout
1374- docalc = true ;
1427+ flags . docalc = true ;
13751428 continue ;
13761429 }
13771430
13781431 // take no chances on transforms
1379- if ( ai . substr ( 0 , 10 ) === 'transforms' ) docalc = true ;
1432+ if ( ai . substr ( 0 , 10 ) === 'transforms' ) flags . docalc = true ;
13801433
13811434 // set attribute in gd.data
13821435 undoit [ ai ] = a0 ( ) ;
13831436 for ( i = 0 ; i < traces . length ; i ++ ) {
1384- cont = gd . data [ traces [ i ] ] ;
1385- contFull = gd . _fullData [ traces [ i ] ] ;
1437+ cont = data [ traces [ i ] ] ;
1438+ contFull = fullData [ traces [ i ] ] ;
13861439 param = Lib . nestedProperty ( cont , ai ) ;
13871440 oldVal = param . get ( ) ;
13881441 newVal = Array . isArray ( vi ) ? vi [ i % vi . length ] : vi ;
@@ -1540,19 +1593,19 @@ Plotly.restyle = function restyle(gd, astr, val, traces) {
15401593 // check if we need to call axis type
15411594 if ( ( traces . indexOf ( 0 ) !== - 1 ) && ( axtypeAttrs . indexOf ( ai ) !== - 1 ) ) {
15421595 Plotly . Axes . clearTypes ( gd , traces ) ;
1543- docalc = true ;
1596+ flags . docalc = true ;
15441597 }
15451598
15461599 // switching from auto to manual binning or z scaling doesn't
15471600 // actually do anything but change what you see in the styling
15481601 // box. everything else at least needs to apply styles
15491602 if ( ( [ 'autobinx' , 'autobiny' , 'zauto' ] . indexOf ( ai ) === - 1 ) ||
15501603 newVal !== false ) {
1551- dostyle = true ;
1604+ flags . dostyle = true ;
15521605 }
15531606 if ( [ 'colorbar' , 'line' ] . indexOf ( param . parts [ 0 ] ) !== - 1 ||
15541607 param . parts [ 0 ] === 'marker' && param . parts [ 1 ] === 'colorbar' ) {
1555- docolorbars = true ;
1608+ flags . docolorbars = true ;
15561609 }
15571610
15581611 if ( recalcAttrs . indexOf ( ai ) !== - 1 ) {
@@ -1561,13 +1614,13 @@ Plotly.restyle = function restyle(gd, astr, val, traces) {
15611614 if ( [ 'orientation' , 'type' ] . indexOf ( ai ) !== - 1 ) {
15621615 axlist = [ ] ;
15631616 for ( i = 0 ; i < traces . length ; i ++ ) {
1564- var trace = gd . data [ traces [ i ] ] ;
1617+ var trace = data [ traces [ i ] ] ;
15651618
15661619 if ( Registry . traceIs ( trace , 'cartesian' ) ) {
15671620 addToAxlist ( trace . xaxis || 'x' ) ;
15681621 addToAxlist ( trace . yaxis || 'y' ) ;
15691622
1570- if ( astr === 'type' ) {
1623+ if ( ai === 'type' ) {
15711624 doextra ( [ 'autobinx' , 'autobiny' ] , true , i ) ;
15721625 }
15731626 }
@@ -1576,12 +1629,17 @@ Plotly.restyle = function restyle(gd, astr, val, traces) {
15761629 doextra ( axlist . map ( autorangeAttr ) , true , 0 ) ;
15771630 doextra ( axlist . map ( rangeAttr ) , [ 0 , 1 ] , 0 ) ;
15781631 }
1579- docalc = true ;
1632+ flags . docalc = true ;
15801633 }
1581- else if ( replotAttrs . indexOf ( ai ) !== - 1 ) doplot = true ;
1582- else if ( autorangeAttrs . indexOf ( ai ) !== - 1 ) docalcAutorange = true ;
1634+ else if ( replotAttrs . indexOf ( ai ) !== - 1 ) flags . doplot = true ;
1635+ else if ( autorangeAttrs . indexOf ( ai ) !== - 1 ) flags . docalcAutorange = true ;
15831636 }
15841637
1638+ // do we need to force a recalc?
1639+ Plotly . Axes . list ( gd ) . forEach ( function ( ax ) {
1640+ if ( ax . autorange ) flags . autorangeOn = true ;
1641+ } ) ;
1642+
15851643 // check axes we've flagged for possible deletion
15861644 // flagAxForDelete is a hash so we can make sure we only get each axis once
15871645 var axListForDelete = Object . keys ( flagAxForDelete ) ;
@@ -1590,9 +1648,10 @@ Plotly.restyle = function restyle(gd, astr, val, traces) {
15901648 var axId = axListForDelete [ i ] ,
15911649 axLetter = axId . charAt ( 0 ) ,
15921650 axAttr = axLetter + 'axis' ;
1593- for ( var j = 0 ; j < gd . data . length ; j ++ ) {
1594- if ( Registry . traceIs ( gd . data [ j ] , 'cartesian' ) &&
1595- ( gd . data [ j ] [ axAttr ] || axLetter ) === axId ) {
1651+
1652+ for ( var j = 0 ; j < data . length ; j ++ ) {
1653+ if ( Registry . traceIs ( data [ j ] , 'cartesian' ) &&
1654+ ( data [ j ] [ axAttr ] || axLetter ) === axId ) {
15961655 continue axisLoop;
15971656 }
15981657 }
@@ -1601,83 +1660,21 @@ Plotly.restyle = function restyle(gd, astr, val, traces) {
16011660 doextra ( 'LAYOUT' + Plotly . Axes . id2name ( axId ) , null , 0 ) ;
16021661 }
16031662
1604- // now all attribute mods are done, as are redo and undo
1605- // so we can save them
1606- Queue . add ( gd , restyle , [ gd , undoit , traces ] , restyle , [ gd , redoit , traces ] ) ;
1607-
1608- // do we need to force a recalc?
1609- var autorangeOn = false ;
1610- Plotly . Axes . list ( gd ) . forEach ( function ( ax ) {
1611- if ( ax . autorange ) autorangeOn = true ;
1612- } ) ;
1613- if ( docalc || dolayout || ( docalcAutorange && autorangeOn ) ) {
1614- gd . calcdata = undefined ;
1663+ // combine a few flags together;
1664+ if ( flags . docalc || ( flags . docalcAutorange && flags . autorangeOn ) ) {
1665+ flags . clearCalc = true ;
16151666 }
1616-
1617- // now update the graphics
1618- // a complete layout redraw takes care of plot and
1619- var seq ;
1620- }
1621- else if ( docalc || doplot || docalcAutorange ) {
1622- seq = [ Plotly . plot ] ;
1623- }
1624- else {
1625- Plots . supplyDefaults ( gd ) ;
1626- seq = [ Plots . previousPromises ] ;
1627- if ( dostyle ) {
1628- seq . push ( function doStyle ( ) {
1629- // first see if we need to do arraysToCalcdata
1630- // call it regardless of what change we made, in case
1631- // supplyDefaults brought in an array that was already
1632- // in gd.data but not in gd._fullData previously
1633- var i , cdi , arraysToCalcdata ;
1634- for ( i = 0 ; i < gd . calcdata . length ; i ++ ) {
1635- cdi = gd . calcdata [ i ] ;
1636- arraysToCalcdata = ( ( ( cdi [ 0 ] || { } ) . trace || { } ) . _module || { } ) . arraysToCalcdata ;
1637- if ( arraysToCalcdata ) arraysToCalcdata ( cdi ) ;
1638- }
1639-
1640- Plots . style ( gd ) ;
1641- Registry . getComponentMethod ( 'legend' , 'draw' ) ( gd ) ;
1642-
1643- return Plots . previousPromises ( gd ) ;
1644- } ) ;
1645- }
1646- if ( docolorbars ) {
1647- seq . push ( function doColorBars ( ) {
1648- gd . calcdata . forEach ( function ( cd ) {
1649- if ( ( cd [ 0 ] . t || { } ) . cb ) {
1650- var trace = cd [ 0 ] . trace ,
1651- cb = cd [ 0 ] . t . cb ;
1652-
1653- if ( Registry . traceIs ( trace , 'contour' ) ) {
1654- cb . line ( {
1655- width : trace . contours . showlines !== false ?
1656- trace . line . width : 0 ,
1657- dash : trace . line . dash ,
1658- color : trace . contours . coloring === 'line' ?
1659- cb . _opts . line . color : trace . line . color
1660- } ) ;
1661- }
1662- if ( Registry . traceIs ( trace , 'markerColorscale' ) ) {
1663- cb . options ( trace . marker . colorbar ) ( ) ;
1664- }
1665- else cb . options ( trace . colorbar ) ( ) ;
1666- }
1667- } ) ;
1668- return Plots . previousPromises ( gd ) ;
1669- } ) ;
1670- }
1667+ if ( flags . docalc || flags . doplot || flags . docalcAutorange ) {
1668+ flags . fullReplot = true ;
16711669 }
16721670
1673- var plotDone = Lib . syncOrAsync ( seq , gd ) ;
1674-
1675- if ( ! plotDone || ! plotDone . then ) plotDone = Promise . resolve ( ) ;
1676-
1677- return plotDone . then ( function ( ) {
1678- gd . emit ( 'plotly_restyle' , Lib . extendDeepNoArrays ( [ ] , [ redoit , traces ] ) ) ;
1679- return gd ;
1680- } ) ;
1671+ return {
1672+ flags : flags ,
1673+ undoit : undoit ,
1674+ redoit : redoit ,
1675+ traces : traces ,
1676+ eventData : Lib . extendDeepNoArrays ( [ ] , [ redoit , traces ] )
1677+ } ;
16811678}
16821679
16831680/**
0 commit comments