10
10
'use strict' ;
11
11
12
12
var d3 = require ( 'd3' ) ;
13
+
14
+ var Registry = require ( '../../registry' ) ;
13
15
var Lib = require ( '../../lib' ) ;
14
16
var Plots = require ( '../plots' ) ;
15
- var getModuleCalcData = require ( '../get_data' ) . getModuleCalcData ;
17
+ var Drawing = require ( '../../components/drawing' ) ;
16
18
19
+ var getModuleCalcData = require ( '../get_data' ) . getModuleCalcData ;
17
20
var axisIds = require ( './axis_ids' ) ;
18
21
var constants = require ( './constants' ) ;
19
22
var xmlnsNamespaces = require ( '../../constants/xmlns_namespaces' ) ;
@@ -129,23 +132,20 @@ exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) {
129
132
// traces are removed
130
133
if ( ! Array . isArray ( traces ) ) {
131
134
traces = [ ] ;
132
-
133
- for ( i = 0 ; i < calcdata . length ; i ++ ) {
134
- traces . push ( i ) ;
135
- }
135
+ for ( i = 0 ; i < calcdata . length ; i ++ ) traces . push ( i ) ;
136
136
}
137
137
138
138
for ( i = 0 ; i < subplots . length ; i ++ ) {
139
- var subplot = subplots [ i ] ,
140
- subplotInfo = fullLayout . _plots [ subplot ] ;
139
+ var subplot = subplots [ i ] ;
140
+ var subplotInfo = fullLayout . _plots [ subplot ] ;
141
141
142
142
// Get all calcdata for this subplot:
143
143
var cdSubplot = [ ] ;
144
144
var pcd ;
145
145
146
146
for ( var j = 0 ; j < calcdata . length ; j ++ ) {
147
- var cd = calcdata [ j ] ,
148
- trace = cd [ 0 ] . trace ;
147
+ var cd = calcdata [ j ] ;
148
+ var trace = cd [ 0 ] . trace ;
149
149
150
150
// Skip trace if whitelist provided and it's not whitelisted:
151
151
// if (Array.isArray(traces) && traces.indexOf(i) === -1) continue;
@@ -182,115 +182,110 @@ exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) {
182
182
} ;
183
183
184
184
function plotOne ( gd , plotinfo , cdSubplot , transitionOpts , makeOnCompleteCallback ) {
185
- var fullLayout = gd . _fullLayout ,
186
- modules = fullLayout . _modules ;
187
-
188
- // remove old traces, then redraw everything
189
- //
190
- // TODO: scatterlayer is manually excluded from this since it knows how
191
- // to update instead of fully removing and redrawing every time. The
192
- // remaining plot traces should also be able to do this. Once implemented,
193
- // we won't need this - which should sometimes be a big speedup.
194
- if ( plotinfo . plot ) {
195
- plotinfo . plot . selectAll ( 'g:not(.scatterlayer):not(.ohlclayer)' ) . selectAll ( 'g.trace' ) . remove ( ) ;
185
+ var traceLayerClasses = constants . traceLayerClasses ;
186
+ var fullLayout = gd . _fullLayout ;
187
+ var modules = fullLayout . _modules ;
188
+ var _module , cdModuleAndOthers , cdModule ;
189
+
190
+ var layerData = [ ] ;
191
+
192
+ for ( var i = 0 ; i < modules . length ; i ++ ) {
193
+ _module = modules [ i ] ;
194
+ var name = _module . name ;
195
+
196
+ if ( Registry . modules [ name ] . categories . svg ) {
197
+ var className = ( _module . layerName || name + 'layer' ) ;
198
+ var plotMethod = _module . plot ;
199
+
200
+ // plot all traces of this type on this subplot at once
201
+ cdModuleAndOthers = getModuleCalcData ( cdSubplot , plotMethod ) ;
202
+ cdModule = cdModuleAndOthers [ 0 ] ;
203
+ // don't need to search the found traces again - in fact we need to NOT
204
+ // so that if two modules share the same plotter we don't double-plot
205
+ cdSubplot = cdModuleAndOthers [ 1 ] ;
206
+
207
+ if ( cdModule . length ) {
208
+ layerData . push ( {
209
+ i : traceLayerClasses . indexOf ( className ) ,
210
+ className : className ,
211
+ plotMethod : plotMethod ,
212
+ cdModule : cdModule
213
+ } ) ;
214
+ }
215
+ }
196
216
}
197
217
198
- // plot all traces for each module at once
199
- for ( var j = 0 ; j < modules . length ; j ++ ) {
200
- var _module = modules [ j ] ;
218
+ layerData . sort ( function ( a , b ) { return a . i - b . i ; } ) ;
219
+
220
+ var layers = plotinfo . plot . selectAll ( 'g.mlayer' )
221
+ . data ( layerData , function ( d ) { return d . className ; } ) ;
201
222
202
- // skip over non-cartesian trace modules
203
- if ( ! _module . plot || _module . basePlotModule . name !== 'cartesian' ) continue ;
223
+ layers . enter ( ) . append ( 'g' )
224
+ . attr ( 'class' , function ( d ) { return d . className ; } )
225
+ . classed ( 'mlayer' , true ) ;
204
226
205
- // plot all traces of this type on this subplot at once
206
- var cdModuleAndOthers = getModuleCalcData ( cdSubplot , _module ) ;
207
- var cdModule = cdModuleAndOthers [ 0 ] ;
208
- // don't need to search the found traces again - in fact we need to NOT
209
- // so that if two modules share the same plotter we don't double-plot
210
- cdSubplot = cdModuleAndOthers [ 1 ] ;
227
+ layers . exit ( ) . remove ( ) ;
211
228
212
- _module . plot ( gd , plotinfo , cdModule , transitionOpts , makeOnCompleteCallback ) ;
229
+ layers . order ( ) ;
230
+
231
+ layers . each ( function ( d ) {
232
+ var sel = d3 . select ( this ) ;
233
+ var className = d . className ;
234
+
235
+ d . plotMethod (
236
+ gd , plotinfo , d . cdModule , sel ,
237
+ transitionOpts , makeOnCompleteCallback
238
+ ) ;
239
+
240
+ // layers that allow `cliponaxis: false`
241
+ if ( className !== 'scatterlayer' && className !== 'barlayer' ) {
242
+ Drawing . setClipUrl ( sel , plotinfo . layerClipId ) ;
243
+ }
244
+ } ) ;
245
+
246
+ // call Scattergl.plot separately
247
+ if ( fullLayout . _has ( 'scattergl' ) ) {
248
+ _module = Registry . getModule ( 'scattergl' ) ;
249
+ cdModule = getModuleCalcData ( cdSubplot , _module ) [ 0 ] ;
250
+ _module . plot ( gd , plotinfo , cdModule ) ;
213
251
}
214
252
}
215
253
216
254
exports . clean = function ( newFullData , newFullLayout , oldFullData , oldFullLayout ) {
217
- var oldModules = oldFullLayout . _modules || [ ] ;
218
- var newModules = newFullLayout . _modules || [ ] ;
219
255
var oldPlots = oldFullLayout . _plots || { } ;
220
-
221
- var hadScatter , hasScatter ;
222
- var hadOHLC , hasOHLC ;
223
- var hadGl , hasGl ;
224
- var i , k , subplotInfo , moduleName ;
256
+ var newPlots = newFullLayout . _plots || { } ;
257
+ var oldSubplotList = oldFullLayout . _subplots || { } ;
258
+ var plotinfo ;
259
+ var i , k ;
225
260
226
261
// when going from a large splom graph to something else,
227
262
// we need to clear <g subplot> so that the new cartesian subplot
228
263
// can have the correct layer ordering
229
264
if ( oldFullLayout . _hasOnlyLargeSploms && ! newFullLayout . _hasOnlyLargeSploms ) {
230
265
for ( k in oldPlots ) {
231
- subplotInfo = oldPlots [ k ] ;
232
- if ( subplotInfo . plotgroup ) subplotInfo . plotgroup . remove ( ) ;
266
+ plotinfo = oldPlots [ k ] ;
267
+ if ( plotinfo . plotgroup ) plotinfo . plotgroup . remove ( ) ;
233
268
}
234
269
}
235
270
236
- for ( i = 0 ; i < oldModules . length ; i ++ ) {
237
- moduleName = oldModules [ i ] . name ;
238
- if ( moduleName === 'scatter' ) hadScatter = true ;
239
- else if ( moduleName === 'scattergl' ) hadGl = true ;
240
- else if ( moduleName === 'ohlc' ) hadOHLC = true ;
241
- }
242
-
243
- for ( i = 0 ; i < newModules . length ; i ++ ) {
244
- moduleName = newModules [ i ] . name ;
245
- if ( moduleName === 'scatter' ) hasScatter = true ;
246
- else if ( moduleName === 'scattergl' ) hasGl = true ;
247
- else if ( moduleName === 'ohlc' ) hasOHLC = true ;
248
- }
249
-
250
- var layersToEmpty = [ ] ;
251
- if ( hadScatter && ! hasScatter ) layersToEmpty . push ( 'g.scatterlayer' ) ;
252
- if ( hadOHLC && ! hasOHLC ) layersToEmpty . push ( 'g.ohlclayer' ) ;
253
-
254
- if ( layersToEmpty . length ) {
255
- for ( var layeri = 0 ; layeri < layersToEmpty . length ; layeri ++ ) {
256
- for ( k in oldPlots ) {
257
- subplotInfo = oldPlots [ k ] ;
258
- if ( subplotInfo . plot ) {
259
- subplotInfo . plot . select ( layersToEmpty [ layeri ] )
260
- . selectAll ( 'g.trace' )
261
- . remove ( ) ;
262
- }
263
- }
264
-
265
- oldFullLayout . _infolayer . selectAll ( 'g.rangeslider-container' )
266
- . select ( layersToEmpty [ layeri ] )
267
- . selectAll ( 'g.trace' )
268
- . remove ( ) ;
269
- }
270
- }
271
+ var hadGl = ( oldFullLayout . _has && oldFullLayout . _has ( 'gl' ) ) ;
272
+ var hasGl = ( newFullLayout . _has && newFullLayout . _has ( 'gl' ) ) ;
271
273
272
274
if ( hadGl && ! hasGl ) {
273
275
for ( k in oldPlots ) {
274
- subplotInfo = oldPlots [ k ] ;
275
-
276
- if ( subplotInfo . _scene ) {
277
- subplotInfo . _scene . destroy ( ) ;
278
- }
276
+ plotinfo = oldPlots [ k ] ;
277
+ if ( plotinfo . _scene ) plotinfo . _scene . destroy ( ) ;
279
278
}
280
279
}
281
280
282
- var oldSubplotList = oldFullLayout . _subplots || { } ;
283
- var newSubplotList = newFullLayout . _subplots || { xaxis : [ ] , yaxis : [ ] } ;
284
-
285
281
// delete any titles we don't need anymore
286
282
// check if axis list has changed, and if so clear old titles
287
283
if ( oldSubplotList . xaxis && oldSubplotList . yaxis ) {
288
- var oldAxIDs = oldSubplotList . xaxis . concat ( oldSubplotList . yaxis ) ;
289
- var newAxIDs = newSubplotList . xaxis . concat ( newSubplotList . yaxis ) ;
290
-
284
+ var oldAxIDs = axisIds . listIds ( { _fullLayout : oldFullLayout } ) ;
291
285
for ( i = 0 ; i < oldAxIDs . length ; i ++ ) {
292
- if ( newAxIDs . indexOf ( oldAxIDs [ i ] ) === - 1 ) {
293
- oldFullLayout . _infolayer . selectAll ( '.g-' + oldAxIDs [ i ] + 'title' ) . remove ( ) ;
286
+ var oldAxId = oldAxIDs [ i ] ;
287
+ if ( ! newFullLayout [ axisIds . id2name ( oldAxId ) ] ) {
288
+ oldFullLayout . _infolayer . selectAll ( '.g-' + oldAxId + 'title' ) . remove ( ) ;
294
289
}
295
290
}
296
291
}
@@ -308,7 +303,7 @@ exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout)
308
303
else if ( oldSubplotList . cartesian ) {
309
304
for ( i = 0 ; i < oldSubplotList . cartesian . length ; i ++ ) {
310
305
var oldSubplotId = oldSubplotList . cartesian [ i ] ;
311
- if ( newSubplotList . cartesian . indexOf ( oldSubplotId ) === - 1 ) {
306
+ if ( ! newPlots [ oldSubplotId ] ) {
312
307
var selector = '.' + oldSubplotId + ',.' + oldSubplotId + '-x,.' + oldSubplotId + '-y' ;
313
308
oldFullLayout . _cartesianlayer . selectAll ( selector ) . remove ( ) ;
314
309
removeSubplotExtras ( oldSubplotId , oldFullLayout ) ;
@@ -482,10 +477,6 @@ function makeSubplotLayer(gd, plotinfo) {
482
477
ensureSingleAndAddDatum ( plotinfo . gridlayer , 'g' , plotinfo . xaxis . _id ) ;
483
478
ensureSingleAndAddDatum ( plotinfo . gridlayer , 'g' , plotinfo . yaxis . _id ) ;
484
479
plotinfo . gridlayer . selectAll ( 'g' ) . sort ( axisIds . idSort ) ;
485
-
486
- for ( var i = 0 ; i < constants . traceLayerClasses . length ; i ++ ) {
487
- ensureSingle ( plotinfo . plot , 'g' , constants . traceLayerClasses [ i ] ) ;
488
- }
489
480
}
490
481
491
482
plotinfo . xlines
@@ -516,11 +507,8 @@ function purgeSubplotLayers(layers, fullLayout) {
516
507
517
508
// must remove overlaid subplot trace layers 'manually'
518
509
519
- var subplots = fullLayout . _plots ;
520
- var subplotIds = Object . keys ( subplots ) ;
521
-
522
- for ( var i = 0 ; i < subplotIds . length ; i ++ ) {
523
- var subplotInfo = subplots [ subplotIds [ i ] ] ;
510
+ for ( var k in fullLayout . _plots ) {
511
+ var subplotInfo = fullLayout . _plots [ k ] ;
524
512
var overlays = subplotInfo . overlays || [ ] ;
525
513
526
514
for ( var j = 0 ; j < overlays . length ; j ++ ) {
0 commit comments