@eclipse-scout/chart 23.1.12 → 23.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/file-list CHANGED
@@ -1,13 +1,13 @@
1
- eclipse-scout-chart-dee874ed46aaa3d247de.min.js
2
- eclipse-scout-chart-dee874ed46aaa3d247de.min.js.map
1
+ eclipse-scout-chart-c0371fbf62b6717784f4.min.js
2
+ eclipse-scout-chart-c0371fbf62b6717784f4.min.js.map
3
3
  eclipse-scout-chart-theme-56ba6667e592ef147869.min.css
4
4
  eclipse-scout-chart-theme-dark-593955eea95984c5aa62.min.css
5
5
  eclipse-scout-chart-theme-dark.css
6
6
  eclipse-scout-chart-theme-dark.css.map
7
7
  eclipse-scout-chart-theme.css
8
8
  eclipse-scout-chart-theme.css.map
9
- eclipse-scout-chart.esm-558d382efe651ca2215b.min.js
10
- eclipse-scout-chart.esm-558d382efe651ca2215b.min.js.map
9
+ eclipse-scout-chart.esm-a918cb3af9403c83adfe.min.js
10
+ eclipse-scout-chart.esm-a918cb3af9403c83adfe.min.js.map
11
11
  eclipse-scout-chart.esm.js
12
12
  eclipse-scout-chart.esm.js.map
13
13
  eclipse-scout-chart.js
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eclipse-scout/chart",
3
- "version": "23.1.12",
3
+ "version": "23.1.15",
4
4
  "description": "Eclipse Scout chart",
5
5
  "author": "BSI Business Systems Integration AG",
6
6
  "homepage": "https://www.eclipse.org/scout",
@@ -26,7 +26,7 @@
26
26
  "src"
27
27
  ],
28
28
  "devDependencies": {
29
- "@eclipse-scout/cli": "23.1.12",
29
+ "@eclipse-scout/cli": "23.1.15",
30
30
  "@eclipse-scout/releng": "^22.0.0",
31
31
  "jasmine-core": "4.5.0",
32
32
  "jasmine-jquery": "2.1.1",
@@ -36,7 +36,7 @@
36
36
  "@types/jasmine-jquery": "1.5.34"
37
37
  },
