Compare commits

..

48 Commits

Author SHA1 Message Date
rozetko 8264719c82 Merge pull request 'Right y-axis fixes' (#51) from right-y-axis-fixes into main 5 months ago
rozetko 0029d22c4e 0.6.26 5 months ago
rozetko 4f28c5dc13 state: new `getYScaleByOrientation` function 5 months ago
rozetko 2abf246a85 right y-axis: render label 5 months ago
rozetko 839bd12d69 Merge pull request '0.6.25' (#50) from bump-version-to-0.6.25 into main 5 months ago
rozetko 1bfe7f6649 0.6.25 5 months ago
rozetko 95343168d9 Merge pull request 'fix autorange for right y-axis' (#49) from fix-autorange-for-right-y-axis into main 5 months ago
rozetko 2b6fa90af5 fix autorange for right y-axis 5 months ago
Coin de Gamma e841792c34 Merge pull request 'mouse over event type and it's calling' (#44) from onmouseover-event-callback-#42 into main 6 months ago
rozetko c546284e70 Merge pull request 'replace todo with comment' (#40) from styles-use-todo into main 6 months ago
glitch4347 e36148772f mouse over event type and it's calling 6 months ago
glitch4347 90af9810a3 update comment 6 months ago
glitch4347 e24bee024b replace todo with comment 6 months ago
Coin de Gamma bc1e06e515 Merge pull request '0.6.24' (#37) from 0.6.24 into main 8 months ago
glitch4347 eea338db16 0.6.24 8 months ago
Coin de Gamma 63bf4ca931 Merge pull request 'rm abstact keyword and methods' (#36) from bad-abstract-onmouseclick-#35 into main 8 months ago
glitch4347 5fc85d6329 rm abstact keyword and methods 8 months ago
Coin de Gamma b36c226bae Merge pull request '0.6.23' (#34) from 0.6.23 into main 8 months ago
glitch4347 6721f7d127 0.6.23 8 months ago
Coin de Gamma 443d2342f7 Merge pull request 'rm demo from build' (#33) from broken-demo-#32 into main 8 months ago
glitch4347 0a64dd94f6 rm demo from build 8 months ago
Coin de Gamma 1711b2cc1e Merge pull request '0.6.22' (#31) from 0.6.22 into main 8 months ago
glitch4347 2d4794ad0c 0.6.22 8 months ago
Coin de Gamma 476feba10c Merge pull request 'rename-eventCallbacs-to-events-#26-2' (#29) from rename-eventCallbacs-to-events-#26-2 into main 8 months ago
glitch4347 c05d989347 rename EventsCallbacs to Events 8 months ago
glitch4347 88dbb2bdec comment about obolure eventsCallbacks 8 months ago
glitch4347 c83becf2aa events refactoring begin 8 months ago
rozetko 3590eeebcc Merge pull request 'zoomin protected method' (#28) from zoomin-protected into main 9 months ago
glitch4347 c1a2124d13 AxisRange to top 9 months ago
glitch4347 29c73517d6 rm rnages undefined check 9 months ago
glitch4347 5d75ccb39f zoomin protected method 9 months ago
rozetko b8f1dac3bd 0.6.21 10 months ago
rozetko e0ecc385a6 0.6.20 10 months ago
rozetko f137cc727e disable right-click brushing 10 months ago
Coin de Gamma 6254f1386a Merge pull request '0.6.19' (#25) from 0.6.19 into main 11 months ago
glitch4347 8f278a15be 0.6.19 11 months ago
Coin de Gamma 3c8865d2c3 Merge pull request 'fix demo pod' (#23) from demopod-build-error-#22 into main 11 months ago
glitch4347 85c68d279c fix demo pod 11 months ago
vargburz a7bf96f7d4 0.6.18 11 months ago
vargburz f0c21dbf67 Merge pull request 'onclick' (#19) from onclick-event-#15 into main 11 months ago
glitch4347 493d52629c onclick 11 months ago
rozetko ffc73dbd85 Merge pull request 'Demo' (#14) from examples into main 11 months ago
vargburz 43852582b6 rename example to demo 11 months ago
vargburz a4251b69b7 build example 11 months ago
vargburz 0cb408c9b5 add example pod 11 months ago
vargburz ae8904079b Merge pull request 'set git repo in package.json' (#7) from set-git-package into main 12 months ago
glitch4347 c4da056f2d set git repo in package.json 12 months ago
vargburz 1e0702a8b6 Merge pull request 'Remove unused methods and options' (#4) from remove-unused-methods into main 1 year ago
  1. 40
      build/webpack.demo.conf.js
  2. 5
      demo/README.md
  3. 38
      demo/demo.html
  4. 56
      demo/demo_pod.ts
  5. 5
      package.json
  6. 42
      src/VueChartwerkPodMixin.ts
  7. 79
      src/index.ts
  8. 69
      src/models/options.ts
  9. 3
      src/models/series.ts
  10. 15
      src/models/state.ts
  11. 37
      src/types.ts
  12. 11
      tsconfig.json

40
build/webpack.demo.conf.js

@ -0,0 +1,40 @@
const path = require('path');
function resolve(dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
context: resolve('demo'),
entry: './demo_pod.ts',
plugins: [],
devtool: 'inline-source-map',
watch: true,
mode: 'development',
module: {
rules: [
{
test: /\.ts$/,
use: 'ts-loader',
exclude: /node_modules/
},
{
test: /\.css$/,
use: [
{ loader: 'style-loader', options: { injectType: 'lazyStyleTag' } },
'css-loader',
],
exclude: /node_modules/
}
],
},
resolve: {
extensions: ['.ts', '.js'],
},
output: {
filename: 'demo.js',
path: resolve('demo/dist'),
libraryTarget: 'umd',
umdNamedDefine: true
}
};

5
demo/README.md

@ -0,0 +1,5 @@
### HOW TO RUN
run `yarn run dev` and `yarn run demo` in separate terminals simultaneously.
open `demo.html` in your browser.

38
demo/demo.html

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<script src="./dist/demo.js" type="text/javascript"></script>
</head>
<body>
<div id="chart" style="width: 50%; height: 500px;"></div>
<script type="text/javascript">
const startTime = 1590590148;
const arrayLength = 20;
const data1 = Array.from({ length: arrayLength }, (el, idx) => [startTime + idx * 10000, Math.floor(Math.random() * 40)]);
let options = {
renderLegend: false,
axis: {
y: { range: [0, 350] },
x: { format: 'time' }
},
zoomEvents: {
mouse: { zoom: { isActive: false }, pan: { isActive: false } },
scroll: { zoom: { isActive: false } }
},
}
var pod = new DemoPod(
document.getElementById('chart'),
[
{ target: 'test1', datapoints: data1, color: 'green' },
],
options
);
pod.render();
</script>
</body>
</html>

56
demo/demo_pod.ts

@ -0,0 +1,56 @@
import {
ChartwerkPod,
Serie,
Options
} from '../dist/index';
import * as d3 from 'd3';
import * as _ from 'lodash';
class DemoPod extends ChartwerkPod<Serie, Options> {
lineGenerator = null;
constructor(
_el: HTMLElement,
_series: Serie[] = [],
_options: Options = {},
) {
super(_el, _series, _options);
}
override renderMetrics(): void {
this.clearAllMetrics();
this.initLineGenerator();
for(const serie of this.series.visibleSeries) {
this.renderLine(serie);
}
}
clearAllMetrics(): void {
// TODO: temporary hack before it will be implemented in core.
this.chartContainer.selectAll('.metric-el').remove();
}
initLineGenerator(): void {
this.lineGenerator = d3.line()
.x(d => this.state.xScale(d[0]))
.y(d => this.state.yScale(d[1]));
}
renderLine(serie: Serie): void {
this.metricContainer
.append('path')
.datum(serie.datapoints)
.attr('class', `metric-path-${serie.idx} metric-el ${serie.class}`)
.attr('fill-opacity', 0)
.attr('stroke', serie.color)
.attr('stroke-width', 1)
.attr('stroke-opacity', 0.7)
.attr('pointer-events', 'none')
.attr('d', this.lineGenerator);
}
}
export { DemoPod };

5
package.json

@ -1,6 +1,6 @@
{ {
"name": "@chartwerk/core", "name": "@chartwerk/core",
"version": "0.6.17", "version": "0.6.26",
"description": "Chartwerk core", "description": "Chartwerk core",
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",
@ -10,11 +10,12 @@
"scripts": { "scripts": {
"build": "webpack --config build/webpack.prod.conf.js", "build": "webpack --config build/webpack.prod.conf.js",
"dev": "webpack --config build/webpack.dev.conf.js", "dev": "webpack --config build/webpack.dev.conf.js",
"demo": "webpack --config build/webpack.demo.conf.js",
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://gitlab.com/chartwerk/core.git" "url": "http://code.corpglory.net/chartwerk/core.git"
}, },
"author": "CorpGlory Inc.", "author": "CorpGlory Inc.",
"license": "ISC", "license": "ISC",

42
src/VueChartwerkPodMixin.ts

@ -39,9 +39,9 @@ export default {
}, },
methods: { methods: {
// it's "abstract" method. "children" components should override it // it's "abstract" method. "children" components should override it
render() { }, render() {},
renderSharedCrosshair(values: { x?: number, y?: number }) { }, renderSharedCrosshair(values: { x?: number, y?: number }) {},
hideSharedCrosshair() { }, hideSharedCrosshair() {},
onPanningRescale(event) { onPanningRescale(event) {
this.pod.rescaleMetricAndAxis(event); this.pod.rescaleMetricAndAxis(event);
}, },
@ -50,41 +50,48 @@ export default {
this.render(); this.render();
}, },
appendEvents() { appendEvents() {
if(this.options.eventsCallbacks === undefined) { if(this.options.events === undefined) {
this.options.eventsCallbacks = {} if(this.options.eventsCallbacks !== undefined) {
this.options.events = this.options.eventsCallbacks
} else {
this.options.events = {};
}
} }
if(has(this.$listeners, 'zoomIn')) { if(has(this.$listeners, 'zoomIn')) {
this.options.eventsCallbacks.zoomIn = this.zoomIn.bind(this); this.options.events.zoomIn = this.zoomIn.bind(this);
} }
if(has(this.$listeners, 'zoomOut')) { if(has(this.$listeners, 'zoomOut')) {
this.options.eventsCallbacks.zoomOut = this.zoomOut.bind(this); this.options.events.zoomOut = this.zoomOut.bind(this);
}
if(has(this.$listeners, 'mouseOver')) {
this.options.events.mouseOver = this.mouseOver.bind(this);
} }
if(has(this.$listeners, 'mouseMove')) { if(has(this.$listeners, 'mouseMove')) {
this.options.eventsCallbacks.mouseMove = this.mouseMove.bind(this); this.options.events.mouseMove = this.mouseMove.bind(this);
} }
if(has(this.$listeners, 'mouseOut')) { if(has(this.$listeners, 'mouseOut')) {
this.options.eventsCallbacks.mouseOut = this.mouseOut.bind(this); this.options.events.mouseOut = this.mouseOut.bind(this);
} }
if(has(this.$listeners, 'onLegendClick')) { if(has(this.$listeners, 'onLegendClick')) {
this.options.eventsCallbacks.onLegendClick = this.onLegendClick.bind(this); this.options.events.onLegendClick = this.onLegendClick.bind(this);
} }
if(has(this.$listeners, 'panningEnd')) { if(has(this.$listeners, 'panningEnd')) {
this.options.eventsCallbacks.panningEnd = this.panningEnd.bind(this); this.options.events.panningEnd = this.panningEnd.bind(this);
} }
if(has(this.$listeners, 'panning')) { if(has(this.$listeners, 'panning')) {
this.options.eventsCallbacks.panning = this.panning.bind(this); this.options.events.panning = this.panning.bind(this);
} }
if(has(this.$listeners, 'contextMenu')) { if(has(this.$listeners, 'contextMenu')) {
this.options.eventsCallbacks.contextMenu = this.contextMenu.bind(this); this.options.events.contextMenu = this.contextMenu.bind(this);
} }
if(has(this.$listeners, 'sharedCrosshairMove')) { if(has(this.$listeners, 'sharedCrosshairMove')) {
this.options.eventsCallbacks.sharedCrosshairMove = this.sharedCrosshairMove.bind(this); this.options.events.sharedCrosshairMove = this.sharedCrosshairMove.bind(this);
} }
if(has(this.$listeners, 'renderStart')) { if(has(this.$listeners, 'renderStart')) {
this.options.eventsCallbacks.renderStart = this.renderStart.bind(this); this.options.events.renderStart = this.renderStart.bind(this);
} }
if(has(this.$listeners, 'renderEnd')) { if(has(this.$listeners, 'renderEnd')) {
this.options.eventsCallbacks.renderEnd = this.renderEnd.bind(this); this.options.events.renderEnd = this.renderEnd.bind(this);
} }
}, },
zoomIn(range) { zoomIn(range) {
@ -93,6 +100,9 @@ export default {
zoomOut(centers) { zoomOut(centers) {
this.$emit('zoomOut', centers); this.$emit('zoomOut', centers);
}, },
mouseOver() {
this.$emit('mouseOver');
},
mouseMove(evt) { mouseMove(evt) {
this.$emit('mouseMove', evt); this.$emit('mouseMove', evt);
}, },

79
src/index.ts

@ -1,3 +1,4 @@
import { AxisRange } from './types';
import VueChartwerkPodMixin from './VueChartwerkPodMixin'; import VueChartwerkPodMixin from './VueChartwerkPodMixin';
import { Grid } from './components/grid'; import { Grid } from './components/grid';
@ -30,15 +31,13 @@ import { palette } from './colors';
import * as d3 from 'd3'; import * as d3 from 'd3';
import first from 'lodash/first';
import last from 'lodash/last';
import debounce from 'lodash/debounce'; import debounce from 'lodash/debounce';
const DEFAULT_TICK_SIZE = 2; const DEFAULT_TICK_SIZE = 2;
const MILISECONDS_IN_MINUTE = 60 * 1000;
abstract class ChartwerkPod<T extends Serie, O extends Options> {
class ChartwerkPod<T extends Serie, O extends Options> {
protected series: CoreSeries<T>; protected series: CoreSeries<T>;
protected options: CoreOptions<O>; protected options: CoreOptions<O>;
@ -80,7 +79,8 @@ abstract class ChartwerkPod<T extends Serie, O extends Options> {
_series: T[] = [], _series: T[] = [],
_options: O _options: O
) { ) {
// TODO: test if it's necessary // need to call explicitly because option lazyStyleTag
// in webpack style-loader
styles.use(); styles.use();
this.options = new CoreOptions(_options); this.options = new CoreOptions(_options);
@ -116,6 +116,7 @@ abstract class ChartwerkPod<T extends Serie, O extends Options> {
this.renderLegend(); this.renderLegend();
this.renderYLabel(); this.renderYLabel();
this.renderY1Label();
this.renderXLabel(); this.renderXLabel();
this.options.callbackRenderEnd(); this.options.callbackRenderEnd();
@ -152,12 +153,13 @@ abstract class ChartwerkPod<T extends Serie, O extends Options> {
this.series.updateSeries(newSeries); this.series.updateSeries(newSeries);
} }
protected abstract renderMetrics(): void; protected renderMetrics(): void {}
protected abstract onMouseOver(): void; protected onMouseOver(): void {}
protected abstract onMouseOut(): void; protected onMouseOut(): void {}
protected abstract onMouseMove(): void; protected onMouseMove(): void {}
public abstract renderSharedCrosshair(values: { x?: number, y?: number }): void; protected onMouseClick(): void {}
public abstract hideSharedCrosshair(): void; public renderSharedCrosshair(values: { x?: number, y?: number }): void {}
public hideSharedCrosshair(): void {}
protected initPodState(): void { protected initPodState(): void {
const boxPararms = { const boxPararms = {
@ -327,12 +329,21 @@ abstract class ChartwerkPod<T extends Serie, O extends Options> {
// TODO: refactor for a new mouse/scroll events // TODO: refactor for a new mouse/scroll events
const panKeyEvent = this.options.mousePanEvent.keyEvent; const panKeyEvent = this.options.mousePanEvent.keyEvent;
const isPanActive = this.options.mousePanEvent.isActive; const isPanActive = this.options.mousePanEvent.isActive;
if(isPanActive === true && panKeyEvent === KeyEvent.MAIN) { const isBrushActive = this.options.mouseZoomEvent.isActive;
this.initPan(); if(panKeyEvent === KeyEvent.MAIN) {
this.initBrush(); if(isPanActive) {
this.initPan();
}
if(isBrushActive) {
this.initBrush();
}
} else { } else {
this.initBrush(); if(isBrushActive) {
this.initPan(); this.initBrush();
}
if(isPanActive) {
this.initPan();
}
} }
this.ensureOverlayExisting(); this.ensureOverlayExisting();
@ -341,6 +352,7 @@ abstract class ChartwerkPod<T extends Serie, O extends Options> {
.on('mouseover', this.onMouseOver.bind(this)) .on('mouseover', this.onMouseOver.bind(this))
.on('mouseout', this.onMouseOut.bind(this)) .on('mouseout', this.onMouseOut.bind(this))
.on('mousemove', this.onMouseMove.bind(this)) .on('mousemove', this.onMouseMove.bind(this))
.on('click', this.onMouseClick.bind(this))
.on('dblclick', () => { .on('dblclick', () => {
d3.event.stopPropagation(); d3.event.stopPropagation();
// TODO: add the same check as we have in line-pod // TODO: add the same check as we have in line-pod
@ -372,10 +384,6 @@ abstract class ChartwerkPod<T extends Serie, O extends Options> {
} }
protected initBrush(): void { protected initBrush(): void {
const isBrushActive = this.options.mouseZoomEvent.isActive;
if(isBrushActive === false) {
return;
}
switch(this.options.mouseZoomEvent.orientation) { switch(this.options.mouseZoomEvent.orientation) {
case BrushOrientation.VERTICAL: case BrushOrientation.VERTICAL:
this.brush = d3.brushY(); this.brush = d3.brushY();
@ -409,9 +417,9 @@ abstract class ChartwerkPod<T extends Serie, O extends Options> {
// TODO: refactor // TODO: refactor
switch(key) { switch(key) {
case KeyEvent.MAIN: case KeyEvent.MAIN:
return () => !d3.event.shiftKey; return () => !d3.event.shiftKey && !d3.event.button;
case KeyEvent.SHIFT: case KeyEvent.SHIFT:
return () => d3.event.shiftKey; return () => d3.event.shiftKey && !d3.event.button;
default: default:
throw new Error(`Unknown type of KeyEvent: ${key}`); throw new Error(`Unknown type of KeyEvent: ${key}`);
} }
@ -502,8 +510,8 @@ abstract class ChartwerkPod<T extends Serie, O extends Options> {
return; return;
} }
this.chartContainer.append('text') this.chartContainer.append('text')
.attr('y', 0 - this.margin.left) .attr('y', -this.margin.left)
.attr('x', 0 - (this.height / 2)) .attr('x', -(this.height / 2))
.attr('dy', '1em') .attr('dy', '1em')
.attr('class', 'y-axis-label') .attr('class', 'y-axis-label')
.attr('transform', 'rotate(-90)') .attr('transform', 'rotate(-90)')
@ -513,6 +521,22 @@ abstract class ChartwerkPod<T extends Serie, O extends Options> {
.text(this.options.axis.y.label); .text(this.options.axis.y.label);
} }
protected renderY1Label(): void {
if(this.options.axis.y1?.label === undefined) {
return;
}
this.chartContainer.append('text')
.attr('y', -this.width - this.margin.right)
.attr('x', (this.height / 2))
.attr('dy', '1em')
.attr('class', 'y-axis-label')
.attr('transform', 'rotate(90)')
.style('text-anchor', 'middle')
.style('font-size', '14px')
.style('fill', 'currentColor')
.text(this.options.axis.y1.label);
}
protected renderXLabel(): void { protected renderXLabel(): void {
if(this.options.axis.x.label === undefined) { if(this.options.axis.x.label === undefined) {
return; return;
@ -793,8 +817,7 @@ abstract class ChartwerkPod<T extends Serie, O extends Options> {
this.state.yValueRange = yRange; this.state.yValueRange = yRange;
this.brushStartSelection = null; this.brushStartSelection = null;
} }
this.zoomIn([xRange, yRange]);
this.options.callbackZoomIn([xRange, yRange]);
} }
protected zoomOut(): void { protected zoomOut(): void {
@ -807,6 +830,10 @@ abstract class ChartwerkPod<T extends Serie, O extends Options> {
this.options.callbackZoomOut(centers); this.options.callbackZoomOut(centers);
} }
protected zoomIn(ranges: AxisRange[]): void {
this.options.callbackZoomIn(ranges);
}
getAxisTicksFormatter(axisOptions: AxisOption): (d: any, i: number) => any { getAxisTicksFormatter(axisOptions: AxisOption): (d: any, i: number) => any {
// TODO: ticksCount === 0 -> suspicious option // TODO: ticksCount === 0 -> suspicious option
if(axisOptions.ticksCount === 0) { if(axisOptions.ticksCount === 0) {

69
src/models/options.ts

@ -90,7 +90,6 @@ export const CORE_DEFAULT_OPTIONS: Options = {
crosshair: DEFAULT_CROSSHAIR_OPTIONS, crosshair: DEFAULT_CROSSHAIR_OPTIONS,
renderLegend: true, renderLegend: true,
margin: DEFAULT_MARGIN, margin: DEFAULT_MARGIN,
eventsCallbacks: {},
} }
export class CoreOptions<O extends Options> { export class CoreOptions<O extends Options> {
@ -106,6 +105,14 @@ export class CoreOptions<O extends Options> {
protected setOptions(options: O): void { protected setOptions(options: O): void {
this._options = lodashDefaultsDeep(lodashCloneDeep(options), this.getDefaults()); this._options = lodashDefaultsDeep(lodashCloneDeep(options), this.getDefaults());
if(this._options.eventsCallbacks !== undefined) {
if(this._options.events !== undefined) {
throw new Error('events and eventsCallbacks are mutually exclusive');
}
this._options.events = this._options.eventsCallbacks;
}
// also bakward compatibility for clients who use "eventsCallbacks" instead of "events"
this._options.eventsCallbacks = this._options.events;
} }
// this getter can be overrited in Pod // this getter can be overrited in Pod
@ -160,74 +167,86 @@ export class CoreOptions<O extends Options> {
// event callbacks // event callbacks
callbackRenderStart(): void { callbackRenderStart(): void {
if(has(this._options.eventsCallbacks, 'renderStart')) { if(has(this._options.events, 'renderStart')) {
this._options.eventsCallbacks.renderStart(); this._options.events.renderStart();
} }
} }
callbackRenderEnd(): void { callbackRenderEnd(): void {
if(has(this._options.eventsCallbacks, 'renderEnd')) { if(has(this._options.events, 'renderEnd')) {
this._options.eventsCallbacks.renderEnd(); this._options.events.renderEnd();
} }
} }
callbackComponentRenderEnd(part: RenderComponent): void { callbackComponentRenderEnd(part: RenderComponent): void {
if(has(this._options.eventsCallbacks, 'componentRenderEnd')) { if(has(this._options.events, 'componentRenderEnd')) {
this._options.eventsCallbacks.componentRenderEnd(part); this._options.events.componentRenderEnd(part);
} }
} }
callbackLegendClick(idx: number): void { callbackLegendClick(idx: number): void {
if(has(this._options.eventsCallbacks, 'onLegendClick')) { if(has(this._options.events, 'onLegendClick')) {
this._options.eventsCallbacks.onLegendClick(idx); this._options.events.onLegendClick(idx);
} }
} }
callbackLegendLabelClick(idx: number): void { callbackLegendLabelClick(idx: number): void {
if(has(this._options.eventsCallbacks, 'onLegendLabelClick')) { if(has(this._options.events, 'onLegendLabelClick')) {
this._options.eventsCallbacks.onLegendLabelClick(idx); this._options.events.onLegendLabelClick(idx);
} }
} }
callbackPanning(event: { ranges: AxisRange[], d3Event: any }): void { callbackPanning(event: { ranges: AxisRange[], d3Event: any }): void {
if(has(this._options.eventsCallbacks, 'panning')) { if(has(this._options.events, 'panning')) {
this._options.eventsCallbacks.panning(event); this._options.events.panning(event);
} }
} }
callbackPanningEnd(ranges: AxisRange[]): void { callbackPanningEnd(ranges: AxisRange[]): void {
if(has(this._options.eventsCallbacks, 'panningEnd')) { if(has(this._options.events, 'panningEnd')) {
this._options.eventsCallbacks.panningEnd(ranges); this._options.events.panningEnd(ranges);
} }
} }
callbackZoomIn(ranges: AxisRange[]): void { callbackZoomIn(ranges: AxisRange[]): void {
if(has(this._options.eventsCallbacks, 'zoomIn')) { if(has(this._options.events, 'zoomIn')) {
this._options.eventsCallbacks.zoomIn(ranges); this._options.events.zoomIn(ranges);
} }
} }
callbackZoomOut(centers: { x: number, y: number }): void { callbackZoomOut(centers: { x: number, y: number }): void {
if(has(this._options.eventsCallbacks, 'zoomOut')) { if(has(this._options.events, 'zoomOut')) {
this._options.eventsCallbacks.zoomOut(centers); this._options.events.zoomOut(centers);
} }
} }
callbackSharedCrosshairMove(event: { datapoints, eventX, eventY }): void { callbackSharedCrosshairMove(event: { datapoints, eventX, eventY }): void {
if(has(this._options.eventsCallbacks, 'sharedCrosshairMove')) { if(has(this._options.events, 'sharedCrosshairMove')) {
this._options.eventsCallbacks.sharedCrosshairMove(event); this._options.events.sharedCrosshairMove(event);
}
}
callbackMouseOver(): void {
if(has(this._options.events, 'mouseOver')) {
this._options.events.mouseOver();
} }
} }
callbackMouseMove(event): void { callbackMouseMove(event): void {
if(has(this._options.eventsCallbacks, 'mouseMove')) { if(has(this._options.events, 'mouseMove')) {
this._options.eventsCallbacks.mouseMove(event); this._options.events.mouseMove(event);
} }
} }
callbackMouseOut(): void { callbackMouseOut(): void {
if(has(this._options.eventsCallbacks, 'mouseOut')) { if(has(this._options.events, 'mouseOut')) {
this._options.eventsCallbacks.mouseOut(); this._options.events.mouseOut();
}
}
callbackMouseClick(event): void {
if(has(this._options.events, 'mouseClick')) {
this._options.events.mouseClick(event);
} }
} }
} }

3
src/models/series.ts

@ -35,6 +35,7 @@ export class CoreSeries<T extends Serie> {
_series: Array<T> = []; _series: Array<T> = [];
constructor(series: T[], private _podDefaults?: Partial<T>) { constructor(series: T[], private _podDefaults?: Partial<T>) {
// TODO: create separate Serie class, and store instances in this._series
this.setSeries(series); this.setSeries(series);
} }
@ -83,7 +84,7 @@ export class CoreSeries<T extends Serie> {
get isSeriesAvailable(): boolean { get isSeriesAvailable(): boolean {
if(this.visibleSeries.length > 0) { if(this.visibleSeries.length > 0) {
const seriesEmptiness = lodashMap(this.visibleSeries, this._isSerieEmpty.bind(this)); const seriesEmptiness = lodashMap(this.visibleSeries, this._isSerieEmpty.bind(this));
return lodashIncludes(seriesEmptiness, false); return lodashIncludes(seriesEmptiness, false);
} }
return false; return false;

15
src/models/state.ts

@ -1,4 +1,4 @@
import { Serie, Options } from '../types'; import { Serie, Options, yAxisOrientation } from '../types';
import { CoreSeries } from './series'; import { CoreSeries } from './series';
import { CoreOptions } from './options'; import { CoreOptions } from './options';
@ -89,6 +89,15 @@ export class PodState<T extends Serie, O extends Options> {
this._transform = { x: 0, y: 0, k: 1 }; this._transform = { x: 0, y: 0, k: 1 };
} }
getYScaleByOrientation(orientation?: yAxisOrientation): d3.ScaleLinear<number, number> {
// TODO: we set defaults in Series class, so we don't expect `undefined` here
// we can remove this check when we implement Serie class (see TODO in `series.ts`)
if(orientation === undefined) {
return this._yScale;
}
return orientation === yAxisOrientation.LEFT ? this._yScale : this._y1Scale;
}
get yScale(): d3.ScaleLinear<number, number> { get yScale(): d3.ScaleLinear<number, number> {
return this._yScale; return this._yScale;
} }
@ -187,7 +196,7 @@ export class PodState<T extends Serie, O extends Options> {
if(this.coreOptions.axis.y1.range !== undefined) { if(this.coreOptions.axis.y1.range !== undefined) {
return min(this.coreOptions.axis.y1.range); return min(this.coreOptions.axis.y1.range);
} }
return this.coreSeries.minValueY; return this.coreSeries.minValueY1;
} }
public getMaxValueY1(): number { public getMaxValueY1(): number {
@ -197,7 +206,7 @@ export class PodState<T extends Serie, O extends Options> {
if(this.coreOptions.axis.y1.range !== undefined) { if(this.coreOptions.axis.y1.range !== undefined) {
return max(this.coreOptions.axis.y1.range); return max(this.coreOptions.axis.y1.range);
} }
return this.coreSeries.maxValueY; return this.coreSeries.maxValueY1;
} }
// getters for correct transform // getters for correct transform

37
src/types.ts

@ -14,23 +14,30 @@ export type Serie = {
yOrientation?: yAxisOrientation, yOrientation?: yAxisOrientation,
}; };
// TODO: move some options to line-chart // TODO: move some options to line-chart
export type Events = {
zoomIn?: (range: AxisRange[]) => void,
panning?: (event: { ranges: AxisRange[], d3Event: any }) => void,
panningEnd?: (range: AxisRange[]) => void,
zoomOut?: (centers: {x: number, y: number}) => void,
mouseOver?: () => void,
mouseMove?: (evt: any) => void,
mouseClick?: (evt: any) => void,
mouseOut?: () => void,
onLegendClick?: (idx: number) => void,
onLegendLabelClick?: (idx: number) => void,
contextMenu?: (evt: any) => void, // the same name as in d3.events
sharedCrosshairMove?: (event: any) => void,
renderStart?: () => void,
renderEnd?: () => void,
componentRenderEnd?: (part: RenderComponent) => void,
}
export type Options = { export type Options = {
margin?: Margin; margin?: Margin;
eventsCallbacks?: { // obsolete property, use events instead
zoomIn?: (range: AxisRange[]) => void, eventsCallbacks?: Events;
panning?: (event: { ranges: AxisRange[], d3Event: any }) => void, events?: Events;
panningEnd?: (range: AxisRange[]) => void,
zoomOut?: (centers: {x: number, y: number}) => void,
mouseMove?: (evt: any) => void,
mouseOut?: () => void,
onLegendClick?: (idx: number) => void,
onLegendLabelClick?: (idx: number) => void,
contextMenu?: (evt: any) => void, // the same name as in d3.events
sharedCrosshairMove?: (event: any) => void,
renderStart?: () => void,
renderEnd?: () => void,
componentRenderEnd?: (part: RenderComponent) => void,
};
axis?: AxesOptions; axis?: AxesOptions;
grid?: GridOptions; grid?: GridOptions;
crosshair?: CrosshairOptions; crosshair?: CrosshairOptions;

11
tsconfig.json

@ -1,7 +1,6 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "es5",
"rootDir": "./src",
"module": "esnext", "module": "esnext",
"declaration": true, "declaration": true,
"declarationDir": "dist", "declarationDir": "dist",
@ -16,7 +15,11 @@
"noImplicitUseStrict": false, "noImplicitUseStrict": false,
"noImplicitAny": false, "noImplicitAny": false,
"noUnusedLocals": false, "noUnusedLocals": false,
"baseUrl": "./src", "moduleResolution": "node",
"moduleResolution": "node" },
} "exclude": [
"node_modules",
"dist",
"demo"
]
} }

Loading…
Cancel
Save