@@ -404,6 +404,29 @@ describe('spikeline hover', function() {
404
404
. then ( done ) ;
405
405
} ) ;
406
406
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
+
407
430
it ( 'correctly responds to setting the spikedistance to 0 by disabling ' +
408
431
'the search for points to draw the spikelines' , function ( done ) {
409
432
var _mock = makeMock ( 'toaxis' , 'closest' ) ;
@@ -593,4 +616,139 @@ describe('spikeline hover', function() {
593
616
. catch ( failTest )
594
617
. then ( done ) ;
595
618
} ) ;
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
+ } ) ;
596
754
} ) ;
0 commit comments