evui 3.4.207 → 3.4.209

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.
Files changed (162) hide show
  1. package/README.md +18 -33
  2. package/dist/404.html +44 -0
  3. package/dist/favicon.ico +0 -0
  4. package/dist/index.js +22738 -0
  5. package/dist/index.umd.cjs +28 -0
  6. package/dist/style.css +1 -0
  7. package/package.json +46 -43
  8. package/dist/evui.common.js +0 -63681
  9. package/dist/evui.common.js.map +0 -1
  10. package/dist/evui.umd.js +0 -63691
  11. package/dist/evui.umd.js.map +0 -1
  12. package/dist/evui.umd.min.js +0 -2
  13. package/dist/evui.umd.min.js.map +0 -1
  14. package/dist/img/EVUI.b82ee81a.svg +0 -293
  15. package/src/assets/logo.png +0 -0
  16. package/src/common/emitter.js +0 -20
  17. package/src/common/utils.bignumber.js +0 -67
  18. package/src/common/utils.debounce.js +0 -223
  19. package/src/common/utils.js +0 -151
  20. package/src/common/utils.table.js +0 -78
  21. package/src/common/utils.throttle.js +0 -83
  22. package/src/common/utils.tree.js +0 -18
  23. package/src/components/button/Button.vue +0 -195
  24. package/src/components/button/index.js +0 -7
  25. package/src/components/buttonGroup/ButtonGroup.vue +0 -11
  26. package/src/components/buttonGroup/index.js +0 -7
  27. package/src/components/calendar/Calendar.vue +0 -725
  28. package/src/components/calendar/index.js +0 -7
  29. package/src/components/calendar/uses.js +0 -1410
  30. package/src/components/chart/Chart.vue +0 -363
  31. package/src/components/chart/ChartToolbar.vue +0 -52
  32. package/src/components/chart/chart.core.js +0 -1170
  33. package/src/components/chart/chartZoom.core.js +0 -540
  34. package/src/components/chart/element/element.bar.js +0 -672
  35. package/src/components/chart/element/element.bar.time.js +0 -166
  36. package/src/components/chart/element/element.heatmap.js +0 -743
  37. package/src/components/chart/element/element.line.js +0 -611
  38. package/src/components/chart/element/element.pie.js +0 -197
  39. package/src/components/chart/element/element.scatter.js +0 -320
  40. package/src/components/chart/element/element.tip.js +0 -717
  41. package/src/components/chart/helpers/helpers.canvas.js +0 -265
  42. package/src/components/chart/helpers/helpers.constant.js +0 -235
  43. package/src/components/chart/helpers/helpers.util.js +0 -400
  44. package/src/components/chart/index.js +0 -9
  45. package/src/components/chart/model/index.js +0 -50
  46. package/src/components/chart/model/model.series.js +0 -125
  47. package/src/components/chart/model/model.store.js +0 -1427
  48. package/src/components/chart/plugins/plugins.interaction.js +0 -1659
  49. package/src/components/chart/plugins/plugins.legend.gradient.js +0 -606
  50. package/src/components/chart/plugins/plugins.legend.js +0 -1543
  51. package/src/components/chart/plugins/plugins.pie.js +0 -254
  52. package/src/components/chart/plugins/plugins.scrollbar.js +0 -732
  53. package/src/components/chart/plugins/plugins.title.js +0 -61
  54. package/src/components/chart/plugins/plugins.tooltip.js +0 -1041
  55. package/src/components/chart/scale/scale.js +0 -951
  56. package/src/components/chart/scale/scale.linear.js +0 -268
  57. package/src/components/chart/scale/scale.logarithmic.js +0 -135
  58. package/src/components/chart/scale/scale.step.js +0 -430
  59. package/src/components/chart/scale/scale.time.category.js +0 -338
  60. package/src/components/chart/scale/scale.time.js +0 -49
  61. package/src/components/chart/style/chart.scss +0 -405
  62. package/src/components/chart/uses.js +0 -721
  63. package/src/components/chartBrush/ChartBrush.vue +0 -323
  64. package/src/components/chartBrush/chartBrush.core.js +0 -691
  65. package/src/components/chartBrush/index.js +0 -9
  66. package/src/components/chartBrush/uses.js +0 -23
  67. package/src/components/chartGroup/ChartGroup.vue +0 -144
  68. package/src/components/chartGroup/index.js +0 -9
  69. package/src/components/chartGroup/style/chartGroup.scss +0 -5
  70. package/src/components/chartGroup/uses.js +0 -53
  71. package/src/components/checkbox/Checkbox.vue +0 -229
  72. package/src/components/checkbox/index.js +0 -7
  73. package/src/components/checkboxGroup/CheckboxGroup.vue +0 -44
  74. package/src/components/checkboxGroup/index.js +0 -7
  75. package/src/components/contextMenu/ContextMenu.vue +0 -95
  76. package/src/components/contextMenu/MenuList.vue +0 -182
  77. package/src/components/contextMenu/index.js +0 -7
  78. package/src/components/contextMenu/uses.js +0 -223
  79. package/src/components/datePicker/DatePicker.vue +0 -504
  80. package/src/components/datePicker/index.js +0 -7
  81. package/src/components/datePicker/uses.js +0 -460
  82. package/src/components/grid/Grid.vue +0 -1535
  83. package/src/components/grid/GridColumnSetting.vue +0 -358
  84. package/src/components/grid/GridFilterSetting.vue +0 -323
  85. package/src/components/grid/GridPagination.vue +0 -75
  86. package/src/components/grid/GridSummary.vue +0 -314
  87. package/src/components/grid/GridToolbar.vue +0 -35
  88. package/src/components/grid/icon/icon-option-button.vue +0 -17
  89. package/src/components/grid/icon/icon-sort-button.vue +0 -67
  90. package/src/components/grid/index.js +0 -11
  91. package/src/components/grid/style/grid.scss +0 -417
  92. package/src/components/grid/uses.js +0 -1629
  93. package/src/components/icon/Icon.vue +0 -53
  94. package/src/components/icon/index.js +0 -8
  95. package/src/components/inputNumber/InputNumber.vue +0 -212
  96. package/src/components/inputNumber/index.js +0 -7
  97. package/src/components/inputNumber/uses.js +0 -217
  98. package/src/components/loading/Loading.vue +0 -125
  99. package/src/components/loading/index.js +0 -7
  100. package/src/components/menu/Menu.vue +0 -79
  101. package/src/components/menu/MenuItem.vue +0 -201
  102. package/src/components/menu/index.js +0 -7
  103. package/src/components/message/Message.vue +0 -229
  104. package/src/components/message/index.js +0 -34
  105. package/src/components/messageBox/MessageBox.vue +0 -358
  106. package/src/components/messageBox/index.js +0 -22
  107. package/src/components/notification/Notification.vue +0 -316
  108. package/src/components/notification/index.js +0 -49
  109. package/src/components/pagination/Pagination.vue +0 -317
  110. package/src/components/pagination/index.js +0 -7
  111. package/src/components/pagination/pageButton.vue +0 -31
  112. package/src/components/progress/Progress.vue +0 -139
  113. package/src/components/progress/index.js +0 -7
  114. package/src/components/radio/Radio.vue +0 -159
  115. package/src/components/radio/index.js +0 -7
  116. package/src/components/radioGroup/RadioGroup.vue +0 -41
  117. package/src/components/radioGroup/index.js +0 -7
  118. package/src/components/scheduler/Scheduler.vue +0 -149
  119. package/src/components/scheduler/index.js +0 -7
  120. package/src/components/scheduler/uses.js +0 -183
  121. package/src/components/select/Select.vue +0 -556
  122. package/src/components/select/index.js +0 -7
  123. package/src/components/select/uses.js +0 -379
  124. package/src/components/slider/Slider.vue +0 -505
  125. package/src/components/slider/index.js +0 -7
  126. package/src/components/slider/uses.js +0 -391
  127. package/src/components/tabPanel/TabPanel.vue +0 -74
  128. package/src/components/tabPanel/index.js +0 -7
  129. package/src/components/tabs/Tabs.vue +0 -517
  130. package/src/components/tabs/index.js +0 -7
  131. package/src/components/textField/TextField.vue +0 -399
  132. package/src/components/textField/index.js +0 -7
  133. package/src/components/timePicker/TimePicker.vue +0 -364
  134. package/src/components/timePicker/index.js +0 -7
  135. package/src/components/toggle/Toggle.vue +0 -115
  136. package/src/components/toggle/index.js +0 -7
  137. package/src/components/tree/Tree.vue +0 -338
  138. package/src/components/tree/TreeNode.vue +0 -293
  139. package/src/components/tree/index.js +0 -7
  140. package/src/components/treeGrid/TreeGrid.vue +0 -1074
  141. package/src/components/treeGrid/TreeGridNode.vue +0 -349
  142. package/src/components/treeGrid/TreeGridToolbar.vue +0 -35
  143. package/src/components/treeGrid/icon/icon-tree.png +0 -0
  144. package/src/components/treeGrid/index.js +0 -9
  145. package/src/components/treeGrid/style/treeGrid.scss +0 -277
  146. package/src/components/treeGrid/uses.js +0 -1178
  147. package/src/components/window/Window.vue +0 -329
  148. package/src/components/window/index.js +0 -7
  149. package/src/components/window/uses.js +0 -908
  150. package/src/directives/clickoutside.js +0 -90
  151. package/src/main.js +0 -120
  152. package/src/style/components/input.scss +0 -108
  153. package/src/style/functions.scss +0 -3
  154. package/src/style/index.scss +0 -6
  155. package/src/style/lib/fonts/EVUI.eot +0 -0
  156. package/src/style/lib/fonts/EVUI.svg +0 -293
  157. package/src/style/lib/fonts/EVUI.ttf +0 -0
  158. package/src/style/lib/fonts/EVUI.woff +0 -0
  159. package/src/style/lib/icon.css +0 -888
  160. package/src/style/mixins.scss +0 -94
  161. package/src/style/themes.scss +0 -69
  162. package/src/style/variables.scss +0 -22
