@@ -14,94 +14,167 @@ var Fx = require('../../components/fx');
1414var  Color  =  require ( '../../components/color' ) ; 
1515
1616module . exports  =  function  hoverPoints ( pointData ,  xval ,  yval ,  hovermode )  { 
17-     // closest mode: handicap box plots a little relative to others 
18-     var  cd  =  pointData . cd , 
19-         trace  =  cd [ 0 ] . trace , 
20-         t  =  cd [ 0 ] . t , 
21-         xa  =  pointData . xa , 
22-         ya  =  pointData . ya , 
23-         closeData  =  [ ] , 
24-         dx ,  dy ,  distfn ,  boxDelta , 
25-         posLetter ,  posAxis , 
26-         val ,  valLetter ,  valAxis ; 
27- 
28-     // adjust inbox w.r.t. to calculate box size 
29-     boxDelta  =  ( hovermode  ===  'closest' )  ? 2.5  *  t . bdPos  : t . bdPos ; 
30- 
31-     if ( trace . orientation  ===  'h' )  { 
32-         dx  =  function ( di )  { 
33-             return  Fx . inbox ( di . min  -  xval ,  di . max  -  xval ) ; 
34-         } ; 
35-         dy  =  function ( di )  { 
36-             var  pos  =  di . pos  +  t . bPos  -  yval ; 
37-             return  Fx . inbox ( pos  -  boxDelta ,  pos  +  boxDelta ) ; 
38-         } ; 
39-         posLetter  =  'y' ; 
40-         posAxis  =  ya ; 
41-         valLetter  =  'x' ; 
42-         valAxis  =  xa ; 
43-     }  else  { 
44-         dx  =  function ( di )  { 
45-             var  pos  =  di . pos  +  t . bPos  -  xval ; 
46-             return  Fx . inbox ( pos  -  boxDelta ,  pos  +  boxDelta ) ; 
47-         } ; 
48-         dy  =  function ( di )  { 
49-             return  Fx . inbox ( di . min  -  yval ,  di . max  -  yval ) ; 
50-         } ; 
51-         posLetter  =  'x' ; 
52-         posAxis  =  xa ; 
53-         valLetter  =  'y' ; 
54-         valAxis  =  ya ; 
55-     } 
17+     var  cd  =  pointData . cd ; 
18+     var  xa  =  pointData . xa ; 
19+     var  ya  =  pointData . ya ; 
20+ 
21+     var  trace  =  cd [ 0 ] . trace ; 
22+     var  hoveron  =  trace . hoveron ; 
23+     var  marker  =  trace . marker  ||  { } ; 
24+ 
25+     // output hover points array 
26+     var  closeData  =  [ ] ; 
27+     // x/y/effective distance functions 
28+     var  dx ,  dy ,  distfn ; 
29+     // orientation-specific fields 
30+     var  posLetter ,  valLetter ,  posAxis ,  valAxis ; 
31+     // calcdata item 
32+     var  di ; 
33+     // hover point item extended from pointData 
34+     var  pointData2 ; 
35+     // loop indices 
36+     var  i ,  j ; 
37+ 
38+     if ( hoveron . indexOf ( 'boxes' )  !==  - 1 )  { 
39+         var  t  =  cd [ 0 ] . t ; 
40+ 
41+         // closest mode: handicap box plots a little relative to others 
42+         // adjust inbox w.r.t. to calculate box size 
43+         var  boxDelta  =  ( hovermode  ===  'closest' )  ? 2.5  *  t . bdPos  : t . bdPos ; 
44+ 
45+         if ( trace . orientation  ===  'h' )  { 
46+             dx  =  function ( di )  { 
47+                 return  Fx . inbox ( di . min  -  xval ,  di . max  -  xval ) ; 
48+             } ; 
49+             dy  =  function ( di )  { 
50+                 var  pos  =  di . pos  +  t . bPos  -  yval ; 
51+                 return  Fx . inbox ( pos  -  boxDelta ,  pos  +  boxDelta ) ; 
52+             } ; 
53+             posLetter  =  'y' ; 
54+             posAxis  =  ya ; 
55+             valLetter  =  'x' ; 
56+             valAxis  =  xa ; 
57+         }  else  { 
58+             dx  =  function ( di )  { 
59+                 var  pos  =  di . pos  +  t . bPos  -  xval ; 
60+                 return  Fx . inbox ( pos  -  boxDelta ,  pos  +  boxDelta ) ; 
61+             } ; 
62+             dy  =  function ( di )  { 
63+                 return  Fx . inbox ( di . min  -  yval ,  di . max  -  yval ) ; 
64+             } ; 
65+             posLetter  =  'x' ; 
66+             posAxis  =  xa ; 
67+             valLetter  =  'y' ; 
68+             valAxis  =  ya ; 
69+         } 
70+ 
71+         distfn  =  Fx . getDistanceFunction ( hovermode ,  dx ,  dy ) ; 
72+         Fx . getClosest ( cd ,  distfn ,  pointData ) ; 
5673
57-     distfn  =  Fx . getDistanceFunction ( hovermode ,  dx ,  dy ) ; 
58-     Fx . getClosest ( cd ,  distfn ,  pointData ) ; 
74+         // skip the rest (for this trace) if we didn't find a close point 
75+         // and create the item(s) in closedata for this point 
76+         if ( pointData . index  !==  false )  { 
77+             di  =  cd [ pointData . index ] ; 
5978
60-     // skip the rest (for this trace) if we didn't find a close point 
61-     if ( pointData . index   ===   false )   return ; 
79+              var   lc   =   trace . line . color ; 
80+              var   mc   =   marker . color ; 
6281
63-     // create the item(s) in closedata for this point 
82+             if ( Color . opacity ( lc )  &&  trace . line . width )  pointData . color  =  lc ; 
83+             else  if ( Color . opacity ( mc )  &&  trace . boxpoints )  pointData . color  =  mc ; 
84+             else  pointData . color  =  trace . fillcolor ; 
6485
65-     // the closest data point 
66-     var  di  =  cd [ pointData . index ] , 
67-         lc  =  trace . line . color , 
68-         mc  =  ( trace . marker  ||  { } ) . color ; 
69-     if ( Color . opacity ( lc )  &&  trace . line . width )  pointData . color  =  lc ; 
70-     else  if ( Color . opacity ( mc )  &&  trace . boxpoints )  pointData . color  =  mc ; 
71-     else  pointData . color  =  trace . fillcolor ; 
86+             pointData [ posLetter  +  '0' ]  =  posAxis . c2p ( di . pos  +  t . bPos  -  t . bdPos ,  true ) ; 
87+             pointData [ posLetter  +  '1' ]  =  posAxis . c2p ( di . pos  +  t . bPos  +  t . bdPos ,  true ) ; 
7288
73-     pointData [ posLetter   +   '0' ]   =   posAxis . c2p ( di . pos   +   t . bPos   -   t . bdPos ,   true ) ; 
74-     pointData [ posLetter  +  '1 ' ]  =  posAxis . c2p ( di . pos   +   t . bPos   +   t . bdPos ,   true ) ; 
89+              Axes . tickText ( posAxis ,   posAxis . c2l ( di . pos ) ,   'hover' ) . text ; 
90+              pointData [ posLetter  +  'LabelVal ' ]  =  di . pos ; 
7591
76-     Axes . tickText ( posAxis ,  posAxis . c2l ( di . pos ) ,  'hover' ) . text ; 
77-     pointData [ posLetter  +  'LabelVal' ]  =  di . pos ; 
92+             // box plots: each "point" gets many labels 
93+             var  usedVals  =  { } ; 
94+             var  attrs  =  [ 'med' ,  'min' ,  'q1' ,  'q3' ,  'max' ] ; 
7895
79-     // box plots: each "point" gets many labels 
80-     var  usedVals  =  { } , 
81-         attrs  =  [ 'med' ,  'min' ,  'q1' ,  'q3' ,  'max' ] , 
82-         attr , 
83-         pointData2 ; 
84-     if ( trace . boxmean )  attrs . push ( 'mean' ) ; 
85-     if ( trace . boxpoints )  [ ] . push . apply ( attrs ,  [ 'lf' ,  'uf' ] ) ; 
96+             if ( trace . boxmean )  attrs . push ( 'mean' ) ; 
97+             if ( trace . boxpoints )  [ ] . push . apply ( attrs ,  [ 'lf' ,  'uf' ] ) ; 
8698
87-     for ( var   i  =  0 ;  i  <  attrs . length ;  i ++ )  { 
88-         attr  =  attrs [ i ] ; 
99+              for ( i  =  0 ;  i  <  attrs . length ;  i ++ )  { 
100+                  var   attr  =  attrs [ i ] ; 
89101
90-         if ( ! ( attr  in  di )  ||  ( di [ attr ]  in  usedVals ) )  continue ; 
91-         usedVals [ di [ attr ] ]  =  true ; 
102+                  if ( ! ( attr  in  di )  ||  ( di [ attr ]  in  usedVals ) )  continue ; 
103+                  usedVals [ di [ attr ] ]  =  true ; 
92104
93-         // copy out to a new object for each value to label 
94-         val  =  valAxis . c2p ( di [ attr ] ,  true ) ; 
95-         pointData2  =  Lib . extendFlat ( { } ,  pointData ) ; 
96-         pointData2 [ valLetter  +  '0' ]  =  pointData2 [ valLetter  +  '1' ]  =  val ; 
97-         pointData2 [ valLetter  +  'LabelVal' ]  =  di [ attr ] ; 
98-         pointData2 . attr  =  attr ; 
105+                  // copy out to a new object for each value to label 
106+                  var   val  =  valAxis . c2p ( di [ attr ] ,  true ) ; 
107+                  pointData2  =  Lib . extendFlat ( { } ,  pointData ) ; 
108+                  pointData2 [ valLetter  +  '0' ]  =  pointData2 [ valLetter  +  '1' ]  =  val ; 
109+                  pointData2 [ valLetter  +  'LabelVal' ]  =  di [ attr ] ; 
110+                  pointData2 . attr  =  attr ; 
99111
100-         if ( attr  ===  'mean'  &&  ( 'sd'  in  di )  &&  trace . boxmean  ===  'sd' )  { 
101-             pointData2 [ valLetter  +  'err' ]  =  di . sd ; 
112+                 if ( attr  ===  'mean'  &&  ( 'sd'  in  di )  &&  trace . boxmean  ===  'sd' )  { 
113+                     pointData2 [ valLetter  +  'err' ]  =  di . sd ; 
114+                 } 
115+                 // only keep name on the first item (median) 
116+                 pointData . name  =  '' ; 
117+ 
118+                 closeData . push ( pointData2 ) ; 
119+             } 
102120        } 
103-         pointData . name  =  '' ;  // only keep name on the first item (median) 
104-         closeData . push ( pointData2 ) ; 
105121    } 
122+ 
123+     if ( hoveron . indexOf ( 'points' )  !==  - 1 )  { 
124+         var  xPx  =  xa . c2p ( xval ) ; 
125+         var  yPx  =  ya . c2p ( yval ) ; 
126+ 
127+         // do not take jitter into consideration in compare hover modes 
128+         var  kx ,  ky ; 
129+         if ( hovermode  ===  'closest' )  { 
130+             kx  =  'x' ; 
131+             ky  =  'y' ; 
132+         }  else  { 
133+             kx  =  'xh' ; 
134+             ky  =  'yh' ; 
135+         } 
136+ 
137+         dx  =  function ( di )  { 
138+             var  rad  =  Math . max ( 3 ,  di . mrc  ||  0 ) ; 
139+             return  Math . max ( Math . abs ( xa . c2p ( di [ kx ] )  -  xPx )  -  rad ,  1  -  3  /  rad ) ; 
140+         } ; 
141+         dy  =  function ( di )  { 
142+             var  rad  =  Math . max ( 3 ,  di . mrc  ||  0 ) ; 
143+             return  Math . max ( Math . abs ( ya . c2p ( di [ ky ] )  -  yPx )  -  rad ,  1  -  3  /  rad ) ; 
144+         } ; 
145+         distfn  =  Fx . getDistanceFunction ( hovermode ,  dx ,  dy ) ; 
146+ 
147+         for ( i  =  0 ;  i  <  cd . length ;  i ++ )  { 
148+             di  =  cd [ i ] ; 
149+ 
150+             for ( j  =  0 ;  j  <  ( di . pts  ||  [ ] ) . length ;  j ++ )  { 
151+                 var  pt  =  di . pts [ j ] ; 
152+ 
153+                 var  newDistance  =  distfn ( pt ) ; 
154+                 if ( newDistance  <=  pointData . distance )  { 
155+                     pointData . distance  =  newDistance ; 
156+ 
157+                     var  xc  =  xa . c2p ( pt . x ,  true ) ; 
158+                     var  yc  =  ya . c2p ( pt . y ,  true ) ; 
159+                     var  rad  =  pt . mrc  ||  1 ; 
160+ 
161+                     pointData2  =  Lib . extendFlat ( { } ,  pointData ,  { 
162+                         // corresponds to index in x/y input data array 
163+                         index : pt . i , 
164+                         color : marker . color , 
165+                         x0 : xc  -  rad , 
166+                         x1 : xc  +  rad , 
167+                         xLabelVal : pt . x , 
168+                         y0 : yc  -  rad , 
169+                         y1 : yc  +  rad , 
170+                         yLabelVal : pt . y 
171+                     } ) ; 
172+ 
173+                     closeData . push ( pointData2 ) ; 
174+                 } 
175+             } 
176+         } 
177+     } 
178+ 
106179    return  closeData ; 
107180} ; 
0 commit comments