@@ -193,13 +193,15 @@ function renderHighlight(root, tweenCallback) {
193193 styleHighlight ( barToStyle ) ;
194194}
195195
196- function getInterval ( b , height , y ) {
196+ function getInterval ( b , d , y ) {
197+ var height = d . height ;
197198 var intervals = b . filter . getConsolidated ( ) ;
198199 var pixIntervals = unitToPx ( intervals , height ) ;
199200 var hoveredInterval = NaN ;
200201 var previousInterval = NaN ;
201202 var nextInterval = NaN ;
202- for ( var i = 0 ; i <= pixIntervals . length ; i ++ ) {
203+ var i ;
204+ for ( i = 0 ; i <= pixIntervals . length ; i ++ ) {
203205 var p = pixIntervals [ i ] ;
204206 if ( p && p [ 0 ] <= y && y <= p [ 1 ] ) {
205207 // over a bar
@@ -226,15 +228,34 @@ function getInterval(b, height, y) {
226228 }
227229 }
228230
231+ var foundInterval = ! isNaN ( closestInterval ) ;
232+
229233 var fPix = pixIntervals [ closestInterval ] ;
230234
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
234238 n : north ( fPix , y ) , // do we hover over the northern resize hotspot
235239 s : south ( fPix , y ) , // do we hover over the northern resize hotspot
236240 m : middle ( fPix , y ) // or over the bar section itself?
237241 } ;
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 ;
238259}
239260
240261function attachDragBehavior ( selection ) {
@@ -249,9 +270,16 @@ function attachDragBehavior(selection) {
249270 return ;
250271 }
251272 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+ }
253281 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 ) ;
255283 } )
256284 . on ( 'mouseleave' , function ( d ) {
257285 if ( d . parent . inBrushDrag ) {
@@ -266,7 +294,7 @@ function attachDragBehavior(selection) {
266294 var y = d . height - d3 . mouse ( this ) [ 1 ] - 2 * c . verticalPadding ;
267295 var unitLocation = d . unitScaleInOrder . invert ( y ) ;
268296 var b = d . brush ;
269- var intData = getInterval ( b , d . height , y ) ;
297+ var intData = getInterval ( b , d , y ) ;
270298 var unitRange = intData . interval ;
271299 var pixelRange = unitRange . map ( d . unitScaleInOrder ) ;
272300 var s = b . svgBrush ;
@@ -276,12 +304,13 @@ function attachDragBehavior(selection) {
276304 s . grabPoint = d . unitScaleInOrder ( unitLocation ) - pixelRange [ 0 ] - c . verticalPadding ;
277305 s . barLength = pixelRange [ 1 ] - pixelRange [ 0 ] ;
278306 s . grabbingBar = active && intData . m && unitRange ;
307+ s . clickableOrdinalRange = intData . clickableOrdinalRange ;
279308 s . stayingIntervals = ! d . multiselect ? [ ] :
280309 barInteraction ?
281310 b . filter . get ( ) . filter ( differentInterval ( unitRange ) ) :
282311 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 ;
285314 var newBrushing = ! s . grabbingBar && ! grabbingBarNorth && ! grabbingBarSouth ;
286315 s . startExtent = newBrushing ? unitLocation : unitRange [ grabbingBarSouth ? 1 : 0 ] ;
287316 d . parent . inBrushDrag = true ;
@@ -333,8 +362,17 @@ function attachDragBehavior(selection) {
333362 d . parent . inBrushDrag = false ;
334363 clearCursor ( ) ; // instead of clearing, a nicer thing would be to set it according to current location
335364 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 ) {
338376 s . extent = s . stayingIntervals ;
339377 if ( s . extent . length === 0 ) {
340378 brushClear ( brush ) ;
@@ -361,12 +399,21 @@ function attachDragBehavior(selection) {
361399 ordinalScaleSnapLo ( a , s . newExtent [ 0 ] , s . stayingIntervals ) ,
362400 ordinalScaleSnapHi ( a , s . newExtent [ 1 ] , s . stayingIntervals )
363401 ] ;
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 ] : [ ] ) ;
365404 if ( ! s . extent . length ) {
366405 brushClear ( brush ) ;
367406 }
368407 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+ }
370417 } else {
371418 mergeIntervals ( ) ; // merging intervals immediately
372419 }
0 commit comments