@eclipse-scout/chart
Version:
Eclipse Scout chart
1,337 lines (1,301 loc) • 329 kB
JavaScript
/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ "./src/bookmark/ChartTableControlConfigHelperImpl.ts":
/*!***********************************************************!*\
!*** ./src/bookmark/ChartTableControlConfigHelperImpl.ts ***!
\***********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ ChartTableControlConfigHelperImpl: () => (/* binding */ ChartTableControlConfigHelperImpl)
/* harmony export */ });
/* harmony import */ var _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @eclipse-scout/core */ "@eclipse-scout/core");
/* harmony import */ var _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_eclipse_scout_core__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _index__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../index */ "./src/index.ts");
/*
* Copyright (c) 2010, 2025 BSI Business Systems Integration AG
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
class ChartTableControlConfigHelperImpl extends _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_0__.ChartTableControlConfigHelper {
async _exportConfig(page) {
if (!page?.detailTable) {
return null;
}
let chartTableControl = page.detailTable.findTableControl(_index__WEBPACK_IMPORTED_MODULE_1__.ChartTableControl);
if (chartTableControl && chartTableControl.selected) {
return _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_0__.scout.create(_index__WEBPACK_IMPORTED_MODULE_1__.ChartTableControlConfigDo, {
chartTypeId: chartTableControl.chartType,
chartGroup1ColumnId: chartTableControl.chartGroup1?.id,
chartGroup1Modifier: chartTableControl.chartGroup1?.modifier,
chartGroup2ColumnId: chartTableControl.chartGroup2?.id,
chartGroup2Modifier: chartTableControl.chartGroup2?.modifier,
chartAggregationColumnId: chartTableControl.chartAggregation?.id,
chartAggregationModifier: chartTableControl.chartAggregation?.modifier
});
}
return null;
}
async _importConfig(page, config) {
if (!page?.detailTable || !config) {
return;
}
let chartTableControl = page.detailTable.findTableControl(_index__WEBPACK_IMPORTED_MODULE_1__.ChartTableControl);
if (chartTableControl) {
chartTableControl.setSelected(true); // necessary, because otherwise internal data structures might not be properly initialized
chartTableControl.setChartType(config.chartTypeId);
chartTableControl.setChartGroup1({
id: config.chartGroup1ColumnId,
modifier: config.chartGroup1Modifier
});
chartTableControl.setChartGroup2({
id: config.chartGroup2ColumnId,
modifier: config.chartGroup2Modifier
});
chartTableControl.setChartAggregation({
id: config.chartAggregationColumnId,
modifier: config.chartAggregationModifier
});
}
}
}
/***/ }),
/***/ "./src/chart/AbstractChartRenderer.ts":
/*!********************************************!*\
!*** ./src/chart/AbstractChartRenderer.ts ***!
\********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ AbstractChartRenderer: () => (/* binding */ AbstractChartRenderer)
/* harmony export */ });
/* harmony import */ var _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @eclipse-scout/core */ "@eclipse-scout/core");
/* harmony import */ var _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_eclipse_scout_core__WEBPACK_IMPORTED_MODULE_0__);
/*
* Copyright (c) 2010, 2025 BSI Business Systems Integration AG
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
class AbstractChartRenderer extends _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_0__.PropertyEventEmitter {
chart;
session;
/** true while this.render() is executing */
rendering;
rendered;
/** set by render() and remove(), makes it unnecessary to carry an argument through all method calls */
animationDuration;
firstOpaqueBackgroundColor;
constructor(chart) {
super();
this.chart = chart;
this.session = chart.session;
this.rendering = false;
this.rendered = false;
this.animationDuration = 0;
this.firstOpaqueBackgroundColor = '';
}
validate() {
if (!this._validateChartData()) {
return false;
}
return this._validate();
}
_validateChartData() {
let chartData = this.chart && this.chart.data;
if (!chartData || !chartData.chartValueGroups || chartData.chartValueGroups.length === 0) {
return false;
}
// check lengths
let i,
length = 0;
for (i = 0; i < chartData.chartValueGroups.length; i++) {
let chartValueGroup = chartData.chartValueGroups[i];
if (!chartValueGroup.values) {
return false;
}
// Length of all "values" arrays have to be equal
if (i === 0) {
length = chartValueGroup.values.length;
} else {
if (chartValueGroup.values.length !== length) {
return false;
}
}
// color should have been set.
if (!this.chart.config.options.autoColor && !_eclipse_scout_core__WEBPACK_IMPORTED_MODULE_0__.arrays.ensure(chartValueGroup.colorHexValue).length && !chartValueGroup.cssClass) {
return false;
}
}
for (i = 0; i < chartData.axes.length; i++) {
if (chartData.axes[i].length !== length) {
return false;
}
}
return true;
}
_validate() {
// Override in subclasses
return true;
}
/**
* @param requestAnimation
* Whether animations should be used while rendering the chart. Note that his
* property is ignored when chart.config.options.animation.duration is <code>0</code>!
*/
render(requestAnimation) {
if (!this.validate() || !this.chart.rendered) {
return;
}
const configAnimationDuration = this.chart.config.options.animation.duration;
this.setAnimationDuration(requestAnimation ? configAnimationDuration : 0);
this.rendering = true;
this._render();
this.rendering = false;
this.rendered = true;
this.setAnimationDuration(configAnimationDuration);
}
_render() {
// Override in subclasses
}
renderCheckedItems() {
if (this.rendered) {
this._renderCheckedItems();
}
}
_renderCheckedItems() {
// nop
}
/**
* @param requestAnimation
* Whether animations should be used while updating the chart. Note that his
* property is ignored when chart.config.options.animation.duration is <code>0</code>!
*/
updateData(requestAnimation) {
if (!this.rendered) {
this.render(requestAnimation);
return;
}
if (!this.validate() || !this.isDataUpdatable()) {
return;
}
const configAnimationDuration = this.chart.config.options.animation.duration;
this.setAnimationDuration(requestAnimation ? configAnimationDuration : 0);
this._updateData();
this.setAnimationDuration(configAnimationDuration);
}
_updateData() {
// Override in subclasses
}
isDataUpdatable() {
return false;
}
isDetachSupported() {
return true;
}
refresh() {
if (this.rendering) {
return;
}
if (this.rendered) {
this.remove(false);
}
this.render(false);
}
setAnimationDuration(animationDuration) {
if (!this.setProperty('animationDuration', animationDuration)) {
return;
}
if (this.rendered) {
this._renderAnimationDuration();
}
}
_setAnimationDuration(animationDuration) {
this._setProperty('animationDuration', animationDuration);
}
_renderAnimationDuration() {
// nop
}
/**
* @param requestAnimation
* Whether animations should be used while removing the chart. Note that his
* property is ignored when chart.config.options.animation.duration is <code>0</code>!
*/
remove() {
let requestAnimation = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
let afterRemoveFunc = arguments.length > 1 ? arguments[1] : undefined;
const configAnimationDuration = this.chart.config.options.animation.duration;
this.setAnimationDuration(requestAnimation && configAnimationDuration);
if (this.animationDuration && this.rendered) {
this._removeAnimated(afterRemoveFunc);
} else {
this._remove(afterRemoveFunc);
}
this.setAnimationDuration(configAnimationDuration);
}
_remove(afterRemoveFunc) {
this.rendered = false;
afterRemoveFunc && afterRemoveFunc();
}
_removeAnimated(afterRemoveFunc) {
// Override in subclasses
this._remove(afterRemoveFunc);
}
/**
* Controls if the animation of the chart is shown when chart data has been updated.
*/
shouldAnimateRemoveOnUpdate(opts) {
return opts.requestAnimation;
}
}
/***/ }),
/***/ "./src/chart/AbstractSvgChartRenderer.ts":
/*!***********************************************!*\
!*** ./src/chart/AbstractSvgChartRenderer.ts ***!
\***********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ AbstractSvgChartRenderer: () => (/* binding */ AbstractSvgChartRenderer)
/* harmony export */ });
/* harmony import */ var _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @eclipse-scout/core */ "@eclipse-scout/core");
/* harmony import */ var _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_eclipse_scout_core__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! jquery */ "jquery");
/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(jquery__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _index__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../index */ "./src/index.ts");
/*
* Copyright (c) 2010, 2025 BSI Business Systems Integration AG
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
class AbstractSvgChartRenderer extends _index__WEBPACK_IMPORTED_MODULE_2__.AbstractChartRenderer {
chartBox;
/** Clipping and masking */
clipId;
maskId;
suppressLegendBox;
height;
width;
chartAnimationStopping;
$svg;
_nonValueClickHandler;
constructor(chart) {
super(chart);
this.chartBox = null;
this.clipId = 'Clip-' + _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_0__.ObjectIdProvider.get().createUiSeqId();
this.maskId = 'Mask-' + _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_0__.ObjectIdProvider.get().createUiSeqId();
this.suppressLegendBox = false;
this._nonValueClickHandler = this._onNonValueClick.bind(this);
}
static FONT_SIZE_SMALLEST = 'smallestFont';
static FONT_SIZE_SMALL = 'smallFont';
static FONT_SIZE_MIDDLE = 'middleFont';
static FONT_SIZE_BIG = 'bigFont';
_render() {
if (!this.$svg) {
this.$svg = this.chart.$container.appendSVG('svg', 'chart-svg');
_eclipse_scout_core__WEBPACK_IMPORTED_MODULE_0__.aria.role(this.$svg, 'img');
// labeling has to be done here because otherwise the svg is ignored
this.linkChartWithFieldLabel(this.$svg);
this.$svg.on('click', this._nonValueClickHandler);
}
this.firstOpaqueBackgroundColor = _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_0__.styles.getFirstOpaqueBackgroundColor(this.$svg);
// This works, because CSS specifies 100% width/height
this.height = this.$svg.height();
this.width = this.$svg.width();
this._initChartBox();
if (this._useFontSizeBig()) {
this.$svg.addClass(AbstractSvgChartRenderer.FONT_SIZE_BIG);
} else if (this._useFontSizeMiddle()) {
this.$svg.addClass(AbstractSvgChartRenderer.FONT_SIZE_MIDDLE);
} else if (this._useFontSizeSmall()) {
this.$svg.addClass(AbstractSvgChartRenderer.FONT_SIZE_SMALL);
} else if (this._useFontSizeSmallest()) {
this.$svg.addClass(AbstractSvgChartRenderer.FONT_SIZE_SMALLEST);
}
if (!this.$svg.isAttached()) {
// user navigated away. do not try to render->error
return;
}
this._renderInternal();
}
/**
* Links chart svg with its field label so the field name is read when entering the chart
*
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-labelledby">ARIA: aria-labelledby</a>
*/
linkChartWithFieldLabel($chartSvg) {
if (!$chartSvg) {
return;
}
let $field = $chartSvg.parents('.chart-field');
if ($field.length > 0) {
let $fieldLabel = $field.eq(0).children('label');
if ($fieldLabel.length > 0) {
_eclipse_scout_core__WEBPACK_IMPORTED_MODULE_0__.aria.linkElementWithLabel($chartSvg, $fieldLabel.eq(0));
}
}
}
_renderInternal() {
// Override in subclasses
}
_useFontSizeBig() {
return false;
}
_useFontSizeMiddle() {
return false;
}
_useFontSizeSmall() {
return false;
}
_useFontSizeSmallest() {
return false;
}
remove() {
let requestAnimation = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
let afterRemoveFunc = arguments.length > 1 ? arguments[1] : undefined;
if (this.rendered && !this.chartAnimationStopping) {
this.chartAnimationStopping = true;
this.$svg.children().stop(true, false);
this.chartAnimationStopping = false;
}
super.remove(requestAnimation, afterRemoveFunc);
}
_remove(afterRemoveFunc) {
// this function is called directly from renderers after all removal animations are done
// however, other animations may have been queued in the meantime (e.g. in case the chart was removed, then added (+animation queued), and then removed again)
if (this.rendered) {
this.$svg.children().stop(true, false);
// need to check again, as stop() may have triggered a chart removal and this may not be rendered anymore
if (this.rendered) {
this.$svg.remove();
this.$svg = null;
}
}
this.rendered = false;
afterRemoveFunc && afterRemoveFunc(this.chartAnimationStopping);
}
/**
* For all parameters: use null when parameter is not used or set by a chart type.
*/
_createClickObject(xIndex, datasetIndex) {
return {
xIndex: xIndex,
dataIndex: xIndex,
datasetIndex: datasetIndex
};
}
_onChartValueClick(event) {
this.chart.handleValueClick(event.data, event.originalEvent);
event.stopPropagation();
}
_onNonValueClick(event) {
this.chart.handleNonValueClick(event.originalEvent);
event.stopPropagation();
}
_measureText(text, legendLabelClass) {
let $label = this.$svg.appendSVG('text', legendLabelClass).attr('x', 0).attr('y', 0).attr('visibility', 'hidden').text(text);
let textBounds;
try {
// Firefox throws error when node is not in dom(already removed by navigating away). all other browser returns a bounding box with 0
textBounds = $label[0].getBBox();
} catch (e) {
return {
height: 0,
width: 0
};
}
$label.remove();
return textBounds;
}
_renderLine(x1, y1, x2, y2, lineClass) {
let $line = this.$svg.appendSVG('line', lineClass).attr('x1', x1).attr('y1', y1).attr('x2', x2).attr('y2', y2);
if (this.animationDuration) {
$line.attr('opacity', 0).animateSVG('opacity', 1, this.animationDuration, null, true);
}
return $line;
}
_renderLineLabel(x, y, label, labelClass, drawBackground) {
let $label = this.$svg.appendSVG('text', labelClass ? labelClass : 'line-label').attr('x', x).attr('y', y).text(label);
if (drawBackground) {
$label.attr('mask', 'url(#' + this.maskId + ')');
let $background = this.$svg.appendSVG('text', labelClass ? labelClass + ' background' : 'line-label-background').attr('x', x).attr('y', y).attr('clip-path', 'url(#' + this.clipId + ')').text(label);
$label.data('$background', $background);
if (this.animationDuration) {
$background.attr('opacity', 0).animateSVG('opacity', 1, this.animationDuration, null, true);
}
}
if (this.animationDuration) {
$label.attr('opacity', 0).animateSVG('opacity', 1, this.animationDuration, null, true);
}
return $label;
}
_initChartBox() {
this.chartBox = {
width: this.width,
height: this.height,
xOffset: 0,
yOffset: 0,
mX: function () {
return this.xOffset + this.width / 2;
},
mY: function () {
return this.yOffset + this.height / 2;
}
};
}
_createAnimationObjectWithTabIndexRemoval(animationFunc, duration) {
return {
step: function (now, fx) {
try {
animationFunc.bind(this)(now, fx);
} catch (e) {
// prevent logging thousands of exceptions (1 per animation step) by stopping and clearing the queue
jquery__WEBPACK_IMPORTED_MODULE_1___default()(this).stop(true, false);
throw e;
}
},
duration: duration ? duration : _index__WEBPACK_IMPORTED_MODULE_2__.Chart.DEFAULT_ANIMATION_DURATION,
complete: function () {
jquery__WEBPACK_IMPORTED_MODULE_1___default()(this).removeAttr('tabindex');
}
};
}
_addClipping(cssClass) {
// add clip and mask paths for all relevant objects
let $clip = this.$svg.appendSVG('clipPath');
$clip[0].id = this.clipId;
let $mask = this.$svg.appendSVG('mask');
$mask.appendSVG('rect').attr('x', 0).attr('y', 0).attr('width', '100%').attr('height', '100%').attr('fill', 'white');
$mask[0].id = this.maskId;
this.chart.$container.find('.' + cssClass).each(function (i) {
this.id = 'ClipMask-' + _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_0__.ObjectIdProvider.get().createUiSeqId();
$clip.appendSVG('use').attrXLINK('href', '#' + this.id);
$mask.appendSVG('use').attrXLINK('href', '#' + this.id);
});
}
_renderWireLegend(text, legendPositions, className, drawBackgroundBox) {
if (!this.chart.config.options.plugins.tooltip.enabled) {
return {
detachFunc: () => {
// nop
},
attachFunc: () => {
// nop
},
removeFunc: () => {
// nop
}
};
}
let legend = {},
padding = 5,
$background,
backgroundWidth = 0,
lineHeight = 17,
backgroundHeight = lineHeight;
if (drawBackgroundBox) {
$background = this.$svg.appendSVG('rect', 'wire-legend-background-box').attr('opacity', '1');
}
let positions = legendPositions;
// draw and measure label
let $legend,
lengthLegend = 0,
horizontalSpace = 0;
if (positions.h === -1) {
horizontalSpace = positions.x2 - 2 * padding;
} else {
horizontalSpace = this.width - positions.x2 - 2 * padding;
}
if (Array.isArray(text)) {
for (let i = 0; i < text.length; i++) {
let posIndex = text.length - i - 1;
let yPos = positions.y2 + positions.v * padding - lineHeight * posIndex - padding * posIndex;
let $line = this._renderLineLabel(positions.x2 + padding, yPos, _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_0__.strings.truncateText(text[i], horizontalSpace, this._measureText.bind(this)), '', drawBackgroundBox);
$line.addClass(className);
lengthLegend = Math.max(lengthLegend, $line[0].getComputedTextLength());
if (i === 0) {
$legend = $line;
} else {
if ($legend.data('lines')) {
$legend.data('lines').push($line);
} else {
$legend.data('lines', [$line]);
}
}
}
} else {
$legend = this._renderLineLabel(positions.x2 + padding, positions.y2 + positions.v * padding, _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_0__.strings.truncateText(text, horizontalSpace, this._measureText.bind(this)), '', drawBackgroundBox);
$legend.addClass(className);
lengthLegend = $legend[0].getComputedTextLength();
}
backgroundWidth = lengthLegend + 2 * padding;
if (legendPositions.autoPosition) {
positions = legendPositions.posFunc.call(this, backgroundWidth, backgroundHeight);
// adjust legend
$legend.attr('x', positions.x2 + padding);
$legend.attr('y', positions.y2 + positions.v * padding);
}
// fix layout depending on orientation of legend
if (positions.h === -1) {
$legend.attr('x', positions.x2 - padding - lengthLegend);
$legend.css('text-anchor', 'left');
if ($legend.data('lines')) {
$legend.data('lines').forEach($line => {
$line.attr('x', positions.x2 - padding - lengthLegend);
$line.css('text-anchor', 'left');
});
}
} else {
$legend.attr('x', positions.x2 + padding);
$legend.css('text-anchor', 'right');
if ($legend.data('lines')) {
$legend.data('lines').forEach($line => {
$line.attr('x', positions.x2 + padding);
$line.css('text-anchor', 'right');
});
}
}
if (positions.v === 1) {
if ($legend.data('lines')) {
$legend.data('lines').forEach(($line, i) => {
$line.attr('y', positions.x2 - padding - lengthLegend);
let index = 1 + i;
$line.attr('y', positions.y2 + positions.v * padding + lineHeight * index + padding * (index + 1));
});
}
$legend.attr('dy', '0.7em');
} else {
if ($legend.data('lines')) {
let index = $legend.data('lines').length;
$legend.attr('y', positions.y2 + positions.v * padding - lineHeight * index - padding * index);
$legend.data('lines').forEach(($line, i) => {
index = $legend.data('lines').length - 1 - i;
$line.attr('y', positions.y2 + positions.v * padding - lineHeight * index - padding * index);
});
}
}
// align background text
$legend.add($legend.data('lines')).each((i, line) => {
let $line = jquery__WEBPACK_IMPORTED_MODULE_1___default()(line),
$background = $line.data('$background');
if ($background) {
$background.attr('x', $line.attr('x'));
$background.attr('y', $line.attr('y'));
$background.css('text-anchor', $line.css('text-anchor'));
$background.attr('dy', $line.attr('dy'));
}
});
// draw lines, if wished
let wires = [];
if (positions.x1 > 0 && positions.y1 > 0) {
wires.push(this._renderLine(positions.x1, positions.y1, positions.x2, positions.y2, 'label-line'));
wires.push(this._renderLine(positions.x2, positions.y2, positions.x2 + positions.h * (lengthLegend + 2 * padding), positions.y2, 'label-line'));
}
$legend.data('wires', wires);
let $svg = this.$svg;
legend.detachFunc = () => {
$legend.data('wires').forEach($wire => {
$wire.detach();
});
if ($legend.data('lines')) {
$legend.data('lines').forEach($line => {
if ($line.data('$background')) {
$svg.append($line.data('$background'));
}
$line.detach();
});
}
if ($legend.data('$background')) {
$legend.data('$background').remove();
}
$legend.detach();
};
legend.attachFunc = () => {
$svg.append($legend);
if ($legend.data('$background')) {
$svg.append($legend.data('$background'));
}
$svg.append($legend.data('wires'));
if ($legend.data('lines')) {
$legend.data('lines').forEach($line => {
$svg.append($line);
if ($line.data('$background')) {
$svg.append($line.data('$background'));
}
});
}
};
legend.removeFunc = () => {
$legend.data('wires').forEach($wire => {
$wire.remove();
});
if ($legend.data('lines')) {
$legend.data('lines').forEach($line => {
if ($line.data('$background')) {
$line.data('$background').remove();
}
$line().remove();
});
}
if ($legend.data('$background')) {
$legend.data('$background').remove();
}
$legend.remove();
};
legend.$field = $legend;
return legend;
}
}
/***/ }),
/***/ "./src/chart/Chart.ts":
/*!****************************!*\
!*** ./src/chart/Chart.ts ***!
\****************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ Chart: () => (/* binding */ Chart),
/* harmony export */ ChartColorMode: () => (/* binding */ ChartColorMode)
/* harmony export */ });
/* harmony import */ var _index__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../index */ "./src/index.ts");
/* harmony import */ var _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @eclipse-scout/core */ "@eclipse-scout/core");
/* harmony import */ var _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_eclipse_scout_core__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! jquery */ "jquery");
/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(jquery__WEBPACK_IMPORTED_MODULE_2__);
/*
* Copyright (c) 2010, 2025 BSI Business Systems Integration AG
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
class Chart extends _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_1__.Widget {
data;
config;
checkedItems;
chartRenderer;
/** @internal */
_updatedOnce;
_updateChartTimeoutId;
_updateChartOpts;
_updateChartOptsWhileNotAttached;
constructor() {
super();
this.$container = null;
this.data = null;
this.config = null;
this.checkedItems = [];
this.chartRenderer = null;
this._updateChartTimeoutId = null;
this._updateChartOpts = null;
this._updateChartOptsWhileNotAttached = [];
this._updatedOnce = false;
}
static Type = {
PIE: 'pie',
LINE: 'line',
BAR: 'bar',
BAR_HORIZONTAL: 'horizontalBar',
COMBO_BAR_LINE: 'comboBarLine',
FULFILLMENT: 'fulfillment',
SPEEDO: 'speedo',
SALESFUNNEL: 'salesfunnel',
VENN: 'venn',
DOUGHNUT: 'doughnut',
POLAR_AREA: 'polarArea',
RADAR: 'radar',
BUBBLE: 'bubble',
SCATTER: 'scatter'
};
static Position = {
TOP: 'top',
BOTTOM: 'bottom',
LEFT: 'left',
RIGHT: 'right',
CENTER: 'center'
};
static DEFAULT_ANIMATION_DURATION = 600; // ms
static DEFAULT_DEBOUNCE_TIMEOUT = 100; // ms
_init(model) {
super._init(model);
this.setConfig(this.config);
this._setData(this.data);
}
_render() {
this.$container = this.$parent.appendDiv('chart');
_eclipse_scout_core__WEBPACK_IMPORTED_MODULE_1__.aria.role(this.$container, 'none'); // ignore this container for screen readers, they care about the chart inside
this.htmlComp = _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_1__.HtmlComponent.install(this.$container, this.session);
this.htmlComp.setLayout(new _index__WEBPACK_IMPORTED_MODULE_0__.ChartLayout(this));
// !!! Do _not_ update the chart here, because usually the container size
// !!! is not correct anyway during the render phase. The ChartLayout
// !!! will eventually call updateChart() when the layout is validated.
}
_renderProperties() {
super._renderProperties();
this._renderClickable();
this._renderCheckable();
this._renderChartType();
this._renderColorScheme();
this.updateChart({
requestAnimation: true,
debounce: Chart.DEFAULT_DEBOUNCE_TIMEOUT
});
}
_renderOnAttach() {
super._renderOnAttach();
const updateChartOptsWhileNotAttached = this._updateChartOptsWhileNotAttached.splice(0);
if (!this.chartRenderer?.isDetachSupported()) {
// the chartRenderer does not support detach => recreate it
this._updateChartRenderer();
updateChartOptsWhileNotAttached.forEach(opts => delete opts.requestAnimation);
updateChartOptsWhileNotAttached.push({
requestAnimation: false
});
}
updateChartOptsWhileNotAttached.forEach(opts => this.updateChart(jquery__WEBPACK_IMPORTED_MODULE_2___default().extend(true, {}, opts, {
debounce: true
})));
}
_remove() {
if (this.chartRenderer) {
this.chartRenderer.remove(false);
}
this.$container.remove();
this.$container = null;
}
setData(data) {
this.setProperty('data', data);
this.setCheckedItems(this.checkedItems);
}
_setData(data) {
if (data) {
data = jquery__WEBPACK_IMPORTED_MODULE_2___default().extend({
axes: []
}, data);
}
this._setProperty('data', data);
}
_renderData() {
this.updateChart({
requestAnimation: true,
debounce: Chart.DEFAULT_DEBOUNCE_TIMEOUT,
onlyUpdateData: true
});
}
setConfig(config) {
let defaultConfig = {
type: Chart.Type.PIE,
options: {
autoColor: true,
colorMode: ChartColorMode.AUTO,
colorScheme: _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_1__.colorSchemes.ColorSchemeId.DEFAULT,
transparent: false,
maxSegments: 5,
adjustGridMaxMin: true,
clickable: false,
checkable: false,
animation: {
duration: Chart.DEFAULT_ANIMATION_DURATION
},
plugins: {
datalabels: {
display: false
},
tooltip: {
enabled: true
},
legend: {
display: true,
clickable: false,
position: Chart.Position.RIGHT,
pointsVisible: true
}
}
}
};
config = jquery__WEBPACK_IMPORTED_MODULE_2___default().extend(true, {}, defaultConfig, config);
config.options.colorScheme = _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_1__.colorSchemes.ensureColorScheme(config.options.colorScheme);
if (_eclipse_scout_core__WEBPACK_IMPORTED_MODULE_1__.objects.equalsRecursive(this.config, config)) {
return;
}
// check if only data has changed
let oldConfigWithNewData = jquery__WEBPACK_IMPORTED_MODULE_2___default().extend(true, {}, this.config);
if (config.data) {
oldConfigWithNewData.data = config.data;
} else {
delete oldConfigWithNewData.data;
}
// the label map is technically part of the config, but it is handled as data. Therefore, it is excluded from this check.
let transferLabelMap = (source, target, identifier) => {
if (!source || !target || !identifier) {
return;
}
// Property not set on source -> remove from target
if (!source.options || !source.options[identifier]) {
if (target.options) {
delete target.options[identifier];
}
if (target.options && _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_1__.objects.isEmpty(target.options.scales) && !(source.options && source.options.scales)) {
delete target.options.scales;
}
if (_eclipse_scout_core__WEBPACK_IMPORTED_MODULE_1__.objects.isEmpty(target.options) && !source.options) {
delete target.options;
}
return;
}
target.options[identifier] = source.options[identifier];
};
transferLabelMap(config, oldConfigWithNewData, 'xLabelMap');
transferLabelMap(config, oldConfigWithNewData, 'yLabelMap');
if (_eclipse_scout_core__WEBPACK_IMPORTED_MODULE_1__.objects.equalsRecursive(oldConfigWithNewData, config)) {
this._setProperty('config', config);
if (this.rendered) {
this._renderConfig(true);
}
this.setCheckedItems(this.checkedItems);
return;
}
if (this.rendered && this.config && this.config.type) {
this.$container.removeClass(this.config.type + '-chart');
}
this.setProperty('config', config);
this.setCheckedItems(this.checkedItems);
this._updateChartRenderer();
}
_renderConfig(onlyUpdateData) {
this._renderClickable();
this._renderCheckable();
this._renderChartType();
this._renderColorScheme();
this.updateChart({
requestAnimation: true,
debounce: Chart.DEFAULT_DEBOUNCE_TIMEOUT,
onlyUpdateData: onlyUpdateData
});
}
setCheckedItems(checkedItems) {
this.setProperty('checkedItems', _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_1__.arrays.ensure(this._filterCheckedItems(checkedItems)));
}
_filterCheckedItems(checkedItems) {
if (!Array.isArray(checkedItems)) {
return checkedItems;
}
let datasetLengths = [];
if (this.data && this.data.chartValueGroups) {
this.data.chartValueGroups.forEach(chartValueGroup => datasetLengths.push(chartValueGroup.values.length));
} else if (this.config && this.config.data) {
this.config.data.datasets.forEach(dataset => datasetLengths.push(dataset.data.length));
}
let filteredCheckedItems = checkedItems.filter(item => datasetLengths[item.datasetIndex] && item.dataIndex < datasetLengths[item.datasetIndex]);
if (filteredCheckedItems.length < checkedItems.length) {
return filteredCheckedItems;
}
return checkedItems;
}
_renderCheckedItems() {
if (this.chartRenderer) {
this.chartRenderer.renderCheckedItems();
}
}
_renderEnabled() {
this.updateChart();
}
_renderClickable() {
this.$container.toggleClass('clickable', this.config.options.clickable);
}
_renderCheckable() {
this.$container.toggleClass('checkable', this.config.options.checkable);
}
_renderChartType() {
this.$container.addClass(this.config.type + '-chart');
}
_renderColorScheme() {
_eclipse_scout_core__WEBPACK_IMPORTED_MODULE_1__.colorSchemes.toggleColorSchemeClasses(this.$container, this.config.options.colorScheme);
}
updateChart(opts) {
opts = opts || {};
opts.onlyUpdateData = opts.onlyUpdateData && this.chartRenderer && this.chartRenderer.isDataUpdatable();
opts.enforceRerender = !opts.onlyUpdateData && !opts.onlyRefresh;
// Cancel previously scheduled update and merge opts
if (this._updateChartTimeoutId) {
clearTimeout(this._updateChartTimeoutId);
if (this._updateChartOpts) {
// Inherit 'true' values from previously scheduled updates
opts.requestAnimation = opts.requestAnimation || this._updateChartOpts.requestAnimation;
opts.onlyUpdateData = opts.onlyUpdateData || this._updateChartOpts.onlyUpdateData;
opts.onlyRefresh = opts.onlyRefresh || this._updateChartOpts.onlyRefresh;
opts.enforceRerender = opts.enforceRerender || this._updateChartOpts.enforceRerender;
}
this._updateChartTimeoutId = null;
this._updateChartOpts = null;
}
let updateChartImplFn = updateChartImpl.bind(this);
let doDebounce = opts.debounce === true || typeof opts.debounce === 'number';
if (doDebounce) {
this._updateChartOpts = opts;
if (typeof opts.debounce === 'number') {
this._updateChartTimeoutId = setTimeout(updateChartImplFn, opts.debounce);
} else {
this._updateChartTimeoutId = setTimeout(updateChartImplFn);
}
} else {
updateChartImplFn();
}
// ---- Helper functions -----
function updateChartImpl() {
this._updateChartTimeoutId = null;
this._updateChartOpts = null;
if (!this.$container || !this.$container.isAttached()) {
this._updateChartOptsWhileNotAttached.push(opts);
return;
}
this._updatedOnce = true;
if (!this.chartRenderer) {
return; // nothing to render when there is no renderer.
}
if (opts.enforceRerender) {
this.chartRenderer.remove(this.chartRenderer.shouldAnimateRemoveOnUpdate(opts), chartAnimationStopping => {
if (this.removing || chartAnimationStopping) {
// prevent exceptions trying to render after navigated away, and do not update/render while a running animation is being stopped
return;
}
this.chartRenderer.render(opts.requestAnimation);
this.trigger('chartRender');
});
} else if (opts.onlyUpdateData) {
this.chartRenderer.updateData(opts.requestAnimation);
} else if (opts.onlyRefresh) {
this.chartRenderer.refresh();
}
}
}
_resolveChartRenderer() {
switch (this.config.type) {
case Chart.Type.FULFILLMENT:
return new _index__WEBPACK_IMPORTED_MODULE_0__.FulfillmentChartRenderer(this);
case Chart.Type.SPEEDO:
return new _index__WEBPACK_IMPORTED_MODULE_0__.SpeedoChartRenderer(this);
case Chart.Type.SALESFUNNEL:
return new _index__WEBPACK_IMPORTED_MODULE_0__.SalesfunnelChartRenderer(this);
case Chart.Type.VENN:
return new _index__WEBPACK_IMPORTED_MODULE_0__.VennChartRenderer(this);
case Chart.Type.BAR:
case Chart.Type.BAR_HORIZONTAL:
case Chart.Type.LINE:
case Chart.Type.COMBO_BAR_LINE:
case Chart.Type.PIE:
case Chart.Type.DOUGHNUT:
case Chart.Type.POLAR_AREA:
case Chart.Type.RADAR:
case Chart.Type.BUBBLE:
case Chart.Type.SCATTER:
return new _index__WEBPACK_IMPORTED_MODULE_0__.ChartJsRenderer(this);
}
return null;
}
_updateChartRenderer() {
this.chartRenderer && this.chartRenderer.remove();
this.setProperty('chartRenderer', this._resolveChartRenderer());
}
handleValueClick(clickedItem, originalEvent) {
if (this.config.options.checkable) {
let checkedItems = [...this.checkedItems],
checkedItem = checkedItems.filter(item => item.datasetIndex === clickedItem.datasetIndex && item.dataIndex === clickedItem.dataIndex)[0];
if (checkedItem) {
_eclipse_scout_core__WEBPACK_IMPORTED_MODULE_1__.arrays.remove(checkedItems, checkedItem);
} else {
checkedItems.push(clickedItem);
}
this.setCheckedItems(checkedItems);
}
this.trigger('valueClick', {
data: clickedItem,
originalEvent
});
}
handleNonValueClick(originalEvent) {
this.trigger('nonValueClick', {
originalEvent
});
}
handleLegendClick(legentItemIndex, originalEvent) {
this.trigger('legendItemClick', {
legendItemIndex: legentItemIndex,
originalEvent: originalEvent
});
}
}
/**
* Determines what parts of the chart data is colored with the same colors.
*/
var ChartColorMode;
(function (ChartColorMode) {
/**
* Uses one of the other options depending on the chart type.
*/
ChartColorMode["AUTO"] = "auto";
/**
* Uses a different color for each dataset.
*/
ChartColorMode["DATASET"] = "dataset";
/**
* Uses a different color for each datapoint in a dataset but the n-th datapoint in each dataset will be colored using the same color.
*/
ChartColorMode["DATA"] = "data";
})(ChartColorMode || (ChartColorMode = {}));
/***/ }),
/***/ "./src/chart/ChartAdapter.ts":
/*!***********************************!*\
!*** ./src/chart/ChartAdapter.ts ***!
\***********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ ChartAdapter: () => (/* binding */ ChartAdapter)
/* harmony export */ });
/* harmony import */ var _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @eclipse-scout/core */ "@eclipse-scout/core");
/* harmony import */ var _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_eclipse_scout_core__WEBPACK_IMPORTED_MODULE_0__);
/*
* Copyright (c) 2010, 2023 BSI Business Systems Integration AG
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
class ChartAdapter extends _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_0__.ModelAdapter {
_onWidgetValueClick(event) {
this._send('valueClick', event.data);
}
_onWidgetEvent(event) {
if (event.type === 'valueClick') {
this._onWidgetValueClick(event);
} else {
super._onWidgetEvent(event);
}
}
}
/***/ }),
/***/ "./src/chart/ChartEventMap.ts":
/*!************************************!*\
!*** ./src/chart/ChartEventMap.ts ***!
\************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/***/ }),
/***/ "./src/chart/ChartJsRenderer.ts":
/*!**************************************!*\
!*** ./src/chart/ChartJsRenderer.ts ***!
\**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ ChartJsRenderer: () => (/* binding */ ChartJsRenderer)
/* harmony export */ });
/* harmony import */ var _index__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../index */ "./src/index.ts");
/* harmony import */ var chart_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! chart.js/auto */ "chart.js");
/* harmony import */ var chart_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(chart_js__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @eclipse-scout/core */ "@eclipse-scout/core");
/* harmony import */ var _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_eclipse_scout_core__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var chartjs_plugin_datalabels__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! chartjs-plugin-datalabels */ "chartjs-plugin-datalabels");
/* harmony import */ var chartjs_plugin_datalabels__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(chartjs_plugin_datalabels__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! jquery */ "jquery");
/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(jquery__WEBPACK_IMPORTED_MODULE_4__);
/*
* Copyright (c) 2010, 2025 BSI Business Systems Integration AG
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
// Import from auto to register charts
chart_js__WEBPACK_IMPORTED_MODULE_1__.Chart.register((chartjs_plugin_datalabels__WEBPACK_IMPORTED_MODULE_3___default()));
jquery__WEBPACK_IMPORTED_MODULE_4___default().extend(true, chart_js__WEBPACK_IMPORTED_MODULE_1__.Chart.defaults, {
maintainAspectRatio: false,
elements: {
line: {
borderWidth: 2
},
point: {
radius: 0,
hitRadius: 10,
hoverRadius: 7,
hoverBorderWidth: 2
},
arc: {
borderWidth: 1
},
bar: {
borderWidth: 1,
borderSkipped: ''
}
},
plugins: {
legend: {
labels: {
usePointStyle: true,
boxHeight: 7
}
}
}
});
jquery__WEBPACK_IMPORTED_MODULE_4___default().extend(true, chart_js__WEBPACK_IMPORTED_MODULE_1__.Chart.overrides, {
line: {
elements: {
point: {
borderWidth: 2
}
}
},
scatter: {
elements: {
point: {
radius: 3
}
}
},
bubble: {
layout: {
// Enabled auto padding would cause Chart.js to automatically add padding, in the size of the largest bubble
// (defined by 'sizeOfLargestBubble'), around the chart. This wastes spaces and is not necessary, as we adjust
// the axes already with the bubble size in mind.
autoPadding: false
}
}
});
let chartJsGlobalsInitialized = false;
const PHI = (1 + Math.sqrt(5)) / 2; // golden ratio
class ChartJsRenderer extends _index__WEBPACK_IMPORTED_MODULE_0__.AbstractChartRenderer {
static ARROW_LEFT_RIGHT = '\u2194';
static ARROW_UP_DOWN = '\u2195';
chartJs;
onlyIntegers;
maxXAxesTicksHeight;
numSupportedColors;
colorSchemeCssClass;
minRadialChartDatalabelSpace;
resetDatasetAfterHover;
legendHoverDatasets;
removing;
$canvas;
_labelFormatter;
_xLabelFormatter;
_yLabelFormatter;
_xAxisFitter;
_yAxisFitter;
_radialChartDatalabelsDisplayHandler;
_radialChartDatalabelsFormatter;
_datalabelsFormatter;
_datalabelBackgroundColorHandler;
_legendLabelGenerator;
_clickHandler;
_hoverHandler;
_pointerHoverHandler;
_legendClickHandler;
_legendHoverHandler;
_legendPointerHoverHandler;
_legendLeaveHandler;
_legendPointerLeaveHandler;
_resizeHandler;
_tooltipTitleGenerator;
_tooltipItemsGenerator;
_tooltipLabelGenerator;
_tooltipLabelValueGenerator;
_tooltipLabelColorGenerator;
_tooltipRenderer;
_tooltip;
_tooltipTimeoutId;
_updatingDatalabels;
_hoveringClickableElement;
constructor(chart) {
super(chart);
this.chartJs = null;
this.onlyIntegers = true;
this.maxXAxesTicksHeight = 75;
this.numSupportedColors = 6;
this.colorSchemeCssClass = '';
this.minRadialChartDatalabelSpace = 25;
this._labelFormatter = this._createLabelFormatter(this._formatLabel);
this._xLabelFormatter = this._createLabelFormatter(this._formatXLabel);
this._yLabelFormatter = this._createLabelFormatter(this._formatYLabel);
this._xAxisFitter = this._fitXAxis.bind(this);
this._yAxisFitter = this._fitYAxis.bind(this);
this._radialChartDatalabelsDisplayHandler = this._displayDatalabelsOnRadialChart.bind(this);
this._radialChartDatalabelsFormatter = this._formatDatalabelsOnRadialChart.bind(this);
this._datalabelsFormatter = this._formatDatalabels.bind(this);
this._datalabelBackgroundColorHandler = this._getBackgroundColorOfDataset.bind(this);
this._legendLabelGenerator = this._generateLegendLabels.bind(this);
this.resetDatasetAfterHover = false;
this._clickHandler = this._onClick.bind(this);
this._hoverHandler = this._onHover.bind(this);
this._pointerHoverHandler = this._onHoverPointer.bind(this);
this.legendHoverDatasets = [];
this._legendClickHandler = this._onLegendClick.bind(this);
this._legendHoverHandler = this._onLegendHover.bind(this);
this._legendPointerHoverHandler = this._onLegendHoverPointer.bind(this);
this._legendLeaveHandler = this._onLegendLeave.bind(this);
this._legendPointerLeaveHandler = this._onLegendLeavePointer.bind(this);
this._resizeHandler = this._onResize.bind(this);
this._tooltipTitleGenerator = this._generateTooltipTitle.bind(this);
this._tooltipItemsGenerator = this._generateTooltipItems.bind(this);
this._tooltipLabelGenerator = this._generateTooltipLabel.bind(this);
this._tooltipLabelValueGenerator = this._generateTooltipLabelValue.bind(this);
this._tooltipLabelColorGenerator = this._generateTooltipLabelColor.bind(this);
this._tooltipRenderer = this._renderTooltip.bind(this);
this._tooltip = null;
this._tooltipTimeoutId = null;
}
_validateChartData() {
let chartDataValid = true;
let chartData = this.chart && this.chart.data;
if (!chartData || !chartData.chartValueGroups || chartData.chartValueGroups.length === 0 || !chartData.axes) {
chartDataValid = false;
}
if (chartDataValid && _eclipse_scout_core__WEBPACK_IMPORTED_MODULE_2__.scout.isOneOf(this.chart.config.type, _index__WEBPACK_IMPORTED_MODULE_0__.Chart.Type.POLAR_AREA, _index__WEBPACK_IMPORTED_MODULE_0__.Chart.Type.RADAR)) {
// check lengths
let i,
length = 0;
for (i = 0; i < chartData.chartValueGroups.length; i++) {
let chartValueGroup = chartData.chartValueGroups[i];
if (!chartValueGroup.values) {
chartDataValid = false;
}
// Length of all "values" arrays have to be equal
if (i === 0) {
length = chartValueGroup.values.length;
} else {
if (chartValueGroup.values.length !== length) {
chartDataValid = false;
}
}
}
for (i = 0; i < chartData.axes.length; i++) {
if (chartData.axes[i].length !== length) {
chartDataValid = false;
}
}
}
if (chartDataValid) {
return true;
}
let chartConfigDataValid = true;
let config = this.chart && this.chart.config;
if (!config || !config.data || !config.data.datasets || c