@@ -404,6 +404,29 @@ describe('spikeline hover', function() {
404404 . then ( done ) ;
405405 } ) ;
406406
407+ it ( 'correctly select the closest bar even when setting spikedistance to -1' , function ( done ) {
408+ var mock = require ( '@mocks/bar_stack-with-gaps' ) ;
409+ var mockCopy = Lib . extendDeep ( { } , mock ) ;
410+ mockCopy . layout . xaxis . showspikes = true ;
411+ mockCopy . layout . yaxis . showspikes = true ;
412+ mockCopy . layout . spikedistance = - 1 ;
413+
414+ Plotly . newPlot ( gd , mockCopy )
415+ . then ( function ( ) {
416+ _hover ( { xpx : 600 , ypx : 400 } ) ;
417+ var lines = d3 . selectAll ( 'line.spikeline' ) ;
418+ expect ( lines . size ( ) ) . toBe ( 4 ) ;
419+ expect ( lines [ 0 ] [ 1 ] . getAttribute ( 'stroke' ) ) . toBe ( '#2ca02c' ) ;
420+
421+ _hover ( { xpx : 600 , ypx : 200 } ) ;
422+ lines = d3 . selectAll ( 'line.spikeline' ) ;
423+ expect ( lines . size ( ) ) . toBe ( 4 ) ;
424+ expect ( lines [ 0 ] [ 1 ] . getAttribute ( 'stroke' ) ) . toBe ( '#1f77b4' ) ;
425+ } )
426+ . catch ( failTest )
427+ . then ( done ) ;
428+ } ) ;
429+
407430 it ( 'correctly responds to setting the spikedistance to 0 by disabling ' +
408431 'the search for points to draw the spikelines' , function ( done ) {
409432 var _mock = makeMock ( 'toaxis' , 'closest' ) ;
@@ -593,4 +616,139 @@ describe('spikeline hover', function() {
593616 . catch ( failTest )
594617 . then ( done ) ;
595618 } ) ;
619+
620+ it ( 'correctly draws lines up to the last point' , function ( done ) {
621+ Plotly . newPlot ( gd , [
622+ { type : 'bar' , y : [ 5 , 7 , 9 , 6 , 4 , 3 ] } ,
623+ { y : [ 5 , 7 , 9 , 6 , 4 , 3 ] } ,
624+ { y : [ 5 , 7 , 9 , 6 , 4 , 3 ] , marker : { color : 'red' } }
625+ ] , {
626+ xaxis : { showspikes : true } ,
627+ yaxis : { showspikes : true } ,
628+ spikedistance : - 1 ,
629+ width : 400 , height : 400 ,
630+ showlegend : false
631+ } )
632+ . then ( function ( ) {
633+ _hover ( { xpx : 150 , ypx : 250 } ) ;
634+
635+ var lines = d3 . selectAll ( 'line.spikeline' ) ;
636+ expect ( lines . size ( ) ) . toBe ( 4 ) ;
637+ expect ( lines [ 0 ] [ 1 ] . getAttribute ( 'stroke' ) ) . toBe ( 'red' ) ;
638+ expect ( lines [ 0 ] [ 3 ] . getAttribute ( 'stroke' ) ) . toBe ( 'red' ) ;
639+ } )
640+ . catch ( failTest )
641+ . then ( done ) ;
642+ } ) ;
643+
644+ describe ( 'works across all cartesian traces' , function ( ) {
645+ var schema = Plotly . PlotSchema . get ( ) ;
646+ var traces = Object . keys ( schema . traces ) ;
647+ var tracesSchema = [ ] ;
648+ var i , j , k ;
649+ for ( i = 0 ; i < traces . length ; i ++ ) {
650+ tracesSchema . push ( schema . traces [ traces [ i ] ] ) ;
651+ }
652+ var excludedTraces = [ 'image' ] ;
653+ var cartesianTraces = tracesSchema . filter ( function ( t ) {
654+ return t . categories . length &&
655+ t . categories . indexOf ( 'cartesian' ) !== - 1 &&
656+ t . categories . indexOf ( 'noHover' ) === - 1 &&
657+ excludedTraces . indexOf ( t . type ) === - 1 ;
658+ } ) ;
659+
660+ function makeData ( type , axName , a , b ) {
661+ var input = [ a , b ] ;
662+ var cat = input [ axName === 'yaxis' ? 1 : 0 ] ;
663+ var data = input [ axName === 'yaxis' ? 0 : 1 ] ;
664+
665+ var measure = [ ] ;
666+ for ( j = 0 ; j < data . length ; j ++ ) {
667+ measure . push ( 'absolute' ) ;
668+ }
669+
670+ var z = Lib . init2dArray ( cat . length , data . length ) ;
671+ for ( j = 0 ; j < z . length ; j ++ ) {
672+ for ( k = 0 ; k < z [ j ] . length ; k ++ ) {
673+ z [ j ] [ k ] = 0 ;
674+ }
675+ }
676+ if ( axName === 'xaxis' ) {
677+ for ( j = 0 ; j < b . length ; j ++ ) {
678+ z [ 0 ] [ j ] = b [ j ] ;
679+ }
680+ }
681+ if ( axName === 'yaxis' ) {
682+ for ( j = 0 ; j < b . length ; j ++ ) {
683+ z [ j ] [ 0 ] = b [ j ] ;
684+ }
685+ }
686+
687+ return Lib . extendDeep ( { } , {
688+ orientation : axName === 'yaxis' ? 'h' : 'v' ,
689+ type : type ,
690+ x : cat ,
691+ a : cat ,
692+
693+ b : data ,
694+ y : data ,
695+ z : z ,
696+
697+ // For OHLC
698+ open : data ,
699+ close : data ,
700+ high : data ,
701+ low : data ,
702+
703+ // For histogram
704+ nbinsx : cat . length ,
705+ nbinsy : data . length ,
706+
707+ // For waterfall
708+ measure : measure ,
709+
710+ // For splom
711+ dimensions : [
712+ {
713+ label : 'DimensionA' ,
714+ values : a
715+ } ,
716+ {
717+ label : 'DimensionB' ,
718+ values : b
719+ }
720+ ]
721+ } ) ;
722+ }
723+
724+ cartesianTraces . forEach ( function ( trace ) {
725+ it ( 'correctly responds to setting the spikedistance to -1 for ' + trace . type , function ( done ) {
726+ var type = trace . type ;
727+ var x = [ 4 , 5 , 6 ] ;
728+ var data = [ 7 , 2 , 3 ] ;
729+
730+ var mock = {
731+ data : [ makeData ( type , 'xaxis' , x , data ) ] ,
732+ layout : {
733+ spikedistance : - 1 ,
734+ xaxis : { showspikes : true } ,
735+ yaxis : { showspikes : true } ,
736+ zaxis : { showspikes : true } ,
737+ title : { text : trace . type } ,
738+ width : 400 , height : 400
739+ }
740+ } ;
741+
742+ Plotly . newPlot ( gd , mock )
743+ . then ( function ( ) {
744+ _hover ( { xpx : 200 , ypx : 100 } ) ;
745+
746+ var lines = d3 . selectAll ( 'line.spikeline' ) ;
747+ expect ( lines . size ( ) ) . toBe ( 4 ) ;
748+ } )
749+ . catch ( failTest )
750+ . then ( done ) ;
751+ } ) ;
752+ } ) ;
753+ } ) ;
596754} ) ;
0 commit comments