import * as d3 from 'd3' ; import * as Utils from '../utils/_index' ; import { AxisOptions } from './AxisOptions' ; import { Dimensions , IMargin } from './Dimensions' ; import { SeriesOptions , ISeriesOptions } from './SeriesOptions' ; import { SymbolOptions } from './SymbolOptions' ; export interface IZoomOptions { x : boolean ; y : boolean ; key : string ; } export interface IAxesSet { x : AxisOptions ; y : AxisOptions ; y2 ? : AxisOptions ; } ; export interface ITwoAxes { x : boolean ; y : boolean ; } export interface IPanOptions { x : ( x : ( number | Date ) [ ] ) => ( number | Date ) [ ] ; x2 : ( x : ( number | Date ) [ ] ) => ( number | Date ) [ ] ; y : ( x : ( number | Date ) [ ] ) => ( number | Date ) [ ] ; y2 : ( x : ( number | Date ) [ ] ) => ( number | Date ) [ ] ; } export class Options { public doubleClickEnabled = true ; public tooltipHook : Function ; public series : ISeriesOptions [ ] = [ ] ; public zoom : IZoomOptions = { x : false , y : false , key : 'altKey' } ; public symbols : SymbolOptions [ ] = [ ] ; public pan : IPanOptions = { x : ( ) => undefined , x2 : ( ) => undefined , y : ( ) => undefined , y2 : ( ) => undefined } ; public axes : IAxesSet = { x : < AxisOptions > { } , y : < AxisOptions > { } } ; constructor ( js ? ) { var options = Utils . ObjectUtils . extend ( this , js ) ; this . margin = this . sanitizeMargin ( Options . getObject ( options . margin , this . margin ) ) ; this . series = this . sanitizeSeries ( Options . getArray ( options . series ) ) ; this . symbols = this . sanitizeSymbols ( Options . getArray ( options . symbols ) ) ; this . axes = this . sanitizeAxes ( Options . getObject ( options . axes , this . axes ) ) ; this . grid = this . sanitizeTwoAxesOptions ( options . grid , this . grid ) ; this . pan = this . sanitizePanOptions ( options . pan , this . pan ) ; this . zoom = this . sanitizeZoomOptions ( options . zoom , this . zoom ) ; this . tooltipHook = Options . getFunction ( options . tooltipHook ) ; this . doubleClickEnabled = Options . getBoolean ( options . doubleClickEnabled , false ) ; } public margin : IMargin = Dimensions . getDefaultMargins ( ) ; public grid : ITwoAxes = { x : false , y : true } ; sanitizeMargin ( margin ) { return < IMargin > { top : Options . getNumber ( margin . top , 0 ) , left : Options . getNumber ( margin . left , 0 ) , bottom : Options . getNumber ( margin . bottom , 0 ) , right : Options . getNumber ( margin . right , 0 ) } ; } sanitizeSeries ( series ) { return ( series ) . map ( ( s ) => new SeriesOptions ( s ) ) ; } sanitizeZoomOptions ( object , def ) { var axis = this . sanitizeTwoAxesOptions ( object , def ) ; var trigger = Options . getString ( object . key , def . key ) ; if ( [ 'altKey' , 'shiftKey' , 'ctrlKey' ] . indexOf ( trigger ) === - 1 ) { console . warn ( 'Unknown zoom key ' + trigger + ' ! Default `altKey` is used.' ) ; trigger = def . key ; } return { x : Options . getBoolean ( object . x , def . x ) , y : Options . getBoolean ( object . y , def . y ) , key : trigger } ; } sanitizeSymbols ( symbols ) { return ( symbols ) . map ( ( s ) => new SymbolOptions ( s ) ) ; } sanitizeTwoAxesOptions ( object , def ) { return { x : Options . getBoolean ( object . x , def . x ) , y : Options . getBoolean ( object . y , def . y ) } ; } sanitizePanOptions ( object , def ) { return { x : this . sanitizePanOption ( object . x ) , x2 : this . sanitizePanOption ( object . x2 ) , y : this . sanitizePanOption ( object . y ) , y2 : this . sanitizePanOption ( object . y2 ) , } ; } sanitizePanOption ( option ) { if ( option === undefined ) { return ( domain ) => undefined ; } else if ( Utils . ObjectUtils . isBoolean ( option ) ) { if ( option ) { return ( domain ) => domain ; } else { return ( domain ) => undefined ; } } else if ( Utils . ObjectUtils . isFunction ( option ) ) { return option ; } else { throw new Error ( 'Pan option should either be a Boolean or a function. Please RTFM.' ) ; } } sanitizeAxes ( axes ) { return < IAxesSet > Object . keys ( axes ) . reduce ( ( prev , key ) => { prev [ key ] = new AxisOptions ( axes [ key ] ) ; return prev ; } , { } ) ; } getAbsKey ( ) { if ( ! this . axes [ AxisOptions . SIDE . X ] ) { throw new TypeError ( 'Cannot find abs key : ' + AxisOptions . SIDE . X ) ; } return this . axes [ AxisOptions . SIDE . X ] . key ; } getVisibleDatasets ( ) { var datasets = [ ] ; this . series . forEach ( ( series ) => { if ( series . visible ) { if ( datasets . indexOf ( series . dataset ) === - 1 ) { datasets . push ( series . dataset ) ; } } } ) ; return datasets ; } getVisibleSeriesBySide ( side ) { return this . series . filter ( s => s . visible && s . axis === side ) ; } getSeriesAndDatasetBySide ( side ) { if ( ! AxisOptions . isValidSide ( side ) ) { throw new TypeError ( 'Cannot get axis side : ' + side ) ; } if ( side === AxisOptions . SIDE . Y2 && ! this . axes [ side ] ) { side = AxisOptions . SIDE . Y ; } var datasetsForSide = [ ] ; var seriesForDataset = { } ; this . series . forEach ( ( series ) => { if ( series . visible && series . axis === side ) { datasetsForSide . push ( series . dataset ) ; if ( ! seriesForDataset [ series . dataset ] ) { seriesForDataset [ series . dataset ] = [ ] ; } seriesForDataset [ series . dataset ] . push ( series ) ; } } ) ; return { seriesForDataset , datasetsForSide } ; } getByAxisSide ( side ) { if ( ! AxisOptions . isValidSide ( side ) ) { throw new TypeError ( 'Cannot get axis side : ' + side ) ; } if ( ! this . axes [ side ] ) { if ( side === AxisOptions . SIDE . Y2 ) { return this . axes [ AxisOptions . SIDE . Y ] ; } else if ( side === AxisOptions . SIDE . X2 ) { return this . axes [ AxisOptions . SIDE . X ] ; } } return this . axes [ side ] ; } getSeriesByType ( type ) { if ( ! SeriesOptions . isValidType ( type ) ) { throw new TypeError ( 'Unknown series type: ' + type ) ; } return this . series . filter ( ( s ) => s . hasType ( type ) ) ; } getSymbolsByType ( type ) { if ( ! SymbolOptions . isValidType ( type ) ) { throw new TypeError ( 'Unknown symbols type: ' + type ) ; } return this . symbols . filter ( ( s ) => s . type === type ) ; } static getBoolean ( value , defaultValue = true ) { if ( typeof value === 'boolean' ) { return value ; } return defaultValue ; } static getNumber ( value , defaultValue ) { var n = parseFloat ( value ) ; return ! isNaN ( n ) ? n : defaultValue ; } static getDate ( value , defaultValue ) { return value instanceof Date ? value : defaultValue ; } static getFunction ( value ) { return value instanceof Function ? value : undefined ; } static getString ( value , defaultValue ? ) { return value ? String ( value ) : defaultValue ; } static getIdentifier ( value ) { var s = Options . getString ( value ) ; return s . replace ( /[^a-zA-Z0-9\-_]/ig , '' ) ; } static getObject ( value , defaultValue = { } ) { if ( ! Utils . ObjectUtils . isObject ( value ) ) { throw TypeError ( value + ' option must be an object.' ) ; } return Utils . ObjectUtils . extend ( defaultValue , value ) ; } static getArray ( value , defaultValue = [ ] ) { return defaultValue . concat ( value ) ; } }