@@ -89,7 +89,6 @@ function linearToData(ax) { return ax.type === 'category' ? ax.l2c : ax.l2d; }
8989
9090shapes . drawAll = function ( gd ) {
9191 var fullLayout = gd . _fullLayout ;
92- fullLayout . _shapelayer . selectAll ( 'path' ) . remove ( ) ;
9392 for ( var i = 0 ; i < fullLayout . shapes . length ; i ++ ) {
9493 shapes . draw ( gd , i ) ;
9594 }
@@ -115,86 +114,106 @@ shapes.add = function(gd) {
115114// if opt is blank, val can be 'add' or a full options object to add a new
116115// annotation at that point in the array, or 'remove' to delete this one
117116shapes . draw = function ( gd , index , opt , value ) {
118- var layout = gd . layout ,
119- fullLayout = gd . _fullLayout ,
120- i ;
121-
122- // TODO: abstract out these drawAll, add, and remove blocks for shapes and annotations
123117 if ( ! isNumeric ( index ) || index === - 1 ) {
124118 // no index provided - we're operating on ALL shapes
125119 if ( ! index && Array . isArray ( value ) ) {
126- // a whole annotation array is passed in
127- // (as in, redo of delete all)
128- layout . shapes = value ;
129- shapes . supplyLayoutDefaults ( layout , fullLayout ) ;
130- shapes . drawAll ( gd ) ;
120+ replaceAllShapes ( gd , value ) ;
131121 return ;
132122 }
133123 else if ( value === 'remove' ) {
134- // delete all
135- delete layout . shapes ;
136- fullLayout . shapes = [ ] ;
137- shapes . drawAll ( gd ) ;
124+ deleteAllShapes ( gd ) ;
138125 return ;
139126 }
140127 else if ( opt && value !== 'add' ) {
141- // make the same change to all shapes
142- for ( i = 0 ; i < fullLayout . shapes . length ; i ++ ) {
143- shapes . draw ( gd , i , opt , value ) ;
144- }
128+ updateAllShapes ( gd , opt , value ) ;
145129 return ;
146130 }
147131 else {
148132 // add a new empty annotation
149- index = fullLayout . shapes . length ;
150- fullLayout . shapes . push ( { } ) ;
133+ index = gd . _fullLayout . shapes . length ;
134+ gd . _fullLayout . shapes . push ( { } ) ;
151135 }
152136 }
153137
154138 if ( ! opt && value ) {
155139 if ( value === 'remove' ) {
156- fullLayout . _shapelayer . selectAll ( '[data-index="' + index + '"]' )
157- . remove ( ) ;
158- fullLayout . shapes . splice ( index , 1 ) ;
159- layout . shapes . splice ( index , 1 ) ;
160- for ( i = index ; i < fullLayout . shapes . length ; i ++ ) {
161- fullLayout . _shapelayer
162- . selectAll ( '[data-index="' + ( i + 1 ) + '"]' )
163- . attr ( 'data-index' , String ( i ) ) ;
164-
165- // redraw all shapes past the removed one,
166- // so they bind to the right events
167- shapes . draw ( gd , i ) ;
168- }
140+ deleteShape ( gd , index ) ;
169141 return ;
170142 }
171143 else if ( value === 'add' || Plotly . Lib . isPlainObject ( value ) ) {
172- fullLayout . shapes . splice ( index , 0 , { } ) ;
144+ insertShape ( gd , index , value ) ;
145+ }
146+ }
173147
174- var rule = Plotly . Lib . isPlainObject ( value ) ?
175- Plotly . Lib . extendFlat ( { } , value ) :
176- { text : 'New text' } ;
148+ updateShape ( gd , index , opt , value ) ;
149+ } ;
177150
178- if ( layout . shapes ) {
179- layout . shapes . splice ( index , 0 , rule ) ;
180- } else {
181- layout . shapes = [ rule ] ;
182- }
151+ function replaceAllShapes ( gd , newShapes ) {
152+ gd . layout . shapes = newShapes ;
153+ shapes . supplyLayoutDefaults ( gd . layout , gd . _fullLayout ) ;
154+ shapes . drawAll ( gd ) ;
155+ }
183156
184- for ( i = fullLayout . shapes . length - 1 ; i > index ; i -- ) {
185- fullLayout . _shapelayer
186- . selectAll ( '[data-index="' + ( i - 1 ) + '"]' )
187- . attr ( 'data-index' , String ( i ) ) ;
188- shapes . draw ( gd , i ) ;
189- }
190- }
157+ function deleteAllShapes ( gd ) {
158+ delete gd . layout . shapes ;
159+ gd . _fullLayout . shapes = [ ] ;
160+ shapes . drawAll ( gd ) ;
161+ }
162+
163+ function updateAllShapes ( gd , opt , value ) {
164+ for ( var i = 0 ; i < gd . _fullLayout . shapes . length ; i ++ ) {
165+ shapes . draw ( gd , i , opt , value ) ;
166+ }
167+ }
168+
169+ function deleteShape ( gd , index ) {
170+ gd . _fullLayout . _shapelayer . selectAll ( '[data-index="' + index + '"]' )
171+ . remove ( ) ;
172+
173+ gd . _fullLayout . shapes . splice ( index , 1 ) ;
174+
175+ gd . layout . shapes . splice ( index , 1 ) ;
176+
177+ for ( var i = index ; i < gd . _fullLayout . shapes . length ; i ++ ) {
178+ // redraw all shapes past the removed one,
179+ // so they bind to the right events
180+ gd . _fullLayout . _shapelayer
181+ . selectAll ( '[data-index="' + ( i + 1 ) + '"]' )
182+ . attr ( 'data-index' , String ( i ) ) ;
183+ shapes . draw ( gd , i ) ;
184+ }
185+ }
186+
187+ function insertShape ( gd , index , newShape ) {
188+ gd . _fullLayout . shapes . splice ( index , 0 , { } ) ;
189+
190+ var rule = Plotly . Lib . isPlainObject ( newShape ) ?
191+ Plotly . Lib . extendFlat ( { } , newShape ) :
192+ { text : 'New text' } ;
193+
194+ if ( gd . layout . shapes ) {
195+ gd . layout . shapes . splice ( index , 0 , rule ) ;
196+ } else {
197+ gd . layout . shapes = [ rule ] ;
191198 }
192199
200+ for ( var i = gd . _fullLayout . shapes . length - 1 ; i > index ; i -- ) {
201+ gd . _fullLayout . _shapelayer
202+ . selectAll ( '[data-index="' + ( i - 1 ) + '"]' )
203+ . attr ( 'data-index' , String ( i ) ) ;
204+ shapes . draw ( gd , i ) ;
205+ }
206+ }
207+
208+ function updateShape ( gd , index , opt , value ) {
209+ var i ;
210+
193211 // remove the existing shape if there is one
194- fullLayout . _shapelayer . selectAll ( '[data-index="' + index + '"]' ) . remove ( ) ;
212+ gd . _fullLayout . _shapelayer . selectAll ( '[data-index="' + index + '"]' )
213+ . remove ( ) ;
195214
196215 // remember a few things about what was already there,
197- var optionsIn = layout . shapes [ index ] ;
216+ var optionsIn = gd . layout . shapes [ index ] ;
198217
199218 // (from annos...) not sure how we're getting here... but C12 is seeing a bug
200219 // where we fail here when they add/remove annotations
@@ -261,8 +280,8 @@ shapes.draw = function(gd, index, opt, value) {
261280 optionsIn [ posAttr ] = position ;
262281 }
263282
264- var options = handleShapeDefaults ( optionsIn , fullLayout ) ;
265- fullLayout . shapes [ index ] = options ;
283+ var options = handleShapeDefaults ( optionsIn , gd . _fullLayout ) ;
284+ gd . _fullLayout . shapes [ index ] = options ;
266285
267286 var attrs = {
268287 'data-index' : String ( index ) ,
@@ -273,15 +292,18 @@ shapes.draw = function(gd, index, opt, value) {
273292
274293 var lineColor = options . line . width ? options . line . color : 'rgba(0,0,0,0)' ;
275294
276- var path = fullLayout . _shapelayer . append ( 'path' )
295+ var path = gd . _fullLayout . _shapelayer . append ( 'path' )
277296 . attr ( attrs )
278297 . style ( 'opacity' , options . opacity )
279298 . call ( Plotly . Color . stroke , lineColor )
280299 . call ( Plotly . Color . fill , options . fillcolor )
281300 . call ( Plotly . Drawing . dashLine , options . line . dash , options . line . width ) ;
282301
283- if ( clipAxes ) path . call ( Plotly . Drawing . setClipUrl , 'clip' + fullLayout . _uid + clipAxes ) ;
284- } ;
302+ if ( clipAxes ) {
303+ path . call ( Plotly . Drawing . setClipUrl ,
304+ 'clip' + gd . _fullLayout . _uid + clipAxes ) ;
305+ }
306+ }
285307
286308function decodeDate ( convertToPx ) {
287309 return function ( v ) { return convertToPx ( v . replace ( '_' , ' ' ) ) ; } ;
0 commit comments