@syncfusion/ej2-schedule 31.1.17 → 31.1.20

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 (167) 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 +1 -1
  5. package/dist/es6/ej2-schedule.es2015.js.map +1 -1
  6. package/dist/es6/ej2-schedule.es5.js +1 -1
  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 +17 -52
  12. package/src/schedule/event-renderer/event-base.js +1 -1
  13. package/styles/bootstrap4-lite.css +8 -0
  14. package/styles/bootstrap4.css +8 -0
  15. package/styles/recurrence-editor/bootstrap4.css +8 -0
  16. package/styles/schedule/bootstrap4.css +8 -0
  17. package/dist/ts/common/calendar-util.d.ts +0 -92
  18. package/dist/ts/common/calendar-util.ts +0 -261
  19. package/dist/ts/common/index.d.ts +0 -4
  20. package/dist/ts/common/index.ts +0 -4
  21. package/dist/ts/components.d.ts +0 -5
  22. package/dist/ts/components.ts +0 -5
  23. package/dist/ts/index.d.ts +0 -6
  24. package/dist/ts/index.ts +0 -7
  25. package/dist/ts/recurrence-editor/date-generator.d.ts +0 -76
  26. package/dist/ts/recurrence-editor/date-generator.ts +0 -1699
  27. package/dist/ts/recurrence-editor/index.d.ts +0 -6
  28. package/dist/ts/recurrence-editor/index.ts +0 -6
  29. package/dist/ts/recurrence-editor/recurrence-editor-model.d.ts +0 -112
  30. package/dist/ts/recurrence-editor/recurrence-editor.d.ts +0 -245
  31. package/dist/ts/recurrence-editor/recurrence-editor.ts +0 -1257
  32. package/dist/ts/schedule/actions/action-base.d.ts +0 -44
  33. package/dist/ts/schedule/actions/action-base.ts +0 -493
  34. package/dist/ts/schedule/actions/crud.d.ts +0 -41
  35. package/dist/ts/schedule/actions/crud.ts +0 -784
  36. package/dist/ts/schedule/actions/data.d.ts +0 -63
  37. package/dist/ts/schedule/actions/data.ts +0 -128
  38. package/dist/ts/schedule/actions/drag.d.ts +0 -75
  39. package/dist/ts/schedule/actions/drag.ts +0 -1401
  40. package/dist/ts/schedule/actions/keyboard.d.ts +0 -100
  41. package/dist/ts/schedule/actions/keyboard.ts +0 -1435
  42. package/dist/ts/schedule/actions/resize.d.ts +0 -27
  43. package/dist/ts/schedule/actions/resize.ts +0 -602
  44. package/dist/ts/schedule/actions/scroll.d.ts +0 -69
  45. package/dist/ts/schedule/actions/scroll.ts +0 -105
  46. package/dist/ts/schedule/actions/touch.d.ts +0 -32
  47. package/dist/ts/schedule/actions/touch.ts +0 -314
  48. package/dist/ts/schedule/actions/virtual-scroll.d.ts +0 -55
  49. package/dist/ts/schedule/actions/virtual-scroll.ts +0 -596
  50. package/dist/ts/schedule/actions/work-cells.d.ts +0 -14
  51. package/dist/ts/schedule/actions/work-cells.ts +0 -151
  52. package/dist/ts/schedule/base/constant.d.ts +0 -102
  53. package/dist/ts/schedule/base/constant.ts +0 -103
  54. package/dist/ts/schedule/base/css-constant.d.ts +0 -475
  55. package/dist/ts/schedule/base/css-constant.ts +0 -475
  56. package/dist/ts/schedule/base/interface.d.ts +0 -673
  57. package/dist/ts/schedule/base/interface.ts +0 -738
  58. package/dist/ts/schedule/base/resource.d.ts +0 -59
  59. package/dist/ts/schedule/base/resource.ts +0 -1091
  60. package/dist/ts/schedule/base/schedule-model.d.ts +0 -930
  61. package/dist/ts/schedule/base/schedule.d.ts +0 -1967
  62. package/dist/ts/schedule/base/schedule.ts +0 -4221
  63. package/dist/ts/schedule/base/type.d.ts +0 -134
  64. package/dist/ts/schedule/base/type.ts +0 -142
  65. package/dist/ts/schedule/base/util.d.ts +0 -266
  66. package/dist/ts/schedule/base/util.ts +0 -492
  67. package/dist/ts/schedule/event-renderer/agenda-base.d.ts +0 -15
  68. package/dist/ts/schedule/event-renderer/agenda-base.ts +0 -423
  69. package/dist/ts/schedule/event-renderer/event-base.d.ts +0 -101
  70. package/dist/ts/schedule/event-renderer/event-base.ts +0 -1501
  71. package/dist/ts/schedule/event-renderer/inline-edit.d.ts +0 -23
  72. package/dist/ts/schedule/event-renderer/inline-edit.ts +0 -287
  73. package/dist/ts/schedule/event-renderer/month.d.ts +0 -60
  74. package/dist/ts/schedule/event-renderer/month.ts +0 -760
  75. package/dist/ts/schedule/event-renderer/timeline-view.d.ts +0 -51
  76. package/dist/ts/schedule/event-renderer/timeline-view.ts +0 -606
  77. package/dist/ts/schedule/event-renderer/vertical-view.d.ts +0 -57
  78. package/dist/ts/schedule/event-renderer/vertical-view.ts +0 -898
  79. package/dist/ts/schedule/event-renderer/year.d.ts +0 -27
  80. package/dist/ts/schedule/event-renderer/year.ts +0 -623
  81. package/dist/ts/schedule/exports/calendar-export.d.ts +0 -16
  82. package/dist/ts/schedule/exports/calendar-export.ts +0 -160
  83. package/dist/ts/schedule/exports/calendar-import.d.ts +0 -18
  84. package/dist/ts/schedule/exports/calendar-import.ts +0 -277
  85. package/dist/ts/schedule/exports/excel-export.d.ts +0 -14
  86. package/dist/ts/schedule/exports/excel-export.ts +0 -89
  87. package/dist/ts/schedule/exports/index.d.ts +0 -7
  88. package/dist/ts/schedule/exports/index.ts +0 -7
  89. package/dist/ts/schedule/exports/print.d.ts +0 -20
  90. package/dist/ts/schedule/exports/print.ts +0 -233
  91. package/dist/ts/schedule/index.d.ts +0 -26
  92. package/dist/ts/schedule/index.ts +0 -26
  93. package/dist/ts/schedule/models/event-settings-model.d.ts +0 -165
  94. package/dist/ts/schedule/models/event-settings.d.ts +0 -149
  95. package/dist/ts/schedule/models/event-settings.ts +0 -187
  96. package/dist/ts/schedule/models/field-options-model.d.ts +0 -37
  97. package/dist/ts/schedule/models/field-options.d.ts +0 -31
  98. package/dist/ts/schedule/models/field-options.ts +0 -41
  99. package/dist/ts/schedule/models/fields-model.d.ts +0 -129
  100. package/dist/ts/schedule/models/fields.d.ts +0 -117
  101. package/dist/ts/schedule/models/fields.ts +0 -149
  102. package/dist/ts/schedule/models/group-model.d.ts +0 -69
  103. package/dist/ts/schedule/models/group.d.ts +0 -60
  104. package/dist/ts/schedule/models/group.ts +0 -75
  105. package/dist/ts/schedule/models/header-rows-model.d.ts +0 -33
  106. package/dist/ts/schedule/models/header-rows.d.ts +0 -30
  107. package/dist/ts/schedule/models/header-rows.ts +0 -35
  108. package/dist/ts/schedule/models/models.d.ts +0 -14
  109. package/dist/ts/schedule/models/models.ts +0 -15
  110. package/dist/ts/schedule/models/quick-info-templates-model.d.ts +0 -52
  111. package/dist/ts/schedule/models/quick-info-templates.d.ts +0 -47
  112. package/dist/ts/schedule/models/quick-info-templates.ts +0 -56
  113. package/dist/ts/schedule/models/resources-model.d.ts +0 -122
  114. package/dist/ts/schedule/models/resources.d.ts +0 -106
  115. package/dist/ts/schedule/models/resources.ts +0 -138
  116. package/dist/ts/schedule/models/time-scale-model.d.ts +0 -57
  117. package/dist/ts/schedule/models/time-scale.d.ts +0 -50
  118. package/dist/ts/schedule/models/time-scale.ts +0 -61
  119. package/dist/ts/schedule/models/toolbar-model.d.ts +0 -196
  120. package/dist/ts/schedule/models/toolbar.d.ts +0 -176
  121. package/dist/ts/schedule/models/toolbar.ts +0 -196
  122. package/dist/ts/schedule/models/views-model.d.ts +0 -370
  123. package/dist/ts/schedule/models/views.d.ts +0 -335
  124. package/dist/ts/schedule/models/views.ts +0 -408
  125. package/dist/ts/schedule/models/work-hours-model.d.ts +0 -29
  126. package/dist/ts/schedule/models/work-hours.d.ts +0 -24
  127. package/dist/ts/schedule/models/work-hours.ts +0 -31
  128. package/dist/ts/schedule/popups/event-tooltip.d.ts +0 -16
  129. package/dist/ts/schedule/popups/event-tooltip.ts +0 -203
  130. package/dist/ts/schedule/popups/event-window.d.ts +0 -118
  131. package/dist/ts/schedule/popups/event-window.ts +0 -2055
  132. package/dist/ts/schedule/popups/form-validator.d.ts +0 -16
  133. package/dist/ts/schedule/popups/form-validator.ts +0 -110
  134. package/dist/ts/schedule/popups/quick-popups.d.ts +0 -78
  135. package/dist/ts/schedule/popups/quick-popups.ts +0 -1470
  136. package/dist/ts/schedule/renderer/agenda.d.ts +0 -45
  137. package/dist/ts/schedule/renderer/agenda.ts +0 -497
  138. package/dist/ts/schedule/renderer/day.d.ts +0 -20
  139. package/dist/ts/schedule/renderer/day.ts +0 -28
  140. package/dist/ts/schedule/renderer/header-renderer.d.ts +0 -48
  141. package/dist/ts/schedule/renderer/header-renderer.ts +0 -736
  142. package/dist/ts/schedule/renderer/month-agenda.d.ts +0 -29
  143. package/dist/ts/schedule/renderer/month-agenda.ts +0 -184
  144. package/dist/ts/schedule/renderer/month.d.ts +0 -61
  145. package/dist/ts/schedule/renderer/month.ts +0 -766
  146. package/dist/ts/schedule/renderer/renderer.d.ts +0 -13
  147. package/dist/ts/schedule/renderer/renderer.ts +0 -165
  148. package/dist/ts/schedule/renderer/timeline-header-row.d.ts +0 -15
  149. package/dist/ts/schedule/renderer/timeline-header-row.ts +0 -132
  150. package/dist/ts/schedule/renderer/timeline-month.d.ts +0 -29
  151. package/dist/ts/schedule/renderer/timeline-month.ts +0 -184
  152. package/dist/ts/schedule/renderer/timeline-view.d.ts +0 -31
  153. package/dist/ts/schedule/renderer/timeline-view.ts +0 -308
  154. package/dist/ts/schedule/renderer/timeline-year.d.ts +0 -22
  155. package/dist/ts/schedule/renderer/timeline-year.ts +0 -450
  156. package/dist/ts/schedule/renderer/vertical-view.d.ts +0 -63
  157. package/dist/ts/schedule/renderer/vertical-view.ts +0 -911
  158. package/dist/ts/schedule/renderer/view-base.d.ts +0 -83
  159. package/dist/ts/schedule/renderer/view-base.ts +0 -709
  160. package/dist/ts/schedule/renderer/week.d.ts +0 -22
  161. package/dist/ts/schedule/renderer/week.ts +0 -35
  162. package/dist/ts/schedule/renderer/work-week.d.ts +0 -22
  163. package/dist/ts/schedule/renderer/work-week.ts +0 -36
  164. package/dist/ts/schedule/renderer/year.d.ts +0 -46
  165. package/dist/ts/schedule/renderer/year.ts +0 -470
  166. package/dist/ts/schedule/timezone/timezone.d.ts +0 -16
  167. 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
- }