@@ -14,38 +14,6 @@ var keyFun = require('../../lib/gup').keyFun;
14
14
var repeat = require ( '../../lib/gup' ) . repeat ;
15
15
var sortAsc = require ( '../../lib' ) . sorterAsc ;
16
16
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
-
49
17
var snapRatio = c . bar . snapRatio ;
50
18
function snapOvershoot ( v , vAdjacent ) { return v * ( 1 - snapRatio ) + vAdjacent * snapRatio ; }
51
19
@@ -113,7 +81,7 @@ function backgroundBarHorizontalSetup(selection) {
113
81
}
114
82
115
83
function setHighlight ( d ) {
116
- if ( ! filterActive ( d . brush ) ) {
84
+ if ( ! d . brush . filterSpecified ) {
117
85
return '0,' + d . height ;
118
86
}
119
87
var pixelRanges = unitToPx ( d . brush . filter . getConsolidated ( ) , d . height ) ;
@@ -144,34 +112,14 @@ function unitToPx(unitRanges, height) {
144
112
} ) ;
145
113
}
146
114
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
-
155
115
// is the cursor over the north, middle, or south of a bar?
156
116
// 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' ;
175
123
}
176
124
177
125
function clearCursor ( ) {
@@ -188,61 +136,67 @@ function styleHighlight(selection) {
188
136
}
189
137
190
138
function renderHighlight ( root , tweenCallback ) {
191
- var bar = d3 . select ( root ) . selectAll ( '.highlight, .highlightShadow ' ) ;
139
+ var bar = d3 . select ( root ) . selectAll ( '.highlight, .highlight-shadow ' ) ;
192
140
var barToStyle = tweenCallback ? bar . transition ( ) . duration ( c . bar . snapDuration ) . each ( 'end' , tweenCallback ) : bar ;
193
141
styleHighlight ( barToStyle ) ;
194
142
}
195
143
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 = { } ;
203
149
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
+ }
216
171
}
217
172
}
218
- }
219
173
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
+ }
228
183
}
229
- }
230
-
231
- var foundInterval = ! isNaN ( closestInterval ) ;
232
184
233
- var fPix = pixIntervals [ closestInterval ] ;
185
+ if ( ! isNaN ( closestInterval ) ) {
186
+ var fPix = pixIntervals [ closestInterval ] ;
187
+ var region = getRegion ( fPix , y ) ;
234
188
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
+ }
242
196
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 ) ;
246
200
for ( i = 0 ; i < a . length ; i ++ ) {
247
201
var rangei = [
248
202
a [ Math . max ( i - 1 , 0 ) ] * 0.25 + a [ i ] * 0.75 ,
@@ -265,71 +219,57 @@ function attachDragBehavior(selection) {
265
219
selection
266
220
. on ( 'mousemove' , function ( d ) {
267
221
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 ) ;
280
231
}
281
- d3 . select ( document . body )
282
- . style ( 'cursor' , cursor ) ;
283
232
} )
284
233
. on ( 'mouseleave' , function ( d ) {
285
- if ( d . parent . inBrushDrag ) {
286
- return ;
287
- }
288
- clearCursor ( ) ;
234
+ if ( ! d . parent . inBrushDrag ) clearCursor ( ) ;
289
235
} )
290
236
. call ( d3 . behavior . drag ( )
291
237
. on ( 'dragstart' , function ( d ) {
292
- var e = d3 . event ;
293
- e . sourceEvent . stopPropagation ( ) ;
238
+ d3 . event . sourceEvent . stopPropagation ( ) ;
294
239
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 ) ;
296
241
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 ;
300
244
var s = b . svgBrush ;
301
- var active = filterActive ( b ) ;
302
- var barInteraction = unitRange && ( intData . m || intData . s || intData . n ) ;
303
245
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 ;
316
260
d . parent . inBrushDrag = true ;
317
261
s . brushStartCallback ( ) ;
318
262
} )
319
263
. 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 ;
322
266
var s = d . brush . svgBrush ;
323
267
s . wasDragged = true ;
324
- e . sourceEvent . stopPropagation ( ) ;
325
268
326
269
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 ) ;
328
271
} 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 ) ;
333
273
}
334
274
335
275
// take care of the parcoords axis height constraint: bar can't breach it
@@ -393,7 +333,7 @@ function attachDragBehavior(selection) {
393
333
} ;
394
334
395
335
if ( d . ordinal ) {
396
- var a = d . ordinalScale . range ( ) . map ( d . paddedUnitScale ) ;
336
+ var a = d . unitTickvals ;
397
337
if ( a [ a . length - 1 ] < a [ 0 ] ) a . reverse ( ) ;
398
338
s . newExtent = [
399
339
ordinalScaleSnapLo ( a , s . newExtent [ 0 ] , s . stayingIntervals ) ,
@@ -442,19 +382,19 @@ function renderAxisBrush(axisBrush) {
442
382
return d . height - c . verticalPadding ;
443
383
} ) ;
444
384
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`
446
386
447
387
highlightShadow . enter ( )
448
388
. append ( 'line' )
449
- . classed ( 'highlightShadow ' , true )
389
+ . classed ( 'highlight-shadow ' , true )
450
390
. attr ( 'x' , - c . bar . width / 2 )
451
391
. attr ( 'stroke-width' , c . bar . width + c . bar . strokeWidth )
452
392
. attr ( 'stroke' , c . bar . strokeColor )
453
393
. attr ( 'opacity' , c . bar . strokeOpacity )
454
394
. attr ( 'stroke-linecap' , 'butt' ) ;
455
395
456
396
highlightShadow
457
- . attr ( 'y1' , function ( d ) { return d . height ; } )
397
+ . attr ( 'y1' , function ( d ) { return d . height ; } )
458
398
. call ( styleHighlight ) ;
459
399
460
400
var highlight = axisBrush . selectAll ( '.highlight' ) . data ( repeat ) ; // we have a set here, can't call it `extent`
@@ -469,7 +409,7 @@ function renderAxisBrush(axisBrush) {
469
409
. attr ( 'stroke-linecap' , 'butt' ) ;
470
410
471
411
highlight
472
- . attr ( 'y1' , function ( d ) { return d . height ; } )
412
+ . attr ( 'y1' , function ( d ) { return d . height ; } )
473
413
. call ( styleHighlight ) ;
474
414
}
475
415
@@ -493,11 +433,6 @@ function brushClear(brush) {
493
433
brush . svgBrush . extent = [ [ 0 , 1 ] ] ;
494
434
}
495
435
496
-
497
- function filterActive ( brush ) {
498
- return brush . filterSpecified ;
499
- }
500
-
501
436
function axisBrushMoved ( callback ) {
502
437
return function axisBrushMoved ( dimension ) {
503
438
var brush = dimension . brush ;
@@ -589,9 +524,7 @@ function cleanRanges(ranges, dimension) {
589
524
}
590
525
591
526
module . exports = {
592
- addFilterBarDefs : addFilterBarDefs ,
593
527
makeBrush : makeBrush ,
594
528
ensureAxisBrush : ensureAxisBrush ,
595
- filterActive : filterActive ,
596
529
cleanRanges : cleanRanges
597
530
} ;
0 commit comments