diff --git a/src/index.ts b/src/index.ts index 9dfa768..89b1782 100755 --- a/src/index.ts +++ b/src/index.ts @@ -10,7 +10,7 @@ import { setBarScaleY, setBarScaleX } from './models/bar_state'; import { BarSerie, BarOptions, DiscreteConfig, NonDiscreteConfig, BarPodType, SizeType, CallbackEvent, Color, Opacity, - ColorFormatter, OpacityFormatter, + BarData, ColorFormatter, OpacityFormatter, Datapoint, ValueX, ValueY, } from './types'; @@ -108,9 +108,19 @@ export class ChartwerkBarPod extends ChartwerkPod { if(!this.series.isSeriesAvailable) { return undefined; } - const mousePoisitionKey = Math.ceil(this.state.xScale.invert(eventX)); + const mousePositionKey = this.state.xScale.invert(eventX); const keys = _.map(this.dataProcessor.dataRows, (dataRow: DataRow) => dataRow.key); - const idx = findClosest(keys, mousePoisitionKey); + let idx: number; + switch(this.options.barType) { + case BarPodType.DISCRETE: + idx = Math.floor(mousePositionKey); + break; + case BarPodType.NON_DISCRETE: + idx = findClosest(keys, mousePositionKey); + break; + default: + break; + } return this.dataProcessor.dataRows[idx]; } @@ -152,6 +162,6 @@ export { BarSerie, BarOptions, TimeFormat, AxisFormat, DiscreteConfig, NonDiscreteConfig, BarPodType, SizeType, CallbackEvent, Color, Opacity, - ColorFormatter, OpacityFormatter, + BarData, ColorFormatter, OpacityFormatter, Datapoint, ValueX, ValueY, DataItem, DataRow, }; diff --git a/src/models/bar_state.ts b/src/models/bar_state.ts index bd6e954..852fb34 100644 --- a/src/models/bar_state.ts +++ b/src/models/bar_state.ts @@ -13,14 +13,24 @@ export function setBarScaleX(state: PodState, dataRows: Da switch(options.barType) { case BarPodType.DISCRETE: const config: DiscreteConfig = options.dicreteConfig; - const discreteStep = _.isNumber(config.step) ? config.step : (_.last(dataRows).key - _.first(dataRows).key) / dataRows.length; + let discreteStep = 0; + if(_.isNumber(config.step)) { + discreteStep = config.step; + } else { + if(!_.isEmpty(dataRows)) { + discreteStep = (_.last(dataRows).key - _.first(dataRows).key) / dataRows.length; + } + } state.xValueRange = [state.xValueRange[0], state.xValueRange[1] + discreteStep]; return; case BarPodType.NON_DISCRETE: if(!_.isEmpty(options.axis.x.range)) { return; } - const nonDiscreteStep = (_.last(dataRows).key - _.first(dataRows).key) / dataRows.length; + let nonDiscreteStep = 0; + if(!_.isEmpty(dataRows)) { + nonDiscreteStep = (_.last(dataRows).key - _.first(dataRows).key) / dataRows.length; + } state.xValueRange = [state.xValueRange[0], state.xValueRange[1] + nonDiscreteStep]; return; } diff --git a/src/models/data_processor.ts b/src/models/data_processor.ts index 629c06c..3da2d57 100644 --- a/src/models/data_processor.ts +++ b/src/models/data_processor.ts @@ -113,7 +113,7 @@ export class DataProcessor { if(_.isFunction(opacity)) { return _.map(values, (value, i) => (opacity as Function)({ value, barIndex: i, key, target })); } - throw new Error(`Unknown type of serie opacity: ${target} ${opacity}`); + throw new Error(`Unknown type of serie opacity: ${target} ${opacity}`); } getMaxSumm(values: number[]): number { @@ -128,6 +128,10 @@ export class DataProcessor { if(this.options.barType === BarPodType.NON_DISCRETE) { return; } + // TODO: move non-empty datapoints validation to core + if(_.isEmpty(this.visibleSeries)) { + return; + } const xValuesList = _.map(_.first(this.visibleSeries).datapoints, dp => dp[0]); _.forEach(this.visibleSeries, serie => { const serieXList = _.map(serie.datapoints, dp => dp[0]); diff --git a/src/types.ts b/src/types.ts index 54f9b5d..91ff1c3 100755 --- a/src/types.ts +++ b/src/types.ts @@ -4,8 +4,9 @@ import { DataRow } from 'models/data_processor'; export type ValueX = (number | string); export type ValueY = number; export type Datapoint = [ValueX, ...ValueY[]]; // [x, y, y, y, ..., y], multiple y values as stacked bars -export type ColorFormatter = (data: { value: ValueY, key: ValueX, barIndex: number, target: string }) => string; -export type OpacityFormatter = (data: { value: ValueY, key: ValueX, barIndex: number, target: string }) => number; +export type BarData = { value: ValueY, key: ValueX, barIndex: number, target: string }; +export type ColorFormatter = (data: BarData) => string; +export type OpacityFormatter = (data: BarData) => number; export type Color = string | string[] | ColorFormatter; export type Opacity = number | number[] | OpacityFormatter;