@syncfusion/ej2-schedule 20.4.53 → 21.1.35

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 (107) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/ej2-schedule.min.js +2 -2
  3. package/dist/ej2-schedule.umd.min.js +2 -2
  4. package/dist/ej2-schedule.umd.min.js.map +1 -1
  5. package/dist/es6/ej2-schedule.es2015.js +321 -134
  6. package/dist/es6/ej2-schedule.es2015.js.map +1 -1
  7. package/dist/es6/ej2-schedule.es5.js +356 -155
  8. package/dist/es6/ej2-schedule.es5.js.map +1 -1
  9. package/dist/global/ej2-schedule.min.js +2 -2
  10. package/dist/global/ej2-schedule.min.js.map +1 -1
  11. package/dist/global/index.d.ts +1 -1
  12. package/package.json +16 -16
  13. package/src/common/calendar-util.d.ts +7 -0
  14. package/src/recurrence-editor/recurrence-editor.d.ts +10 -0
  15. package/src/schedule/actions/action-base.js +5 -0
  16. package/src/schedule/actions/crud.js +1 -0
  17. package/src/schedule/actions/data.d.ts +14 -2
  18. package/src/schedule/actions/data.js +26 -2
  19. package/src/schedule/actions/keyboard.js +10 -9
  20. package/src/schedule/base/interface.d.ts +23 -23
  21. package/src/schedule/base/resource.js +5 -6
  22. package/src/schedule/base/schedule-model.d.ts +34 -27
  23. package/src/schedule/base/schedule.d.ts +50 -27
  24. package/src/schedule/base/schedule.js +39 -7
  25. package/src/schedule/base/type.d.ts +66 -1
  26. package/src/schedule/event-renderer/agenda-base.js +6 -2
  27. package/src/schedule/event-renderer/event-base.d.ts +1 -0
  28. package/src/schedule/event-renderer/event-base.js +26 -9
  29. package/src/schedule/event-renderer/month.js +4 -5
  30. package/src/schedule/event-renderer/vertical-view.d.ts +0 -1
  31. package/src/schedule/event-renderer/vertical-view.js +6 -30
  32. package/src/schedule/event-renderer/year.d.ts +1 -0
  33. package/src/schedule/event-renderer/year.js +135 -54
  34. package/src/schedule/models/event-settings-model.d.ts +11 -2
  35. package/src/schedule/models/event-settings.d.ts +10 -2
  36. package/src/schedule/models/event-settings.js +3 -0
  37. package/src/schedule/models/fields-model.d.ts +4 -2
  38. package/src/schedule/models/fields.d.ts +6 -4
  39. package/src/schedule/models/fields.js +2 -2
  40. package/src/schedule/models/header-rows-model.d.ts +5 -5
  41. package/src/schedule/models/header-rows.d.ts +5 -5
  42. package/src/schedule/models/quick-info-templates-model.d.ts +3 -3
  43. package/src/schedule/models/quick-info-templates.d.ts +3 -3
  44. package/src/schedule/models/views-model.d.ts +16 -15
  45. package/src/schedule/models/views.d.ts +16 -15
  46. package/src/schedule/popups/event-tooltip.js +2 -1
  47. package/src/schedule/popups/event-window.js +26 -5
  48. package/src/schedule/popups/quick-popups.js +32 -10
  49. package/src/schedule/renderer/header-renderer.js +1 -0
  50. package/src/schedule/renderer/month-agenda.d.ts +2 -1
  51. package/src/schedule/renderer/month-agenda.js +5 -0
  52. package/src/schedule/renderer/month.d.ts +1 -0
  53. package/src/schedule/renderer/month.js +5 -3
  54. package/src/schedule/renderer/timeline-year.js +12 -8
  55. package/src/schedule/renderer/vertical-view.js +1 -1
  56. package/src/schedule/renderer/view-base.js +3 -4
  57. package/src/schedule/renderer/year.js +5 -1
  58. package/styles/bootstrap-dark.css +99 -89
  59. package/styles/bootstrap.css +99 -89
  60. package/styles/bootstrap4.css +99 -89
  61. package/styles/bootstrap5-dark.css +110 -100
  62. package/styles/bootstrap5.css +110 -100
  63. package/styles/fabric-dark.css +98 -88
  64. package/styles/fabric.css +98 -88
  65. package/styles/fluent-dark.css +109 -99
  66. package/styles/fluent.css +109 -99
  67. package/styles/highcontrast-light.css +98 -88
  68. package/styles/highcontrast.css +98 -88
  69. package/styles/material-dark.css +98 -88
  70. package/styles/material.css +98 -88
  71. package/styles/recurrence-editor/_bootstrap5-definition.scss +1 -1
  72. package/styles/recurrence-editor/_fluent-definition.scss +1 -1
  73. package/styles/recurrence-editor/_tailwind-definition.scss +1 -1
  74. package/styles/schedule/_bootstrap-dark-definition.scss +8 -1
  75. package/styles/schedule/_bootstrap-definition.scss +8 -1
  76. package/styles/schedule/_bootstrap4-definition.scss +7 -0
  77. package/styles/schedule/_bootstrap5-definition.scss +17 -10
  78. package/styles/schedule/_fabric-dark-definition.scss +7 -0
  79. package/styles/schedule/_fabric-definition.scss +7 -0
  80. package/styles/schedule/_fluent-definition.scss +15 -8
  81. package/styles/schedule/_fusionnew-definition.scss +7 -0
  82. package/styles/schedule/_highcontrast-definition.scss +7 -0
  83. package/styles/schedule/_highcontrast-light-definition.scss +7 -0
  84. package/styles/schedule/_layout.scss +63 -48
  85. package/styles/schedule/_material-dark-definition.scss +7 -0
  86. package/styles/schedule/_material-definition.scss +7 -0
  87. package/styles/schedule/_tailwind-definition.scss +17 -10
  88. package/styles/schedule/_theme.scss +40 -41
  89. package/styles/schedule/bootstrap-dark.css +99 -89
  90. package/styles/schedule/bootstrap.css +99 -89
  91. package/styles/schedule/bootstrap4.css +99 -89
  92. package/styles/schedule/bootstrap5-dark.css +110 -100
  93. package/styles/schedule/bootstrap5.css +110 -100
  94. package/styles/schedule/fabric-dark.css +98 -88
  95. package/styles/schedule/fabric.css +98 -88
  96. package/styles/schedule/fluent-dark.css +109 -99
  97. package/styles/schedule/fluent.css +109 -99
  98. package/styles/schedule/highcontrast-light.css +98 -88
  99. package/styles/schedule/highcontrast.css +98 -88
  100. package/styles/schedule/material-dark.css +98 -88
  101. package/styles/schedule/material.css +98 -88
  102. package/styles/schedule/tailwind-dark.css +106 -96
  103. package/styles/schedule/tailwind.css +106 -96
  104. package/styles/tailwind-dark.css +106 -96
  105. package/styles/tailwind.css +106 -96
  106. package/styles/recurrence-editor/_material3-definition.scss +0 -13
  107. package/styles/schedule/_material3-definition.scss +0 -283
@@ -1021,6 +1021,7 @@ class HeaderRenderer {
1021
1021
  overflowMode: 'Popup',
1022
1022
  clicked: this.toolbarClickHandler.bind(this),
1023
1023
  enableRtl: this.parent.enableRtl,
1024
+ enableHtmlSanitizer: this.parent.enableHtmlSanitizer,
1024
1025
  locale: this.parent.locale
1025
1026
  });
1026
1027
  this.toolbarObj.appendTo(this.parent.element.querySelector('.' + HEADER_TOOLBAR));
