@syncfusion/ej2-schedule 20.1.57 → 20.2.36

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 (79) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/ej2-schedule.umd.min.js +2 -2
  3. package/dist/ej2-schedule.umd.min.js.map +1 -1
  4. package/dist/es6/ej2-schedule.es2015.js +199 -48
  5. package/dist/es6/ej2-schedule.es2015.js.map +1 -1
  6. package/dist/es6/ej2-schedule.es5.js +204 -48
  7. package/dist/es6/ej2-schedule.es5.js.map +1 -1
  8. package/dist/global/ej2-schedule.min.js +2 -2
  9. package/dist/global/ej2-schedule.min.js.map +1 -1
  10. package/dist/global/index.d.ts +1 -1
  11. package/helpers/e2e/index.js +9 -7
  12. package/helpers/e2e/recurrence-editor.js +41 -25
  13. package/helpers/e2e/schedule.js +44 -28
  14. package/package.json +15 -15
  15. package/src/recurrence-editor/recurrence-editor.js +4 -1
  16. package/src/schedule/actions/action-base.d.ts +1 -0
  17. package/src/schedule/actions/action-base.js +3 -2
  18. package/src/schedule/actions/crud.js +9 -7
  19. package/src/schedule/actions/drag.js +1 -1
  20. package/src/schedule/base/interface.d.ts +6 -0
  21. package/src/schedule/base/schedule.d.ts +8 -0
  22. package/src/schedule/base/schedule.js +66 -0
  23. package/src/schedule/event-renderer/agenda-base.js +6 -6
  24. package/src/schedule/event-renderer/event-base.js +7 -4
  25. package/src/schedule/event-renderer/month.js +3 -6
  26. package/src/schedule/event-renderer/vertical-view.js +3 -3
  27. package/src/schedule/event-renderer/year.js +2 -2
  28. package/src/schedule/exports/excel-export.js +8 -4
  29. package/src/schedule/popups/event-window.js +2 -1
  30. package/src/schedule/popups/quick-popups.js +5 -4
  31. package/src/schedule/renderer/agenda.js +2 -2
  32. package/src/schedule/renderer/timeline-month.d.ts +1 -0
  33. package/src/schedule/renderer/timeline-month.js +9 -0
  34. package/src/schedule/renderer/timeline-view.d.ts +1 -0
  35. package/src/schedule/renderer/timeline-view.js +14 -0
  36. package/src/schedule/renderer/timeline-year.js +3 -0
  37. package/src/schedule/renderer/vertical-view.d.ts +2 -0
  38. package/src/schedule/renderer/vertical-view.js +37 -5
  39. package/src/schedule/renderer/view-base.d.ts +1 -0
  40. package/src/schedule/renderer/view-base.js +19 -0
  41. package/src/schedule/renderer/year.js +2 -1
  42. package/styles/bootstrap-dark.css +6 -5
  43. package/styles/bootstrap.css +6 -5
  44. package/styles/bootstrap4.css +6 -5
  45. package/styles/bootstrap5-dark.css +5 -3
  46. package/styles/bootstrap5.css +6 -5
  47. package/styles/fabric-dark.css +6 -5
  48. package/styles/fabric.css +6 -5
  49. package/styles/fluent-dark.css +7 -5
  50. package/styles/fluent.css +8 -7
  51. package/styles/highcontrast-light.css +6 -5
  52. package/styles/highcontrast.css +6 -5
  53. package/styles/material-dark.css +6 -5
  54. package/styles/material.css +6 -5
  55. package/styles/recurrence-editor/_fusionnew-definition.scss +15 -0
  56. package/styles/recurrence-editor/_material3-definition.scss +15 -0
  57. package/styles/schedule/_fluent-definition.scss +1 -1
  58. package/styles/schedule/_fusionnew-definition.scss +224 -0
  59. package/styles/schedule/_layout.scss +6 -2
  60. package/styles/schedule/_material3-definition.scss +224 -0
  61. package/styles/schedule/bootstrap-dark.css +6 -5
  62. package/styles/schedule/bootstrap.css +6 -5
  63. package/styles/schedule/bootstrap4.css +6 -5
  64. package/styles/schedule/bootstrap5-dark.css +5 -3
  65. package/styles/schedule/bootstrap5.css +6 -5
  66. package/styles/schedule/fabric-dark.css +6 -5
  67. package/styles/schedule/fabric.css +6 -5
  68. package/styles/schedule/fluent-dark.css +7 -5
  69. package/styles/schedule/fluent.css +8 -7
  70. package/styles/schedule/highcontrast-light.css +6 -5
  71. package/styles/schedule/highcontrast.css +6 -5
  72. package/styles/schedule/icons/_fusionnew.scss +232 -0
  73. package/styles/schedule/icons/_material3.scss +232 -0
  74. package/styles/schedule/material-dark.css +6 -5
  75. package/styles/schedule/material.css +6 -5
  76. package/styles/schedule/tailwind-dark.css +5 -3
  77. package/styles/schedule/tailwind.css +6 -5
  78. package/styles/tailwind-dark.css +5 -3
  79. package/styles/tailwind.css +6 -5
