@@ -39,6 +39,13 @@ var YSHIFTY = Math.sin(YA_RADIANS);
39
39
var HOVERARROWSIZE = constants . HOVERARROWSIZE ;
40
40
var HOVERTEXTPAD = constants . HOVERTEXTPAD ;
41
41
42
+ var multipleHoverPoints = {
43
+ box : true ,
44
+ ohlc : true ,
45
+ violin : true ,
46
+ candlestick : true
47
+ } ;
48
+
42
49
// fx.hover: highlight data on hover
43
50
// evt can be a mousemove event, or an object with data about what points
44
51
// to hover on
@@ -651,39 +658,58 @@ function _hover(gd, evt, subplot, noHoverEvent) {
651
658
} ;
652
659
sortHoverData ( ) ;
653
660
654
- // If in compare mode, select every point at position
655
661
if (
656
662
helpers . isXYhover ( _mode ) &&
657
663
hoverData [ 0 ] . length !== 0 &&
658
664
hoverData [ 0 ] . trace . type !== 'splom' // TODO: add support for splom
659
665
) {
666
+ // pick winning point
660
667
var winningPoint = hoverData [ 0 ] ;
668
+ // discard other points
669
+ if ( multipleHoverPoints [ winningPoint . trace . type ] ) {
670
+ hoverData = hoverData . filter ( function ( d ) {
671
+ return d . trace . index === winningPoint . trace . index ;
672
+ } ) ;
673
+ } else {
674
+ hoverData = [ winningPoint ] ;
675
+ }
676
+ var initLen = hoverData . length ;
661
677
662
- var customXVal = customVal ( 'x' , winningPoint , fullLayout ) ;
663
- var customYVal = customVal ( 'y' , winningPoint , fullLayout ) ;
678
+ var winX = getCoord ( 'x' , winningPoint , fullLayout ) ;
679
+ var winY = getCoord ( 'y' , winningPoint , fullLayout ) ;
664
680
665
- findHoverPoints ( customXVal , customYVal ) ;
681
+ // in compare mode, select every point at position
682
+ findHoverPoints ( winX , winY ) ;
666
683
667
684
var finalPoints = [ ] ;
668
685
var seen = { } ;
669
- var insert = function ( hd ) {
670
- var type = hd . trace . type ;
671
- var key = (
672
- type === 'box' ||
673
- type === 'violin' ||
674
- type === 'ohlc' ||
675
- type === 'candlestick'
676
- ) ? hoverDataKey ( hd ) : hd . trace . index ;
686
+ var id = 0 ;
687
+ var insert = function ( newHd ) {
688
+ var key = multipleHoverPoints [ newHd . trace . type ] ? hoverDataKey ( newHd ) : newHd . trace . index ;
677
689
if ( ! seen [ key ] ) {
678
- seen [ key ] = true ;
679
- finalPoints . push ( hd ) ;
690
+ id ++ ;
691
+ seen [ key ] = id ;
692
+ finalPoints . push ( newHd ) ;
693
+ } else {
694
+ var oldId = seen [ key ] - 1 ;
695
+ var oldHd = finalPoints [ oldId ] ;
696
+ if ( oldId > 0 &&
697
+ Math . abs ( newHd . distance ) <
698
+ Math . abs ( oldHd . distance )
699
+ ) {
700
+ // replace with closest
701
+ finalPoints [ oldId ] = newHd ;
702
+ }
680
703
}
681
704
} ;
682
705
683
- // insert the winnig point first
684
- insert ( winningPoint ) ;
706
+ var k ;
707
+ // insert the winnig point(s) first
708
+ for ( k = 0 ; k < initLen ; k ++ ) {
709
+ insert ( hoverData [ k ] ) ;
710
+ }
685
711
// override from the end
686
- for ( var k = hoverData . length - 1 ; k > 0 ; k -- ) {
712
+ for ( k = hoverData . length - 1 ; k > initLen - 1 ; k -- ) {
687
713
insert ( hoverData [ k ] ) ;
688
714
}
689
715
hoverData = finalPoints ;
@@ -1045,8 +1071,9 @@ function createHoverText(hoverData, opts, gd) {
1045
1071
legendDraw ( gd , mockLegend ) ;
1046
1072
1047
1073
// Position the hover
1048
- var ly = Lib . mean ( hoverData . map ( function ( c ) { return ( c . y0 + c . y1 ) / 2 ; } ) ) ;
1049
- var lx = Lib . mean ( hoverData . map ( function ( c ) { return ( c . x0 + c . x1 ) / 2 ; } ) ) ;
1074
+ var winningPoint = hoverData [ 0 ] ;
1075
+ var ly = ( winningPoint . y0 + winningPoint . y1 ) / 2 ;
1076
+ var lx = ( winningPoint . x0 + winningPoint . x1 ) / 2 ;
1050
1077
var legendContainer = container . select ( 'g.legend' ) ;
1051
1078
var tbb = legendContainer . node ( ) . getBoundingClientRect ( ) ;
1052
1079
lx += xa . _offset ;
@@ -1892,7 +1919,7 @@ function orderRangePoints(hoverData, hovermode) {
1892
1919
return first . concat ( second ) . concat ( last ) ;
1893
1920
}
1894
1921
1895
- function customVal ( axLetter , winningPoint , fullLayout ) {
1922
+ function getCoord ( axLetter , winningPoint , fullLayout ) {
1896
1923
var ax = winningPoint [ axLetter + 'a' ] ;
1897
1924
var val = winningPoint [ axLetter + 'Val' ] ;
1898
1925
0 commit comments