1010'use strict' ;
1111
1212var d3 = require ( 'd3' ) ;
13- var isNumeric = require ( 'fast-isnumeric' ) ;
1413
1514var Plotly = require ( '../../plotly' ) ;
1615var Plots = require ( '../../plots/plots' ) ;
@@ -22,8 +21,6 @@ var svgTextUtils = require('../../lib/svg_text_utils');
2221var setCursor = require ( '../../lib/setcursor' ) ;
2322var dragElement = require ( '../dragelement' ) ;
2423
25- var handleAnnotationDefaults = require ( './annotation_defaults' ) ;
26- var supplyLayoutDefaults = require ( './defaults' ) ;
2724var drawArrowHead = require ( './draw_arrow_head' ) ;
2825
2926
@@ -41,6 +38,9 @@ module.exports = {
4138 drawOne : drawOne
4239} ;
4340
41+ /*
42+ * draw: draw all annotations without any new modifications
43+ */
4444function draw ( gd ) {
4545 var fullLayout = gd . _fullLayout ;
4646
@@ -55,196 +55,26 @@ function draw(gd) {
5555 return Plots . previousPromises ( gd ) ;
5656}
5757
58- function drawOne ( gd , index , opt , value ) {
58+ /*
59+ * drawOne: draw a single annotation, potentially with modifications
60+ *
61+ * index (int): the annotation to draw
62+ */
63+ function drawOne ( gd , index ) {
5964 var layout = gd . layout ,
6065 fullLayout = gd . _fullLayout ,
61- i ;
62-
63- if ( ! isNumeric ( index ) || index === - 1 ) {
64-
65- // no index provided - we're operating on ALL annotations
66- if ( ! index && Array . isArray ( value ) ) {
67- // a whole annotation array is passed in
68- // (as in, redo of delete all)
69- layout . annotations = value ;
70- supplyLayoutDefaults ( layout , fullLayout ) ;
71- draw ( gd ) ;
72- return ;
73- }
74- else if ( value === 'remove' ) {
75- // delete all
76- delete layout . annotations ;
77- fullLayout . annotations = [ ] ;
78- draw ( gd ) ;
79- return ;
80- }
81- else if ( opt && value !== 'add' ) {
82- // make the same change to all annotations
83- for ( i = 0 ; i < fullLayout . annotations . length ; i ++ ) {
84- drawOne ( gd , i , opt , value ) ;
85- }
86- return ;
87- }
88- else {
89- // add a new empty annotation
90- index = fullLayout . annotations . length ;
91- fullLayout . annotations . push ( { } ) ;
92- }
93- }
94-
95- if ( ! opt && value ) {
96- if ( value === 'remove' ) {
97- fullLayout . _infolayer . selectAll ( '.annotation[data-index="' + index + '"]' )
98- . remove ( ) ;
99- fullLayout . annotations . splice ( index , 1 ) ;
100- layout . annotations . splice ( index , 1 ) ;
101- for ( i = index ; i < fullLayout . annotations . length ; i ++ ) {
102- fullLayout . _infolayer
103- . selectAll ( '.annotation[data-index="' + ( i + 1 ) + '"]' )
104- . attr ( 'data-index' , String ( i ) ) ;
105-
106- // redraw all annotations past the removed one,
107- // so they bind to the right events
108- drawOne ( gd , i ) ;
109- }
110- return ;
111- }
112- else if ( value === 'add' || Lib . isPlainObject ( value ) ) {
113- fullLayout . annotations . splice ( index , 0 , { } ) ;
114-
115- var rule = Lib . isPlainObject ( value ) ?
116- Lib . extendFlat ( { } , value ) :
117- { text : 'New text' } ;
118-
119- if ( layout . annotations ) {
120- layout . annotations . splice ( index , 0 , rule ) ;
121- } else {
122- layout . annotations = [ rule ] ;
123- }
124-
125- for ( i = fullLayout . annotations . length - 1 ; i > index ; i -- ) {
126- fullLayout . _infolayer
127- . selectAll ( '.annotation[data-index="' + ( i - 1 ) + '"]' )
128- . attr ( 'data-index' , String ( i ) ) ;
129- drawOne ( gd , i ) ;
130- }
131- }
132- }
66+ gs = gd . _fullLayout . _size ;
13367
13468 // remove the existing annotation if there is one
13569 fullLayout . _infolayer . selectAll ( '.annotation[data-index="' + index + '"]' ) . remove ( ) ;
13670
13771 // remember a few things about what was already there,
13872 var optionsIn = layout . annotations [ index ] ,
139- oldPrivate = fullLayout . annotations [ index ] ;
140-
141- // not sure how we're getting here... but C12 is seeing a bug
142- // where we fail here when they add/remove annotations
143- if ( ! optionsIn ) return ;
73+ options = fullLayout . annotations [ index ] ;
14474
145- // alter the input annotation as requested
146- var optionsEdit = { } ;
147- if ( typeof opt === 'string' && opt ) optionsEdit [ opt ] = value ;
148- else if ( Lib . isPlainObject ( opt ) ) optionsEdit = opt ;
149-
150- var optionKeys = Object . keys ( optionsEdit ) ;
151- for ( i = 0 ; i < optionKeys . length ; i ++ ) {
152- var k = optionKeys [ i ] ;
153- Lib . nestedProperty ( optionsIn , k ) . set ( optionsEdit [ k ] ) ;
154- }
155-
156- // return early in visible: false updates
157- if ( optionsIn . visible === false ) return ;
158-
159- var gs = fullLayout . _size ;
160- var oldRef = { xref : optionsIn . xref , yref : optionsIn . yref } ;
161-
162- var axLetters = [ 'x' , 'y' ] ;
163- for ( i = 0 ; i < 2 ; i ++ ) {
164- var axLetter = axLetters [ i ] ;
165- // if we don't have an explicit position already,
166- // don't set one just because we're changing references
167- // or axis type.
168- // the defaults will be consistent most of the time anyway,
169- // except in log/linear changes
170- if ( optionsEdit [ axLetter ] !== undefined ||
171- optionsIn [ axLetter ] === undefined ) {
172- continue ;
173- }
174-
175- var axOld = Axes . getFromId ( gd , Axes . coerceRef ( oldRef , { } , gd , axLetter , '' , 'paper' ) ) ,
176- axNew = Axes . getFromId ( gd , Axes . coerceRef ( optionsIn , { } , gd , axLetter , '' , 'paper' ) ) ,
177- position = optionsIn [ axLetter ] ,
178- axTypeOld = oldPrivate [ '_' + axLetter + 'type' ] ;
179-
180- if ( optionsEdit [ axLetter + 'ref' ] !== undefined ) {
181-
182- // TODO: include ax / ay / axref / ayref here if not 'pixel'
183- // or even better, move all of this machinery out of here and into
184- // streambed as extra attributes to a regular relayout call
185- // we should do this after v2.0 when it can work equivalently for
186- // annotations, shapes, and images.
187-
188- var autoAnchor = optionsIn [ axLetter + 'anchor' ] === 'auto' ,
189- plotSize = ( axLetter === 'x' ? gs . w : gs . h ) ,
190- halfSizeFrac = ( oldPrivate [ '_' + axLetter + 'size' ] || 0 ) /
191- ( 2 * plotSize ) ;
192- if ( axOld && axNew ) { // data -> different data
193- // go to the same fraction of the axis length
194- // whether or not these axes share a domain
195-
196- position = axNew . fraction2r ( axOld . r2fraction ( position ) ) ;
197- }
198- else if ( axOld ) { // data -> paper
199- // first convert to fraction of the axis
200- position = axOld . r2fraction ( position ) ;
201-
202- // next scale the axis to the whole plot
203- position = axOld . domain [ 0 ] +
204- position * ( axOld . domain [ 1 ] - axOld . domain [ 0 ] ) ;
205-
206- // finally see if we need to adjust auto alignment
207- // because auto always means middle / center alignment for data,
208- // but it changes for page alignment based on the closest side
209- if ( autoAnchor ) {
210- var posPlus = position + halfSizeFrac ,
211- posMinus = position - halfSizeFrac ;
212- if ( position + posMinus < 2 / 3 ) position = posMinus ;
213- else if ( position + posPlus > 4 / 3 ) position = posPlus ;
214- }
215- }
216- else if ( axNew ) { // paper -> data
217- // first see if we need to adjust auto alignment
218- if ( autoAnchor ) {
219- if ( position < 1 / 3 ) position += halfSizeFrac ;
220- else if ( position > 2 / 3 ) position -= halfSizeFrac ;
221- }
222-
223- // next convert to fraction of the axis
224- position = ( position - axNew . domain [ 0 ] ) /
225- ( axNew . domain [ 1 ] - axNew . domain [ 0 ] ) ;
226-
227- // finally convert to data coordinates
228- position = axNew . fraction2r ( position ) ;
229- }
230- }
231-
232- if ( axNew && axNew === axOld && axTypeOld ) {
233- if ( axTypeOld === 'log' && axNew . type !== 'log' ) {
234- position = Math . pow ( 10 , position ) ;
235- }
236- else if ( axTypeOld !== 'log' && axNew . type === 'log' ) {
237- position = ( position > 0 ) ?
238- Math . log ( position ) / Math . LN10 : undefined ;
239- }
240- }
241-
242- optionsIn [ axLetter ] = position ;
243- }
244-
245- var options = { } ;
246- handleAnnotationDefaults ( optionsIn , options , fullLayout ) ;
247- fullLayout . annotations [ index ] = options ;
75+ // this annotation is gone - quit now after deleting it
76+ // TODO: use d3 idioms instead of deleting and redrawing every time
77+ if ( ! optionsIn || options . visible === false ) return ;
24878
24979 var xa = Axes . getFromId ( gd , options . xref ) ,
25080 ya = Axes . getFromId ( gd , options . yref ) ,
@@ -457,9 +287,6 @@ function drawOne(gd, index, opt, value) {
457287
458288 options [ '_' + axLetter + 'padplus' ] = ( annSize / 2 ) + textPadShift ;
459289 options [ '_' + axLetter + 'padminus' ] = ( annSize / 2 ) - textPadShift ;
460-
461- // save the current axis type for later log/linear changes
462- options [ '_' + axLetter + 'type' ] = ax && ax . type ;
463290 } ) ;
464291
465292 if ( annotationIsOffscreen ) {
0 commit comments