@@ -5600,7 +5600,7 @@ class EventBase {
5600
5600
  removeSelectedAppointmentClass() {
5601
5601
  const selectedAppointments = this.getSelectedAppointments();
5602
5602
  for (const appointment of selectedAppointments) {
5603
- appointment.setAttribute('aria-selected', 'false');
5603
+ appointment.setAttribute('aria-pressed', 'false');
5604
5604
  }
5605
5605
  removeClass(selectedAppointments, APPOINTMENT_BORDER);
5606
5606
  if (this.parent.currentView === 'Agenda' || this.parent.currentView === 'MonthAgenda') {
@@ -5609,7 +5609,7 @@ class EventBase {
5609
5609
  }
5610
5610
  addSelectedAppointments(cells) {
5611
5611
  for (const cell of cells) {
5612
- cell.setAttribute('aria-selected', 'true');
5612
+ cell.setAttribute('aria-pressed', 'true');
5613
5613
  }
5614
5614
  if (this.parent.currentView !== 'MonthAgenda') {
5615
5615
  this.parent.removeSelectedClass();
@@ -5737,6 +5737,7 @@ class EventBase {
5737
5737
  }
5738
5738
  else if (!closest(element, '.' + POPUP_OPEN)) {
5739
5739
  this.removeSelectedAppointmentClass();
5740
+ this.parent.selectedElements = [];
5740
5741
  }
5741
5742
  }
5742
5743
  wireAppointmentEvents(element, event, isPreventCrud = false) {
@@ -5838,6 +5839,7 @@ class EventBase {
5838
5839
  this.parent.trigger(eventClick, args, (eventClickArgs) => {
5839
5840
  if (eventClickArgs.cancel) {
5840
5841
  this.removeSelectedAppointmentClass();
5842
+ this.parent.selectedElements = [];
5841
5843
  if (this.parent.quickPopup) {
5842
5844
  this.parent.quickPopup.quickPopupHide();
5843
5845
  }
@@ -5869,6 +5871,7 @@ class EventBase {
5869
5871
  this.activeEventData(e, true);
5870
5872
  }
5871
5873
  this.removeSelectedAppointmentClass();
5874
+ this.parent.selectedElements = [];
5872
5875
  if (this.parent.activeEventData.element.classList.contains(INLINE_APPOINTMENT_CLASS) ||
5873
5876
  this.parent.activeEventData.element.querySelector('.' + INLINE_SUBJECT_CLASS)) {
5874
5877
  return;
@@ -5943,7 +5946,7 @@ class EventBase {
5943
5946
  const exception = event[this.parent.eventFields.recurrenceException];
5944
5947
  let maxCount;
5945
5948
  if (this.parent.currentView !== 'Agenda' && isMaxCount) {
5946
- maxCount = getDateCount(this.parent.activeView.startDate(), this.parent.activeView.endDate()) + 1;
5949
+ maxCount = getDateCount(viewDate, this.parent.activeView.endDate()) + 1;
5947
5950
  }
5948
5951
  const newTimezone = this.parent.timezone || this.parent.tzModule.getLocalTimezoneName();
5949
5952
  const firstDay = this.parent.activeViewOptions.firstDayOfWeek;
@@ -6120,7 +6123,7 @@ class EventBase {
6120
6123
  className: BLOCK_APPOINTMENT_CLASS,
6121
6124
  attrs: {
6122
6125
  'data-id': 'Appointment_' + record[this.parent.eventFields.id],
6123
- 'aria-readonly': 'true', 'aria-selected': 'false'
6126
+ 'aria-disabled': 'true', 'aria-pressed': 'false'
6124
6127
  }
6125
6128
  });
6126
6129
  let templateElement;
@@ -6544,8 +6547,8 @@ class VerticalEvent extends EventBase {
6544
6547
  'data-guid': record.Guid,
6545
6548
  'role': 'button',
6546
6549
  'tabindex': '0',
6547
- 'aria-readonly': this.parent.eventBase.getReadonlyAttribute(record),
6548
- 'aria-selected': 'false',
6550
+ 'aria-disabled': this.parent.eventBase.getReadonlyAttribute(record),
6551
+ 'aria-pressed': 'false',
6549
6552
  'aria-grabbed': 'true',
6550
6553
  'aria-label': this.parent.getAnnouncementString(record)
6551
6554
  }
@@ -6640,7 +6643,7 @@ class VerticalEvent extends EventBase {
6640
6643
  });
6641
6644
  const moreIndicatorElement = createElement('div', {
6642
6645
  className: MORE_INDICATOR_CLASS,
6643
- attrs: { 'tabindex': '0', 'role': 'list', 'data-index': index.toString(), 'data-count': '1' },
6646
+ attrs: { 'tabindex': '0', 'data-index': index.toString(), 'data-count': '1' },
6644
6647
  innerHTML: '+1 ' + (this.parent.isAdaptive ? '' : this.parent.localeObj.getConstant('more'))
6645
6648
  });
6646
6649
  innerCountWrap.appendChild(moreIndicatorElement);
@@ -7229,9 +7232,7 @@ class MonthEvent extends EventBase {
7229
7232
  this.sortByDateTime(blockList);
7230
7233
  if (this.parent.currentView === 'Month' && this.parent.rowAutoHeight && this.parent.activeViewOptions.group.resources.length === 0) {
7231
7234
  const totalCells = [].slice.call(this.parent.element.querySelectorAll('.e-content-wrap table tr td:first-child'));
7232
- const height = this.parent.height === 'auto' ? (this.parent.element.querySelector('.e-content-wrap').clientHeight +
7233
- this.parent.element.querySelector('.e-date-header-wrap').clientHeight) / totalCells.length
7234
- : this.parent.element.querySelector('.e-schedule-table').clientHeight / totalCells.length;
7235
+ const height = this.parent.element.querySelector('.' + CONTENT_TABLE_CLASS).clientHeight / totalCells.length;
7235
7236
  totalCells.forEach((cell) => {
7236
7237
  setStyleAttribute(cell, { 'height': height + 'px' });
7237
7238
  });
@@ -7435,7 +7436,7 @@ class MonthEvent extends EventBase {
7435
7436
  const attrs = {
7436
7437
  'data-id': 'Appointment_' + record[this.fields.id],
7437
7438
  'role': 'button', 'tabindex': '0',
7438
- 'aria-readonly': this.parent.eventBase.getReadonlyAttribute(record), 'aria-selected': 'false', 'aria-grabbed': 'true',
7439
+ 'aria-disabled': this.parent.eventBase.getReadonlyAttribute(record), 'aria-pressed': 'false', 'aria-grabbed': 'true',
7439
7440
  'aria-label': this.parent.getAnnouncementString(newRecord, eventSubject)
7440
7441
  };
7441
7442
  if (!isCloneElement) {
@@ -7725,8 +7726,7 @@ class MonthEvent extends EventBase {
7725
7726
  'tabindex': '0',
7726
7727
  'data-count': count.toString(),
7727
7728
  'data-start-date': startDate.getTime().toString(),
7728
- 'data-end-date': endDate.getTime().toString(),
7729
- 'role': 'list'
7729
+ 'data-end-date': endDate.getTime().toString()
7730
7730
  }
7731
7731
  });
7732
7732
  return moreIndicatorElement;
@@ -8892,8 +8892,8 @@ class QuickPopups {
8892
8892
  attrs: {
8893
8893
  'data-id': '' + eventData[fields.id],
8894
8894
  'data-guid': eventData.Guid, 'role': 'button', 'tabindex': '0',
8895
- 'aria-readonly': this.parent.eventBase.getReadonlyAttribute(eventData),
8896
- 'aria-selected': 'false', 'aria-grabbed': 'true', 'aria-label': this.parent.getAnnouncementString(eventData)
8895
+ 'aria-disabled': this.parent.eventBase.getReadonlyAttribute(eventData),
8896
+ 'aria-pressed': 'false', 'aria-grabbed': 'true', 'aria-label': this.parent.getAnnouncementString(eventData)
8897
8897
  }
8898
8898
  });
8899
8899
  let templateElement;
@@ -8984,7 +8984,7 @@ class QuickPopups {
8984
8984
  this.quickPopupHide();
8985
8985
  return;
8986
8986
  }
8987
- const targetEle = args.event.target;
8987
+ const targetEle = !isNullOrUndefined(args.event) ? args.event.target : args.element;
8988
8988
  if (this.parent.isAdaptive) {
8989
8989
  this.quickPopupHide();
8990
8990
  let newEventClone = this.parent.element.querySelector('.' + NEW_EVENT_CLASS);
@@ -9080,6 +9080,7 @@ class QuickPopups {
9080
9080
  }
9081
9081
  else {
9082
9082
  const isSameTarget = this.isSameEventClick(events);
9083
+ this.parent.selectedElements = [];
9083
9084
  if (isSameTarget) {
9084
9085
  return;
9085
9086
  }
@@ -9145,7 +9146,7 @@ class QuickPopups {
9145
9146
  `<button class="${DELETE_CLASS + ' ' + ICON}" title="${this.l10n.getConstant('delete')}"></button>` +
9146
9147
  `<button class="${CLOSE_CLASS}" title="${this.l10n.getConstant('close')}"></button></div>` +
9147
9148
  `<div class="${SUBJECT_WRAP}"><div class="${SUBJECT_CLASS} ${TEXT_ELLIPSIS}" ` +
9148
- `title="${args.eventSubject}">${args.eventSubject}</div></div >`;
9149
+ `title="${args.eventSubject ? args.eventSubject.replaceAll('"', '\'') : args.eventSubject}">${args.eventSubject}</div></div >`;
9149
9150
  break;
9150
9151
  }
9151
9152
  const templateWrapper = createElement('div', { innerHTML: header });
@@ -10370,7 +10371,7 @@ let RecurrenceEditor = class RecurrenceEditor extends Component {
10370
10371
  value: VALUEFIELD
10371
10372
  },
10372
10373
  placeholder: this.localeObj.getConstant(REPEAT),
10373
- htmlAttributes: { 'title': this.localeObj.getConstant(REPEAT) },
10374
+ htmlAttributes: { 'title': this.localeObj.getConstant(REPEAT), role: 'option' },
10374
10375
  change: (args) => {
10375
10376
  self.setProperties({ selectedType: this.frequencies.indexOf(args.value) }, false);
10376
10377
  self.element.querySelector('.' + REPEATCONTENT).innerHTML =
@@ -10392,6 +10393,7 @@ let RecurrenceEditor = class RecurrenceEditor extends Component {
10392
10393
  text: TEXTFIELD,
10393
10394
  value: VALUEFIELD
10394
10395
  },
10396
+ htmlAttributes: { role: 'option' },
10395
10397
  change: (args) => {
10396
10398
  self.freshOnEndForm();
10397
10399
  self.updateEndOnForm(args.value);
@@ -10409,6 +10411,7 @@ let RecurrenceEditor = class RecurrenceEditor extends Component {
10409
10411
  text: TEXTFIELD,
10410
10412
  value: VALUEFIELD
10411
10413
  },
10414
+ htmlAttributes: { role: 'option' },
10412
10415
  index: 1,
10413
10416
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
10414
10417
  change: (args) => {
@@ -10428,6 +10431,7 @@ let RecurrenceEditor = class RecurrenceEditor extends Component {
10428
10431
  text: TEXTFIELD,
10429
10432
  value: VALUEFIELD
10430
10433
  },
10434
+ htmlAttributes: { role: 'option' },
10431
10435
  enableRtl: this.enableRtl,
10432
10436
  index: 7,
10433
10437
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -11526,6 +11530,7 @@ class EventWindow {
11526
11530
  resourceData.colorField + '}"></div><div class="e-resource-text">${' + resourceData.textField + '}</div></div>';
11527
11531
  if (resourceData.allowMultiple) {
11528
11532
  const listObj = new MultiSelect({
11533
+ enableRtl: this.parent.enableRtl,
11529
11534
  cssClass: this.parent.cssClass || '',
11530
11535
  dataSource: resourceData.dataSource,
11531
11536
  change: this.onMultiselectResourceChange.bind(this),
@@ -11583,7 +11588,7 @@ class EventWindow {
11583
11588
  query = (e.text !== '') ? query.where('Text', 'contains', e.text, true) : query;
11584
11589
  e.updateData(this.parent.timezoneDataSource, query);
11585
11590
  },
11586
- htmlAttributes: { 'title': this.getFieldLabel(value), 'name': fieldName },
11591
+ htmlAttributes: { 'title': this.getFieldLabel(value), 'name': fieldName, role: 'option' },
11587
11592
  floatLabelType: 'Always',
11588
11593
  placeholder: this.getFieldLabel(value),
11589
11594
  popupHeight: '230px'
@@ -13925,13 +13930,15 @@ class Crud {
13925
13930
  else {
13926
13931
  endDate = new Date(+followEvent[fields.startTime]);
13927
13932
  const newRecurrenceRule = followEvent[fields.recurrenceRule];
13928
- const startDate = parentEvent[fields.startTime];
13929
- const ruleException = (this.parent.currentAction === 'DeleteFollowingEvents') ? followEvent[fields.recurrenceException] : null;
13930
- const dateCollection = generate(startDate, newRecurrenceRule, ruleException, this.parent.activeViewOptions.firstDayOfWeek);
13931
- const untilDate = new Date(dateCollection.slice(-1)[0]);
13932
- untilDate.setHours(endDate.getHours(), endDate.getMinutes(), endDate.getSeconds());
13933
- endDate.setHours(startDate.getHours(), startDate.getMinutes(), startDate.getSeconds());
13934
- followEvent[fields.recurrenceRule] = this.getUpdatedRecurrenceRule(newRecurrenceRule, new Date(+untilDate), false);
13933
+ if (newRecurrenceRule) {
13934
+ const startDate = parentEvent[fields.startTime];
13935
+ const ruleException = (this.parent.currentAction === 'DeleteFollowingEvents') ? followEvent[fields.recurrenceException] : null;
13936
+ const dateCollection = generate(startDate, newRecurrenceRule, ruleException, this.parent.activeViewOptions.firstDayOfWeek);
13937
+ const untilDate = new Date(dateCollection.slice(-1)[0]);
13938
+ untilDate.setHours(endDate.getHours(), endDate.getMinutes(), endDate.getSeconds());
13939
+ endDate.setHours(startDate.getHours(), startDate.getMinutes(), startDate.getSeconds());
13940
+ followEvent[fields.recurrenceRule] = this.getUpdatedRecurrenceRule(newRecurrenceRule, new Date(+untilDate), false);
13941
+ }
13935
13942
  }
13936
13943
  parentEvent[fields.recurrenceRule] = this.getUpdatedRecurrenceRule(recurrenceRule, addDays(new Date(endDate.getTime()), -1), true);
13937
13944
  }
@@ -17626,6 +17633,67 @@ let Schedule = class Schedule extends Component {
17626
17633
  this.eventWindow.dialogClose();
17627
17634
  }
17628
17635
  }
17636
+ /**
17637
+ * To manually open the quick info popup based on cell or event details.
17638
+ *
17639
+ * @param {object} data Defines the cell or event data. If the data contains valid ID, it will open event quick info popup,
17640
+ * otherwise cell quick info popup displayed.
17641
+ * @returns {void}
17642
+ */
17643
+ openQuickInfoPopup(data) {
17644
+ if (this.currentView === 'Year' || isNullOrUndefined(data)) {
17645
+ return;
17646
+ }
17647
+ if (isNullOrUndefined(data[this.eventFields.id])) {
17648
+ if (this.currentView === 'Agenda' || this.currentView === 'MonthAgenda' || isNullOrUndefined(this.activeView)) {
17649
+ return;
17650
+ }
17651
+ const cellData = {
17652
+ startTime: this.activeCellsData.startTime = this.getDateTime(data[this.eventFields.startTime]),
17653
+ endTime: this.activeCellsData.endTime = this.getDateTime(data[this.eventFields.endTime]),
17654
+ isAllDay: this.activeCellsData.isAllDay =
17655
+ !isNullOrUndefined(data[this.eventFields.isAllDay]) ? data[this.eventFields.isAllDay] : false
17656
+ };
17657
+ const startTime = this.activeView.getAdjustedDate(new Date(cellData.startTime));
17658
+ if (startTime) {
17659
+ let query = '.' + WORK_CELLS_CLASS + '[data-date="' + startTime.getTime() + '"]';
17660
+ if (this.activeViewOptions.group.resources.length > 0 && !this.uiStateValues.isGroupAdaptive
17661
+ && this.resourceBase && this.eventBase) {
17662
+ cellData.groupIndex = this.eventBase.getGroupIndexFromEvent(data);
17663
+ query = '.' + WORK_CELLS_CLASS + '[data-date="' + startTime.getTime() + '"][data-group-index="' + cellData.groupIndex + '"]';
17664
+ }
17665
+ const workCell = this.element.querySelector(query);
17666
+ if (workCell) {
17667
+ workCell.focus();
17668
+ cellData.element = workCell;
17669
+ this.notify(cellClick, cellData);
17670
+ }
17671
+ }
17672
+ }
17673
+ else {
17674
+ const app = this.getCurrentViewEvents().filter((item) => data[this.eventFields.id] === item[this.eventFields.id]);
17675
+ if (app.length <= 0) {
17676
+ return;
17677
+ }
17678
+ let selectEvent = app[0];
17679
+ if (data[this.eventFields.recurrenceRule]) {
17680
+ const occurence = app.filter((x) => x[this.eventFields.startTime].getTime() === data[this.eventFields.startTime].getTime());
17681
+ if (occurence.length > 0) {
17682
+ selectEvent = occurence[0];
17683
+ }
17684
+ }
17685
+ const element = this.element.querySelector('div[data-guid="' + selectEvent.Guid + '"]');
17686
+ if (element) {
17687
+ this.eventBase.removeSelectedAppointmentClass();
17688
+ this.eventBase.addSelectedAppointments([element]);
17689
+ this.activeEventData = { event: selectEvent, element: element };
17690
+ if (this.currentView === 'Agenda' || this.currentView === 'MonthAgenda') {
17691
+ addClass([this.activeEventData.element], AGENDA_SELECTED_CELL);
17692
+ }
17693
+ this.notify(eventClick, this.activeEventData);
17694
+ }
17695
+ }
17696
+ }
17629
17697
  /**
17630
17698
  * To manually close the quick info popup
17631
17699
  *
@@ -18294,6 +18362,7 @@ class ActionBase {
18294
18362
  }
18295
18363
  }
18296
18364
  updateScrollPosition(e) {
18365
+ this.scrollEventArgs = e;
18297
18366
  if (this.actionObj.scroll.enable && isNullOrUndefined(this.actionObj.scrollInterval)) {
18298
18367
  this.actionObj.scrollInterval = window.setInterval(() => {
18299
18368
  if (this.autoScrollValidation() && !this.actionObj.clone.classList.contains(ALLDAY_APPOINTMENT_CLASS)) {
@@ -18303,10 +18372,10 @@ class ActionBase {
18303
18372
  }
18304
18373
  this.autoScroll();
18305
18374
  if (this.actionObj.action === 'drag') {
18306
- this.parent.dragAndDropModule.updateDraggingDateTime(e);
18375
+ this.parent.dragAndDropModule.updateDraggingDateTime(this.scrollEventArgs);
18307
18376
  }
18308
18377
  else {
18309
- this.parent.resizeModule.updateResizingDirection(e);
18378
+ this.parent.resizeModule.updateResizingDirection(this.scrollEventArgs);
18310
18379
  }
18311
18380
  }
18312
18381
  }, this.actionObj.scroll.timeDelay);
@@ -19058,7 +19127,7 @@ class YearEvent extends TimelineEvent {
19058
19127
  }
19059
19128
  }
19060
19129
  timelineYearViewEvents() {
19061
- const workCell = this.parent.element.querySelector('.' + WORK_CELLS_CLASS);
19130
+ const workCell = this.parent.element.querySelector('.' + WORK_CELLS_CLASS + ':not(.' + OTHERMONTH_CLASS + ')');
19062
19131
  this.cellWidth = workCell.offsetWidth;
19063
19132
  this.cellHeader = getOuterHeight(workCell.querySelector('.' + DATE_HEADER_CLASS));
19064
19133
  const eventTable = this.parent.element.querySelector('.' + EVENT_TABLE_CLASS);
@@ -19334,7 +19403,7 @@ class YearEvent extends TimelineEvent {
19334
19403
  'data-id': 'Appointment_' + record[this.fields.id],
19335
19404
  'data-guid': record.Guid,
19336
19405
  'role': 'button', 'tabindex': '0',
19337
- 'aria-readonly': this.parent.eventBase.getReadonlyAttribute(record), 'aria-selected': 'false', 'aria-grabbed': 'true',
19406
+ 'aria-disabled': this.parent.eventBase.getReadonlyAttribute(record), 'aria-pressed': 'false', 'aria-grabbed': 'true',
19338
19407
  'aria-label': this.parent.getAnnouncementString(record)
19339
19408
  }
19340
19409
  });
@@ -20686,7 +20755,7 @@ class DragAndDrop extends ActionBase {
20686
20755
  const cursorElement = this.getCursorElement(e);
20687
20756
  if (cursorElement) {
20688
20757
  top = cursorElement.classList.contains(WORK_CELLS_CLASS) ? cursorElement.offsetTop :
20689
- cursorElement.offsetParent.classList.contains(APPOINTMENT_CLASS) ?
20758
+ (cursorElement.offsetParent && cursorElement.offsetParent.classList.contains(APPOINTMENT_CLASS)) ?
20690
20759
  cursorElement.offsetParent.offsetTop : top;
20691
20760
  }
20692
20761
  }
@@ -21225,6 +21294,14 @@ class ViewBase {
21225
21294
  const tdDate = new Date(resetTime(new Date(+scrollDate)).getTime()).getTime();
21226
21295
  const dateElement = scrollWrap.querySelector(`.${WORK_CELLS_CLASS}[data-date="${tdDate}"]`);
21227
21296
  if (this.parent.currentView === 'Month' && dateElement) {
21297
+ if (scrollWrap.scrollWidth > scrollWrap.clientWidth) {
21298
+ if (!this.parent.enableRtl) {
21299
+ scrollWrap.scrollLeft = dateElement.offsetLeft;
21300
+ }
21301
+ else {
21302
+ scrollWrap.scrollLeft = -(this.parent.getContentTable().offsetWidth - dateElement.offsetLeft - dateElement.offsetWidth);
21303
+ }
21304
+ }
21228
21305
  scrollWrap.scrollTop = dateElement.offsetTop;
21229
21306
  }
21230
21307
  if (this.parent.currentView === 'TimelineMonth' && dateElement) {
@@ -21268,6 +21345,17 @@ class ViewBase {
21268
21345
  }
21269
21346
  return endDate;
21270
21347
  }
21348
+ getAdjustedDate(startTime) {
21349
+ if (!this.parent.activeViewOptions.timeScale.enable || this.parent.currentView === 'Month' ||
21350
+ (this.parent.currentView === 'TimelineYear' && this.parent.activeViewOptions.group.resources.length === 0)) {
21351
+ return new Date(startTime.setHours(0, 0, 0, 0));
21352
+ }
21353
+ else if (this.parent.currentView === 'TimelineYear' && this.parent.activeViewOptions.group.resources.length > 0) {
21354
+ startTime.setHours(0, 0, 0, 0);
21355
+ return new Date(startTime.setDate(1));
21356
+ }
21357
+ return null;
21358
+ }
21271
21359
  destroy() {
21272
21360
  if (this.element && this.element.parentNode) {
21273
21361
  remove(this.element);
@@ -21413,11 +21501,26 @@ class VerticalView extends ViewBase {
21413
21501
  }
21414
21502
  scrollToHour(hour, scrollDate) {
21415
21503
  const date = this.parent.getStartEndTime(hour);
21416
- if (isNullOrUndefined(date) || !isNullOrUndefined(scrollDate)) {
21504
+ if (!isNullOrUndefined(scrollDate)) {
21505
+ const headerElement = this.element.querySelector('.' + HEADER_CELLS_CLASS + '[data-date="' + new Date(resetTime(scrollDate)).getTime() + '"]');
21506
+ if (headerElement) {
21507
+ if (this.parent.enableRtl) {
21508
+ const conWrap = this.element.querySelector('.' + CONTENT_TABLE_CLASS);
21509
+ this.getScrollableElement().scrollLeft = -(conWrap.offsetWidth - headerElement.offsetLeft - headerElement.offsetWidth);
21510
+ }
21511
+ else {
21512
+ this.getScrollableElement().scrollLeft = headerElement.offsetLeft;
21513
+ }
21514
+ }
21515
+ }
21516
+ if (isNullOrUndefined(date)) {
21417
21517
  return;
21418
21518
  }
21419
21519
  this.getScrollableElement().scrollTop = this.getTopFromDateTime(date);
21420
21520
  }
21521
+ scrollToDate(scrollDate) {
21522
+ this.scrollToHour(null, scrollDate);
21523
+ }
21421
21524
  generateColumnLevels() {
21422
21525
  const level = this.getDateSlots(this.renderDates, this.parent.activeViewOptions.workDays);
21423
21526
  let columnLevels = [];
@@ -21748,12 +21851,11 @@ class VerticalView extends ViewBase {
21748
21851
  const wrap = createElement('div', { className: DATE_HEADER_WRAP_CLASS });
21749
21852
  container.appendChild(wrap);
21750
21853
  const tbl = this.createTableLayout();
21751
- const trEle = createElement('tr');
21854
+ const trEle = createElement('tr', { className: HEADER_ROW_CLASS });
21752
21855
  const rowCount = this.colLevels.length;
21753
21856
  const lastLevel = this.colLevels[rowCount - 1];
21754
21857
  for (let i = 0; i < rowCount; i++) {
21755
21858
  const ntr = trEle.cloneNode();
21756
- addClass([ntr], HEADER_ROW_CLASS);
21757
21859
  const level = this.colLevels[i];
21758
21860
  for (let j = 0; j < level.length; j++) {
21759
21861
  ntr.appendChild(this.createTd(level[j]));
@@ -21766,13 +21868,13 @@ class VerticalView extends ViewBase {
21766
21868
  return container;
21767
21869
  }
21768
21870
  createAllDayRow(table, tdData) {
21769
- const ntr = createElement('tr');
21770
- addClass([ntr], ALLDAY_ROW_CLASS);
21871
+ const ntr = createElement('tr', { className: ALLDAY_ROW_CLASS });
21771
21872
  for (let j = 0; j < tdData.length; j++) {
21772
21873
  const td = extend({}, tdData[j]);
21773
21874
  td.className = [ALLDAY_CELLS_CLASS];
21774
21875
  td.type = 'alldayCells';
21775
21876
  const ntd = this.createTd(td);
21877
+ ntd.setAttribute('role', 'gridcell');
21776
21878
  ntd.setAttribute('data-date', td.date.getTime().toString());
21777
21879
  if (!isNullOrUndefined(td.groupIndex)) {
21778
21880
  ntd.setAttribute('data-group-index', '' + td.groupIndex);
@@ -21805,6 +21907,7 @@ class VerticalView extends ViewBase {
21805
21907
  }
21806
21908
  if (td.type === 'dateHeader' && td.className.indexOf(HEADER_CELLS_CLASS) >= 0) {
21807
21909
  tdEle.setAttribute('data-date', td.date.getTime().toString());
21910
+ tdEle.setAttribute('role', 'gridcell');
21808
21911
  if (!isNullOrUndefined(td.groupIndex)) {
21809
21912
  tdEle.setAttribute('data-group-index', '' + td.groupIndex);
21810
21913
  }
@@ -22003,6 +22106,23 @@ class VerticalView extends ViewBase {
22003
22106
  }
22004
22107
  return rows;
22005
22108
  }
22109
+ getAdjustedDate(startTime) {
22110
+ if (!this.parent.activeViewOptions.timeScale.enable) {
22111
+ return new Date(startTime.setHours(0, 0, 0, 0));
22112
+ }
22113
+ else {
22114
+ const timeSlots = this.getTimeSlotRows();
22115
+ const startDate = new Date(new Date(timeSlots[0].date.getTime()).
22116
+ setHours(startTime.getHours(), startTime.getMinutes(), startTime.getMilliseconds()));
22117
+ for (let i = 0; i < timeSlots.length; i++) {
22118
+ if (timeSlots[i].date.getTime() > startDate.getTime()) {
22119
+ startTime.setHours(timeSlots[i - 1].date.getHours(), timeSlots[i - 1].date.getMinutes(), timeSlots[i - 1].date.getMilliseconds());
22120
+ return new Date(startTime);
22121
+ }
22122
+ }
22123
+ }
22124
+ return null;
22125
+ }
22006
22126
  destroy() {
22007
22127
  if (!this.parent || this.parent && this.parent.isDestroyed) {
22008
22128
  return;
@@ -23053,7 +23173,8 @@ class Year extends ViewBase {
23053
23173
  return this.parent.currentView === 'Year' ? getWeekFirstDate(this.getStartDate(), this.parent.firstDayOfWeek) : this.getStartDate();
23054
23174
  }
23055
23175
  endDate() {
23056
- return this.parent.currentView === 'Year' ? addDays(getWeekLastDate(this.getEndDate(), this.parent.firstDayOfWeek), 1) : this.getEndDate();
23176
+ return this.parent.currentView === 'Year' ? addDays(getWeekLastDate(this.getEndDate(), this.parent.firstDayOfWeek), 1) :
23177
+ addDays(this.getEndDate(), 1);
23057
23178
  }
23058
23179
  getEndDateFromStartDate(start) {
23059
23180
  let date = new Date(start.getTime());
@@ -23163,8 +23284,8 @@ class AgendaBase extends ViewBase {
23163
23284
  'data-guid': listData[li].Guid,
23164
23285
  'role': 'button',
23165
23286
  'tabindex': '0',
23166
- 'aria-readonly': this.parent.eventBase.getReadonlyAttribute(listData[li]),
23167
- 'aria-selected': 'false',
23287
+ 'aria-disabled': this.parent.eventBase.getReadonlyAttribute(listData[li]),
23288
+ 'aria-pressed': 'false',
23168
23289
  'aria-grabbed': 'true',
23169
23290
  'aria-label': this.parent.getAnnouncementString(listData[li])
23170
23291
  }
@@ -23429,8 +23550,8 @@ class AgendaBase extends ViewBase {
23429
23550
  ntd.appendChild(this.createDateHeaderElement(tempData.date));
23430
23551
  addClass([ntd], [AGENDA_CELLS_CLASS, AGENDA_DATE_CLASS, DATE_BORDER_CLASS]);
23431
23552
  const daysCount = getDaysCount(this.parent.selectedDate.getTime(), tempData.date.getTime());
23432
- ntr.setAttribute('aria-rowindex', daysCount.toString());
23433
- if (this.parent.element.querySelector(`.e-agenda-view tr[aria-rowindex="${daysCount}"]`)) {
23553
+ ntr.setAttribute('data-row-index', daysCount.toString());
23554
+ if (this.parent.element.querySelector(`.e-agenda-view tr[data-row-index="${daysCount}"]`)) {
23434
23555
  break;
23435
23556
  }
23436
23557
  ntr.insertBefore(ntd, ntr.childNodes[0]);
@@ -23466,13 +23587,13 @@ class AgendaBase extends ViewBase {
23466
23587
  }
23467
23588
  createTableRowElement(date, type) {
23468
23589
  const daysCount = getDaysCount(this.parent.selectedDate.getTime(), date.getTime());
23469
- const tr = createElement('tr', { attrs: { 'role': 'row', 'aria-rowindex': daysCount.toString() } });
23590
+ const tr = createElement('tr', { attrs: { 'role': 'row', 'data-row-index': daysCount.toString() } });
23470
23591
  const td = createElement('td', {
23471
23592
  attrs: {
23472
23593
  'class': (type === 'monthHeader') ? MONTH_HEADER_CLASS : AGENDA_CELLS_CLASS,
23473
23594
  'role': 'gridcell',
23474
23595
  'aria-selected': 'false',
23475
- 'aria-colindex': daysCount.toString(),
23596
+ 'data-column-index': daysCount.toString(),
23476
23597
  'data-date': date.getTime().toString()
23477
23598
  }
23478
23599
  });
@@ -23639,7 +23760,7 @@ class Agenda extends AgendaBase {
23639
23760
  for (let day = 0; day < this.parent.agendaDaysCount; day++) {
23640
23761
  const filterData = this.appointmentFiltering(agendaDate);
23641
23762
  const nTr = this.createTableRowElement(agendaDate, 'data');
23642
- if (this.element.querySelector('tr[aria-rowindex="' + parseInt(nTr.getAttribute('aria-rowindex'), 10) + '"]')) {
23763
+ if (this.element.querySelector('tr[data-row-index="' + parseInt(nTr.getAttribute('data-row-index'), 10) + '"]')) {
23643
23764
  agendaDate = addDays(agendaDate, 1);
23644
23765
  continue;
23645
23766
  }
@@ -23703,7 +23824,7 @@ class Agenda extends AgendaBase {
23703
23824
  prepend([].slice.call(emptyTBody.childNodes), tBody);
23704
23825
  this.wireEventActions();
23705
23826
  for (let s = 0, element = tBody.children; s < element.length; s++) {
23706
- if (element[s].getAttribute('aria-rowindex') === topElement.getAttribute('aria-colindex')) {
23827
+ if (element[s].getAttribute('data-row-index') === topElement.getAttribute('data-column-index')) {
23707
23828
  const scrollToValue = element[s].offsetTop -
23708
23829
  this.element.querySelector('.e-agenda-item').offsetHeight;
23709
23830
  target.scrollTop = scrollToValue;
@@ -24403,6 +24524,20 @@ class TimelineViews extends VerticalView {
24403
24524
  this.timelineAppointment.renderAppointments();
24404
24525
  this.parent.notify(eventsLoaded, {});
24405
24526
  }
24527
+ getAdjustedDate(date) {
24528
+ if (!this.parent.activeViewOptions.timeScale.enable) {
24529
+ return new Date(date.setHours(0, 0, 0, 0));
24530
+ }
24531
+ else {
24532
+ const timeSlots = this.colLevels[this.colLevels.length - 1];
24533
+ for (let i = 0; i < timeSlots.length; i++) {
24534
+ if (timeSlots[i].date.getTime() > date.getTime()) {
24535
+ return timeSlots[i - 1].date;
24536
+ }
24537
+ }
24538
+ }
24539
+ return null;
24540
+ }
24406
24541
  destroy() {
24407
24542
  if (!this.parent || this.parent && this.parent.isDestroyed) {
24408
24543
  return;
@@ -24543,6 +24678,15 @@ class TimelineMonth extends Month {
24543
24678
  this.colLevels = colLevels;
24544
24679
  return colLevels;
24545
24680
  }
24681
+ getAdjustedDate(startTime) {
24682
+ const timeSlots = this.colLevels[this.colLevels.length - 1];
24683
+ for (let i = 0; i < timeSlots.length; i++) {
24684
+ if (timeSlots[i].date.getTime() > startTime.getTime()) {
24685
+ return timeSlots[i - 1].date;
24686
+ }
24687
+ }
24688
+ return null;
24689
+ }
24546
24690
  destroy() {
24547
24691
  if (!this.parent || this.parent && this.parent.isDestroyed) {
24548
24692
  return;
@@ -24812,6 +24956,9 @@ class TimelineYear extends Year {
24812
24956
  else {
24813
24957
  addClass([td], OTHERMONTH_CLASS);
24814
24958
  }
24959
+ if (td.classList.contains(OTHERMONTH_CLASS)) {
24960
+ continue;
24961
+ }
24815
24962
  td.appendChild(dateHeader);
24816
24963
  if (isDateAvail) {
24817
24964
  td.setAttribute('data-date', date.getTime().toString());
@@ -25316,6 +25463,10 @@ class ExcelExport {
25316
25463
  const exportName = excelExportOptions.fileName || 'Schedule';
25317
25464
  const exportType = excelExportOptions.exportType || 'xlsx';
25318
25465
  const isIncludeOccurrences = excelExportOptions.includeOccurrences || false;
25466
+ let separator;
25467
+ if (!isNullOrUndefined(excelExportOptions.separator) && excelExportOptions.separator !== ',') {
25468
+ separator = excelExportOptions.separator;
25469
+ }
25319
25470
  let eventCollection;
25320
25471
  if (excelExportOptions.customData) {
25321
25472
  eventCollection = !isIncludeOccurrences ? excelExportOptions.customData :
@@ -25324,9 +25475,9 @@ class ExcelExport {
25324
25475
  else {
25325
25476
  eventCollection = !isIncludeOccurrences ? this.parent.eventsData : this.parent.eventsProcessed;
25326
25477
  }
25327
- this.processWorkbook(exportColumns, exportName, exportType, eventCollection);
25478
+ this.processWorkbook(exportColumns, exportName, exportType, eventCollection, separator);
25328
25479
  }
25329
- processWorkbook(fields, name, type, eventCollection) {
25480
+ processWorkbook(fields, name, type, eventCollection, separator) {
25330
25481
  const columns = [];
25331
25482
  const rows = [];
25332
25483
  const columnHeader = [];
@@ -25347,7 +25498,7 @@ class ExcelExport {
25347
25498
  rows.push({ index: i + 2, cells: columnData });
25348
25499
  });
25349
25500
  const workSheet = [{ columns: columns, rows: rows }];
25350
- const book = new Workbook({ worksheets: workSheet }, type, this.parent.locale);
25501
+ const book = new Workbook({ worksheets: workSheet }, type, this.parent.locale, undefined, separator);
25351
25502
  book.save(name + '.' + type);
25352
25503
  }
25353
25504
  getExportColumns(exportOptions) {