1010'use strict' ;
1111
1212var d3 = require ( 'd3' ) ;
13+
14+ var Registry = require ( '../../registry' ) ;
1315var Lib = require ( '../../lib' ) ;
1416var Plots = require ( '../plots' ) ;
15- var getModuleCalcData = require ( '../get_data' ) . getModuleCalcData ;
17+ var Drawing = require ( '../../components/drawing' ) ;
1618
19+ var getModuleCalcData = require ( '../get_data' ) . getModuleCalcData ;
1720var axisIds = require ( './axis_ids' ) ;
1821var constants = require ( './constants' ) ;
1922var xmlnsNamespaces = require ( '../../constants/xmlns_namespaces' ) ;
@@ -129,23 +132,20 @@ exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) {
129132 // traces are removed
130133 if ( ! Array . isArray ( traces ) ) {
131134 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 ) ;
136136 }
137137
138138 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 ] ;
141141
142142 // Get all calcdata for this subplot:
143143 var cdSubplot = [ ] ;
144144 var pcd ;
145145
146146 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 ;
149149
150150 // Skip trace if whitelist provided and it's not whitelisted:
151151 // if (Array.isArray(traces) && traces.indexOf(i) === -1) continue;
@@ -182,115 +182,110 @@ exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) {
182182} ;
183183
184184function 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+ }
196216 }
197217
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 ; } ) ;
201222
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 ) ;
204226
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 ( ) ;
211228
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 ) ;
213251 }
214252}
215253
216254exports . clean = function ( newFullData , newFullLayout , oldFullData , oldFullLayout ) {
217- var oldModules = oldFullLayout . _modules || [ ] ;
218- var newModules = newFullLayout . _modules || [ ] ;
219255 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 ;
225260
226261 // when going from a large splom graph to something else,
227262 // we need to clear <g subplot> so that the new cartesian subplot
228263 // can have the correct layer ordering
229264 if ( oldFullLayout . _hasOnlyLargeSploms && ! newFullLayout . _hasOnlyLargeSploms ) {
230265 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 ( ) ;
233268 }
234269 }
235270
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' ) ) ;
271273
272274 if ( hadGl && ! hasGl ) {
273275 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 ( ) ;
279278 }
280279 }
281280
282- var oldSubplotList = oldFullLayout . _subplots || { } ;
283- var newSubplotList = newFullLayout . _subplots || { xaxis : [ ] , yaxis : [ ] } ;
284-
285281 // delete any titles we don't need anymore
286282 // check if axis list has changed, and if so clear old titles
287283 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 } ) ;
291285 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 ( ) ;
294289 }
295290 }
296291 }
@@ -308,7 +303,7 @@ exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout)
308303 else if ( oldSubplotList . cartesian ) {
309304 for ( i = 0 ; i < oldSubplotList . cartesian . length ; i ++ ) {
310305 var oldSubplotId = oldSubplotList . cartesian [ i ] ;
311- if ( newSubplotList . cartesian . indexOf ( oldSubplotId ) === - 1 ) {
306+ if ( ! newPlots [ oldSubplotId ] ) {
312307 var selector = '.' + oldSubplotId + ',.' + oldSubplotId + '-x,.' + oldSubplotId + '-y' ;
313308 oldFullLayout . _cartesianlayer . selectAll ( selector ) . remove ( ) ;
314309 removeSubplotExtras ( oldSubplotId , oldFullLayout ) ;
@@ -482,10 +477,6 @@ function makeSubplotLayer(gd, plotinfo) {
482477 ensureSingleAndAddDatum ( plotinfo . gridlayer , 'g' , plotinfo . xaxis . _id ) ;
483478 ensureSingleAndAddDatum ( plotinfo . gridlayer , 'g' , plotinfo . yaxis . _id ) ;
484479 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- }
489480 }
490481
491482 plotinfo . xlines
@@ -516,11 +507,8 @@ function purgeSubplotLayers(layers, fullLayout) {
516507
517508 // must remove overlaid subplot trace layers 'manually'
518509
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 ] ;
524512 var overlays = subplotInfo . overlays || [ ] ;
525513
526514 for ( var j = 0 ; j < overlays . length ; j ++ ) {
0 commit comments