@@ -96,13 +96,17 @@ module.exports = function draw(gd) {
96
96
97
97
// remove exiting header, remove dropped buttons and reset margins
98
98
if ( headerGroups . enter ( ) . size ( ) ) {
99
- foldDropdownMenu ( gButton , scrollBox ) ;
99
+ gButton
100
+ . call ( removeAllButtons )
101
+ . attr ( constants . menuIndexAttrName , '-1' ) ;
100
102
}
101
103
102
104
headerGroups . exit ( ) . each ( function ( menuOpts ) {
103
105
d3 . select ( this ) . remove ( ) ;
104
106
105
- foldDropdownMenu ( gButton , scrollBox ) ;
107
+ gButton
108
+ . call ( removeAllButtons )
109
+ . attr ( constants . menuIndexAttrName , '-1' ) ;
106
110
107
111
Plots . autoMargin ( gd , constants . autoMarginIdRoot + menuOpts . _index ) ;
108
112
} ) ;
@@ -119,12 +123,12 @@ module.exports = function draw(gd) {
119
123
if ( menuOpts . type === 'dropdown' ) {
120
124
drawHeader ( gd , gHeader , gButton , scrollBox , menuOpts ) ;
121
125
122
- // update dropdown buttons if this menu is active
126
+ // if this menu is active, update the dropdown container
123
127
if ( isActive ( gButton , menuOpts ) ) {
124
- unfoldDropdownMenu ( gd , gHeader , gButton , scrollBox , menuOpts ) ;
128
+ drawButtons ( gd , gHeader , gButton , scrollBox , menuOpts ) ;
125
129
}
126
130
} else {
127
- drawButtons ( gd , gHeader , null , scrollBox , menuOpts ) ;
131
+ drawButtons ( gd , gHeader , null , null , menuOpts ) ;
128
132
}
129
133
130
134
} ) ;
@@ -163,86 +167,22 @@ function isActive(gButton, menuOpts) {
163
167
return + gButton . attr ( constants . menuIndexAttrName ) === menuOpts . _index ;
164
168
}
165
169
166
- function unfoldDropdownMenu ( gd , gHeader , gButton , scrollBox , menuOpts ) {
167
- // enable the scrollbox
168
- var direction = menuOpts . direction ,
169
- isUp = ( direction === 'up' ) ,
170
- isDown = ( direction === 'down' ) ,
171
- isLeft = ( direction === 'left' ) ,
172
- isRight = ( direction === 'right' ) ,
173
- isVertical = ( isUp || isDown ) ;
174
-
175
- var x0 , y0 ;
176
- if ( isDown ) {
177
- x0 = 0 ;
178
- y0 = menuOpts . headerHeight + constants . gapButtonHeader ;
179
- }
180
- else if ( isUp ) {
181
- x0 = 0 ;
182
- y0 = menuOpts . headerHeight + constants . gapButton - menuOpts . openHeight ;
183
- }
184
- else if ( isRight ) {
185
- x0 = menuOpts . headerWidth + constants . gapButtonHeader ;
186
- y0 = 0 ;
187
- }
188
- else if ( isLeft ) {
189
- x0 = menuOpts . headerWidth + constants . gapButton - menuOpts . openWidth ;
190
- y0 = 0 ;
191
- }
192
-
193
- var position = {
194
- l : menuOpts . lx + menuOpts . borderwidth + x0 + menuOpts . pad . l ,
195
- t : menuOpts . ly + menuOpts . borderwidth + y0 + menuOpts . pad . t ,
196
- w : Math . max ( menuOpts . openWidth , menuOpts . headerWidth ) ,
197
- h : menuOpts . openHeight
198
- } ;
199
-
200
- var active = menuOpts . active ,
201
- translateX , translateY ,
202
- i ;
203
- if ( isVertical ) {
204
- translateY = 0 ;
205
- for ( i = 0 ; i < active ; i ++ ) {
206
- translateY += menuOpts . heights [ i ] + constants . gapButton ;
207
- }
208
- }
209
- else {
210
- translateX = 0 ;
211
- for ( i = 0 ; i < active ; i ++ ) {
212
- translateX += menuOpts . widths [ i ] + constants . gapButton ;
213
- }
214
- }
215
-
216
- scrollBox . enable ( position , translateX , translateY ) ;
217
-
218
- // store index of active menu (-1 means dropdown menu is folded)
219
- gButton . attr ( constants . menuIndexAttrName , menuOpts . _index ) ;
220
-
221
- drawButtons ( gd , gHeader , gButton , scrollBox , menuOpts ) ;
222
- }
223
-
224
- function foldDropdownMenu ( gButton , scrollBox ) {
225
- scrollBox . disable ( ) ;
226
-
227
- // -1 means dropdown menu is folded
228
- gButton
229
- . attr ( constants . menuIndexAttrName , '-1' )
230
- . call ( removeAllButtons ) ;
231
- }
232
-
233
170
function setActive ( gd , menuOpts , buttonOpts , gHeader , gButton , scrollBox , buttonIndex , isSilentUpdate ) {
234
171
// update 'active' attribute in menuOpts
235
172
menuOpts . _input . active = menuOpts . active = buttonIndex ;
236
173
237
- if ( menuOpts . type === 'dropdown' ) {
174
+ if ( menuOpts . type === 'buttons' ) {
175
+ drawButtons ( gd , gHeader , null , null , menuOpts ) ;
176
+ }
177
+ else if ( menuOpts . type === 'dropdown' ) {
238
178
// fold up buttons and redraw header
239
179
gButton . attr ( constants . menuIndexAttrName , '-1' ) ;
240
180
241
181
drawHeader ( gd , gHeader , gButton , scrollBox , menuOpts ) ;
242
- }
243
182
244
- if ( ! isSilentUpdate || menuOpts . type === 'buttons' ) {
245
- drawButtons ( gd , gHeader , gButton , scrollBox , menuOpts ) ;
183
+ if ( ! isSilentUpdate ) {
184
+ drawButtons ( gd , gHeader , gButton , scrollBox , menuOpts ) ;
185
+ }
246
186
}
247
187
}
248
188
@@ -283,18 +223,19 @@ function drawHeader(gd, gHeader, gButton, scrollBox, menuOpts) {
283
223
} ) ;
284
224
285
225
header . on ( 'click' , function ( ) {
286
- if ( isFolded ( gButton ) ) {
287
- unfoldDropdownMenu ( gd , gHeader , gButton , scrollBox , menuOpts ) ;
288
- }
289
- else if ( isActive ( gButton , menuOpts ) ) {
290
- foldDropdownMenu ( gButton , scrollBox ) ;
291
- }
292
- else {
293
- // the dropdown menu is unfolded,
294
- // but the clicked header is not the active header
295
- foldDropdownMenu ( gButton , scrollBox ) ;
296
- unfoldDropdownMenu ( gd , gHeader , gButton , scrollBox , menuOpts ) ;
297
- }
226
+ gButton . call ( removeAllButtons ) ;
227
+
228
+
229
+ // if this menu is active, fold the dropdown container
230
+ // otherwise, make this menu active
231
+ gButton . attr (
232
+ constants . menuIndexAttrName ,
233
+ isActive ( gButton , menuOpts ) ?
234
+ - 1 :
235
+ String ( menuOpts . _index )
236
+ ) ;
237
+
238
+ drawButtons ( gd , gHeader , gButton , scrollBox , menuOpts ) ;
298
239
} ) ;
299
240
300
241
header . on ( 'mouseover' , function ( ) {
@@ -339,20 +280,11 @@ function drawButtons(gd, gHeader, gButton, scrollBox, menuOpts) {
339
280
340
281
exit . transition ( )
341
282
. attr ( 'opacity' , '0' )
342
- . remove ( )
343
- . each ( 'end' , function ( ) {
344
- // remove the scrollbox, if all the buttons have been removed
345
- if ( gButton . selectAll ( 'g.' + klass ) . size ( ) === 0 ) {
346
- foldDropdownMenu ( gButton , scrollBox ) ;
347
- }
348
- } ) ;
283
+ . remove ( ) ;
349
284
} else {
350
285
exit . remove ( ) ;
351
286
}
352
287
353
- // if folding a dropdown menu, don't draw the buttons
354
- if ( ! buttons . size ( ) ) return ;
355
-
356
288
var x0 = 0 ;
357
289
var y0 = 0 ;
358
290
@@ -411,6 +343,107 @@ function drawButtons(gd, gHeader, gButton, scrollBox, menuOpts) {
411
343
} ) ;
412
344
413
345
buttons . call ( styleButtons , menuOpts ) ;
346
+
347
+ if ( scrollBox ) {
348
+ if ( buttons . size ( ) ) {
349
+ drawScrollBox ( gd , gHeader , gButton , scrollBox , menuOpts ) ;
350
+ }
351
+ else {
352
+ hideScrollBox ( scrollBox ) ;
353
+ }
354
+ }
355
+ }
356
+
357
+ function drawScrollBox ( gd , gHeader , gButton , scrollBox , menuOpts ) {
358
+ // enable the scrollbox
359
+ var direction = menuOpts . direction ,
360
+ isUp = ( direction === 'up' ) ,
361
+ isDown = ( direction === 'down' ) ,
362
+ isLeft = ( direction === 'left' ) ,
363
+ isRight = ( direction === 'right' ) ,
364
+ isVertical = ( isUp || isDown ) ;
365
+
366
+ var x0 , y0 ;
367
+ if ( isDown ) {
368
+ x0 = 0 ;
369
+ y0 = menuOpts . headerHeight + constants . gapButtonHeader ;
370
+ }
371
+ else if ( isUp ) {
372
+ x0 = 0 ;
373
+ y0 = menuOpts . headerHeight + constants . gapButton - menuOpts . openHeight ;
374
+ }
375
+ else if ( isRight ) {
376
+ x0 = menuOpts . headerWidth + constants . gapButtonHeader ;
377
+ y0 = 0 ;
378
+ }
379
+ else if ( isLeft ) {
380
+ x0 = menuOpts . headerWidth + constants . gapButton - menuOpts . openWidth ;
381
+ y0 = 0 ;
382
+ }
383
+
384
+ var position = {
385
+ l : menuOpts . lx + menuOpts . borderwidth + x0 + menuOpts . pad . l ,
386
+ t : menuOpts . ly + menuOpts . borderwidth + y0 + menuOpts . pad . t ,
387
+ w : Math . max ( menuOpts . openWidth , menuOpts . headerWidth ) ,
388
+ h : menuOpts . openHeight
389
+ } ;
390
+
391
+ var active = menuOpts . active ,
392
+ translateX , translateY ,
393
+ i ;
394
+ if ( isVertical ) {
395
+ translateY = 0 ;
396
+ for ( i = 0 ; i < active ; i ++ ) {
397
+ translateY += menuOpts . heights [ i ] + constants . gapButton ;
398
+ }
399
+ }
400
+ else {
401
+ translateX = 0 ;
402
+ for ( i = 0 ; i < active ; i ++ ) {
403
+ translateX += menuOpts . widths [ i ] + constants . gapButton ;
404
+ }
405
+ }
406
+
407
+ scrollBox . enable ( position , translateX , translateY ) ;
408
+
409
+ if ( scrollBox . hbar ) {
410
+ scrollBox . hbar
411
+ . attr ( 'opacity' , '0' )
412
+ . transition ( )
413
+ . attr ( 'opacity' , '1' ) ;
414
+ }
415
+
416
+ if ( scrollBox . vbar ) {
417
+ scrollBox . vbar
418
+ . attr ( 'opacity' , '0' )
419
+ . transition ( )
420
+ . attr ( 'opacity' , '1' ) ;
421
+ }
422
+ }
423
+
424
+ function hideScrollBox ( scrollBox ) {
425
+ var hasHBar = ! ! scrollBox . hbar ,
426
+ hasVBar = ! ! scrollBox . vbar ;
427
+
428
+ if ( hasHBar ) {
429
+ scrollBox . hbar
430
+ . transition ( )
431
+ . attr ( 'opacity' , '0' )
432
+ . each ( 'end' , function ( ) {
433
+ hasHBar = false ;
434
+ if ( ! hasVBar ) scrollBox . disable ( ) ;
435
+ } ) ;
436
+ }
437
+
438
+ if ( hasVBar ) {
439
+ scrollBox . vbar
440
+ . transition ( )
441
+ . attr ( 'opacity' , '0' )
442
+ . each ( 'end' , function ( ) {
443
+ hasVBar = false ;
444
+ if ( ! hasHBar ) scrollBox . disable ( ) ;
445
+ } ) ;
446
+ }
414
447
}
415
448
416
449
function drawItem ( item , menuOpts , itemOpts ) {
0 commit comments