@@ -2273,15 +2274,16 @@ class KeyboardInteraction {
2273
2274
  const args = {
2274
2275
  element: target, requestType: cellSelect
2275
2276
  };
2276
- const cellData = {};
2277
- const cellDetails = this.parent.getCellDetails(target);
2278
- if (this.parent.eventWindow && cellDetails) {
2279
- if (this.parent.activeCellsData.element !== cellDetails.element) {
2280
- this.parent.activeCellsData = cellDetails;
2281
- }
2282
- this.parent.eventWindow.convertToEventData(this.parent.activeCellsData, cellData);
2283
- args.data = cellData;
2284
- }
2277
+ // activeCellsData is not reset on schedule property changed(group properties)
2278
+ // const cellData: Record<string, any> = {};
2279
+ // const cellDetails: CellClickEventArgs = this.parent.getCellDetails(target);
2280
+ // if (this.parent.eventWindow && cellDetails) {
2281
+ // if (this.parent.activeCellsData.element !== cellDetails.element) {
2282
+ // this.parent.activeCellsData = cellDetails;
2283
+ // }
2284
+ // this.parent.eventWindow.convertToEventData(this.parent.activeCellsData as unknown as Record<string, any>, cellData);
2285
+ // args.data = cellData;
2286
+ // }
2285
2287
  this.parent.trigger(select, args, () => {
2286
2288
  this.initialTarget = target;
2287
2289
  this.selectedCells = [target];
@@ -2982,11 +2984,13 @@ class Data {
2982
2984
  /**
2983
2985
  * Constructor for data module
2984
2986
  *
2987
+ * @param {Schedule} parent Accepts the schedule element instance
2985
2988
  * @param {Object | DataManager} dataSource Accepts the datasource as JSON objects or DataManager
2986
2989
  * @param {Query} query Accepts the query to process the data
2987
2990
  * @private
2988
2991
  */
2989
- constructor(dataSource, query) {
2992
+ constructor(parent, dataSource, query) {
2993
+ this.parent = parent;
2990
2994
  this.initDataManager(dataSource, query);
2991
2995
  }
2992
2996
  /**
@@ -3011,6 +3015,11 @@ class Data {
3011
3015
  */
3012
3016
  generateQuery(startDate, endDate) {
3013
3017
  const query = this.query.clone();
3018
+ if (this.parent && this.parent.eventSettings.includeFiltersInQuery && startDate && endDate) {
3019
+ const dateQuery = this.getStartEndQuery(startDate, endDate);
3020
+ const recurrenceQuery = new Predicate(this.parent.eventFields.recurrenceRule, 'notequal', null).and(new Predicate(this.parent.eventFields.recurrenceRule, 'notequal', ''));
3021
+ return query.where(dateQuery.or(recurrenceQuery));
3022
+ }
3014
3023
  if (startDate) {
3015
3024
  query.addParams('StartDate', startDate.toISOString());
3016
3025
  }
@@ -3019,6 +3028,23 @@ class Data {
3019
3028
  }
3020
3029
  return query;
3021
3030
  }
3031
+ /**
3032
+ * The function used to generate updated Query from schedule model
3033
+ *
3034
+ * @param {Date} startDate Accepts the start date
3035
+ * @param {Date} endDate Accepts the end date
3036
+ * @returns {void}
3037
+ * @private
3038
+ */
3039
+ getStartEndQuery(startDate, endDate) {
3040
+ const fieldMapping = this.parent.eventFields;
3041
+ const dateQuery = new Predicate(fieldMapping.startTime, 'greaterthanorequal', startDate)
3042
+ .and(new Predicate(fieldMapping.endTime, 'greaterthanorequal', startDate))
3043
+ .and(new Predicate(fieldMapping.startTime, 'lessthan', endDate))
3044
+ .or(new Predicate(fieldMapping.startTime, 'lessthanorequal', startDate)
3045
+ .and(new Predicate(fieldMapping.endTime, 'greaterthan', startDate)));
3046
+ return dateQuery;
3047
+ }
3022
3048
  /**
3023
3049
  * The function used to get dataSource by executing given Query
3024
3050
  *
@@ -5396,12 +5422,7 @@ class EventBase {
5396
5422
  return this.filterEvents(eStart, eEnd, blockEvents, resourceData);
5397
5423
  }
5398
5424
  filterEvents(startDate, endDate, appointments = this.parent.eventsProcessed, resourceTdData) {
5399
- const fieldMapping = this.parent.eventFields;
5400
- const predicate = new Predicate(fieldMapping.startTime, 'greaterthanorequal', startDate).
5401
- and(new Predicate(fieldMapping.endTime, 'greaterthanorequal', startDate)).
5402
- and(new Predicate(fieldMapping.startTime, 'lessthan', endDate)).
5403
- or(new Predicate(fieldMapping.startTime, 'lessthanorequal', startDate).
5404
- and(new Predicate(fieldMapping.endTime, 'greaterthan', startDate)));
5425
+ const predicate = this.parent.dataModule.getStartEndQuery(startDate, endDate);
5405
5426
  let filter = new DataManager({ json: appointments }).executeLocal(new Query().where(predicate));
5406
5427
  if (resourceTdData) {
5407
5428
  filter = this.filterEventsByResource(resourceTdData, filter);
@@ -6234,9 +6255,8 @@ class EventBase {
6234
6255
  templateElement = this.parent.getAppointmentTemplate()(record, this.parent, templateName, templateId, false);
6235
6256
  }
6236
6257
  else {
6237
- const appointmentSubject = createElement('div', {
6238
- className: SUBJECT_CLASS, innerHTML: eventSubject
6239
- });
6258
+ const appointmentSubject = createElement('div', { className: SUBJECT_CLASS });
6259
+ appointmentSubject.innerText = this.parent.sanitize(eventSubject);
6240
6260
  templateElement = [appointmentSubject];
6241
6261
  }
6242
6262
  append(templateElement, appointmentWrapper);
@@ -6414,6 +6434,29 @@ class EventBase {
6414
6434
  return eventArgs && eventArgs.changedTouches ? eventArgs.changedTouches[0] : e.changedTouches ? e.changedTouches[0] :
6415
6435
  eventArgs || e;
6416
6436
  }
6437
+ renderSpannedIcon(element, spanEvent) {
6438
+ const iconElement = createElement('div', { className: EVENT_INDICATOR_CLASS + ' ' + ICON });
6439
+ if (spanEvent.isLeft) {
6440
+ const iconLeft = iconElement.cloneNode();
6441
+ addClass([iconLeft], EVENT_ICON_LEFT_CLASS);
6442
+ prepend([iconLeft], element);
6443
+ }
6444
+ if (spanEvent.isRight) {
6445
+ const iconRight = iconElement.cloneNode();
6446
+ addClass([iconRight], EVENT_ICON_RIGHT_CLASS);
6447
+ append([iconRight], element);
6448
+ }
6449
+ if (spanEvent.isTop) {
6450
+ const iconTop = iconElement.cloneNode();
6451
+ addClass([iconTop], EVENT_ICON_UP_CLASS);
6452
+ prepend([iconTop], element);
6453
+ }
6454
+ if (spanEvent.isBottom) {
6455
+ const iconBottom = iconElement.cloneNode();
6456
+ addClass([iconBottom], EVENT_ICON_DOWN_CLASS);
6457
+ append([iconBottom], element);
6458
+ }
6459
+ }
6417
6460
  unWireEvents() {
6418
6461
  const appElements = [].slice.call(this.parent.element.querySelectorAll('.' + APPOINTMENT_CLASS));
6419
6462
  for (const element of appElements) {
@@ -6738,7 +6781,8 @@ class VerticalEvent extends EventBase {
6738
6781
  templateElement = this.parent.getAppointmentTemplate()(record, this.parent, templateName, templateId, false);
6739
6782
  }
6740
6783
  else {
6741
- const appointmentSubject = createElement('div', { className: SUBJECT_CLASS, innerHTML: recordSubject });
6784
+ const appointmentSubject = createElement('div', { className: SUBJECT_CLASS });
6785
+ appointmentSubject.innerText = this.parent.sanitize(recordSubject);
6742
6786
  if (isAllDay) {
6743
6787
  if (record[fieldMapping.isAllDay]) {
6744
6788
  templateElement = [appointmentSubject];
@@ -6770,10 +6814,8 @@ class VerticalEvent extends EventBase {
6770
6814
  className: APPOINTMENT_TIME + (this.parent.isAdaptive ? ' ' + DISABLE_CLASS : ''),
6771
6815
  innerHTML: timeStr
6772
6816
  });
6773
- const appointmentLocation = createElement('div', {
6774
- className: LOCATION_CLASS,
6775
- innerHTML: (record[fieldMapping.location] || this.parent.eventSettings.fields.location.default || '')
6776
- });
6817
+ const appointmentLocation = createElement('div', { className: LOCATION_CLASS });
6818
+ appointmentLocation.innerText = this.parent.sanitize((record[fieldMapping.location] || this.parent.eventSettings.fields.location.default || ''));
6777
6819
  templateElement = [appointmentSubject, appointmentTime, appointmentLocation];
6778
6820
  }
6779
6821
  }
@@ -6790,7 +6832,7 @@ class VerticalEvent extends EventBase {
6790
6832
  appointmentWrapper.appendChild(recurrenceIcon);
6791
6833
  }
6792
6834
  }
6793
- this.renderSpannedIcon(isAllDay ? appointmentDetails : appointmentWrapper, eventData);
6835
+ this.parent.eventBase.renderSpannedIcon(isAllDay ? appointmentDetails : appointmentWrapper, eventData);
6794
6836
  if (!isNullOrUndefined(this.cssClass)) {
6795
6837
  addClass([appointmentWrapper], this.cssClass);
6796
6838
  }
@@ -6822,29 +6864,6 @@ class VerticalEvent extends EventBase {
6822
6864
  countCell.innerHTML = '+' + this.parent.globalize.formatNumber(moreCount) + '&nbsp;' + (this.parent.isAdaptive ? '' : this.parent.localeObj.getConstant('more'));
6823
6865
  }
6824
6866
  }
6825
- renderSpannedIcon(element, spanEvent) {
6826
- const iconElement = createElement('div', { className: EVENT_INDICATOR_CLASS + ' ' + ICON });
6827
- if (spanEvent.isLeft) {
6828
- const iconLeft = iconElement.cloneNode();
6829
- addClass([iconLeft], EVENT_ICON_LEFT_CLASS);
6830
- prepend([iconLeft], element);
6831
- }
6832
- if (spanEvent.isRight) {
6833
- const iconRight = iconElement.cloneNode();
6834
- addClass([iconRight], EVENT_ICON_RIGHT_CLASS);
6835
- append([iconRight], element);
6836
- }
6837
- if (spanEvent.isTop) {
6838
- const iconTop = iconElement.cloneNode();
6839
- addClass([iconTop], EVENT_ICON_UP_CLASS);
6840
- prepend([iconTop], element);
6841
- }
6842
- if (spanEvent.isBottom) {
6843
- const iconBottom = iconElement.cloneNode();
6844
- addClass([iconBottom], EVENT_ICON_DOWN_CLASS);
6845
- append([iconBottom], element);
6846
- }
6847
- }
6848
6867
  isSpannedEvent(record, day, resource) {
6849
6868
  let currentDate = resetTime(this.dateRender[parseInt(resource.toString(), 10)][parseInt(day.toString(), 10)]);
6850
6869
  const renderedDate = this.getRenderedDates(this.dateRender[parseInt(resource.toString(), 10)]) || [currentDate];
@@ -7646,10 +7665,8 @@ class MonthEvent extends EventBase {
7646
7665
  }
7647
7666
  else {
7648
7667
  const eventLocation = (record[this.fields.location] || this.parent.eventSettings.fields.location.default || '');
7649
- const appointmentSubject = createElement('div', {
7650
- className: SUBJECT_CLASS,
7651
- innerHTML: (eventSubject + (eventLocation ? ';&nbsp' + eventLocation : ''))
7652
- });
7668
+ const appointmentSubject = createElement('div', { className: SUBJECT_CLASS });
7669
+ appointmentSubject.innerText = this.parent.sanitize((eventSubject + (eventLocation ? '; ' + eventLocation : '')));
7653
7670
  const appointmentStartTime = createElement('div', {
7654
7671
  className: APPOINTMENT_TIME + (this.parent.isAdaptive ? ' ' + DISABLE_CLASS : ''),
7655
7672
  innerHTML: this.parent.getTimeString(eventData[this.fields.startTime])
@@ -7692,7 +7709,8 @@ class MonthEvent extends EventBase {
7692
7709
  const appTime = createElement('div', {
7693
7710
  className: APPOINTMENT_TIME + (this.parent.isAdaptive ? ' ' + DISABLE_CLASS : ''), innerHTML: timeString
7694
7711
  });
7695
- const appLocation = createElement('div', { className: LOCATION_CLASS, innerHTML: eventLocation });
7712
+ const appLocation = createElement('div', { className: LOCATION_CLASS });
7713
+ appLocation.innerText = this.parent.sanitize(eventLocation);
7696
7714
  innerElement = [appointmentSubject, appTime, appLocation];
7697
7715
  }
7698
7716
  const wrap = createElement('div', { className: 'e-inner-wrap' });
@@ -8888,6 +8906,7 @@ class QuickPopups {
8888
8906
  cssClass: QUICK_DIALOG_CLASS,
8889
8907
  closeOnEscape: true,
8890
8908
  enableRtl: this.parent.enableRtl,
8909
+ enableHtmlSanitizer: this.parent.enableHtmlSanitizer,
8891
8910
  beforeClose: this.beforeQuickDialogClose.bind(this),
8892
8911
  isModal: true,
8893
8912
  position: { X: 'center', Y: 'center' },
@@ -8919,6 +8938,7 @@ class QuickPopups {
8919
8938
  cssClass: className,
8920
8939
  disabled: isDisabled,
8921
8940
  enableRtl: this.parent.enableRtl,
8941
+ enableHtmlSanitizer: this.parent.enableHtmlSanitizer,
8922
8942
  iconCss: iconName
8923
8943
  });
8924
8944
  buttonObj.appendTo(element);
@@ -9112,7 +9132,8 @@ class QuickPopups {
9112
9132
  append(templateElement, appointmentElement);
9113
9133
  }
9114
9134
  else {
9115
- appointmentElement.appendChild(createElement('div', { className: SUBJECT_CLASS, innerHTML: eventText }));
9135
+ appointmentElement.appendChild(createElement('div', { className: SUBJECT_CLASS }));
9136
+ appointmentElement.firstElementChild.innerText = this.parent.sanitize(eventText);
9116
9137
  }
9117
9138
  if (!isNullOrUndefined(groupIndex)) {
9118
9139
  appointmentElement.setAttribute('data-group-index', groupIndex);
@@ -9361,10 +9382,14 @@ class QuickPopups {
9361
9382
  `<button class="${DELETE_CLASS + ' ' + ICON}" title="${this.l10n.getConstant('delete')}"></button>` +
9362
9383
  `<button class="${CLOSE_CLASS}" title="${this.l10n.getConstant('close')}"></button></div>` +
9363
9384
  `<div class="${SUBJECT_WRAP}"><div class="${SUBJECT_CLASS} ${TEXT_ELLIPSIS}" ` +
9364
- `title="${args.eventSubject ? args.eventSubject.replaceAll('"', '\'') : args.eventSubject}">${args.eventSubject}</div></div >`;
9385
+ `title="${args.eventSubject ? args.eventSubject.replaceAll('"', '\'') : args.eventSubject}"></div></div >`;
9365
9386
  break;
9366
9387
  }
9367
9388
  const templateWrapper = createElement('div', { innerHTML: header });
9389
+ if (headerType === 'Event') {
9390
+ const subjectText = templateWrapper.querySelector('.' + SUBJECT_CLASS);
9391
+ subjectText.innerText = this.parent.sanitize(args.eventSubject);
9392
+ }
9368
9393
  append([].slice.call(templateWrapper.childNodes), headerTemplate);
9369
9394
  }
9370
9395
  return headerTemplate;
@@ -9392,7 +9417,7 @@ class QuickPopups {
9392
9417
  `${TEXT_ELLIPSIS}">${cellDetails.details}</div></div>` +
9393
9418
  `${this.parent.activeViewOptions.group.resources.length > 0 ? `<div class="${RESOURCE_CLASS}">` +
9394
9419
  `<div class="${RESOURCE_ICON_CLASS} ${ICON} "></div><div class="${RESOURCE_DETAILS_CLASS} ` +
9395
- `${TEXT_ELLIPSIS}">${resourceText}</div></div>` : ''}</td></tr></tbody></table>`;
9420
+ `${TEXT_ELLIPSIS}"></div></div>` : ''}</td></tr></tbody></table>`;
9396
9421
  break;
9397
9422
  case 'Event':
9398
9423
  argsData = this.getFormattedString(data);
@@ -9406,8 +9431,7 @@ class QuickPopups {
9406
9431
  content += '</div></div>';
9407
9432
  if (data[this.parent.eventFields.location]) {
9408
9433
  content += '<div class="' + LOCATION_CLASS + '"><div class="' + LOCATION_ICON_CLASS + ' ' +
9409
- ICON + '"></div><div class="' + LOCATION_DETAILS_CLASS + ' ' + TEXT_ELLIPSIS + '">' +
9410
- data[this.parent.eventFields.location] + '</div></div>';
9434
+ ICON + '"></div><div class="' + LOCATION_DETAILS_CLASS + ' ' + TEXT_ELLIPSIS + '"></div></div>';
9411
9435
  }
9412
9436
  if (data[this.parent.eventFields.startTimezone] || data[this.parent.eventFields.endTimezone]) {
9413
9437
  content += '<div class="' + TIME_ZONE_CLASS + '"><div class="' + TIME_ZONE_ICON_CLASS + ' ' + ICON +
@@ -9416,17 +9440,33 @@ class QuickPopups {
9416
9440
  }
9417
9441
  if (data[this.parent.eventFields.description]) {
9418
9442
  content += '<div class="' + DESCRIPTION_CLASS + '"><div class="' + DESCRIPTION_ICON_CLASS + ' ' + ICON +
9419
- '"></div><div class="' + DESCRIPTION_DETAILS_CLASS + ' ' + TEXT_ELLIPSIS + '">' +
9420
- data[this.parent.eventFields.description] + '</div></div>';
9443
+ '"></div><div class="' + DESCRIPTION_DETAILS_CLASS + ' ' + TEXT_ELLIPSIS + '"></div></div>';
9421
9444
  }
9422
9445
  if (this.parent.resourceCollection.length > 0) {
9423
9446
  content += '<div class="' + RESOURCE_CLASS + '"><div class="' + RESOURCE_ICON_CLASS + ' ' + ICON +
9424
- '"></div><div class="' + RESOURCE_DETAILS_CLASS + ' ' + TEXT_ELLIPSIS + '">' +
9425
- resourceText + '</div></div>';
9447
+ '"></div><div class="' + RESOURCE_DETAILS_CLASS + ' ' + TEXT_ELLIPSIS + '"></div></div>';
9426
9448
  }
9427
9449
  break;
9428
9450
  }
9429
9451
  const templateWrapper = createElement('div', { innerHTML: content });
9452
+ if (data[this.parent.eventFields.location]) {
9453
+ const locationDetails = templateWrapper.querySelector('.' + LOCATION_DETAILS_CLASS);
9454
+ if (!isNullOrUndefined(locationDetails)) {
9455
+ locationDetails.innerText = this.parent.sanitize(data[this.parent.eventFields.location]);
9456
+ }
9457
+ }
9458
+ if (data[this.parent.eventFields.description]) {
9459
+ const descriptionDetails = templateWrapper.querySelector('.' + DESCRIPTION_DETAILS_CLASS);
9460
+ if (!isNullOrUndefined(descriptionDetails)) {
9461
+ descriptionDetails.innerText = this.parent.sanitize(data[this.parent.eventFields.description]);
9462
+ }
9463
+ }
9464
+ if (resourceText) {
9465
+ const resourceDetails = templateWrapper.querySelector('.' + RESOURCE_DETAILS_CLASS);
9466
+ if (!isNullOrUndefined(resourceDetails)) {
9467
+ resourceDetails.innerText = this.parent.sanitize(resourceText);
9468
+ }
9469
+ }
9430
9470
  append([].slice.call(templateWrapper.childNodes), contentTemplate);
9431
9471
  }
9432
9472
  return contentTemplate;
@@ -9955,7 +9995,7 @@ class QuickPopups {
9955
9995
  }
9956
9996
  quickPopupClose() {
9957
9997
  this.parent.eventBase.focusElement();
9958
- this.quickPopup.relateTo = WORK_CELLS_CLASS;
9998
+ this.quickPopup.relateTo = '.' + WORK_CELLS_CLASS;
9959
9999
  this.fieldValidator.destroyToolTip();
9960
10000
  if (this.quickPopup.element.querySelectorAll('.e-formvalidator').length) {
9961
10001
  this.fieldValidator.destroy();
@@ -10172,7 +10212,8 @@ class EventTooltip {
10172
10212
  target: this.getTargets(),
10173
10213
  beforeRender: this.onBeforeRender.bind(this),
10174
10214
  beforeClose: this.onBeforeClose.bind(this),
10175
- enableRtl: this.parent.enableRtl
10215
+ enableRtl: this.parent.enableRtl,
10216
+ enableHtmlSanitizer: this.parent.enableHtmlSanitizer
10176
10217
  });
10177
10218
  this.tooltipObj.appendTo(this.parent.element);
10178
10219
  }
@@ -11434,6 +11475,7 @@ class EventWindow {
11434
11475
  content: this.getEventWindowContent(),
11435
11476
  cssClass: EVENT_WINDOW_DIALOG_CLASS,
11436
11477
  enableRtl: this.parent.enableRtl,
11478
+ enableHtmlSanitizer: this.parent.enableHtmlSanitizer,
11437
11479
  height: this.parent.isAdaptive ? '100%' : 'auto',
11438
11480
  minHeight: '300px',
11439
11481
  isModal: true,
@@ -11641,6 +11683,10 @@ class EventWindow {
11641
11683
  renderFormElements(form, args) {
11642
11684
  if (!isNullOrUndefined(this.parent.editorTemplate)) {
11643
11685
  if (args) {
11686
+ if (this.fieldValidator) {
11687
+ this.fieldValidator.destroy();
11688
+ this.fieldValidator = null;
11689
+ }
11644
11690
  if (this.recurrenceEditor) {
11645
11691
  this.recurrenceEditor.destroy();
11646
11692
  this.recurrenceEditor = null;
@@ -11813,6 +11859,7 @@ class EventWindow {
11813
11859
  if (resourceData.allowMultiple) {
11814
11860
  const listObj = new MultiSelect({
11815
11861
  enableRtl: this.parent.enableRtl,
11862
+ enableHtmlSanitizer: this.parent.enableHtmlSanitizer,
11816
11863
  cssClass: this.parent.cssClass || '',
11817
11864
  dataSource: resourceData.dataSource,
11818
11865
  change: this.onMultiselectResourceChange.bind(this),
@@ -11950,6 +11997,7 @@ class EventWindow {
11950
11997
  change: this.onChange.bind(this),
11951
11998
  cssClass: value + ' ' + this.parent.cssClass,
11952
11999
  enableRtl: this.parent.enableRtl,
12000
+ enableHtmlSanitizer: this.parent.enableHtmlSanitizer,
11953
12001
  label: this.getFieldLabel(value)
11954
12002
  });
11955
12003
  checkBox.appendTo(checkBoxInput);
@@ -12076,6 +12124,7 @@ class EventWindow {
12076
12124
  target: this.element,
12077
12125
  animationSettings: { effect: 'Zoom' },
12078
12126
  enableRtl: this.parent.enableRtl,
12127
+ enableHtmlSanitizer: this.parent.enableHtmlSanitizer,
12079
12128
  isModal: true,
12080
12129
  cssClass: REPEAT_DIALOG_CLASS,
12081
12130
  open: this.repeatOpenDialog.bind(this)
@@ -12143,6 +12192,9 @@ class EventWindow {
12143
12192
  if (!this.parent.eventSettings.allowAdding) {
12144
12193
  return;
12145
12194
  }
12195
+ if (this.parent.isAdaptive && repeatType && !this.repeatDialogObject) {
12196
+ this.renderRepeatDialog();
12197
+ }
12146
12198
  this.element.querySelector('.' + FORM_CLASS).removeAttribute('data-id');
12147
12199
  this.element.querySelector('.' + EVENT_WINDOW_TITLE_TEXT_CLASS).innerHTML = this.l10n.getConstant('newEvent');
12148
12200
  eventObj.Timezone = false;
@@ -12172,10 +12224,18 @@ class EventWindow {
12172
12224
  selectedType: !isNullOrUndefined(repeatType) ? repeatType : !isNullOrUndefined(eventObj[this.fields.recurrenceRule]) ?
12173
12225
  this.recurrenceEditor.selectedType : 0
12174
12226
  });
12227
+ this.repeatRule = this.recurrenceEditor.value;
12175
12228
  }
12176
12229
  if (this.parent.isAdaptive && isNullOrUndefined(this.parent.editorTemplate)) {
12177
12230
  const element = this.element.querySelector('.' + REPEAT_CONTAINER_CLASS);
12178
- addClass([element], HIDE_STYLE_CLASS);
12231
+ if (eventObj[this.fields.recurrenceRule] || repeatType) {
12232
+ removeClass([element], HIDE_STYLE_CLASS);
12233
+ this.repeatStatus.setProperties({ checked: true });
12234
+ }
12235
+ else {
12236
+ addClass([element], HIDE_STYLE_CLASS);
12237
+ this.repeatStatus.setProperties({ checked: false });
12238
+ }
12179
12239
  this.updateRepeatLabel(this.repeatRule);
12180
12240
  }
12181
12241
  else {
@@ -12816,9 +12876,11 @@ class EventWindow {
12816
12876
  }
12817
12877
  const currentStartTime = new Date(+currentData[this.fields.startTime]);
12818
12878
  const currentEndTime = new Date(+currentData[this.fields.endTime]);
12879
+ let nextStartTime;
12880
+ let nextEndTime;
12819
12881
  if (index !== recurColl.length - 1) {
12820
- var nextStartTime = new Date(+recurColl[index + 1][this.fields.startTime]);
12821
- var nextEndTime = new Date(+recurColl[index + 1][this.fields.endTime]);
12882
+ nextStartTime = new Date(+recurColl[index + 1][this.fields.startTime]);
12883
+ nextEndTime = new Date(+recurColl[index + 1][this.fields.endTime]);
12822
12884
  }
12823
12885
  const lastEndTime = new Date(+recurColl[recurColl.length - 1][this.fields.endTime]);
12824
12886
  if (index === 0) {
@@ -13009,7 +13071,7 @@ class EventWindow {
13009
13071
  value = element.checked;
13010
13072
  }
13011
13073
  else {
13012
- value = SanitizeHtmlHelper.sanitize(element.value);
13074
+ value = this.parent.sanitize(element.value);
13013
13075
  }
13014
13076
  }
13015
13077
  return value;
@@ -14019,6 +14081,7 @@ class Crud {
14019
14081
  if (this.parent.currentAction !== 'EditFollowingEvents' && !this.isBlockEvent(eventData)
14020
14082
  && this.parent.eventBase.isBlockRange(eventData)) {
14021
14083
  this.parent.quickPopup.openValidationError('blockAlert', eventData);
14084
+ this.parent.crudModule.crudObj.isCrudAction = false;
14022
14085
  return;
14023
14086
  }
14024
14087
  const updateEvents = (eventData instanceof Array) ? eventData : [eventData];
@@ -14665,8 +14728,8 @@ var __decorate$7 = (undefined && undefined.__decorate) || function (decorators,
14665
14728
  return c > 3 && r && Object.defineProperty(target, key, r), r;
14666
14729
  };
14667
14730
  /**
14668
- * A Class that holds the collection of event fields that requires to be mapped with the dataSource
14669
- * fields along with its available configuration settings. Each field in it accepts both string and Object
14731
+ * A class that holds the collection of event fields that requires to be mapped with the dataSource
14732
+ * fields along with its available configuration settings. Each field in it accepts both string and object
14670
14733
  * data type. When each of the field is assigned with simple `string` value, it is assumed that the dataSource field
14671
14734
  * name is mapped with it. If the `object` type is defined on each fields, then the validation related settings and mapping of
14672
14735
  * those fields with dataSource can be given altogether within it.
@@ -14782,6 +14845,9 @@ __decorate$6([
14782
14845
  __decorate$6([
14783
14846
  Property()
14784
14847
  ], EventSettings.prototype, "sortComparer", void 0);
14848
+ __decorate$6([
14849
+ Property()
14850
+ ], EventSettings.prototype, "includeFiltersInQuery", void 0);
14785
14851
 
14786
14852
  var __decorate$9 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
14787
14853
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -15063,7 +15129,7 @@ class ResourceBase {
15063
15129
  classList(target, [RESOURCE_COLLAPSE_CLASS], [RESOURCE_EXPAND_CLASS]);
15064
15130
  hide = false;
15065
15131
  }
15066
- const eventElements = [].slice.call(this.parent.element.querySelectorAll('.' + APPOINTMENT_CLASS));
15132
+ const eventElements = [].slice.call(this.parent.element.querySelectorAll('.' + APPOINTMENT_CLASS + ',.' + MORE_INDICATOR_CLASS));
15067
15133
  for (const element of eventElements) {
15068
15134
  remove(element);
15069
15135
  }
@@ -15192,6 +15258,7 @@ class ResourceBase {
15192
15258
  this.treeViewObj = new TreeView({
15193
15259
  cssClass: this.parent.cssClass,
15194
15260
  enableRtl: this.parent.enableRtl,
15261
+ enableHtmlSanitizer: this.parent.enableHtmlSanitizer,
15195
15262
  fields: {
15196
15263
  dataSource: [].slice.call(this.generateTreeData()),
15197
15264
  id: 'resourceId',
@@ -15288,10 +15355,8 @@ class ResourceBase {
15288
15355
  for (let i = 0, len = resource.groupOrder.length; i < len; i++) {
15289
15356
  const resourceLevel = this.resourceCollection[parseInt(i.toString(), 10)];
15290
15357
  const resourceText = resourceLevel.dataSource.filter((resData) => resData[resourceLevel.idField] === resource.groupOrder[parseInt(i.toString(), 10)]);
15291
- const resourceName = createElement('div', {
15292
- className: RESOURCE_NAME,
15293
- innerHTML: resourceText[0][resourceLevel.textField]
15294
- });
15358
+ const resourceName = createElement('div', { className: RESOURCE_NAME });
15359
+ resourceName.innerText = this.parent.sanitize(resourceText[0][resourceLevel.textField]);
15295
15360
  headerCollection.push(resourceName);
15296
15361
  const levelIcon = createElement('div', { className: 'e-icons e-icon-next' });
15297
15362
  headerCollection.push(levelIcon);
@@ -15363,7 +15428,7 @@ class ResourceBase {
15363
15428
  this.parent.showSpinner();
15364
15429
  const promises = [];
15365
15430
  for (const resource of this.parent.resources) {
15366
- const dataModule = new Data(resource.dataSource, resource.query);
15431
+ const dataModule = new Data(this.parent, resource.dataSource, resource.query);
15367
15432
  promises.push(dataModule.getData(dataModule.generateQuery()));
15368
15433
  }
15369
15434
  Promise.all(promises).then((e) => this.dataManagerSuccess(e, isSetModel))
@@ -15997,7 +16062,7 @@ let Schedule = class Schedule extends Component {
15997
16062
  /**
15998
16063
  * Method to render react templates
15999
16064
  *
16000
- * @param {Function} callBack - specifies the callBack method
16065
+ * @param {Function} callback - Specifies the callBack method
16001
16066
  * @returns {void}
16002
16067
  * @private
16003
16068
  */
@@ -16021,6 +16086,19 @@ let Schedule = class Schedule extends Component {
16021
16086
  this.clearTemplate(templates);
16022
16087
  }
16023
16088
  }
16089
+ /**
16090
+ * Method to sanitize any suspected untrusted strings and scripts before rendering them.
16091
+ *
16092
+ * @param {string} value - A string value representing the HTML string value to be sanitized.
16093
+ * @returns {string} A sanitized Html string.
16094
+ * @private
16095
+ */
16096
+ sanitize(value) {
16097
+ if (this.enableHtmlSanitizer) {
16098
+ return SanitizeHtmlHelper.sanitize(value);
16099
+ }
16100
+ return value;
16101
+ }
16024
16102
  initializeResources(isSetModel = false) {
16025
16103
  if (this.resources.length > 0) {
16026
16104
  this.resourceBase = new ResourceBase(this);
@@ -16230,7 +16308,7 @@ let Schedule = class Schedule extends Component {
16230
16308
  followingID: this.eventSettings.fields.followingID
16231
16309
  };
16232
16310
  this.setEditorTitles();
16233
- this.dataModule = new Data(this.eventSettings.dataSource, this.eventSettings.query);
16311
+ this.dataModule = new Data(this, this.eventSettings.dataSource, this.eventSettings.query);
16234
16312
  this.crudModule = new Crud(this);
16235
16313
  }
16236
16314
  setEditorTitles() {
@@ -16643,7 +16721,9 @@ let Schedule = class Schedule extends Component {
16643
16721
  removeSelectedClass() {
16644
16722
  const selectedCells = this.getSelectedCells();
16645
16723
  for (const cell of selectedCells) {
16646
- cell.setAttribute('aria-selected', 'false');
16724
+ if (this.currentView !== 'Year') {
16725
+ cell.setAttribute('aria-selected', 'false');
16726
+ }
16647
16727
  cell.removeAttribute('tabindex');
16648
16728
  }
16649
16729
  removeClass(selectedCells, SELECTED_CELL_CLASS);
@@ -16661,8 +16741,10 @@ let Schedule = class Schedule extends Component {
16661
16741
  * @private
16662
16742
  */
16663
16743
  addSelectedClass(cells, focusCell, isPreventScroll) {
16664
- for (const cell of cells) {
16665
- cell.setAttribute('aria-selected', 'true');
16744
+ if (this.currentView !== 'Year') {
16745
+ for (const cell of cells) {
16746
+ cell.setAttribute('aria-selected', 'true');
16747
+ }
16666
16748
  }
16667
16749
  addClass(cells, SELECTED_CELL_CLASS);
16668
16750
  if (focusCell) {
@@ -17492,6 +17574,7 @@ let Schedule = class Schedule extends Component {
17492
17574
  case 'dataSource':
17493
17575
  case 'query':
17494
17576
  case 'fields':
17577
+ case 'includeFiltersInQuery':
17495
17578
  this.initializeDataModule();
17496
17579
  state.isDataManager = true;
17497
17580
  break;
@@ -17892,6 +17975,17 @@ let Schedule = class Schedule extends Component {
17892
17975
  addEvent(data) {
17893
17976
  this.crudModule.addEvent(data);
17894
17977
  }
17978
+ /**
17979
+ * Generates the occurrences of a single recurrence event based on the provided event.
17980
+ *
17981
+ * @function generateEventOccurrences
17982
+ * @param {Object} event Accepts the parent recurrence event from which the occurrences are generated.
17983
+ * @param {Date} startDate Accepts the start date for the event occurrences. If not provided, the event's start date will be used.
17984
+ * @returns {Object[]} Returns the collection of occurrence event objects.
17985
+ */
17986
+ generateEventOccurrences(event, startDate) {
17987
+ return (this.eventBase) ? this.eventBase.generateOccurrence(event, startDate) : [];
17988
+ }
17895
17989
  /**
17896
17990
  * Allows the Scheduler events data to be exported as an Excel file either in .xlsx or .csv file formats.
17897
17991
  * By default, the whole event collection bound to the Scheduler gets exported as an Excel file.
@@ -18558,6 +18652,9 @@ __decorate([
18558
18652
  __decorate([
18559
18653
  Property(null)
18560
18654
  ], Schedule.prototype, "timeFormat", void 0);
18655
+ __decorate([
18656
+ Property(true)
18657
+ ], Schedule.prototype, "enableHtmlSanitizer", void 0);
18561
18658
  __decorate([
18562
18659
  Property(false)
18563
18660
  ], Schedule.prototype, "enableAllDayScroll", void 0);
@@ -18806,6 +18903,7 @@ class ActionBase {
18806
18903
  parseInt(this.actionObj.element.getAttribute('data-group-index'), 10) === this.actionObj.groupIndex : true;
18807
18904
  if (+eventObj[this.parent.eventFields.startTime] === +this.actionObj.event[this.parent.eventFields.startTime] &&
18808
18905
  +eventObj[this.parent.eventFields.endTime] === +this.actionObj.event[this.parent.eventFields.endTime] && isSameResource) {
18906
+ this.parent.crudModule.crudObj.isCrudAction = false;
18809
18907
  return;
18810
18908
  }
18811
18909
  if (eventObj[this.parent.eventFields.recurrenceRule]) {
@@ -19079,6 +19177,10 @@ class ActionBase {
19079
19177
  }
19080
19178
  appWidth = eventObj.isSpanned.count * this.actionObj.cellWidth;
19081
19179
  }
19180
+ if (!isResize && this.parent.activeViewOptions.orientation === 'Vertical' && this.parent.activeViewOptions.group.resources.length !== 0) {
19181
+ const eventObj = this.yearEvent.isSpannedEvent(event, event[this.parent.eventFields.startTime]);
19182
+ appWidth = eventObj.isSpanned.count * this.actionObj.cellWidth;
19183
+ }
19082
19184
  const appointmentElement = this.createAppointmentElement(this.actionObj.groupIndex, event[this.parent.eventFields.subject]);
19083
19185
  appointmentElement.setAttribute('drag', 'true');
19084
19186
  addClass([appointmentElement], CLONE_ELEMENT_CLASS);
@@ -19813,7 +19915,7 @@ class YearEvent extends TimelineEvent {
19813
19915
  }
19814
19916
  timelineYearViewEvents() {
19815
19917
  const workCell = this.parent.element.querySelector('.' + WORK_CELLS_CLASS + ':not(.' + OTHERMONTH_CLASS + ')');
19816
- this.cellWidth = workCell.offsetWidth;
19918
+ this.cellWidth = workCell.getBoundingClientRect().width;
19817
19919
  this.cellHeader = getOuterHeight(workCell.querySelector('.' + DATE_HEADER_CLASS));
19818
19920
  const eventTable = this.parent.element.querySelector('.' + EVENT_TABLE_CLASS);
19819
19921
  this.eventHeight = getElementHeightFromClass(eventTable, APPOINTMENT_CLASS);
@@ -19824,7 +19926,7 @@ class YearEvent extends TimelineEvent {
19824
19926
  for (let row = 0; row < months.length; row++) {
19825
19927
  const wrapper = wrapperCollection[parseInt(row.toString(), 10)];
19826
19928
  let td = row + 1;
19827
- const eventWrapper = createElement('div', { className: APPOINTMENT_WRAPPER_CLASS });
19929
+ let eventWrapper = createElement('div', { className: APPOINTMENT_WRAPPER_CLASS });
19828
19930
  wrapper.appendChild(eventWrapper);
19829
19931
  let monthStart = new Date(this.parent.selectedDate.getFullYear(), months[parseInt(row.toString(), 10)], 1);
19830
19932
  const monthEnd = new Date(monthStart.getFullYear(), monthStart.getMonth() + 1, 0);
@@ -19839,7 +19941,7 @@ class YearEvent extends TimelineEvent {
19839
19941
  if (this.parent.activeViewOptions.orientation === 'Vertical') {
19840
19942
  const wrapper = wrapperCollection[parseInt(dayIndex.toString(), 10)];
19841
19943
  td = dayIndex + 1;
19842
- let eventWrapper = wrapper.querySelector('.' + APPOINTMENT_WRAPPER_CLASS);
19944
+ eventWrapper = wrapper.querySelector('.' + APPOINTMENT_WRAPPER_CLASS);
19843
19945
  if (!eventWrapper) {
19844
19946
  eventWrapper = createElement('div', { className: APPOINTMENT_WRAPPER_CLASS });
19845
19947
  wrapper.appendChild(eventWrapper);
@@ -19891,8 +19993,7 @@ class YearEvent extends TimelineEvent {
19891
19993
  continue;
19892
19994
  }
19893
19995
  }
19894
- const isRowAutoHeight = this.parent.rowAutoHeight && this.parent.activeViewOptions.orientation === 'Horizontal';
19895
- if (isRowAutoHeight || this.cellHeight > availedHeight) {
19996
+ if (this.parent.rowAutoHeight || this.cellHeight > availedHeight) {
19896
19997
  this.renderEvent(eventWrapper, eventData, row, leftValue, rightValue, monthStart, dayIndex);
19897
19998
  this.updateCellHeight(rowTd, availedHeight);
19898
19999
  isSpannedCollection.push(eventData);
@@ -19914,6 +20015,19 @@ class YearEvent extends TimelineEvent {
19914
20015
  }
19915
20016
  }
19916
20017
  }
20018
+ if (this.parent.rowAutoHeight && this.parent.activeViewOptions.orientation === 'Vertical') {
20019
+ const appContainer = [].slice.call(this.parent.element.querySelectorAll('.' + APPOINTMENT_CONTAINER_CLASS));
20020
+ const tr = [].slice.call(this.parent.element.querySelectorAll('.' + CONTENT_TABLE_CLASS + ' tbody tr'));
20021
+ appContainer.forEach((ele, index) => {
20022
+ const app = [].slice.call(ele.querySelectorAll('.' + APPOINTMENT_CLASS));
20023
+ const appTop = tr[parseInt(index.toString(), 10)].offsetTop + this.cellHeader + EVENT_GAP$2;
20024
+ app.forEach((app) => {
20025
+ const overlap = parseInt(app.getAttribute('data-index'), 10);
20026
+ app.style.top = appTop + (overlap * this.eventHeight) + 'px';
20027
+ app.removeAttribute('data-index');
20028
+ });
20029
+ });
20030
+ }
19917
20031
  }
19918
20032
  updateSpannedEvents(eventObj, dayStart, dayEnd) {
19919
20033
  const isLeftRightResize = (this.isResource && this.parent.activeViewOptions.orientation === 'Vertical') ||
@@ -19928,7 +20042,8 @@ class YearEvent extends TimelineEvent {
19928
20042
  }
19929
20043
  }
19930
20044
  if ((dayEnd.getTime() >= eventObj[this.fields.endTime].getTime()) || (isLeftRightResize && !this.isResource &&
19931
- addDays(dayEnd, -1).getMonth() === eventObj[this.fields.endTime].getMonth())) {
20045
+ addDays(dayEnd, -1).getMonth() === eventObj[this.fields.endTime].getMonth()) ||
20046
+ (isLeftRightResize && this.isResource && (dayEnd.getTime() <= eventObj[this.fields.endTime].getTime()))) {
19932
20047
  if (isLeftRightResize) {
19933
20048
  data.isRight = false;
19934
20049
  }
@@ -19939,8 +20054,10 @@ class YearEvent extends TimelineEvent {
19939
20054
  eventObj.data = data;
19940
20055
  }
19941
20056
  timelineResourceEvents() {
20057
+ const contentTable = this.parent.element.querySelector('.' + CONTENT_WRAP_CLASS);
20058
+ const isVerticalScrollbarAvail = contentTable.offsetWidth > contentTable.clientWidth;
19942
20059
  const workCell = this.parent.element.querySelector('.' + WORK_CELLS_CLASS);
19943
- this.cellWidth = workCell.offsetWidth;
20060
+ this.cellWidth = workCell.getBoundingClientRect().width;
19944
20061
  this.cellHeader = 0;
19945
20062
  const eventTable = this.parent.element.querySelector('.' + EVENT_TABLE_CLASS);
19946
20063
  this.eventHeight = getElementHeightFromClass(eventTable, APPOINTMENT_CLASS);
@@ -19968,6 +20085,39 @@ class YearEvent extends TimelineEvent {
19968
20085
  }
19969
20086
  }
19970
20087
  }
20088
+ if (this.parent.rowAutoHeight && !isVerticalScrollbarAvail && contentTable.offsetWidth > contentTable.clientWidth) {
20089
+ const appointments = [].slice.call(this.parent.element.querySelectorAll('.' + APPOINTMENT_CLASS));
20090
+ appointments.forEach((ele) => {
20091
+ ele.style.removeProperty('left');
20092
+ ele.style.removeProperty('right');
20093
+ });
20094
+ const appContainer = [].slice.call(this.parent.element.querySelectorAll('.' + APPOINTMENT_CONTAINER_CLASS));
20095
+ const conTable = this.parent.element.querySelector('.' + CONTENT_TABLE_CLASS);
20096
+ const tr = [].slice.call(conTable.querySelectorAll('tbody tr'));
20097
+ appContainer.forEach((ele, index) => {
20098
+ const appWrapper = [].slice.call(ele.children);
20099
+ const row = tr[parseInt(index.toString(), 10)];
20100
+ appWrapper.forEach((appWrap, cellIndex) => {
20101
+ const td = row.querySelector(`td:nth-child(${cellIndex + 1})`);
20102
+ const app = [].slice.call(appWrap.children);
20103
+ const width = td.getBoundingClientRect().width;
20104
+ const left = td.offsetLeft;
20105
+ if (this.parent.enableRtl) {
20106
+ const right = conTable.offsetWidth - left - td.offsetWidth;
20107
+ app.forEach((app) => {
20108
+ app.style.width = Math.floor(parseInt(app.style.width, 10) / width) * width + 'px';
20109
+ app.style.right = right + 'px';
20110
+ });
20111
+ }
20112
+ else {
20113
+ app.forEach((app) => {
20114
+ app.style.width = Math.floor(parseInt(app.style.width, 10) / width) * width + 'px';
20115
+ app.style.left = left + 'px';
20116
+ });
20117
+ }
20118
+ });
20119
+ });
20120
+ }
19971
20121
  }
19972
20122
  renderResourceEvent(wrapper, resource, month, index, monthStart) {
19973
20123
  const eventWrapper = createElement('div', { className: APPOINTMENT_WRAPPER_CLASS });
@@ -19978,6 +20128,7 @@ class YearEvent extends TimelineEvent {
19978
20128
  const td = this.parent.element.querySelector(`.e-content-wrap tr:nth-child(${rowIndex + 1}) td`);
19979
20129
  this.cellHeight = td.offsetHeight;
19980
20130
  this.groupOrder = resource.groupOrder;
20131
+ const isSpannedCollection = [];
19981
20132
  for (let a = 0; a < eventDatas.length; a++) {
19982
20133
  const data = eventDatas[parseInt(a.toString(), 10)];
19983
20134
  let overlapIndex;
@@ -19997,9 +20148,17 @@ class YearEvent extends TimelineEvent {
19997
20148
  if (!this.parent.isMinMaxDate(eventData[this.fields.startTime])) {
19998
20149
  return;
19999
20150
  }
20151
+ if (this.parent.activeViewOptions.orientation === 'Vertical' && this.parent.activeViewOptions.group.resources.length > 0) {
20152
+ const isRendered = this.renderedEvents.filter((eventObj) => eventObj.Guid === eventData.Guid);
20153
+ const isSpanned = isSpannedCollection.filter((eventObj) => eventObj.Guid === eventData.Guid);
20154
+ if (isRendered.length > 0 || isSpanned.length > 0) {
20155
+ continue;
20156
+ }
20157
+ }
20000
20158
  if (this.parent.rowAutoHeight || this.cellHeight > availedHeight) {
20001
20159
  this.renderEvent(eventWrapper, eventData, month, leftValue, leftValue, monthStart, index);
20002
20160
  this.updateCellHeight(td, availedHeight);
20161
+ isSpannedCollection.push(eventData);
20003
20162
  }
20004
20163
  else {
20005
20164
  const moreIndex = this.parent.activeViewOptions.orientation === 'Horizontal' ? month : index;
@@ -20035,13 +20194,16 @@ class YearEvent extends TimelineEvent {
20035
20194
  }
20036
20195
  else {
20037
20196
  index = rowIndex + 1;
20038
- width = this.cellWidth;
20197
+ width = this.isResource ? eventObj.isSpanned.count * this.cellWidth : this.cellWidth;
20039
20198
  }
20040
20199
  const rowTd = this.parent.element.querySelector(`.e-content-wrap tr:nth-child(${index}) td`);
20041
20200
  const top = rowTd.offsetTop + this.cellHeader + (this.eventHeight * eventObj.Index) + EVENT_GAP$2;
20042
20201
  setStyleAttribute(wrap, {
20043
20202
  'width': width + 'px', 'height': this.eventHeight + 'px', 'left': left + 'px', 'right': right + 'px', 'top': top + 'px'
20044
20203
  });
20204
+ if (!this.isResource && this.parent.rowAutoHeight && this.parent.activeViewOptions.orientation === 'Vertical') {
20205
+ wrap.setAttribute('data-index', eventObj.Index.toString());
20206
+ }
20045
20207
  const args = { data: eventObj, element: wrap, cancel: false, type: 'event' };
20046
20208
  this.parent.trigger(eventRendered, args, (eventArgs) => {
20047
20209
  if (!eventArgs.cancel) {
@@ -20147,6 +20309,7 @@ class YearEvent extends TimelineEvent {
20147
20309
  const appointmentDetails = createElement('div', { className: APPOINTMENT_DETAILS });
20148
20310
  append(templateElement, appointmentDetails);
20149
20311
  eventWrapper.appendChild(appointmentDetails);
20312
+ this.parent.eventBase.renderSpannedIcon(eventWrapper, record.isSpanned);
20150
20313
  this.renderResizeHandler(eventWrapper, record.data, record[this.fields.isReadonly]);
20151
20314
  this.applyResourceColor(eventWrapper, eventObj, 'backgroundColor', this.groupOrder);
20152
20315
  return eventWrapper;
@@ -20158,24 +20321,28 @@ class YearEvent extends TimelineEvent {
20158
20321
  const eventStart = eventData[this.fields.startTime];
20159
20322
  const eventEnd = eventData[this.fields.endTime];
20160
20323
  const isSpanned = { isLeft: false, isRight: false, count: 1 };
20324
+ const yearStart = new Date(this.parent.selectedDate.getFullYear(), this.parent.firstMonthOfYear, 1);
20325
+ const yearEnd = addMonths(yearStart, this.parent.monthsCount);
20161
20326
  if (this.isResource) {
20162
20327
  this.updateSpannedEvents(eventObj, monthStart, monthEnd);
20163
20328
  }
20164
- if (eventStart.getTime() < monthStart.getTime()) {
20165
- eventData[this.fields.startTime] = monthStart;
20166
- isSpanned.isLeft = true;
20167
- }
20168
- if (eventEnd.getTime() > monthEnd.getTime()) {
20169
- eventData[this.fields.endTime] = monthEnd;
20170
- isSpanned.isRight = true;
20329
+ if (this.parent.activeViewOptions.orientation === 'Vertical' && this.parent.activeViewOptions.group.resources.length > 0) {
20330
+ this.updateSpannedEventDetails(eventStart, eventEnd, yearStart, yearEnd, eventData, isSpanned);
20331
+ const originalStartTime = eventData[this.fields.startTime];
20332
+ const originalEndTime = new Date(eventData[this.fields.endTime] - 1);
20333
+ isSpanned.count = (originalEndTime.getMonth() - originalStartTime.getMonth()) +
20334
+ (this.parent.monthsCount * (originalEndTime.getFullYear() - originalStartTime.getFullYear())) + 1;
20171
20335
  }
20172
- if (this.parent.activeViewOptions.group.resources.length === 0 || this.parent.uiStateValues.isGroupAdaptive) {
20173
- let end = resetTime(eventData[this.fields.endTime]).getTime();
20174
- const start = resetTime(eventData[this.fields.startTime]).getTime();
20175
- if (eventObj[this.fields.isAllDay] && end === eventObj[this.fields.endTime].getTime() || isSpanned.isRight) {
20176
- end = addDays(new Date(end), -1).getTime();
20336
+ else {
20337
+ this.updateSpannedEventDetails(eventStart, eventEnd, monthStart, monthEnd, eventData, isSpanned);
20338
+ if (this.parent.activeViewOptions.group.resources.length === 0 || this.parent.uiStateValues.isGroupAdaptive) {
20339
+ let end = resetTime(eventData[this.fields.endTime]).getTime();
20340
+ const start = resetTime(eventData[this.fields.startTime]).getTime();
20341
+ if (eventObj[this.fields.isAllDay] && end === eventObj[this.fields.endTime].getTime() || isSpanned.isRight) {
20342
+ end = addDays(new Date(end), -1).getTime();
20343
+ }
20344
+ isSpanned.count = Math.ceil((end - start) / MS_PER_DAY) + 1;
20177
20345
  }
20178
- isSpanned.count = Math.ceil((end - start) / MS_PER_DAY) + 1;
20179
20346
  }
20180
20347
  eventData.isSpanned = isSpanned;
20181
20348
  if (resetTime(eventStart).getTime() < resetTime(this.parent.minDate).getTime()) {
@@ -20186,6 +20353,16 @@ class YearEvent extends TimelineEvent {
20186
20353
  }
20187
20354
  return eventData;
20188
20355
  }
20356
+ updateSpannedEventDetails(eventStart, eventEnd, viewStart, viewEnd, eventObj, isSpanned) {
20357
+ if (eventStart.getTime() < viewStart.getTime()) {
20358
+ eventObj[this.fields.startTime] = viewStart;
20359
+ isSpanned.isLeft = true;
20360
+ }
20361
+ if (eventEnd.getTime() > viewEnd.getTime()) {
20362
+ eventObj[this.fields.endTime] = viewEnd;
20363
+ isSpanned.isRight = true;
20364
+ }
20365
+ }
20189
20366
  getOverlapEvents(date, appointments) {
20190
20367
  const appointmentsList = [];
20191
20368
  let dateStart;
@@ -20208,19 +20385,11 @@ class YearEvent extends TimelineEvent {
20208
20385
  for (const app of appointments) {
20209
20386
  const appStart = new Date(app[this.fields.startTime].getTime());
20210
20387
  const appEnd = new Date(app[this.fields.endTime].getTime());
20211
- if (this.parent.activeViewOptions.orientation === 'Vertical' &&
20212
- this.parent.activeViewOptions.group.resources.length > 0) {
20213
- if ((resetTime(appStart).getTime() >= dateStart) && (resetTime(appEnd).getTime() <= dateEnd)) {
20214
- appointmentsList.push(app);
20215
- }
20216
- }
20217
- else {
20218
- const timeCondition = app[this.fields.isAllDay] ? resetTime(appEnd).getTime() > dateStart :
20219
- resetTime(appEnd).getTime() >= dateStart;
20220
- if (((resetTime(appStart).getTime() <= dateStart) && (timeCondition)) ||
20221
- (resetTime(appStart).getTime() >= dateStart) && (resetTime(appEnd).getTime() <= dateEnd)) {
20222
- appointmentsList.push(app);
20223
- }
20388
+ const timeCondition = app[this.fields.isAllDay] ? resetTime(appEnd).getTime() > dateStart :
20389
+ resetTime(appEnd).getTime() >= dateStart;
20390
+ if (((resetTime(appStart).getTime() <= dateStart) && (timeCondition)) ||
20391
+ (resetTime(appStart).getTime() >= dateStart) && (resetTime(appEnd).getTime() <= dateEnd)) {
20392
+ appointmentsList.push(app);
20224
20393
  }
20225
20394
  }
20226
20395
  return appointmentsList;
@@ -21950,9 +22119,9 @@ class ViewBase {
21950
22119
  append(quickTemplate, tdElement);
21951
22120
  }
21952
22121
  else {
21953
- tdElement.appendChild(createElement('div', {
21954
- className: className, innerHTML: tdData.resourceData[tdData.resource.textField]
21955
- }));
22122
+ const resourceText = createElement('div', { className: className });
22123
+ resourceText.innerText = this.parent.sanitize(tdData.resourceData[tdData.resource.textField]);
22124
+ tdElement.appendChild(resourceText);
21956
22125
  }
21957
22126
  }
21958
22127
  renderResourceMobileLayout() {
@@ -21976,7 +22145,6 @@ class ViewBase {
21976
22145
  const colElements = this.getColElements();
21977
22146
  const contentBody = this.element.querySelector('.' + CONTENT_TABLE_CLASS + ' tbody');
21978
22147
  const colWidth = (contentBody.getBoundingClientRect().width / (colElements.length / 2));
21979
- colElements.forEach((col) => setStyleAttribute(col, { 'width': formatUnit(colWidth) }));
21980
22148
  if (content.offsetHeight !== content.clientHeight) {
21981
22149
  const resourceColumn = this.parent.element.querySelector('.' + RESOURCE_COLUMN_WRAP_CLASS);
21982
22150
  if (!isNullOrUndefined(resourceColumn)) {
@@ -22188,8 +22356,8 @@ class VerticalView extends ViewBase {
22188
22356
  const content = this.getScrollableElement();
22189
22357
  const header = this.getDatesHeaderElement();
22190
22358
  const scrollerHeight = this.parent.element.offsetHeight - headerBarHeight - header.offsetHeight;
22191
- this.setColWidth(content);
22192
22359
  this.setContentHeight(content, timeCells, scrollerHeight);
22360
+ this.setColWidth(content);
22193
22361
  const scrollBarWidth = getScrollBarWidth();
22194
22362
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
22195
22363
  header.firstElementChild.style[args.cssProperties.rtlBorder] = '';
@@ -23414,9 +23582,11 @@ class Month extends ViewBase {
23414
23582
  if (!this.parent.isMinMaxDate(data.date)) {
23415
23583
  data.className.push(DISABLE_DATES);
23416
23584
  }
23417
- if (this.parent.currentView === 'MonthAgenda' && this.parent.isSelectedDate(data.date)) {
23418
- data.className.push(SELECTED_CELL_CLASS);
23419
- }
23585
+ this.updateSelectedCellClass(data);
23586
+ }
23587
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
23588
+ updateSelectedCellClass(data) {
23589
+ return;
23420
23590
  }
23421
23591
  isOtherMonth(date) {
23422
23592
  return date.getTime() < this.monthDates.start.getTime() || date.getTime() > this.monthDates.end.getTime();
@@ -23747,6 +23917,7 @@ class Year extends ViewBase {
23747
23917
  calendarElement.appendChild(this.renderCalendarContent(currentMonth));
23748
23918
  calendarWrapper.appendChild(calendarElement);
23749
23919
  }
23920
+ this.renderDates.splice(0, 1);
23750
23921
  }
23751
23922
  renderCalendarHeader(currentDate) {
23752
23923
  const headerWrapper = createElement('div', { className: 'e-header e-month' });
@@ -23805,7 +23976,7 @@ class Year extends ViewBase {
23805
23976
  for (const date of weekDates) {
23806
23977
  const td = createElement('td', {
23807
23978
  className: 'e-cell ' + WORK_CELLS_CLASS,
23808
- attrs: { 'aria-selected': 'false', 'data-date': date.getTime().toString() }
23979
+ attrs: { 'data-date': date.getTime().toString() }
23809
23980
  });
23810
23981
  if (this.parent.activeViewOptions.cellHeaderTemplate) {
23811
23982
  const args = { date: date, type: 'monthCells' };
@@ -23833,6 +24004,9 @@ class Year extends ViewBase {
23833
24004
  addClass([td], classList$$1);
23834
24005
  }
23835
24006
  tr.appendChild(td);
24007
+ if (currentDate.getMonth() === date.getMonth()) {
24008
+ this.renderDates.push(new Date(date));
24009
+ }
23836
24010
  if (!this.parent.isMinMaxDate(date)) {
23837
24011
  addClass([td], DISABLE_DATES);
23838
24012
  }
@@ -24182,9 +24356,13 @@ class AgendaBase extends ViewBase {
24182
24356
  if (!isNullOrUndefined(eventLocation) && eventLocation !== '') {
24183
24357
  eventSubject += ',';
24184
24358
  }
24185
- appSubjectWrap.appendChild(createElement('div', { className: SUBJECT_CLASS, innerHTML: eventSubject }));
24359
+ const appSubjectText = createElement('div', { className: SUBJECT_CLASS });
24360
+ appSubjectText.innerText = this.parent.sanitize(eventSubject);
24361
+ appSubjectWrap.appendChild(appSubjectText);
24186
24362
  if (!isNullOrUndefined(eventLocation) && eventLocation !== '') {
24187
- appSubjectWrap.appendChild(createElement('div', { className: LOCATION_CLASS, innerHTML: eventLocation }));
24363
+ const appLocation = createElement('div', { className: LOCATION_CLASS });
24364
+ appLocation.innerText = this.parent.sanitize(eventLocation);
24365
+ appSubjectWrap.appendChild(appLocation);
24188
24366
  }
24189
24367
  if (!isNullOrUndefined(event[fieldMapping.recurrenceRule])) {
24190
24368
  const iconClass = (event[fieldMapping.id] === event[fieldMapping.recurrenceID]) ?
@@ -24925,6 +25103,11 @@ class MonthAgenda extends Month {
24925
25103
  }
24926
25104
  return 'abbreviated';
24927
25105
  }
25106
+ updateSelectedCellClass(data) {
25107
+ if (resetTime(data.date).getTime() === resetTime(this.monthAgendaDate).getTime()) {
25108
+ data.className.push(SELECTED_CELL_CLASS);
25109
+ }
25110
+ }
24928
25111
  setEventWrapperHeight() {
24929
25112
  let headerHeight = (this.parent.headerModule ? this.parent.headerModule.getHeaderElement().offsetHeight : 0) + 2;
24930
25113
  const resourceWrapper = this.parent.element.querySelector('.' + RESOURCE_HEADER_TOOLBAR);
@@ -25731,15 +25914,15 @@ class TimelineYear extends Year {
25731
25914
  this.parent.virtualScrollModule.renderVirtualTrack(content);
25732
25915
  }
25733
25916
  const contentTBody = contentTable.querySelector('tbody');
25734
- if (this.parent.activeViewOptions.group.resources.length > 0 && !this.parent.uiStateValues.isGroupAdaptive) {
25735
- if (this.parent.rowAutoHeight) {
25736
- const addClassTable = [contentTable];
25737
- const monthHeader = this.parent.element.querySelector('.' + MONTH_HEADER_WRAPPER + ' .' + SCHEDULE_TABLE_CLASS);
25738
- if (monthHeader) {
25739
- addClassTable.push(monthHeader);
25740
- }
25741
- addClass(addClassTable, AUTO_HEIGHT);
25917
+ if (this.parent.rowAutoHeight) {
25918
+ const addClassTable = [contentTable];
25919
+ const monthHeader = this.parent.element.querySelector('.' + MONTH_HEADER_WRAPPER + ' .' + SCHEDULE_TABLE_CLASS);
25920
+ if (monthHeader) {
25921
+ addClassTable.push(monthHeader);
25742
25922
  }
25923
+ addClass(addClassTable, AUTO_HEIGHT);
25924
+ }
25925
+ if (this.parent.activeViewOptions.group.resources.length > 0 && !this.parent.uiStateValues.isGroupAdaptive) {
25743
25926
  const colCount = this.parent.activeViewOptions.orientation === 'Horizontal' ? this.colLevels.slice(-1)[0].length : this.columnCount;
25744
25927
  contentTable.appendChild(this.createTableColGroup(colCount));
25745
25928
  this.renderResourceContent(eventWrapper, monthTBody, contentTBody);
@@ -25841,6 +26024,9 @@ class TimelineYear extends Year {
25841
26024
  if (td.classList.contains(OTHERMONTH_CLASS)) {
25842
26025
  continue;
25843
26026
  }
26027
+ else {
26028
+ this.renderDates.push(new Date(date));
26029
+ }
25844
26030
  td.appendChild(dateHeader);
25845
26031
  if (isDateAvail) {
25846
26032
  td.setAttribute('data-date', date.getTime().toString());
@@ -25855,6 +26041,7 @@ class TimelineYear extends Year {
25855
26041
  }
25856
26042
  }
25857
26043
  }
26044
+ this.renderDates.splice(0, 1);
25858
26045
  }
25859
26046
  getContentRows() {
25860
26047
  const tRow = [];