@@ -14,38 +14,6 @@ var keyFun = require('../../lib/gup').keyFun;
1414var repeat = require ( '../../lib/gup' ) . repeat ;
1515var sortAsc = require ( '../../lib' ) . sorterAsc ;
1616
17- function addFilterBarDefs ( defs ) {
18- var filterBarPattern = defs . selectAll ( '#' + c . id . filterBarPattern )
19- . data ( repeat , keyFun ) ;
20-
21- filterBarPattern . enter ( )
22- . append ( 'pattern' )
23- . attr ( 'id' , c . id . filterBarPattern )
24- . attr ( 'patternUnits' , 'userSpaceOnUse' ) ;
25-
26- filterBarPattern
27- . attr ( 'x' , - c . bar . width )
28- . attr ( 'width' , c . bar . captureWidth )
29- . attr ( 'height' , function ( d ) { return d . model . height ; } ) ;
30-
31- var filterBarPatternGlyph = filterBarPattern . selectAll ( 'rect' )
32- . data ( repeat , keyFun ) ;
33-
34- filterBarPatternGlyph . enter ( )
35- . append ( 'rect' )
36- . attr ( 'shape-rendering' , 'crispEdges' ) ;
37-
38- filterBarPatternGlyph
39- . attr ( 'height' , function ( d ) { return d . model . height ; } )
40- . attr ( 'width' , c . bar . width )
41- . attr ( 'x' , c . bar . width / 2 )
42- . attr ( 'fill' , c . bar . fillColor )
43- . attr ( 'fill-opacity' , c . bar . fillOpacity )
44- . attr ( 'stroke' , c . bar . strokeColor )
45- . attr ( 'stroke-opacity' , c . bar . strokeOpacity )
46- . attr ( 'stroke-width' , c . bar . strokeWidth ) ;
47- }
48-
4917var snapRatio = c . bar . snapRatio ;
5018function snapOvershoot ( v , vAdjacent ) { return v * ( 1 - snapRatio ) + vAdjacent * snapRatio ; }
5119
@@ -113,7 +81,7 @@ function backgroundBarHorizontalSetup(selection) {
11381}
11482
11583function setHighlight ( d ) {
116- if ( ! filterActive ( d . brush ) ) {
84+ if ( ! d . brush . filterSpecified ) {
11785 return '0,' + d . height ;
11886 }
11987 var pixelRanges = unitToPx ( d . brush . filter . getConsolidated ( ) , d . height ) ;
@@ -144,34 +112,14 @@ function unitToPx(unitRanges, height) {
144112 } ) ;
145113}
146114
147- function differentInterval ( int1 ) {
148- // An interval is different if the extents don't match, which is a safe test only because the intervals
149- // get consolidated anyway (ie. the identity of overlapping intervals won't be preserved; they get fused)
150- return function ( int2 ) {
151- return int1 [ 0 ] !== int2 [ 0 ] || int1 [ 1 ] !== int2 [ 1 ] ;
152- } ;
153- }
154-
155115// is the cursor over the north, middle, or south of a bar?
156116// the end handles extend over the last 10% of the bar
157- function north ( fPix , y ) {
158- return north90 ( fPix ) <= y && y <= fPix [ 1 ] + c . bar . handleHeight ;
159- }
160-
161- function south ( fPix , y ) {
162- return fPix [ 0 ] - c . bar . handleHeight <= y && y <= south90 ( fPix ) ;
163- }
164-
165- function middle ( fPix , y ) {
166- return south90 ( fPix ) < y && y < north90 ( fPix ) ;
167- }
168-
169- function north90 ( fPix ) {
170- return 0.9 * fPix [ 1 ] + 0.1 * fPix [ 0 ] ;
171- }
172-
173- function south90 ( fPix ) {
174- return 0.9 * fPix [ 0 ] + 0.1 * fPix [ 1 ] ;
117+ function getRegion ( fPix , y ) {
118+ var pad = c . bar . handleHeight ;
119+ if ( y > fPix [ 1 ] + pad || y < fPix [ 0 ] - pad ) return ;
120+ if ( y >= 0.9 * fPix [ 1 ] + 0.1 * fPix [ 0 ] ) return 'n' ;
121+ if ( y <= 0.9 * fPix [ 0 ] + 0.1 * fPix [ 1 ] ) return 's' ;
122+ return 'ns' ;
175123}
176124
177125function clearCursor ( ) {
@@ -188,61 +136,67 @@ function styleHighlight(selection) {
188136}
189137
190138function renderHighlight ( root , tweenCallback ) {
191- var bar = d3 . select ( root ) . selectAll ( '.highlight, .highlightShadow ' ) ;
139+ var bar = d3 . select ( root ) . selectAll ( '.highlight, .highlight-shadow ' ) ;
192140 var barToStyle = tweenCallback ? bar . transition ( ) . duration ( c . bar . snapDuration ) . each ( 'end' , tweenCallback ) : bar ;
193141 styleHighlight ( barToStyle ) ;
194142}
195143
196- function getInterval ( b , d , y ) {
197- var height = d . height ;
198- var intervals = b . filter . getConsolidated ( ) ;
199- var pixIntervals = unitToPx ( intervals , height ) ;
200- var hoveredInterval = NaN ;
201- var previousInterval = NaN ;
202- var nextInterval = NaN ;
144+ function getInterval ( d , y ) {
145+ var b = d . brush ;
146+ var active = b . filterSpecified ;
147+ var closestInterval = NaN ;
148+ var out = { } ;
203149 var i ;
204- for ( i = 0 ; i <= pixIntervals . length ; i ++ ) {
205- var p = pixIntervals [ i ] ;
206- if ( p && p [ 0 ] <= y && y <= p [ 1 ] ) {
207- // over a bar
208- hoveredInterval = i ;
209- break ;
210- } else {
211- // between bars, or before/after the first/last bar
212- previousInterval = i ? i - 1 : NaN ;
213- if ( p && p [ 0 ] > y ) {
214- nextInterval = i ;
215- break ; // no point continuing as intervals are non-overlapping and sorted; could use log search
150+
151+ if ( active ) {
152+ var height = d . height ;
153+ var intervals = b . filter . getConsolidated ( ) ;
154+ var pixIntervals = unitToPx ( intervals , height ) ;
155+ var hoveredInterval = NaN ;
156+ var previousInterval = NaN ;
157+ var nextInterval = NaN ;
158+ for ( i = 0 ; i <= pixIntervals . length ; i ++ ) {
159+ var p = pixIntervals [ i ] ;
160+ if ( p && p [ 0 ] <= y && y <= p [ 1 ] ) {
161+ // over a bar
162+ hoveredInterval = i ;
163+ break ;
164+ } else {
165+ // between bars, or before/after the first/last bar
166+ previousInterval = i ? i - 1 : NaN ;
167+ if ( p && p [ 0 ] > y ) {
168+ nextInterval = i ;
169+ break ; // no point continuing as intervals are non-overlapping and sorted; could use log search
170+ }
216171 }
217172 }
218- }
219173
220- var closestInterval = hoveredInterval ;
221- if ( isNaN ( closestInterval ) ) {
222- if ( isNaN ( previousInterval ) || isNaN ( nextInterval ) ) {
223- closestInterval = isNaN ( previousInterval ) ? nextInterval : previousInterval ;
224- }
225- else {
226- closestInterval = ( y - pixIntervals [ previousInterval ] [ 1 ] < pixIntervals [ nextInterval ] [ 0 ] - y ) ?
227- previousInterval : nextInterval ;
174+ closestInterval = hoveredInterval ;
175+ if ( isNaN ( closestInterval ) ) {
176+ if ( isNaN ( previousInterval ) || isNaN ( nextInterval ) ) {
177+ closestInterval = isNaN ( previousInterval ) ? nextInterval : previousInterval ;
178+ }
179+ else {
180+ closestInterval = ( y - pixIntervals [ previousInterval ] [ 1 ] < pixIntervals [ nextInterval ] [ 0 ] - y ) ?
181+ previousInterval : nextInterval ;
182+ }
228183 }
229- }
230-
231- var foundInterval = ! isNaN ( closestInterval ) ;
232184
233- var fPix = pixIntervals [ closestInterval ] ;
185+ if ( ! isNaN ( closestInterval ) ) {
186+ var fPix = pixIntervals [ closestInterval ] ;
187+ var region = getRegion ( fPix , y ) ;
234188
235- var out = {
236- interval : foundInterval ? intervals [ closestInterval ] : null , // activated interval in domain terms
237- intervalPix : foundInterval ? fPix : null , // activated interval in pixel terms
238- n : north ( fPix , y ) , // do we hover over the northern resize hotspot
239- s : south ( fPix , y ) , // do we hover over the northern resize hotspot
240- m : middle ( fPix , y ) // or over the bar section itself?
241- } ;
189+ if ( region ) {
190+ out . interval = intervals [ closestInterval ] ;
191+ out . intervalPix = fPix ;
192+ out . region = region ;
193+ }
194+ }
195+ }
242196
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 ) ;
197+ if ( d . ordinal && ! out . region ) {
198+ var a = d . unitTickvals ;
199+ var unitLocation = d . unitToPaddedPx . invert ( y ) ;
246200 for ( i = 0 ; i < a . length ; i ++ ) {
247201 var rangei = [
248202 a [ Math . max ( i - 1 , 0 ) ] * 0.25 + a [ i ] * 0.75 ,
@@ -265,71 +219,57 @@ function attachDragBehavior(selection) {
265219 selection
266220 . on ( 'mousemove' , function ( d ) {
267221 d3 . event . preventDefault ( ) ;
268- var b = d . brush ;
269- if ( d . parent . inBrushDrag ) {
270- return ;
271- }
272- var y = d . height - d3 . mouse ( this ) [ 1 ] - 2 * c . verticalPadding ;
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' ;
222+ if ( ! d . parent . inBrushDrag ) {
223+ var y = d . height - d3 . mouse ( this ) [ 1 ] - 2 * c . verticalPadding ;
224+ var interval = getInterval ( d , y ) ;
225+
226+ var cursor = 'crosshair' ;
227+ if ( interval . clickableOrdinalRange ) cursor = 'pointer' ;
228+ else if ( interval . region ) cursor = interval . region + '-resize' ;
229+ d3 . select ( document . body )
230+ . style ( 'cursor' , cursor ) ;
280231 }
281- d3 . select ( document . body )
282- . style ( 'cursor' , cursor ) ;
283232 } )
284233 . on ( 'mouseleave' , function ( d ) {
285- if ( d . parent . inBrushDrag ) {
286- return ;
287- }
288- clearCursor ( ) ;
234+ if ( ! d . parent . inBrushDrag ) clearCursor ( ) ;
289235 } )
290236 . call ( d3 . behavior . drag ( )
291237 . on ( 'dragstart' , function ( d ) {
292- var e = d3 . event ;
293- e . sourceEvent . stopPropagation ( ) ;
238+ d3 . event . sourceEvent . stopPropagation ( ) ;
294239 var y = d . height - d3 . mouse ( this ) [ 1 ] - 2 * c . verticalPadding ;
295- var unitLocation = d . unitScaleInOrder . invert ( y ) ;
240+ var unitLocation = d . unitToPaddedPx . invert ( y ) ;
296241 var b = d . brush ;
297- var intData = getInterval ( b , d , y ) ;
298- var unitRange = intData . interval ;
299- var pixelRange = unitRange . map ( d . unitScaleInOrder ) ;
242+ var interval = getInterval ( d , y ) ;
243+ var unitRange = interval . interval ;
300244 var s = b . svgBrush ;
301- var active = filterActive ( b ) ;
302- var barInteraction = unitRange && ( intData . m || intData . s || intData . n ) ;
303245 s . wasDragged = false ; // we start assuming there won't be a drag - useful for reset
304- s . grabPoint = d . unitScaleInOrder ( unitLocation ) - pixelRange [ 0 ] - c . verticalPadding ;
305- s . barLength = pixelRange [ 1 ] - pixelRange [ 0 ] ;
306- s . grabbingBar = active && intData . m && unitRange ;
307- s . clickableOrdinalRange = intData . clickableOrdinalRange ;
308- s . stayingIntervals = ! d . multiselect ? [ ] :
309- barInteraction ?
310- b . filter . get ( ) . filter ( differentInterval ( unitRange ) ) :
311- b . filter . get ( ) ; // keep all preexisting bars if interaction wasn't a barInteraction
312- var grabbingBarNorth = active && intData . n ;
313- var grabbingBarSouth = active && intData . s ;
314- var newBrushing = ! s . grabbingBar && ! grabbingBarNorth && ! grabbingBarSouth ;
315- s . startExtent = newBrushing ? unitLocation : unitRange [ grabbingBarSouth ? 1 : 0 ] ;
246+ s . grabbingBar = interval . region === 'ns' ;
247+ if ( s . grabbingBar ) {
248+ var pixelRange = unitRange . map ( d . unitToPaddedPx ) ;
249+ s . grabPoint = y - pixelRange [ 0 ] - c . verticalPadding ;
250+ s . barLength = pixelRange [ 1 ] - pixelRange [ 0 ] ;
251+ }
252+ s . clickableOrdinalRange = interval . clickableOrdinalRange ;
253+ s . stayingIntervals = ( d . multiselect && b . filterSpecified ) ? b . filter . getConsolidated ( ) : [ ] ;
254+ if ( unitRange ) {
255+ s . stayingIntervals = s . stayingIntervals . filter ( function ( int2 ) {
256+ return int2 [ 0 ] !== unitRange [ 0 ] && int2 [ 1 ] !== unitRange [ 1 ] ;
257+ } ) ;
258+ }
259+ s . startExtent = interval . region ? unitRange [ interval . region === 's' ? 1 : 0 ] : unitLocation ;
316260 d . parent . inBrushDrag = true ;
317261 s . brushStartCallback ( ) ;
318262 } )
319263 . on ( 'drag' , function ( d ) {
320- var e = d3 . event ;
321- var y = d . unitScaleInOrder ( d . unitScale . invert ( e . y + c . verticalPadding ) ) ;
264+ d3 . event . sourceEvent . stopPropagation ( ) ;
265+ var y = d . height - d3 . mouse ( this ) [ 1 ] - 2 * c . verticalPadding ;
322266 var s = d . brush . svgBrush ;
323267 s . wasDragged = true ;
324- e . sourceEvent . stopPropagation ( ) ;
325268
326269 if ( s . grabbingBar ) { // moving the bar
327- s . newExtent = [ y - s . grabPoint , y + s . barLength - s . grabPoint ] . map ( d . unitScaleInOrder . invert ) ;
270+ s . newExtent = [ y - s . grabPoint , y + s . barLength - s . grabPoint ] . map ( d . unitToPaddedPx . invert ) ;
328271 } else { // south/north drag or new bar creation
329- var endExtent = d . unitScaleInOrder . invert ( y ) ;
330- s . newExtent = s . startExtent < endExtent ?
331- [ s . startExtent , endExtent ] :
332- [ endExtent , s . startExtent ] ;
272+ s . newExtent = [ s . startExtent , d . unitToPaddedPx . invert ( y ) ] . sort ( sortAsc ) ;
333273 }
334274
335275 // take care of the parcoords axis height constraint: bar can't breach it
@@ -393,7 +333,7 @@ function attachDragBehavior(selection) {
393333 } ;
394334
395335 if ( d . ordinal ) {
396- var a = d . ordinalScale . range ( ) . map ( d . paddedUnitScale ) ;
336+ var a = d . unitTickvals ;
397337 if ( a [ a . length - 1 ] < a [ 0 ] ) a . reverse ( ) ;
398338 s . newExtent = [
399339 ordinalScaleSnapLo ( a , s . newExtent [ 0 ] , s . stayingIntervals ) ,
@@ -442,19 +382,19 @@ function renderAxisBrush(axisBrush) {
442382 return d . height - c . verticalPadding ;
443383 } ) ;
444384
445- var highlightShadow = axisBrush . selectAll ( '.highlightShadow ' ) . data ( repeat ) ; // we have a set here, can't call it `extent`
385+ var highlightShadow = axisBrush . selectAll ( '.highlight-shadow ' ) . data ( repeat ) ; // we have a set here, can't call it `extent`
446386
447387 highlightShadow . enter ( )
448388 . append ( 'line' )
449- . classed ( 'highlightShadow ' , true )
389+ . classed ( 'highlight-shadow ' , true )
450390 . attr ( 'x' , - c . bar . width / 2 )
451391 . attr ( 'stroke-width' , c . bar . width + c . bar . strokeWidth )
452392 . attr ( 'stroke' , c . bar . strokeColor )
453393 . attr ( 'opacity' , c . bar . strokeOpacity )
454394 . attr ( 'stroke-linecap' , 'butt' ) ;
455395
456396 highlightShadow
457- . attr ( 'y1' , function ( d ) { return d . height ; } )
397+ . attr ( 'y1' , function ( d ) { return d . height ; } )
458398 . call ( styleHighlight ) ;
459399
460400 var highlight = axisBrush . selectAll ( '.highlight' ) . data ( repeat ) ; // we have a set here, can't call it `extent`
@@ -469,7 +409,7 @@ function renderAxisBrush(axisBrush) {
469409 . attr ( 'stroke-linecap' , 'butt' ) ;
470410
471411 highlight
472- . attr ( 'y1' , function ( d ) { return d . height ; } )
412+ . attr ( 'y1' , function ( d ) { return d . height ; } )
473413 . call ( styleHighlight ) ;
474414}
475415
@@ -493,11 +433,6 @@ function brushClear(brush) {
493433 brush . svgBrush . extent = [ [ 0 , 1 ] ] ;
494434}
495435
496-
497- function filterActive ( brush ) {
498- return brush . filterSpecified ;
499- }
500-
501436function axisBrushMoved ( callback ) {
502437 return function axisBrushMoved ( dimension ) {
503438 var brush = dimension . brush ;
@@ -589,9 +524,7 @@ function cleanRanges(ranges, dimension) {
589524}
590525
591526module . exports = {
592- addFilterBarDefs : addFilterBarDefs ,
593527 makeBrush : makeBrush ,
594528 ensureAxisBrush : ensureAxisBrush ,
595- filterActive : filterActive ,
596529 cleanRanges : cleanRanges
597530} ;
0 commit comments