@@ -17,6 +17,7 @@ var axes = module.exports = {};
17
17
18
18
axes . layoutAttributes = require ( './layout_attributes' ) ;
19
19
20
+ axes . setConvert = require ( './set_convert' ) ;
20
21
21
22
var utils = require ( './utils' ) ;
22
23
axes . id2name = utils . id2name ;
@@ -533,238 +534,6 @@ axes.category = function(a) {
533
534
return curvecats > curvenums * 2 ;
534
535
} ;
535
536
536
- // cleanDatum: removes characters
537
- // same replace criteria used in the grid.js:scrapeCol
538
- // but also handling dates, numbers, and NaN, null, Infinity etc
539
- axes . cleanDatum = function ( c ) {
540
- try {
541
- if ( typeof c === 'object' && c !== null && c . getTime ) {
542
- return Plotly . Lib . ms2DateTime ( c ) ;
543
- }
544
- if ( typeof c !== 'string' && ! isNumeric ( c ) ) {
545
- return '' ;
546
- }
547
- c = c . toString ( ) . replace ( / [ ' " % , $ # ] / g, '' ) ;
548
- } catch ( e ) {
549
- console . log ( e , c ) ;
550
- }
551
- return c ;
552
- } ;
553
-
554
- // setConvert: define the conversion functions for an axis
555
- // data is used in 4 ways:
556
- // d: data, in whatever form it's provided
557
- // c: calcdata: turned into numbers, but not linearized
558
- // l: linearized - same as c except for log axes (and other
559
- // mappings later?) this is used by ranges, and when we
560
- // need to know if it's *possible* to show some data on
561
- // this axis, without caring about the current range
562
- // p: pixel value - mapped to the screen with current size and zoom
563
- // setAxConvert creates/updates these conversion functions
564
- // also clears the autorange bounds ._min and ._max
565
- // and the autotick constraints ._minDtick, ._forceTick0,
566
- // and looks for date ranges that aren't yet in numeric format
567
- axes . setConvert = function ( ax ) {
568
- // clipMult: how many axis lengths past the edge do we render?
569
- // for panning, 1-2 would suffice, but for zooming more is nice.
570
- // also, clipping can affect the direction of lines off the edge...
571
- var clipMult = 10 ;
572
-
573
- function toLog ( v , clip ) {
574
- if ( v > 0 ) return Math . log ( v ) / Math . LN10 ;
575
-
576
- else if ( v <= 0 && clip && ax . range && ax . range . length === 2 ) {
577
- // clip NaN (ie past negative infinity) to clipMult axis
578
- // length past the negative edge
579
- var r0 = ax . range [ 0 ] ,
580
- r1 = ax . range [ 1 ] ;
581
- return 0.5 * ( r0 + r1 - 3 * clipMult * Math . abs ( r0 - r1 ) ) ;
582
- }
583
-
584
- else return axes . BADNUM ;
585
- }
586
- function fromLog ( v ) { return Math . pow ( 10 , v ) ; }
587
- function num ( v ) { return isNumeric ( v ) ? Number ( v ) : axes . BADNUM ; }
588
-
589
- ax . c2l = ( ax . type === 'log' ) ? toLog : num ;
590
- ax . l2c = ( ax . type === 'log' ) ? fromLog : num ;
591
- ax . l2d = function ( v ) { return ax . c2d ( ax . l2c ( v ) ) ; } ;
592
- ax . p2d = function ( v ) { return ax . l2d ( ax . p2l ( v ) ) ; } ;
593
-
594
- // set scaling to pixels
595
- ax . setScale = function ( ) {
596
- var gs = ax . _td . _fullLayout . _size ,
597
- i ;
598
-
599
- // TODO cleaner way to handle this case
600
- if ( ! ax . _categories ) ax . _categories = [ ] ;
601
-
602
- // make sure we have a domain (pull it in from the axis
603
- // this one is overlaying if necessary)
604
- if ( ax . overlaying ) {
605
- var ax2 = axes . getFromId ( ax . _td , ax . overlaying ) ;
606
- ax . domain = ax2 . domain ;
607
- }
608
-
609
- // make sure we have a range (linearized data values)
610
- // and that it stays away from the limits of javascript numbers
611
- if ( ! ax . range || ax . range . length !== 2 || ax . range [ 0 ] === ax . range [ 1 ] ) {
612
- ax . range = [ - 1 , 1 ] ;
613
- }
614
- for ( i = 0 ; i < 2 ; i ++ ) {
615
- if ( ! isNumeric ( ax . range [ i ] ) ) {
616
- ax . range [ i ] = isNumeric ( ax . range [ 1 - i ] ) ?
617
- ( ax . range [ 1 - i ] * ( i ? 10 : 0.1 ) ) :
618
- ( i ? 1 : - 1 ) ;
619
- }
620
-
621
- if ( ax . range [ i ] < - ( Number . MAX_VALUE / 2 ) ) {
622
- ax . range [ i ] = - ( Number . MAX_VALUE / 2 ) ;
623
- }
624
- else if ( ax . range [ i ] > Number . MAX_VALUE / 2 ) {
625
- ax . range [ i ] = Number . MAX_VALUE / 2 ;
626
- }
627
-
628
- }
629
-
630
- if ( ax . _id . charAt ( 0 ) === 'y' ) {
631
- ax . _offset = gs . t + ( 1 - ax . domain [ 1 ] ) * gs . h ;
632
- ax . _length = gs . h * ( ax . domain [ 1 ] - ax . domain [ 0 ] ) ;
633
- ax . _m = ax . _length / ( ax . range [ 0 ] - ax . range [ 1 ] ) ;
634
- ax . _b = - ax . _m * ax . range [ 1 ] ;
635
- }
636
- else {
637
- ax . _offset = gs . l + ax . domain [ 0 ] * gs . w ;
638
- ax . _length = gs . w * ( ax . domain [ 1 ] - ax . domain [ 0 ] ) ;
639
- ax . _m = ax . _length / ( ax . range [ 1 ] - ax . range [ 0 ] ) ;
640
- ax . _b = - ax . _m * ax . range [ 0 ] ;
641
- }
642
-
643
- if ( ! isFinite ( ax . _m ) || ! isFinite ( ax . _b ) ) {
644
- Plotly . Lib . notifier (
645
- 'Something went wrong with axis scaling' ,
646
- 'long' ) ;
647
- ax . _td . _replotting = false ;
648
- throw new Error ( 'axis scaling' ) ;
649
- }
650
- } ;
651
-
652
- ax . l2p = function ( v ) {
653
- if ( ! isNumeric ( v ) ) return axes . BADNUM ;
654
- // include 2 fractional digits on pixel, for PDF zooming etc
655
- return d3 . round ( Plotly . Lib . constrain ( ax . _b + ax . _m * v ,
656
- - clipMult * ax . _length , ( 1 + clipMult ) * ax . _length ) , 2 ) ;
657
- } ;
658
-
659
- ax . p2l = function ( px ) { return ( px - ax . _b ) / ax . _m ; } ;
660
-
661
- ax . c2p = function ( v , clip ) { return ax . l2p ( ax . c2l ( v , clip ) ) ; } ;
662
- ax . p2c = function ( px ) { return ax . l2c ( ax . p2l ( px ) ) ; } ;
663
-
664
- if ( [ 'linear' , 'log' , '-' ] . indexOf ( ax . type ) !== - 1 ) {
665
- ax . c2d = num ;
666
- ax . d2c = function ( v ) {
667
- v = axes . cleanDatum ( v ) ;
668
- return isNumeric ( v ) ? Number ( v ) : axes . BADNUM ;
669
- } ;
670
- ax . d2l = function ( v , clip ) {
671
- if ( ax . type === 'log' ) return ax . c2l ( ax . d2c ( v ) , clip ) ;
672
- else return ax . d2c ( v ) ;
673
- } ;
674
- }
675
- else if ( ax . type === 'date' ) {
676
- ax . c2d = function ( v ) {
677
- return isNumeric ( v ) ? Plotly . Lib . ms2DateTime ( v ) : axes . BADNUM ;
678
- } ;
679
-
680
- ax . d2c = function ( v ) {
681
- return ( isNumeric ( v ) ) ? Number ( v ) : Plotly . Lib . dateTime2ms ( v ) ;
682
- } ;
683
-
684
- ax . d2l = ax . d2c ;
685
-
686
- // check if date strings or js date objects are provided for range
687
- // and convert to ms
688
- if ( ax . range && ax . range . length > 1 ) {
689
- try {
690
- var ar1 = ax . range . map ( Plotly . Lib . dateTime2ms ) ;
691
- if ( ! isNumeric ( ax . range [ 0 ] ) && isNumeric ( ar1 [ 0 ] ) ) {
692
- ax . range [ 0 ] = ar1 [ 0 ] ;
693
- }
694
- if ( ! isNumeric ( ax . range [ 1 ] ) && isNumeric ( ar1 [ 1 ] ) ) {
695
- ax . range [ 1 ] = ar1 [ 1 ] ;
696
- }
697
- }
698
- catch ( e ) { console . log ( e , ax . range ) ; }
699
- }
700
- }
701
- else if ( ax . type === 'category' ) {
702
-
703
- ax . c2d = function ( v ) {
704
- return ax . _categories [ Math . round ( v ) ] ;
705
- } ;
706
-
707
- ax . d2c = function ( v ) {
708
- // create the category list
709
- // this will enter the categories in the order it
710
- // encounters them, ie all the categories from the
711
- // first data set, then all the ones from the second
712
- // that aren't in the first etc.
713
- // TODO: sorting options - do the sorting
714
- // progressively here as we insert?
715
- if ( ax . _categories . indexOf ( v ) === - 1 ) ax . _categories . push ( v ) ;
716
-
717
- var c = ax . _categories . indexOf ( v ) ;
718
- return c === - 1 ? axes . BADNUM : c ;
719
- } ;
720
-
721
- ax . d2l = ax . d2c ;
722
- }
723
-
724
- // makeCalcdata: takes an x or y array and converts it
725
- // to a position on the axis object "ax"
726
- // inputs:
727
- // tdc - a data object from td.data
728
- // axletter - a string, either 'x' or 'y', for which item
729
- // to convert (TODO: is this now always the same as
730
- // the first letter of ax._id?)
731
- // in case the expected data isn't there, make a list of
732
- // integers based on the opposite data
733
- ax . makeCalcdata = function ( tdc , axletter ) {
734
- var arrayIn , arrayOut , i ;
735
-
736
- if ( axletter in tdc ) {
737
- arrayIn = tdc [ axletter ] ;
738
- arrayOut = new Array ( arrayIn . length ) ;
739
-
740
- for ( i = 0 ; i < arrayIn . length ; i ++ ) arrayOut [ i ] = ax . d2c ( arrayIn [ i ] ) ;
741
- }
742
- else {
743
- var v0 = ( ( axletter + '0' ) in tdc ) ?
744
- ax . d2c ( tdc [ axletter + '0' ] ) : 0 ,
745
- dv = ( tdc [ 'd' + axletter ] ) ?
746
- Number ( tdc [ 'd' + axletter ] ) : 1 ;
747
-
748
- // the opposing data, for size if we have x and dx etc
749
- arrayIn = tdc [ { x : 'y' , y : 'x' } [ axletter ] ] ;
750
- arrayOut = new Array ( arrayIn . length ) ;
751
-
752
- for ( i = 0 ; i < arrayIn . length ; i ++ ) arrayOut [ i ] = v0 + i * dv ;
753
- }
754
- return arrayOut ;
755
- } ;
756
-
757
- // for autoranging: arrays of objects:
758
- // {val: axis value, pad: pixel padding}
759
- // on the low and high sides
760
- ax . _min = [ ] ;
761
- ax . _max = [ ] ;
762
-
763
- // and for bar charts and box plots: reset forced minimum tick spacing
764
- ax . _minDtick = null ;
765
- ax . _forceTick0 = null ;
766
- } ;
767
-
768
537
// incorporate a new minimum difference and first tick into
769
538
// forced
770
539
axes . minDtick = function ( ax , newDiff , newFirst , allow ) {
0 commit comments