38
38
  "dependencies": {
39
- "@eclipse-scout/core": "23.1.12",
39
+ "@eclipse-scout/core": "23.1.15",
40
40
  "jquery": "3.6.0",
41
41
  "chart.js": "3.9.1",
42
42
  "chartjs-plugin-datalabels": "2.1.0"
@@ -7,13 +7,14 @@
7
7
  *
8
8
  * SPDX-License-Identifier: EPL-2.0
9
9
  */
10
- import {AbstractChartRenderer, Chart} from '../index';
10
+ import {AbstractChartRenderer, Chart, chartJsDateAdapter} from '../index';
11
11
  import {
12
- ActiveElement, ArcElement, BarElement, BubbleDataPoint, CartesianScaleOptions, Chart as ChartJs, ChartArea, ChartConfiguration, ChartDataset, ChartEvent, ChartType as ChartJsType, Color, DefaultDataPoint, FontSpec, LegendElement,
12
+ _adapters as chartJsAdapters, ActiveElement, ArcElement, BarElement, BubbleDataPoint, CartesianScaleOptions, Chart as ChartJs, ChartArea, ChartConfiguration, ChartDataset, ChartEvent, ChartType as ChartJsType, Color, DefaultDataPoint,
13
+ FontSpec, LegendElement,
13
14
  LegendItem, LegendOptions, LinearScaleOptions, PointElement, PointHoverOptions, PointOptions, PointProps, RadialLinearScaleOptions, Scale, ScatterDataPoint, TooltipCallbacks, TooltipItem, TooltipLabelStyle, TooltipModel, TooltipOptions
14
15
  } from 'chart.js';
15
16
  import 'chart.js/auto'; // Import from auto to register charts
16
- import {arrays, colorSchemes, graphics, numbers, objects, scout, strings, styles, Tooltip, tooltips} from '@eclipse-scout/core';
17
+ import {arrays, colorSchemes, graphics, numbers, objects, Point, scout, strings, styles, Tooltip, tooltips} from '@eclipse-scout/core';
17
18
  import ChartDataLabels, {Context} from 'chartjs-plugin-datalabels';
18
19
  import $ from 'jquery';
19
20
  import {ChartAxis, ChartConfig, ChartData, ChartType, ClickObject, NumberFormatter} from './Chart';
@@ -235,6 +236,7 @@ export class ChartJsRenderer extends AbstractChartRenderer {
235
236
  this.firstOpaqueBackgroundColor = styles.getFirstOpaqueBackgroundColor(this.$canvas);
236
237
  if (!chartJsGlobalsInitialized) {
237
238
  ChartJs.defaults.font.family = this.$canvas.css('font-family');
239
+ chartJsAdapters._date.override(chartJsDateAdapter.getAdapter(this.chart.session));
238
240
  chartJsGlobalsInitialized = true;
239
241
  }
240
242
  let config = $.extend(true, {}, this.chart.config);
@@ -962,6 +964,10 @@ export class ChartJsRenderer extends AbstractChartRenderer {
962
964
  if (isTooltipShowing) {
963
965
  this._renderTooltipLater(context);
964
966
  } else {
967
+ // clear timeout before creating a new handler.
968
+ // Otherwise, changing the context within the tooltip delay time creates a second handler
969
+ // and the first one will always be executed, since the tooltipTimoutId reference to it is lost
970
+ clearTimeout(this._tooltipTimeoutId);
965
971
  this._tooltipTimeoutId = setTimeout(() => this._renderTooltipLater(context), tooltips.DEFAULT_TOOLTIP_DELAY);
966
972
  }
967
973
  }
@@ -1001,11 +1007,8 @@ export class ChartJsRenderer extends AbstractChartRenderer {
1001
1007
  tooltipText += arrays.ensure(tooltipItems(dataPoints, tooltipLabel, tooltipLabelValue, tooltipColor)).join('');
1002
1008
  }
1003
1009
 
1004
- let positionAndOffset = this._computeTooltipPositionAndOffset(firstDataPoint),
1005
- origin = graphics.offsetBounds(this.$canvas);
1006
- origin.x += tooltip.caretX + positionAndOffset.offsetX;
1007
- origin.y += tooltip.caretY + positionAndOffset.offsetY;
1008
- origin.height = positionAndOffset.height;
1010
+ let positionAndOffset = this._computeTooltipPositionAndOffset(firstDataPoint);
1011
+ let offset = new Point(tooltip.caretX + positionAndOffset.offsetX, tooltip.caretY + positionAndOffset.offsetY);
1009
1012
 
1010
1013
  this._tooltip = scout.create({
1011
1014
  objectType: Tooltip,
@@ -1016,7 +1019,12 @@ export class ChartJsRenderer extends AbstractChartRenderer {
1016
1019
  cssClass: strings.join(' ', 'chart-tooltip', tooltipOptions.cssClass),
1017
1020
  tooltipPosition: positionAndOffset.tooltipPosition,
1018
1021
  tooltipDirection: positionAndOffset.tooltipDirection,
1019
- origin: origin
1022
+ originProducer: $anchor => {
1023
+ const origin = graphics.offsetBounds($anchor);
1024
+ origin.height = positionAndOffset.height;
1025
+ return origin;
1026
+ },
1027
+ offsetProducer: origin => offset
1020
1028
  });
1021
1029
  this._tooltip.render();
1022
1030
 
@@ -1428,7 +1436,7 @@ export class ChartJsRenderer extends AbstractChartRenderer {
1428
1436
  return labelMap[label];
1429
1437
  }
1430
1438
  // @ts-expect-error
1431
- if (isNaN(label)) {
1439
+ if (isNaN(label) || typeof label === 'string') {
1432
1440
  return '' + label;
1433
1441
  }
1434
1442
  if (numberFormatter) {
@@ -0,0 +1,188 @@
1
+ /*
2
+ * Copyright (c) 2010-2023 BSI Business Systems Integration AG.
3
+ * All rights reserved. This program and the accompanying materials
4
+ * are made available under the terms of the Eclipse Public License v1.0
5
+ * which accompanies this distribution, and is available at
6
+ * https://www.eclipse.org/legal/epl-v10.html
7
+ *
8
+ * Contributors:
9
+ * BSI Business Systems Integration AG - initial API and implementation
10
+ */
11
+ import {DateAdapter, TimeUnit} from 'chart.js';
12
+ import {DateFormat, dates, Locale, objects, Session, strings} from '@eclipse-scout/core';
13
+
14
+ export const chartJsDateAdapter = {
15
+ getAdapter(session: Session): Partial<DateAdapter> {
16
+ return {
17
+ formats: (): { [key: string]: string } => _getFormats(session.locale),
18
+
19
+ parse: (value: unknown, format?: TimeUnit): number | null => {
20
+ if (objects.isNullOrUndefined(value)) {
21
+ return null;
22
+ }
23
+ if (value instanceof Date) {
24
+ return value.getTime();
25
+ }
26
+ if (objects.isString(value)) {
27
+ if (objects.isString(format) && strings.hasText(format)) {
28
+ let dateFormat = new DateFormat(session.locale, format);
29
+ value = dateFormat.parse(value);
30
+ return value instanceof Date ? value.getTime() : null;
31
+ }
32
+ value = dates.parseJsonDate(value);
33
+ return value instanceof Date ? value.getTime() : null;
34
+ }
35
+ return null;
36
+ },
37
+
38
+ format: (timestamp: number, format: TimeUnit): string => {
39
+ if (format === 'quarter') {
40
+ // Quarters are not supported by DateFormat, but Chart.js anyway never uses this time unit for formatting by default, because it is not very common.
41
+ // See the function "determineUnitForFormatting" in scale.time.js for more details. Therefore, we refrain from supporting this here.
42
+ throw new Error('The time unit "quarter" is not supported for formatting.');
43
+ }
44
+ return dates.format(new Date(timestamp), session.locale, format);
45
+ },
46
+
47
+ add: (timestamp: number, amount: number, unit: TimeUnit): number => {
48
+ let date = new Date(timestamp);
49
+ switch (unit) {
50
+ case 'millisecond':
51
+ return dates.shiftTime(date, 0, 0, 0, amount).getTime();
52
+ case 'second':
53
+ return dates.shiftTime(date, 0, 0, amount, 0).getTime();
54
+ case 'minute':
55
+ return dates.shiftTime(date, 0, amount, 0, 0).getTime();
56
+ case 'hour':
57
+ return dates.shiftTime(date, amount, 0, 0, 0).getTime();
58
+ case 'day':
59
+ return dates.shift(date, 0, 0, amount).getTime();
60
+ case 'week':
61
+ return dates.shift(date, 0, 0, amount * 7).getTime();
62
+ case 'month':
63
+ return dates.shift(date, 0, amount, 0).getTime();
64
+ case 'quarter':
65
+ return dates.shift(date, 0, amount * 3, 0).getTime();
66
+ case 'year':
67
+ return dates.shift(date, amount, 0, 0).getTime();
68
+ default:
69
+ return timestamp;
70
+ }
71
+ },
72
+
73
+ diff: (a: number, b: number, unit: TimeUnit): number => {
74
+ switch (unit) {
75
+ case 'millisecond':
76
+ return a - b;
77
+ case 'second':
78
+ return (a - b) / 1000;
79
+ case 'minute':
80
+ return (a - b) / 1000 / 60;
81
+ case 'hour':
82
+ return (a - b) / 1000 / 60 / 60;
83
+ case 'day':
84
+ return dates.compareDays(new Date(a), new Date(b));
85
+ case 'week':
86
+ return dates.compareDays(new Date(a), new Date(b)) / 7;
87
+ case 'month':
88
+ return dates.compareMonths(new Date(a), new Date(b));
89
+ case 'quarter':
90
+ return dates.compareMonths(new Date(a), new Date(b)) / 3;
91
+ case 'year':
92
+ return new Date(a).getFullYear() - new Date(b).getFullYear();
93
+ default:
94
+ return 0;
95
+ }
96
+ },
97
+
98
+ startOf: (timestamp: number, unit: TimeUnit | 'isoWeek', weekday?: number): number => {
99
+ let date = new Date(timestamp);
100
+ switch (unit) {
101
+ case 'second':
102
+ return date.setMilliseconds(0);
103
+ case 'minute':
104
+ return date.setSeconds(0, 0);
105
+ case 'hour':
106
+ return date.setMinutes(0, 0, 0);
107
+ case 'day':
108
+ return date.setHours(0, 0, 0, 0);
109
+ case 'week':
110
+ return dates.firstDayOfWeek(date, 0).getTime();
111
+ case 'isoWeek':
112
+ return dates.firstDayOfWeek(date, weekday).getTime();
113
+ case 'month':
114
+ return dates.trunc(date).setDate(0);
115
+ case 'quarter':
116
+ return dates.trunc(date).setMonth(date.getMonth() % 4, 1);
117
+ case 'year':
118
+ return dates.trunc(date).setMonth(0, 1);
119
+ default:
120
+ return timestamp;
121
+ }
122
+ },
123
+
124
+ endOf: (timestamp: number, unit: TimeUnit | 'isoWeek'): number => {
125
+ let date = new Date(timestamp);
126
+ switch (unit) {
127
+ case 'second':
128
+ return date.setMilliseconds(999);
129
+ case 'minute':
130
+ return date.setSeconds(59, 999);
131
+ case 'hour':
132
+ return date.setMinutes(59, 59, 999);
133
+ case 'day':
134
+ return date.setHours(23, 59, 59, 999);
135
+ case 'week': {
136
+ date.setHours(23, 59, 59, 999);
137
+ let firstDayOfWeek = dates.firstDayOfWeek(date, 0);
138
+ return firstDayOfWeek.setDate(firstDayOfWeek.getDate() + 7);
139
+ }
140
+ case 'month': {
141
+ date.setHours(23, 59, 59, 999);
142
+ return date.setDate(_getNumberOfDays(date.getMonth(), date.getFullYear()));
143
+ }
144
+ case 'quarter': {
145
+ date.setHours(23, 59, 59, 999);
146
+ let endOfQuarterMonth = date.getMonth() % 4 + 2;
147
+ return date.setMonth(endOfQuarterMonth, _getNumberOfDays(endOfQuarterMonth, date.getFullYear()));
148
+ }
149
+ case 'year': {
150
+ date.setHours(23, 59, 59, 999);
151
+ return date.setMonth(11, 31);
152
+ }
153
+ default:
154
+ return timestamp;
155
+ }
156
+ }
157
+ };
158
+ }
159
+ };
160
+
161
+ function _getFormats(locale: Locale) {
162
+ return {
163
+ datetime: locale.dateFormatPatternDefault + ' ' + locale.timeFormatPatternDefault,
164
+ millisecond: 'HH:mm:ss.SSS',
165
+ second: 'HH:mm:ss',
166
+ minute: locale.timeFormatPatternDefault,
167
+ hour: locale.timeFormatPatternDefault,
168
+ day: locale.dateFormatPatternDefault,
169
+ week: 'ww',
170
+ month: 'MMM yyyy',
171
+ quarter: 'qqq - yyyy',
172
+ year: 'yyyy'
173
+ };
174
+ }
175
+
176
+ /**
177
+ * @param month 0 = january, 11 = december
178
+ * @returns the number of days in the given month and year.
179
+ */
180
+ function _getNumberOfDays(month: number, year: number): number {
181
+ if (month in [3, 5, 8, 10]) { // april, june, september, november
182
+ return 30;
183
+ } else if (month === 1) { // february
184
+ return dates.isLeapYear(year) ? 29 : 28;
185
+ }
186
+ // january, march, may, july, august, october, december
187
+ return 31;
188
+ }
package/src/index.ts CHANGED
@@ -16,6 +16,7 @@ export * from './chart/ChartLayout';
16
16
  export * from './chart/ChartModel';
17
17
  export * from './chart/AbstractChartRenderer';
18
18
  export * from './chart/AbstractSvgChartRenderer';
19
+ export * from './chart/chartJsDateAdapter';
19
20
  export * from './chart/ChartJsRenderer';
20
21
  export * from './chart/FulfillmentChartRenderer';
21
22
  export * from './chart/SpeedoChartRenderer';