@syncfusion/ej2-schedule 31.1.17 → 31.1.21

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 (168) hide show
  1. package/dist/ej2-schedule.min.js +2 -2
  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 +7 -3
  5. package/dist/es6/ej2-schedule.es2015.js.map +1 -1
  6. package/dist/es6/ej2-schedule.es5.js +6 -2
  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/package.json +18 -53
  12. package/src/schedule/actions/virtual-scroll.js +5 -1
  13. package/src/schedule/event-renderer/event-base.js +1 -1
  14. package/styles/bootstrap4-lite.css +8 -0
  15. package/styles/bootstrap4.css +8 -0
  16. package/styles/recurrence-editor/bootstrap4.css +8 -0
  17. package/styles/schedule/bootstrap4.css +8 -0
  18. package/dist/ts/common/calendar-util.d.ts +0 -92
  19. package/dist/ts/common/calendar-util.ts +0 -261
  20. package/dist/ts/common/index.d.ts +0 -4
  21. package/dist/ts/common/index.ts +0 -4
  22. package/dist/ts/components.d.ts +0 -5
  23. package/dist/ts/components.ts +0 -5
  24. package/dist/ts/index.d.ts +0 -6
  25. package/dist/ts/index.ts +0 -7
  26. package/dist/ts/recurrence-editor/date-generator.d.ts +0 -76
  27. package/dist/ts/recurrence-editor/date-generator.ts +0 -1699
  28. package/dist/ts/recurrence-editor/index.d.ts +0 -6
  29. package/dist/ts/recurrence-editor/index.ts +0 -6
  30. package/dist/ts/recurrence-editor/recurrence-editor-model.d.ts +0 -112
  31. package/dist/ts/recurrence-editor/recurrence-editor.d.ts +0 -245
  32. package/dist/ts/recurrence-editor/recurrence-editor.ts +0 -1257
  33. package/dist/ts/schedule/actions/action-base.d.ts +0 -44
  34. package/dist/ts/schedule/actions/action-base.ts +0 -493
  35. package/dist/ts/schedule/actions/crud.d.ts +0 -41
  36. package/dist/ts/schedule/actions/crud.ts +0 -784
  37. package/dist/ts/schedule/actions/data.d.ts +0 -63
  38. package/dist/ts/schedule/actions/data.ts +0 -128
  39. package/dist/ts/schedule/actions/drag.d.ts +0 -75
  40. package/dist/ts/schedule/actions/drag.ts +0 -1401
  41. package/dist/ts/schedule/actions/keyboard.d.ts +0 -100
  42. package/dist/ts/schedule/actions/keyboard.ts +0 -1435
  43. package/dist/ts/schedule/actions/resize.d.ts +0 -27
  44. package/dist/ts/schedule/actions/resize.ts +0 -602
  45. package/dist/ts/schedule/actions/scroll.d.ts +0 -69
  46. package/dist/ts/schedule/actions/scroll.ts +0 -105
  47. package/dist/ts/schedule/actions/touch.d.ts +0 -32
  48. package/dist/ts/schedule/actions/touch.ts +0 -314
  49. package/dist/ts/schedule/actions/virtual-scroll.d.ts +0 -55
  50. package/dist/ts/schedule/actions/virtual-scroll.ts +0 -596
  51. package/dist/ts/schedule/actions/work-cells.d.ts +0 -14
  52. package/dist/ts/schedule/actions/work-cells.ts +0 -151
  53. package/dist/ts/schedule/base/constant.d.ts +0 -102
  54. package/dist/ts/schedule/base/constant.ts +0 -103
  55. package/dist/ts/schedule/base/css-constant.d.ts +0 -475
  56. package/dist/ts/schedule/base/css-constant.ts +0 -475
  57. package/dist/ts/schedule/base/interface.d.ts +0 -673
  58. package/dist/ts/schedule/base/interface.ts +0 -738
  59. package/dist/ts/schedule/base/resource.d.ts +0 -59
  60. package/dist/ts/schedule/base/resource.ts +0 -1091
  61. package/dist/ts/schedule/base/schedule-model.d.ts +0 -930
  62. package/dist/ts/schedule/base/schedule.d.ts +0 -1967
  63. package/dist/ts/schedule/base/schedule.ts +0 -4221
  64. package/dist/ts/schedule/base/type.d.ts +0 -134
  65. package/dist/ts/schedule/base/type.ts +0 -142
  66. package/dist/ts/schedule/base/util.d.ts +0 -266
  67. package/dist/ts/schedule/base/util.ts +0 -492
  68. package/dist/ts/schedule/event-renderer/agenda-base.d.ts +0 -15
  69. package/dist/ts/schedule/event-renderer/agenda-base.ts +0 -423
  70. package/dist/ts/schedule/event-renderer/event-base.d.ts +0 -101
  71. package/dist/ts/schedule/event-renderer/event-base.ts +0 -1501
  72. package/dist/ts/schedule/event-renderer/inline-edit.d.ts +0 -23
  73. package/dist/ts/schedule/event-renderer/inline-edit.ts +0 -287
  74. package/dist/ts/schedule/event-renderer/month.d.ts +0 -60
  75. package/dist/ts/schedule/event-renderer/month.ts +0 -760
  76. package/dist/ts/schedule/event-renderer/timeline-view.d.ts +0 -51
  77. package/dist/ts/schedule/event-renderer/timeline-view.ts +0 -606
  78. package/dist/ts/schedule/event-renderer/vertical-view.d.ts +0 -57
  79. package/dist/ts/schedule/event-renderer/vertical-view.ts +0 -898
  80. package/dist/ts/schedule/event-renderer/year.d.ts +0 -27
  81. package/dist/ts/schedule/event-renderer/year.ts +0 -623
  82. package/dist/ts/schedule/exports/calendar-export.d.ts +0 -16
  83. package/dist/ts/schedule/exports/calendar-export.ts +0 -160
  84. package/dist/ts/schedule/exports/calendar-import.d.ts +0 -18
  85. package/dist/ts/schedule/exports/calendar-import.ts +0 -277
  86. package/dist/ts/schedule/exports/excel-export.d.ts +0 -14
  87. package/dist/ts/schedule/exports/excel-export.ts +0 -89
  88. package/dist/ts/schedule/exports/index.d.ts +0 -7
  89. package/dist/ts/schedule/exports/index.ts +0 -7
  90. package/dist/ts/schedule/exports/print.d.ts +0 -20
  91. package/dist/ts/schedule/exports/print.ts +0 -233
  92. package/dist/ts/schedule/index.d.ts +0 -26
  93. package/dist/ts/schedule/index.ts +0 -26
  94. package/dist/ts/schedule/models/event-settings-model.d.ts +0 -165
  95. package/dist/ts/schedule/models/event-settings.d.ts +0 -149
  96. package/dist/ts/schedule/models/event-settings.ts +0 -187
  97. package/dist/ts/schedule/models/field-options-model.d.ts +0 -37
  98. package/dist/ts/schedule/models/field-options.d.ts +0 -31
  99. package/dist/ts/schedule/models/field-options.ts +0 -41
  100. package/dist/ts/schedule/models/fields-model.d.ts +0 -129
  101. package/dist/ts/schedule/models/fields.d.ts +0 -117
  102. package/dist/ts/schedule/models/fields.ts +0 -149
  103. package/dist/ts/schedule/models/group-model.d.ts +0 -69
  104. package/dist/ts/schedule/models/group.d.ts +0 -60
  105. package/dist/ts/schedule/models/group.ts +0 -75
  106. package/dist/ts/schedule/models/header-rows-model.d.ts +0 -33
  107. package/dist/ts/schedule/models/header-rows.d.ts +0 -30
  108. package/dist/ts/schedule/models/header-rows.ts +0 -35
  109. package/dist/ts/schedule/models/models.d.ts +0 -14
  110. package/dist/ts/schedule/models/models.ts +0 -15
  111. package/dist/ts/schedule/models/quick-info-templates-model.d.ts +0 -52
  112. package/dist/ts/schedule/models/quick-info-templates.d.ts +0 -47
  113. package/dist/ts/schedule/models/quick-info-templates.ts +0 -56
  114. package/dist/ts/schedule/models/resources-model.d.ts +0 -122
  115. package/dist/ts/schedule/models/resources.d.ts +0 -106
  116. package/dist/ts/schedule/models/resources.ts +0 -138
  117. package/dist/ts/schedule/models/time-scale-model.d.ts +0 -57
  118. package/dist/ts/schedule/models/time-scale.d.ts +0 -50
  119. package/dist/ts/schedule/models/time-scale.ts +0 -61
  120. package/dist/ts/schedule/models/toolbar-model.d.ts +0 -196
  121. package/dist/ts/schedule/models/toolbar.d.ts +0 -176
  122. package/dist/ts/schedule/models/toolbar.ts +0 -196
  123. package/dist/ts/schedule/models/views-model.d.ts +0 -370
  124. package/dist/ts/schedule/models/views.d.ts +0 -335
  125. package/dist/ts/schedule/models/views.ts +0 -408
  126. package/dist/ts/schedule/models/work-hours-model.d.ts +0 -29
  127. package/dist/ts/schedule/models/work-hours.d.ts +0 -24
  128. package/dist/ts/schedule/models/work-hours.ts +0 -31
  129. package/dist/ts/schedule/popups/event-tooltip.d.ts +0 -16
  130. package/dist/ts/schedule/popups/event-tooltip.ts +0 -203
  131. package/dist/ts/schedule/popups/event-window.d.ts +0 -118
  132. package/dist/ts/schedule/popups/event-window.ts +0 -2055
  133. package/dist/ts/schedule/popups/form-validator.d.ts +0 -16
  134. package/dist/ts/schedule/popups/form-validator.ts +0 -110
  135. package/dist/ts/schedule/popups/quick-popups.d.ts +0 -78
  136. package/dist/ts/schedule/popups/quick-popups.ts +0 -1470
  137. package/dist/ts/schedule/renderer/agenda.d.ts +0 -45
  138. package/dist/ts/schedule/renderer/agenda.ts +0 -497
  139. package/dist/ts/schedule/renderer/day.d.ts +0 -20
  140. package/dist/ts/schedule/renderer/day.ts +0 -28
  141. package/dist/ts/schedule/renderer/header-renderer.d.ts +0 -48
  142. package/dist/ts/schedule/renderer/header-renderer.ts +0 -736
  143. package/dist/ts/schedule/renderer/month-agenda.d.ts +0 -29
  144. package/dist/ts/schedule/renderer/month-agenda.ts +0 -184
  145. package/dist/ts/schedule/renderer/month.d.ts +0 -61
  146. package/dist/ts/schedule/renderer/month.ts +0 -766
  147. package/dist/ts/schedule/renderer/renderer.d.ts +0 -13
  148. package/dist/ts/schedule/renderer/renderer.ts +0 -165
  149. package/dist/ts/schedule/renderer/timeline-header-row.d.ts +0 -15
  150. package/dist/ts/schedule/renderer/timeline-header-row.ts +0 -132
  151. package/dist/ts/schedule/renderer/timeline-month.d.ts +0 -29
  152. package/dist/ts/schedule/renderer/timeline-month.ts +0 -184
  153. package/dist/ts/schedule/renderer/timeline-view.d.ts +0 -31
  154. package/dist/ts/schedule/renderer/timeline-view.ts +0 -308
  155. package/dist/ts/schedule/renderer/timeline-year.d.ts +0 -22
  156. package/dist/ts/schedule/renderer/timeline-year.ts +0 -450
  157. package/dist/ts/schedule/renderer/vertical-view.d.ts +0 -63
  158. package/dist/ts/schedule/renderer/vertical-view.ts +0 -911
  159. package/dist/ts/schedule/renderer/view-base.d.ts +0 -83
  160. package/dist/ts/schedule/renderer/view-base.ts +0 -709
  161. package/dist/ts/schedule/renderer/week.d.ts +0 -22
  162. package/dist/ts/schedule/renderer/week.ts +0 -35
  163. package/dist/ts/schedule/renderer/work-week.d.ts +0 -22
  164. package/dist/ts/schedule/renderer/work-week.ts +0 -36
  165. package/dist/ts/schedule/renderer/year.d.ts +0 -46
  166. package/dist/ts/schedule/renderer/year.ts +0 -470
  167. package/dist/ts/schedule/timezone/timezone.d.ts +0 -16
  168. package/dist/ts/schedule/timezone/timezone.ts +0 -313
