@@ -177,17 +177,20 @@ function handleCartesian(gd, ev) {
177177 astr = button . getAttribute ( 'data-attr' ) ,
178178 val = button . getAttribute ( 'data-val' ) || true ,
179179 fullLayout = gd . _fullLayout ,
180- aobj = { } ;
180+ aobj = { } ,
181+ axList = Axes . list ( gd , null , true ) ,
182+ ax ,
183+ allEnabled = 'on' ,
184+ i ;
181185
182186 if ( astr === 'zoom' ) {
183187 var mag = ( val === 'in' ) ? 0.5 : 2 ,
184188 r0 = ( 1 + mag ) / 2 ,
185- r1 = ( 1 - mag ) / 2 ,
186- axList = Axes . list ( gd , null , true ) ;
189+ r1 = ( 1 - mag ) / 2 ;
187190
188- var ax , axName ;
191+ var axName ;
189192
190- for ( var i = 0 ; i < axList . length ; i ++ ) {
193+ for ( i = 0 ; i < axList . length ; i ++ ) {
191194 ax = axList [ i ] ;
192195
193196 if ( ! ax . fixedrange ) {
@@ -202,6 +205,12 @@ function handleCartesian(gd, ev) {
202205 aobj [ axName + '.range[0]' ] = rangeInitial [ 0 ] ;
203206 aobj [ axName + '.range[1]' ] = rangeInitial [ 1 ] ;
204207 }
208+ if ( ax . _showSpikeInitial !== undefined ) {
209+ aobj [ axName + '.showspikes' ] = ax . _showSpikeInitial ;
210+ if ( allEnabled === 'on' && ! ax . _showSpikeInitial ) {
211+ allEnabled = 'off' ;
212+ }
213+ }
205214 }
206215 else {
207216 var rangeNow = [
@@ -219,12 +228,24 @@ function handleCartesian(gd, ev) {
219228 }
220229 }
221230 }
231+ fullLayout . _cartesianSpikesEnabled = allEnabled ;
222232 }
223233 else {
224234 // if ALL traces have orientation 'h', 'hovermode': 'x' otherwise: 'y'
225235 if ( astr === 'hovermode' && ( val === 'x' || val === 'y' ) ) {
226236 val = fullLayout . _isHoriz ? 'y' : 'x' ;
227237 button . setAttribute ( 'data-val' , val ) ;
238+ if ( val !== 'closest' ) {
239+ fullLayout . _cartesianSpikesEnabled = 'off' ;
240+ }
241+ } else if ( astr === 'hovermode' && val === 'closest' ) {
242+ for ( i = 0 ; i < axList . length ; i ++ ) {
243+ ax = axList [ i ] ;
244+ if ( allEnabled === 'on' && ! ax . showspikes ) {
245+ allEnabled = 'off' ;
246+ }
247+ }
248+ fullLayout . _cartesianSpikesEnabled = allEnabled ;
228249 }
229250
230251 aobj [ astr ] = val ;
@@ -518,3 +539,38 @@ modeBarButtons.resetViews = {
518539 // geo subplots.
519540 }
520541} ;
542+
543+ modeBarButtons . toggleSpikelines = {
544+ name : 'toggleSpikelines' ,
545+ title : 'Toggle Spike Lines' ,
546+ icon : Icons . spikeline ,
547+ attr : '_cartesianSpikesEnabled' ,
548+ val : 'on' ,
549+ click : function ( gd ) {
550+ var fullLayout = gd . _fullLayout ;
551+
552+ fullLayout . _cartesianSpikesEnabled = fullLayout . hovermode === 'closest' ?
553+ ( fullLayout . _cartesianSpikesEnabled === 'on' ? 'off' : 'on' ) : 'on' ;
554+
555+ var aobj = setSpikelineVisibility ( gd ) ;
556+
557+ aobj . hovermode = 'closest' ;
558+ Plotly . relayout ( gd , aobj ) ;
559+ }
560+ } ;
561+
562+ function setSpikelineVisibility ( gd ) {
563+ var fullLayout = gd . _fullLayout ,
564+ axList = Axes . list ( gd , null , true ) ,
565+ ax ,
566+ axName ,
567+ aobj = { } ;
568+
569+ for ( var i = 0 ; i < axList . length ; i ++ ) {
570+ ax = axList [ i ] ;
571+ axName = ax . _name ;
572+ aobj [ axName + '.showspikes' ] = fullLayout . _cartesianSpikesEnabled === 'on' ? true : false ;
573+ }
574+
575+ return aobj ;
576+ }
0 commit comments