@@ -14,7 +14,6 @@ var Drawing = require('../drawing');
1414var Color = require ( '../color' ) ;
1515var dragElement = require ( '../dragelement' ) ;
1616var Axes = require ( '../../plots/cartesian/axes' ) ;
17- var alignPeriod = require ( '../../plots/cartesian/align_period' ) ;
1817var Registry = require ( '../../registry' ) ;
1918
2019var helpers = require ( './helpers' ) ;
@@ -491,6 +490,7 @@ function _hover(gd, evt, subplot, noHoverEvent) {
491490 if ( hoverdistance !== 0 ) {
492491 if ( trace . _module && trace . _module . hoverPoints ) {
493492 var newPoints = trace . _module . hoverPoints ( pointData , xval , yval , _mode , {
493+ finiteRange : true ,
494494 hoverLayer : fullLayout . _hoverlayer
495495 } ) ;
496496
@@ -643,80 +643,51 @@ function _hover(gd, evt, subplot, noHoverEvent) {
643643 }
644644 }
645645
646- hoverData . sort ( function ( d1 , d2 ) { return d1 . distance - d2 . distance ; } ) ;
646+ var sortHoverData = function ( ) {
647+ hoverData . sort ( function ( d1 , d2 ) { return d1 . distance - d2 . distance ; } ) ;
647648
648- // move period positioned points to the end of list
649- hoverData = orderPeriod ( hoverData , hovermode ) ;
649+ // move period positioned points and box/bar-like traces to the end of the list
650+ hoverData = orderRangePoints ( hoverData , hovermode ) ;
651+ } ;
652+ sortHoverData ( ) ;
650653
651654 // If in compare mode, select every point at position
652655 if (
653656 helpers . isXYhover ( _mode ) &&
654657 hoverData [ 0 ] . length !== 0 &&
655658 hoverData [ 0 ] . trace . type !== 'splom' // TODO: add support for splom
656659 ) {
657- var initLen = hoverData . length ;
658660 var winningPoint = hoverData [ 0 ] ;
659661
660662 var customXVal = customVal ( 'x' , winningPoint , fullLayout ) ;
661663 var customYVal = customVal ( 'y' , winningPoint , fullLayout ) ;
662664
663665 findHoverPoints ( customXVal , customYVal ) ;
664666
665- // also find start, middle and end point for period
666- var axLetter = hovermode . charAt ( 0 ) ;
667- if ( winningPoint . trace [ axLetter + 'period' ] ) {
668- var v = winningPoint [ axLetter + 'LabelVal' ] ;
669- var ax = winningPoint [ axLetter + 'a' ] ;
670- var T = { } ;
671- T [ axLetter + 'period' ] = winningPoint . trace [ axLetter + 'period' ] ;
672- T [ axLetter + 'period0' ] = winningPoint . trace [ axLetter + 'period0' ] ;
673-
674- T [ axLetter + 'periodalignment' ] = 'start' ;
675- var start = alignPeriod ( T , ax , axLetter , [ v ] ) [ 0 ] ;
676-
677- T [ axLetter + 'periodalignment' ] = 'middle' ;
678- var middle = alignPeriod ( T , ax , axLetter , [ v ] ) [ 0 ] ;
679-
680- T [ axLetter + 'periodalignment' ] = 'end' ;
681- var end = alignPeriod ( T , ax , axLetter , [ v ] ) [ 0 ] ;
682-
683- if ( axLetter === 'x' ) {
684- findHoverPoints ( start , customYVal ) ;
685- findHoverPoints ( middle , customYVal ) ;
686- findHoverPoints ( end , customYVal ) ;
687- } else {
688- findHoverPoints ( customXVal , start ) ;
689- findHoverPoints ( customXVal , middle ) ;
690- findHoverPoints ( customXVal , end ) ;
691- }
692-
693- var k ;
694- var seen = { } ;
695- for ( k = 0 ; k < initLen ; k ++ ) {
696- seen [ hoverData [ k ] . trace . index ] = true ;
667+ var finalPoints = [ ] ;
668+ 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 ;
677+ if ( ! seen [ key ] ) {
678+ seen [ key ] = true ;
679+ finalPoints . push ( hd ) ;
697680 }
681+ } ;
698682
699- // remove non-period aditions and traces that seen before
700- for ( k = hoverData . length - 1 ; k >= initLen ; k -- ) {
701- if (
702- seen [ hoverData [ k ] . trace . index ] ||
703- ! hoverData [ k ] . trace [ axLetter + 'period' ]
704- ) {
705- hoverData . splice ( k , 1 ) ;
706- }
707- }
683+ // insert the winnig point first
684+ insert ( winningPoint ) ;
685+ // override from the end
686+ for ( var k = hoverData . length - 1 ; k > 0 ; k -- ) {
687+ insert ( hoverData [ k ] ) ;
708688 }
709-
710- // Remove duplicated hoverData points
711- // note that d3 also filters identical points in the rendering steps
712- var repeated = { } ;
713- hoverData = hoverData . filter ( function ( hd ) {
714- var key = hoverDataKey ( hd ) ;
715- if ( ! repeated [ key ] ) {
716- repeated [ key ] = true ;
717- return repeated [ key ] ;
718- }
719- } ) ;
689+ hoverData = finalPoints ;
690+ sortHoverData ( ) ;
720691 }
721692
722693 // lastly, emit custom hover/unhover events
@@ -820,9 +791,7 @@ function createHoverText(hoverData, opts, gd) {
820791 var xa = c0 . xa ;
821792 var ya = c0 . ya ;
822793 var axLetter = hovermode . charAt ( 0 ) ;
823- var v0 = c0 [ axLetter + 'LabelVal' ] ;
824794 var t0 = c0 [ axLetter + 'Label' ] ;
825- var t00 = ( String ( t0 ) || '' ) . split ( ' ' ) [ 0 ] ;
826795 var outerContainerBB = outerContainer . node ( ) . getBoundingClientRect ( ) ;
827796 var outerTop = outerContainerBB . top ;
828797 var outerWidth = outerContainerBB . width ;
@@ -1011,44 +980,13 @@ function createHoverText(hoverData, opts, gd) {
1011980 }
1012981
1013982 label . attr ( 'transform' , strTranslate ( lx , ly ) ) ;
1014-
1015- // remove the "close but not quite" points
1016- // because of error bars, only take up to a space
1017- hoverData = filterClosePoints ( hoverData ) ;
1018983 } ) ;
1019984
1020- function filterClosePoints ( hoverData ) {
1021- return hoverData . filter ( function ( d ) {
1022- if ( d . zLabelVal !== undefined ) return true ;
1023- if ( ( d [ axLetter + 'Label' ] || '' ) . split ( ' ' ) [ 0 ] === t00 ) return true ;
1024- if ( d . trace [ axLetter + 'period' ] ) {
1025- var v = d [ axLetter + 'LabelVal' ] ;
1026- var ax = d [ axLetter + 'a' ] ;
1027- var trace = { } ;
1028- trace [ axLetter + 'period' ] = d . trace [ axLetter + 'period' ] ;
1029- trace [ axLetter + 'period0' ] = d . trace [ axLetter + 'period0' ] ;
1030-
1031- trace [ axLetter + 'periodalignment' ] = 'start' ;
1032- var start = alignPeriod ( trace , ax , axLetter , [ v ] ) [ 0 ] ;
1033-
1034- trace [ axLetter + 'periodalignment' ] = 'end' ;
1035- var end = alignPeriod ( trace , ax , axLetter , [ v ] ) [ 0 ] ;
1036-
1037- if ( v0 >= start && v0 < end ) return true ;
1038- }
1039-
1040- return false ;
1041- } ) ;
1042- }
1043-
1044985 // Show a single hover label
1045986 if ( helpers . isUnifiedHover ( hovermode ) ) {
1046987 // Delete leftover hover labels from other hovermodes
1047988 container . selectAll ( 'g.hovertext' ) . remove ( ) ;
1048989
1049- // similarly to compare mode, we remove the "close but not quite together" points
1050- if ( ( t0 !== undefined ) && ( c0 . distance <= opts . hoverdistance ) ) hoverData = filterClosePoints ( hoverData ) ;
1051-
1052990 // Return early if nothing is hovered on
1053991 if ( hoverData . length === 0 ) return ;
1054992
@@ -1929,23 +1867,29 @@ function plainText(s, len) {
19291867 } ) ;
19301868}
19311869
1932- function orderPeriod ( hoverData , hovermode ) {
1870+ function orderRangePoints ( hoverData , hovermode ) {
19331871 var axLetter = hovermode . charAt ( 0 ) ;
19341872
19351873 var first = [ ] ;
1874+ var second = [ ] ;
19361875 var last = [ ] ;
19371876
19381877 for ( var i = 0 ; i < hoverData . length ; i ++ ) {
19391878 var d = hoverData [ i ] ;
19401879
1941- if ( d . trace [ axLetter + 'period' ] ) {
1880+ if (
1881+ Registry . traceIs ( d . trace , 'bar-like' ) ||
1882+ Registry . traceIs ( d . trace , 'box-violin' )
1883+ ) {
19421884 last . push ( d ) ;
1885+ } else if ( d . trace [ axLetter + 'period' ] ) {
1886+ second . push ( d ) ;
19431887 } else {
19441888 first . push ( d ) ;
19451889 }
19461890 }
19471891
1948- return first . concat ( last ) ;
1892+ return first . concat ( second ) . concat ( last ) ;
19491893}
19501894
19511895function customVal ( axLetter , winningPoint , fullLayout ) {
0 commit comments