@@ -1,1543 +0,0 @@
1
- import Util from '../helpers/helpers.util';
2
-
3
- const modules = {
4
- /**
5
- * Create legend DOM
6
- *
7
- * @returns {undefined}
8
- */
9
- createLegendLayout() {
10
- this.legendDOM = document.createElement('div');
11
- this.legendDOM.className = 'ev-chart-legend';
12
- this.legendBoxDOM = document.createElement('div');
13
- this.legendBoxDOM.className = 'ev-chart-legend-box';
14
-
15
- if (this.options?.legend?.allowResize) {
16
- this.resizeDOM = document.createElement('div');
17
- this.resizeDOM.className = 'ev-chart-resize-bar';
18
- this.ghostDOM = document.createElement('div');
19
- this.ghostDOM.className = 'ev-chart-resize-ghost';
20
- this.wrapperDOM.appendChild(this.resizeDOM);
21
- }
22
-
23
- if (this.useTable) {
24
- this.legendTableDOM = document.createElement('table');
25
- this.legendTableDOM.className = 'ev-chart-legend--table';
26
- this.setLegendColumnHeader();
27
- this.legendBoxDOM.appendChild(this.legendTableDOM);
28
- this.legendDOM.style.overflow = 'auto';
29
- } else {
30
- this.legendBoxDOM.style.overflowX = 'hidden';
31
- this.legendBoxDOM.style.overflowY = 'auto';
32
- this.legendBoxDOM.style.height = '100%';
33
- }
34
-
35
- this.legendDOM.appendChild(this.legendBoxDOM);
36
- this.wrapperDOM.appendChild(this.legendDOM);
37
-
38
-
39
- if (this.options.legend.virtualScroll && !this.useTable) {
40
- this.legendTopSpacer = document.createElement('div');
41
- this.legendTopSpacer.className = 'ev-chart-legend--top-spacer';
42
- this.legendTopSpacer.style.clear = 'both';
43
- this.legendTopSpacer.style.opacity = 0;
44
-
45
- this.legendBottomSpacer = document.createElement('div');
46
- this.legendBottomSpacer.className = 'ev-chart-legend--bottom-spacer';
47
- this.legendBottomSpacer.style.clear = 'both';
48
- this.legendBottomSpacer.style.opacity = 0;
49
-
50
- this.legendBoxDOM.appendChild(this.legendTopSpacer);
51
- this.legendBoxDOM.appendChild(this.legendBottomSpacer);
52
- this.updateVisibleRowCountFrameId = requestAnimationFrame(() => {
53
- this.updateVisibleRowCount();
54
- });
55
- }
56
- },
57
-
58
- /**
59
- * Create and append Table Header DOM
60
- * Only chartOption > legend > table > use : true
61
- *
62
- * @returns {undefined}
63
- */
64
- setLegendColumnHeader() {
65
- const tableOpt = this.options.legend?.table;
66
- const columns = tableOpt.columns;
67
- const columnKeyList = ['color', ...Object.keys(columns)];
68
-
69
- columnKeyList.forEach((key) => {
70
- const columnNameDOM = document.createElement('th');
71
- columnNameDOM.className = 'ev-chart-legend--table__column-name';
72
-
73
- if (columns[key]?.use || key === 'color' || key === 'name') {
74
- const columnOpt = columns[key];
75
- const keyText = columnOpt?.title ?? '';
76
-
77
- columnNameDOM.textContent = keyText;
78
- columnNameDOM.setAttribute('title', keyText);
79
- columnNameDOM.dataset.type = keyText;
80
-
81
- Util.setDOMStyle(columnNameDOM, tableOpt?.style?.header);
82
-
83
- this.legendTableDOM.append(columnNameDOM);
84
- }
85
- });
86
- },
87
-
88
- /**
89
- * Initialize legend
90
- * If there was no initialization, create DOM and set default layout.
91
- * It not, there will already be set layout, so add a legend for each series with group
92
- *
93
- * @returns {undefined}
94
- */
95
- initLegend() {
96
- this.isHeatMapType = this.options.type === 'heatMap';
97
- this.useTable = !!this.options.legend?.table?.use && this.options.type !== 'heatmap' && this.options.type !== 'scatter';
98
- this.legendItemHeight = 18;
99
-
100
- if (!this.isInitLegend) {
101
- this.createLegendLayout();
102
- }
103
-
104
- if (this.isHeatMapType) {
105
- this.initEventForColorLegend();
106
- this.addColorLegendList();
107
- } else {
108
- this.initEvent();
109
- this.addLegendList();
110
- }
111
-
112
- this.initResizeEvent();
113
-
114
- this.isInitLegend = true;
115
- this.isLegendMove = false;
116
- },
117
-
118
- /**
119
- * Calculate and update the number of rows and items per row that are visible
120
- * within the legend container based on its dimensions and the layout of the legend.
121
- * If the legend is positioned on the right or left, only one item per row is shown.
122
- * Otherwise, the number of items per row is determined by dividing the container width
123
- * by the item width.
124
- *
125
- * @returns {undefined}
126
- */
127
- updateVisibleRowCount() {
128
- const isLeftOrRight = this.options.legend.position === 'right' || this.options.legend.position === 'left';
129
- const legendBoxHeight = this.legendBoxDOM.clientHeight;
130
- const legendBoxWidth = this.legendBoxDOM.clientWidth;
131
-
132
- const itemWidth = Math.max(this.options.legend.width - 8, 1);
133
- const useLegendSeriesCount = Object.values(this.seriesList)
134
- .filter(series => series.showLegend !== false)
135
- .length;
136
-
137
- this.itemsPerRow = isLeftOrRight ? 1 : Math.floor(legendBoxWidth / itemWidth);
138
- this.totalRowCount = Math.ceil(useLegendSeriesCount / this.itemsPerRow);
139
- this.visibleRowCount = legendBoxHeight > this.legendItemHeight
140
- ? Math.round(legendBoxHeight / this.legendItemHeight) + 1 : this.totalRowCount;
141
- },
142
-
143
- /**
144
- * Calculate and set the start and end row indexes for visible items within the
145
- * scrollable legend area. Determines the row range that should be displayed based
146
- * on the current scroll position and the height of each legend item.
147
- *
148
- * @returns {undefined}
149
- */
150
- updateStartEndRowIndex() {
151
- const index = Math.max(Math.floor(this.legendBoxDOM?.scrollTop / this.legendItemHeight), 0);
152
- this.startRowIndex = Math.min(index, Math.max(this.totalRowCount - this.visibleRowCount, 0));
153
- this.endRowIndex = this.startRowIndex + this.visibleRowCount + 1;
154
- },
155
-
156
- /**
157
- * Render only the visible legend items in the legend container based on the
158
- * calculated start and end row indexes. Removes existing legend items,
159
- * adjusts spacer heights to enable smooth scrolling, and adds only the items
160
- * within the visible range.
161
- *
162
- * @returns {undefined}
163
- */
164
- renderVisibleLegends() {
165
- this.updateStartEndRowIndex();
166
-
167
- const elementsToRemove = this.legendBoxDOM.querySelectorAll('.ev-chart-legend-container');
168
- elementsToRemove.forEach(element => element.remove());
169
-
170
- const totalScrollHeight = this.totalRowCount * this.legendItemHeight;
171
- const top = this.startRowIndex * this.legendItemHeight;
172
- const bottom = Math.max(
173
- totalScrollHeight - this.visibleRowCount * this.legendItemHeight - top,
174
- 0,
175
- );
176
- this.legendTopSpacer.style.height = `${top}px`;
177
- this.legendBottomSpacer.style.height = `${bottom}px`;
178
-
179
- const startIndex = this.startRowIndex * this.itemsPerRow;
180
- const endIndex = this.endRowIndex * this.itemsPerRow;
181
-
182
- const groups = this.data.groups.at(0);
183
-
184
- let useLegendSeries = [];
185
- if (groups) {
186
- useLegendSeries = groups.filter(sId => this.seriesList[sId].showLegend)
187
- .map(sId => [sId, this.seriesList[sId]]);
188
- } else {
189
- useLegendSeries = Object.entries(this.seriesList)
190
- .filter(([, series]) => series.showLegend);
191
- }
192
- useLegendSeries.slice(startIndex, endIndex).forEach(([, series]) => {
193
- this.addLegend(series);
194
- });
195
- },
196
-
197
- /**
198
- * Add legend with group information to align each series properly.
199
- * Especially if a chart is stacked,
200
- * legends have to align with series ordering as we can see in chart.
201
- *
202
- * @returns {undefined}
203
- */
204
- addLegendList() {
205
- const { groups } = this.data;
206
- const { seriesList } = this;
207
-
208
- if (this.options.legend.virtualScroll && !this.useTable) {
209
- this.renderVisibleLegendsFrameId = requestAnimationFrame(() => {
210
- this.renderVisibleLegends();
211
- });
212
- } else {
213
- this.addLegendForGroups(groups, seriesList, this.useTable);
214
- this.addStandaloneLegends(seriesList, this.useTable);
215
- }
216
- },
217
- /**
218
- * Adds legends for each group in `groups` array, iterating through each series within the group.
219
- * Only adds series with `showLegend` set to `true`.
220
- *
221
- * @param {Array} groups - Array of groups containing series identifiers.
222
- * @param {Object} seriesList - Object containing all series, keyed by series ID.
223
- * @param {boolean} useTable - Determines whether to add legends with additional values.
224
- * @returns {undefined}
225
- */
226
- addLegendForGroups(groups, seriesList, useTable) {
227
- groups.forEach((group) => {
228
- group.forEach((sId) => {
229
- const series = seriesList[sId];
230
- if (series && series.showLegend) {
231
- this.addLegendBasedOnType(series, useTable);
232
- }
233
- });
234
- });
235
- },
236
- /**
237
- * Adds legends for series that are not part of any group. Iterates through each series
238
- * in `seriesList` and only adds those that are not assigned to any group (based on `isExistGrp`)
239
- * and have `showLegend` set to `true`.
240
- *
241
- * @param {Object} seriesList - Object containing all series, keyed by series ID.
242
- * @param {boolean} useTable - Determines whether to add legends with additional values.
243
- * @returns {undefined}
244
- */
245
- addStandaloneLegends(seriesList, useTable) {
246
- Object.values(seriesList).forEach((series) => {
247
- if (!series.isExistGrp && series.showLegend) {
248
- this.addLegendBasedOnType(series, useTable);
249
- }
250
- });
251
- },
252
- /**
253
- * Adds a legend item for a specific series, determining whether to include additional
254
- * values based on the `useTable` parameter. Calls `addLegendWithValues` if `useTable` is true,
255
- * otherwise calls `addLegend`.
256
- *
257
- * @param {Object} series - Series object containing data to display in the legend.
258
- * @param {boolean} useTable - Determines whether to add legends with additional values.
259
- * @returns {undefined}
260
- */
261
- addLegendBasedOnType(series, useTable) {
262
- if (useTable) {
263
- this.addLegendWithValues(series);
264
- } else {
265
- this.addLegend(series);
266
- }
267
- },
268
-
269
- /**
270
- * Add Legend with Color Information
271
- * Only Heatmap chart
272
- *
273
- * @returns {undefined}
274
- */
275
- addColorLegendList() {
276
- const seriesList = this.seriesList;
277
-
278
- Object.values(seriesList).forEach((series) => {
279
- if (!series.isExistGrp && series.showLegend) {
280
- const { colorState, valueOpt } = series;
281
- const { min, max, interval, existError, decimalPoint } = valueOpt;
282
- const length = colorState.length;
283
- const endIndex = existError ? length - 2 : length - 1;
284
-
285
- for (let index = 0; index < length; index++) {
286
- const { id, color, label = '' } = colorState[index];
287
- const minValue = min + (interval * index);
288
- let maxValue = minValue + interval;
289
- if (index < endIndex) {
290
- maxValue -= (0.1 ** decimalPoint);
291
- } else {
292
- maxValue = max + (0.1 ** decimalPoint);
293
- }
294
-
295
- let name = label;
296
- if (!name) {
297
- name = `${minValue.toFixed(decimalPoint)} - ${maxValue.toFixed(decimalPoint)}`;
298
- if (min === undefined || max === undefined) {
299
- if (index === 0) {
300
- name = '0';
301
- } else {
302
- break;
303
- }
304
- } else if (minValue > max) {
305
- break;
306
- } else if (interval <= 1 && decimalPoint === 0) {
307
- name = minValue;
308
- }
309
- }
310
-
311
- this.addLegend({
312
- cId: id,
313
- color,
314
- name,
315
- show: true,
316
- });
317
- }
318
- }
319
- });
320
- },
321
-
322
- /**
323
- * Get Container DOM by Event Object
324
- * @param e Event
325
- *
326
- * @returns {Element}
327
- */
328
- getContainerDOM(e) {
329
- let targetDOM = null;
330
- const type = e.target.dataset.type;
331
-
332
- const childTypes = ['name', 'color', 'min', 'max', 'avg', 'total', 'last'];
333
-
334
- if (type === 'container') {
335
- targetDOM = e.target;
336
- } else if (childTypes.includes(type)) {
337
- targetDOM = e.target.parentElement;
338
-
339
- if (!targetDOM?.series) {
340
- targetDOM = targetDOM.parentElement;
341
- }
342
- }
343
-
344
- return targetDOM;
345
- },
346
-
347
- /**
348
- * Initialize legend event
349
- *
350
- * @returns {undefined}
351
- */
352
- initEvent() {
353
- if (this.isInitLegend) {
354
- return;
355
- }
356
-
357
- const classList = {
358
- container: `ev-chart-legend${this.useTable ? '--table__row' : '-container'}`,
359
- color: `ev-chart-legend${this.useTable ? '--table__color' : '-color'}`,
360
- name: `ev-chart-legend${this.useTable ? '--table__name' : '-name'}`,
361
- value: `ev-chart-legend${this.useTable ? '--table__value' : '-value'}`,
362
- };
363
-
364
- /**
365
- * callback for legendBoxDOM to show/hide clicked series
366
- *
367
- * @param {Element} _targetDOM - target DOM
368
- * @param {string} _inactiveColor - inactive color
369
- * @returns {void}
370
- */
371
- const inactiveDomAndSeries = (_targetDOM, _inactiveColor) => {
372
- const _colorDOM = _targetDOM?.getElementsByClassName(classList.color)[0];
373
- const _nameDOM = _targetDOM?.getElementsByClassName(classList.name)[0];
374
- const _valueDOMList = _targetDOM?.getElementsByClassName(classList.value);
375
- const _series = _targetDOM?.series;
376
-
377
- _colorDOM.style.backgroundColor = _inactiveColor;
378
- _colorDOM.style.borderColor = _inactiveColor;
379
- _nameDOM.style.color = _inactiveColor;
380
- _valueDOMList?.forEach((dom) => {
381
- dom.style.color = _inactiveColor;
382
- });
383
-
384
- _series.show = false;
385
- _targetDOM.dataset.inactive = true;
386
- };
387
-
388
- /**
389
- * callback for legendBoxDOM to show/hide clicked series
390
- *
391
- * @param {Element} _targetDOM - target DOM
392
- * @param {string} _activeColor - active color
393
- * @returns {void}
394
- */
395
- const activeDomAndSeries = (_targetDOM, _activeColor) => {
396
- let seriesColor;
397
-
398
- const _colorDOM = _targetDOM?.getElementsByClassName(classList.color)[0];
399
- const _nameDOM = _targetDOM?.getElementsByClassName(classList.name)[0];
400
- const _valueDOMList = _targetDOM?.getElementsByClassName(classList.value);
401
- const _series = _targetDOM?.series;
402
-
403
- if (typeof _series.color !== 'string') {
404
- seriesColor = _series.color[_series.color.length - 1][1];
405
- } else {
406
- seriesColor = _series.color;
407
- }
408
-
409
- if (_series.type === 'line' && _series.fill) {
410
- _colorDOM.style.height = '8px';
411
- _colorDOM.style.backgroundColor = Util.rgbaAdjustHalfOpacity(seriesColor);
412
- _colorDOM.style.border = `1px solid ${seriesColor}`;
413
- } else {
414
- _colorDOM.style.backgroundColor = seriesColor;
415
- }
416
-
417
- _nameDOM.style.color = _activeColor;
418
- _valueDOMList?.forEach((dom) => {
419
- const style = this.options.legend.table?.columns[dom.dataset.type]?.style;
420
- dom.style.color = style?.color ? style.color : _activeColor;
421
- });
422
-
423
- _series.show = true;
424
- _targetDOM.dataset.inactive = false;
425
- };
426
-
427
- const hideAllSeries = () => {
428
- const legendSeries = (() => {
429
- if (this.data.groups.at(0)) {
430
- return this.data.groups.at(0).slice().reverse()
431
- .filter(sId => this.seriesList[sId].showLegend)
432
- .map(sId => [sId, this.seriesList[sId]]);
433
- }
434
- return Object.entries(this.seriesList)
435
- .filter(([, series]) => series.showLegend);
436
- })();
437
- legendSeries.forEach(([, s]) => {
438
- s.show = false;
439
- });
440
- };
441
- const showAllSeries = () => {
442
- const legendSeries = (() => {
443
- if (this.data.groups.at(0)) {
444
- return this.data.groups.at(0).slice().reverse()
445
- .filter(sId => this.seriesList[sId].showLegend)
446
- .map(sId => [sId, this.seriesList[sId]]);
447
- }
448
- return Object.entries(this.seriesList)
449
- .filter(([, series]) => series.showLegend);
450
- })();
451
- legendSeries.forEach(([, s]) => {
452
- s.show = true;
453
- });
454
- };
455
-
456
- /**
457
- * callback for legendBoxDOM to show/hide clicked series
458
- *
459
- * @returns {undefined}
460
- */
461
- /**
462
- * 범례 박스 클릭 이벤트 핸들러
463
- * 시리즈의 표시/숨김을 토글하고 범례의 시각적 상태를 변경
464
- */
465
- this.onLegendBoxClick = (e) => {
466
- const { legend: opt } = this.options;
467
-
468
- if (opt?.stopClickEvt) {
469
- return;
470
- }
471
- const { chartIdx } = this.data;
472
-
473
- const targetDOM = this.getContainerDOM(e);
474
- if (!targetDOM) {
475
- return;
476
- }
477
-
478
- const colorDOM = targetDOM?.getElementsByClassName(classList.color)[0];
479
- const nameDOM = targetDOM?.getElementsByClassName(classList.name)[0];
480
- const isActive = targetDOM?.dataset.inactive === 'false';
481
-
482
- if (!colorDOM || !nameDOM) {
483
- return;
484
- }
485
-
486
- // clickMode active - 클릭시 활성화
487
- if (opt.clickMode === 'active') {
488
- const legendContainerDOMs = Array.from(
489
- this.legendBoxDOM.getElementsByClassName(classList.container),
490
- );
491
- const isActiveAll = legendContainerDOMs.every(dom => dom.dataset.inactive === 'false');
492
-
493
- if (isActiveAll) {
494
- legendContainerDOMs.forEach((dom) => {
495
- inactiveDomAndSeries(dom, opt.inactive);
496
- });
497
- hideAllSeries();
498
-
499
- activeDomAndSeries(targetDOM, opt.color);
500
- this.seriesInfo.count = 1;
501
- } else if (isActive) {
502
- inactiveDomAndSeries(targetDOM, opt.inactive);
503
- this.seriesInfo.count--;
504
- } else if (!isActive) {
505
- activeDomAndSeries(targetDOM, opt.color);
506
- this.seriesInfo.count++;
507
- }
508
-
509
- const isInactiveAll = legendContainerDOMs.every(dom => dom.dataset.inactive === 'true');
510
-
511
- if (isInactiveAll) {
512
- legendContainerDOMs.forEach((dom) => {
513
- activeDomAndSeries(dom, opt.color);
514
- });
515
- showAllSeries();
516
- this.seriesInfo.count = legendContainerDOMs.length;
517
- }
518
- }
519
-
520
- // clickMode inactive - 클릭시 비활성화
521
- if (opt.clickMode !== 'active') {
522
- if (isActive && this.seriesInfo.count === 1) {
523
- return;
524
- }
525
-
526
- if (isActive) {
527
- inactiveDomAndSeries(targetDOM, opt.inactive);
528
- this.seriesInfo.count--;
529
- } else {
530
- activeDomAndSeries(targetDOM, opt.color);
531
- this.seriesInfo.count++;
532
- }
533
- }
534
-
535
- if (this.brushSeries) {
536
- const seriesList = [...this.brushSeries.list];
537
- seriesList[chartIdx] = this.seriesList;
538
-
539
- this.brushSeries.list = seriesList;
540
- this.brushSeries.chartIdx = chartIdx;
541
- }
542
-
543
- this.update({
544
- updateSeries: false,
545
- updateSelTip: { update: true, keepDomain: true },
546
- });
547
- };
548
-
549
- /**
550
- * callback for mouseleave event on legendBoxDOM
551
- *
552
- * @returns {undefined}
553
- */
554
- this.onLegendBoxLeave = () => {
555
- this.legendHover = null;
556
-
557
- this.update({
558
- updateSeries: false,
559
- updateSelTip: { update: false, keepDomain: false },
560
- hitInfo: {
561
- legend: null,
562
- },
563
- });
564
- };
565
-
566
- /**
567
- * callback for legendBoxDOM hovering
568
- *
569
- * @returns {undefined}
570
- */
571
- this.onLegendBoxOver = (e) => {
572
- const targetDOM = this.getContainerDOM(e);
573
- if (!targetDOM) {
574
- this.onLegendBoxLeave();
575
- return;
576
- }
577
-
578
- const targetId = targetDOM?.series?.sId;
579
- const legendHitInfo = { sId: targetId, type: this.options.type };
580
-
581
- this.legendHover = legendHitInfo;
582
-
583
- this.update({
584
- updateSeries: false,
585
- updateSelTip: { update: false, keepDomain: false },
586
- hitInfo: {
587
- legend: legendHitInfo,
588
- },
589
- });
590
- };
591
-
592
- this.legendBoxDOM.addEventListener('click', this.onLegendBoxClick);
593
- this.legendBoxDOM.addEventListener('mouseover', this.onLegendBoxOver);
594
- this.legendBoxDOM.addEventListener('mouseleave', this.onLegendBoxLeave);
595
-
596
- if (this.options.legend.virtualScroll && !this.useTable) {
597
- this.legendBoxDOM.addEventListener('resize', this.updateVisibleRowCount);
598
- this.legendBoxDOM.addEventListener('scroll', this.renderVisibleLegends.bind(this));
599
- }
600
-
601
- this.initResizeEvent();
602
- },
603
-
604
- /**
605
- * Init Event on Color Legend
606
- * Only Heatmap
607
- */
608
- initEventForColorLegend() {
609
- if (this.isInitLegend) {
610
- return;
611
- }
612
- const classList = {
613
- container: `ev-chart-legend${this.useTable ? '--table__row' : '-container'}`,
614
- color: `ev-chart-legend${this.useTable ? '--table__color' : '-color'}`,
615
- name: `ev-chart-legend${this.useTable ? '--table__name' : '-name'}`,
616
- };
617
-
618
- /**
619
- * callback for legendBoxDOM to show/hide clicked series
620
- *
621
- * @param {Element} _targetDOM - target DOM
622
- * @param {string} _inactiveColor - inactive color
623
- * @returns {void}
624
- */
625
- const inactiveDomAndSeries = (_targetDOM, _inactiveColor) => {
626
- const _colorDOM = _targetDOM?.getElementsByClassName(classList.color)[0];
627
- const _nameDOM = _targetDOM?.getElementsByClassName(classList.name)[0];
628
- const _series = Object.values(this.seriesList)[0];
629
- const targetId = _targetDOM?.series?.cId;
630
-
631
- _colorDOM.style.backgroundColor = _inactiveColor;
632
- _colorDOM.style.borderColor = _inactiveColor;
633
- _nameDOM.style.color = _inactiveColor;
634
-
635
- const targetIndex = _series.colorState.findIndex(colorItem => colorItem.id === targetId);
636
- if (targetIndex > -1) {
637
- _series.colorState[targetIndex].show = false;
638
- }
639
-
640
- _targetDOM.dataset.inactive = true;
641
- };
642
-
643
- /**
644
- * callback for legendBoxDOM to show/hide clicked series
645
- *
646
- * @param {Element} _targetDOM - target DOM
647
- * @param {string} _activeColor - active color
648
- * @returns {void}
649
- */
650
- const activeDomAndSeries = (_targetDOM, _activeColor) => {
651
- const _colorDOM = _targetDOM?.getElementsByClassName(classList.color)[0];
652
- const _nameDOM = _targetDOM?.getElementsByClassName(classList.name)[0];
653
- const _series = Object.values(this.seriesList)[0];
654
- const targetId = _targetDOM?.series?.cId;
655
-
656
- _colorDOM.style.backgroundColor = _targetDOM?.series?.color;
657
- _nameDOM.style.color = _activeColor;
658
-
659
- const targetIndex = _series.colorState.findIndex(colorItem => colorItem.id === targetId);
660
- if (targetIndex > -1) {
661
- _series.colorState[targetIndex].show = true;
662
- }
663
-
664
- _targetDOM.dataset.inactive = false;
665
- };
666
-
667
- const hideAllSeries = () => {
668
- const series = Object.values(this.seriesList)[0];
669
- series.colorState.forEach((colorItem) => {
670
- colorItem.show = false;
671
- });
672
- };
673
- const showAllSeries = () => {
674
- const series = Object.values(this.seriesList)[0];
675
- series.colorState.forEach((colorItem) => {
676
- colorItem.show = true;
677
- });
678
- };
679
-
680
- /**
681
- * callback for legendBoxDOM to show/hide clicked series
682
- *
683
- * @returns {undefined}
684
- */
685
- this.onLegendBoxClick = (e) => {
686
- const opt = this.options.legend;
687
- if (opt?.stopClickEvt) {
688
- return;
689
- }
690
- const series = Object.values(this.seriesList)[0];
691
-
692
- const targetDOM = this.getContainerDOM(e);
693
- if (!targetDOM) {
694
- return;
695
- }
696
-
697
- const colorDOM = targetDOM?.getElementsByClassName(classList.color)[0];
698
- const nameDOM = targetDOM?.getElementsByClassName(classList.name)[0];
699
- const isActive = targetDOM?.dataset.inactive === 'false';
700
- const activeCount = series.colorState.filter(colorItem => colorItem.show).length;
701
-
702
- if (!colorDOM || !nameDOM) {
703
- return;
704
- }
705
-
706
- // clickMode active - 클릭시 활성화
707
- if (opt.clickMode === 'active') {
708
- const legendContainerDOMs = Array.from(
709
- this.legendBoxDOM.getElementsByClassName(classList.container),
710
- );
711
- const isActiveAll = legendContainerDOMs.every(dom => dom.dataset.inactive === 'false');
712
-
713
- if (isActiveAll) {
714
- legendContainerDOMs.forEach((dom) => {
715
- inactiveDomAndSeries(dom, opt.inactive);
716
- });
717
- hideAllSeries();
718
-
719
- activeDomAndSeries(targetDOM, opt.color);
720
- } else if (isActive) {
721
- inactiveDomAndSeries(targetDOM, opt.inactive);
722
- } else if (!isActive) {
723
- activeDomAndSeries(targetDOM, opt.color);
724
- }
725
-
726
- const isInactiveAll = legendContainerDOMs.every(dom => dom.dataset.inactive === 'true');
727
-
728
- if (isInactiveAll) {
729
- legendContainerDOMs.forEach((dom) => {
730
- activeDomAndSeries(dom, opt.color);
731
- });
732
- showAllSeries();
733
- }
734
- }
735
-
736
- // clickMode inactive - 클릭시 비활성화
737
- if (opt.clickMode !== 'active') {
738
- if (isActive && activeCount === 1) {
739
- return;
740
- }
741
-
742
- if (isActive) {
743
- inactiveDomAndSeries(targetDOM, opt.inactive);
744
- } else {
745
- activeDomAndSeries(targetDOM, opt.color);
746
- }
747
- }
748
-
749
- this.update({
750
- updateSeries: false,
751
- updateSelTip: { update: true, keepDomain: true },
752
- });
753
- };
754
-
755
- /**
756
- * callback for mouseleave event on legendBoxDOM
757
- *
758
- * @returns {undefined}
759
- */
760
- this.onLegendBoxLeave = () => {
761
- this.legendHover = null;
762
-
763
- const series = Object.values(this.seriesList)[0];
764
- series.colorState.forEach((item) => {
765
- item.state = 'normal';
766
- });
767
-
768
- this.update({
769
- updateSeries: false,
770
- updateSelTip: { update: false, keepDomain: false },
771
- });
772
- };
773
-
774
- /**
775
- * callback for legendBoxDOM hovering
776
- *
777
- * @returns {undefined}
778
- */
779
- this.onLegendBoxOver = (e) => {
780
- const series = Object.values(this.seriesList)?.[0];
781
-
782
- const targetDOM = this.getContainerDOM(e);
783
- if (!targetDOM) {
784
- this.onLegendBoxLeave();
785
- return;
786
- }
787
-
788
- const targetId = targetDOM?.series?.cId;
789
- const legendHitInfo = { sId: targetId, type: this.options.type };
790
-
791
- this.legendHover = legendHitInfo;
792
-
793
- series.colorState.forEach((colorItem) => {
794
- colorItem.state = colorItem.id === targetId ? 'highlight' : 'downplay';
795
- });
796
-
797
- this.update({
798
- updateSeries: false,
799
- updateSelTip: { update: false, keepDomain: false },
800
- hitInfo: {
801
- legend: legendHitInfo,
802
- },
803
- });
804
- };
805
-
806
- this.legendBoxDOM.addEventListener('click', this.onLegendBoxClick);
807
- this.legendBoxDOM.addEventListener('mouseover', this.onLegendBoxOver);
808
- this.legendBoxDOM.addEventListener('mouseleave', this.onLegendBoxLeave);
809
-
810
- this.initResizeEvent();
811
- },
812
-
813
- initResizeEvent() {
814
- /**
815
- * callback for resizeDOM click event
816
- * 1. hide resizeDOM
817
- * 2. show ghost DOM on same position with hidden resizeDOM
818
- *
819
- * @returns {undefined}
820
- */
821
- this.onResizeMouseDown = (e) => {
822
- e.stopPropagation();
823
- e.preventDefault();
824
-
825
- const opt = this.options;
826
- const pos = opt.legend.position;
827
- const title = opt.title.show ? opt.title.height : 0;
828
-
829
- const ghostDOM = this.ghostDOM;
830
- this.resizeDOM.style.display = 'none';
831
- this.wrapperDOM.appendChild(ghostDOM);
832
-
833
- // mouse down 시, resizeDOM의 위치를 기반으로 ghostDOM의 위치를 세팅
834
- if (pos === 'left' || pos === 'right') {
835
- ghostDOM.style.top = `${title}px`;
836
- ghostDOM.style.left = this.resizeDOM.style.left;
837
- ghostDOM.style.right = this.resizeDOM.style.right;
838
- ghostDOM.style.height = this.resizeDOM.style.height;
839
- } else {
840
- ghostDOM.classList.add('horizontal');
841
-
842
- if (pos === 'top') {
843
- ghostDOM.style.top = this.resizeDOM.style.top;
844
- } else if (pos === 'bottom') {
845
- ghostDOM.style.bottom = this.resizeDOM.style.bottom;
846
- }
847
- }
848
-
849
- this.wrapperDOM.addEventListener('mousemove', this.mouseMove, false);
850
- this.wrapperDOM.addEventListener('mouseup', this.mouseUp, false);
851
- };
852
-
853
- if (this.resizeDOM) {
854
- this.resizeDOM.addEventListener('mousedown', this.onResizeMouseDown);
855
- this.mouseMove = this.onMouseMove.bind(this); // resizing function
856
- this.mouseUp = this.onMouseUp.bind(this); // resizing function
857
- }
858
- },
859
-
860
- /**
861
- * To update legend, reset all process.
862
- *
863
- * @returns {undefined}
864
- */
865
- updateLegend() {
866
- this.resetLegend();
867
-
868
- if (this.isHeatMapType) {
869
- this.addColorLegendList();
870
- } else {
871
- this.addLegendList();
872
- }
873
- },
874
-
875
- /**
876
- * To update value text on legend table
877
- * Only chartOption > legend > table > use : true
878
- *
879
- * @returns {undefined}
880
- */
881
- updateLegendTableValues() {
882
- const columns = this.options?.legend?.table?.columns;
883
- const aggregations = this.getAggregations();
884
- const rowDOMList = this.legendBoxDOM?.getElementsByClassName('ev-chart-legend--table__row');
885
-
886
- rowDOMList.forEach((row) => {
887
- const valueDOMList = row?.getElementsByClassName('ev-chart-legend--table__value');
888
-
889
- valueDOMList.forEach((dom) => {
890
- const key = dom.dataset.type;
891
- if (key === 'name') {
892
- return;
893
- }
894
-
895
- const seriesId = row.series.sId;
896
- const value = aggregations?.[seriesId]?.[key];
897
- dom.textContent = this.getFormattedValue(columns[key], value);
898
- });
899
- });
900
- },
901
-
902
- /**
903
- * Force Update Legend. Remove and Create
904
- *
905
- * @returns {undefined}
906
- */
907
- forceUpdateLegend() {
908
- this.destroyLegend();
909
- this.initLegend();
910
- },
911
-
912
- /**
913
- * To update legend, remove all of legendBoxDOM's children
914
- * (except spacers when virtualScroll is enabled)
915
- *
916
- * @returns {undefined}
917
- */
918
- resetLegend() {
919
- const legendBoxDOM = this.legendBoxDOM;
920
-
921
- if (!legendBoxDOM) {
922
- return;
923
- }
924
-
925
- if (this.useTable) {
926
- const legendTableDOM = this.legendTableDOM;
927
- while (legendTableDOM.hasChildNodes()) {
928
- legendTableDOM.removeChild(legendTableDOM.firstChild);
929
- }
930
- this.setLegendColumnHeader();
931
- } else if (this.options.legend.virtualScroll) {
932
- this.updateVisibleRowCount();
933
- this.renderVisibleLegends();
934
- } else {
935
- while (legendBoxDOM.hasChildNodes()) {
936
- legendBoxDOM.removeChild(legendBoxDOM.firstChild);
937
- }
938
- }
939
- this.seriesInfo.count = 0;
940
- },
941
-
942
- /**
943
- * To update legend, remove all of legendBoxDOM's children
944
- *
945
- * @returns {undefined}
946
- */
947
- destroyLegend() {
948
- const legendDOM = this.legendDOM;
949
-
950
- if (this.renderVisibleLegendsFrameId != null) {
951
- cancelAnimationFrame(this.renderVisibleLegendsFrameId);
952
- this.renderVisibleLegendsFrameId = null;
953
- }
954
- if (this.updateVisibleRowCountFrameId != null) {
955
- cancelAnimationFrame(this.updateVisibleRowCountFrameId);
956
- this.updateVisibleRowCountFrameId = null;
957
- }
958
-
959
- if (!legendDOM) {
960
- return;
961
- }
962
- legendDOM.remove();
963
-
964
- this.legendDOM = null;
965
- this.legendBoxDOM = null;
966
- this.resizeDOM = null;
967
- this.isInitLegend = false;
968
- this.seriesInfo.count = 0;
969
- },
970
-
971
- /**
972
- * Create DOM for each series
973
- *
974
- * @returns {undefined}
975
- */
976
- /**
977
- * 새로운 범례 아이템을 생성하고 범례 영역에 추가
978
- * @param {Object} series - 시리즈 정보 객체
979
- */
980
- addLegend(series) {
981
- const opt = this.options.legend;
982
-
983
- const containerDOM = document.createElement('div');
984
- const colorDOM = document.createElement('span');
985
- const nameDOM = document.createElement('div');
986
-
987
- containerDOM.className = 'ev-chart-legend-container';
988
- containerDOM.dataset.inactive = !series.show;
989
- containerDOM.series = series;
990
-
991
- colorDOM.className = 'ev-chart-legend-color';
992
-
993
- if (series.type === 'line' && series.point && !series.fill) {
994
- colorDOM.className += ' ev-chart-legend-color--point-line';
995
- }
996
-
997
- nameDOM.className = 'ev-chart-legend-name';
998
-
999
- let seriesColor;
1000
- if (!series.show) {
1001
- seriesColor = opt.inactive;
1002
- } else if (typeof series.color !== 'string') {
1003
- seriesColor = series.color[series.color.length - 1][1];
1004
- } else {
1005
- seriesColor = series.color;
1006
- }
1007
-
1008
- if (series.type === 'line' && series.fill) {
1009
- colorDOM.style.height = '8px';
1010
- colorDOM.style.backgroundColor = series.show
1011
- ? Util.rgbaAdjustHalfOpacity(seriesColor) : opt.inactive;
1012
- colorDOM.style.border = `1px solid ${seriesColor}`;
1013
- } else {
1014
- colorDOM.style.backgroundColor = seriesColor;
1015
- }
1016
-
1017
- colorDOM.dataset.type = 'color';
1018
-
1019
- nameDOM.style.color = opt.color;
1020
- nameDOM.textContent = series.name;
1021
- nameDOM.setAttribute('title', series.name);
1022
- nameDOM.dataset.type = 'name';
1023
-
1024
- containerDOM.appendChild(colorDOM);
1025
- containerDOM.appendChild(nameDOM);
1026
-
1027
- if (opt.position === 'top' || opt.position === 'bottom') {
1028
- containerDOM.style.width = `${opt.width - 8}px`;
1029
- containerDOM.style.margin = '0 4px';
1030
- } else {
1031
- containerDOM.style.width = '100%';
1032
- }
1033
-
1034
- containerDOM.style.height = `${this.legendItemHeight}px`;
1035
- containerDOM.style.display = 'inline-block';
1036
- containerDOM.style.overflow = 'hidden';
1037
- containerDOM.dataset.type = 'container';
1038
-
1039
- this.legendBoxDOM.insertBefore(containerDOM, this.legendBottomSpacer);
1040
-
1041
- if (series.show) {
1042
- this.seriesInfo.count++;
1043
- }
1044
- },
1045
-
1046
- /**
1047
- * Add Legend Items With aggregation Values
1048
- * Only chartOption > legend > table > use : true
1049
- * @param series
1050
- */
1051
- addLegendWithValues(series) {
1052
- const opt = this.options.legend;
1053
- const columns = opt?.table?.columns;
1054
-
1055
- const aggregations = this.getAggregations()?.[series?.sId];
1056
- if (!aggregations || !columns) {
1057
- return;
1058
- }
1059
-
1060
- // create row
1061
- const rowDOM = document.createElement('tr');
1062
- rowDOM.className = 'ev-chart-legend--table__row';
1063
- rowDOM.dataset.inactive = !series.show;
1064
- Util.setDOMStyle(rowDOM, opt.table?.style?.row);
1065
- rowDOM.series = series;
1066
- rowDOM.dataset.type = 'container';
1067
-
1068
- // create td - color
1069
- const colorWrapperDOM = document.createElement('td');
1070
- colorWrapperDOM.className = 'ev-chart-legend--table__color-wrapper';
1071
- colorWrapperDOM.dataset.type = 'color';
1072
-
1073
- const colorDOM = document.createElement('div');
1074
- colorDOM.className = 'ev-chart-legend--table__color';
1075
- colorDOM.dataset.type = 'color';
1076
-
1077
- // set series color
1078
- let seriesColor;
1079
- if (!series.show) {
1080
- seriesColor = opt.inactive;
1081
- } else if (typeof series.color !== 'string') {
1082
- seriesColor = series.color[series.color.length - 1][1];
1083
- } else {
1084
- seriesColor = series.color;
1085
- }
1086
-
1087
- switch (series.type) {
1088
- case 'line': {
1089
- if (series.fill) {
1090
- colorDOM.style.backgroundColor = Util.rgbaAdjustHalfOpacity(seriesColor);
1091
- colorDOM.style.border = `1px solid ${seriesColor}`;
1092
- } else {
1093
- if (series.point) {
1094
- colorDOM.className += ' ev-chart-legend--table__color--point-line';
1095
- }
1096
-
1097
- colorDOM.className += ' ev-chart-legend--table__color--line';
1098
- colorDOM.style.backgroundColor = seriesColor;
1099
- }
1100
- break;
1101
- }
1102
-
1103
- case 'bar':
1104
- case 'pie':
1105
- default: {
1106
- colorDOM.style.height = '10px';
1107
- colorDOM.style.backgroundColor = seriesColor;
1108
- break;
1109
- }
1110
- }
1111
-
1112
- if (series.type === 'line' && series.fill) {
1113
- colorDOM.style.height = '8px';
1114
- colorDOM.style.backgroundColor = series.show
1115
- ? Util.rgbaAdjustHalfOpacity(seriesColor) : opt.inactive;
1116
- colorDOM.style.border = `1px solid ${seriesColor}`;
1117
- } else {
1118
- colorDOM.style.backgroundColor = seriesColor;
1119
- }
1120
-
1121
- colorWrapperDOM.appendChild(colorDOM);
1122
- rowDOM.appendChild(colorWrapperDOM);
1123
-
1124
- // create td - name
1125
- const nameDOM = document.createElement('td');
1126
- nameDOM.className = 'ev-chart-legend--table__name';
1127
- nameDOM.style.color = series.show ? opt.color : opt.inactive;
1128
- nameDOM.textContent = series.name;
1129
- nameDOM.setAttribute('title', series.name);
1130
- nameDOM.dataset.type = 'name';
1131
- Util.setDOMStyle(nameDOM, columns?.name?.style);
1132
-
1133
- if (!series.show) {
1134
- nameDOM.style.color = opt.inactive;
1135
- }
1136
-
1137
- rowDOM.appendChild(nameDOM);
1138
-
1139
- // create td - values
1140
- const columnKeyList = Object.keys(columns);
1141
- columnKeyList?.forEach((key) => {
1142
- if (key === 'name') {
1143
- return;
1144
- }
1145
-
1146
- if (columns[key].use) {
1147
- const formattedTxt = this.getFormattedValue(columns[key], aggregations[key]);
1148
- const valueDOM = document.createElement('td');
1149
- valueDOM.className = 'ev-chart-legend--table__value';
1150
- valueDOM.style.color = series.show ? opt.color : opt.inactive;
1151
- valueDOM.textContent = formattedTxt;
1152
- valueDOM.dataset.type = key.toString();
1153
- Util.setDOMStyle(valueDOM, columns[key]?.style);
1154
-
1155
- if (!series.show) {
1156
- valueDOM.style.color = opt.inactive;
1157
- }
1158
-
1159
- rowDOM.appendChild(valueDOM);
1160
- }
1161
- });
1162
-
1163
- this.legendTableDOM.appendChild(rowDOM);
1164
- if (series.show) {
1165
- this.seriesInfo.count++;
1166
- }
1167
- },
1168
-
1169
- /**
1170
- * Set legend components position by option
1171
- *
1172
- * @returns {undefined}
1173
- */
1174
- setLegendPosition() {
1175
- const opt = this.options;
1176
- const position = opt?.legend?.position;
1177
- const wrapperStyle = this.wrapperDOM?.style;
1178
- const legendStyle = this.legendDOM?.style;
1179
- const boxStyle = this.legendBoxDOM?.style;
1180
- const resizeStyle = this.resizeDOM?.style;
1181
-
1182
- let chartRect;
1183
- let legendPad;
1184
- const title = opt?.title?.show ? opt?.title?.height : 0;
1185
- const positionTop = title + opt?.legend?.height;
1186
- const { top = 0, bottom = 0, left = 0, right = 0 } = opt?.legend?.padding ?? {};
1187
-
1188
- if (!wrapperStyle || !legendStyle) {
1189
- return;
1190
- }
1191
-
1192
- boxStyle.padding = `${top}px ${right}px ${bottom}px ${left}px`;
1193
-
1194
- switch (position) {
1195
- case 'top':
1196
- wrapperStyle.padding = `${positionTop}px 0 0 0`;
1197
- chartRect = this.chartDOM.getBoundingClientRect();
1198
- legendPad = parseInt(legendStyle.paddingTop) + parseInt(legendStyle.paddingBottom);
1199
-
1200
- boxStyle.width = '100%';
1201
- boxStyle.height = `${opt.legend.height - legendPad}px`;
1202
-
1203
- legendStyle.top = `${title}px`;
1204
- legendStyle.right = '';
1205
- legendStyle.bottom = '';
1206
- legendStyle.left = '';
1207
-
1208
- legendStyle.width = `${chartRect.width}px`;
1209
- legendStyle.height = `${opt.legend.height + (resizeStyle ? 4 : 0)}px`; // 4 resize bar size
1210
-
1211
- if (resizeStyle) {
1212
- resizeStyle.top = `${positionTop}px`;
1213
- resizeStyle.right = '';
1214
- resizeStyle.bottom = '';
1215
- resizeStyle.left = '';
1216
-
1217
- resizeStyle.width = `${chartRect.width}px`;
1218
- resizeStyle.height = '4px';
1219
- resizeStyle.cursor = 'row-resize';
1220
- }
1221
- break;
1222
- case 'right':
1223
- wrapperStyle.padding = `${title}px ${opt.legend.width}px 0 0`;
1224
- chartRect = this.chartDOM.getBoundingClientRect();
1225
-
1226
- boxStyle.width = `${opt.legend.width - 10}px`; // legendDOM left padding
1227
- boxStyle.maxHeight = `${chartRect.height}px`;
1228
-
1229
- legendStyle.paddingLeft = '10px';
1230
- legendStyle.top = `${title}px`;
1231
- legendStyle.right = '0px';
1232
- legendStyle.bottom = '';
1233
- legendStyle.left = '';
1234
-
1235
- legendStyle.width = `${opt.legend.width}px`;
1236
- legendStyle.height = `${chartRect.height}px`;
1237
-
1238
- if (resizeStyle) {
1239
- resizeStyle.top = `${title}px`;
1240
- resizeStyle.right = `${opt.legend.width}px`;
1241
- resizeStyle.bottom = '';
1242
- resizeStyle.left = '';
1243
-
1244
- resizeStyle.width = '4px';
1245
- resizeStyle.height = `${chartRect.height}px`;
1246
- resizeStyle.cursor = 'col-resize';
1247
- }
1248
- break;
1249
- case 'bottom':
1250
- wrapperStyle.padding = `${title}px 0 ${opt.legend.height}px 0`;
1251
- chartRect = this.chartDOM.getBoundingClientRect();
1252
- legendPad = parseInt(legendStyle.paddingTop) + parseInt(legendStyle.paddingBottom);
1253
-
1254
- boxStyle.width = '100%';
1255
- boxStyle.height = `${opt.legend.height - legendPad}px`;
1256
-
1257
- legendStyle.top = '';
1258
- legendStyle.right = '';
1259
- legendStyle.bottom = '0px';
1260
- legendStyle.left = '0px';
1261
-
1262
- legendStyle.width = `${chartRect.width}px`;
1263
- legendStyle.height = `${opt.legend.height + (resizeStyle ? 4 : 0)}px`; // 4 resize bar size
1264
-
1265
- if (resizeStyle) {
1266
- resizeStyle.top = '';
1267
- resizeStyle.right = '';
1268
- resizeStyle.bottom = `${opt.legend.height}px`;
1269
- resizeStyle.left = '';
1270
-
1271
- resizeStyle.width = `${chartRect.width}px`;
1272
- resizeStyle.height = '4px';
1273
- resizeStyle.cursor = 'row-resize';
1274
- }
1275
- break;
1276
- case 'left':
1277
- wrapperStyle.padding = `${title}px 0 0 ${opt.legend.width}px`;
1278
- chartRect = this.chartDOM.getBoundingClientRect();
1279
-
1280
- boxStyle.width = `${opt.legend.width}px`;
1281
- boxStyle.maxHeight = `${chartRect.height}px`;
1282
- boxStyle.display = 'absolute';
1283
- boxStyle.bottom = '0px';
1284
-
1285
- legendStyle.top = `${title}px`;
1286
- legendStyle.right = '';
1287
- legendStyle.bottom = '';
1288
- legendStyle.left = '0px';
1289
-
1290
- legendStyle.width = `${opt.legend.width}px`;
1291
- legendStyle.height = `${chartRect.height}px`;
1292
-
1293
- if (resizeStyle) {
1294
- resizeStyle.top = `${title}px`;
1295
- resizeStyle.right = '';
1296
- resizeStyle.bottom = '';
1297
- resizeStyle.left = `${opt.legend.width}px`;
1298
-
1299
- resizeStyle.width = '4px';
1300
- resizeStyle.height = `${chartRect.height}px`;
1301
- resizeStyle.cursor = 'col-resize';
1302
- }
1303
- break;
1304
- default:
1305
- break;
1306
- }
1307
- },
1308
-
1309
- /**
1310
- * Update legend components size
1311
- *
1312
- * @returns {undefined}
1313
- */
1314
- updateLegendContainerSize() {
1315
- if (!this.options || !this.legendBoxDOM) {
1316
- return;
1317
- }
1318
-
1319
- const opt = this.options?.legend;
1320
- const container = this.legendBoxDOM.getElementsByClassName('ev-chart-legend-container');
1321
-
1322
- if (!container) {
1323
- return;
1324
- }
1325
-
1326
- for (let ix = 0; ix < container.length; ix++) {
1327
- if (opt.position === 'top' || opt.position === 'bottom') {
1328
- container[ix].style.width = `${opt.width - 8}px`;
1329
- container[ix].style.margin = '0 4px';
1330
- } else {
1331
- container[ix].style.width = '100%';
1332
- }
1333
- }
1334
- },
1335
-
1336
- /**
1337
- * When user moves resizeDOM, this function will change css
1338
- *
1339
- * @returns {undefined}
1340
- */
1341
- onMouseMove(e) {
1342
- e.stopPropagation();
1343
- e.preventDefault();
1344
-
1345
- const offset = this.wrapperDOM.getBoundingClientRect();
1346
- const offsetWidth = this.wrapperDOM.offsetWidth;
1347
- const offsetHeight = this.wrapperDOM.offsetHeight;
1348
-
1349
- const titleHeight = this.options.title.show ? this.options.title.height : 0;
1350
- const position = this.options.legend.position;
1351
-
1352
- const chartMinWidth = 150;
1353
- const chartMinHeight = 70;
1354
-
1355
- const legendMinWidth = 120;
1356
- const legendMinHeight = 20;
1357
-
1358
- let move;
1359
-
1360
- switch (position) {
1361
- case 'left':
1362
- move = e.clientX - offset.left;
1363
- if (move < legendMinWidth) {
1364
- move = legendMinWidth;
1365
- } else if (move > offsetWidth - chartMinWidth) {
1366
- move = offsetWidth - chartMinWidth;
1367
- }
1368
- this.ghostDOM.style.left = `${move}px`;
1369
- break;
1370
- case 'right':
1371
- move = e.clientX - offset.left;
1372
- if (move < chartMinWidth) {
1373
- move = chartMinWidth;
1374
- } else if (move > offsetWidth - legendMinWidth) {
1375
- move = offsetWidth - legendMinWidth;
1376
- }
1377
- this.ghostDOM.style.left = `${move}px`;
1378
- break;
1379
- case 'top':
1380
- move = e.clientY - offset.top;
1381
- if (move < legendMinHeight + titleHeight) {
1382
- move = legendMinHeight + titleHeight;
1383
- } else if (move > offsetHeight - chartMinHeight) {
1384
- move = offsetHeight - chartMinHeight;
1385
- }
1386
- this.ghostDOM.style.top = `${move}px`;
1387
- break;
1388
- case 'bottom':
1389
- move = e.clientY - offset.top;
1390
- if (move < chartMinHeight + titleHeight) {
1391
- move = chartMinHeight + titleHeight;
1392
- } else if (move > offsetHeight - legendMinHeight) {
1393
- move = offsetHeight - legendMinHeight;
1394
- }
1395
- this.ghostDOM.style.bottom = `${this.wrapperDOM.offsetHeight - move}px`;
1396
- break;
1397
- default:
1398
- break;
1399
- }
1400
-
1401
- this.isLegendMove = true;
1402
- },
1403
-
1404
- /**
1405
- * callback for mouseup on ghostDOM, this function will change legend and chart size.
1406
- *
1407
- * @returns {undefined}
1408
- */
1409
- onMouseUp(e) {
1410
- e.stopPropagation();
1411
- e.preventDefault();
1412
-
1413
- this.wrapperDOM.removeEventListener('mousemove', this.mouseMove, false);
1414
- this.wrapperDOM.removeEventListener('mouseup', this.mouseUp, false);
1415
-
1416
- const opt = this.options;
1417
- const pos = opt.legend.position;
1418
- const resizeDOMStyle = this.resizeDOM.style;
1419
- const legendDOMStyle = this.legendDOM.style;
1420
- const boxDOMStyle = this.legendBoxDOM.style;
1421
- const ghostDOMStyle = this.ghostDOM.style;
1422
- const wrapperDOMStyle = this.wrapperDOM.style;
1423
-
1424
- const title = opt.title.show ? opt.title.height : 0;
1425
- const padding = +this.legendDOM.style.paddingLeft.replace('px', '');
1426
- let move;
1427
- if (this.isLegendMove) {
1428
- switch (pos) {
1429
- case 'top':
1430
- resizeDOMStyle.top = ghostDOMStyle.top;
1431
- move = +ghostDOMStyle.top.replace('px', '');
1432
- legendDOMStyle.height = `${move - title}px`;
1433
- boxDOMStyle.height = `${move - title - 4}px`;
1434
- opt.legend.height = move - title - 4;
1435
- wrapperDOMStyle.padding = `${move}px 0 0 0`;
1436
- break;
1437
- case 'right':
1438
- resizeDOMStyle.left = ghostDOMStyle.left;
1439
- move = +ghostDOMStyle.left.replace('px', '');
1440
- legendDOMStyle.width = `${(this.wrapperDOM.offsetWidth - move - 4)}px`;
1441
- boxDOMStyle.width = `${(this.wrapperDOM.offsetWidth - move - 4 - padding)}px`;
1442
- opt.legend.width = this.wrapperDOM.offsetWidth - move - 4;
1443
- wrapperDOMStyle.padding = `${title}px ${this.wrapperDOM.offsetWidth - move}px 0 0`;
1444
- break;
1445
- case 'bottom':
1446
- resizeDOMStyle.bottom = ghostDOMStyle.bottom;
1447
- move = this.wrapperDOM.offsetHeight - (+ghostDOMStyle.bottom.replace('px', ''));
1448
- legendDOMStyle.height = `${this.wrapperDOM.offsetHeight - move}px`;
1449
- boxDOMStyle.height = `${move - title - 4}px`;
1450
- opt.legend.height = this.wrapperDOM.offsetHeight - move;
1451
- wrapperDOMStyle.padding = `${title}px 0 ${this.wrapperDOM.offsetHeight - move}px 0`;
1452
- break;
1453
- case 'left':
1454
- resizeDOMStyle.left = ghostDOMStyle.left;
1455
- move = +ghostDOMStyle.left.replace('px', '');
1456
- legendDOMStyle.width = `${move}px`;
1457
- boxDOMStyle.width = `${move}px`;
1458
- opt.legend.width = move;
1459
- wrapperDOMStyle.padding = `${title}px 0 0 ${move - 4}px`;
1460
- break;
1461
- default:
1462
- break;
1463
- }
1464
- }
1465
-
1466
- resizeDOMStyle.display = 'block';
1467
- this.ghostDOM.remove();
1468
-
1469
- if (this.isLegendMove) {
1470
- this.render();
1471
- this.isLegendMove = false;
1472
- }
1473
- },
1474
-
1475
- /**
1476
- * Show legend components by manipulating css
1477
- *
1478
- * @returns {undefined}
1479
- */
1480
- showLegend() {
1481
- if (this.resizeDOM) {
1482
- this.resizeDOM.style.display = 'block';
1483
- }
1484
-
1485
- if (this.legendDOM) {
1486
- this.legendDOM.style.display = 'block';
1487
- }
1488
- },
1489
-
1490
- /**
1491
- * Hide legend components by manipulating css
1492
- *
1493
- * @returns {undefined}
1494
- */
1495
- hideLegend() {
1496
- const opt = this.options;
1497
- const wrapperStyle = this.wrapperDOM?.style;
1498
- const resizeStyle = this.resizeDOM?.style;
1499
- const legendStyle = this.legendDOM?.style;
1500
- const title = opt?.title?.show ? opt?.title?.height : 0;
1501
-
1502
- if (!legendStyle || !wrapperStyle) {
1503
- return;
1504
- }
1505
-
1506
- if (resizeStyle) {
1507
- resizeStyle.display = 'none';
1508
- }
1509
-
1510
- legendStyle.display = 'none';
1511
- legendStyle.width = '0';
1512
- legendStyle.height = '0';
1513
- wrapperStyle.padding = `${title}px 0 0 0`;
1514
- },
1515
-
1516
- /**
1517
- * Get formatted value by formatter function
1518
- * Only chartOption > legend > table > use : true
1519
- * @param formatter
1520
- * @param decimalPoint
1521
- * @param value
1522
- * @returns {string}
1523
- */
1524
- getFormattedValue({ formatter, decimalPoint }, value) {
1525
- if (value === undefined || value === null) {
1526
- return 'Null';
1527
- }
1528
-
1529
- let formattedTxt;
1530
- if (formatter) {
1531
- formattedTxt = formatter(+value);
1532
- }
1533
-
1534
- if (!formatter || typeof formattedTxt !== 'string') {
1535
- formattedTxt = Util.labelSignFormat(+value, decimalPoint);
1536
- }
1537
-
1538
- return formattedTxt;
1539
- },
1540
-
1541
- };
1542
-
1543
- export default modules;