evui 3.3.25 → 3.3.28

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "evui",
3
- "version": "3.3.25",
3
+ "version": "3.3.28",
4
4
  "description": "A EXEM Library project",
5
5
  "author": "exem <dev_client@ex-em.com>",
6
6
  "license": "MIT",
@@ -12,7 +12,7 @@
12
12
  "test:unit": "vue-cli-service test:unit",
13
13
  "lint": "eslint src test docs",
14
14
  "docs": "vue-cli-service serve --port 9999 docs/main.js",
15
- "docs_build": "vue-cli-service build docs/main.js"
15
+ "docs_build": "vue-cli-service build --mode production docs/main.js"
16
16
  },
17
17
  "files": [
18
18
  "dist",
@@ -44,6 +44,7 @@
44
44
  "eslint-config-exem": "^3.0.3",
45
45
  "eslint-plugin-import": "^2.21.2",
46
46
  "eslint-plugin-vue": "^7.0.0-0",
47
+ "gh-pages": "^4.0.0",
47
48
  "highlight.js": "^10.2.0",
48
49
  "lodash-es": "^4.17.15",
49
50
  "marked": "^1.1.1",
@@ -307,7 +307,7 @@ export default {
307
307
  const timeReg = new RegExp(/(HH|2[0-3]|[01][0-9]):(mm|[0-5][0-9]):(ss|[0-5][0-9])/);
308
308
  return (multiType ? ['weekday', 'week', 'date'].indexOf(multiType) !== -1 : true)
309
309
  && (multiDayLimit ? typeof multiDayLimit === 'number' && multiDayLimit > 0 : true)
310
- && (disabledDate ? typeof disabledDate === 'function' : true)
310
+ && (disabledDate ? (typeof disabledDate === 'function' || Array.isArray(disabledDate)) : true)
311
311
  && Array.isArray(timeFormat)
312
312
  ? timeFormat.every(v => !!(!v || timeReg.exec(v)))
313
313
  : !!(!timeFormat || (timeReg.exec(timeFormat)));
@@ -349,7 +349,6 @@ export default {
349
349
  clickTime,
350
350
  wheelMonth,
351
351
  wheelTime,
352
- resetCalendarInfo,
353
352
  calendarEventName,
354
353
  onMousemoveDate,
355
354
  preventTimeEventType,
@@ -357,6 +356,8 @@ export default {
357
356
  selectedValue,
358
357
  mainCalendarPageInfo,
359
358
  expandedCalendarPageInfo,
359
+ mainTimeTableInfo,
360
+ expandedTimeTableInfo,
360
361
  setCalendarDate,
361
362
  setHmsTime,
362
363
  });
@@ -391,7 +392,6 @@ export default {
391
392
  clickTime,
392
393
  wheelMonth,
393
394
  wheelTime,
394
- resetCalendarInfo,
395
395
  calendarEventName,
396
396
  onMousemoveDate,
397
397
  preventTimeEventType,
@@ -206,6 +206,10 @@ const getTimeInfoByTimeFormat = (timeFormat, dateTimeValue, typeToImport) => {
206
206
  * @returns string
207
207
  */
208
208
  export const getChangedValueByTimeFormat = (timeFormat, modelValue) => {
209
+ if (!modelValue) {
210
+ return '';
211
+ }
212
+
209
213
  const hourByTimeFormat = lpadToTwoDigits(getTimeInfoByTimeFormat(timeFormat, modelValue, 'hour'));
210
214
  const minByTimeFormat = lpadToTwoDigits(getTimeInfoByTimeFormat(timeFormat, modelValue, 'min'));
211
215
  const secByTimeFormat = lpadToTwoDigits(getTimeInfoByTimeFormat(timeFormat, modelValue, 'sec'));
@@ -224,8 +228,8 @@ const compareFromAndToDateTime = (mode, calendarType, targetDate, modelValue) =>
224
228
  let toDateTime = toDate;
225
229
  if (!targetDate.split(' ')[1]) {
226
230
  if (mode === 'dateTimeRange') {
227
- fromDate = fromDateTime.split(' ')[0];
228
- toDate = toDateTime.split(' ')[0];
231
+ fromDate = fromDate.split(' ')[0];
232
+ toDate = toDate.split(' ')[0];
229
233
  const fromTime = modelValue[0].split(' ')[1];
230
234
  const toTime = modelValue[1].split(' ')[1];
231
235
  fromDateTime = `${fromDate} ${fromTime}`;
@@ -236,7 +240,8 @@ const compareFromAndToDateTime = (mode, calendarType, targetDate, modelValue) =>
236
240
  }
237
241
  }
238
242
 
239
- return new Date(fromDateTime).getTime() > +new Date(toDateTime).getTime();
243
+ return (fromDateTime && toDateTime)
244
+ && new Date(fromDateTime).getTime() > +new Date(toDateTime).getTime();
240
245
  };
241
246
 
242
247
  /**
@@ -303,16 +308,12 @@ export const useModel = () => {
303
308
  } else if (props.mode === 'dateRange' && props.modelValue) {
304
309
  if (!Array.isArray(props.modelValue)) {
305
310
  console.warn('[EVUI][Calendar] When mode is \'dateRange\', v-model must be \'Array\' type.');
306
- } else if (props.modelValue.length !== 0 && props.modelValue.length !== 2) {
307
- console.warn('[EVUI][Calendar] When mode is \'dateRange\', v-model\'s length is 0 or 2.');
308
311
  } else if (getDateMs(`${props.modelValue[0]} 00:00:00`) > getDateMs(`${props.modelValue[1]} 00:00:00`)) {
309
312
  console.warn('[EVUI][Calendar] When mode is \'dateRange\', fromDate must be less than toDate.');
310
313
  }
311
314
  } else if (props.mode === 'dateTimeRange' && props.modelValue) {
312
315
  if (!Array.isArray(props.modelValue)) {
313
316
  console.warn('[EVUI][Calendar] When mode is \'dateTimeRange\', v-model must be \'Array\' type.');
314
- } else if (props.modelValue.length !== 0 && props.modelValue.length !== 2) {
315
- console.warn('[EVUI][Calendar] When mode is \'dateRange\', v-model\'s length is 0 or 2.');
316
317
  } else if (getDateMs(props.modelValue[0]) > getDateMs(props.modelValue[1])) {
317
318
  console.warn('[EVUI][Calendar] When mode is \'dateRange\', fromDate must be less than toDate.');
318
319
  }
@@ -322,10 +323,10 @@ export const useModel = () => {
322
323
  // 메인(좌측) 달력(연, 월, 시, 분, 초) 페이징 정보
323
324
  let mainCalendarPageInfo;
324
325
  const mainValue = !['dateRange', 'dateTimeRange'].includes(props.mode) ? selectedValue.value : selectedValue.value[0];
325
- if (props.mode) {
326
+ if (mainValue?.length) {
326
327
  mainCalendarPageInfo = reactive({
327
- year: getDateTimeInfoByType(mainValue, 'year') || new Date().getFullYear(),
328
- month: getDateTimeInfoByType(mainValue, 'month') || new Date().getMonth() + 1,
328
+ year: getDateTimeInfoByType(mainValue, 'year'),
329
+ month: getDateTimeInfoByType(mainValue, 'month'),
329
330
  hour: Math.floor(getDateTimeInfoByType(mainValue, 'hour') / CELL_CNT_IN_ONE_PAGE) + 1 || 1,
330
331
  min: Math.floor(getDateTimeInfoByType(mainValue, 'min') / CELL_CNT_IN_ONE_PAGE) + 1 || 1,
331
332
  sec: Math.floor(getDateTimeInfoByType(mainValue, 'sec') / CELL_CNT_IN_ONE_PAGE) + 1 || 1,
@@ -334,6 +335,9 @@ export const useModel = () => {
334
335
  mainCalendarPageInfo = reactive({
335
336
  year: new Date().getFullYear(),
336
337
  month: new Date().getMonth() + 1,
338
+ hour: 1,
339
+ min: 1,
340
+ sec: 1,
337
341
  });
338
342
  }
339
343
 
@@ -356,17 +360,13 @@ export const useModel = () => {
356
360
  expandedCalendarPageInfo.sec = Math.floor(getDateTimeInfoByType(expandedValue, 'sec') / CELL_CNT_IN_ONE_PAGE) + 1 || 1;
357
361
  }
358
362
  } else {
359
- expandedCalendarPageInfo = reactive(getSideMonthCalendarInfo(
360
- 'next',
361
- mainCalendarPageInfo.year,
362
- mainCalendarPageInfo.month,
363
- ));
364
-
365
- if (props.mode === 'dateTimeRange') {
366
- expandedCalendarPageInfo.hour = 1;
367
- expandedCalendarPageInfo.min = 1;
368
- expandedCalendarPageInfo.sec = 1;
369
- }
363
+ expandedCalendarPageInfo = reactive({
364
+ year: new Date().getFullYear(),
365
+ month: new Date().getMonth() + 1,
366
+ hour: 1,
367
+ min: 1,
368
+ sec: 1,
369
+ });
370
370
  }
371
371
 
372
372
  // 현재 달력이 표현되는 월
@@ -401,7 +401,7 @@ export const useModel = () => {
401
401
  };
402
402
 
403
403
  export const useCalendarDate = (param) => {
404
- const { props } = getCurrentInstance();
404
+ const { props, emit } = getCurrentInstance();
405
405
  const { selectedValue, mainCalendarPageInfo, expandedCalendarPageInfo } = param;
406
406
 
407
407
  // 메인 달력 테이블의 날짜 정보 (6X7, 2차원배열)
@@ -421,6 +421,42 @@ export const useCalendarDate = (param) => {
421
421
  sec: [],
422
422
  });
423
423
 
424
+ /**
425
+ * calendar setting 하기 전 선택된 날짜가 disabledDate에 포함되는지 체크
426
+ * @param isRangeMode
427
+ * @param calendarType
428
+ * @param disabledDate
429
+ */
430
+ const checkDisabledDate = ({ isRangeMode, calendarType, disabledDate }) => {
431
+ if (isRangeMode) {
432
+ if (calendarType === 'main' && selectedValue.value[0]) {
433
+ if (disabledDate && disabledDate(new Date(selectedValue.value[0]))) {
434
+ selectedValue.value[0] = '';
435
+ emit('update:modelValue', [...selectedValue.value]);
436
+ }
437
+ } else if (calendarType === 'expanded' && selectedValue.value[1]) {
438
+ if (disabledDate && disabledDate(new Date(selectedValue.value[1]))) {
439
+ selectedValue.value[1] = '';
440
+ emit('update:modelValue', [...selectedValue.value]);
441
+ }
442
+ }
443
+ } else if (props.mode === 'dateMulti') {
444
+ let isUpdate = false;
445
+ selectedValue.value.forEach((value, index) => {
446
+ if (disabledDate && disabledDate(new Date(value))) {
447
+ selectedValue.value.splice(index, 1);
448
+ isUpdate = true;
449
+ }
450
+ });
451
+ if (isUpdate) {
452
+ emit('update:modelValue', [...selectedValue.value]);
453
+ }
454
+ } else if (disabledDate && disabledDate(new Date(selectedValue.value))) {
455
+ selectedValue.value = '';
456
+ emit('update:modelValue', selectedValue.value);
457
+ }
458
+ };
459
+
424
460
  /**
425
461
  * Dropdown Calendar 날짜 정보 세팅하기
426
462
  * @param calendarType - 달력 종류 ('main'|'expanded')
@@ -430,7 +466,18 @@ export const useCalendarDate = (param) => {
430
466
  ? expandedCalendarPageInfo : mainCalendarPageInfo;
431
467
  const calendarTableInfo = calendarType === 'expanded'
432
468
  ? expandedCalendarTableInfo : mainCalendarTableInfo;
433
- const disabledDate = props.options.disabledDate;
469
+
470
+ let disabledDate = props.options.disabledDate;
471
+ if (disabledDate && Array.isArray(disabledDate)) {
472
+ disabledDate = calendarType === 'main' ? disabledDate[0] : disabledDate[1];
473
+ }
474
+ const isRangeMode = ['dateRange', 'dateTimeRange'].includes(props.mode);
475
+
476
+ checkDisabledDate({
477
+ isRangeMode,
478
+ calendarType,
479
+ disabledDate,
480
+ });
434
481
 
435
482
  const TODAY_YMD = formatDateTime({
436
483
  year: new Date().getFullYear(),
@@ -462,6 +509,15 @@ export const useCalendarDate = (param) => {
462
509
  calendarPageInfo.month,
463
510
  ));
464
511
 
512
+ let modelValue = '';
513
+ if (props.mode.includes('Time')) {
514
+ if (props.mode === 'dateTime') {
515
+ modelValue = selectedValue.value;
516
+ } else {
517
+ modelValue = calendarType === 'main' ? selectedValue.value[0] : selectedValue.value[1];
518
+ }
519
+ }
520
+
465
521
  let monthDate = 0;
466
522
  let year = 0;
467
523
  let month = 0;
@@ -470,22 +526,26 @@ export const useCalendarDate = (param) => {
470
526
  // date 숫자 및 속성 세팅
471
527
  const setDateInfo = (monthType, i, j) => {
472
528
  currDate = formatDateTime({ year, month, date });
473
- const isRangeMode = ['dateRange', 'dateTimeRange'].includes(props.mode);
474
- const isDisabled = disabledDate ? disabledDate(new Date(currDate)) : false;
475
529
  const isInvalidDate = isRangeMode
476
530
  && compareFromAndToDateTime(props.mode, calendarType, currDate, selectedValue.value);
477
531
 
478
- const index = calendarType !== 'main' | 0;
532
+ // time 모드인 경우 현재 값의 시간을 가지고 테스트
533
+ const timeValue = modelValue?.split(' ')[1] ?? '';
534
+
535
+ const isDisabled = disabledDate && disabledDate(new Date(`${currDate} ${timeValue}`));
536
+
537
+ const index = +(calendarType !== 'main');
479
538
  const isRangeSelected = isRangeMode && selectedValue.value.length > index
480
539
  && selectedValue.value[index].split(' ')[0].includes(currDate);
540
+ const isSelected = !isDisabled && (isRangeMode
541
+ ? monthType === '' && isRangeSelected
542
+ : selectedValue.value?.includes(currDate));
481
543
 
482
544
  // mode가 dateRange일 때는 이전, 다음달에 selected 를 하지 않는다.
483
545
  calendarTableInfo[i][j] = {
484
546
  monthType: `${monthType}${isDisabled || isInvalidDate ? ' disabled' : ''}`,
485
547
  isToday: TODAY_YMD === currDate,
486
- isSelected: isRangeMode
487
- ? monthType === '' && isRangeSelected
488
- : selectedValue.value?.includes(currDate),
548
+ isSelected,
489
549
  year,
490
550
  month,
491
551
  date,
@@ -539,13 +599,17 @@ export const useCalendarDate = (param) => {
539
599
  */
540
600
  const setHmsTime = () => {
541
601
  const timeFormat = props.options?.timeFormat;
602
+ const disabledDate = props.options?.disabledDate;
542
603
  const mainTimeFormat = Array.isArray(timeFormat) ? timeFormat[0] : timeFormat;
543
604
  const expandedTimeFormat = Array.isArray(timeFormat) ? timeFormat[1] : '';
544
605
  const mainDateTimeValue = props.mode === 'dateTimeRange' ? selectedValue.value[0] : selectedValue.value;
545
606
  const expandedDateTimeValue = props.mode === 'dateTimeRange' ? selectedValue.value[1] : '';
607
+ const mainDisabledDate = Array.isArray(disabledDate) ? disabledDate[0] : disabledDate;
608
+ const expandedDisabledDate = Array.isArray(disabledDate) ? disabledDate[1] : disabledDate;
546
609
 
547
610
  const compareDateTimeValue = (calendarType, timeType, value) => {
548
611
  const dateTimeValue = calendarType === 'main' ? mainDateTimeValue : expandedDateTimeValue;
612
+ const disabledDateFunc = calendarType === 'main' ? mainDisabledDate : expandedDisabledDate;
549
613
  if (!dateTimeValue) {
550
614
  return false;
551
615
  }
@@ -564,6 +628,10 @@ export const useCalendarDate = (param) => {
564
628
  }
565
629
 
566
630
  const targetDateTimeValue = `${date} ${lpadToTwoDigits(hour)}:${lpadToTwoDigits(min)}:${lpadToTwoDigits(sec)}`;
631
+ if (disabledDateFunc && disabledDateFunc(new Date(targetDateTimeValue))) {
632
+ return true;
633
+ }
634
+
567
635
  return compareFromAndToDateTime(
568
636
  props.mode,
569
637
  calendarType,
@@ -584,18 +652,20 @@ export const useCalendarDate = (param) => {
584
652
  const expandedTimeValue = expandedDateTimeValue && expandedDateTimeValue.length > 0
585
653
  ? getTimeInfoByTimeFormat(expandedTimeFormat, expandedDateTimeValue, v) : -1;
586
654
  for (let i = 0; i < cnt; i++) {
587
- mainTimeTableInfo[v][i] = {
655
+ let isDisabled = props.mode === 'dateTimeRange' && compareDateTimeValue('main', v, i);
656
+ mainTimeTableInfo[v][i] = {
588
657
  timeType: v,
589
658
  num: i,
590
- isSelected: mainTimeValue === i,
591
- isDisabled: props.mode === 'dateTimeRange' && compareDateTimeValue('main', v, i),
659
+ isSelected: !isDisabled && mainTimeValue === i,
660
+ isDisabled,
592
661
  };
593
662
  if (props.mode === 'dateTimeRange') {
663
+ isDisabled = compareDateTimeValue('expanded', v, i);
594
664
  expandedTimeTableInfo[v][i] = {
595
665
  timeType: v,
596
666
  num: i,
597
- isSelected: expandedTimeValue === i,
598
- isDisabled: compareDateTimeValue('expanded', v, i),
667
+ isSelected: !isDisabled && expandedTimeValue === i,
668
+ isDisabled,
599
669
  };
600
670
  }
601
671
  }
@@ -634,12 +704,13 @@ export const useCalendarDate = (param) => {
634
704
 
635
705
  export const useEvent = (param) => {
636
706
  const { props, emit } = getCurrentInstance();
637
- const disabledDate = props.options.disabledDate;
638
707
  const timeFormat = props.options?.timeFormat;
639
708
  const {
640
709
  selectedValue,
641
710
  mainCalendarPageInfo,
642
711
  expandedCalendarPageInfo,
712
+ mainTimeTableInfo,
713
+ expandedTimeTableInfo,
643
714
  setCalendarDate,
644
715
  setHmsTime,
645
716
  } = param;
@@ -787,6 +858,11 @@ export const useEvent = (param) => {
787
858
  ? props.modelValue?.map(v => v.split(' ')[0])
788
859
  : props.modelValue.split(' ')[0])
789
860
  .includes(CURR_DATE_STR) : false;
861
+
862
+ let disabledDate = props.options.disabledDate;
863
+ if (disabledDate && Array.isArray(disabledDate)) {
864
+ disabledDate = calendarType === 'main' ? disabledDate[0] : disabledDate[1];
865
+ }
790
866
  // 제한된 날짜는 선택할 수 없다.
791
867
  if (disabledDate && disabledDate(new Date(CURR_DATE_STR)) && !isExistCurrDate) {
792
868
  return;
@@ -812,13 +888,12 @@ export const useEvent = (param) => {
812
888
 
813
889
  const setRangeModeDateByIndex = (currIndex, currDate) => {
814
890
  if (compareFromAndToDateTime(props.mode, calendarType, currDate, selectedValue.value)) {
815
- return false;
891
+ return;
816
892
  }
817
893
 
818
894
  selectedValue.value[currIndex] = currDate;
819
895
  moveDispCalendarMonth();
820
896
  updateCalendarPage(selectedValue.value);
821
- return true;
822
897
  };
823
898
 
824
899
  switch (props.mode) {
@@ -997,11 +1072,18 @@ export const useEvent = (param) => {
997
1072
 
998
1073
  const calendarPageInfo = calendarType === 'expanded'
999
1074
  ? expandedCalendarPageInfo : mainCalendarPageInfo;
1075
+ const timeInfo = calendarType === 'main'
1076
+ ? mainTimeTableInfo : expandedTimeTableInfo;
1000
1077
  const currPage = calendarPageInfo[timeType] - 1;
1001
1078
  const currRowIdx = i - 1;
1002
1079
  const currColIdx = j - 1;
1003
1080
  const clickedNum = (currPage * CELL_CNT_IN_ONE_PAGE)
1004
1081
  + (currRowIdx * CELL_CNT_IN_ONE_ROW) + currColIdx;
1082
+
1083
+ if (timeInfo[timeType][clickedNum]?.isDisabled) {
1084
+ return;
1085
+ }
1086
+
1005
1087
  const TODAY = new Date();
1006
1088
  const TODAY_INFO = {
1007
1089
  year: TODAY.getFullYear(),
@@ -1164,31 +1246,22 @@ export const useEvent = (param) => {
1164
1246
  }
1165
1247
  }, 10);
1166
1248
 
1167
- /**
1168
- * Calendar Info 전체 업데이트
1169
- */
1170
- const resetCalendarInfo = () => {
1171
- let valueListByUpdatePage = [];
1172
-
1173
- if (['date', 'dateTime'].includes(props.mode)) {
1174
- valueListByUpdatePage.push(selectedValue.value);
1175
- } else {
1176
- valueListByUpdatePage = selectedValue.value;
1177
- }
1178
-
1179
- if (['dateTime', 'dateTimeRange'].includes(props.mode)) {
1180
- updateCalendarPage(valueListByUpdatePage);
1181
- setHmsTime();
1182
- }
1183
- };
1184
-
1185
1249
  watch(
1186
- () => props.modelValue,
1187
- (curr) => {
1188
- selectedValue.value = curr;
1189
- resetCalendarInfo();
1190
- },
1191
- );
1250
+ () => props.modelValue,
1251
+ (curr) => {
1252
+ selectedValue.value = curr;
1253
+
1254
+ if (props.mode.includes('Time')) {
1255
+ let updateValue = [];
1256
+ if (props.mode === 'dateTime') {
1257
+ updateValue = [selectedValue.value];
1258
+ } else if (props.mode === 'dateTimeRange') {
1259
+ updateValue = selectedValue.value;
1260
+ }
1261
+ updateCalendarPage(updateValue);
1262
+ setHmsTime();
1263
+ }
1264
+ });
1192
1265
 
1193
1266
  return {
1194
1267
  clickPrevNextBtn,
@@ -1197,7 +1270,6 @@ export const useEvent = (param) => {
1197
1270
  clickTime,
1198
1271
  wheelMonth,
1199
1272
  wheelTime,
1200
- resetCalendarInfo,
1201
1273
  calendarEventName,
1202
1274
  onMousemoveDate,
1203
1275
  preventTimeEventType,
@@ -122,14 +122,21 @@ class EvChart {
122
122
  initRect() {
123
123
  const opt = this.options;
124
124
  if (opt.title.show) {
125
- this.initTitle();
125
+ if (!this.isInitTitle) {
126
+ this.initTitle();
127
+ }
128
+
126
129
  this.showTitle();
127
130
  }
128
131
 
129
132
  if (opt.legend.show) {
130
- this.initLegend();
133
+ if (!this.isInitLegend) {
134
+ this.initLegend();
135
+ }
136
+
131
137
  this.setLegendPosition();
132
138
  }
139
+
133
140
  this.chartRect = this.getChartRect();
134
141
  }
135
142
 
@@ -755,6 +762,7 @@ class EvChart {
755
762
  this.bufferCtx.restore();
756
763
  this.bufferCtx.save();
757
764
 
765
+ this.initRect();
758
766
  this.initScale();
759
767
  this.chartRect = this.getChartRect();
760
768
  this.drawChart();
@@ -150,7 +150,10 @@ class Pie {
150
150
 
151
151
  let formattedTxt;
152
152
  if (formatter) {
153
- formattedTxt = formatter(value);
153
+ formattedTxt = formatter({
154
+ value,
155
+ percentage: this.data.percentage,
156
+ });
154
157
  }
155
158
 
156
159
  if (!formatter || typeof formattedTxt !== 'string') {
@@ -173,8 +173,6 @@ export default {
173
173
  label = assignLabelWith(value, milli, 'M');
174
174
  } else if (value >= killo) {
175
175
  label = assignLabelWith(value, 1000, 'K');
176
- } else if (value < 1 && value > 0) {
177
- label = value.toFixed(1);
178
176
  } else {
179
177
  label = value.toFixed(decimalPoint);
180
178
  }
@@ -17,32 +17,15 @@ const modules = {
17
17
  if (this.dragInfo?.isMove) {
18
18
  return;
19
19
  }
20
+
20
21
  const { indicator, tooltip, type } = this.options;
21
22
  const offset = this.getMousePosition(e);
22
23
  const hitInfo = this.findHitItem(offset);
24
+
23
25
  if (tooltip?.showAllValueInRange && hitInfo?.items) {
24
- const isHorizontal = !!this.options.horizontal;
25
- const hitItemId = Object.keys(hitInfo.items)[0];
26
- const hitItemData = isHorizontal
27
- ? hitInfo.items?.[hitItemId]?.data?.y : hitInfo.items?.[hitItemId]?.data?.x;
28
- const sIds = Object.keys(this.seriesList);
29
- for (let ix = 0; ix < sIds.length; ix++) {
30
- const sId = sIds[ix];
31
- const series = this.seriesList[sId];
32
- const hasData = series.data.find(data =>
33
- (isHorizontal ? data.y : data?.x === hitItemData));
34
- if (hasData && !hitInfo.items[sId] && series?.show) {
35
- const item = {};
36
- item.color = series.color;
37
- item.hit = false;
38
- item.name = series.name;
39
- item.axis = { x: series.xAxisIndex, y: series.yAxisIndex };
40
- item.index = isHorizontal ? series.yAxisIndex : series.xAxisIndex;
41
- item.data = hasData;
42
- hitInfo.items[sId] = item;
43
- }
44
- }
26
+ this.addNotHitInfo(hitInfo);
45
27
  }
28
+
46
29
  const ctx = this.overlayCtx;
47
30
 
48
31
  this.overlayClear();
@@ -376,10 +359,6 @@ const modules = {
376
359
  const items = {};
377
360
  const isHorizontal = !!this.options.horizontal;
378
361
  const ctx = this.tooltipCtx;
379
- const tooltipOpt = this.options.tooltip;
380
- const tooltipValueFormatter = typeof tooltipOpt.formatter === 'function'
381
- ? tooltipOpt.formatter
382
- : tooltipOpt.formatter?.value;
383
362
 
384
363
  let hitId = null;
385
364
  let maxs = '';
@@ -414,31 +393,11 @@ const modules = {
414
393
  item.axis = { x: series.xAxisIndex, y: series.yAxisIndex };
415
394
  items[sId] = item;
416
395
 
417
- let formattedTxt = '';
418
- if (tooltipValueFormatter) {
419
- if (this.options.type === 'pie') {
420
- formattedTxt = tooltipValueFormatter({
421
- value: gdata,
422
- name: sName,
423
- });
424
- } else if (this.options.type === 'heatMap') {
425
- formattedTxt = tooltipValueFormatter({
426
- x: item.data.x,
427
- y: item.data.y,
428
- value: gdata > -1 ? gdata : 'error',
429
- });
430
- } else {
431
- formattedTxt = tooltipValueFormatter({
432
- x: this.options.horizontal ? gdata : item.data.x,
433
- y: this.options.horizontal ? item.data.y : gdata,
434
- name: sName,
435
- });
436
- }
437
- }
438
-
439
- if (!tooltipValueFormatter || typeof formattedTxt !== 'string') {
440
- formattedTxt = numberWithComma(gdata);
441
- }
396
+ const formattedTxt = this.getFormattedTooltipValue({
397
+ seriesName: sName,
398
+ value: gdata,
399
+ itemData: item.data,
400
+ });
442
401
 
443
402
  item.data.formatted = formattedTxt;
444
403
 
@@ -470,6 +429,97 @@ const modules = {
470
429
  return { items, hitId, maxTip: [maxs, maxv], maxHighlight };
471
430
  },
472
431
 
432
+ /**
433
+ * get formatted value for tooltip
434
+ * @param seriesName
435
+ * @param value
436
+ * @param x
437
+ * @param y
438
+ * @returns {string}
439
+ */
440
+ getFormattedTooltipValue({ seriesName, value, itemData }) {
441
+ const tooltipOpt = this.options.tooltip;
442
+ const tooltipValueFormatter = typeof tooltipOpt.formatter === 'function'
443
+ ? tooltipOpt.formatter
444
+ : tooltipOpt.formatter?.value;
445
+
446
+ let formattedTxt = value;
447
+ if (tooltipValueFormatter) {
448
+ if (this.options.type === 'pie') {
449
+ formattedTxt = tooltipValueFormatter({
450
+ value,
451
+ name: seriesName,
452
+ percentage: itemData.percentage,
453
+ });
454
+ } else if (this.options.type === 'heatMap') {
455
+ formattedTxt = tooltipValueFormatter({
456
+ x: itemData.x,
457
+ y: itemData.y,
458
+ value: value > -1 ? value : 'error',
459
+ });
460
+ } else {
461
+ formattedTxt = tooltipValueFormatter({
462
+ x: this.options.horizontal ? value : itemData.x,
463
+ y: this.options.horizontal ? itemData.y : value,
464
+ name: seriesName,
465
+ });
466
+ }
467
+ }
468
+
469
+ if (value && (!tooltipValueFormatter || typeof formattedTxt !== 'string')) {
470
+ if (this.options.type === 'heatMap') {
471
+ formattedTxt = value < 0 ? 'error' : numberWithComma(value);
472
+ } else {
473
+ formattedTxt = numberWithComma(value);
474
+ }
475
+ }
476
+
477
+ return formattedTxt;
478
+ },
479
+
480
+ /**
481
+ * add not hit info
482
+ * @param hitInfo
483
+ */
484
+ addNotHitInfo(hitInfo) {
485
+ const isHorizontal = !!this.options.horizontal;
486
+
487
+ const hitItemId = Object.keys(hitInfo.items)[0];
488
+ const hitItemData = isHorizontal
489
+ ? hitInfo.items?.[hitItemId]?.data?.y : hitInfo.items?.[hitItemId]?.data?.x;
490
+
491
+ const sIds = Object.keys(this.seriesList);
492
+ for (let ix = 0; ix < sIds.length; ix++) {
493
+ const sId = sIds[ix];
494
+ const series = this.seriesList[sId];
495
+
496
+ const hasData = series.data.find(data => (
497
+ isHorizontal
498
+ ? data?.y === hitItemData
499
+ : data?.x === hitItemData
500
+ ),
501
+ );
502
+
503
+ if (hasData && !hitInfo.items[sId] && series?.show) {
504
+ const item = {};
505
+ item.color = series.color;
506
+ item.hit = false;
507
+ item.name = series.name;
508
+ item.axis = { x: series.xAxisIndex, y: series.yAxisIndex };
509
+ item.index = isHorizontal ? series.yAxisIndex : series.xAxisIndex;
510
+ item.data = hasData;
511
+ item.data.formatted = this.getFormattedTooltipValue({
512
+ seriesName: series.name,
513
+ value: hasData.o,
514
+ x: hasData.x,
515
+ y: hasData.y,
516
+ });
517
+
518
+ hitInfo.items[sId] = item;
519
+ }
520
+ }
521
+ },
522
+
473
523
  /**
474
524
  *
475
525
  * @param targetInfo {object} '{ dataIndex: number, seriesID: string }'
@@ -695,7 +745,7 @@ const modules = {
695
745
  }
696
746
 
697
747
  const sId = Object.keys(this.seriesList)[0];
698
- const { xMin, xMax, yMin, yMax } = this.seriesList[sId].findSelectionRange(range);
748
+ const { xMin, xMax, yMin, yMax } = this.seriesList[sId].findSelectionRange(range) ?? {};
699
749
 
700
750
  return {
701
751
  xMin: xMin ?? dataRangeX.graphMin,