99'use strict' ; 
1010
1111var  Axes  =  require ( '../../plots/cartesian/axes' ) ; 
12+ var  Lib  =  require ( '../../lib' ) ; 
1213var  Fx  =  require ( '../../components/fx' ) ; 
1314var  Color  =  require ( '../../components/color' ) ; 
1415var  fillHoverText  =  require ( '../scatter/fill_hover_text' ) ; 
@@ -18,32 +19,44 @@ var DIRSYMBOL = {
1819    decreasing : '▼' 
1920} ; 
2021
21- module . exports  =  function  hoverPoints ( pointData ,  xval ,  yval ,  hovermode )  { 
22+ function  hoverPoints ( pointData ,  xval ,  yval ,  hovermode )  { 
23+     var  cd  =  pointData . cd ; 
24+     var  trace  =  cd [ 0 ] . trace ; 
25+ 
26+     if ( trace . hoverlabel . split )  { 
27+         return  hoverSplit ( pointData ,  xval ,  yval ,  hovermode ) ; 
28+     } 
29+ 
30+     return  hoverOnPoints ( pointData ,  xval ,  yval ,  hovermode ) ; 
31+ } 
32+ 
33+ function  getClosestPoint ( pointData ,  xval ,  yval ,  hovermode )  { 
2234    var  cd  =  pointData . cd ; 
2335    var  xa  =  pointData . xa ; 
24-     var  ya  =  pointData . ya ; 
2536    var  trace  =  cd [ 0 ] . trace ; 
2637    var  t  =  cd [ 0 ] . t ; 
2738
2839    var  type  =  trace . type ; 
2940    var  minAttr  =  type  ===  'ohlc'  ? 'l'  : 'min' ; 
3041    var  maxAttr  =  type  ===  'ohlc'  ? 'h'  : 'max' ; 
3142
43+     var  hoverPseudoDistance ,  spikePseudoDistance ; 
44+ 
3245    // potentially shift xval for grouped candlesticks 
3346    var  centerShift  =  t . bPos  ||  0 ; 
34-     var  x0  =  xval   -   centerShift ; 
47+     var  shiftPos  =  function ( di )   {   return   di . pos   +   centerShift   -   xval ;   } ; 
3548
3649    // ohlc and candlestick call displayHalfWidth different things... 
3750    var  displayHalfWidth  =  t . bdPos  ||  t . tickLen ; 
3851    var  hoverHalfWidth  =  t . wHover ; 
3952
40-     // if two items  are overlaying, let the narrowest one win 
53+     // if two figures  are overlaying, let the narrowest one win 
4154    var  pseudoDistance  =  Math . min ( 1 ,  displayHalfWidth  /  Math . abs ( xa . r2c ( xa . range [ 1 ] )  -  xa . r2c ( xa . range [ 0 ] ) ) ) ; 
42-     var   hoverPseudoDistance  =  pointData . maxHoverDistance  -  pseudoDistance ; 
43-     var   spikePseudoDistance  =  pointData . maxSpikeDistance  -  pseudoDistance ; 
55+     hoverPseudoDistance  =  pointData . maxHoverDistance  -  pseudoDistance ; 
56+     spikePseudoDistance  =  pointData . maxSpikeDistance  -  pseudoDistance ; 
4457
4558    function  dx ( di )  { 
46-         var  pos  =  di . pos   -   x0 ; 
59+         var  pos  =  shiftPos ( di ) ; 
4760        return  Fx . inbox ( pos  -  hoverHalfWidth ,  pos  +  hoverHalfWidth ,  hoverPseudoDistance ) ; 
4861    } 
4962
@@ -52,18 +65,13 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
5265    } 
5366
5467    function  dxy ( di )  {  return  ( dx ( di )  +  dy ( di ) )  /  2 ;  } 
68+ 
5569    var  distfn  =  Fx . getDistanceFunction ( hovermode ,  dx ,  dy ,  dxy ) ; 
5670    Fx . getClosest ( cd ,  distfn ,  pointData ) ; 
5771
58-     // skip the rest (for this trace) if we didn't find a close point 
59-     if ( pointData . index  ===  false )  return  [ ] ; 
60- 
61-     // we don't make a calcdata point if we're missing any piece (x/o/h/l/c) 
62-     // so we need to fix the index here to point to the data arrays 
63-     var  cdIndex  =  pointData . index ; 
64-     var  di  =  cd [ cdIndex ] ; 
65-     var  i  =  pointData . index  =  di . i ; 
72+     if ( pointData . index  ===  false )  return  null ; 
6673
74+     var  di  =  cd [ pointData . index ] ; 
6775    var  dir  =  di . dir ; 
6876    var  container  =  trace [ dir ] ; 
6977    var  lc  =  container . line . color ; 
@@ -79,6 +87,81 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
7987    pointData . spikeDistance  =  dxy ( di )  *  spikePseudoDistance  /  hoverPseudoDistance ; 
8088    pointData . xSpike  =  xa . c2p ( di . pos ,  true ) ; 
8189
90+     return  pointData ; 
91+ } 
92+ 
93+ function  hoverSplit ( pointData ,  xval ,  yval ,  hovermode )  { 
94+     var  cd  =  pointData . cd ; 
95+     var  ya  =  pointData . ya ; 
96+     var  trace  =  cd [ 0 ] . trace ; 
97+     var  t  =  cd [ 0 ] . t ; 
98+     var  closeBoxData  =  [ ] ; 
99+ 
100+     var  closestPoint  =  getClosestPoint ( pointData ,  xval ,  yval ,  hovermode ) ; 
101+     // skip the rest (for this trace) if we didn't find a close point 
102+     if ( ! closestPoint )  return  [ ] ; 
103+ 
104+     var  hoverinfo  =  trace . hoverinfo ; 
105+     var  hoverParts  =  hoverinfo . split ( '+' ) ; 
106+     var  isAll  =  hoverinfo  ===  'all' ; 
107+     var  hasY  =  isAll  ||  hoverParts . indexOf ( 'y' )  !==  - 1 ; 
108+ 
109+     // similar to hoverOnPoints, we return nothing 
110+     // if all or y is not present. 
111+     if ( ! hasY )  return  [ ] ; 
112+ 
113+     var  attrs  =  [ 'high' ,  'open' ,  'close' ,  'low' ] ; 
114+ 
115+     // several attributes can have the same y-coordinate. We will 
116+     // bunch them together in a single text block. For this, we keep 
117+     // a dictionary mapping y-coord -> point data. 
118+     var  usedVals  =  { } ; 
119+ 
120+     for ( var  i  =  0 ;  i  <  attrs . length ;  i ++ )  { 
121+         var  attr  =  attrs [ i ] ; 
122+ 
123+         var  val  =  trace [ attr ] [ closestPoint . index ] ; 
124+         var  valPx  =  ya . c2p ( val ,  true ) ; 
125+         var  pointData2 ; 
126+         if ( val  in  usedVals )  { 
127+             pointData2  =  usedVals [ val ] ; 
128+             pointData2 . yLabel  +=  '<br>'  +  t . labels [ attr ]  +  Axes . hoverLabelText ( ya ,  val ) ; 
129+         } 
130+         else  { 
131+             // copy out to a new object for each new y-value to label 
132+             pointData2  =  Lib . extendFlat ( { } ,  closestPoint ) ; 
133+ 
134+             pointData2 . y0  =  pointData2 . y1  =  valPx ; 
135+             pointData2 . yLabelVal  =  val ; 
136+             pointData2 . yLabel  =  t . labels [ attr ]  +  Axes . hoverLabelText ( ya ,  val ) ; 
137+ 
138+             pointData2 . name  =  '' ; 
139+ 
140+             closeBoxData . push ( pointData2 ) ; 
141+             usedVals [ val ]  =  pointData2 ; 
142+         } 
143+     } 
144+ 
145+     return  closeBoxData ; 
146+ } 
147+ 
148+ function  hoverOnPoints ( pointData ,  xval ,  yval ,  hovermode )  { 
149+     var  cd  =  pointData . cd ; 
150+     var  ya  =  pointData . ya ; 
151+     var  trace  =  cd [ 0 ] . trace ; 
152+     var  t  =  cd [ 0 ] . t ; 
153+ 
154+     var  closestPoint  =  getClosestPoint ( pointData ,  xval ,  yval ,  hovermode ) ; 
155+     // skip the rest (for this trace) if we didn't find a close point 
156+     if ( ! closestPoint )  return  [ ] ; 
157+ 
158+     // we don't make a calcdata point if we're missing any piece (x/o/h/l/c) 
159+     // so we need to fix the index here to point to the data arrays 
160+     var  cdIndex  =  closestPoint . index ; 
161+     var  di  =  cd [ cdIndex ] ; 
162+     var  i  =  closestPoint . index  =  di . i ; 
163+     var  dir  =  di . dir ; 
164+ 
82165    function  getLabelLine ( attr )  { 
83166        return  t . labels [ attr ]  +  Axes . hoverLabelText ( ya ,  trace [ attr ] [ i ] ) ; 
84167    } 
@@ -99,11 +182,17 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
99182
100183    // don't make .yLabelVal or .text, since we're managing hoverinfo 
101184    // put it all in .extraText 
102-     pointData . extraText  =  textParts . join ( '<br>' ) ; 
185+     closestPoint . extraText  =  textParts . join ( '<br>' ) ; 
103186
104187    // this puts the label *and the spike* at the midpoint of the box, ie 
105188    // halfway between open and close, not between high and low. 
106-     pointData . y0  =  pointData . y1  =  ya . c2p ( di . yc ,  true ) ; 
189+     closestPoint . y0  =  closestPoint . y1  =  ya . c2p ( di . yc ,  true ) ; 
190+ 
191+     return  [ closestPoint ] ; 
192+ } 
107193
108-     return  [ pointData ] ; 
194+ module . exports  =  { 
195+     hoverPoints : hoverPoints , 
196+     hoverSplit : hoverSplit , 
197+     hoverOnPoints : hoverOnPoints 
109198} ; 
0 commit comments