@@ -1,1435 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { KeyboardEvents, KeyboardEventArgs, closest, EventHandler, extend, Browser } from '@syncfusion/ej2-base';
3
- import { isNullOrUndefined, addClass, removeClass } from '@syncfusion/ej2-base';
4
- import { View } from '../base/type';
5
- import { Schedule } from '../base/schedule';
6
- import { CellClickEventArgs, KeyEventArgs, ResizeEdges, SelectEventArgs, InlineClickArgs, EventClickArgs, ResourceDetails, BeforePasteEventArgs } from '../base/interface';
7
- import * as event from '../base/constant';
8
- import * as util from '../base/util';
9
- import * as cls from '../base/css-constant';
10
- import { cellSelect } from '../base/constant';
11
-
12
- /**
13
- * Keyboard interaction
14
- */
15
- export class KeyboardInteraction {
16
- /**
17
- * Constructor
18
- */
19
- private parent: Schedule;
20
- private initialTarget: HTMLTableCellElement;
21
- public selectedCells: HTMLTableCellElement[] = [];
22
- private clipBoardTextArea: HTMLInputElement;
23
- private isCutContentPasted: boolean = false;
24
- private isCutAction: boolean = false;
25
- private keyConfigs: { [key: string]: string } = {
26
- downArrow: 'downarrow',
27
- upArrow: 'uparrow',
28
- rightArrow: 'rightarrow',
29
- leftArrow: 'leftarrow',
30
- shiftDownArrow: 'shift+downarrow',
31
- shiftUpArrow: 'shift+uparrow',
32
- shiftRightArrow: 'shift+rightarrow',
33
- shiftLeftArrow: 'shift+leftarrow',
34
- ctrlLeftArrow: 'ctrl+leftarrow',
35
- ctrlRightArrow: 'ctrl+rightarrow',
36
- altOne: 'alt+1',
37
- altTwo: 'alt+2',
38
- altThree: 'alt+3',
39
- altFour: 'alt+4',
40
- altFive: 'alt+5',
41
- altSix: 'alt+6',
42
- altSeven: 'alt+7',
43
- altEight: 'alt+8',
44
- altNine: 'alt+9',
45
- enter: 'enter',
46
- escape: 'escape',
47
- delete: 'delete',
48
- backspace: 'backspace',
49
- home: 'home',
50
- pageUp: 'pageup',
51
- pageDown: 'pagedown',
52
- tab: 'tab',
53
- shiftTab: 'shift+tab',
54
- ctrlShiftUpArrow: 'ctrl+shift+uparrow',
55
- ctrlShiftDownArrow: 'ctrl+shift+downarrow',
56
- ctrlShiftLeftArrow: 'ctrl+shift+leftarrow',
57
- ctrlShiftRightArrow: 'ctrl+shift+rightarrow',
58
- shiftAltY: 'shift+alt+y',
59
- shiftAltN: 'shift+alt+n',
60
- cut: 'ctrl+x',
61
- copy: 'ctrl+c',
62
- cmdCut: 'cmd+x',
63
- cmdCopy: 'cmd+c'
64
- };
65
- private keyboardModule: KeyboardEvents;
66
- constructor(parent: Schedule) {
67
- this.parent = parent;
68
- this.parent.element.tabIndex = this.parent.element.tabIndex === -1 ? 0 : this.parent.element.tabIndex;
69
- this.keyboardModule = new KeyboardEvents(this.parent.element, {
70
- keyAction: this.keyActionHandler.bind(this),
71
- keyConfigs: this.keyConfigs,
72
- eventName: 'keydown'
73
- });
74
- this.addEventListener();
75
- this.createClipboardElement();
76
- }
77
- private keyActionHandler(e: KeyboardEventArgs): void {
78
- const target: HTMLElement = e.target as HTMLElement;
79
- if (e.action === 'home' && target && ['INPUT', 'TEXTAREA', 'SELECT'].indexOf(target.tagName) > -1 && target.closest('.e-quick-popup-wrapper')) {
80
- return;
81
- }
82
- switch (e.action) {
83
- case 'downArrow':
84
- case 'shiftDownArrow':
85
- this.processDown(e, e.shiftKey);
86
- break;
87
- case 'upArrow':
88
- case 'shiftUpArrow':
89
- this.processUp(e, e.shiftKey);
90
- break;
91
- case 'leftArrow':
92
- case 'shiftLeftArrow':
93
- this.processLeft(e, e.shiftKey);
94
- break;
95
- case 'rightArrow':
96
- case 'shiftRightArrow':
97
- this.processRight(e, e.shiftKey);
98
- break;
99
- case 'ctrlLeftArrow':
100
- this.parent.changeDate(this.parent.activeView.getNextPreviousDate('Previous'), e);
101
- if (this.parent.headerModule) {
102
- (this.parent.headerModule.element.querySelector('.e-prev button') as HTMLElement).focus();
103
- }
104
- break;
105
- case 'ctrlRightArrow':
106
- this.parent.changeDate(this.parent.activeView.getNextPreviousDate('Next'), e);
107
- if (this.parent.headerModule) {
108
- (this.parent.headerModule.element.querySelector('.e-next button') as HTMLElement).focus();
109
- }
110
- break;
111
- case 'altOne':
112
- case 'altTwo':
113
- case 'altThree':
114
- case 'altFour':
115
- case 'altFive':
116
- case 'altSix':
117
- case 'altSeven':
118
- case 'altEight':
119
- case 'altNine':
120
- this.processViewNavigation(e);
121
- break;
122
- case 'enter':
123
- this.processEnter(e);
124
- break;
125
- case 'home':
126
- this.focusFirstCell();
127
- break;
128
- case 'tab':
129
- case 'shiftTab':
130
- this.processTab(e, e.shiftKey);
131
- break;
132
- case 'delete':
133
- case 'backspace':
134
- this.processDelete(e);
135
- break;
136
- case 'ctrlShiftUpArrow':
137
- case 'ctrlShiftDownArrow':
138
- case 'ctrlShiftLeftArrow':
139
- case 'ctrlShiftRightArrow':
140
- this.processCtrlShiftNavigationArrows(e);
141
- break;
142
- case 'escape':
143
- this.processEscape(e);
144
- break;
145
- case 'fTwelve':
146
- if (this.parent.allowInline && this.parent.inlineModule) {
147
- e.preventDefault();
148
- this.processFTwelve(e);
149
- }
150
- break;
151
- case 'shiftAltY':
152
- this.parent.changeDate(new Date(), e);
153
- break;
154
- case 'shiftAltN':
155
- if (this.parent.currentView === 'Agenda' || this.parent.currentView === 'MonthAgenda' ||
156
- this.parent.currentView === 'Year') {
157
- return;
158
- }
159
- this.processShiftAltN(e);
160
- break;
161
- case 'cut':
162
- case 'cmdCut':
163
- if (e.ctrlKey || e.metaKey) {
164
- this.processClipboardAction(true, undefined, e);
165
- }
166
- break;
167
- case 'copy':
168
- case 'cmdCopy':
169
- if (e.ctrlKey || e.metaKey) {
170
- this.processClipboardAction(false, undefined, e);
171
- }
172
- break;
173
- }
174
- }
175
-
176
- private processShiftAltN(e: Event): void {
177
- const selectedCells: Element[] = this.parent.getSelectedCells();
178
- const target: HTMLTableCellElement = e.target as HTMLTableCellElement;
179
- let cellData: CellClickEventArgs = <CellClickEventArgs>extend({}, null, true);
180
- if (selectedCells.length > 0 && (closest(target, '.' + cls.WORK_CELLS_CLASS)
181
- || closest(target, '.' + cls.ALLDAY_CELLS_CLASS) || closest(target, '.' + cls.HEADER_CELLS_CLASS))) {
182
- cellData = this.getSelectedElements(target);
183
- }
184
- else if (closest(target, '.' + cls.APPOINTMENT_CLASS) && !isNullOrUndefined(this.parent.activeEventData.event)) {
185
- const event: { StartTime: Date, EndTime: Date, IsAllDay: boolean } =
186
- this.parent.activeEventData.event as { StartTime: Date, EndTime: Date, IsAllDay: boolean };
187
- cellData.startTime = event.StartTime;
188
- cellData.endTime = event.EndTime;
189
- cellData.isAllDay = event.IsAllDay;
190
- }
191
- else {
192
- const workHour: Date = this.parent.getStartEndTime(this.parent.workHours.start);
193
- const slotInterval: number = this.parent.activeViewOptions.timeScale.interval /
194
- this.parent.activeViewOptions.timeScale.slotCount;
195
- cellData.startTime = new Date(this.parent.selectedDate);
196
- cellData.startTime.setHours(workHour.getHours(), workHour.getMinutes(), 0, 0);
197
- cellData.endTime = new Date(cellData.startTime.getTime() + slotInterval * 60000);
198
- }
199
- const args: CellClickEventArgs = <CellClickEventArgs>extend(cellData, { cancel: false, event: e });
200
- if (args != null) {
201
- this.parent.eventWindow.openEditor(args, 'Add');
202
- }
203
- }
204
-
205
- private processFTwelve(e: KeyboardEventArgs): void {
206
- const target: HTMLTableCellElement = e.target as HTMLTableCellElement;
207
- if (target.classList.contains(cls.WORK_CELLS_CLASS) || target.classList.contains(cls.ALLDAY_CELLS_CLASS)) {
208
- this.parent.activeCellsData = this.getSelectedElements(target);
209
- const args: CellClickEventArgs = <CellClickEventArgs>extend(this.parent.activeCellsData, { cancel: false, event: e });
210
- const inlineArgs: InlineClickArgs = {
211
- element: args.element as HTMLElement,
212
- groupIndex: args.groupIndex, type: 'Cell'
213
- };
214
- this.parent.notify(event.inlineClick, inlineArgs);
215
- }
216
- if (target.classList.contains(cls.APPOINTMENT_CLASS)) {
217
- target.click();
218
- return;
219
- }
220
- }
221
- private addEventListener(): void {
222
- this.parent.on(event.cellMouseDown, this.onCellMouseDown, this);
223
- if (this.parent.allowClipboard) {
224
- this.parent.on(event.documentPaste, this.pasteHandler, this);
225
- }
226
- }
227
- private removeEventListener(): void {
228
- this.parent.off(event.cellMouseDown, this.onCellMouseDown);
229
- this.parent.off(event.documentPaste, this.pasteHandler);
230
- }
231
-
232
- private onCellMouseDown(e: { event: Event & MouseEvent }): void {
233
- if (e.event.shiftKey) { return; }
234
- this.initialTarget = this.getClosestCell(e.event);
235
- if (this.parent.activeViewOptions.readonly || this.parent.currentView === 'MonthAgenda' || !this.initialTarget) { return; }
236
- if ((e.event.target as HTMLElement).classList.contains(cls.WORK_CELLS_CLASS) && e.event.which !== 3) {
237
- this.parent.removeSelectedClass();
238
- EventHandler.add(this.parent.getContentTable(), 'mousemove', this.onMouseSelection, this);
239
- EventHandler.add(this.parent.getContentTable(), 'mouseup mouseleave', this.onMoveUp, this);
240
- }
241
- if ((e.event.target as HTMLElement).classList.contains(cls.ALLDAY_CELLS_CLASS) && e.event.which !== 3) {
242
- this.parent.removeSelectedClass();
243
- const allDayRow: HTMLTableRowElement = <HTMLTableRowElement>this.parent.getAllDayRow();
244
- EventHandler.add(allDayRow, 'mousemove', this.onMouseSelection, this);
245
- EventHandler.add(allDayRow, 'mouseup mouseleave', this.onMoveUp, this);
246
- }
247
- }
248
-
249
- public onMouseSelection(e: MouseEvent): void {
250
- const appointments: Element[] = [].slice.call(this.parent.element.querySelectorAll('.' + cls.APPOINTMENT_CLASS)) as Element[];
251
- addClass(appointments, 'e-allow-select');
252
- const selectionEdges: ResizeEdges = this.parent.boundaryValidation(e.pageY, e.pageX);
253
- if (selectionEdges.bottom || selectionEdges.top || selectionEdges.left || selectionEdges.right) {
254
- const parent: HTMLElement = this.parent.element.querySelector('.' + cls.CONTENT_WRAP_CLASS) as HTMLElement;
255
- const yInBounds: boolean = parent.offsetHeight <= parent.scrollHeight && parent.scrollTop >= 0 &&
256
- parent.scrollTop + parent.offsetHeight <= parent.scrollHeight;
257
- const xInBounds: boolean = parent.offsetWidth <= parent.scrollWidth && parent.scrollLeft >= 0 &&
258
- parent.scrollLeft + parent.offsetWidth <= parent.scrollWidth;
259
- if (yInBounds && (selectionEdges.top || selectionEdges.bottom)) {
260
- parent.scrollTop += selectionEdges.top ? -(e.target as HTMLElement).offsetHeight : (e.target as HTMLElement).offsetHeight;
261
- }
262
- if (xInBounds && (selectionEdges.left || selectionEdges.right)) {
263
- parent.scrollLeft += selectionEdges.left ? -(e.target as HTMLElement).offsetWidth : (e.target as HTMLElement).offsetWidth;
264
- }
265
- }
266
- const target: HTMLTableCellElement = this.getClosestCell(e);
267
- if (target) {
268
- this.selectCells(true, target);
269
- }
270
- }
271
-
272
- private getClosestCell(e: Event): HTMLTableCellElement {
273
- return closest(<Element>e.target, '.' + cls.WORK_CELLS_CLASS + ',.' + cls.ALLDAY_CELLS_CLASS) as HTMLTableCellElement;
274
- }
275
- private onMoveUp(e: Event): void {
276
- const appointments: Element[] = [].slice.call(this.parent.element.querySelectorAll('.' + cls.APPOINTMENT_CLASS)) as Element[];
277
- removeClass(appointments, 'e-allow-select');
278
- EventHandler.remove(this.parent.getContentTable(), 'mousemove', this.onMouseSelection);
279
- EventHandler.remove(this.parent.getContentTable(), 'mouseup mouseleave', this.onMoveUp);
280
- if ((e.target as HTMLElement).classList.contains(cls.ALLDAY_CELLS_CLASS)) {
281
- const allDayRow: HTMLTableRowElement = <HTMLTableRowElement>this.parent.getAllDayRow();
282
- EventHandler.remove(allDayRow, 'mousemove', this.onMouseSelection);
283
- EventHandler.remove(allDayRow, 'mouseup mouseleave', this.onMoveUp);
284
- }
285
- if (this.isPreventAction(e)) {
286
- return;
287
- }
288
- const queryStr: string = '.' + cls.WORK_CELLS_CLASS + ',.' + cls.ALLDAY_CELLS_CLASS + ',.' + cls.HEADER_CELLS_CLASS;
289
- let target: HTMLTableCellElement = closest((e.target as Element), queryStr) as HTMLTableCellElement;
290
- if (!target) { return; }
291
- const selectedCells: Element[] = this.parent.getSelectedCells();
292
- if (selectedCells.length > 0 && selectedCells.indexOf(target) === -1) {
293
- target = selectedCells[selectedCells.length - 1] as HTMLTableCellElement;
294
- }
295
- if (this.parent.currentView === 'TimelineYear' && target.classList.contains(cls.OTHERMONTH_CLASS)) {
296
- return;
297
- }
298
- this.parent.activeCellsData = this.getSelectedElements(target);
299
- const cellData: Record<string, any> = {};
300
- if (this.parent.eventWindow) {
301
- this.parent.eventWindow.convertToEventData(this.parent.activeCellsData as unknown as Record<string, any>, cellData);
302
- }
303
- const args: SelectEventArgs = {
304
- data: cellData, element: this.parent.activeCellsData.element, event: e,
305
- requestType: cellSelect, showQuickPopup: false
306
- };
307
- this.parent.trigger(event.select, args, (selectArgs: SelectEventArgs) => {
308
- const isPopupShow: boolean = selectArgs.showQuickPopup || this.parent.quickInfoOnSelectionEnd;
309
- if (isPopupShow && selectedCells.length > 1) {
310
- const cellArgs: CellClickEventArgs =
311
- <CellClickEventArgs>extend(this.parent.activeCellsData, { cancel: false, event: e, name: 'cellClick' });
312
- this.parent.notify(event.cellClick, cellArgs);
313
- }
314
- });
315
- }
316
- private processEnter(e: Event): void {
317
- if ((this.parent.activeViewOptions.readonly && !(e.target as Element).classList.contains(cls.APPOINTMENT_CLASS))
318
- || this.isPreventAction(e)) {
319
- return;
320
- }
321
- if (this.parent.currentView === 'TimelineYear' && (e.target as Element).classList.contains(cls.OTHERMONTH_CLASS)) {
322
- return;
323
- }
324
- const target: HTMLTableCellElement = e.target as HTMLTableCellElement;
325
- if (closest(target, '.' + cls.POPUP_WRAPPER_CLASS)) {
326
- if (target.classList.contains(cls.QUICK_POPUP_EVENT_DETAILS_CLASS) ||
327
- target.classList.contains(cls.EVENT_CREATE_CLASS) ||
328
- target.classList.contains(cls.EDIT_EVENT_CLASS) ||
329
- target.classList.contains(cls.DELETE_EVENT_CLASS) ||
330
- target.classList.contains(cls.CLOSE_CLASS)) {
331
- target.click();
332
- e.preventDefault();
333
- } else if (target.classList.contains(cls.SUBJECT_CLASS)) {
334
- (this.parent.element.querySelector('.' + cls.EVENT_CREATE_CLASS) as HTMLElement).click();
335
- e.preventDefault();
336
- }
337
- return;
338
- }
339
- if (target.classList.contains(cls.RESOURCE_CELLS_CLASS) && target.classList.contains(cls.RESOURCE_PARENT_CLASS)) {
340
- const resourceIcon: HTMLElement = target.querySelector('.' + cls.RESOURCE_TREE_ICON_CLASS) as HTMLElement;
341
- if (resourceIcon) {
342
- resourceIcon.click();
343
- }
344
- return;
345
- }
346
- if (target.classList.contains(cls.WORK_CELLS_CLASS) || target.classList.contains(cls.ALLDAY_CELLS_CLASS)) {
347
- this.parent.activeCellsData = this.getSelectedElements(target);
348
- const args: CellClickEventArgs = <CellClickEventArgs>extend(this.parent.activeCellsData, { cancel: false, event: e });
349
- if (this.parent.allowInline) {
350
- const inlineArgs: InlineClickArgs = {
351
- element: args.element as HTMLElement,
352
- groupIndex: args.groupIndex, type: 'Cell'
353
- };
354
- this.parent.notify(event.inlineClick, inlineArgs);
355
- } else {
356
- if (this.parent.currentView === 'Year') {
357
- target.click();
358
- } else {
359
- this.parent.notify(event.cellClick, args);
360
- }
361
- }
362
- return;
363
- }
364
- if (target.classList.contains(cls.INLINE_SUBJECT_CLASS) && this.parent.inlineModule) {
365
- this.parent.inlineModule.inlineCrudActions(target);
366
- return;
367
- }
368
- if (target.classList.contains(cls.APPOINTMENT_CLASS) || target.classList.contains(cls.MORE_EVENT_CLOSE_CLASS) ||
369
- target.classList.contains(cls.ALLDAY_APPOINTMENT_SECTION_CLASS) || target.classList.contains(cls.MORE_INDICATOR_CLASS)) {
370
- target.click();
371
- return;
372
- }
373
- if (target.classList.contains(cls.MORE_EVENT_HEADER_DATE_CLASS)) {
374
- this.parent.setProperties({ selectedDate: this.parent.getDateFromElement(target) }, true);
375
- this.parent.changeView(this.parent.getNavigateView(), e);
376
- this.processEscape(e);
377
- return;
378
- }
379
- }
380
- private getSelectedElements(target: HTMLTableCellElement): CellClickEventArgs {
381
- let cellDetails: CellClickEventArgs;
382
- if (this.selectedCells.length > 1 && target.classList.contains(cls.SELECTED_CELL_CLASS)) {
383
- const start: CellClickEventArgs = this.parent.getCellDetails(this.selectedCells[0]);
384
- const end: CellClickEventArgs = this.parent.getCellDetails(this.selectedCells.slice(-1)[0]);
385
- start.endTime = end.endTime;
386
- start.element = target;
387
- cellDetails = start;
388
- } else {
389
- cellDetails = this.parent.getCellDetails(target);
390
- }
391
- return cellDetails;
392
- }
393
- private getCells(isInverseTable: boolean, start: HTMLTableCellElement, end: HTMLTableCellElement): HTMLTableCellElement[] {
394
- const tableEle: HTMLTableElement = this.parent.getContentTable() as HTMLTableElement;
395
- const isTimelineYear: boolean = this.parent.currentView === 'TimelineYear';
396
- const query: string = isTimelineYear && !isInverseTable ? '.' + cls.WORK_CELLS_CLASS + ':not(.' + cls.OTHERMONTH_CLASS + ')' : 'td';
397
- let cells: HTMLTableCellElement[] = [].slice.call(tableEle.querySelectorAll(query));
398
- let maxRow: number = tableEle.rows.length;
399
- let maxColumn: number = tableEle.rows[0].cells.length;
400
- if (start && start.classList.contains(cls.ALLDAY_CELLS_CLASS)) {
401
- const allDayRow: HTMLTableRowElement = this.parent.getAllDayRow() as HTMLTableRowElement;
402
- cells = [].slice.call(allDayRow.cells);
403
- maxRow = 1;
404
- maxColumn = allDayRow.cells.length;
405
- }
406
- let startIndex: number = cells.indexOf(start);
407
- let endIndex: number = cells.indexOf(end);
408
- const inverseCells: HTMLTableCellElement[] = [];
409
- if (isInverseTable) {
410
- for (let i: number = 0; i < maxColumn; i++) {
411
- for (let j: number = 0; j < maxRow; j++) {
412
- const cell: HTMLTableCellElement = cells[maxColumn * j + i];
413
- if (isTimelineYear && cell.classList.contains(cls.OTHERMONTH_CLASS)) {
414
- continue;
415
- }
416
- inverseCells.push(cell);
417
- }
418
- }
419
- startIndex = inverseCells.indexOf(start);
420
- endIndex = inverseCells.indexOf(end);
421
- }
422
- if (startIndex > endIndex) {
423
- const temp: number = startIndex;
424
- startIndex = endIndex;
425
- endIndex = temp;
426
- }
427
- const sCells: HTMLTableCellElement[] = isInverseTable ? inverseCells : cells;
428
- return sCells.slice(startIndex, endIndex + 1);
429
- }
430
- private focusFirstCell(): void {
431
- if (this.parent.currentView === 'Agenda') {
432
- const focusCell: HTMLElement = this.parent.getContentTable().querySelector('.' + cls.AGENDA_CELLS_CLASS) as HTMLTableCellElement;
433
- focusCell.setAttribute('tabindex', '0');
434
- focusCell.focus();
435
- return;
436
- }
437
- this.parent.eventBase.removeSelectedAppointmentClass();
438
- if (this.parent.activeView.isTimelineView() && this.parent.currentView !== 'TimelineYear') {
439
- const cell: Element = this.parent.element.querySelector('.' + cls.CONTENT_TABLE_CLASS +
440
- ' tr:not(.' + cls.HIDDEN_CLASS + ') .' + cls.WORK_CELLS_CLASS + ':not(.' + cls.RESOURCE_GROUP_CELLS_CLASS + ')');
441
- this.selectCells(false, cell as HTMLTableCellElement);
442
- } else if (this.parent.currentView.indexOf('Year') > -1) {
443
- let query: string = '.' + cls.WORK_CELLS_CLASS + ':not(.' + cls.OTHERMONTH_CLASS + ')' + ':not(.' + cls.RESOURCE_GROUP_CELLS_CLASS + ')';
444
- const isVerticalYear: boolean = this.parent.currentView === 'TimelineYear' && this.parent.activeViewOptions.orientation === 'Vertical';
445
- query += isVerticalYear ? '[data-date="' + this.parent.activeView.startDate().getTime() + '"]' : '';
446
- this.selectCells(false, this.parent.element.querySelector(query));
447
- } else {
448
- this.selectCells(false, this.parent.getWorkCellElements()[0] as HTMLTableCellElement);
449
- }
450
- }
451
- private isInverseTableSelect(): boolean {
452
- return this.parent.activeView.isInverseTableSelect;
453
- }
454
- /**
455
- * Internal method to select cells
456
- *
457
- * @param {boolean} isMultiple Accepts to select multiple cells or not
458
- * @param {HTMLTableCellElement} targetCell Accepts the target cells
459
- * @returns {void}
460
- * @private
461
- */
462
- public selectCells(isMultiple: boolean, targetCell: HTMLTableCellElement): void {
463
- this.parent.removeSelectedClass();
464
- let target: HTMLTableCellElement = (targetCell instanceof Array) ? targetCell.slice(-1)[0] : targetCell;
465
- if (isMultiple) {
466
- let initialId: string;
467
- const views: string[] = ['Day', 'Week', 'WorkWeek', 'TimelineDay', 'TimelineWeek', 'TimelineWorkWeek', 'TimelineMonth', 'TimelineYear'];
468
- const args: SelectEventArgs = { element: targetCell, requestType: 'mousemove', allowMultipleRow: true };
469
- this.parent.inlineModule.removeInlineAppointmentElement();
470
- this.parent.trigger(event.select, args, (selectArgs: SelectEventArgs) => {
471
- const allowMultipleRow: boolean = (!selectArgs.allowMultipleRow) || (!this.parent.allowMultiRowSelection);
472
- if (allowMultipleRow) {
473
- const isTimelineYear: boolean = this.parent.currentView === 'TimelineYear';
474
- if (isTimelineYear && this.parent.activeViewOptions.orientation === 'Horizontal' || this.parent.currentView === 'Month') {
475
- const isGroupYear: boolean = isTimelineYear && this.parent.activeViewOptions.group.resources.length > 0;
476
- target = isGroupYear ? this.initialTarget :
477
- this.initialTarget.parentElement.children[target.cellIndex] as HTMLTableCellElement;
478
- } else if (views.indexOf(this.parent.currentView) > -1) {
479
- target = target.parentElement.children[this.initialTarget.cellIndex] as HTMLTableCellElement;
480
- }
481
- }
482
- let selectedCells: HTMLTableCellElement[] = this.getCells(this.isInverseTableSelect(), this.initialTarget, target);
483
- if (this.parent.activeViewOptions.group.resources.length > 0) {
484
- initialId = this.initialTarget.getAttribute('data-group-index');
485
- const resourceSelectedCells: HTMLTableCellElement[] = [];
486
- for (const cell of selectedCells) {
487
- if (cell.getAttribute('data-group-index') === initialId) {
488
- resourceSelectedCells.push(cell);
489
- }
490
- }
491
- selectedCells = resourceSelectedCells;
492
- }
493
- if (!this.parent.allowMultiCellSelection) {
494
- selectedCells = [this.initialTarget];
495
- }
496
- this.selectedCells = selectedCells;
497
- if (selectedCells.length > 2 && !target.classList.contains(cls.ALLDAY_CELLS_CLASS)) {
498
- let allDayCells: HTMLTableCellElement[] = this.getAllDayCells(selectedCells);
499
- if (this.parent.activeViewOptions.group.resources.length > 0) {
500
- const resourceAllDayCells: HTMLTableCellElement[] = [];
501
- for (const cell of allDayCells) {
502
- if (cell.getAttribute('data-group-index') === initialId) {
503
- resourceAllDayCells.push(cell);
504
- }
505
- }
506
- allDayCells = resourceAllDayCells;
507
- }
508
- selectedCells = selectedCells.concat(allDayCells);
509
- }
510
- if ((target.getAttribute('data-group-index') !== initialId) && this.parent.activeViewOptions.group.resources.length > 0) {
511
- target = this.selectedCells[this.selectedCells.length - 1];
512
- }
513
- this.parent.addSelectedClass(selectedCells, target);
514
- });
515
- } else {
516
- const args: SelectEventArgs = {
517
- element: target, requestType: cellSelect
518
- };
519
- // activeCellsData is not reset on schedule property changed(group properties)
520
- // const cellData: Record<string, any> = {};
521
- // const cellDetails: CellClickEventArgs = this.parent.getCellDetails(target);
522
- // if (this.parent.eventWindow && cellDetails) {
523
- // if (this.parent.activeCellsData.element !== cellDetails.element) {
524
- // this.parent.activeCellsData = cellDetails;
525
- // }
526
- // this.parent.eventWindow.convertToEventData(this.parent.activeCellsData as unknown as Record<string, any>, cellData);
527
- // args.data = cellData;
528
- // }
529
- this.parent.trigger(event.select, args, () => {
530
- this.initialTarget = target;
531
- this.selectedCells = [target];
532
- this.parent.addSelectedClass([target], target);
533
- });
534
- }
535
- }
536
- private selectAppointment(isReverse: boolean, target: Element): void {
537
- const appointments: HTMLElement[] = this.getAppointmentElements();
538
- if (appointments.length < 0) {
539
- return;
540
- }
541
- this.parent.eventBase.removeSelectedAppointmentClass();
542
- let nextAppEle: HTMLElement;
543
- if (target.classList.contains(cls.APPOINTMENT_CLASS)) {
544
- const targetIndex: number = appointments.indexOf(target as HTMLElement);
545
- nextAppEle = appointments[(isReverse ? targetIndex - 1 : targetIndex + 1)];
546
- } else {
547
- nextAppEle = isReverse ? appointments[appointments.length - 1] : appointments[0];
548
- }
549
- if (nextAppEle) {
550
- this.parent.eventBase.addSelectedAppointments([nextAppEle], true);
551
- nextAppEle.focus();
552
- addClass([nextAppEle as Element], cls.AGENDA_SELECTED_CELL);
553
- }
554
- }
555
- private selectAppointmentElementFromWorkCell(isReverse: boolean, target: Element): void {
556
- this.parent.eventBase.removeSelectedAppointmentClass();
557
- this.parent.removeSelectedClass();
558
- if (target.classList.contains(cls.WORK_CELLS_CLASS) || target.classList.contains(cls.ALLDAY_CELLS_CLASS)) {
559
- const appointmentElements: HTMLElement[] = this.getUniqueAppointmentElements();
560
- const filteredElements: HTMLElement[] = [];
561
- const selectedDate: number = this.parent.getDateFromElement(target).getTime();
562
- const selectedSeriesEvents: Record<string, any>[] = this.parent.eventsProcessed.filter((eventObject: Record<string, any>) => {
563
- return (!isReverse ? ((<Date>eventObject[this.parent.eventFields.startTime]).getTime() >= selectedDate) :
564
- ((<Date>eventObject[this.parent.eventFields.startTime]).getTime() <= selectedDate));
565
- }) as Record<string, any>[];
566
- selectedSeriesEvents.filter((event: Record<string, any>) => {
567
- appointmentElements.filter((element: HTMLElement) => {
568
- if (JSON.stringify(event.Guid) === JSON.stringify(element.getAttribute('data-guid'))) {
569
- filteredElements.push(element);
570
- }
571
- });
572
- });
573
- if (filteredElements.length > 0) {
574
- const selectedElement: Element = isReverse ? filteredElements[filteredElements.length - 1] : filteredElements[0];
575
- const focusElements: HTMLElement[] = this.getAppointmentElementsByGuid(selectedElement.getAttribute('data-guid'));
576
- this.parent.eventBase.addSelectedAppointments(focusElements, true);
577
- (focusElements[focusElements.length - 1]).focus();
578
- }
579
- }
580
- }
581
- private getAllDayCells(cells: HTMLTableCellElement[]): HTMLTableCellElement[] {
582
- const allDayRow: HTMLTableRowElement = <HTMLTableRowElement>this.parent.getAllDayRow();
583
- if (!allDayRow) { return []; }
584
- const startCell: HTMLTableCellElement = cells[0];
585
- const endCell: HTMLTableCellElement = cells[cells.length - 1];
586
- const start: CellClickEventArgs = this.parent.getCellDetails(startCell);
587
- const end: CellClickEventArgs = this.parent.getCellDetails(endCell);
588
- if (end.endTime.getTime() - start.startTime.getTime() >= util.MS_PER_DAY) {
589
- const allDayCells: HTMLTableCellElement[] = [].slice.call(allDayRow.cells);
590
- return allDayCells.slice(startCell.cellIndex, endCell.cellIndex + 1);
591
- }
592
- return [];
593
- }
594
- private getAppointmentElements(): HTMLElement[] {
595
- return [].slice.call(this.parent.element.querySelectorAll('.' + cls.APPOINTMENT_CLASS));
596
- }
597
- private getAppointmentElementsByGuid(guid: string): HTMLElement[] {
598
- return [].slice.call(this.parent.element.querySelectorAll('div[data-guid="' + guid + '"]'));
599
- }
600
- private getUniqueAppointmentElements(): HTMLElement[] {
601
- const appointments: HTMLElement[] = this.getAppointmentElements();
602
- const appointmentElements: HTMLElement[] = [];
603
- appointments.map((value: HTMLElement) => value.getAttribute('data-guid')).filter((value: string, index: number, self: string[]) => {
604
- if (self.indexOf(value) === index) {
605
- appointmentElements.push(appointments[parseInt(index.toString(), 10)]);
606
- }
607
- });
608
- return appointmentElements;
609
- }
610
- private getWorkCellFromAppointmentElement(target: Element): HTMLTableCellElement {
611
- const selectedObject: Record<string, any> =
612
- this.parent.eventBase.getEventByGuid(target.getAttribute('data-guid')) as Record<string, any>;
613
- return this.parent.eventBase.selectWorkCellByTime([selectedObject]) as HTMLTableCellElement;
614
- }
615
- private processViewNavigation(e: KeyboardEventArgs): void {
616
- if (isNullOrUndefined(e.code)) {
617
- return;
618
- }
619
- const index: number = parseInt(e.code.slice(e.code.length - 1), 10) - 1;
620
- if (!isNaN(index) && !isNullOrUndefined(this.parent.views) && index < this.parent.views.length) {
621
- const view: View = this.parent.viewCollections[parseInt(index.toString(), 10)].option;
622
- this.parent.changeView(view, e, undefined, index);
623
- if (this.parent.headerModule) {
624
- (this.parent.headerModule.element.querySelector('.e-active-view button') as HTMLElement).focus();
625
- }
626
- }
627
- }
628
- private isCalendarTarget(e: KeyboardEventArgs): boolean {
629
- const keyTarget: Element = e.currentTarget as Element || e.target as Element;
630
- if (keyTarget && !isNullOrUndefined(keyTarget.querySelector('.e-header-popup.e-popup-open'))) {
631
- return true;
632
- }
633
- return false;
634
- }
635
- private cancelUpDownAction(isTimelineYear: boolean): boolean {
636
- const isVerticalYear: boolean = isTimelineYear && this.parent.activeViewOptions.orientation === 'Vertical';
637
- const isGroup: boolean = this.parent.activeViewOptions.group.resources.length > 0;
638
- if (isVerticalYear && isGroup || isTimelineYear && this.initialTarget.classList.contains(cls.OTHERMONTH_CLASS)) {
639
- return true;
640
- }
641
- if (this.parent.activeView.isTimelineView() && !isTimelineYear || this.parent.currentView === 'MonthAgenda') {
642
- return true;
643
- }
644
- return false;
645
- }
646
- private processUp(e: KeyboardEventArgs, isMultiple: boolean): void {
647
- const isTimelineYear: boolean = this.parent.currentView === 'TimelineYear';
648
- if (isMultiple && this.cancelUpDownAction(isTimelineYear) || (this.isCalendarTarget(e))) {
649
- return;
650
- }
651
- let target: HTMLTableCellElement = (e.target) as HTMLTableCellElement;
652
- const selectedElements: Element[] = this.parent.getSelectedCells();
653
- const selectedEventElements: Element[] = this.parent.eventBase.getSelectedAppointments();
654
- const moreEventWrapper: HTMLElement = <HTMLElement>this.parent.element.querySelector('.' + cls.MORE_POPUP_WRAPPER_CLASS);
655
- const quickPopupWrapper: HTMLElement = this.getQuickPopupElement();
656
- if (selectedElements.length > 0 && !(e.target as HTMLTableCellElement).classList.contains(cls.WORK_CELLS_CLASS)) {
657
- target = selectedElements[selectedElements.length - 1] as HTMLTableCellElement;
658
- }
659
- if (selectedEventElements.length > 0 && !moreEventWrapper.classList.contains(cls.POPUP_OPEN) &&
660
- !quickPopupWrapper.classList.contains(cls.POPUP_OPEN) &&
661
- ['Day', 'Week', 'WorkWeek', 'Month'].indexOf(this.parent.currentView) !== -1) {
662
- target = this.getWorkCellFromAppointmentElement(selectedEventElements[selectedEventElements.length - 1]);
663
- this.parent.eventBase.removeSelectedAppointmentClass();
664
- }
665
- if (!target) { return; }
666
- if (target.classList.contains(cls.WORK_CELLS_CLASS) && !this.parent.element.querySelector('.' + cls.POPUP_OPEN)) {
667
- const tableRows: HTMLTableRowElement[] = this.parent.getTableRows() as HTMLTableRowElement[];
668
- const curRowIndex: number = tableRows.indexOf(target.parentElement as HTMLTableRowElement);
669
- let targetCell: HTMLTableCellElement;
670
- if (isTimelineYear && isMultiple && this.parent.activeViewOptions.group.resources.length === 0) {
671
- targetCell = this.isInverseTableSelect() ? this.getVerticalUpDownCell(tableRows, target, curRowIndex, true) :
672
- this.getHorizontalUpDownCell(tableRows, target, curRowIndex, true);
673
- }
674
- if ((curRowIndex > 0 || targetCell) && curRowIndex < tableRows.length) {
675
- targetCell = targetCell ? targetCell : (tableRows[curRowIndex - 1]).cells[target.cellIndex];
676
- if (this.parent.currentView === 'Year' && targetCell.classList.contains(cls.OTHERMONTH_CLASS)) {
677
- if (this.parent.activeView.getStartDate().getTime() < +targetCell.getAttribute('data-date')) {
678
- targetCell = this.getYearUpDownCell(tableRows, curRowIndex - 1, target.cellIndex, true);
679
- } else {
680
- return;
681
- }
682
- }
683
- e.preventDefault();
684
- this.selectCells(isMultiple, targetCell);
685
- }
686
- } else if (this.parent.currentView === 'Agenda' || this.parent.currentView === 'MonthAgenda') {
687
- this.selectAppointment(true, target);
688
- }
689
- }
690
- private processDown(e: KeyboardEventArgs, isMultiple: boolean): void {
691
- const isTimelineYear: boolean = this.parent.currentView === 'TimelineYear';
692
- if (isMultiple && this.cancelUpDownAction(isTimelineYear) || (this.isCalendarTarget(e))) {
693
- return;
694
- }
695
- let target: HTMLTableCellElement = (e.target) as HTMLTableCellElement;
696
- const selectedCells: Element[] = this.parent.getSelectedCells();
697
- const selectedElements: Element[] = this.parent.eventBase.getSelectedAppointments();
698
- const moreEventWrapper: HTMLElement = <HTMLElement>this.parent.element.querySelector('.' + cls.MORE_POPUP_WRAPPER_CLASS);
699
- const quickPopupWrapper: HTMLElement = this.getQuickPopupElement();
700
- if (selectedCells.length > 0 && !(e.target as HTMLTableCellElement).classList.contains(cls.WORK_CELLS_CLASS)) {
701
- target = selectedCells[selectedCells.length - 1] as HTMLTableCellElement;
702
- }
703
- if (selectedElements.length > 0 && !moreEventWrapper.classList.contains(cls.POPUP_OPEN) &&
704
- !quickPopupWrapper.classList.contains(cls.POPUP_OPEN) &&
705
- ['Day', 'Week', 'WorkWeek', 'Month'].indexOf(this.parent.currentView) !== -1) {
706
- target = this.getWorkCellFromAppointmentElement(selectedElements[selectedElements.length - 1]);
707
- this.parent.eventBase.removeSelectedAppointmentClass();
708
- }
709
- const tableRows: HTMLTableRowElement[] = this.parent.getTableRows() as HTMLTableRowElement[];
710
- if (!target) { return; }
711
- if (target.classList.contains(cls.WORK_CELLS_CLASS) && !this.parent.element.querySelector('.' + cls.POPUP_OPEN)) {
712
- const curRowIndex: number = tableRows.indexOf(target.parentElement as HTMLTableRowElement);
713
- let targetCell: HTMLTableCellElement;
714
- if (isTimelineYear && isMultiple && this.parent.activeViewOptions.group.resources.length === 0) {
715
- targetCell = this.isInverseTableSelect() ? this.getVerticalUpDownCell(tableRows, target, curRowIndex, false)
716
- : this.getHorizontalUpDownCell(tableRows, target, curRowIndex, false);
717
- }
718
- if (curRowIndex >= 0 && ((curRowIndex < tableRows.length - 1) || targetCell)) {
719
- targetCell = targetCell ? targetCell : (tableRows[curRowIndex + 1]).cells[target.cellIndex];
720
- if (this.parent.currentView === 'Year' && targetCell.classList.contains(cls.OTHERMONTH_CLASS)) {
721
- if (this.parent.activeView.getEndDate().getTime() > +targetCell.getAttribute('data-date')) {
722
- targetCell = this.getYearUpDownCell(tableRows, curRowIndex + 1, target.cellIndex, false);
723
- } else {
724
- return;
725
- }
726
- }
727
- e.preventDefault();
728
- this.selectCells(isMultiple, targetCell);
729
- }
730
- } else if (this.parent.currentView === 'Agenda' || this.parent.currentView === 'MonthAgenda') {
731
- this.selectAppointment(false, target);
732
- }
733
- }
734
- private getYearUpDownCell(tableRows: HTMLTableRowElement[], rowIndex: number, cellIndex: number, isUp: boolean): HTMLTableCellElement {
735
- while (tableRows[parseInt(rowIndex.toString(), 10)] &&
736
- tableRows[parseInt(rowIndex.toString(), 10)].cells[parseInt(cellIndex.toString(), 10)].classList.contains(cls.OTHERMONTH_CLASS)) {
737
- rowIndex = rowIndex + (isUp ? -1 : 1);
738
- }
739
- return tableRows[parseInt(rowIndex.toString(), 10)].cells[parseInt(cellIndex.toString(), 10)];
740
- }
741
- // eslint-disable-next-line max-len
742
- private getHorizontalUpDownCell(tableRows: HTMLTableRowElement[], target: HTMLTableCellElement, curRowIndex: number, isUp: boolean): HTMLTableCellElement {
743
- const row: HTMLTableRowElement = tableRows[curRowIndex + (isUp ? -1 : 1)];
744
- let cell: HTMLTableCellElement = row ? row.cells[target.cellIndex] : target;
745
- if (cell.classList.contains(cls.OTHERMONTH_CLASS)) {
746
- const workCell: HTMLTableCellElement = row.querySelector('.' + cls.WORK_CELLS_CLASS + ':not(.' + cls.OTHERMONTH_CLASS + ')');
747
- const date: Date = new Date(+workCell.getAttribute('data-date'));
748
- const query: string = '[data-date="' + new Date(date.getFullYear(), date.getMonth() + 1, 0).getTime() + '"]';
749
- cell = cell.cellIndex < workCell.cellIndex ? workCell : row.querySelector(query);
750
- }
751
- return cell;
752
- }
753
- // eslint-disable-next-line max-len
754
- private getVerticalUpDownCell(tableRows: HTMLTableRowElement[], target: HTMLTableCellElement, curRowIndex: number, isUp: boolean): HTMLTableCellElement {
755
- const hasRow: boolean = isUp && curRowIndex > 0 || !isUp && curRowIndex < tableRows.length - 1;
756
- let targetCell: HTMLTableCellElement = hasRow ? tableRows[curRowIndex + (isUp ? -1 : 1)].cells[target.cellIndex] : undefined;
757
- if (!targetCell || targetCell.classList.contains(cls.OTHERMONTH_CLASS)) {
758
- const column: HTMLTableCellElement = tableRows[parseInt(curRowIndex.toString(), 10)].cells[target.cellIndex - (isUp ? 1 : -1)];
759
- if (column) {
760
- const dateAttr: number = +target.getAttribute('data-date') - (isUp ? util.MS_PER_DAY : -util.MS_PER_DAY);
761
- return this.parent.getContentTable().querySelector('.' + cls.WORK_CELLS_CLASS + '[data-date="' + dateAttr + '"]');
762
- }
763
- targetCell = target;
764
- }
765
- return targetCell;
766
- }
767
- private processLeftRight(target: HTMLTableCellElement): KeyEventArgs {
768
- const tableEle: HTMLTableElement = (this.parent.currentView === 'Year' ? target.closest('tbody') : this.parent.getContentTable()) as HTMLTableElement;
769
- const curRowIndex: number = (target.parentNode as HTMLTableRowElement).sectionRowIndex;
770
- const key: KeyEventArgs = {
771
- element: tableEle,
772
- rowIndex: curRowIndex,
773
- columnIndex: target.cellIndex,
774
- maxIndex: tableEle.rows[parseInt(curRowIndex.toString(), 10)].cells.length
775
- };
776
- return key;
777
- }
778
- private getQuickPopupElement(): HTMLElement {
779
- return (this.parent.isAdaptive ? document.body : this.parent.element).querySelector('.' + cls.POPUP_WRAPPER_CLASS) as HTMLElement;
780
- }
781
- private isCancelLeftRightAction(e: KeyboardEventArgs, isMultiple: boolean, isTimelineYear: boolean): boolean {
782
- const prevent: boolean = this.parent.currentView === 'MonthAgenda' || isTimelineYear && this.initialTarget.classList.contains(cls.OTHERMONTH_CLASS);
783
- if (this.parent.currentView === 'Agenda' || (isMultiple && prevent)) {
784
- return true;
785
- }
786
- if (this.isPreventAction(e) && isMultiple) {
787
- return true;
788
- }
789
- const moreEventWrapper: HTMLElement = <HTMLElement>this.parent.element.querySelector('.' + cls.MORE_POPUP_WRAPPER_CLASS);
790
- const quickPopupWrapper: HTMLElement = this.getQuickPopupElement();
791
- if (moreEventWrapper.classList.contains(cls.POPUP_OPEN) || quickPopupWrapper.classList.contains(cls.POPUP_OPEN)) {
792
- return true;
793
- }
794
- return false;
795
- }
796
- private processRight(e: KeyboardEventArgs, isMultiple: boolean): void {
797
- const isTimelineYear: boolean = this.parent.currentView === 'TimelineYear';
798
- if (this.isCancelLeftRightAction(e, isMultiple, isTimelineYear) || (this.isCalendarTarget(e))) {
799
- return;
800
- }
801
- const selectedCells: Element[] = this.parent.getSelectedCells();
802
- let targetCell: HTMLTableCellElement;
803
- const selectedAppointments: Element[] = this.parent.eventBase.getSelectedAppointments();
804
- let target: HTMLTableCellElement = (e.target) as HTMLTableCellElement;
805
- if (selectedCells.length > 0 && !target.classList.contains(cls.WORK_CELLS_CLASS) &&
806
- !target.classList.contains(cls.ALLDAY_CELLS_CLASS)) {
807
- target = selectedCells[selectedCells.length - 1] as HTMLTableCellElement;
808
- }
809
- if (selectedAppointments.length > 0) {
810
- target = this.getWorkCellFromAppointmentElement(selectedAppointments[selectedAppointments.length - 1]);
811
- this.parent.eventBase.removeSelectedAppointmentClass();
812
- if (!target) { return; }
813
- }
814
- if (target.classList.contains(cls.WORK_CELLS_CLASS) &&
815
- ((e.target) as HTMLTableCellElement).classList.contains(cls.WORK_CELLS_CLASS)) {
816
- const key: KeyEventArgs = this.processLeftRight(target);
817
- const targetDate: Date = new Date(+target.getAttribute('data-date'));
818
- const isMonthEnd: boolean = this.parent.currentView === 'Year' && targetDate.getTime() === util.lastDateOfMonth(targetDate).getTime();
819
- if (key.columnIndex >= 0 && key.columnIndex < key.maxIndex - 1 && !isMonthEnd) {
820
- targetCell = this.calculateNextPrevDate(target, key.element.rows[key.rowIndex].cells[target.cellIndex + 1], 'right');
821
- if (isTimelineYear && isMultiple && targetCell.classList.contains(cls.OTHERMONTH_CLASS)) {
822
- targetCell = this.getTimelineYearTargetCell(key, target, true);
823
- }
824
- if (!isNullOrUndefined(targetCell)) {
825
- this.selectCells(isMultiple, targetCell);
826
- }
827
- } else if (key.columnIndex === key.maxIndex - 1 || isMonthEnd) {
828
- if (!this.isInverseTableSelect() && key.rowIndex < key.element.rows.length - 1 && !isMonthEnd) {
829
- targetCell = this.calculateNextPrevDate(target, key.element.rows[key.rowIndex + 1].cells[0], 'right');
830
- const changeTargetCell: boolean = isTimelineYear && isMultiple && targetCell.classList.contains(cls.OTHERMONTH_CLASS);
831
- targetCell = changeTargetCell ? this.getHorizontalLeftRightCell(key, target, true) : targetCell;
832
- if (!isNullOrUndefined(targetCell)) {
833
- this.selectCells(isMultiple, targetCell);
834
- }
835
- } else if (!isMultiple) {
836
- if (isMonthEnd && targetDate.getTime() !== this.parent.activeView.getEndDate().getTime()) {
837
- this.selectCells(isMultiple, this.parent.element.querySelector(':not(.' + cls.OTHERMONTH_CLASS + ')[data-date="' + (targetDate.getTime() + util.MS_PER_DAY) + '"]'));
838
- return;
839
- }
840
-
841
- const rowIndex: number = this.isInverseTableSelect() ? key.rowIndex : 0;
842
- this.parent.changeDate(this.parent.activeView.getNextPreviousDate('Next'), e);
843
- const tableEle: HTMLTableElement = this.parent.getContentTable() as HTMLTableElement;
844
- const cell: HTMLTableCellElement = isMonthEnd ? tableEle.rows[parseInt(rowIndex.toString(), 10)].querySelector('.' + cls.WORK_CELLS_CLASS + ':not(.' + cls.OTHERMONTH_CLASS + ')')
845
- : tableEle.rows[parseInt(rowIndex.toString(), 10)].cells[0];
846
- this.selectCells(false, cell);
847
- }
848
- }
849
- } else if (target.classList.contains(cls.ALLDAY_CELLS_CLASS)) {
850
- const curColIndex: number = target.cellIndex;
851
- const allDayRow: HTMLTableRowElement = <HTMLTableRowElement>this.parent.getAllDayRow();
852
- const maxColIndex: number = allDayRow.cells.length;
853
- if (curColIndex >= 0 && curColIndex < maxColIndex - 1) {
854
- this.selectCells(isMultiple, allDayRow.cells[curColIndex + 1]);
855
- } else if (curColIndex === maxColIndex - 1 && !isMultiple) {
856
- this.parent.changeDate(this.parent.activeView.getNextPreviousDate('Next'), e);
857
- const allDayRow: HTMLTableRowElement = <HTMLTableRowElement>this.parent.getAllDayRow();
858
- this.selectCells(false, allDayRow.cells[0]);
859
- }
860
- }
861
- }
862
- private processLeft(e: KeyboardEventArgs, isMultiple: boolean): void {
863
- const isTimelineYear: boolean = this.parent.currentView === 'TimelineYear';
864
- if (this.isCancelLeftRightAction(e, isMultiple, isTimelineYear) || (this.isCalendarTarget(e))) {
865
- return;
866
- }
867
- let target: HTMLTableCellElement = (e.target) as HTMLTableCellElement;
868
- const selectedCells: Element[] = this.parent.getSelectedCells();
869
- let targetCell: HTMLTableCellElement;
870
- if (selectedCells.length > 0 && !target.classList.contains(cls.WORK_CELLS_CLASS) &&
871
- !target.classList.contains(cls.ALLDAY_CELLS_CLASS)) {
872
- target = selectedCells[selectedCells.length - 1] as HTMLTableCellElement;
873
- }
874
- const selectedElements: Element[] = this.parent.eventBase.getSelectedAppointments();
875
- if (selectedElements.length > 0) {
876
- target = this.getWorkCellFromAppointmentElement(selectedElements[selectedElements.length - 1]);
877
- this.parent.eventBase.removeSelectedAppointmentClass();
878
- if (!target) { return; }
879
- }
880
- if (((e.target) as HTMLTableCellElement).classList.contains(cls.WORK_CELLS_CLASS) &&
881
- target.classList.contains(cls.WORK_CELLS_CLASS)) {
882
- const key: KeyEventArgs = this.processLeftRight(target);
883
- const targetDate: Date = new Date(+target.getAttribute('data-date'));
884
- const isMonthStart: boolean = this.parent.currentView === 'Year' && targetDate.getTime() === util.firstDateOfMonth(targetDate).getTime();
885
- if (key.columnIndex > 0 && key.columnIndex < key.maxIndex && !isMonthStart) {
886
- targetCell = this.calculateNextPrevDate(target, key.element.rows[key.rowIndex].cells[target.cellIndex - 1], 'left');
887
- if (isTimelineYear && isMultiple && targetCell.classList.contains(cls.OTHERMONTH_CLASS)) {
888
- targetCell = this.getTimelineYearTargetCell(key, target, false);
889
- }
890
- if (!isNullOrUndefined(targetCell)) {
891
- this.selectCells(isMultiple, targetCell);
892
- }
893
- } else if (key.columnIndex === 0 || isMonthStart) {
894
- if (!this.isInverseTableSelect() && key.rowIndex > 0) {
895
- targetCell = this.calculateNextPrevDate(target, key.element.rows[key.rowIndex - 1].cells[key.maxIndex - 1], 'left');
896
- const otherMonthCell: boolean = isTimelineYear && isMultiple && targetCell.classList.contains(cls.OTHERMONTH_CLASS);
897
- targetCell = otherMonthCell ? this.getHorizontalLeftRightCell(key, target, false) : targetCell;
898
- if (!isNullOrUndefined(targetCell)) {
899
- this.selectCells(isMultiple, targetCell);
900
- }
901
- } else if (!isMultiple) {
902
- if (isMonthStart && targetDate.getTime() !== this.parent.activeView.getStartDate().getTime()) {
903
- this.selectCells(isMultiple, this.parent.element.querySelector('[data-date="' + (targetDate.getTime() - util.MS_PER_DAY) + '"]'));
904
- return;
905
- }
906
-
907
- this.parent.changeDate(this.parent.activeView.getNextPreviousDate('Previous'), e);
908
- const tableEle: HTMLTableElement = this.parent.getContentTable() as HTMLTableElement;
909
- const rowIndex: number = this.isInverseTableSelect() ? key.rowIndex : tableEle.rows.length - 1;
910
- let cell: HTMLTableCellElement = tableEle.rows[parseInt(rowIndex.toString(), 10)].cells[key.maxIndex - 1];
911
- if (isMonthStart) {
912
- const tbody: NodeListOf<Element> = this.parent.element.querySelectorAll('.' + cls.CONTENT_TABLE_CLASS + ' tbody');
913
- cell = tbody.item(tbody.length - 1).querySelector(':not(.' + cls.OTHERMONTH_CLASS + ')[data-date="' + this.parent.activeView.getEndDate().getTime() + '"]');
914
- }
915
- this.selectCells(false, cell);
916
- }
917
- }
918
- } else if (target.classList.contains(cls.ALLDAY_CELLS_CLASS)) {
919
- const curColIndex: number = target.cellIndex;
920
- const allDayRow: HTMLTableRowElement = <HTMLTableRowElement>this.parent.getAllDayRow();
921
- const maxColIndex: number = allDayRow.cells.length;
922
- if (curColIndex > 0 && curColIndex < maxColIndex) {
923
- this.selectCells(isMultiple, allDayRow.cells[curColIndex - 1]);
924
- } else if (curColIndex === 0 && !isMultiple) {
925
- this.parent.changeDate(this.parent.activeView.getNextPreviousDate('Previous'), e);
926
- const allDayRow: HTMLTableRowElement = <HTMLTableRowElement>this.parent.getAllDayRow();
927
- this.selectCells(false, allDayRow.cells[maxColIndex - 1]);
928
- }
929
- }
930
- }
931
- private getTimelineYearTargetCell(key: KeyEventArgs, target: HTMLTableCellElement, isRight: boolean): HTMLTableCellElement {
932
- return this.isInverseTableSelect() ? this.getVerticalLeftRightCell(target, isRight) :
933
- this.getHorizontalLeftRightCell(key, target, isRight);
934
- }
935
- private getHorizontalLeftRightCell(key: KeyEventArgs, target: HTMLTableCellElement, isRight: boolean): HTMLTableCellElement {
936
- const row: HTMLTableRowElement = key.element.rows[(<HTMLTableRowElement>target.parentNode).sectionRowIndex + (isRight ? 1 : -1)];
937
- if (row) {
938
- const query: string = isRight ? '.' + cls.WORK_CELLS_CLASS + ':not(.' + cls.OTHERMONTH_CLASS + ')'
939
- : '[data-date="' + ((+target.getAttribute('data-date')) - util.MS_PER_DAY) + '"]';
940
- return row.querySelector(query);
941
- }
942
- return target;
943
- }
944
- private getVerticalLeftRightCell(target: HTMLTableCellElement, isRight: boolean): HTMLTableCellElement {
945
- const date: Date = new Date(+target.getAttribute('data-date'));
946
- const start: Date = new Date(date.getFullYear(), date.getMonth() + (isRight ? 1 : -1), 1);
947
- const tableEle: HTMLTableElement = this.parent.getContentTable() as HTMLTableElement;
948
- const targetCell: HTMLTableCellElement = tableEle.querySelector('[data-date="' + start.getTime() + '"]');
949
- if ((targetCell.parentNode as HTMLTableRowElement).sectionRowIndex > (target.parentNode as HTMLTableRowElement).sectionRowIndex) {
950
- return targetCell;
951
- }
952
- return tableEle.querySelector('[data-date="' + new Date(start.getFullYear(), start.getMonth() + 1, 0).getTime() + '"]');
953
- }
954
- private calculateNextPrevDate(currentCell: HTMLTableCellElement, target: HTMLTableCellElement, type: string): HTMLTableCellElement {
955
- const initialId: string = this.initialTarget.getAttribute('data-group-index');
956
- if (this.parent.activeViewOptions.group.resources.length > 0 && this.parent.currentView === 'Month') {
957
- if (currentCell && target && target.getAttribute('data-group-index') !== initialId) {
958
- const currentDate: Date = this.parent.getDateFromElement(currentCell);
959
- const nextPrevDate: Date = (type === 'right') ? new Date(currentDate.setDate(currentDate.getDate() + 1))
960
- : new Date(currentDate.setDate(currentDate.getDate() - 1));
961
- target = [].slice.call(this.parent.element.querySelectorAll('td[data-date="'
962
- + nextPrevDate.getTime().toString() + '"]' + '[data-group-index="' + initialId + '"]'))[0];
963
- }
964
- }
965
- return target;
966
- }
967
-
968
- private getFocusableElements(container: Element): Element[] {
969
- const queryString: string = 'a[href]:not([tabindex="-1"]),input:not([disabled]):not([tabindex="-1"]),' +
970
- 'textarea:not([disabled]):not([tabindex="-1"]),button:not([disabled]):not([tabindex="-1"]),' +
971
- 'select:not([disabled]):not([tabindex="-1"]),[tabindex]:not([tabindex="-1"]),[contentEditable=true]:not([tabindex="-1"])';
972
- return [].slice.call(container.querySelectorAll(queryString));
973
- }
974
-
975
- private processTabOnPopup(e: KeyboardEventArgs, popupElement: Element): void {
976
- let focusableElements: Element[] = this.getFocusableElements(popupElement);
977
- focusableElements = focusableElements.filter((element: Element) => {
978
- const footerEle: HTMLElement = this.parent.element.querySelector('.' + cls.POPUP_FOOTER_CLASS) as HTMLElement;
979
- if (footerEle && footerEle.offsetParent) {
980
- return !(element.classList.contains(cls.EDIT_CLASS) || element.classList.contains(cls.DELETE_CLASS));
981
- } else {
982
- return !(element.classList.contains(cls.EDIT_EVENT_CLASS) || element.classList.contains(cls.DELETE_EVENT_CLASS));
983
- }
984
- });
985
- const firstEle: Element = focusableElements[0];
986
- const lastEle: Element = focusableElements[focusableElements.length - 1];
987
- if (!isNullOrUndefined(lastEle) && document.activeElement === lastEle && !e.shiftKey) {
988
- e.preventDefault();
989
- (firstEle as HTMLElement).focus();
990
- }
991
- if (!isNullOrUndefined(firstEle) && document.activeElement === firstEle && e.shiftKey) {
992
- e.preventDefault();
993
- (lastEle as HTMLElement).focus();
994
- }
995
- }
996
-
997
- private processTab(e: KeyboardEventArgs, isReverse: boolean): void {
998
- let target: Element = e.target as Element;
999
- if (target.classList.contains(cls.INLINE_SUBJECT_CLASS) && this.parent.inlineModule) {
1000
- target = target.closest('.e-appointment');
1001
- this.parent.inlineModule.inlineCrudActions(e.target as HTMLTableCellElement);
1002
- }
1003
- if (this.parent.currentView === 'TimelineYear' && target.classList.contains(cls.OTHERMONTH_CLASS)) {
1004
- if (target.classList.contains(cls.SELECTED_CELL_CLASS)) {
1005
- this.parent.removeSelectedClass();
1006
- }
1007
- return;
1008
- }
1009
- const popupWrapper: Element = closest(target, '.' + cls.POPUP_WRAPPER_CLASS + ',.' + cls.MORE_POPUP_WRAPPER_CLASS);
1010
- if (popupWrapper && popupWrapper.classList.contains(cls.POPUP_OPEN)) {
1011
- if (popupWrapper.classList.contains(cls.MORE_POPUP_WRAPPER_CLASS)) {
1012
- this.parent.eventBase.removeSelectedAppointmentClass();
1013
- }
1014
- this.processTabOnPopup(e, popupWrapper);
1015
- return;
1016
- }
1017
- if (target.classList.contains(cls.ROOT)) {
1018
- this.parent.eventBase.removeSelectedAppointmentClass();
1019
- return;
1020
- }
1021
- if (target.classList.contains(cls.RESOURCE_CELLS_CLASS) && this.parent.activeView.isTimelineView()
1022
- && this.parent.activeViewOptions.group.resources.length > 0) {
1023
- const index: number = parseInt(target.getAttribute('data-group-index'), 10);
1024
- const appSelector: string = `.${cls.APPOINTMENT_CLASS}[data-group-index="${isReverse ? index - 1 : index}"]`;
1025
- const appElements: HTMLElement[] = [].slice.call(this.parent.element.querySelectorAll(appSelector));
1026
- if (appElements.length > 0) {
1027
- this.parent.eventBase.removeSelectedAppointmentClass();
1028
- const focusAppointment: HTMLElement = isReverse ? appElements.slice(-1)[0] : appElements[0];
1029
- this.parent.eventBase.addSelectedAppointments([focusAppointment], true);
1030
- focusAppointment.focus();
1031
- e.preventDefault();
1032
- } else if (index + 1 === this.parent.resourceBase.lastResourceLevel.length) {
1033
- this.parent.element.focus();
1034
- e.preventDefault();
1035
- } else if (this.parent.virtualScrollModule) {
1036
- const virtual: HTMLElement = this.parent.element.querySelector('.' + cls.VIRTUAL_TRACK_CLASS) as HTMLElement;
1037
- const averageRowHeight: number = Math.round(virtual.offsetHeight / this.parent.resourceBase.expandedResources.length);
1038
- this.parent.element.querySelector('.e-content-wrap').scrollTop = ((isReverse ? index - 1 : index + 1) * averageRowHeight);
1039
- this.parent.virtualScrollModule.virtualScrolling();
1040
- } else {
1041
- this.setScrollPosition(index);
1042
- }
1043
- return;
1044
- }
1045
- if (target.classList.contains(cls.APPOINTMENT_CLASS)) {
1046
- let appElements: HTMLElement[] = [].slice.call(this.parent.element.querySelectorAll('.' + cls.APPOINTMENT_CLASS));
1047
- const isTimelineYear: boolean = this.parent.currentView === 'TimelineYear';
1048
- const isTimeline: boolean = this.parent.activeView.isTimelineView() && !isTimelineYear;
1049
- if ((isTimeline || isTimelineYear && this.parent.activeViewOptions.orientation === 'Vertical') && this.parent.activeViewOptions.group.resources.length > 0) {
1050
- const index: number = parseInt(target.getAttribute('data-group-index'), 10);
1051
- appElements = [].slice.call(this.parent.element.querySelectorAll(`.${cls.APPOINTMENT_CLASS}[data-group-index="${index}"]`));
1052
- const resCellSelector: string = `.${cls.RESOURCE_CELLS_CLASS}[data-group-index="${isReverse ? index : index + 1}"]`;
1053
- const resourceCell: HTMLElement = this.parent.element.querySelector(resCellSelector) as HTMLElement;
1054
- if (resourceCell && (isReverse && target.getAttribute('data-guid') === appElements[0].getAttribute('data-guid') ||
1055
- !isReverse && target.getAttribute('data-guid') === appElements.slice(-1)[0].getAttribute('data-guid'))) {
1056
- this.parent.eventBase.removeSelectedAppointmentClass();
1057
- if (this.parent.virtualScrollModule) {
1058
- resourceCell.focus({ preventScroll: true });
1059
- } else {
1060
- resourceCell.focus();
1061
- }
1062
- if (this.parent.activeView.isTimelineView() && this.parent.activeViewOptions.group.resources.length > 0 &&
1063
- isNullOrUndefined(this.parent.virtualScrollModule)) {
1064
- this.setScrollPosition(index);
1065
- }
1066
- e.preventDefault();
1067
- return;
1068
- }
1069
- }
1070
- const selectedAppointments: Element[] = this.parent.eventBase.getSelectedAppointments();
1071
- if (selectedAppointments.length > 0) {
1072
- target = selectedAppointments[selectedAppointments.length - 1] as Element;
1073
- }
1074
- this.parent.eventBase.removeSelectedAppointmentClass();
1075
- if (!isReverse && target.getAttribute('data-guid') === appElements[appElements.length - 1].getAttribute('data-guid') ||
1076
- isReverse && target.getAttribute('data-guid') === appElements[0].getAttribute('data-guid')) {
1077
- return;
1078
- }
1079
- if (this.parent.currentView === 'Agenda' || this.parent.currentView === 'MonthAgenda') {
1080
- this.selectAppointment(isReverse, target);
1081
- e.preventDefault();
1082
- }
1083
- return;
1084
- }
1085
- const selectedCells: Element[] = this.parent.getSelectedCells();
1086
- if (selectedCells.length > 0 && !target.classList.contains(cls.APPOINTMENT_CLASS)) {
1087
- target = selectedCells[selectedCells.length - 1] as Element;
1088
- this.selectAppointmentElementFromWorkCell(isReverse, target);
1089
- e.preventDefault();
1090
- return;
1091
- }
1092
- if (target && !target.classList.contains(cls.RESOURCE_CELLS_CLASS) && this.parent.activeView.isTimelineView()
1093
- && this.parent.activeViewOptions.group.resources.length > 0) {
1094
- this.processTabOnResourceCells(target, isReverse);
1095
- }
1096
- }
1097
- private processDelete(e: KeyboardEventArgs): void {
1098
- let activeEle: Element = document.activeElement;
1099
- if (this.parent.currentView === 'MonthAgenda' || (!isNullOrUndefined(activeEle) && closest(activeEle, '.' + cls.POPUP_WRAPPER_CLASS))) {
1100
- const selectedEle: HTMLElement[] = this.parent.eventBase.getSelectedEvents().element as HTMLElement[];
1101
- activeEle = <Element>((selectedEle && isNullOrUndefined(selectedEle.length)) ? selectedEle : selectedEle[0]);
1102
- }
1103
- if (activeEle && activeEle.classList.contains(cls.APPOINTMENT_CLASS)) {
1104
- addClass([activeEle], cls.APPOINTMENT_BORDER);
1105
- this.parent.activeEventData = this.parent.eventBase.getSelectedEvents();
1106
- if (this.parent.activeViewOptions.readonly || activeEle.classList.contains(cls.READ_ONLY) ||
1107
- !this.parent.eventSettings.allowDeleting) {
1108
- return;
1109
- }
1110
- this.parent.quickPopup.deleteClick(e);
1111
- }
1112
- }
1113
- private processCtrlShiftNavigationArrows(e: KeyboardEventArgs): void {
1114
- if (this.parent.activeViewOptions.group.resources.length > 0 && document.activeElement.classList.contains(cls.APPOINTMENT_CLASS)) {
1115
- const groupIndex: number = parseInt(document.activeElement.getAttribute('data-group-index'), 10);
1116
- let index: number = (e.action === 'ctrlShiftLeftArrow' || e.action === 'ctrlShiftUpArrow') ? groupIndex - 1 : groupIndex + 1;
1117
- index = index < 0 ? 0 : index > this.parent.resourceBase.lastResourceLevel.length ?
1118
- this.parent.resourceBase.lastResourceLevel.length : index;
1119
- let eventEle: HTMLElement[] = [];
1120
- while (eventEle.length === 0 && index >= 0 && index <= this.parent.resourceBase.lastResourceLevel.length) {
1121
- eventEle = [].slice.call(this.parent.element.querySelectorAll(`.${cls.APPOINTMENT_CLASS}[data-group-index="${index}"]`));
1122
- index = (e.action === 'ctrlShiftLeftArrow' || e.action === 'ctrlShiftUpArrow') ? index - 1 : index + 1;
1123
- }
1124
- const nextAppEle: HTMLElement = eventEle[0];
1125
- if (nextAppEle) {
1126
- this.parent.eventBase.removeSelectedAppointmentClass();
1127
- this.parent.eventBase.addSelectedAppointments([nextAppEle], true);
1128
- nextAppEle.focus();
1129
- }
1130
- } else if (this.parent.activeViewOptions.group.resources.length > 0 &&
1131
- !document.activeElement.classList.contains(cls.APPOINTMENT_CLASS)) {
1132
- const index: number = this.parent.resourceBase.renderedResources[0].groupIndex;
1133
- const appSelector: string = `.${cls.APPOINTMENT_CLASS}[data-group-index="${index}"]`;
1134
- const appElements: HTMLElement[] = [].slice.call(this.parent.element.querySelectorAll(appSelector));
1135
- if (appElements.length > 0) {
1136
- this.parent.eventBase.removeSelectedAppointmentClass();
1137
- const focusAppointment: HTMLElement = appElements[0];
1138
- this.parent.eventBase.addSelectedAppointments([focusAppointment], true);
1139
- focusAppointment.focus();
1140
- e.preventDefault();
1141
- }
1142
- }
1143
- }
1144
- private processEscape(event: Event): void {
1145
- this.parent.quickPopup.onClosePopup(event);
1146
- this.parent.quickPopup.morePopup.hide();
1147
- if (this.parent.headerModule) {
1148
- this.parent.headerModule.hideHeaderPopup();
1149
- }
1150
- if (this.parent.inlineModule) {
1151
- this.parent.inlineModule.removeInlineAppointmentElement();
1152
- }
1153
- }
1154
- private isPreventAction(e: Event): boolean {
1155
- const target: Element = closest((e.target as Element), '.' + cls.RESOURCE_GROUP_CELLS_CLASS);
1156
- if (this.parent.activeView.isTimelineView() && !isNullOrUndefined(target)) {
1157
- return true;
1158
- }
1159
- return false;
1160
- }
1161
- private processTabOnResourceCells(target: Element, isReverse: boolean): void {
1162
- const tabElements: Element[] = [].slice.call(this.parent.element.querySelectorAll('[tabIndex="0"]'));
1163
- const currentTabIndex: number = tabElements.indexOf(target);
1164
- const nextTabElement: Element = !isReverse ? tabElements[currentTabIndex + 1] : tabElements[currentTabIndex - 1];
1165
- if (nextTabElement && nextTabElement.classList.contains(cls.RESOURCE_CELLS_CLASS)) {
1166
- const groupIndex: number = parseInt(nextTabElement.getAttribute('data-group-index'), 10);
1167
- if (this.parent.virtualScrollModule) {
1168
- const resColWrap: HTMLElement = this.parent.element.querySelector('.' + cls.RESOURCE_COLUMN_WRAP_CLASS);
1169
- const resCells: HTMLElement[] = [].slice.call(this.parent.element.querySelectorAll('.' + cls.RESOURCE_CELLS_CLASS));
1170
- resCells.forEach((element: HTMLElement) => {
1171
- if (element.getBoundingClientRect().top < resColWrap.getBoundingClientRect().top) {
1172
- element.setAttribute('tabindex', '-1');
1173
- }
1174
- });
1175
- } else {
1176
- this.setScrollPosition(groupIndex);
1177
- }
1178
- }
1179
- }
1180
- private setScrollPosition(index: number): void {
1181
- const workCell: HTMLElement =
1182
- this.parent.element.querySelector(`.${cls.WORK_CELLS_CLASS}[data-group-index="${index}"]`) as HTMLElement;
1183
- if (workCell) {
1184
- this.parent.element.querySelector('.' + cls.CONTENT_WRAP_CLASS).scrollTop = workCell.offsetTop;
1185
- }
1186
- }
1187
-
1188
- private createClipboardElement(): void {
1189
- if (!this.parent.allowClipboard) {
1190
- return;
1191
- }
1192
- this.clipBoardTextArea = this.parent.createElement('textarea', {
1193
- className: cls.CLIPBOARD_CLASS,
1194
- attrs: {
1195
- tabindex: '-1'
1196
- }
1197
- }) as HTMLInputElement;
1198
- this.parent.element.appendChild(this.clipBoardTextArea);
1199
- }
1200
-
1201
- private setCopy(copiedEventData?: Record<string, any>[], e?: KeyboardEventArgs): void {
1202
- if (window.getSelection().toString() !== '') {
1203
- return;
1204
- }
1205
- this.clipBoardTextArea.value = '';
1206
- let eventDetails: Record<string, any> = { elements: [], eventDatas: [] };
1207
- if (copiedEventData) {
1208
- const filteredContent: Record<string, any>[] = this.filterReadOnlyEvent(copiedEventData);
1209
- eventDetails.eventDatas = filteredContent;
1210
- } else {
1211
- if (!this.parent || !this.parent.eventBase) {
1212
- return;
1213
- }
1214
- const selectedEvents: EventClickArgs = this.parent.eventBase.getSelectedEvents();
1215
- selectedEvents.event = selectedEvents && selectedEvents.event ? Array.isArray(selectedEvents.event)
1216
- ? this.filterReadOnlyEvent(selectedEvents.event) :
1217
- this.filterReadOnlyEvent([selectedEvents.event]) : undefined;
1218
- if (selectedEvents.element && selectedEvents.event) {
1219
- eventDetails = {
1220
- elements: selectedEvents.element,
1221
- eventDatas: selectedEvents.event
1222
- };
1223
- }
1224
- else {
1225
- eventDetails.element = [e.target];
1226
- eventDetails.eventDatas = [this.parent.getEventDetails(e.target as Element)];
1227
- }
1228
- }
1229
- this.clipBoardTextArea.value = JSON.stringify(eventDetails.eventDatas, undefined, 2);
1230
- if (!/ipad|ipod|iphone/i.test(Browser.userAgent)) {
1231
- this.clipBoardTextArea.select();
1232
- } else {
1233
- this.clipBoardTextArea.setSelectionRange(0, this.clipBoardTextArea.value.length);
1234
- }
1235
- if (!isNullOrUndefined((navigator as any).clipboard)) {
1236
- (navigator as any).clipboard.writeText(this.clipBoardTextArea.value)
1237
- .then(() => {
1238
- this.clipBoardTextArea.blur();
1239
- window.getSelection().removeAllRanges();
1240
- if (e) {
1241
- const closestAppointment: Element = (e.target as HTMLElement).closest('.' + cls.APPOINTMENT_CLASS);
1242
- if (closestAppointment) {
1243
- (closestAppointment as HTMLElement).focus();
1244
- }
1245
- }
1246
- })
1247
- .catch((err: Error) => {
1248
- throw err;
1249
- });
1250
- }
1251
- }
1252
-
1253
- private filterReadOnlyEvent(args: Record<string, any>[]): Record<string, any>[] {
1254
- return args.filter((event: Record<string, any>) => !event[this.parent.eventFields.isReadonly]);
1255
- }
1256
-
1257
- public processClipboardAction(isCut: boolean, copiedEventData?: Record<string, any>[], e?: KeyboardEventArgs): void {
1258
- if (!this.parent.allowClipboard) {
1259
- return;
1260
- }
1261
- this.isCutAction = isCut;
1262
- this.isCutContentPasted = false;
1263
- this.parent.closeQuickInfoPopup();
1264
- this.setCopy(copiedEventData ? copiedEventData : undefined, e);
1265
- }
1266
-
1267
- public pasteHandler(clipboardEvent: ClipboardEvent, targetElement?: HTMLElement): void {
1268
- if (!this.parent.allowClipboard || this.isCutContentPasted) {
1269
- return;
1270
- }
1271
- const target: Element[] = this.parent.getSelectedCells().length > 0
1272
- ? this.parent.getSelectedCells()
1273
- : (targetElement ? [targetElement] : []);
1274
- if (target.length === 0 || this.parent.eventWindow.dialogObject.visible ||
1275
- this.parent.quickPopup.quickPopup.element.classList.contains(cls.POPUP_OPEN)) {
1276
- return;
1277
- }
1278
- const clipboardData: DataTransfer = clipboardEvent.clipboardData || (clipboardEvent as any).event.clipboardData
1279
- || (window as any).clipboardData;
1280
- const pastedData: string = clipboardData.getData('text');
1281
- if (pastedData === '[]' || pastedData === '') {
1282
- return;
1283
- }
1284
- let parsedData: any;
1285
- try {
1286
- parsedData = JSON.parse(pastedData);
1287
- } catch {
1288
- parsedData = pastedData;
1289
- }
1290
- const args: Record<string, any> = { cancel: false, data: parsedData, element: target };
1291
- this.parent.trigger(event.beforePaste, args, (pasteEventArgs: BeforePasteEventArgs) => {
1292
- if (!pasteEventArgs.cancel) {
1293
- if (!Array.isArray(pasteEventArgs.data) || !pasteEventArgs.data.every((item: any) => typeof item === 'object')) {
1294
- this.clipBoardTextArea.value = '';
1295
- return;
1296
- }
1297
- this.processPaste(pasteEventArgs.data, targetElement);
1298
- if (this.isCutAction) {
1299
- this.isCutContentPasted = true;
1300
- }
1301
- }
1302
- else {
1303
- this.parent.closeQuickInfoPopup();
1304
- return;
1305
- }
1306
- });
1307
- }
1308
-
1309
- private processPaste(data?: any, targetElement?: HTMLElement): void {
1310
- if (!this.parent || !this.parent.eventWindow || !this.parent.eventBase || !data || !data.length) {
1311
- return;
1312
- }
1313
- const target: Element[] = this.getTargetElements(targetElement);
1314
- const cellDetails: CellClickEventArgs = this.parent.getCellDetails(target);
1315
- const eventDetails: Record<string, any> = {};
1316
- this.parent.eventWindow.convertToEventData(cellDetails, eventDetails);
1317
- const isAllDay: boolean = this.isAllDayEvent(target);
1318
- const resources: ResourceDetails | null = this.parent.getResourcesByIndex(cellDetails.groupIndex);
1319
- const processedData: Record<string, any>[] = this.processEventData(data, isAllDay, cellDetails, resources);
1320
- const selectedEventData: Array<Record<string, any>> = this.parent.eventBase.sortByDateTime(processedData);
1321
- const saveData: Record<string, any>[] = this.prepareEventData(selectedEventData, eventDetails);
1322
- removeClass(target, cls.SELECTED_CELL_CLASS);
1323
- if (saveData.length > 0) {
1324
- if (this.isCutAction) {
1325
- this.parent.saveEvent(saveData);
1326
- } else {
1327
- this.parent.addEvent(saveData);
1328
- }
1329
- }
1330
- }
1331
-
1332
- private getTargetElements(targetElement?: HTMLElement): Element[] {
1333
- return this.parent.getSelectedCells().length > 0
1334
- ? this.parent.getSelectedCells()
1335
- : (targetElement ? [targetElement] : []);
1336
- }
1337
-
1338
- private isAllDayEvent(target: Element[]): boolean {
1339
- return !target.some((cell: Element) => cell.classList.contains(cls.WORK_CELLS_CLASS));
1340
- }
1341
-
1342
- private processEventData(
1343
- data: any[], isAllDay: boolean, cellDetails: CellClickEventArgs, resources: ResourceDetails | null): Record<string, any>[] {
1344
- return data.map((item: Record<string, any>) => {
1345
- const processedItem: Record<string, any> = {
1346
- ...item,
1347
- [this.parent.eventFields.startTime]: new Date(item[this.parent.eventFields.startTime]),
1348
- [this.parent.eventFields.endTime]: new Date(item[this.parent.eventFields.endTime]),
1349
- [this.parent.eventFields.recurrenceID]: null as any,
1350
- [this.parent.eventFields.isAllDay]: isAllDay
1351
- };
1352
- this.adjustEventTime(processedItem, isAllDay, item.IsAllDay, cellDetails);
1353
-
1354
- if (resources && resources.groupData) {
1355
- Object.assign(processedItem, resources.groupData);
1356
- }
1357
-
1358
- return processedItem;
1359
- });
1360
- }
1361
-
1362
- private adjustEventTime(
1363
- processedItem: Record<string, any>, isAllDay: boolean, itemIsAllDay: boolean, cellDetails: CellClickEventArgs): void {
1364
- const isTimeScaleEnabled: boolean = this.parent.activeViewOptions.timeScale.enable;
1365
- if ((['Day', 'Week', 'WorkWeek'].indexOf(this.parent.currentView) !== -1) && isTimeScaleEnabled) {
1366
- if (isAllDay) {
1367
- processedItem[this.parent.eventFields.endTime] = new Date(processedItem[this.parent.eventFields.startTime]);
1368
- processedItem[this.parent.eventFields.endTime].setDate(processedItem[this.parent.eventFields.startTime].getDate() + 1);
1369
-
1370
- } else if (itemIsAllDay) {
1371
- processedItem[this.parent.eventFields.startTime] = new Date(processedItem[this.parent.eventFields.startTime]
1372
- .setHours(0, 0, 0, 0));
1373
- processedItem[this.parent.eventFields.endTime] = new Date(processedItem[this.parent.eventFields.startTime].getTime() + (
1374
- cellDetails.endTime.getTime() - cellDetails.startTime.getTime()));
1375
- }
1376
- } else if (itemIsAllDay) {
1377
- processedItem[this.parent.eventFields.isAllDay] = true;
1378
- processedItem[this.parent.eventFields.startTime] = new Date(processedItem[this.parent.eventFields.startTime]
1379
- .setHours(0, 0, 0, 0));
1380
- processedItem[this.parent.eventFields.endTime] = new Date(processedItem[this.parent.eventFields.startTime].getTime() +
1381
- (processedItem[this.parent.eventFields.endTime].getTime() - processedItem[this.parent.eventFields.startTime].getTime()));
1382
- }
1383
- }
1384
-
1385
- private prepareEventData(selectedEventData: Array<Record<string, any>>, eventDetails: Record<string, any>): Record<string, any>[] {
1386
- const initialEventTime: Date = new Date(selectedEventData[0][this.parent.eventFields.startTime]);
1387
- let uniqueId: number = this.parent.getEventMaxID() as number;
1388
- return selectedEventData.map((events: Record<string, any>) => {
1389
- const totalDuration: number = this.calculateTotalDuration(events, eventDetails, initialEventTime);
1390
- const cloneDetails: Record<string, any> = this.isCutAction ? events : { ...events };
1391
- if (!events[this.parent.eventFields.recurrenceRule]) {
1392
- cloneDetails[this.parent.eventFields.startTime] =
1393
- new Date(new Date(cloneDetails[this.parent.eventFields.startTime]).setMilliseconds(totalDuration));
1394
- cloneDetails[this.parent.eventFields.endTime] =
1395
- new Date(new Date(cloneDetails[this.parent.eventFields.endTime]).setMilliseconds(totalDuration));
1396
- }
1397
- if (!this.isCutAction) {
1398
- cloneDetails[this.parent.eventFields.id] = uniqueId++;
1399
- }
1400
- return cloneDetails;
1401
- });
1402
- }
1403
-
1404
- private calculateTotalDuration(events: Record<string, any>, eventDetails: Record<string, any>, initialEventTime: Date): number {
1405
- if ((['Month', 'TimelineMonth', 'TimelineYear'].indexOf(this.parent.currentView) !== -1) || !this.parent.activeViewOptions.timeScale.enable) {
1406
- const eventStartTime: Date = new Date(events[this.parent.eventFields.startTime]);
1407
- return eventDetails[this.parent.eventFields.startTime].getTime() - initialEventTime.getTime() +
1408
- (eventStartTime.getHours() * 3600000 + eventStartTime.getMinutes() * 60000 + eventStartTime.getSeconds() * 1000);
1409
- } else {
1410
- return eventDetails[this.parent.eventFields.startTime].getTime() - initialEventTime.getTime();
1411
- }
1412
- }
1413
-
1414
- /**
1415
- * Get module name.
1416
- *
1417
- * @returns {string} Returns the module name.
1418
- */
1419
- protected getModuleName(): string {
1420
- return 'keyboard';
1421
- }
1422
- /**
1423
- * To destroy the keyboard module.
1424
- *
1425
- * @returns {void}
1426
- * @private
1427
- */
1428
- public destroy(): void {
1429
- this.removeEventListener();
1430
- this.selectedCells = [];
1431
- this.clipBoardTextArea = null;
1432
- this.keyboardModule.destroy();
1433
- }
1434
-
1435
- }