@@ -193,13 +193,15 @@ function renderHighlight(root, tweenCallback) {
193
193
styleHighlight ( barToStyle ) ;
194
194
}
195
195
196
- function getInterval ( b , height , y ) {
196
+ function getInterval ( b , d , y ) {
197
+ var height = d . height ;
197
198
var intervals = b . filter . getConsolidated ( ) ;
198
199
var pixIntervals = unitToPx ( intervals , height ) ;
199
200
var hoveredInterval = NaN ;
200
201
var previousInterval = NaN ;
201
202
var nextInterval = NaN ;
202
- for ( var i = 0 ; i <= pixIntervals . length ; i ++ ) {
203
+ var i ;
204
+ for ( i = 0 ; i <= pixIntervals . length ; i ++ ) {
203
205
var p = pixIntervals [ i ] ;
204
206
if ( p && p [ 0 ] <= y && y <= p [ 1 ] ) {
205
207
// over a bar
@@ -226,15 +228,34 @@ function getInterval(b, height, y) {
226
228
}
227
229
}
228
230
231
+ var foundInterval = ! isNaN ( closestInterval ) ;
232
+
229
233
var fPix = pixIntervals [ closestInterval ] ;
230
234
231
- return {
232
- interval : isNaN ( closestInterval ) ? null : intervals [ closestInterval ] , // activated interval in domain terms
233
- intervalPix : isNaN ( closestInterval ) ? null : fPix , // activated interval in pixel terms
235
+ var out = {
236
+ interval : foundInterval ? intervals [ closestInterval ] : null , // activated interval in domain terms
237
+ intervalPix : foundInterval ? fPix : null , // activated interval in pixel terms
234
238
n : north ( fPix , y ) , // do we hover over the northern resize hotspot
235
239
s : south ( fPix , y ) , // do we hover over the northern resize hotspot
236
240
m : middle ( fPix , y ) // or over the bar section itself?
237
241
} ;
242
+
243
+ if ( d . ordinal && ( ! ( out . n || out . s || out . m ) || ! filterActive ( b ) ) ) {
244
+ var a = d . ordinalScale . range ( ) . map ( d . paddedUnitScale ) ;
245
+ var unitLocation = d . unitScaleInOrder . invert ( y ) ;
246
+ for ( i = 0 ; i < a . length ; i ++ ) {
247
+ var rangei = [
248
+ a [ Math . max ( i - 1 , 0 ) ] * 0.25 + a [ i ] * 0.75 ,
249
+ a [ Math . min ( i + 1 , a . length - 1 ) ] * 0.25 + a [ i ] * 0.75
250
+ ] ;
251
+ if ( unitLocation >= rangei [ 0 ] && unitLocation <= rangei [ 1 ] ) {
252
+ out . clickableOrdinalRange = rangei ;
253
+ break ;
254
+ }
255
+ }
256
+ }
257
+
258
+ return out ;
238
259
}
239
260
240
261
function attachDragBehavior ( selection ) {
@@ -249,9 +270,16 @@ function attachDragBehavior(selection) {
249
270
return ;
250
271
}
251
272
var y = d . height - d3 . mouse ( this ) [ 1 ] - 2 * c . verticalPadding ;
252
- var interval = getInterval ( b , d . height , y ) ;
273
+ var interval = getInterval ( b , d , y ) ;
274
+ var cursor = 'crosshair' ;
275
+ if ( interval . clickableOrdinalRange ) cursor = 'pointer' ;
276
+ else if ( filterActive ( b ) ) {
277
+ if ( interval . n ) cursor = 'n-resize' ;
278
+ else if ( interval . s ) cursor = 's-resize' ;
279
+ else if ( interval . m ) cursor = 'ns-resize' ;
280
+ }
253
281
d3 . select ( document . body )
254
- . style ( 'cursor' , interval . n ? 'n-resize' : interval . s ? 's-resize' : ! interval . m ? 'crosshair' : filterActive ( b ) ? 'ns-resize' : 'crosshair' ) ;
282
+ . style ( 'cursor' , cursor ) ;
255
283
} )
256
284
. on ( 'mouseleave' , function ( d ) {
257
285
if ( d . parent . inBrushDrag ) {
@@ -266,7 +294,7 @@ function attachDragBehavior(selection) {
266
294
var y = d . height - d3 . mouse ( this ) [ 1 ] - 2 * c . verticalPadding ;
267
295
var unitLocation = d . unitScaleInOrder . invert ( y ) ;
268
296
var b = d . brush ;
269
- var intData = getInterval ( b , d . height , y ) ;
297
+ var intData = getInterval ( b , d , y ) ;
270
298
var unitRange = intData . interval ;
271
299
var pixelRange = unitRange . map ( d . unitScaleInOrder ) ;
272
300
var s = b . svgBrush ;
@@ -276,12 +304,13 @@ function attachDragBehavior(selection) {
276
304
s . grabPoint = d . unitScaleInOrder ( unitLocation ) - pixelRange [ 0 ] - c . verticalPadding ;
277
305
s . barLength = pixelRange [ 1 ] - pixelRange [ 0 ] ;
278
306
s . grabbingBar = active && intData . m && unitRange ;
307
+ s . clickableOrdinalRange = intData . clickableOrdinalRange ;
279
308
s . stayingIntervals = ! d . multiselect ? [ ] :
280
309
barInteraction ?
281
310
b . filter . get ( ) . filter ( differentInterval ( unitRange ) ) :
282
311
b . filter . get ( ) ; // keep all preexisting bars if interaction wasn't a barInteraction
283
- var grabbingBarNorth = intData . n ;
284
- var grabbingBarSouth = intData . s ;
312
+ var grabbingBarNorth = active && intData . n ;
313
+ var grabbingBarSouth = active && intData . s ;
285
314
var newBrushing = ! s . grabbingBar && ! grabbingBarNorth && ! grabbingBarSouth ;
286
315
s . startExtent = newBrushing ? unitLocation : unitRange [ grabbingBarSouth ? 1 : 0 ] ;
287
316
d . parent . inBrushDrag = true ;
@@ -333,8 +362,17 @@ function attachDragBehavior(selection) {
333
362
d . parent . inBrushDrag = false ;
334
363
clearCursor ( ) ; // instead of clearing, a nicer thing would be to set it according to current location
335
364
if ( ! s . wasDragged ) { // a click+release on the same spot (ie. w/o dragging) means a bar or full reset
336
- s . wasDragged = undefined ; // logic-wise unneded, just shows `wasDragged` has no longer a meaning
337
- if ( grabbingBar ) {
365
+ s . wasDragged = undefined ; // logic-wise unneeded, just shows `wasDragged` has no longer a meaning
366
+ if ( s . clickableOrdinalRange ) {
367
+ if ( brush . filterSpecified && d . multiselect ) {
368
+ s . extent . push ( s . clickableOrdinalRange ) ;
369
+ }
370
+ else {
371
+ s . extent = [ s . clickableOrdinalRange ] ;
372
+ brush . filterSpecified = true ;
373
+ }
374
+ }
375
+ else if ( grabbingBar ) {
338
376
s . extent = s . stayingIntervals ;
339
377
if ( s . extent . length === 0 ) {
340
378
brushClear ( brush ) ;
@@ -361,12 +399,21 @@ function attachDragBehavior(selection) {
361
399
ordinalScaleSnapLo ( a , s . newExtent [ 0 ] , s . stayingIntervals ) ,
362
400
ordinalScaleSnapHi ( a , s . newExtent [ 1 ] , s . stayingIntervals )
363
401
] ;
364
- s . extent = s . stayingIntervals . concat ( s . newExtent [ 1 ] > s . newExtent [ 0 ] ? [ s . newExtent ] : [ ] ) ;
402
+ var hasNewExtent = s . newExtent [ 1 ] > s . newExtent [ 0 ] ;
403
+ s . extent = s . stayingIntervals . concat ( hasNewExtent ? [ s . newExtent ] : [ ] ) ;
365
404
if ( ! s . extent . length ) {
366
405
brushClear ( brush ) ;
367
406
}
368
407
s . brushCallback ( d ) ;
369
- renderHighlight ( this . parentNode , mergeIntervals ) ; // merging intervals post the snap tween
408
+ if ( hasNewExtent ) {
409
+ // merging intervals post the snap tween
410
+ renderHighlight ( this . parentNode , mergeIntervals ) ;
411
+ }
412
+ else {
413
+ // if no new interval, don't animate, just redraw the highlight immediately
414
+ mergeIntervals ( ) ;
415
+ renderHighlight ( this . parentNode ) ;
416
+ }
370
417
} else {
371
418
mergeIntervals ( ) ; // merging intervals immediately
372
419
}
0 commit comments