ulogger-server/js/chart.js

173 lines
4.7 KiB
JavaScript
Raw Normal View History

2019-06-29 12:54:32 +02:00
/*
* μlogger
*
* Copyright(C) 2019 Bartek Fabiszewski (www.fabiszewski.net)
*
* This is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
2019-05-15 11:32:36 +02:00
import { config, lang } from './constants.js';
import uEvent from './event.js';
import uUtils from './utils.js';
/* global Chartist */
document.addEventListener('DOMContentLoaded', () => {
Chart.onDomLoaded();
});
export default class Chart {
/**
* @param {uBinder} binder
*/
constructor(binder) {
2019-06-29 12:54:32 +02:00
binder.addEventListener(uEvent.MARKER_OVER, this);
binder.addEventListener(uEvent.MARKER_SELECT, this);
2019-05-15 11:32:36 +02:00
binder.addEventListener(uEvent.TRACK_READY, this);
2019-06-29 12:54:32 +02:00
binder.addEventListener(uEvent.UI_READY, this);
2019-05-15 11:32:36 +02:00
this._binder = binder;
this._targetEl = null;
2019-06-29 12:54:32 +02:00
this._points = null;
2019-05-15 11:32:36 +02:00
}
/**
* @return {Array<{x: number, y: number}>}
*/
get data() {
return this._data;
}
render() {
if (!this._targetEl) {
return;
}
const chart = new Chartist.Line(this._targetEl, {
series: [ this.data ]
}, {
lineSmooth: true,
showArea: true,
axisX: {
type: Chartist.AutoScaleAxis,
onlyInteger: true,
showLabel: false
},
plugins: [
Chartist.plugins.ctAxisTitle({
axisY: {
axisTitle: `${lang.strings['altitude']} (${config.unit_m})`,
axisClass: 'ct-axis-title',
offset: {
x: 0,
y: 20
},
textAnchor: 'middle',
flipTitle: true
}
})
]
});
chart.on('created', () => {
2019-06-29 12:54:32 +02:00
this._points = document.querySelectorAll('.ct-chart-line .ct-point');
const len = this._points.length;
for (let i = 0; i < len; i++) {
2019-05-15 11:32:36 +02:00
((id) => {
2019-06-29 12:54:32 +02:00
this._points[id].addEventListener('click', () => {
this._binder.dispatchEvent(uEvent.CHART_CLICKED, id);
2019-05-15 11:32:36 +02:00
});
})(i);
}
2019-06-29 12:54:32 +02:00
this._binder.dispatchEvent(uEvent.CHART_READY, len);
2019-05-15 11:32:36 +02:00
});
// need to update chart first time the container becomes visible
2019-06-29 12:54:32 +02:00
if (!this.isVisible()) {
2019-05-15 11:32:36 +02:00
const observer = new MutationObserver(() => {
2019-06-29 12:54:32 +02:00
if (this.isVisible()) {
2019-05-15 11:32:36 +02:00
// eslint-disable-next-line no-underscore-dangle
this._targetEl.__chartist__.update();
observer.disconnect();
}
});
observer.observe(this._targetEl.parentNode, { attributes: true });
}
2019-06-29 12:54:32 +02:00
}
2019-05-15 11:32:36 +02:00
2019-06-29 12:54:32 +02:00
isVisible() {
return this._targetEl && this._targetEl.parentNode && this._targetEl.parentNode.style.display === 'block';
2019-05-15 11:32:36 +02:00
}
static onDomLoaded() {
uUtils.addScript('js/lib/chartist.min.js', 'chartist_js', () => {
uUtils.addScript('js/lib/chartist-plugin-axistitle.min.js', 'chartist_axistitle_js');
});
uUtils.addCss('css/chartist.min.css', 'chartist_css');
}
/**
* @param {uEvent} event
* @param {*=} args
*/
handleEvent(event, args) {
if (event.type === uEvent.TRACK_READY) {
/** @type {uTrack} */
const track = args;
this._data = track.plotData;
this.render()
} else if (event.type === uEvent.UI_READY) {
/** @type {uUI} */
const ui = args;
this._targetEl = ui.chart;
2019-06-29 12:54:32 +02:00
} else if (event.type === uEvent.MARKER_OVER) {
/** @type {number} */
const pointId = args;
if (pointId) {
this.pointOver(pointId);
} else {
this.pointOut();
}
} else if (event.type === uEvent.MARKER_SELECT) {
/** @type {number} */
const pointId = args;
if (pointId) {
this.pointSelect(pointId);
} else {
this.pointUnselect();
}
2019-05-15 11:32:36 +02:00
}
}
2019-06-29 12:54:32 +02:00
pointOver(pointId) {
if (this.isVisible()) {
const point = this._points[pointId];
point.classList.add('ct-point-hilight');
}
}
pointOut() {
this._targetEl.querySelectorAll('.ct-point-hilight').forEach((el) => el.classList.remove('ct-point-hilight'));
}
pointSelect(pointId) {
if (this.isVisible()) {
const point = this._points[pointId];
point.classList.add('ct-point-selected');
}
}
pointUnselect() {
this._targetEl.querySelectorAll('.ct-point-selected').forEach((el) => el.classList.remove('ct-point-selected'));
}
2019-05-15 11:32:36 +02:00
}