3
3
var axisIds = require ( '../../plots/cartesian/axis_ids' ) ;
4
4
var scatterSubTypes = require ( '../../traces/scatter/subtypes' ) ;
5
5
var Registry = require ( '../../registry' ) ;
6
+ var isUnifiedHover = require ( '../fx/helpers' ) . isUnifiedHover ;
6
7
7
8
var createModeBar = require ( './modebar' ) ;
8
9
var modeBarButtons = require ( './buttons' ) ;
@@ -66,25 +67,6 @@ var DRAW_MODES = [
66
67
'eraseshape'
67
68
] ;
68
69
69
- var HOVER_MODES = [
70
- 'hoverCompareCartesian' ,
71
- 'hoverClosestCartesian' ,
72
- 'hoverClosestGl2d' ,
73
- 'hoverClosest3d' ,
74
- 'hoverClosestGeo' ,
75
- 'hoverClosestPie' ,
76
- 'toggleHover'
77
- ] ;
78
-
79
- var SPIKE_MODES = [
80
- 'toggleSpikelines'
81
- ] ;
82
-
83
- var EXTRA_MODES = [ ]
84
- . concat ( DRAW_MODES )
85
- . concat ( HOVER_MODES )
86
- . concat ( SPIKE_MODES ) ;
87
-
88
70
// logic behind which buttons are displayed by default
89
71
function getButtonGroups ( gd ) {
90
72
var fullLayout = gd . _fullLayout ;
@@ -104,6 +86,7 @@ function getButtonGroups(gd) {
104
86
var hasPolar = fullLayout . _has ( 'polar' ) ;
105
87
var hasSankey = fullLayout . _has ( 'sankey' ) ;
106
88
var allAxesFixed = areAllAxesFixed ( fullLayout ) ;
89
+ var hasUnifiedHoverLabel = isUnifiedHover ( fullLayout . hovermode ) ;
107
90
108
91
var groups = [ ] ;
109
92
@@ -128,23 +111,45 @@ function getButtonGroups(gd) {
128
111
addGroup ( commonGroup ) ;
129
112
130
113
var zoomGroup = [ ] ;
114
+ var hoverGroup = [ ] ;
131
115
var resetGroup = [ ] ;
132
116
var dragModeGroup = [ ] ;
133
117
134
118
if ( ( hasCartesian || hasGL2D || hasPie || hasFunnelarea || hasTernary ) + hasGeo + hasGL3D + hasMapbox + hasPolar > 1 ) {
135
119
// graphs with more than one plot types get 'union buttons'
136
- // which reset the view across all subplots.
120
+ // which reset the view or toggle hover labels across all subplots.
121
+ hoverGroup = [ 'toggleHover' ] ;
137
122
resetGroup = [ 'resetViews' ] ;
138
123
} else if ( hasGeo ) {
139
124
zoomGroup = [ 'zoomInGeo' , 'zoomOutGeo' ] ;
125
+ hoverGroup = [ 'hoverClosestGeo' ] ;
140
126
resetGroup = [ 'resetGeo' ] ;
141
127
} else if ( hasGL3D ) {
128
+ hoverGroup = [ 'hoverClosest3d' ] ;
142
129
resetGroup = [ 'resetCameraDefault3d' , 'resetCameraLastSave3d' ] ;
143
130
} else if ( hasMapbox ) {
144
131
zoomGroup = [ 'zoomInMapbox' , 'zoomOutMapbox' ] ;
132
+ hoverGroup = [ 'toggleHover' ] ;
145
133
resetGroup = [ 'resetViewMapbox' ] ;
134
+ } else if ( hasGL2D ) {
135
+ hoverGroup = [ 'hoverClosestGl2d' ] ;
136
+ } else if ( hasPie ) {
137
+ hoverGroup = [ 'hoverClosestPie' ] ;
146
138
} else if ( hasSankey ) {
139
+ hoverGroup = [ 'hoverClosestCartesian' , 'hoverCompareCartesian' ] ;
147
140
resetGroup = [ 'resetViewSankey' ] ;
141
+ } else { // hasPolar, hasTernary
142
+ // always show at least one hover icon.
143
+ hoverGroup = [ 'toggleHover' ] ;
144
+ }
145
+ // if we have cartesian, allow switching between closest and compare
146
+ // regardless of what other types are on the plot, since they'll all
147
+ // just treat any truthy hovermode as 'closest'
148
+ if ( hasCartesian ) {
149
+ hoverGroup = [ 'toggleSpikelines' , 'hoverClosestCartesian' , 'hoverCompareCartesian' ] ;
150
+ }
151
+ if ( hasNoHover ( fullData ) || hasUnifiedHoverLabel ) {
152
+ hoverGroup = [ ] ;
148
153
}
149
154
150
155
if ( ( hasCartesian || hasGL2D ) && ! allAxesFixed ) {
@@ -165,20 +170,40 @@ function getButtonGroups(gd) {
165
170
dragModeGroup . push ( 'select2d' , 'lasso2d' ) ;
166
171
}
167
172
168
- // accept pre-defined buttons as string
173
+ var enabledHoverGroup = [ ] ;
174
+ var enableHover = function ( a ) {
175
+ // return if already added
176
+ if ( enabledHoverGroup . indexOf ( a ) !== - 1 ) return ;
177
+ // should be in hoverGroup
178
+ if ( hoverGroup . indexOf ( a ) !== - 1 ) {
179
+ enabledHoverGroup . push ( a ) ;
180
+ }
181
+ } ;
169
182
if ( Array . isArray ( buttonsToAdd ) ) {
170
183
var newList = [ ] ;
171
184
for ( var i = 0 ; i < buttonsToAdd . length ; i ++ ) {
172
185
var b = buttonsToAdd [ i ] ;
173
186
if ( typeof b === 'string' ) {
174
- if ( EXTRA_MODES . indexOf ( b ) !== - 1 ) {
187
+ if ( DRAW_MODES . indexOf ( b ) !== - 1 ) {
188
+ // accept pre-defined drag modes i.e. shape drawing features as string
175
189
if (
176
- DRAW_MODES . indexOf ( b ) === - 1 ||
177
190
fullLayout . _has ( 'mapbox' ) || // draw shapes in paper coordinate (could be improved in future to support data coordinate, when there is no pitch)
178
191
fullLayout . _has ( 'cartesian' ) // draw shapes in data coordinate
179
192
) {
180
193
dragModeGroup . push ( b ) ;
181
194
}
195
+ } else if ( b === 'toggleSpikelines' ) {
196
+ enableHover ( 'toggleSpikelines' ) ;
197
+ } else if ( b === 'toggleHover' ) {
198
+ enableHover ( 'toggleHover' ) ;
199
+ } else if ( b === 'hoverCompare' ) {
200
+ enableHover ( 'hoverCompareCartesian' ) ;
201
+ } else if ( b === 'hoverClosest' ) {
202
+ enableHover ( 'hoverClosestCartesian' ) ;
203
+ enableHover ( 'hoverClosestGeo' ) ;
204
+ enableHover ( 'hoverClosest3d' ) ;
205
+ enableHover ( 'hoverClosestGl2d' ) ;
206
+ enableHover ( 'hoverClosestPie' ) ;
182
207
}
183
208
} else newList . push ( b ) ;
184
209
}
@@ -187,6 +212,7 @@ function getButtonGroups(gd) {
187
212
188
213
addGroup ( dragModeGroup ) ;
189
214
addGroup ( zoomGroup . concat ( resetGroup ) ) ;
215
+ addGroup ( enabledHoverGroup ) ;
190
216
191
217
return appendButtonsToGroups ( groups , buttonsToAdd ) ;
192
218
}
@@ -235,6 +261,14 @@ function isSelectable(fullData) {
235
261
return selectable ;
236
262
}
237
263
264
+ // check whether all trace are 'noHover'
265
+ function hasNoHover ( fullData ) {
266
+ for ( var i = 0 ; i < fullData . length ; i ++ ) {
267
+ if ( ! Registry . traceIs ( fullData [ i ] , 'noHover' ) ) return false ;
268
+ }
269
+ return true ;
270
+ }
271
+
238
272
function appendButtonsToGroups ( groups , buttons ) {
239
273
if ( buttons . length ) {
240
274
if ( Array . isArray ( buttons [ 0 ] ) ) {
0 commit comments