evui 3.4.131 → 3.4.133
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/evui.common.js +1451 -1246
- package/dist/evui.common.js.map +1 -1
- package/dist/evui.umd.js +1451 -1246
- package/dist/evui.umd.js.map +1 -1
- package/dist/evui.umd.min.js +1 -1
- package/dist/evui.umd.min.js.map +1 -1
- package/package.json +1 -1
- package/src/components/chart/element/element.line.js +14 -13
- package/src/components/chart/plugins/plugins.interaction.js +37 -66
- package/src/components/chart/plugins/plugins.legend.js +265 -72
- package/src/components/chart/uses.js +1 -0
- package/src/components/select/uses.js +4 -2
package/package.json
CHANGED
|
@@ -341,7 +341,7 @@ class Line {
|
|
|
341
341
|
item.hit = true;
|
|
342
342
|
}
|
|
343
343
|
}
|
|
344
|
-
} else if (typeof this.beforeFindItemIndex === 'number' && this.show && useSelectLabelOrItem) {
|
|
344
|
+
} else if (typeof this.beforeFindItemIndex === 'number' && this.beforeFindItemIndex !== -1 && this.show && useSelectLabelOrItem) {
|
|
345
345
|
item.data = gdata[this.beforeFindItemIndex];
|
|
346
346
|
item.index = this.beforeFindItemIndex;
|
|
347
347
|
} else {
|
|
@@ -434,27 +434,28 @@ class Line {
|
|
|
434
434
|
}
|
|
435
435
|
|
|
436
436
|
// 두 가지 임계값 설정
|
|
437
|
-
const
|
|
438
|
-
const relaxedThreshold = avgInterval; // 느슨한 임계값: 데이터 간격 전체
|
|
437
|
+
const threshold = Math.max(avgInterval, 1);
|
|
439
438
|
|
|
440
439
|
// 1. 먼저 엄격한 임계값으로 정확한 매치 확인
|
|
441
|
-
if (closestXDistance <=
|
|
440
|
+
if (closestXDistance <= threshold) {
|
|
442
441
|
// 정확히 일치하거나 매우 가까운 데이터가 있음
|
|
443
442
|
item.data = gdata[closestIndex];
|
|
444
443
|
item.index = closestIndex;
|
|
445
444
|
} else {
|
|
446
|
-
// 2. 정확한 매치가 없을 때, 현재 X 위치 근처에 다른
|
|
447
|
-
let
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
445
|
+
// 2. 정확한 매치가 없을 때, 현재 X 위치 근처에 다른 데이터가 있는지 확인
|
|
446
|
+
let hasNearbyAnyData = false;
|
|
447
|
+
let closestDistance = isLinearInterpolation ? Infinity : threshold;
|
|
448
|
+
const dataSet = isLinearInterpolation ? validData : gdata;
|
|
449
|
+
for (let i = 0; i < dataSet.length; i++) {
|
|
450
|
+
const xDist = Math.abs(xp - dataSet[i].xp);
|
|
451
|
+
if (xDist <= closestDistance) {
|
|
452
|
+
hasNearbyAnyData = true;
|
|
453
|
+
closestDistance = xDist;
|
|
454
|
+
closestIndex = isLinearInterpolation ? dataSet[i].originalIndex : i;
|
|
453
455
|
}
|
|
454
456
|
}
|
|
455
457
|
|
|
456
|
-
|
|
457
|
-
if (!hasNearbyValidData && closestXDistance <= relaxedThreshold) {
|
|
458
|
+
if (hasNearbyAnyData) {
|
|
458
459
|
item.data = gdata[closestIndex];
|
|
459
460
|
item.index = closestIndex;
|
|
460
461
|
}
|
|
@@ -317,7 +317,6 @@ const modules = {
|
|
|
317
317
|
};
|
|
318
318
|
|
|
319
319
|
const setSelectedLabelInfo = (targetAxis) => {
|
|
320
|
-
const itemHitInfo = this.getItemByPosition(offset, false);
|
|
321
320
|
const {
|
|
322
321
|
labelIndex: clickedLabelIndex,
|
|
323
322
|
} = this.getLabelInfoByPosition(offset, targetAxis);
|
|
@@ -336,8 +335,8 @@ const modules = {
|
|
|
336
335
|
eventTarget: 'label',
|
|
337
336
|
...cloneDeep(this.defaultSelectInfo),
|
|
338
337
|
};
|
|
339
|
-
args.label =
|
|
340
|
-
args.dataIndex =
|
|
338
|
+
args.label = this.defaultSelectInfo?.label?.at(0);
|
|
339
|
+
args.dataIndex = this.defaultSelectInfo?.dataIndex?.at(0);
|
|
341
340
|
};
|
|
342
341
|
|
|
343
342
|
const setSelectedSeriesInfo = () => {
|
|
@@ -906,75 +905,16 @@ const modules = {
|
|
|
906
905
|
let maxg = null;
|
|
907
906
|
let maxSID = null;
|
|
908
907
|
|
|
909
|
-
// 파이 차트는 특별한 처리가 필요
|
|
910
|
-
if (this.options.type === 'pie') {
|
|
911
|
-
for (let ix = 0; ix < sIds.length; ix++) {
|
|
912
|
-
const sId = sIds[ix];
|
|
913
|
-
const series = this.seriesList[sId];
|
|
914
|
-
|
|
915
|
-
if (series.findGraphData && series.show) {
|
|
916
|
-
const item = series.findGraphData(offset);
|
|
917
|
-
|
|
918
|
-
if (item?.data && item.hit) {
|
|
919
|
-
const gdata = item.data.o;
|
|
920
|
-
|
|
921
|
-
if (gdata !== null && gdata !== undefined) {
|
|
922
|
-
const formattedSeriesName = this.getFormattedTooltipLabel({
|
|
923
|
-
dataId: series.id,
|
|
924
|
-
seriesId: sId,
|
|
925
|
-
seriesName: series.name,
|
|
926
|
-
itemData: item.data,
|
|
927
|
-
});
|
|
928
|
-
const sw = ctx ? ctx.measureText(formattedSeriesName).width : 1;
|
|
929
|
-
|
|
930
|
-
item.id = series.id;
|
|
931
|
-
item.name = formattedSeriesName;
|
|
932
|
-
item.axis = { x: 0, y: 0 };
|
|
933
|
-
items[sId] = item;
|
|
934
|
-
|
|
935
|
-
const formattedTxt = this.getFormattedTooltipValue({
|
|
936
|
-
dataId: series.id,
|
|
937
|
-
seriesId: sId,
|
|
938
|
-
seriesName: formattedSeriesName,
|
|
939
|
-
value: gdata,
|
|
940
|
-
itemData: item.data,
|
|
941
|
-
});
|
|
942
|
-
|
|
943
|
-
item.data.formatted = formattedTxt;
|
|
944
|
-
|
|
945
|
-
if (maxsw < sw) {
|
|
946
|
-
maxs = formattedSeriesName;
|
|
947
|
-
maxsw = sw;
|
|
948
|
-
}
|
|
949
|
-
|
|
950
|
-
if (maxv.length <= `${formattedTxt}`.length) {
|
|
951
|
-
maxv = `${formattedTxt}`;
|
|
952
|
-
}
|
|
953
|
-
|
|
954
|
-
if (maxg === null || maxg <= gdata) {
|
|
955
|
-
maxg = gdata;
|
|
956
|
-
maxSID = sId;
|
|
957
|
-
}
|
|
958
|
-
|
|
959
|
-
hitId = sId;
|
|
960
|
-
}
|
|
961
|
-
}
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
const maxHighlight = maxg !== null ? [maxSID, maxg] : null;
|
|
966
|
-
return { items, hitId, maxTip: [maxs, maxv], maxHighlight };
|
|
967
|
-
}
|
|
968
|
-
|
|
969
908
|
// 1. 먼저 공통으로 사용할 데이터 인덱스 결정
|
|
970
909
|
const targetDataIndex = this.findClosestDataIndex(offset, sIds);
|
|
971
910
|
|
|
972
|
-
if (targetDataIndex === -1) {
|
|
911
|
+
if (targetDataIndex === -1 && this.options.type !== 'pie') {
|
|
973
912
|
return { items, hitId, maxTip: [maxs, maxv], maxHighlight: null };
|
|
974
913
|
}
|
|
975
914
|
|
|
976
915
|
// 2. 모든 시리즈가 동일한 데이터 인덱스 사용
|
|
977
916
|
const allSeriesIsBar = sIds.every(sId => this.seriesList[sId].type === 'bar');
|
|
917
|
+
|
|
978
918
|
for (let ix = 0; ix < sIds.length; ix++) {
|
|
979
919
|
const sId = sIds[ix];
|
|
980
920
|
const series = this.seriesList[sId];
|
|
@@ -1056,8 +996,6 @@ const modules = {
|
|
|
1056
996
|
const [xp, yp] = offset;
|
|
1057
997
|
const isHorizontal = !!this.options.horizontal;
|
|
1058
998
|
const mousePos = isHorizontal ? yp : xp;
|
|
1059
|
-
let closestDistance = Infinity;
|
|
1060
|
-
let closestIndex = -1;
|
|
1061
999
|
|
|
1062
1000
|
// 첫 번째 표시 중인 시리즈를 기준으로 라벨 위치 확인
|
|
1063
1001
|
const referenceSeries = sIds.find(sId => this.seriesList[sId]?.show);
|
|
@@ -1067,6 +1005,39 @@ const modules = {
|
|
|
1067
1005
|
|
|
1068
1006
|
const referenceData = this.seriesList[referenceSeries].data;
|
|
1069
1007
|
|
|
1008
|
+
// 데이터 간격 계산 - 모든 데이터(null 포함)의 평균 간격 사용
|
|
1009
|
+
let avgInterval = 50;
|
|
1010
|
+
if (referenceData.length > 1) {
|
|
1011
|
+
const intervals = [];
|
|
1012
|
+
for (let i = 1; i < referenceData.length; i++) {
|
|
1013
|
+
const prevPoint = referenceData[i - 1];
|
|
1014
|
+
const currPoint = referenceData[i];
|
|
1015
|
+
if (prevPoint && currPoint) {
|
|
1016
|
+
let prevPos;
|
|
1017
|
+
let currPos;
|
|
1018
|
+
|
|
1019
|
+
if (isHorizontal) {
|
|
1020
|
+
prevPos = prevPoint.h ? prevPoint.yp + (prevPoint.h / 2) : prevPoint.yp;
|
|
1021
|
+
currPos = currPoint.h ? currPoint.yp + (currPoint.h / 2) : currPoint.yp;
|
|
1022
|
+
} else {
|
|
1023
|
+
prevPos = prevPoint.w ? prevPoint.xp + (prevPoint.w / 2) : prevPoint.xp;
|
|
1024
|
+
currPos = currPoint.w ? currPoint.xp + (currPoint.w / 2) : currPoint.xp;
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
if (prevPos !== null && currPos !== null) {
|
|
1028
|
+
intervals.push(Math.abs(currPos - prevPos));
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
if (intervals.length > 0) {
|
|
1033
|
+
avgInterval = intervals.reduce((a, b) => a + b, 0) / intervals.length;
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
let closestDistance = this.seriesList?.[referenceSeries]?.useLinearInterpolation?.()
|
|
1038
|
+
? Infinity : avgInterval;
|
|
1039
|
+
let closestIndex = -1;
|
|
1040
|
+
|
|
1070
1041
|
// 각 라벨에서 가장 가까운 것 찾기
|
|
1071
1042
|
for (let i = 0; i < referenceData.length; i++) {
|
|
1072
1043
|
// 이 라벨에 유효한 데이터가 있는 시리즈가 하나 이상 있는지 확인
|
|
@@ -206,15 +206,10 @@ const modules = {
|
|
|
206
206
|
const { groups } = this.data;
|
|
207
207
|
const { seriesList } = this;
|
|
208
208
|
|
|
209
|
-
if (this.options.legend.virtualScroll) {
|
|
210
|
-
|
|
211
|
-
this.
|
|
212
|
-
|
|
213
|
-
} else {
|
|
214
|
-
this.renderVisibleLegendsFrameId = requestAnimationFrame(() => {
|
|
215
|
-
this.renderVisibleLegends();
|
|
216
|
-
});
|
|
217
|
-
}
|
|
209
|
+
if (this.options.legend.virtualScroll && !this.useTable) {
|
|
210
|
+
this.renderVisibleLegendsFrameId = requestAnimationFrame(() => {
|
|
211
|
+
this.renderVisibleLegends();
|
|
212
|
+
});
|
|
218
213
|
} else {
|
|
219
214
|
this.addLegendForGroups(groups, seriesList, this.useTable);
|
|
220
215
|
this.addStandaloneLegends(seriesList, this.useTable);
|
|
@@ -362,19 +357,116 @@ const modules = {
|
|
|
362
357
|
}
|
|
363
358
|
|
|
364
359
|
const classList = {
|
|
365
|
-
container: `ev-chart-legend${this.useTable ? '--
|
|
360
|
+
container: `ev-chart-legend${this.useTable ? '--table__row' : '-container'}`,
|
|
366
361
|
color: `ev-chart-legend${this.useTable ? '--table__color' : '-color'}`,
|
|
367
362
|
name: `ev-chart-legend${this.useTable ? '--table__name' : '-name'}`,
|
|
368
363
|
value: `ev-chart-legend${this.useTable ? '--table__value' : '-value'}`,
|
|
369
364
|
};
|
|
370
365
|
|
|
366
|
+
/**
|
|
367
|
+
* callback for legendBoxDOM to show/hide clicked series
|
|
368
|
+
*
|
|
369
|
+
* @param {Element} _targetDOM - target DOM
|
|
370
|
+
* @param {string} _inactiveColor - inactive color
|
|
371
|
+
* @returns {void}
|
|
372
|
+
*/
|
|
373
|
+
const inactiveDomAndSeries = (_targetDOM, _inactiveColor) => {
|
|
374
|
+
const _colorDOM = _targetDOM?.getElementsByClassName(classList.color)[0];
|
|
375
|
+
const _nameDOM = _targetDOM?.getElementsByClassName(classList.name)[0];
|
|
376
|
+
const _valueDOMList = _targetDOM?.getElementsByClassName(classList.value);
|
|
377
|
+
const _series = _targetDOM?.series;
|
|
378
|
+
|
|
379
|
+
_colorDOM.style.backgroundColor = _inactiveColor;
|
|
380
|
+
_colorDOM.style.borderColor = _inactiveColor;
|
|
381
|
+
_nameDOM.style.color = _inactiveColor;
|
|
382
|
+
_valueDOMList?.forEach((dom) => {
|
|
383
|
+
dom.style.color = _inactiveColor;
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
_series.show = false;
|
|
387
|
+
_targetDOM.dataset.inactive = true;
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* callback for legendBoxDOM to show/hide clicked series
|
|
392
|
+
*
|
|
393
|
+
* @param {Element} _targetDOM - target DOM
|
|
394
|
+
* @param {string} _activeColor - active color
|
|
395
|
+
* @returns {void}
|
|
396
|
+
*/
|
|
397
|
+
const activeDomAndSeries = (_targetDOM, _activeColor) => {
|
|
398
|
+
let seriesColor;
|
|
399
|
+
|
|
400
|
+
const _colorDOM = _targetDOM?.getElementsByClassName(classList.color)[0];
|
|
401
|
+
const _nameDOM = _targetDOM?.getElementsByClassName(classList.name)[0];
|
|
402
|
+
const _valueDOMList = _targetDOM?.getElementsByClassName(classList.value);
|
|
403
|
+
const _series = _targetDOM?.series;
|
|
404
|
+
|
|
405
|
+
if (typeof _series.color !== 'string') {
|
|
406
|
+
seriesColor = _series.color[_series.color.length - 1][1];
|
|
407
|
+
} else {
|
|
408
|
+
seriesColor = _series.color;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
if (_series.type === 'line' && _series.fill) {
|
|
412
|
+
_colorDOM.style.height = '8px';
|
|
413
|
+
_colorDOM.style.backgroundColor = Util.rgbaAdjustHalfOpacity(seriesColor);
|
|
414
|
+
_colorDOM.style.border = `1px solid ${seriesColor}`;
|
|
415
|
+
} else {
|
|
416
|
+
_colorDOM.style.backgroundColor = seriesColor;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
_nameDOM.style.color = _activeColor;
|
|
420
|
+
_valueDOMList?.forEach((dom) => {
|
|
421
|
+
const style = this.options.legend.table?.columns[dom.dataset.type]?.style;
|
|
422
|
+
dom.style.color = style?.color ? style.color : _activeColor;
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
_series.show = true;
|
|
426
|
+
_targetDOM.dataset.inactive = false;
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
const hideAllSeries = () => {
|
|
430
|
+
const legendSeries = (() => {
|
|
431
|
+
if (this.data.groups.at(0)) {
|
|
432
|
+
return this.data.groups.at(0).slice().reverse()
|
|
433
|
+
.filter(sId => this.seriesList[sId].showLegend)
|
|
434
|
+
.map(sId => [sId, this.seriesList[sId]]);
|
|
435
|
+
}
|
|
436
|
+
return Object.entries(this.seriesList)
|
|
437
|
+
.filter(([, series]) => series.showLegend);
|
|
438
|
+
})();
|
|
439
|
+
legendSeries.forEach(([, s]) => {
|
|
440
|
+
s.show = false;
|
|
441
|
+
});
|
|
442
|
+
};
|
|
443
|
+
const showAllSeries = () => {
|
|
444
|
+
const legendSeries = (() => {
|
|
445
|
+
if (this.data.groups.at(0)) {
|
|
446
|
+
return this.data.groups.at(0).slice().reverse()
|
|
447
|
+
.filter(sId => this.seriesList[sId].showLegend)
|
|
448
|
+
.map(sId => [sId, this.seriesList[sId]]);
|
|
449
|
+
}
|
|
450
|
+
return Object.entries(this.seriesList)
|
|
451
|
+
.filter(([, series]) => series.showLegend);
|
|
452
|
+
})();
|
|
453
|
+
legendSeries.forEach(([, s]) => {
|
|
454
|
+
s.show = true;
|
|
455
|
+
});
|
|
456
|
+
};
|
|
457
|
+
|
|
371
458
|
/**
|
|
372
459
|
* callback for legendBoxDOM to show/hide clicked series
|
|
373
460
|
*
|
|
374
461
|
* @returns {undefined}
|
|
375
462
|
*/
|
|
463
|
+
/**
|
|
464
|
+
* 범례 박스 클릭 이벤트 핸들러
|
|
465
|
+
* 시리즈의 표시/숨김을 토글하고 범례의 시각적 상태를 변경
|
|
466
|
+
*/
|
|
376
467
|
this.onLegendBoxClick = (e) => {
|
|
377
468
|
const { legend: opt } = this.options;
|
|
469
|
+
|
|
378
470
|
if (opt?.stopClickEvt) {
|
|
379
471
|
return;
|
|
380
472
|
}
|
|
@@ -385,59 +477,63 @@ const modules = {
|
|
|
385
477
|
return;
|
|
386
478
|
}
|
|
387
479
|
|
|
388
|
-
const series = targetDOM?.series;
|
|
389
|
-
|
|
390
480
|
const colorDOM = targetDOM?.getElementsByClassName(classList.color)[0];
|
|
391
481
|
const nameDOM = targetDOM?.getElementsByClassName(classList.name)[0];
|
|
392
|
-
const
|
|
393
|
-
|
|
394
|
-
const isActive = !targetDOM?.className.includes('inactive');
|
|
395
|
-
if (isActive && this.seriesInfo.count === 1) {
|
|
396
|
-
return;
|
|
397
|
-
}
|
|
482
|
+
const isActive = targetDOM?.dataset.inactive === 'false';
|
|
398
483
|
|
|
399
484
|
if (!colorDOM || !nameDOM) {
|
|
400
485
|
return;
|
|
401
486
|
}
|
|
402
487
|
|
|
403
|
-
|
|
404
|
-
|
|
488
|
+
// clickMode active - 클릭시 활성화
|
|
489
|
+
if (opt.clickMode === 'active') {
|
|
490
|
+
const legendContainerDOMs = Array.from(
|
|
491
|
+
this.legendBoxDOM.getElementsByClassName(classList.container),
|
|
492
|
+
);
|
|
493
|
+
const isActiveAll = legendContainerDOMs.every(dom => dom.dataset.inactive === 'false');
|
|
405
494
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
495
|
+
if (isActiveAll) {
|
|
496
|
+
legendContainerDOMs.forEach((dom) => {
|
|
497
|
+
inactiveDomAndSeries(dom, opt.inactive);
|
|
498
|
+
});
|
|
499
|
+
hideAllSeries();
|
|
500
|
+
|
|
501
|
+
activeDomAndSeries(targetDOM, opt.color);
|
|
502
|
+
this.seriesInfo.count = 1;
|
|
503
|
+
} else if (isActive) {
|
|
504
|
+
inactiveDomAndSeries(targetDOM, opt.inactive);
|
|
505
|
+
this.seriesInfo.count--;
|
|
506
|
+
} else if (!isActive) {
|
|
507
|
+
activeDomAndSeries(targetDOM, opt.color);
|
|
508
|
+
this.seriesInfo.count++;
|
|
509
|
+
}
|
|
415
510
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
511
|
+
const isInactiveAll = legendContainerDOMs.every(dom => dom.dataset.inactive === 'true');
|
|
512
|
+
|
|
513
|
+
if (isInactiveAll) {
|
|
514
|
+
legendContainerDOMs.forEach((dom) => {
|
|
515
|
+
activeDomAndSeries(dom, opt.color);
|
|
516
|
+
});
|
|
517
|
+
showAllSeries();
|
|
518
|
+
this.seriesInfo.count = legendContainerDOMs.length;
|
|
421
519
|
}
|
|
520
|
+
}
|
|
422
521
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
} else {
|
|
428
|
-
colorDOM.style.backgroundColor = seriesColor;
|
|
522
|
+
// clickMode inactive - 클릭시 비활성화
|
|
523
|
+
if (opt.clickMode !== 'active') {
|
|
524
|
+
if (isActive && this.seriesInfo.count === 1) {
|
|
525
|
+
return;
|
|
429
526
|
}
|
|
430
527
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
528
|
+
if (isActive) {
|
|
529
|
+
inactiveDomAndSeries(targetDOM, opt.inactive);
|
|
530
|
+
this.seriesInfo.count--;
|
|
531
|
+
} else {
|
|
532
|
+
activeDomAndSeries(targetDOM, opt.color);
|
|
533
|
+
this.seriesInfo.count++;
|
|
534
|
+
}
|
|
436
535
|
}
|
|
437
536
|
|
|
438
|
-
series.show = !series.show;
|
|
439
|
-
targetDOM.classList.toggle('inactive');
|
|
440
|
-
|
|
441
537
|
if (this.brushSeries) {
|
|
442
538
|
const seriesList = [...this.brushSeries.list];
|
|
443
539
|
seriesList[chartIdx] = this.seriesList;
|
|
@@ -515,6 +611,73 @@ const modules = {
|
|
|
515
611
|
if (this.isInitLegend) {
|
|
516
612
|
return;
|
|
517
613
|
}
|
|
614
|
+
const classList = {
|
|
615
|
+
container: `ev-chart-legend${this.useTable ? '--table__row' : '-container'}`,
|
|
616
|
+
color: `ev-chart-legend${this.useTable ? '--table__color' : '-color'}`,
|
|
617
|
+
name: `ev-chart-legend${this.useTable ? '--table__name' : '-name'}`,
|
|
618
|
+
};
|
|
619
|
+
|
|
620
|
+
/**
|
|
621
|
+
* callback for legendBoxDOM to show/hide clicked series
|
|
622
|
+
*
|
|
623
|
+
* @param {Element} _targetDOM - target DOM
|
|
624
|
+
* @param {string} _inactiveColor - inactive color
|
|
625
|
+
* @returns {void}
|
|
626
|
+
*/
|
|
627
|
+
const inactiveDomAndSeries = (_targetDOM, _inactiveColor) => {
|
|
628
|
+
const _colorDOM = _targetDOM?.getElementsByClassName(classList.color)[0];
|
|
629
|
+
const _nameDOM = _targetDOM?.getElementsByClassName(classList.name)[0];
|
|
630
|
+
const _series = Object.values(this.seriesList)[0];
|
|
631
|
+
const targetId = _targetDOM?.series?.cId;
|
|
632
|
+
|
|
633
|
+
_colorDOM.style.backgroundColor = _inactiveColor;
|
|
634
|
+
_colorDOM.style.borderColor = _inactiveColor;
|
|
635
|
+
_nameDOM.style.color = _inactiveColor;
|
|
636
|
+
|
|
637
|
+
const targetIndex = _series.colorState.findIndex(colorItem => colorItem.id === targetId);
|
|
638
|
+
if (targetIndex > -1) {
|
|
639
|
+
_series.colorState[targetIndex].show = false;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
_targetDOM.dataset.inactive = true;
|
|
643
|
+
};
|
|
644
|
+
|
|
645
|
+
/**
|
|
646
|
+
* callback for legendBoxDOM to show/hide clicked series
|
|
647
|
+
*
|
|
648
|
+
* @param {Element} _targetDOM - target DOM
|
|
649
|
+
* @param {string} _activeColor - active color
|
|
650
|
+
* @returns {void}
|
|
651
|
+
*/
|
|
652
|
+
const activeDomAndSeries = (_targetDOM, _activeColor) => {
|
|
653
|
+
const _colorDOM = _targetDOM?.getElementsByClassName(classList.color)[0];
|
|
654
|
+
const _nameDOM = _targetDOM?.getElementsByClassName(classList.name)[0];
|
|
655
|
+
const _series = Object.values(this.seriesList)[0];
|
|
656
|
+
const targetId = _targetDOM?.series?.cId;
|
|
657
|
+
|
|
658
|
+
_colorDOM.style.backgroundColor = _targetDOM?.series?.color;
|
|
659
|
+
_nameDOM.style.color = _activeColor;
|
|
660
|
+
|
|
661
|
+
const targetIndex = _series.colorState.findIndex(colorItem => colorItem.id === targetId);
|
|
662
|
+
if (targetIndex > -1) {
|
|
663
|
+
_series.colorState[targetIndex].show = true;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
_targetDOM.dataset.inactive = false;
|
|
667
|
+
};
|
|
668
|
+
|
|
669
|
+
const hideAllSeries = () => {
|
|
670
|
+
const series = Object.values(this.seriesList)[0];
|
|
671
|
+
series.colorState.forEach((colorItem) => {
|
|
672
|
+
colorItem.show = false;
|
|
673
|
+
});
|
|
674
|
+
};
|
|
675
|
+
const showAllSeries = () => {
|
|
676
|
+
const series = Object.values(this.seriesList)[0];
|
|
677
|
+
series.colorState.forEach((colorItem) => {
|
|
678
|
+
colorItem.show = true;
|
|
679
|
+
});
|
|
680
|
+
};
|
|
518
681
|
|
|
519
682
|
/**
|
|
520
683
|
* callback for legendBoxDOM to show/hide clicked series
|
|
@@ -533,36 +696,57 @@ const modules = {
|
|
|
533
696
|
return;
|
|
534
697
|
}
|
|
535
698
|
|
|
536
|
-
const colorDOM = targetDOM?.getElementsByClassName(
|
|
537
|
-
const nameDOM = targetDOM?.getElementsByClassName(
|
|
538
|
-
const
|
|
539
|
-
const isActive = !colorDOM?.className.includes('inactive');
|
|
699
|
+
const colorDOM = targetDOM?.getElementsByClassName(classList.color)[0];
|
|
700
|
+
const nameDOM = targetDOM?.getElementsByClassName(classList.name)[0];
|
|
701
|
+
const isActive = targetDOM?.dataset.inactive === 'false';
|
|
540
702
|
const activeCount = series.colorState.filter(colorItem => colorItem.show).length;
|
|
541
703
|
|
|
542
|
-
if (isActive && activeCount === 1) {
|
|
543
|
-
return;
|
|
544
|
-
}
|
|
545
|
-
|
|
546
704
|
if (!colorDOM || !nameDOM) {
|
|
547
705
|
return;
|
|
548
706
|
}
|
|
549
707
|
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
nameDOM.style.color = opt.color;
|
|
557
|
-
}
|
|
708
|
+
// clickMode active - 클릭시 활성화
|
|
709
|
+
if (opt.clickMode === 'active') {
|
|
710
|
+
const legendContainerDOMs = Array.from(
|
|
711
|
+
this.legendBoxDOM.getElementsByClassName(classList.container),
|
|
712
|
+
);
|
|
713
|
+
const isActiveAll = legendContainerDOMs.every(dom => dom.dataset.inactive === 'false');
|
|
558
714
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
715
|
+
if (isActiveAll) {
|
|
716
|
+
legendContainerDOMs.forEach((dom) => {
|
|
717
|
+
inactiveDomAndSeries(dom, opt.inactive);
|
|
718
|
+
});
|
|
719
|
+
hideAllSeries();
|
|
720
|
+
|
|
721
|
+
activeDomAndSeries(targetDOM, opt.color);
|
|
722
|
+
} else if (isActive) {
|
|
723
|
+
inactiveDomAndSeries(targetDOM, opt.inactive);
|
|
724
|
+
} else if (!isActive) {
|
|
725
|
+
activeDomAndSeries(targetDOM, opt.color);
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
const isInactiveAll = legendContainerDOMs.every(dom => dom.dataset.inactive === 'true');
|
|
729
|
+
|
|
730
|
+
if (isInactiveAll) {
|
|
731
|
+
legendContainerDOMs.forEach((dom) => {
|
|
732
|
+
activeDomAndSeries(dom, opt.color);
|
|
733
|
+
});
|
|
734
|
+
showAllSeries();
|
|
735
|
+
}
|
|
562
736
|
}
|
|
563
737
|
|
|
564
|
-
|
|
565
|
-
|
|
738
|
+
// clickMode inactive - 클릭시 비활성화
|
|
739
|
+
if (opt.clickMode !== 'active') {
|
|
740
|
+
if (isActive && activeCount === 1) {
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
if (isActive) {
|
|
745
|
+
inactiveDomAndSeries(targetDOM, opt.inactive);
|
|
746
|
+
} else {
|
|
747
|
+
activeDomAndSeries(targetDOM, opt.color);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
566
750
|
|
|
567
751
|
this.update({
|
|
568
752
|
updateSeries: false,
|
|
@@ -791,13 +975,19 @@ const modules = {
|
|
|
791
975
|
*
|
|
792
976
|
* @returns {undefined}
|
|
793
977
|
*/
|
|
978
|
+
/**
|
|
979
|
+
* 새로운 범례 아이템을 생성하고 범례 영역에 추가
|
|
980
|
+
* @param {Object} series - 시리즈 정보 객체
|
|
981
|
+
*/
|
|
794
982
|
addLegend(series) {
|
|
795
983
|
const opt = this.options.legend;
|
|
984
|
+
|
|
796
985
|
const containerDOM = document.createElement('div');
|
|
797
986
|
const colorDOM = document.createElement('span');
|
|
798
987
|
const nameDOM = document.createElement('div');
|
|
799
988
|
|
|
800
|
-
containerDOM.className =
|
|
989
|
+
containerDOM.className = 'ev-chart-legend-container';
|
|
990
|
+
containerDOM.dataset.inactive = !series.show;
|
|
801
991
|
containerDOM.series = series;
|
|
802
992
|
|
|
803
993
|
colorDOM.className = 'ev-chart-legend-color';
|
|
@@ -808,7 +998,6 @@ const modules = {
|
|
|
808
998
|
|
|
809
999
|
nameDOM.className = 'ev-chart-legend-name';
|
|
810
1000
|
|
|
811
|
-
// set series color
|
|
812
1001
|
let seriesColor;
|
|
813
1002
|
if (!series.show) {
|
|
814
1003
|
seriesColor = opt.inactive;
|
|
@@ -828,6 +1017,7 @@ const modules = {
|
|
|
828
1017
|
}
|
|
829
1018
|
|
|
830
1019
|
colorDOM.dataset.type = 'color';
|
|
1020
|
+
|
|
831
1021
|
nameDOM.style.color = opt.color;
|
|
832
1022
|
nameDOM.textContent = series.name;
|
|
833
1023
|
nameDOM.setAttribute('title', series.name);
|
|
@@ -842,12 +1032,14 @@ const modules = {
|
|
|
842
1032
|
} else {
|
|
843
1033
|
containerDOM.style.width = '100%';
|
|
844
1034
|
}
|
|
1035
|
+
|
|
845
1036
|
containerDOM.style.height = `${this.legendItemHeight}px`;
|
|
846
1037
|
containerDOM.style.display = 'inline-block';
|
|
847
1038
|
containerDOM.style.overflow = 'hidden';
|
|
848
1039
|
containerDOM.dataset.type = 'container';
|
|
849
1040
|
|
|
850
1041
|
this.legendBoxDOM.insertBefore(containerDOM, this.legendBottomSpacer);
|
|
1042
|
+
|
|
851
1043
|
if (series.show) {
|
|
852
1044
|
this.seriesInfo.count++;
|
|
853
1045
|
}
|
|
@@ -869,7 +1061,8 @@ const modules = {
|
|
|
869
1061
|
|
|
870
1062
|
// create row
|
|
871
1063
|
const rowDOM = document.createElement('tr');
|
|
872
|
-
rowDOM.className =
|
|
1064
|
+
rowDOM.className = 'ev-chart-legend--table__row';
|
|
1065
|
+
rowDOM.dataset.inactive = !series.show;
|
|
873
1066
|
Util.setDOMStyle(rowDOM, opt.table?.style?.row);
|
|
874
1067
|
rowDOM.series = series;
|
|
875
1068
|
rowDOM.dataset.type = 'container';
|
|
@@ -300,9 +300,11 @@ export const useDropdown = (param) => {
|
|
|
300
300
|
if (props.filterable) {
|
|
301
301
|
filterTextRef.value = '';
|
|
302
302
|
}
|
|
303
|
-
mv.value = val;
|
|
304
303
|
isDropbox.value = false;
|
|
305
|
-
|
|
304
|
+
if (mv.value !== val) {
|
|
305
|
+
mv.value = val;
|
|
306
|
+
changeMv();
|
|
307
|
+
}
|
|
306
308
|
};
|
|
307
309
|
const multipleClickItem = (val) => {
|
|
308
310
|
if (props.filterable) {
|