@@ -365,176 +365,178 @@ function _hover(gd, evt, subplot, noHoverEvent) {
365
365
// find the closest point in each trace
366
366
// this is minimum dx and/or dy, depending on mode
367
367
// and the pixel position for the label (labelXpx, labelYpx)
368
- for ( curvenum = 0 ; curvenum < searchData . length ; curvenum ++ ) {
369
- cd = searchData [ curvenum ] ;
368
+ function findHoverPoints ( vals ) {
369
+ for ( curvenum = 0 ; curvenum < searchData . length ; curvenum ++ ) {
370
+ cd = searchData [ curvenum ] ;
370
371
371
- // filter out invisible or broken data
372
- if ( ! cd || ! cd [ 0 ] || ! cd [ 0 ] . trace ) continue ;
372
+ // filter out invisible or broken data
373
+ if ( ! cd || ! cd [ 0 ] || ! cd [ 0 ] . trace ) continue ;
373
374
374
- trace = cd [ 0 ] . trace ;
375
+ trace = cd [ 0 ] . trace ;
375
376
376
- if ( trace . visible !== true || trace . _length === 0 ) continue ;
377
+ if ( trace . visible !== true || trace . _length === 0 ) continue ;
377
378
378
- // Explicitly bail out for these two. I don't know how to otherwise prevent
379
- // the rest of this function from running and failing
380
- if ( [ 'carpet' , 'contourcarpet' ] . indexOf ( trace . _module . name ) !== - 1 ) continue ;
379
+ // Explicitly bail out for these two. I don't know how to otherwise prevent
380
+ // the rest of this function from running and failing
381
+ if ( [ 'carpet' , 'contourcarpet' ] . indexOf ( trace . _module . name ) !== - 1 ) continue ;
381
382
382
- if ( trace . type === 'splom' ) {
383
- // splom traces do not generate overlay subplots,
384
- // it is safe to assume here splom traces correspond to the 0th subplot
385
- subploti = 0 ;
386
- subplotId = subplots [ subploti ] ;
387
- } else {
388
- subplotId = helpers . getSubplot ( trace ) ;
389
- subploti = subplots . indexOf ( subplotId ) ;
390
- }
391
-
392
- // within one trace mode can sometimes be overridden
393
- mode = hovermode ;
394
- if ( [ 'x unified' , 'y unified' ] . indexOf ( mode ) !== - 1 ) {
395
- mode = mode . charAt ( 0 ) ;
396
- }
397
-
398
- // container for new point, also used to pass info into module.hoverPoints
399
- pointData = {
400
- // trace properties
401
- cd : cd ,
402
- trace : trace ,
403
- xa : xaArray [ subploti ] ,
404
- ya : yaArray [ subploti ] ,
405
-
406
- // max distances for hover and spikes - for points that want to show but do not
407
- // want to override other points, set distance/spikeDistance equal to max*Distance
408
- // and it will not get filtered out but it will be guaranteed to have a greater
409
- // distance than any point that calculated a real distance.
410
- maxHoverDistance : hoverdistance ,
411
- maxSpikeDistance : spikedistance ,
412
-
413
- // point properties - override all of these
414
- index : false , // point index in trace - only used by plotly.js hoverdata consumers
415
- distance : Math . min ( distance , hoverdistance ) , // pixel distance or pseudo-distance
416
-
417
- // distance/pseudo-distance for spikes. This distance should always be calculated
418
- // as if in "closest" mode, and should only be set if this point should
419
- // generate a spike.
420
- spikeDistance : Infinity ,
421
-
422
- // in some cases the spikes have different positioning from the hover label
423
- // they don't need x0/x1, just one position
424
- xSpike : undefined ,
425
- ySpike : undefined ,
426
-
427
- // where and how to display the hover label
428
- color : Color . defaultLine , // trace color
429
- name : trace . name ,
430
- x0 : undefined ,
431
- x1 : undefined ,
432
- y0 : undefined ,
433
- y1 : undefined ,
434
- xLabelVal : undefined ,
435
- yLabelVal : undefined ,
436
- zLabelVal : undefined ,
437
- text : undefined
438
- } ;
383
+ if ( trace . type === 'splom' ) {
384
+ // splom traces do not generate overlay subplots,
385
+ // it is safe to assume here splom traces correspond to the 0th subplot
386
+ subploti = 0 ;
387
+ subplotId = subplots [ subploti ] ;
388
+ } else {
389
+ subplotId = helpers . getSubplot ( trace ) ;
390
+ subploti = subplots . indexOf ( subplotId ) ;
391
+ }
439
392
440
- // add ref to subplot object (non-cartesian case)
441
- if ( fullLayout [ subplotId ] ) {
442
- pointData . subplot = fullLayout [ subplotId ] . _subplot ;
443
- }
444
- // add ref to splom scene
445
- if ( fullLayout . _splomScenes && fullLayout . _splomScenes [ trace . uid ] ) {
446
- pointData . scene = fullLayout . _splomScenes [ trace . uid ] ;
447
- }
393
+ // within one trace mode can sometimes be overridden
394
+ mode = hovermode ;
395
+ if ( [ 'x unified' , 'y unified' ] . indexOf ( mode ) !== - 1 ) {
396
+ mode = mode . charAt ( 0 ) ;
397
+ }
448
398
449
- closedataPreviousLength = hoverData . length ;
399
+ // container for new point, also used to pass info into module.hoverPoints
400
+ pointData = {
401
+ // trace properties
402
+ cd : cd ,
403
+ trace : trace ,
404
+ xa : xaArray [ subploti ] ,
405
+ ya : yaArray [ subploti ] ,
406
+
407
+ // max distances for hover and spikes - for points that want to show but do not
408
+ // want to override other points, set distance/spikeDistance equal to max*Distance
409
+ // and it will not get filtered out but it will be guaranteed to have a greater
410
+ // distance than any point that calculated a real distance.
411
+ maxHoverDistance : hoverdistance ,
412
+ maxSpikeDistance : spikedistance ,
413
+
414
+ // point properties - override all of these
415
+ index : false , // point index in trace - only used by plotly.js hoverdata consumers
416
+ distance : Math . min ( distance , hoverdistance ) , // pixel distance or pseudo-distance
417
+
418
+ // distance/pseudo-distance for spikes. This distance should always be calculated
419
+ // as if in "closest" mode, and should only be set if this point should
420
+ // generate a spike.
421
+ spikeDistance : Infinity ,
422
+
423
+ // in some cases the spikes have different positioning from the hover label
424
+ // they don't need x0/x1, just one position
425
+ xSpike : undefined ,
426
+ ySpike : undefined ,
427
+
428
+ // where and how to display the hover label
429
+ color : Color . defaultLine , // trace color
430
+ name : trace . name ,
431
+ x0 : undefined ,
432
+ x1 : undefined ,
433
+ y0 : undefined ,
434
+ y1 : undefined ,
435
+ xLabelVal : undefined ,
436
+ yLabelVal : undefined ,
437
+ zLabelVal : undefined ,
438
+ text : undefined
439
+ } ;
440
+
441
+ // add ref to subplot object (non-cartesian case)
442
+ if ( fullLayout [ subplotId ] ) {
443
+ pointData . subplot = fullLayout [ subplotId ] . _subplot ;
444
+ }
445
+ // add ref to splom scene
446
+ if ( fullLayout . _splomScenes && fullLayout . _splomScenes [ trace . uid ] ) {
447
+ pointData . scene = fullLayout . _splomScenes [ trace . uid ] ;
448
+ }
450
449
451
- // for a highlighting array, figure out what
452
- // we're searching for with this element
453
- if ( mode === 'array' ) {
454
- var selection = evt [ curvenum ] ;
455
- if ( 'pointNumber' in selection ) {
456
- pointData . index = selection . pointNumber ;
457
- mode = 'closest' ;
458
- } else {
459
- mode = '' ;
460
- if ( 'xval' in selection ) {
461
- xval = selection . xval ;
462
- mode = 'x' ;
463
- }
464
- if ( 'yval' in selection ) {
465
- yval = selection . yval ;
466
- mode = mode ? 'closest' : 'y' ;
450
+ closedataPreviousLength = hoverData . length ;
451
+
452
+ // for a highlighting array, figure out what
453
+ // we're searching for with this element
454
+ if ( mode === 'array' ) {
455
+ var selection = evt [ curvenum ] ;
456
+ if ( 'pointNumber' in selection ) {
457
+ pointData . index = selection . pointNumber ;
458
+ mode = 'closest' ;
459
+ } else {
460
+ mode = '' ;
461
+ if ( 'xval' in selection ) {
462
+ xval = selection . xval ;
463
+ mode = 'x' ;
464
+ }
465
+ if ( 'yval' in selection ) {
466
+ yval = selection . yval ;
467
+ mode = mode ? 'closest' : 'y' ;
468
+ }
467
469
}
470
+ } else {
471
+ xval = xvalArray [ subploti ] ;
472
+ yval = yvalArray [ subploti ] ;
468
473
}
469
- } else {
470
- xval = xvalArray [ subploti ] ;
471
- yval = yvalArray [ subploti ] ;
472
- }
473
474
474
- // Now if there is range to look in, find the points to hover.
475
- if ( hoverdistance !== 0 ) {
476
- if ( trace . _module && trace . _module . hoverPoints ) {
477
- var newPoints = trace . _module . hoverPoints ( pointData , xval , yval , mode , fullLayout . _hoverlayer ) ;
478
- if ( newPoints ) {
479
- var newPoint ;
480
- for ( var newPointNum = 0 ; newPointNum < newPoints . length ; newPointNum ++ ) {
481
- newPoint = newPoints [ newPointNum ] ;
482
- if ( isNumeric ( newPoint . x0 ) && isNumeric ( newPoint . y0 ) ) {
483
- hoverData . push ( cleanPoint ( newPoint , hovermode ) ) ;
475
+ // Now if there is range to look in, find the points to hover.
476
+ if ( hoverdistance !== 0 ) {
477
+ if ( trace . _module && trace . _module . hoverPoints ) {
478
+ var newPoints = trace . _module . hoverPoints ( pointData , xval , yval , mode , fullLayout . _hoverlayer ) ;
479
+ if ( newPoints ) {
480
+ var newPoint ;
481
+ for ( var newPointNum = 0 ; newPointNum < newPoints . length ; newPointNum ++ ) {
482
+ newPoint = newPoints [ newPointNum ] ;
483
+ if ( isNumeric ( newPoint . x0 ) && isNumeric ( newPoint . y0 ) ) {
484
+ hoverData . push ( cleanPoint ( newPoint , hovermode ) ) ;
485
+ }
484
486
}
485
487
}
488
+ } else {
489
+ Lib . log ( 'Unrecognized trace type in hover:' , trace ) ;
486
490
}
487
- } else {
488
- Lib . log ( 'Unrecognized trace type in hover:' , trace ) ;
489
491
}
490
- }
491
492
492
- // in closest mode, remove any existing (farther) points
493
- // and don't look any farther than this latest point (or points, some
494
- // traces like box & violin make multiple hover labels at once)
495
- if ( hovermode === 'closest' && hoverData . length > closedataPreviousLength ) {
496
- hoverData . splice ( 0 , closedataPreviousLength ) ;
497
- distance = hoverData [ 0 ] . distance ;
498
- }
493
+ // in closest mode, remove any existing (farther) points
494
+ // and don't look any farther than this latest point (or points, some
495
+ // traces like box & violin make multiple hover labels at once)
496
+ if ( hovermode === 'closest' && hoverData . length > closedataPreviousLength ) {
497
+ hoverData . splice ( 0 , closedataPreviousLength ) ;
498
+ distance = hoverData [ 0 ] . distance ;
499
+ }
499
500
500
- // Now if there is range to look in, find the points to draw the spikelines
501
- // Do it only if there is no hoverData
502
- if ( hasCartesian && ( spikedistance !== 0 ) ) {
503
- if ( hoverData . length === 0 ) {
504
- pointData . distance = spikedistance ;
505
- pointData . index = false ;
506
- var closestPoints = trace . _module . hoverPoints ( pointData , xval , yval , 'closest' , fullLayout . _hoverlayer ) ;
507
- if ( closestPoints ) {
508
- closestPoints = closestPoints . filter ( function ( point ) {
509
- // some hover points, like scatter fills, do not allow spikes,
510
- // so will generate a hover point but without a valid spikeDistance
511
- return point . spikeDistance <= spikedistance ;
512
- } ) ;
513
- }
514
- if ( closestPoints && closestPoints . length ) {
515
- var tmpPoint ;
516
- var closestVPoints = closestPoints . filter ( function ( point ) {
517
- return point . xa . showspikes ;
518
- } ) ;
519
- if ( closestVPoints . length ) {
520
- var closestVPt = closestVPoints [ 0 ] ;
521
- if ( isNumeric ( closestVPt . x0 ) && isNumeric ( closestVPt . y0 ) ) {
522
- tmpPoint = fillSpikePoint ( closestVPt ) ;
523
- if ( ! spikePoints . vLinePoint || ( spikePoints . vLinePoint . spikeDistance > tmpPoint . spikeDistance ) ) {
524
- spikePoints . vLinePoint = tmpPoint ;
501
+ // Now if there is range to look in, find the points to draw the spikelines
502
+ // Do it only if there is no hoverData
503
+ if ( hasCartesian && ( spikedistance !== 0 ) ) {
504
+ if ( hoverData . length === 0 ) {
505
+ pointData . distance = spikedistance ;
506
+ pointData . index = false ;
507
+ var closestPoints = trace . _module . hoverPoints ( pointData , xval , yval , 'closest' , fullLayout . _hoverlayer ) ;
508
+ if ( closestPoints ) {
509
+ closestPoints = closestPoints . filter ( function ( point ) {
510
+ // some hover points, like scatter fills, do not allow spikes,
511
+ // so will generate a hover point but without a valid spikeDistance
512
+ return point . spikeDistance <= spikedistance ;
513
+ } ) ;
514
+ }
515
+ if ( closestPoints && closestPoints . length ) {
516
+ var tmpPoint ;
517
+ var closestVPoints = closestPoints . filter ( function ( point ) {
518
+ return point . xa . showspikes ;
519
+ } ) ;
520
+ if ( closestVPoints . length ) {
521
+ var closestVPt = closestVPoints [ 0 ] ;
522
+ if ( isNumeric ( closestVPt . x0 ) && isNumeric ( closestVPt . y0 ) ) {
523
+ tmpPoint = fillSpikePoint ( closestVPt ) ;
524
+ if ( ! spikePoints . vLinePoint || ( spikePoints . vLinePoint . spikeDistance > tmpPoint . spikeDistance ) ) {
525
+ spikePoints . vLinePoint = tmpPoint ;
526
+ }
525
527
}
526
528
}
527
- }
528
529
529
- var closestHPoints = closestPoints . filter ( function ( point ) {
530
- return point . ya . showspikes ;
531
- } ) ;
532
- if ( closestHPoints . length ) {
533
- var closestHPt = closestHPoints [ 0 ] ;
534
- if ( isNumeric ( closestHPt . x0 ) && isNumeric ( closestHPt . y0 ) ) {
535
- tmpPoint = fillSpikePoint ( closestHPt ) ;
536
- if ( ! spikePoints . hLinePoint || ( spikePoints . hLinePoint . spikeDistance > tmpPoint . spikeDistance ) ) {
537
- spikePoints . hLinePoint = tmpPoint ;
530
+ var closestHPoints = closestPoints . filter ( function ( point ) {
531
+ return point . ya . showspikes ;
532
+ } ) ;
533
+ if ( closestHPoints . length ) {
534
+ var closestHPt = closestHPoints [ 0 ] ;
535
+ if ( isNumeric ( closestHPt . x0 ) && isNumeric ( closestHPt . y0 ) ) {
536
+ tmpPoint = fillSpikePoint ( closestHPt ) ;
537
+ if ( ! spikePoints . hLinePoint || ( spikePoints . hLinePoint . spikeDistance > tmpPoint . spikeDistance ) ) {
538
+ spikePoints . hLinePoint = tmpPoint ;
539
+ }
538
540
}
539
541
}
540
542
}
@@ -543,6 +545,8 @@ function _hover(gd, evt, subplot, noHoverEvent) {
543
545
}
544
546
}
545
547
548
+ findHoverPoints ( ) ;
549
+
546
550
function selectClosestPoint ( pointsData , spikedistance ) {
547
551
var resultPoint = null ;
548
552
var minDistance = Infinity ;
0 commit comments