@syncfusion/ej2-schedule 30.2.4 → 31.1.17

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 (308) 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 +132 -43
  5. package/dist/es6/ej2-schedule.es2015.js.map +1 -1
  6. package/dist/es6/ej2-schedule.es5.js +132 -43
  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/dist/ts/common/calendar-util.d.ts +92 -0
  12. package/dist/ts/common/calendar-util.ts +261 -0
  13. package/dist/ts/common/index.d.ts +4 -0
  14. package/dist/ts/common/index.ts +4 -0
  15. package/dist/ts/components.d.ts +5 -0
  16. package/dist/ts/components.ts +5 -0
  17. package/dist/ts/index.d.ts +6 -0
  18. package/dist/ts/index.ts +7 -0
  19. package/dist/ts/recurrence-editor/date-generator.d.ts +76 -0
  20. package/dist/ts/recurrence-editor/date-generator.ts +1699 -0
  21. package/dist/ts/recurrence-editor/index.d.ts +6 -0
  22. package/dist/ts/recurrence-editor/index.ts +6 -0
  23. package/dist/ts/recurrence-editor/recurrence-editor-model.d.ts +112 -0
  24. package/dist/ts/recurrence-editor/recurrence-editor.d.ts +245 -0
  25. package/dist/ts/recurrence-editor/recurrence-editor.ts +1257 -0
  26. package/dist/ts/schedule/actions/action-base.d.ts +44 -0
  27. package/dist/ts/schedule/actions/action-base.ts +493 -0
  28. package/dist/ts/schedule/actions/crud.d.ts +41 -0
  29. package/dist/ts/schedule/actions/crud.ts +784 -0
  30. package/dist/ts/schedule/actions/data.d.ts +63 -0
  31. package/dist/ts/schedule/actions/data.ts +128 -0
  32. package/dist/ts/schedule/actions/drag.d.ts +75 -0
  33. package/dist/ts/schedule/actions/drag.ts +1401 -0
  34. package/dist/ts/schedule/actions/keyboard.d.ts +100 -0
  35. package/dist/ts/schedule/actions/keyboard.ts +1435 -0
  36. package/dist/ts/schedule/actions/resize.d.ts +27 -0
  37. package/dist/ts/schedule/actions/resize.ts +602 -0
  38. package/dist/ts/schedule/actions/scroll.d.ts +69 -0
  39. package/dist/ts/schedule/actions/scroll.ts +105 -0
  40. package/dist/ts/schedule/actions/touch.d.ts +32 -0
  41. package/dist/ts/schedule/actions/touch.ts +314 -0
  42. package/dist/ts/schedule/actions/virtual-scroll.d.ts +55 -0
  43. package/dist/ts/schedule/actions/virtual-scroll.ts +596 -0
  44. package/dist/ts/schedule/actions/work-cells.d.ts +14 -0
  45. package/dist/ts/schedule/actions/work-cells.ts +151 -0
  46. package/dist/ts/schedule/base/constant.d.ts +102 -0
  47. package/dist/ts/schedule/base/constant.ts +103 -0
  48. package/dist/ts/schedule/base/css-constant.d.ts +475 -0
  49. package/dist/ts/schedule/base/css-constant.ts +475 -0
  50. package/dist/ts/schedule/base/interface.d.ts +673 -0
  51. package/dist/ts/schedule/base/interface.ts +738 -0
  52. package/dist/ts/schedule/base/resource.d.ts +59 -0
  53. package/dist/ts/schedule/base/resource.ts +1091 -0
  54. package/dist/ts/schedule/base/schedule-model.d.ts +930 -0
  55. package/dist/ts/schedule/base/schedule.d.ts +1967 -0
  56. package/dist/ts/schedule/base/schedule.ts +4221 -0
  57. package/dist/ts/schedule/base/type.d.ts +134 -0
  58. package/dist/ts/schedule/base/type.ts +142 -0
  59. package/dist/ts/schedule/base/util.d.ts +266 -0
  60. package/dist/ts/schedule/base/util.ts +492 -0
  61. package/dist/ts/schedule/event-renderer/agenda-base.d.ts +15 -0
  62. package/dist/ts/schedule/event-renderer/agenda-base.ts +423 -0
  63. package/dist/ts/schedule/event-renderer/event-base.d.ts +101 -0
  64. package/dist/ts/schedule/event-renderer/event-base.ts +1501 -0
  65. package/dist/ts/schedule/event-renderer/inline-edit.d.ts +23 -0
  66. package/dist/ts/schedule/event-renderer/inline-edit.ts +287 -0
  67. package/dist/ts/schedule/event-renderer/month.d.ts +60 -0
  68. package/dist/ts/schedule/event-renderer/month.ts +760 -0
  69. package/dist/ts/schedule/event-renderer/timeline-view.d.ts +51 -0
  70. package/dist/ts/schedule/event-renderer/timeline-view.ts +606 -0
  71. package/dist/ts/schedule/event-renderer/vertical-view.d.ts +57 -0
  72. package/dist/ts/schedule/event-renderer/vertical-view.ts +898 -0
  73. package/dist/ts/schedule/event-renderer/year.d.ts +27 -0
  74. package/dist/ts/schedule/event-renderer/year.ts +623 -0
  75. package/dist/ts/schedule/exports/calendar-export.d.ts +16 -0
  76. package/dist/ts/schedule/exports/calendar-export.ts +160 -0
  77. package/dist/ts/schedule/exports/calendar-import.d.ts +18 -0
  78. package/dist/ts/schedule/exports/calendar-import.ts +277 -0
  79. package/dist/ts/schedule/exports/excel-export.d.ts +14 -0
  80. package/dist/ts/schedule/exports/excel-export.ts +89 -0
  81. package/dist/ts/schedule/exports/index.d.ts +7 -0
  82. package/dist/ts/schedule/exports/index.ts +7 -0
  83. package/dist/ts/schedule/exports/print.d.ts +20 -0
  84. package/dist/ts/schedule/exports/print.ts +233 -0
  85. package/dist/ts/schedule/index.d.ts +26 -0
  86. package/dist/ts/schedule/index.ts +26 -0
  87. package/dist/ts/schedule/models/event-settings-model.d.ts +165 -0
  88. package/dist/ts/schedule/models/event-settings.d.ts +149 -0
  89. package/dist/ts/schedule/models/event-settings.ts +187 -0
  90. package/dist/ts/schedule/models/field-options-model.d.ts +37 -0
  91. package/dist/ts/schedule/models/field-options.d.ts +31 -0
  92. package/dist/ts/schedule/models/field-options.ts +41 -0
  93. package/dist/ts/schedule/models/fields-model.d.ts +129 -0
  94. package/dist/ts/schedule/models/fields.d.ts +117 -0
  95. package/dist/ts/schedule/models/fields.ts +149 -0
  96. package/dist/ts/schedule/models/group-model.d.ts +69 -0
  97. package/dist/ts/schedule/models/group.d.ts +60 -0
  98. package/dist/ts/schedule/models/group.ts +75 -0
  99. package/dist/ts/schedule/models/header-rows-model.d.ts +33 -0
  100. package/dist/ts/schedule/models/header-rows.d.ts +30 -0
  101. package/dist/ts/schedule/models/header-rows.ts +35 -0
  102. package/dist/ts/schedule/models/models.d.ts +14 -0
  103. package/dist/ts/schedule/models/models.ts +15 -0
  104. package/dist/ts/schedule/models/quick-info-templates-model.d.ts +52 -0
  105. package/dist/ts/schedule/models/quick-info-templates.d.ts +47 -0
  106. package/dist/ts/schedule/models/quick-info-templates.ts +56 -0
  107. package/dist/ts/schedule/models/resources-model.d.ts +122 -0
  108. package/dist/ts/schedule/models/resources.d.ts +106 -0
  109. package/dist/ts/schedule/models/resources.ts +138 -0
  110. package/dist/ts/schedule/models/time-scale-model.d.ts +57 -0
  111. package/dist/ts/schedule/models/time-scale.d.ts +50 -0
  112. package/dist/ts/schedule/models/time-scale.ts +61 -0
  113. package/dist/ts/schedule/models/toolbar-model.d.ts +196 -0
  114. package/dist/ts/schedule/models/toolbar.d.ts +176 -0
  115. package/dist/ts/schedule/models/toolbar.ts +196 -0
  116. package/dist/ts/schedule/models/views-model.d.ts +370 -0
  117. package/dist/ts/schedule/models/views.d.ts +335 -0
  118. package/dist/ts/schedule/models/views.ts +408 -0
  119. package/dist/ts/schedule/models/work-hours-model.d.ts +29 -0
  120. package/dist/ts/schedule/models/work-hours.d.ts +24 -0
  121. package/dist/ts/schedule/models/work-hours.ts +31 -0
  122. package/dist/ts/schedule/popups/event-tooltip.d.ts +16 -0
  123. package/dist/ts/schedule/popups/event-tooltip.ts +203 -0
  124. package/dist/ts/schedule/popups/event-window.d.ts +118 -0
  125. package/dist/ts/schedule/popups/event-window.ts +2055 -0
  126. package/dist/ts/schedule/popups/form-validator.d.ts +16 -0
  127. package/dist/ts/schedule/popups/form-validator.ts +110 -0
  128. package/dist/ts/schedule/popups/quick-popups.d.ts +78 -0
  129. package/dist/ts/schedule/popups/quick-popups.ts +1470 -0
  130. package/dist/ts/schedule/renderer/agenda.d.ts +45 -0
  131. package/dist/ts/schedule/renderer/agenda.ts +497 -0
  132. package/dist/ts/schedule/renderer/day.d.ts +20 -0
  133. package/dist/ts/schedule/renderer/day.ts +28 -0
  134. package/dist/ts/schedule/renderer/header-renderer.d.ts +48 -0
  135. package/dist/ts/schedule/renderer/header-renderer.ts +736 -0
  136. package/dist/ts/schedule/renderer/month-agenda.d.ts +29 -0
  137. package/dist/ts/schedule/renderer/month-agenda.ts +184 -0
  138. package/dist/ts/schedule/renderer/month.d.ts +61 -0
  139. package/dist/ts/schedule/renderer/month.ts +766 -0
  140. package/dist/ts/schedule/renderer/renderer.d.ts +13 -0
  141. package/dist/ts/schedule/renderer/renderer.ts +165 -0
  142. package/dist/ts/schedule/renderer/timeline-header-row.d.ts +15 -0
  143. package/dist/ts/schedule/renderer/timeline-header-row.ts +132 -0
  144. package/dist/ts/schedule/renderer/timeline-month.d.ts +29 -0
  145. package/dist/ts/schedule/renderer/timeline-month.ts +184 -0
  146. package/dist/ts/schedule/renderer/timeline-view.d.ts +31 -0
  147. package/dist/ts/schedule/renderer/timeline-view.ts +308 -0
  148. package/dist/ts/schedule/renderer/timeline-year.d.ts +22 -0
  149. package/dist/ts/schedule/renderer/timeline-year.ts +450 -0
  150. package/dist/ts/schedule/renderer/vertical-view.d.ts +63 -0
  151. package/dist/ts/schedule/renderer/vertical-view.ts +911 -0
  152. package/dist/ts/schedule/renderer/view-base.d.ts +83 -0
  153. package/dist/ts/schedule/renderer/view-base.ts +709 -0
  154. package/dist/ts/schedule/renderer/week.d.ts +22 -0
  155. package/dist/ts/schedule/renderer/week.ts +35 -0
  156. package/dist/ts/schedule/renderer/work-week.d.ts +22 -0
  157. package/dist/ts/schedule/renderer/work-week.ts +36 -0
  158. package/dist/ts/schedule/renderer/year.d.ts +46 -0
  159. package/dist/ts/schedule/renderer/year.ts +470 -0
  160. package/dist/ts/schedule/timezone/timezone.d.ts +16 -0
  161. package/dist/ts/schedule/timezone/timezone.ts +313 -0
  162. package/package.json +56 -21
  163. package/src/schedule/actions/action-base.js +3 -0
  164. package/src/schedule/actions/drag.js +11 -4
  165. package/src/schedule/actions/keyboard.js +1 -1
  166. package/src/schedule/actions/resize.js +9 -5
  167. package/src/schedule/actions/virtual-scroll.js +3 -0
  168. package/src/schedule/base/css-constant.d.ts +2 -0
  169. package/src/schedule/base/css-constant.js +2 -0
  170. package/src/schedule/base/schedule.js +15 -1
  171. package/src/schedule/event-renderer/agenda-base.d.ts +1 -1
  172. package/src/schedule/event-renderer/agenda-base.js +5 -4
  173. package/src/schedule/event-renderer/inline-edit.js +11 -6
  174. package/src/schedule/event-renderer/month.js +5 -3
  175. package/src/schedule/event-renderer/vertical-view.js +3 -0
  176. package/src/schedule/event-renderer/year.d.ts +2 -0
  177. package/src/schedule/event-renderer/year.js +28 -4
  178. package/src/schedule/popups/event-tooltip.js +4 -0
  179. package/src/schedule/popups/event-window.js +2 -2
  180. package/src/schedule/popups/quick-popups.js +5 -1
  181. package/src/schedule/renderer/agenda.js +3 -2
  182. package/src/schedule/renderer/month.js +9 -7
  183. package/src/schedule/renderer/vertical-view.js +1 -1
  184. package/src/schedule/renderer/view-base.d.ts +2 -0
  185. package/src/schedule/renderer/view-base.js +9 -0
  186. package/src/schedule/renderer/year.js +3 -2
  187. package/styles/bds-lite.css +11 -8
  188. package/styles/bds.css +11 -8
  189. package/styles/bootstrap-dark-lite.css +12 -9
  190. package/styles/bootstrap-dark.css +12 -9
  191. package/styles/bootstrap-lite.css +12 -9
  192. package/styles/bootstrap.css +12 -9
  193. package/styles/bootstrap4-lite.css +11 -8
  194. package/styles/bootstrap4.css +11 -8
  195. package/styles/bootstrap5-dark-lite.css +11 -8
  196. package/styles/bootstrap5-dark.css +11 -8
  197. package/styles/bootstrap5-lite.css +11 -8
  198. package/styles/bootstrap5.3-lite.css +11 -8
  199. package/styles/bootstrap5.3.css +11 -8
  200. package/styles/bootstrap5.css +11 -8
  201. package/styles/fabric-dark-lite.css +12 -9
  202. package/styles/fabric-dark.css +12 -9
  203. package/styles/fabric-lite.css +12 -9
  204. package/styles/fabric.css +12 -9
  205. package/styles/fluent-dark-lite.css +13 -10
  206. package/styles/fluent-dark.css +13 -10
  207. package/styles/fluent-lite.css +13 -10
  208. package/styles/fluent.css +13 -10
  209. package/styles/fluent2-lite.css +11 -8
  210. package/styles/fluent2.css +11 -8
  211. package/styles/highcontrast-light-lite.css +12 -9
  212. package/styles/highcontrast-light.css +12 -9
  213. package/styles/highcontrast-lite.css +12 -9
  214. package/styles/highcontrast.css +12 -9
  215. package/styles/material-dark-lite.css +12 -9
  216. package/styles/material-dark.css +12 -9
  217. package/styles/material-lite.css +12 -9
  218. package/styles/material.css +12 -9
  219. package/styles/material3-dark-lite.css +11 -8
  220. package/styles/material3-dark.css +11 -8
  221. package/styles/material3-lite.css +11 -8
  222. package/styles/material3.css +11 -8
  223. package/styles/recurrence-editor/_bds-definition.scss +1 -0
  224. package/styles/recurrence-editor/_bootstrap-dark-definition.scss +1 -0
  225. package/styles/recurrence-editor/_bootstrap-definition.scss +1 -0
  226. package/styles/recurrence-editor/_bootstrap4-definition.scss +1 -0
  227. package/styles/recurrence-editor/_bootstrap5-definition.scss +1 -0
  228. package/styles/recurrence-editor/_bootstrap5.3-definition.scss +1 -0
  229. package/styles/recurrence-editor/_fabric-dark-definition.scss +1 -0
  230. package/styles/recurrence-editor/_fabric-definition.scss +1 -0
  231. package/styles/recurrence-editor/_fluent-definition.scss +1 -0
  232. package/styles/recurrence-editor/_fluent2-definition.scss +1 -0
  233. package/styles/recurrence-editor/_fusionnew-definition.scss +1 -0
  234. package/styles/recurrence-editor/_highcontrast-definition.scss +1 -0
  235. package/styles/recurrence-editor/_highcontrast-light-definition.scss +1 -0
  236. package/styles/recurrence-editor/_layout.scss +5 -1
  237. package/styles/recurrence-editor/_material-dark-definition.scss +1 -0
  238. package/styles/recurrence-editor/_material-definition.scss +1 -0
  239. package/styles/recurrence-editor/_material3-definition.scss +1 -0
  240. package/styles/recurrence-editor/_tailwind-definition.scss +1 -0
  241. package/styles/recurrence-editor/_tailwind3-definition.scss +1 -0
  242. package/styles/recurrence-editor/bds.css +3 -0
  243. package/styles/recurrence-editor/bootstrap-dark.css +4 -1
  244. package/styles/recurrence-editor/bootstrap.css +4 -1
  245. package/styles/recurrence-editor/bootstrap4.css +3 -0
  246. package/styles/recurrence-editor/bootstrap5-dark.css +3 -0
  247. package/styles/recurrence-editor/bootstrap5.3.css +3 -0
  248. package/styles/recurrence-editor/bootstrap5.css +3 -0
  249. package/styles/recurrence-editor/fabric-dark.css +4 -1
  250. package/styles/recurrence-editor/fabric.css +4 -1
  251. package/styles/recurrence-editor/fluent-dark.css +4 -1
  252. package/styles/recurrence-editor/fluent.css +4 -1
  253. package/styles/recurrence-editor/fluent2.css +3 -0
  254. package/styles/recurrence-editor/highcontrast-light.css +4 -1
  255. package/styles/recurrence-editor/highcontrast.css +4 -1
  256. package/styles/recurrence-editor/material-dark.css +4 -1
  257. package/styles/recurrence-editor/material.css +4 -1
  258. package/styles/recurrence-editor/material3-dark.css +3 -0
  259. package/styles/recurrence-editor/material3.css +3 -0
  260. package/styles/recurrence-editor/tailwind-dark.css +3 -0
  261. package/styles/recurrence-editor/tailwind.css +3 -0
  262. package/styles/recurrence-editor/tailwind3.css +3 -0
  263. package/styles/schedule/_bds-definition.scss +2 -0
  264. package/styles/schedule/_bootstrap-dark-definition.scss +2 -0
  265. package/styles/schedule/_bootstrap-definition.scss +2 -0
  266. package/styles/schedule/_bootstrap4-definition.scss +2 -0
  267. package/styles/schedule/_bootstrap5-definition.scss +2 -0
  268. package/styles/schedule/_bootstrap5.3-definition.scss +2 -0
  269. package/styles/schedule/_fabric-dark-definition.scss +2 -0
  270. package/styles/schedule/_fabric-definition.scss +2 -0
  271. package/styles/schedule/_fluent-definition.scss +3 -1
  272. package/styles/schedule/_fluent2-definition.scss +2 -0
  273. package/styles/schedule/_fusionnew-definition.scss +2 -0
  274. package/styles/schedule/_highcontrast-definition.scss +2 -0
  275. package/styles/schedule/_highcontrast-light-definition.scss +2 -0
  276. package/styles/schedule/_layout.scss +12 -11
  277. package/styles/schedule/_material-dark-definition.scss +2 -0
  278. package/styles/schedule/_material-definition.scss +2 -0
  279. package/styles/schedule/_material3-definition.scss +2 -0
  280. package/styles/schedule/_tailwind-definition.scss +2 -0
  281. package/styles/schedule/_tailwind3-definition.scss +2 -0
  282. package/styles/schedule/bds.css +8 -8
  283. package/styles/schedule/bootstrap-dark.css +8 -8
  284. package/styles/schedule/bootstrap.css +8 -8
  285. package/styles/schedule/bootstrap4.css +8 -8
  286. package/styles/schedule/bootstrap5-dark.css +8 -8
  287. package/styles/schedule/bootstrap5.3.css +8 -8
  288. package/styles/schedule/bootstrap5.css +8 -8
  289. package/styles/schedule/fabric-dark.css +8 -8
  290. package/styles/schedule/fabric.css +8 -8
  291. package/styles/schedule/fluent-dark.css +9 -9
  292. package/styles/schedule/fluent.css +9 -9
  293. package/styles/schedule/fluent2.css +8 -8
  294. package/styles/schedule/highcontrast-light.css +8 -8
  295. package/styles/schedule/highcontrast.css +8 -8
  296. package/styles/schedule/material-dark.css +8 -8
  297. package/styles/schedule/material.css +8 -8
  298. package/styles/schedule/material3-dark.css +8 -8
  299. package/styles/schedule/material3.css +8 -8
  300. package/styles/schedule/tailwind-dark.css +8 -8
  301. package/styles/schedule/tailwind.css +8 -8
  302. package/styles/schedule/tailwind3.css +8 -8
  303. package/styles/tailwind-dark-lite.css +11 -8
  304. package/styles/tailwind-dark.css +11 -8
  305. package/styles/tailwind-lite.css +11 -8
  306. package/styles/tailwind.css +11 -8
  307. package/styles/tailwind3-lite.css +11 -8
  308. package/styles/tailwind3.css +11 -8
@@ -0,0 +1,2055 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { createElement, L10n, isNullOrUndefined, addClass, remove, EventHandler, extend, append, EmitType, detach } from '@syncfusion/ej2-base';
3
+ import { cldrData, removeClass, getValue, getDefaultDateObject, closest, KeyboardEventArgs, SanitizeHtmlHelper, initializeCSPTemplate } from '@syncfusion/ej2-base';
4
+ import { Query, Deferred } from '@syncfusion/ej2-data';
5
+ import { CheckBox, ChangeEventArgs, Button } from '@syncfusion/ej2-buttons';
6
+ import { Dialog, DialogModel, BeforeOpenEventArgs, BeforeCloseEventArgs } from '@syncfusion/ej2-popups';
7
+ import { DropDownList, FilteringEventArgs, MultiSelect, ChangeEventArgs as ddlChangeEventArgs, MultiSelectChangeEventArgs, PopupEventArgs } from '@syncfusion/ej2-dropdowns';
8
+ import { Input, FormValidator, NumericTextBox } from '@syncfusion/ej2-inputs';
9
+ import { DatePicker, DateTimePicker, ChangedEventArgs } from '@syncfusion/ej2-calendars';
10
+ import { Schedule } from '../base/schedule';
11
+ import { EJ2Instance, EventFieldsMapping, PopupOpenEventArgs, TdData, CellClickEventArgs, PopupCloseEventArgs, CallbackFunction } from '../base/interface';
12
+ import { CurrentAction } from '../base/type';
13
+ import { FieldValidator } from './form-validator';
14
+ import { RecurrenceEditor } from '../../recurrence-editor/recurrence-editor';
15
+ import { ResourcesModel } from '../models/resources-model';
16
+ import * as cls from '../base/css-constant';
17
+ import * as event from '../base/constant';
18
+ import * as util from '../base/util';
19
+
20
+ const EVENT_FIELD: string = 'e-field';
21
+ const REPEAT_CONTAINER_CLASS: string = 'e-recurrence-container';
22
+ const REPEAT_BUTTON_ICON_CLASS: string = 'e-recurrence-edit';
23
+ const REPEAT_BUTTON_CLASS: string = 'e-recurrence-edit-button';
24
+ const REPEAT_DIALOG_CLASS: string = 'e-recurrence-dialog';
25
+ const HIDE_STYLE_CLASS: string = 'e-hide';
26
+
27
+ /**
28
+ * Event editor window
29
+ */
30
+ export class EventWindow {
31
+ private parent: Schedule;
32
+ public dialogObject: Dialog;
33
+ private element: HTMLElement;
34
+ private fields: EventFieldsMapping;
35
+ private l10n: L10n;
36
+ private eventData: Record<string, any>;
37
+ private eventCrudData: Record<string, any>;
38
+ private fieldValidator: FieldValidator;
39
+ private recurrenceEditor: RecurrenceEditor;
40
+ private repeatDialogObject: Dialog;
41
+ private repeatTempRule: string;
42
+ private repeatRule: string;
43
+ private repeatStatus: CheckBox;
44
+ private buttonObj: Button;
45
+ private repeatStartDate: Date;
46
+ private cellClickAction: boolean;
47
+ private duration: number;
48
+ private isCrudAction: boolean;
49
+ private eventWindowTime: Record<string, Date>;
50
+ private isEnterKey: boolean;
51
+ private dialogEvent: Event;
52
+
53
+ constructor(parent: Schedule) {
54
+ this.parent = parent;
55
+ this.l10n = this.parent.localeObj;
56
+ this.fields = this.parent.eventFields;
57
+ this.eventWindowTime = { startTime: new Date(), endTime: new Date() };
58
+ this.renderEventWindow();
59
+ }
60
+
61
+ private renderEventWindow(): void {
62
+ this.element = createElement('div', { id: this.parent.element.id + '_dialog_wrapper' });
63
+ this.parent.element.appendChild(this.element);
64
+ const dialogModel: DialogModel = {
65
+ animationSettings: { effect: 'Zoom' },
66
+ content: this.getEventWindowContent(),
67
+ cssClass: cls.EVENT_WINDOW_DIALOG_CLASS,
68
+ enableRtl: this.parent.enableRtl,
69
+ enableHtmlSanitizer: this.parent.enableHtmlSanitizer,
70
+ height: this.parent.isAdaptive ? '100%' : 'auto',
71
+ minHeight: '300px',
72
+ isModal: true,
73
+ showCloseIcon: this.parent.isAdaptive ? false : true,
74
+ target: document.body,
75
+ visible: false,
76
+ width: '500px',
77
+ beforeOpen: this.onBeforeOpen.bind(this),
78
+ beforeClose: this.onBeforeClose.bind(this)
79
+ };
80
+ if (this.parent.isAdaptive) {
81
+ dialogModel.cssClass = cls.EVENT_WINDOW_DIALOG_CLASS + ' ' + cls.DEVICE_CLASS;
82
+ if (!this.parent.editorHeaderTemplate) {
83
+ dialogModel.header = '<div class="e-title-header"><div class="e-back-icon e-icons"></div><div class="e-title-text">' +
84
+ this.l10n.getConstant('newEvent') + '</div><div class="e-save-icon e-icons"></div></div>';
85
+ }
86
+ } else {
87
+ if (!this.parent.editorFooterTemplate) {
88
+ this.renderDialogButtons(dialogModel);
89
+ }
90
+ if (!this.parent.editorHeaderTemplate) {
91
+ dialogModel.header = '<div class="e-title-text">' + this.l10n.getConstant('newEvent') + '</div>';
92
+ }
93
+ }
94
+ this.dialogObject = new Dialog(dialogModel, this.element);
95
+ if (this.dialogObject.element.querySelector('.e-dlg-closeicon-btn')) {
96
+ this.dialogObject.element.querySelector('.e-dlg-closeicon-btn').setAttribute('title', this.l10n.getConstant('close'));
97
+ }
98
+ this.addEventHandlers();
99
+ addClass([this.element.parentElement], cls.EVENT_WINDOW_DIALOG_CLASS + '-container');
100
+ EventHandler.add(this.dialogObject.element, 'keydown', this.preventEventSave, this);
101
+ this.applyFormValidation();
102
+ }
103
+
104
+ private renderDialogButtons(dialogButton: DialogModel | Dialog): void {
105
+ dialogButton.buttons = [{
106
+ buttonModel: {
107
+ content: this.l10n.getConstant('deleteButton'), cssClass: cls.DELETE_EVENT_CLASS,
108
+ disabled: !this.parent.eventSettings.allowDeleting || this.parent.readonly
109
+ },
110
+ click: this.eventDelete.bind(this)
111
+ }, {
112
+ buttonModel: {
113
+ content: this.l10n.getConstant('saveButton'), cssClass: 'e-primary ' + cls.EVENT_WINDOW_SAVE_BUTTON_CLASS,
114
+ isPrimary: true, disabled: !this.parent.eventSettings.allowAdding || this.parent.readonly
115
+ },
116
+ click: this.eventSave.bind(this)
117
+ }, {
118
+ buttonModel: { cssClass: cls.EVENT_WINDOW_CANCEL_BUTTON_CLASS, content: this.l10n.getConstant('cancelButton') },
119
+ click: this.dialogClose.bind(this)
120
+ }];
121
+ }
122
+
123
+ private addEventHandlers(): void {
124
+ const backIcon: Element = this.element.querySelector('.' + cls.EVENT_WINDOW_BACK_ICON_CLASS);
125
+ const saveIcon: Element = this.element.querySelector('.' + cls.EVENT_WINDOW_SAVE_ICON_CLASS);
126
+ if (this.parent.isAdaptive && !isNullOrUndefined(backIcon) && !isNullOrUndefined(saveIcon)) {
127
+ EventHandler.add(backIcon, 'click', this.dialogClose, this);
128
+ EventHandler.add(saveIcon, 'click', this.eventSave, this);
129
+ }
130
+ }
131
+
132
+ public refresh(): void {
133
+ this.destroy(true);
134
+ this.renderEventWindow();
135
+ }
136
+
137
+ public refreshRecurrenceEditor(): void {
138
+ if (this.recurrenceEditor) {
139
+ const recurrenceEditor: HTMLElement = this.recurrenceEditor.element;
140
+ this.recurrenceEditor.destroy();
141
+ this.createRecurrenceEditor(recurrenceEditor);
142
+ }
143
+ }
144
+
145
+ public setRecurrenceEditor(recurrenceEditor: RecurrenceEditor): void {
146
+ if (this.parent.editorTemplate) {
147
+ this.recurrenceEditor = recurrenceEditor;
148
+ }
149
+ }
150
+
151
+ public openEditor(data: Record<string, any>, type: CurrentAction, isEventData?: boolean, repeatType?: number): void {
152
+ this.parent.currentAction = type;
153
+ this.parent.removeNewEventElement();
154
+ if (this.parent.quickPopup) {
155
+ this.parent.quickPopup.quickPopupHide(true);
156
+ }
157
+ this.parent.inlineModule.removeInlineAppointmentElement();
158
+ if (type === 'Add') {
159
+ let eventObj: Record<string, any> = {};
160
+ this.cellClickAction = !isEventData;
161
+ this.parent.activeCellsData = data as unknown as CellClickEventArgs;
162
+ const event: Record<string, any> = data;
163
+ if (this.cellClickAction) {
164
+ this.convertToEventData(event, eventObj);
165
+ } else {
166
+ this.parent.activeCellsData = {
167
+ startTime: <Date>(event.startTime || event[this.fields.startTime]),
168
+ endTime: <Date>(event.endTime || event[this.fields.endTime]),
169
+ isAllDay: <boolean>(event.isAllDay || event[this.fields.isAllDay]),
170
+ element: <HTMLElement>event.element,
171
+ groupIndex: <number>event.groupIndex
172
+ };
173
+ eventObj = event;
174
+ }
175
+ data = eventObj;
176
+ }
177
+ if (!isNullOrUndefined(this.parent.editorHeaderTemplate)) {
178
+ this.parent.resetTemplates(['editorHeaderTemplate']);
179
+ if (this.parent.isAdaptive && !this.parent.editorFooterTemplate) {
180
+ this.dialogObject.header = this.createAdaptiveHeaderElement(data);
181
+ } else {
182
+ this.dialogObject.header = this.getDialogHeader(data);
183
+ }
184
+ }
185
+ if (!isNullOrUndefined(this.parent.editorFooterTemplate)) {
186
+ this.parent.resetTemplates(['editorFooterTemplate']);
187
+ this.dialogObject.footerTemplate = this.getDialogFooter(data);
188
+ }
189
+ if (!isNullOrUndefined(this.parent.editorHeaderTemplate) || !isNullOrUndefined(this.parent.editorFooterTemplate)) {
190
+ this.dialogObject.dataBind();
191
+ this.addEventHandlers();
192
+ }
193
+ if (!isNullOrUndefined(this.parent.editorTemplate)) {
194
+ this.renderFormElements(this.element.querySelector('.e-schedule-form'), data, type, repeatType);
195
+ } else {
196
+ this.setEditorContent(data, type, repeatType);
197
+ }
198
+ }
199
+
200
+ private setEditorContent(data: Record<string, any>, type: CurrentAction, repeatType: number): void {
201
+ if (!this.parent.isAdaptive && isNullOrUndefined(this.parent.editorTemplate)) {
202
+ removeClass([this.dialogObject.element.querySelector('.e-recurrenceeditor')], cls.DISABLE_CLASS);
203
+ }
204
+ if (this.recurrenceEditor) {
205
+ this.recurrenceEditor.firstDayOfWeek = this.parent.activeViewOptions.firstDayOfWeek;
206
+ }
207
+ switch (type) {
208
+ case 'Add':
209
+ this.onCellDetailsUpdate(data, repeatType);
210
+ break;
211
+ case 'Save':
212
+ case 'EditOccurrence':
213
+ case 'EditSeries':
214
+ case 'EditFollowingEvents':
215
+ if (type === 'EditOccurrence' && !this.parent.isAdaptive && isNullOrUndefined(this.parent.editorTemplate)) {
216
+ addClass([this.dialogObject.element.querySelector('.e-recurrenceeditor')], cls.DISABLE_CLASS);
217
+ }
218
+ this.cellClickAction = false;
219
+ this.onEventDetailsUpdate(data);
220
+ break;
221
+ }
222
+ }
223
+
224
+ public setDialogContent(): void {
225
+ this.dialogObject.content = this.getEventWindowContent();
226
+ this.dialogObject.dataBind();
227
+ this.applyFormValidation();
228
+ }
229
+ public setDialogHeader(): void {
230
+ if (!isNullOrUndefined(this.parent.editorHeaderTemplate)) {
231
+ this.parent.resetTemplates(['editorHeaderTemplate']);
232
+ if (this.parent.isAdaptive && !this.parent.editorFooterTemplate) {
233
+ this.dialogObject.header = this.createAdaptiveHeaderElement();
234
+ }
235
+ else {
236
+ this.dialogObject.header = this.getDialogHeader();
237
+ }
238
+ } else if (this.parent.isAdaptive) {
239
+ this.dialogObject.header = '<div class="e-title-header"><div class="e-back-icon e-icons"></div><div class="e-title-text">' +
240
+ this.l10n.getConstant('newEvent') + '</div><div class="e-save-icon e-icons"></div></div>';
241
+ } else {
242
+ this.dialogObject.header = '<div class="e-title-text">' + this.l10n.getConstant('newEvent') + '</div>';
243
+ }
244
+ this.dialogObject.dataBind();
245
+ this.addEventHandlers();
246
+ }
247
+ public setDialogFooter(): void {
248
+ if (!isNullOrUndefined(this.parent.editorFooterTemplate)) {
249
+ this.parent.resetTemplates(['editorFooterTemplate']);
250
+ this.dialogObject.footerTemplate = this.getDialogFooter();
251
+ } else if (!this.parent.isAdaptive && isNullOrUndefined(this.parent.editorFooterTemplate)) {
252
+ this.renderDialogButtons(this.dialogObject);
253
+ } else if (this.parent.isAdaptive && isNullOrUndefined(this.parent.editorFooterTemplate)) {
254
+ this.dialogObject.footerTemplate = null;
255
+ }
256
+ this.dialogObject.dataBind();
257
+ }
258
+
259
+ private createAdaptiveHeaderElement(data?: Record<string, any>): HTMLElement {
260
+ const header: HTMLElement = createElement('div', { className: 'e-title-header' });
261
+ const headerBackIcon: HTMLElement = createElement('div', { className: 'e-back-icon e-icons' });
262
+ header.appendChild(headerBackIcon);
263
+ const headerTemplate: HTMLElement = this.getDialogHeader(data);
264
+ header.appendChild(headerTemplate);
265
+ const headerSaveIcon: HTMLElement = createElement('div', { className: 'e-save-icon e-icons' });
266
+ header.appendChild(headerSaveIcon);
267
+ return header;
268
+ }
269
+ private getDialogHeader(args?: Record<string, any>): HTMLElement {
270
+ let headerTemplate: Element[] = [];
271
+ const headerTemplateId: string = this.parent.element.id + '_editorHeaderTemplate';
272
+ const temHeaderDiv: HTMLElement = document.createElement('div');
273
+ headerTemplate = [].slice.call(this.parent.getEditorHeaderTemplate()(args || {}, this.parent, 'editorHeaderTemplate', headerTemplateId, false));
274
+ append(headerTemplate, temHeaderDiv);
275
+ return temHeaderDiv;
276
+ }
277
+
278
+ private getDialogFooter(args?: Record<string, any>): HTMLElement {
279
+ let footerTemplate: Element[] = [];
280
+ const footerTemplateId: string = this.parent.element.id + '_editorFooterTemplate';
281
+ const temFooterDiv: HTMLElement = document.createElement('div');
282
+ footerTemplate = [].slice.call(this.parent.getEditorFooterTemplate()(args || {}, this.parent, 'editorFooterTemplate', footerTemplateId, false));
283
+ append(footerTemplate, temFooterDiv);
284
+ return temFooterDiv;
285
+ }
286
+
287
+ private preventEventSave(e: KeyboardEventArgs): void {
288
+ if (this.parent && !this.parent.allowKeyboardInteraction && (e as KeyboardEventArgs).code === 'Enter') {
289
+ this.isEnterKey = true;
290
+ }
291
+ }
292
+
293
+ private onBeforeOpen(args: BeforeOpenEventArgs): Deferred {
294
+ const endTime: number = this.eventData[this.fields.endTime].getTime();
295
+ const eventProp: PopupOpenEventArgs = {
296
+ type: 'Editor',
297
+ data: this.eventData,
298
+ cancel: false,
299
+ element: this.element,
300
+ target: (this.cellClickAction ? this.parent.activeCellsData.element : this.parent.activeEventData.element) as HTMLElement
301
+ };
302
+ if (this.cellClickAction) {
303
+ eventProp.duration = this.getSlotDuration();
304
+ }
305
+ const saveObj: Button = this.getInstance(cls.EVENT_WINDOW_SAVE_BUTTON_CLASS) as unknown as Button;
306
+ if (saveObj) {
307
+ saveObj.disabled = !(this.cellClickAction ? this.parent.eventSettings.allowAdding : this.parent.eventSettings.allowEditing);
308
+ saveObj.dataBind();
309
+ }
310
+ const deleteObj: Button = this.getInstance(cls.DELETE_EVENT_CLASS) as unknown as Button;
311
+ if (deleteObj) {
312
+ deleteObj.disabled = !this.parent.eventSettings.allowDeleting;
313
+ deleteObj.dataBind();
314
+ }
315
+ const callBackPromise: Deferred = new Deferred();
316
+ this.parent.trigger(event.popupOpen, eventProp, (popupArgs: PopupOpenEventArgs) => {
317
+ args.cancel = popupArgs.cancel;
318
+ args.maxHeight = this.parent.isAdaptive ? 'max-content' : args.maxHeight;
319
+ this.duration = this.cellClickAction ? popupArgs.duration : null;
320
+ if (this.eventData[this.fields.endTime].getTime() === endTime && !this.cellClickAction &&
321
+ (<Date>this.eventData[this.fields.endTime]).getHours() === 0 &&
322
+ (<Date>this.eventData[this.fields.endTime]).getMinutes() === 0) {
323
+ this.eventData = <Record<string, any>>extend({}, this.eventData, null, true);
324
+ this.trimAllDay(this.eventData);
325
+ }
326
+ this.refreshDateTimePicker(this.duration);
327
+ if (this.cellClickAction && popupArgs.duration !== this.getSlotDuration() && isNullOrUndefined(this.parent.editorTemplate)) {
328
+ const startObj: DateTimePicker = this.getInstance(cls.EVENT_WINDOW_START_CLASS) as unknown as DateTimePicker;
329
+ const endObj: DateTimePicker = this.getInstance(cls.EVENT_WINDOW_END_CLASS) as unknown as DateTimePicker;
330
+ endObj.value = new Date(startObj.value.getTime() + (util.MS_PER_MINUTE * popupArgs.duration));
331
+ endObj.dataBind();
332
+ }
333
+ if (this.parent.editorTemplate && this.element.querySelector('.e-recurrenceeditor') && !this.recurrenceEditor) {
334
+ this.recurrenceEditor = this.getInstance('e-recurrenceeditor') as unknown as RecurrenceEditor;
335
+ }
336
+ callBackPromise.resolve(args);
337
+ });
338
+ return callBackPromise;
339
+ }
340
+
341
+ private onBeforeClose(args: BeforeCloseEventArgs): Deferred {
342
+ if (args.isInteracted) {
343
+ this.isCrudAction = false;
344
+ }
345
+ const eventProp: PopupCloseEventArgs = {
346
+ type: 'Editor',
347
+ event: args.event || this.dialogEvent,
348
+ data: this.eventCrudData,
349
+ cancel: false,
350
+ element: this.element,
351
+ target: (this.cellClickAction ? this.parent.activeCellsData.element : this.parent.activeEventData.element) as HTMLElement
352
+ };
353
+ const callBackPromise: Deferred = new Deferred();
354
+ this.parent.trigger(event.popupClose, eventProp, (popupArgs: PopupCloseEventArgs) => {
355
+ args.cancel = popupArgs.cancel;
356
+ if (!popupArgs.cancel) {
357
+ if (this.isCrudAction) {
358
+ args.cancel = this.processCrudActions(popupArgs.data);
359
+ this.isCrudAction = args.cancel;
360
+ }
361
+ if (!this.isCrudAction) {
362
+ this.resetForm();
363
+ this.parent.eventBase.focusElement(true);
364
+ this.eventCrudData = null;
365
+ }
366
+ }
367
+ callBackPromise.resolve(args);
368
+ });
369
+ return callBackPromise;
370
+ }
371
+
372
+ private getEventWindowContent(): HTMLElement {
373
+ const container: HTMLElement = createElement('div', { className: cls.FORM_CONTAINER_CLASS });
374
+ const form: HTMLFormElement = createElement('form', {
375
+ id: this.parent.element.id + 'EditForm',
376
+ className: cls.FORM_CLASS
377
+ }) as HTMLFormElement;
378
+ form.onsubmit = () => { return false; };
379
+ this.renderFormElements(form);
380
+ container.appendChild(form);
381
+ return container;
382
+ }
383
+
384
+ private renderFormElements(form: HTMLFormElement, args?: Record<string, any>, type?: CurrentAction, repeatType?: number): void {
385
+ if (!isNullOrUndefined(this.parent.editorTemplate)) {
386
+ if (args) {
387
+ if (this.fieldValidator) {
388
+ this.fieldValidator.destroy();
389
+ this.fieldValidator = null;
390
+ }
391
+ if (this.recurrenceEditor) {
392
+ this.recurrenceEditor.destroy();
393
+ this.recurrenceEditor = null;
394
+ }
395
+ this.destroyComponents();
396
+ this.parent.resetTemplates(['editorTemplate']);
397
+ EventHandler.clearEvents(form);
398
+ if (!this.parent.isReact) {
399
+ const formElements: HTMLElement[] = [].slice.call(form.children);
400
+ for (const element of formElements) {
401
+ remove(element);
402
+ }
403
+ }
404
+ }
405
+ const templateId: string = this.parent.element.id + '_editorTemplate';
406
+ const tempEle: HTMLElement[] =
407
+ [].slice.call(this.parent.getEditorTemplate()(args || {}, this.parent, 'editorTemplate', templateId, false));
408
+ append(tempEle, form);
409
+ this.parent.renderTemplates(() => {
410
+ if (this.element) {
411
+ this.applyFormValidation();
412
+ if (args) {
413
+ this.setEditorContent(args, type, repeatType);
414
+ }
415
+ }
416
+ });
417
+ } else {
418
+ form.appendChild(this.getDefaultEventWindowContent());
419
+ if (args) {
420
+ this.setEditorContent(args, type, repeatType);
421
+ }
422
+ }
423
+ }
424
+
425
+ private getDefaultEventWindowContent(): HTMLElement {
426
+ const parentDiv: HTMLElement = this.createDivElement(cls.EVENT_WINDOW_DIALOG_PARENT_CLASS);
427
+ const titleLocationDiv: HTMLElement = this.createDivElement(cls.EVENT_WINDOW_TITLE_LOCATION_DIV_CLASS);
428
+ parentDiv.appendChild(titleLocationDiv);
429
+ titleLocationDiv.appendChild(this.renderTextBox(cls.SUBJECT_CLASS));
430
+ titleLocationDiv.appendChild(this.renderTextBox(cls.LOCATION_CLASS));
431
+ const startEndDateTimeDiv: HTMLElement = this.createDivElement(cls.EVENT_WINDOW_START_END_DIV_CLASS);
432
+ parentDiv.appendChild(startEndDateTimeDiv);
433
+ startEndDateTimeDiv.appendChild(this.renderDateTimePicker(cls.EVENT_WINDOW_START_CLASS, this.onTimeChange.bind(this)));
434
+ startEndDateTimeDiv.appendChild(this.renderDateTimePicker(cls.EVENT_WINDOW_END_CLASS));
435
+ const allDayTimezoneDiv: HTMLElement = this.createDivElement(cls.EVENT_WINDOW_ALLDAY_TZ_DIV_CLASS);
436
+ parentDiv.appendChild(allDayTimezoneDiv);
437
+ allDayTimezoneDiv.appendChild(this.renderCheckBox(cls.EVENT_WINDOW_ALL_DAY_CLASS));
438
+ allDayTimezoneDiv.appendChild(this.renderCheckBox(cls.TIME_ZONE_CLASS));
439
+ const timezoneParentDiv: HTMLElement = this.createDivElement(cls.EVENT_WINDOW_TIME_ZONE_DIV_CLASS);
440
+ parentDiv.appendChild(timezoneParentDiv);
441
+ timezoneParentDiv.appendChild(this.renderDropDown(cls.EVENT_WINDOW_START_TZ_CLASS));
442
+ timezoneParentDiv.appendChild(this.renderDropDown(cls.EVENT_WINDOW_END_TZ_CLASS));
443
+ const repeatParentDiv: HTMLElement = this.createDivElement(cls.EVENT_WINDOW_REPEAT_DIV_CLASS);
444
+ parentDiv.appendChild(repeatParentDiv);
445
+ const repeatDiv: HTMLElement = this.renderCheckBox(cls.EVENT_WINDOW_REPEAT_CLASS);
446
+ const repeatEditContainer: HTMLElement = createElement('span', { className: REPEAT_CONTAINER_CLASS });
447
+ const button: HTMLElement = createElement('button', {
448
+ className: REPEAT_BUTTON_CLASS,
449
+ attrs: { type: 'button', 'title': this.l10n.getConstant('editRecurrence') }
450
+ });
451
+ this.buttonObj = new Button({ iconCss: REPEAT_BUTTON_ICON_CLASS + ' e-icons', cssClass: 'e-medium ' + this.parent.cssClass });
452
+ repeatEditContainer.appendChild(button);
453
+ this.buttonObj.appendTo(button);
454
+ repeatDiv.appendChild(repeatEditContainer);
455
+ repeatParentDiv.appendChild(repeatDiv);
456
+ if (this.parent.isAdaptive) {
457
+ EventHandler.add(button, 'click', this.loadRecurrenceEditor, this);
458
+ } else {
459
+ this.createRecurrenceEditor(parentDiv);
460
+ }
461
+ if (this.parent.resourceCollection.length > 0) {
462
+ const resourceParentDiv: HTMLElement = this.createDivElement(cls.EVENT_WINDOW_RESOURCES_DIV_CLASS);
463
+ for (const resource of this.parent.resourceBase.resourceCollection) {
464
+ resourceParentDiv.appendChild(this.renderResourceDetails(resource));
465
+ }
466
+ parentDiv.appendChild(resourceParentDiv);
467
+ }
468
+ const description: HTMLElement = this.createDivElement(cls.DESCRIPTION_CLASS + '-row');
469
+ description.appendChild(this.renderTextBox(cls.DESCRIPTION_CLASS));
470
+ parentDiv.appendChild(description);
471
+ const submit: HTMLElement = createElement('button', { attrs: { type: 'hidden', title: 'submit' } });
472
+ submit.style.display = 'none';
473
+ parentDiv.appendChild(submit);
474
+ return parentDiv;
475
+ }
476
+
477
+ private createRecurrenceEditor(parentDiv: HTMLElement): void {
478
+ const recurrenceEditor: HTMLElement = createElement('div', { id: this.parent.element.id + '_recurrence_editor' });
479
+ parentDiv.appendChild(recurrenceEditor);
480
+ this.recurrenceEditor = this.renderRecurrenceEditor();
481
+ this.recurrenceEditor.appendTo(recurrenceEditor);
482
+ this.updateMinMaxDateToEditor();
483
+ }
484
+
485
+ private createDivElement(className?: string): HTMLElement {
486
+ return createElement('div', { className: className });
487
+ }
488
+
489
+ private createInputElement(className: string, fieldName: string, type?: string): HTMLElement {
490
+ return createElement(type || 'input', {
491
+ className: className, attrs: {
492
+ type: 'text', name: fieldName, value: '', id: fieldName
493
+ }
494
+ });
495
+ }
496
+
497
+ private getSlotDuration(): number {
498
+ return this.parent.activeViewOptions.timeScale.interval / this.parent.activeViewOptions.timeScale.slotCount;
499
+ }
500
+
501
+ private renderDateTimePicker(value: string, changeEvent?: EmitType<ChangedEventArgs>): HTMLElement {
502
+ const dateTimeDiv: HTMLElement = this.createDivElement(value + '-container');
503
+ const fieldName: string = this.getFieldName(value);
504
+ const dateTimeInput: HTMLElement = this.createInputElement(value + ' ' + EVENT_FIELD, fieldName);
505
+ dateTimeDiv.appendChild(dateTimeInput);
506
+ const dateTimePicker: DateTimePicker = new DateTimePicker({
507
+ change: changeEvent,
508
+ firstDayOfWeek: this.parent.activeViewOptions.firstDayOfWeek,
509
+ calendarMode: this.parent.calendarMode,
510
+ min: this.parent.minDate,
511
+ max: new Date(new Date(+this.parent.maxDate).setHours(23, 59, 59)),
512
+ cssClass: this.parent.cssClass,
513
+ enableRtl: this.parent.enableRtl,
514
+ locale: this.parent.locale,
515
+ floatLabelType: 'Always',
516
+ strictMode: true,
517
+ timeFormat: this.parent.activeViewOptions.timeFormat,
518
+ format: (isNullOrUndefined(this.parent.dateFormat) ?
519
+ this.getFormat('dateFormats') : this.parent.dateFormat) + ' ' + this.parent.activeViewOptions.timeFormat,
520
+ placeholder: this.getFieldLabel(value),
521
+ step: this.getSlotDuration(),
522
+ width: '100%'
523
+ });
524
+ dateTimePicker.appendTo(dateTimeInput);
525
+ return dateTimeDiv;
526
+ }
527
+
528
+ public refreshDateTimePicker(duration?: number): void {
529
+ const elementSelector: string = '.' + cls.EVENT_WINDOW_START_CLASS + ',.' + cls.EVENT_WINDOW_END_CLASS;
530
+ const startEndElement: HTMLElement[] = [].slice.call(this.element.querySelectorAll(elementSelector));
531
+ for (const element of startEndElement) {
532
+ const instance: DateTimePicker = ((<HTMLElement>element) as EJ2Instance).ej2_instances[0] as DateTimePicker;
533
+ instance.firstDayOfWeek = this.parent.activeViewOptions.firstDayOfWeek;
534
+ instance.timeFormat = this.parent.activeViewOptions.timeFormat;
535
+ instance.step = duration || this.getSlotDuration();
536
+ instance.dataBind();
537
+ }
538
+ }
539
+
540
+ private onTimeChange(): void {
541
+ const startObj: DateTimePicker = this.getInstance(cls.EVENT_WINDOW_START_CLASS) as unknown as DateTimePicker;
542
+ if (startObj.element.parentElement.classList.contains('e-input-focus')) {
543
+ const endObj: DateTimePicker = this.getInstance(cls.EVENT_WINDOW_END_CLASS) as unknown as DateTimePicker;
544
+ let duration: number = 0;
545
+ if (this.cellClickAction) {
546
+ duration = util.MS_PER_MINUTE * this.duration;
547
+ this.eventWindowTime.startTime = startObj.value;
548
+ } else {
549
+ duration = (<Date>this.eventData[this.fields.endTime]).getTime() - (<Date>this.eventData[this.fields.startTime]).getTime();
550
+ }
551
+ const endDate: Date = (isNullOrUndefined(startObj.value)) ? null : new Date(startObj.value.getTime() + duration);
552
+ if (this.cellClickAction) {
553
+ this.eventWindowTime.endTime = endDate;
554
+ }
555
+ endObj.value = endDate;
556
+ endObj.dataBind();
557
+ }
558
+ if (this.recurrenceEditor) {
559
+ this.recurrenceEditor.updateRuleUntilDate(this.eventWindowTime.startTime);
560
+ }
561
+ }
562
+
563
+ private renderResourceDetails(resourceData: ResourcesModel): HTMLElement {
564
+ const fieldName: string = resourceData.field;
565
+ const value: string = 'e-' + fieldName;
566
+ const labelValue: string = resourceData.title;
567
+ const resourceDiv: HTMLElement = this.createDivElement(value + '-container' + ' ' + 'e-resources');
568
+ const resourceInput: HTMLElement = this.createInputElement(value + ' ' + EVENT_FIELD, fieldName);
569
+ resourceDiv.appendChild(resourceInput);
570
+ const resourceTemplate: Function = function(data: any): string {
571
+ return SanitizeHtmlHelper.sanitize(`<div class="e-resource-template">
572
+ <div class="e-resource-color" data-resource-color="${data[resourceData.colorField]}"></div>
573
+ <div class="e-resource-text">${data[resourceData.textField]}</div></div>`);
574
+ };
575
+ initializeCSPTemplate(resourceTemplate, resourceData);
576
+ if (resourceData.allowMultiple) {
577
+ const listObj: MultiSelect = new MultiSelect({
578
+ enableRtl: this.parent.enableRtl,
579
+ enableHtmlSanitizer: this.parent.enableHtmlSanitizer,
580
+ cssClass: this.parent.cssClass || '',
581
+ dataSource: resourceData.dataSource as Record<string, any>[],
582
+ change: this.onMultiselectResourceChange.bind(this),
583
+ itemTemplate: resourceTemplate as any,
584
+ fields: {
585
+ text: resourceData.textField,
586
+ value: resourceData.idField
587
+ },
588
+ htmlAttributes: {'name': fieldName },
589
+ floatLabelType: 'Always',
590
+ placeholder: labelValue,
591
+ popupHeight: '230px',
592
+ popupWidth: '447px',
593
+ mode: 'Box',
594
+ open: (args: PopupEventArgs) => {
595
+ Promise.resolve().then(() => {
596
+ this.applyStylesAfterRender(args);
597
+ });
598
+ }
599
+ });
600
+ listObj.appendTo(resourceInput);
601
+ } else {
602
+ const dropDownList: DropDownList = new DropDownList({
603
+ cssClass: this.parent.cssClass || '',
604
+ change: this.onDropdownResourceChange.bind(this),
605
+ dataSource: resourceData.dataSource as Record<string, any>[],
606
+ enableRtl: this.parent.enableRtl,
607
+ fields: {
608
+ text: resourceData.textField,
609
+ value: resourceData.idField
610
+ },
611
+ htmlAttributes: { 'name': fieldName },
612
+ floatLabelType: 'Always',
613
+ placeholder: labelValue,
614
+ popupHeight: '230px',
615
+ popupWidth: '447px',
616
+ itemTemplate: resourceTemplate as any,
617
+ open: (args: PopupEventArgs) => {
618
+ Promise.resolve().then(() => {
619
+ this.applyStylesAfterRender(args);
620
+ });
621
+ }
622
+ });
623
+ dropDownList.appendTo(resourceInput);
624
+ }
625
+ return resourceDiv;
626
+ }
627
+
628
+ private applyStylesAfterRender(args: PopupEventArgs): void {
629
+ if (!args.popup || !args.popup.element) { return; }
630
+ const resourceColors: NodeListOf<Element> = args.popup.element.querySelectorAll('.e-resource-color[data-resource-color]');
631
+ resourceColors.forEach((element: Element) => {
632
+ const color: string = element.getAttribute('data-resource-color');
633
+ if (color) {
634
+ (element as HTMLElement).style.backgroundColor = color;
635
+ }
636
+ });
637
+ }
638
+
639
+ private renderDropDown(value: string): HTMLElement {
640
+ const fieldName: string = this.getFieldName(value);
641
+ const timezoneDiv: HTMLElement = this.createDivElement(value + '-container');
642
+ const timezoneInput: HTMLElement = this.createInputElement(value + ' ' + EVENT_FIELD, fieldName);
643
+ timezoneDiv.appendChild(timezoneInput);
644
+ const dropDownList: DropDownList = new DropDownList({
645
+ allowFiltering: true,
646
+ change: this.onTimezoneChange.bind(this),
647
+ cssClass: this.parent.cssClass || '',
648
+ dataSource: this.parent.timezoneDataSource as any[],
649
+ enableRtl: this.parent.enableRtl,
650
+ fields: { text: 'Text', value: 'Value' },
651
+ filterBarPlaceholder: this.parent.localeObj.getConstant('searchTimezone'),
652
+ noRecordsTemplate: this.parent.localeObj.getConstant('noRecords'),
653
+ filtering: (e: FilteringEventArgs) => {
654
+ let query: Query = new Query();
655
+ query = (e.text !== '') ? query.where('Text', 'contains', e.text, true) : query;
656
+ e.updateData(this.parent.timezoneDataSource as any[], query);
657
+ },
658
+ htmlAttributes: { 'title': this.getFieldLabel(value), 'name': fieldName },
659
+ floatLabelType: 'Always',
660
+ placeholder: this.getFieldLabel(value),
661
+ popupHeight: '230px'
662
+ });
663
+ dropDownList.appendTo(timezoneInput);
664
+ return timezoneDiv;
665
+ }
666
+
667
+ private onMultiselectResourceChange(args: MultiSelectChangeEventArgs): void {
668
+ if (!args.value || !this.parent.activeViewOptions.group.byGroupID || this.parent.resourceCollection.length <= 1) {
669
+ return;
670
+ }
671
+ const resourceCollection: ResourcesModel[] = this.parent.resourceBase.resourceCollection;
672
+ const fieldName: string = args.element.getAttribute('name') || this.getColumnName(args.element as HTMLInputElement);
673
+ for (let i: number = 0; i < resourceCollection.length; i++) {
674
+ if (resourceCollection[parseInt(i.toString(), 10)].field === fieldName && i < resourceCollection.length - 1) {
675
+ const resObject: MultiSelect | DropDownList = this.createInstance(i);
676
+ let datasource: Record<string, any>[] = [];
677
+ for (let j: number = 0; j < args.value.length; j++) {
678
+ const resourceModel: ResourcesModel = resourceCollection[i + 1];
679
+ // eslint-disable-next-line max-len
680
+ const filter: Record<string, any> = (resourceModel.dataSource as Record<string, any>[]).filter((data: Record<string, any>) =>
681
+ data[resourceModel.groupIDField] === args.value[parseInt(j.toString(), 10)])[0];
682
+ const groupId: number = (!isNullOrUndefined(filter)) ?
683
+ filter[resourceCollection[i + 1].groupIDField] as number : null;
684
+ const filterRes: Record<string, any>[] = this.filterDatasource(i, groupId);
685
+ datasource = datasource.concat(filterRes);
686
+ }
687
+ resObject.dataSource = datasource;
688
+ resObject.dataBind();
689
+ }
690
+ }
691
+ }
692
+
693
+ private createInstance(index: number): MultiSelect | DropDownList {
694
+ const resourceData: Record<string, any> = this.parent.resourceBase.resourceCollection[index + 1] as Record<string, any>;
695
+ const resObject: MultiSelect | DropDownList = (this.element.querySelector('.e-' + resourceData.field) as EJ2Instance).
696
+ ej2_instances[0] as MultiSelect | DropDownList;
697
+ resObject.clear();
698
+ return resObject;
699
+ }
700
+
701
+ private onDropdownResourceChange(args: ddlChangeEventArgs): void {
702
+ if (!args.value || this.parent.resourceCollection.length <= 1 || !this.parent.activeViewOptions.group.byGroupID) {
703
+ return;
704
+ }
705
+ const fieldName: string = args.element.getAttribute('name') || this.getColumnName(args.element as HTMLInputElement);
706
+ const resourceCollection: ResourcesModel[] = this.parent.resourceBase.resourceCollection;
707
+ for (let i: number = 0; i < resourceCollection.length; i++) {
708
+ if ((i < resourceCollection.length - 1) && resourceCollection[parseInt(i.toString(), 10)].field === fieldName) {
709
+ const resObj: MultiSelect | DropDownList = this.createInstance(i);
710
+ const groupId: number =
711
+ (args.itemData as Record<string, any>)[resourceCollection[parseInt(i.toString(), 10)].idField] as number;
712
+ resObj.dataSource = this.filterDatasource(i, groupId);
713
+ resObj.dataBind();
714
+ const resValue: string = (resObj.dataSource.length > 0) ?
715
+ resObj.dataSource[0][resourceCollection[i + 1].idField] as string : null;
716
+ resObj.value = (resourceCollection[i + 1].allowMultiple) ? [resValue] : resValue;
717
+ resObj.dataBind();
718
+ }
719
+ }
720
+ }
721
+
722
+ private filterDatasource(index: number, groupId: number | string): Record<string, any>[] {
723
+ const resourceData: ResourcesModel = this.parent.resourceBase.resourceCollection[index + 1];
724
+ return (resourceData.dataSource as Record<string, any>[]).filter((data: Record<string, any>) =>
725
+ data[resourceData.groupIDField] === groupId);
726
+ }
727
+
728
+ private onTimezoneChange(args: ddlChangeEventArgs): void {
729
+ const fieldName: string = args.element.getAttribute('name') || this.getColumnName(args.element as HTMLInputElement);
730
+ if (fieldName === this.parent.eventFields.startTimezone) {
731
+ const startTimezoneObj: DropDownList = this.getInstance(cls.EVENT_WINDOW_START_TZ_CLASS) as unknown as DropDownList;
732
+ const endTimezoneObj: DropDownList = this.getInstance(cls.EVENT_WINDOW_END_TZ_CLASS) as unknown as DropDownList;
733
+ endTimezoneObj.value = startTimezoneObj.value;
734
+ endTimezoneObj.dataBind();
735
+ }
736
+ }
737
+
738
+ private renderCheckBox(value: string): HTMLElement {
739
+ const checkBoxDiv: HTMLElement = this.createDivElement(value + '-container');
740
+ const fieldName: string = this.getFieldName(value);
741
+ const checkBoxInput: HTMLElement = this.createInputElement(value + ' ' + EVENT_FIELD, fieldName);
742
+ checkBoxDiv.appendChild(checkBoxInput);
743
+ const checkBox: CheckBox = new CheckBox({
744
+ change: this.onChange.bind(this),
745
+ cssClass: value + ' ' + this.parent.cssClass,
746
+ enableRtl: this.parent.enableRtl,
747
+ enableHtmlSanitizer: this.parent.enableHtmlSanitizer,
748
+ label: this.getFieldLabel(value)
749
+ });
750
+ checkBox.appendTo(checkBoxInput);
751
+ checkBoxInput.setAttribute('name', fieldName);
752
+ if (fieldName === 'Repeat') {
753
+ this.repeatStatus = checkBox;
754
+ }
755
+ return checkBoxDiv;
756
+ }
757
+
758
+ private renderTextBox(value: string): HTMLElement {
759
+ const textBoxDiv: HTMLElement = this.createDivElement(value + '-container');
760
+ const fieldName: string = this.getFieldName(value);
761
+ const elementType: string = (value === cls.DESCRIPTION_CLASS) ? 'textarea' : 'input';
762
+ const textBoxInput: HTMLElement = this.createInputElement(value + ' ' + EVENT_FIELD, fieldName, elementType);
763
+ textBoxDiv.appendChild(textBoxInput);
764
+ Input.createInput({
765
+ element: textBoxInput as HTMLInputElement,
766
+ floatLabelType: 'Always',
767
+ properties: {
768
+ enableRtl: this.parent.enableRtl,
769
+ placeholder: this.getFieldLabel(value)
770
+ }
771
+ });
772
+ return textBoxDiv;
773
+ }
774
+
775
+ private getFieldName(name: string): string {
776
+ let fieldName: string = '';
777
+ switch (name) {
778
+ case cls.SUBJECT_CLASS:
779
+ fieldName = this.fields.subject;
780
+ break;
781
+ case cls.LOCATION_CLASS:
782
+ fieldName = this.fields.location;
783
+ break;
784
+ case cls.EVENT_WINDOW_START_CLASS:
785
+ fieldName = this.fields.startTime;
786
+ break;
787
+ case cls.EVENT_WINDOW_END_CLASS:
788
+ fieldName = this.fields.endTime;
789
+ break;
790
+ case cls.DESCRIPTION_CLASS:
791
+ fieldName = this.fields.description;
792
+ break;
793
+ case cls.EVENT_WINDOW_ALL_DAY_CLASS:
794
+ fieldName = this.fields.isAllDay;
795
+ break;
796
+ case cls.EVENT_WINDOW_START_TZ_CLASS:
797
+ fieldName = this.fields.startTimezone;
798
+ break;
799
+ case cls.EVENT_WINDOW_END_TZ_CLASS:
800
+ fieldName = this.fields.endTimezone;
801
+ break;
802
+ case cls.TIME_ZONE_CLASS:
803
+ fieldName = 'Timezone';
804
+ break;
805
+ case cls.EVENT_WINDOW_REPEAT_CLASS:
806
+ fieldName = 'Repeat';
807
+ break;
808
+ }
809
+ return fieldName;
810
+ }
811
+
812
+ private getFieldLabel(fieldName: string): string {
813
+ let labelText: string = '';
814
+ switch (fieldName) {
815
+ case cls.SUBJECT_CLASS:
816
+ labelText = this.parent.editorTitles.subject;
817
+ break;
818
+ case cls.LOCATION_CLASS:
819
+ labelText = this.parent.editorTitles.location;
820
+ break;
821
+ case cls.DESCRIPTION_CLASS:
822
+ labelText = this.parent.editorTitles.description;
823
+ break;
824
+ case cls.EVENT_WINDOW_START_CLASS:
825
+ labelText = this.parent.editorTitles.startTime;
826
+ break;
827
+ case cls.EVENT_WINDOW_END_CLASS:
828
+ labelText = this.parent.editorTitles.endTime;
829
+ break;
830
+ case cls.EVENT_WINDOW_START_TZ_CLASS:
831
+ labelText = this.parent.editorTitles.startTimezone;
832
+ break;
833
+ case cls.EVENT_WINDOW_END_TZ_CLASS:
834
+ labelText = this.parent.editorTitles.endTimezone;
835
+ break;
836
+ case cls.EVENT_WINDOW_REPEAT_CLASS:
837
+ labelText = this.parent.editorTitles.recurrenceRule;
838
+ break;
839
+ case cls.EVENT_WINDOW_ALL_DAY_CLASS:
840
+ labelText = this.parent.editorTitles.isAllDay;
841
+ break;
842
+ case cls.TIME_ZONE_CLASS:
843
+ labelText = this.l10n.getConstant('timezone');
844
+ break;
845
+ }
846
+ return labelText;
847
+ }
848
+
849
+ private onChange(args: ChangeEventArgs): void {
850
+ if (args.event && args.event.target) {
851
+ const targetSelector: string = `.${cls.EVENT_WINDOW_ALL_DAY_CLASS},.${cls.TIME_ZONE_CLASS},.${cls.EVENT_WINDOW_REPEAT_CLASS}`;
852
+ const target: Element = closest(args.event.target as Element, targetSelector);
853
+ if (target.classList.contains(cls.EVENT_WINDOW_ALL_DAY_CLASS)) {
854
+ this.onAllDayChange(args.checked);
855
+ } else if (target.classList.contains(cls.TIME_ZONE_CLASS)) {
856
+ this.timezoneChangeStyle(args.checked);
857
+ } else if (target.classList.contains(cls.EVENT_WINDOW_REPEAT_CLASS)) {
858
+ this.onRepeatChange(args.checked);
859
+ }
860
+ }
861
+ }
862
+
863
+ private renderRepeatDialog(): void {
864
+ const element: HTMLElement = createElement('div');
865
+ this.repeatDialogObject = new Dialog({
866
+ header: this.l10n.getConstant('recurrence'),
867
+ visible: false,
868
+ content: '<div class="e-rec-editor"></div>',
869
+ closeOnEscape: true,
870
+ width: '90%',
871
+ buttons: [{
872
+ click: this.repeatSaveDialog.bind(this),
873
+ buttonModel: { content: this.l10n.getConstant('save'), cssClass: 'e-save', isPrimary: true }
874
+ },
875
+ { click: this.repeatCancelDialog.bind(this), buttonModel: { cssClass: 'e-cancel', content: this.l10n.getConstant('cancel') } }],
876
+ target: this.element,
877
+ animationSettings: { effect: 'Zoom' },
878
+ enableRtl: this.parent.enableRtl,
879
+ enableHtmlSanitizer: this.parent.enableHtmlSanitizer,
880
+ isModal: true,
881
+ cssClass: REPEAT_DIALOG_CLASS,
882
+ open: this.repeatOpenDialog.bind(this)
883
+ });
884
+ this.element.appendChild(element);
885
+ this.repeatDialogObject.appendTo(element);
886
+ this.createRecurrenceEditor(<HTMLElement>this.repeatDialogObject.element.querySelector('.e-rec-editor'));
887
+ }
888
+
889
+ private loadRecurrenceEditor(): void {
890
+ this.repeatDialogObject.show();
891
+ if (this.recurrenceEditor && this.repeatRule) {
892
+ this.recurrenceEditor.setRecurrenceRule(this.repeatRule);
893
+ }
894
+ }
895
+
896
+ private onRepeatChange(state: boolean): void {
897
+ if (state) {
898
+ if (!this.repeatDialogObject) {
899
+ this.renderRepeatDialog();
900
+ }
901
+ this.recurrenceEditor.setProperties({ startDate: <Date>this.repeatStartDate, selectedType: 0 });
902
+ this.loadRecurrenceEditor();
903
+ } else {
904
+ if (this.repeatDialogObject) {
905
+ this.repeatDialogObject.hide();
906
+ }
907
+ this.repeatRule = '';
908
+ if (this.recurrenceEditor) {
909
+ this.recurrenceEditor.setRecurrenceRule(this.repeatRule);
910
+ this.updateRepeatLabel(this.repeatRule);
911
+ }
912
+ const element: HTMLElement = <HTMLElement>this.element.querySelector('.' + REPEAT_CONTAINER_CLASS);
913
+ addClass([element], HIDE_STYLE_CLASS);
914
+ }
915
+ }
916
+
917
+ private repeatSaveDialog(): void {
918
+ this.repeatRule = this.recurrenceEditor.getRecurrenceRule();
919
+ const element: HTMLElement = <HTMLElement>this.element.querySelector('.' + REPEAT_CONTAINER_CLASS);
920
+ if (this.recurrenceEditor.getRecurrenceRule()) {
921
+ removeClass([element], HIDE_STYLE_CLASS);
922
+ } else {
923
+ addClass([element], HIDE_STYLE_CLASS);
924
+ this.repeatStatus.setProperties({ checked: false });
925
+ }
926
+ this.updateRepeatLabel(this.repeatRule);
927
+ this.closeRepeatDialog();
928
+ }
929
+
930
+ private closeRepeatDialog(): void {
931
+ this.repeatDialogObject.hide();
932
+ }
933
+
934
+ private repeatCancelDialog(): void {
935
+ this.closeRepeatDialog();
936
+ if (this.recurrenceEditor) {
937
+ this.recurrenceEditor.setRecurrenceRule(this.repeatTempRule);
938
+ }
939
+ if (!this.repeatTempRule) {
940
+ this.repeatStatus.setProperties({ checked: false });
941
+ }
942
+ }
943
+
944
+ private repeatOpenDialog(): void {
945
+ this.repeatTempRule = this.recurrenceEditor.getRecurrenceRule();
946
+ }
947
+
948
+ private onCellDetailsUpdate(eventObj: Record<string, any>, repeatType: number): void {
949
+ if (!this.parent.eventSettings.allowAdding) {
950
+ return;
951
+ }
952
+ if (this.parent.isAdaptive && repeatType && !this.repeatDialogObject) {
953
+ this.renderRepeatDialog();
954
+ }
955
+ this.element.querySelector('.' + cls.FORM_CLASS).removeAttribute('data-id');
956
+ if (isNullOrUndefined(this.parent.editorHeaderTemplate)) {
957
+ this.element.querySelector('.' + cls.EVENT_WINDOW_TITLE_TEXT_CLASS).innerHTML = this.l10n.getConstant('newEvent');
958
+ }
959
+ eventObj.Timezone = false;
960
+ this.repeatStartDate = <Date>eventObj[this.fields.startTime];
961
+ this.repeatRule = '';
962
+ if (!isNullOrUndefined(this.parent.eventSettings.fields.subject.default)) {
963
+ eventObj[this.fields.subject] = this.parent.eventSettings.fields.subject.default;
964
+ }
965
+ if (!isNullOrUndefined(this.parent.eventSettings.fields.location.default)) {
966
+ eventObj[this.fields.location] = this.parent.eventSettings.fields.location.default;
967
+ }
968
+ if (!isNullOrUndefined(this.parent.eventSettings.fields.description.default)) {
969
+ eventObj[this.fields.description] = this.parent.eventSettings.fields.description.default;
970
+ }
971
+ this.showDetails(eventObj);
972
+ if (eventObj[this.fields.recurrenceRule] && this.recurrenceEditor) {
973
+ this.recurrenceEditor.setRecurrenceRule(<string>eventObj[this.fields.recurrenceRule], <Date>eventObj[this.fields.startTime]);
974
+ this.repeatRule = <string>eventObj[this.fields.recurrenceRule];
975
+ }
976
+ const deleteButton: Element = this.element.querySelector('.' + cls.DELETE_EVENT_CLASS);
977
+ if (deleteButton) {
978
+ addClass([deleteButton], cls.DISABLE_CLASS);
979
+ }
980
+ if (this.recurrenceEditor) {
981
+ this.recurrenceEditor.setProperties({
982
+ startDate: <Date>eventObj[this.fields.startTime],
983
+ selectedType: !isNullOrUndefined(repeatType) ? repeatType : !isNullOrUndefined(eventObj[this.fields.recurrenceRule]) ?
984
+ this.recurrenceEditor.selectedType : 0
985
+ });
986
+ this.repeatRule = this.recurrenceEditor.value;
987
+ }
988
+ if (this.parent.isAdaptive && isNullOrUndefined(this.parent.editorTemplate)) {
989
+ const element: HTMLElement = <HTMLElement>this.element.querySelector('.' + REPEAT_CONTAINER_CLASS);
990
+ if (eventObj[this.fields.recurrenceRule] || repeatType) {
991
+ removeClass([element], HIDE_STYLE_CLASS);
992
+ this.repeatStatus.setProperties({ checked: true });
993
+ }
994
+ else {
995
+ addClass([element], HIDE_STYLE_CLASS);
996
+ this.repeatStatus.setProperties({ checked: false });
997
+ }
998
+ this.updateRepeatLabel(this.repeatRule);
999
+ } else {
1000
+ const saveButton: Element = this.element.querySelector('.' + cls.EVENT_WINDOW_SAVE_BUTTON_CLASS);
1001
+ this.disableButton(saveButton, false);
1002
+ }
1003
+ this.dialogObject.show();
1004
+ }
1005
+
1006
+ public convertToEventData(cellsData: Record<string, any>, eventObj: Record<string, any>): void {
1007
+ if (!cellsData) { return; }
1008
+ if (cellsData.subject) {
1009
+ eventObj[this.fields.subject] = cellsData.subject;
1010
+ }
1011
+ eventObj[this.fields.startTime] = cellsData.startTime;
1012
+ eventObj[this.fields.endTime] = cellsData.endTime;
1013
+ eventObj[this.fields.isAllDay] = cellsData.isAllDay;
1014
+ if (cellsData.RecurrenceRule) {
1015
+ eventObj[this.fields.recurrenceRule] = cellsData.RecurrenceRule;
1016
+ }
1017
+ if (this.parent.resourceCollection.length > 0 || this.parent.activeViewOptions.group.resources.length > 0) {
1018
+ this.parent.resourceBase.setResourceValues(eventObj);
1019
+ }
1020
+ }
1021
+
1022
+ private applyFormValidation(): void {
1023
+ const form: HTMLFormElement = this.element.querySelector('.' + cls.FORM_CLASS) as HTMLFormElement;
1024
+ if (!form) {
1025
+ return;
1026
+ }
1027
+ const getValidationRule: CallbackFunction = (rules: Record<string, any>) =>
1028
+ (rules && Object.keys(rules).length > 0) ? rules : undefined;
1029
+ const rules: Record<string, any> = {};
1030
+ const subjectRule: Record<string, any> = getValidationRule(this.parent.eventSettings.fields.subject.validation);
1031
+ if (!isNullOrUndefined(subjectRule)) {
1032
+ rules[this.parent.eventSettings.fields.subject.name] = subjectRule;
1033
+ }
1034
+ const locationRule: Record<string, any> = getValidationRule(this.parent.eventSettings.fields.location.validation);
1035
+ if (!isNullOrUndefined(locationRule)) {
1036
+ rules[this.parent.eventSettings.fields.location.name] = locationRule;
1037
+ }
1038
+ const startTimeRule: Record<string, any> = getValidationRule(this.parent.eventSettings.fields.startTime.validation);
1039
+ if (!isNullOrUndefined(startTimeRule)) {
1040
+ rules[this.parent.eventSettings.fields.startTime.name] = startTimeRule;
1041
+ }
1042
+ const endTimeRule: Record<string, any> = getValidationRule(this.parent.eventSettings.fields.endTime.validation);
1043
+ if (!isNullOrUndefined(endTimeRule)) {
1044
+ rules[this.parent.eventSettings.fields.endTime.name] = endTimeRule;
1045
+ }
1046
+ const descriptionRule: Record<string, any> = getValidationRule(this.parent.eventSettings.fields.description.validation);
1047
+ if (!isNullOrUndefined(descriptionRule)) {
1048
+ rules[this.parent.eventSettings.fields.description.name] = descriptionRule;
1049
+ }
1050
+ if (this.fieldValidator) {
1051
+ this.fieldValidator.destroy();
1052
+ this.fieldValidator = null;
1053
+ }
1054
+ this.fieldValidator = new FieldValidator();
1055
+ this.fieldValidator.renderFormValidator(form, rules, this.element, this.parent.locale);
1056
+ }
1057
+
1058
+ private showDetails(eventData: Record<string, any>): void {
1059
+ this.eventData = eventData;
1060
+ const eventObj: Record<string, any> = <Record<string, any>>extend({}, eventData, null, true);
1061
+ const formElements: HTMLInputElement[] = this.getFormElements(cls.EVENT_WINDOW_DIALOG_CLASS);
1062
+ if ((!this.cellClickAction || this.cellClickAction && !isNullOrUndefined(this.parent.editorTemplate)) &&
1063
+ (<Date>eventObj[this.fields.endTime]).getHours() === 0 && (<Date>eventObj[this.fields.endTime]).getMinutes() === 0) {
1064
+ this.trimAllDay(eventObj);
1065
+ }
1066
+ const keyNames: string[] = Object.keys(eventObj);
1067
+ for (const curElement of formElements) {
1068
+ const columnName: string = curElement.name || this.getColumnName(curElement);
1069
+ if (!isNullOrUndefined(columnName) && columnName !== '') {
1070
+ if (keyNames.indexOf(columnName) !== -1) {
1071
+ this.setValueToElement(curElement as HTMLElement, eventObj[`${columnName}`] as string);
1072
+ } else {
1073
+ this.setDefaultValueToElement(curElement as HTMLElement);
1074
+ }
1075
+ }
1076
+ }
1077
+ if (isNullOrUndefined(this.parent.editorTemplate)) {
1078
+ this.onAllDayChange(eventObj[this.fields.isAllDay] as boolean);
1079
+ const timezoneObj: CheckBox = this.getInstance(cls.TIME_ZONE_CLASS + '.' + EVENT_FIELD) as unknown as CheckBox;
1080
+ if (!(isNullOrUndefined(eventObj[this.fields.startTimezone]) && isNullOrUndefined(eventObj[this.fields.endTimezone]))) {
1081
+ timezoneObj.checked = true;
1082
+ timezoneObj.dataBind();
1083
+ }
1084
+ this.timezoneChangeStyle(timezoneObj.checked);
1085
+ delete eventObj.Timezone;
1086
+ }
1087
+ }
1088
+
1089
+ private getColumnName(element: HTMLInputElement): string {
1090
+ let attrName: string = element.getAttribute('data-name') || '';
1091
+ if (attrName === '') {
1092
+ let isDropDowns: boolean = false;
1093
+ let fieldSelector: string = '';
1094
+ if (element.classList.contains('e-dropdownlist')) {
1095
+ fieldSelector = 'e-ddl';
1096
+ isDropDowns = true;
1097
+ } else if (element.classList.contains('e-multiselect')) {
1098
+ fieldSelector = 'e-multiselect';
1099
+ isDropDowns = true;
1100
+ } else if (element.classList.contains('e-datetimepicker')) {
1101
+ fieldSelector = 'e-datetimepicker';
1102
+ } else if (element.classList.contains('e-datepicker')) {
1103
+ fieldSelector = 'e-datepicker';
1104
+ } else if (element.classList.contains('e-checkbox')) {
1105
+ fieldSelector = 'e-checkbox';
1106
+ } else if (element.classList.contains('e-numerictextbox')) {
1107
+ fieldSelector = 'e-numerictextbox';
1108
+ }
1109
+ const classSelector: string = isDropDowns ? `.${fieldSelector}:not(.e-control)` : `.${fieldSelector}`;
1110
+ const control: Element = closest(element, classSelector) || element.querySelector(`.${fieldSelector}`);
1111
+ if (control) {
1112
+ const attrEle: Element = control.querySelector('[name]');
1113
+ if (attrEle) {
1114
+ attrName = (<HTMLInputElement>attrEle).name;
1115
+ }
1116
+ }
1117
+ }
1118
+ return attrName;
1119
+ }
1120
+
1121
+ private onAllDayChange(allDayStatus: boolean): void {
1122
+ const startObj: DateTimePicker = this.getInstance(cls.EVENT_WINDOW_START_CLASS) as unknown as DateTimePicker;
1123
+ const endObj: DateTimePicker = this.getInstance(cls.EVENT_WINDOW_END_CLASS) as unknown as DateTimePicker;
1124
+ const timezoneDiv: HTMLElement = this.element.querySelector('.e-time-zone-container') as HTMLElement;
1125
+ let format: string;
1126
+ if (allDayStatus) {
1127
+ format = (isNullOrUndefined(this.parent.dateFormat)) ? this.getFormat('dateFormats') : this.parent.dateFormat;
1128
+ addClass(this.element.querySelectorAll('.e-time-icon'), cls.EVENT_WINDOW_ICON_DISABLE_CLASS);
1129
+ addClass([timezoneDiv], cls.DISABLE_CLASS);
1130
+ if (this.element.querySelector('.' + cls.EVENT_WINDOW_TIME_ZONE_DIV_CLASS)) {
1131
+ removeClass([this.element.querySelector('.' + cls.EVENT_WINDOW_TIME_ZONE_DIV_CLASS)], cls.ENABLE_CLASS);
1132
+ }
1133
+ startObj.format = endObj.format = format;
1134
+ } else {
1135
+ format = (isNullOrUndefined(this.parent.dateFormat)) ? this.getFormat('dateFormats') + ' ' +
1136
+ this.parent.activeViewOptions.timeFormat : this.parent.dateFormat + ' ' + this.parent.activeViewOptions.timeFormat;
1137
+ removeClass(this.element.querySelectorAll('.e-time-icon'), cls.EVENT_WINDOW_ICON_DISABLE_CLASS);
1138
+ removeClass([timezoneDiv], cls.DISABLE_CLASS);
1139
+ if ((this.element.querySelector('.e-checkbox-wrapper .e-time-zone') as HTMLInputElement).checked) {
1140
+ addClass([this.element.querySelector('.' + cls.EVENT_WINDOW_TIME_ZONE_DIV_CLASS)], cls.ENABLE_CLASS);
1141
+ }
1142
+ startObj.format = endObj.format = format;
1143
+ }
1144
+ if (this.cellClickAction) { this.updateDateTime(allDayStatus, startObj, endObj); }
1145
+ startObj.dataBind();
1146
+ endObj.dataBind();
1147
+ if (!isNullOrUndefined(this.recurrenceEditor)) {
1148
+ this.recurrenceEditor.updateRuleUntilDate(startObj.value);
1149
+ }
1150
+ }
1151
+
1152
+ private updateDateTime(allDayStatus: boolean, startObj: DateTimePicker, endObj: DateTimePicker): void {
1153
+ let startDate: Date; let endDate: Date;
1154
+ if (isNullOrUndefined(this.eventWindowTime.startTime) && isNullOrUndefined(this.eventWindowTime.endTime)) { return; }
1155
+ if (allDayStatus) {
1156
+ startDate = util.resetTime(new Date(this.eventWindowTime.startTime.getTime()));
1157
+ if (this.parent.activeCellsData.isAllDay) {
1158
+ const temp: number = util.addDays(new Date((<Date>this.eventWindowTime.endTime).getTime()), -1).getTime();
1159
+ endDate = (+this.eventWindowTime.startTime > temp) ? this.eventWindowTime.endTime : new Date(temp);
1160
+ } else {
1161
+ endDate = util.resetTime(new Date(this.eventWindowTime.endTime.getTime()));
1162
+ }
1163
+ } else {
1164
+ const start: Date = this.parent.activeCellsData.startTime;
1165
+ startDate = new Date(this.eventWindowTime.startTime.getTime());
1166
+ startDate.setHours(start.getHours(), start.getMinutes(), start.getSeconds());
1167
+ if (this.parent.activeCellsData.isAllDay) {
1168
+ const startHour: Date = this.parent.getStartEndTime(this.parent.workHours.start);
1169
+ startDate.setHours(startHour.getHours(), startHour.getMinutes(), startHour.getSeconds());
1170
+ endDate = new Date(startDate.getTime());
1171
+ endDate.setMilliseconds(util.MS_PER_MINUTE * this.getSlotDuration());
1172
+ } else {
1173
+ endDate = new Date(startDate.getTime());
1174
+ endDate.setMilliseconds(this.parent.activeCellsData.endTime.getTime() - this.parent.activeCellsData.startTime.getTime());
1175
+ }
1176
+ }
1177
+ this.eventWindowTime = { startTime: new Date(startDate.getTime()), endTime: new Date(endDate.getTime()) };
1178
+ startObj.value = startDate;
1179
+ endObj.value = endDate;
1180
+ startObj.dataBind();
1181
+ endObj.dataBind();
1182
+ }
1183
+
1184
+ private getFormat(formatType: string): string {
1185
+ let format: string;
1186
+ if (isNullOrUndefined(this.parent.locale) || this.parent.locale === 'en' || this.parent.locale === 'en-US') {
1187
+ format = getValue(formatType + '.short', getDefaultDateObject(this.parent.getCalendarMode()));
1188
+ } else {
1189
+ format = getValue(`main.${this.parent.locale}.dates.calendars.${this.parent.getCalendarMode()}.${formatType}.short`, cldrData);
1190
+ }
1191
+ return format;
1192
+ }
1193
+
1194
+ private onEventDetailsUpdate(eventObj: Record<string, any>): void {
1195
+ if (!this.parent.eventSettings.allowEditing) {
1196
+ return;
1197
+ }
1198
+ if (!this.parent.isAdaptive && isNullOrUndefined(this.parent.editorFooterTemplate)) {
1199
+ removeClass([this.element.querySelector('.' + cls.DELETE_EVENT_CLASS)], cls.DISABLE_CLASS);
1200
+ }
1201
+ if (isNullOrUndefined(this.parent.editorHeaderTemplate)) {
1202
+ this.element.querySelector('.' + cls.EVENT_WINDOW_TITLE_TEXT_CLASS).innerHTML = this.l10n.getConstant('editEvent');
1203
+ }
1204
+ this.element.querySelector('.' + cls.FORM_CLASS).setAttribute('data-id', eventObj[this.fields.id].toString());
1205
+ if (isNullOrUndefined(this.parent.editorTemplate)) {
1206
+ eventObj = <Record<string, any>>extend({}, eventObj, null, true);
1207
+ const timezoneObj: CheckBox = this.getInstance(cls.TIME_ZONE_CLASS + '.' + EVENT_FIELD) as unknown as CheckBox;
1208
+ let timezoneValue: boolean;
1209
+ if (eventObj[this.fields.startTimezone] || eventObj[this.fields.endTimezone]) {
1210
+ timezoneValue = true;
1211
+ this.parent.eventBase.timezoneConvert(eventObj);
1212
+ } else {
1213
+ timezoneValue = false;
1214
+ }
1215
+ eventObj.Timezone = timezoneValue;
1216
+ timezoneObj.checked = timezoneValue;
1217
+ timezoneObj.dataBind();
1218
+ }
1219
+ this.showDetails(eventObj);
1220
+ if (eventObj[this.fields.recurrenceRule] && this.recurrenceEditor) {
1221
+ this.recurrenceEditor.setRecurrenceRule(<string>eventObj[this.fields.recurrenceRule], <Date>eventObj[this.fields.startTime]);
1222
+ } else if (!this.parent.isAdaptive && this.recurrenceEditor) {
1223
+ this.recurrenceEditor.setProperties({ startDate: eventObj[this.fields.startTime] });
1224
+ this.recurrenceEditor.setRecurrenceRule('');
1225
+ }
1226
+ this.repeatStartDate = <Date>eventObj[this.fields.startTime];
1227
+ this.repeatRule = '';
1228
+ if (eventObj[this.fields.recurrenceRule]) {
1229
+ if (this.recurrenceEditor) {
1230
+ this.recurrenceEditor.setRecurrenceRule(
1231
+ <string>eventObj[this.fields.recurrenceRule], <Date>eventObj[this.fields.startTime]);
1232
+ }
1233
+ this.repeatRule = <string>eventObj[this.fields.recurrenceRule];
1234
+ }
1235
+ if (this.parent.isAdaptive && isNullOrUndefined(this.parent.editorTemplate)) {
1236
+ const element: HTMLElement = <HTMLElement>this.element.querySelector('.' + REPEAT_CONTAINER_CLASS);
1237
+ if (eventObj[this.fields.recurrenceRule]) {
1238
+ removeClass([element], HIDE_STYLE_CLASS);
1239
+ this.repeatStatus.setProperties({ checked: true });
1240
+ } else {
1241
+ addClass([element], HIDE_STYLE_CLASS);
1242
+ this.repeatStatus.setProperties({ checked: false });
1243
+ }
1244
+ this.updateRepeatLabel(this.repeatRule);
1245
+ }
1246
+ const isDisable: boolean = (this.parent.readonly || eventObj[this.fields.isReadonly]) as boolean;
1247
+ if (!this.parent.isAdaptive) {
1248
+ const saveButton: Element = this.element.querySelector('.' + cls.EVENT_WINDOW_SAVE_BUTTON_CLASS);
1249
+ const deleteButton: Element = this.element.querySelector('.' + cls.DELETE_EVENT_CLASS);
1250
+ this.disableButton(saveButton, isDisable);
1251
+ this.disableButton(deleteButton, isDisable);
1252
+ } else {
1253
+ const saveIcon: Element = this.element.querySelector('.' + cls.EVENT_WINDOW_SAVE_ICON_CLASS);
1254
+ if (saveIcon) {
1255
+ if (isDisable) {
1256
+ addClass([saveIcon], cls.ICON_DISABLE_CLASS);
1257
+ } else {
1258
+ removeClass([saveIcon], cls.ICON_DISABLE_CLASS);
1259
+ }
1260
+ }
1261
+ }
1262
+ this.dialogObject.show();
1263
+ }
1264
+
1265
+ private disableButton(element: Element, value: boolean): void {
1266
+ if (element) {
1267
+ ((element as EJ2Instance).ej2_instances[0] as Button).disabled = value;
1268
+ }
1269
+ }
1270
+
1271
+ private renderRecurrenceEditor(): RecurrenceEditor {
1272
+ return new RecurrenceEditor({
1273
+ calendarMode: this.parent.calendarMode,
1274
+ cssClass: this.parent.cssClass,
1275
+ dateFormat: this.parent.dateFormat,
1276
+ enableRtl: this.parent.enableRtl,
1277
+ firstDayOfWeek: this.parent.activeViewOptions.firstDayOfWeek,
1278
+ locale: this.parent.locale
1279
+ });
1280
+ }
1281
+
1282
+ public updateMinMaxDateToEditor(): void {
1283
+ const startDate: Element = this.element.querySelector('.e-start');
1284
+ const endDate: Element = this.element.querySelector('.e-end');
1285
+ if (startDate && endDate) {
1286
+ const startObj: DatePicker = (startDate as EJ2Instance).ej2_instances[0] as DatePicker;
1287
+ const endObj: DatePicker = (endDate as EJ2Instance).ej2_instances[0] as DatePicker;
1288
+ startObj.min = this.parent.minDate;
1289
+ startObj.max = new Date(new Date(+this.parent.maxDate).setHours(23, 59, 59));
1290
+ endObj.min = this.parent.minDate;
1291
+ endObj.max = new Date(new Date(+this.parent.maxDate).setHours(23, 59, 59));
1292
+ startObj.dataBind();
1293
+ endObj.dataBind();
1294
+ }
1295
+ if (this.recurrenceEditor) {
1296
+ const untilDate: Element = this.recurrenceEditor.element.querySelector('.e-until-date');
1297
+ if (untilDate) {
1298
+ const untilObj: DatePicker = (untilDate as EJ2Instance).ej2_instances[0] as DatePicker;
1299
+ untilObj.min = this.parent.minDate;
1300
+ untilObj.max = this.parent.maxDate;
1301
+ untilObj.dataBind();
1302
+ }
1303
+ }
1304
+ }
1305
+
1306
+ private updateRepeatLabel(repeatRule: string): void {
1307
+ if (this.parent.isAdaptive && !this.repeatDialogObject) {
1308
+ this.renderRepeatDialog();
1309
+ }
1310
+ const data: string = repeatRule ?
1311
+ (this.l10n.getConstant('repeats') + ' ' + this.recurrenceEditor.getRuleSummary(repeatRule)) : this.l10n.getConstant('repeat');
1312
+ this.repeatStatus.setProperties({ label: data });
1313
+ }
1314
+
1315
+ public dialogClose(event?: Event): void {
1316
+ if (this.isEnterKey) {
1317
+ this.isEnterKey = false;
1318
+ return;
1319
+ }
1320
+ this.dialogEvent = event;
1321
+ this.isCrudAction = false;
1322
+ this.parent.activeEventData = { event: undefined, element: undefined };
1323
+ this.parent.currentAction = null;
1324
+ this.dialogObject.hide();
1325
+ }
1326
+
1327
+ private resetForm(): void {
1328
+ this.fieldValidator.destroyToolTip();
1329
+ this.resetFormFields();
1330
+ if (!this.parent.isAdaptive && this.recurrenceEditor && !this.recurrenceEditor.isDestroyed) {
1331
+ this.recurrenceEditor.resetFields();
1332
+ }
1333
+ }
1334
+
1335
+ private timezoneChangeStyle(value: boolean): void {
1336
+ const timezoneDiv: HTMLElement = this.element.querySelector('.' + cls.EVENT_WINDOW_TIME_ZONE_DIV_CLASS) as HTMLElement;
1337
+ const localTimezoneName: string = this.parent.tzModule.getLocalTimezoneName();
1338
+ if (value) {
1339
+ addClass([timezoneDiv], cls.ENABLE_CLASS);
1340
+ const startTimezoneObj: DropDownList = this.getInstance(cls.EVENT_WINDOW_START_TZ_CLASS) as unknown as DropDownList;
1341
+ const endTimezoneObj: DropDownList = this.getInstance(cls.EVENT_WINDOW_END_TZ_CLASS) as unknown as DropDownList;
1342
+ const timezone: Record<string, any>[] = startTimezoneObj.dataSource as Record<string, any>[];
1343
+ if (!startTimezoneObj.value || !this.parent.timezone) {
1344
+ const found: boolean = timezone.some((tz: Record<string, any>) => { return tz.Value === localTimezoneName; });
1345
+ if (!found) {
1346
+ timezone.push({ Value: localTimezoneName, Text: localTimezoneName });
1347
+ startTimezoneObj.dataSource = timezone;
1348
+ endTimezoneObj.dataSource = timezone;
1349
+ startTimezoneObj.dataBind();
1350
+ endTimezoneObj.dataBind();
1351
+ }
1352
+ }
1353
+ startTimezoneObj.value = startTimezoneObj.value || this.parent.timezone || localTimezoneName;
1354
+ endTimezoneObj.value = endTimezoneObj.value || this.parent.timezone || localTimezoneName;
1355
+ startTimezoneObj.dataBind();
1356
+ endTimezoneObj.dataBind();
1357
+ } else {
1358
+ removeClass([timezoneDiv], cls.ENABLE_CLASS);
1359
+ }
1360
+ }
1361
+
1362
+ private resetFormFields(): void {
1363
+ const formElement: HTMLInputElement[] = this.getFormElements(cls.EVENT_WINDOW_DIALOG_CLASS);
1364
+ for (const currentElement of formElement) {
1365
+ const columnName: string = currentElement.name || this.getColumnName(currentElement);
1366
+ if (!isNullOrUndefined(columnName) && columnName !== '') {
1367
+ this.setDefaultValueToElement(currentElement as HTMLElement);
1368
+ }
1369
+ }
1370
+ }
1371
+
1372
+ public eventSave(event: Event, alert?: string): void {
1373
+ if (this.isEnterKey) {
1374
+ this.isEnterKey = false;
1375
+ return;
1376
+ }
1377
+ const formElement: Element = this.element.querySelector('.' + cls.FORM_CLASS);
1378
+ if (formElement && formElement.classList.contains('e-formvalidator') &&
1379
+ !((formElement as EJ2Instance).ej2_instances[0] as FormValidator).validate()) {
1380
+ return;
1381
+ }
1382
+ const dataCollection: Record<string, Record<string, any>> = this.getEventDataFromEditor();
1383
+ if (this.processEventValidation(dataCollection.tempData, alert)) {
1384
+ return;
1385
+ }
1386
+ this.eventCrudData = dataCollection.eventData;
1387
+ this.dialogEvent = event;
1388
+ this.isCrudAction = true;
1389
+ this.dialogObject.hide();
1390
+ }
1391
+
1392
+ public getEventDataFromEditor(): Record<string, Record<string, any>> {
1393
+ const eventObj: Record<string, any> =
1394
+ extend({}, this.getObjectFromFormData(cls.EVENT_WINDOW_DIALOG_CLASS)) as Record<string, any>;
1395
+ if (!eventObj.Timezone) {
1396
+ eventObj[this.fields.startTimezone] = null;
1397
+ eventObj[this.fields.endTimezone] = null;
1398
+ }
1399
+ delete eventObj.Timezone;
1400
+ delete eventObj.Repeat;
1401
+ this.setDefaultValueToObject(eventObj);
1402
+ eventObj[this.fields.recurrenceRule] = this.recurrenceEditor ? this.recurrenceEditor.getRecurrenceRule() || null : undefined;
1403
+ const tempObj: Record<string, any> = extend({}, eventObj, null, true) as Record<string, any>;
1404
+ if (eventObj[this.fields.isAllDay]) {
1405
+ eventObj[this.fields.startTime] = (isNullOrUndefined(eventObj[this.fields.startTime])) ? null
1406
+ : util.resetTime(new Date((<Date>eventObj[this.fields.startTime]).getTime()));
1407
+ eventObj[this.fields.endTime] = (isNullOrUndefined(eventObj[this.fields.endTime])) ? null
1408
+ : util.addDays(util.resetTime(new Date((<Date>eventObj[this.fields.endTime]).getTime())), 1);
1409
+ }
1410
+ return { eventData: eventObj, tempData: tempObj };
1411
+ }
1412
+
1413
+ private processEventValidation(eventObj: Record<string, any>, alert?: string): boolean {
1414
+ let alertType: string;
1415
+ if (isNullOrUndefined(this.parent.editorTemplate)) {
1416
+ if (!eventObj[this.fields.startTime] || !eventObj[this.fields.endTime]) {
1417
+ this.parent.quickPopup.openValidationError('invalidDateError');
1418
+ return true;
1419
+ }
1420
+ if (eventObj[this.fields.startTime] > eventObj[this.fields.endTime]) {
1421
+ this.parent.quickPopup.openValidationError('startEndError');
1422
+ return true;
1423
+ }
1424
+ }
1425
+ if (this.recurrenceEditor && this.recurrenceEditor.value && this.recurrenceEditor.value !== '') {
1426
+ if (this.parent.currentAction !== 'EditOccurrence') {
1427
+ alertType = this.recurrenceValidation(<Date>eventObj[this.fields.startTime], <Date>eventObj[this.fields.endTime], alert);
1428
+ }
1429
+ let isShowAlert: boolean = true;
1430
+ if (alertType === 'seriesChangeAlert' && this.parent.uiStateValues.isIgnoreOccurrence) {
1431
+ isShowAlert = false;
1432
+ }
1433
+ if (!isNullOrUndefined(alertType) && isShowAlert
1434
+ && ((!this.parent.enableRecurrenceValidation && alertType === 'wrongPattern') || this.parent.enableRecurrenceValidation)) {
1435
+ this.parent.quickPopup.openRecurrenceValidationAlert(alertType);
1436
+ return true;
1437
+ }
1438
+ }
1439
+ return false;
1440
+ }
1441
+
1442
+ private processCrudActions(eventObj: Record<string, any>): boolean {
1443
+ this.parent.uiStateValues.isBlock = false;
1444
+ const resourceData: string[] | number[] = this.getResourceData(eventObj);
1445
+ const isResourceEventExpand: boolean = (this.parent.activeViewOptions.group.resources.length > 0 ||
1446
+ this.parent.resourceCollection.length > 0) && !this.parent.activeViewOptions.group.allowGroupEdit
1447
+ && !isNullOrUndefined(resourceData);
1448
+ const eventId: string = this.getEventIdFromForm();
1449
+ if (!isNullOrUndefined(eventId)) {
1450
+ let eveId: number | string = this.parent.eventBase.getEventIDType() === 'string' ? eventId : parseInt(eventId, 10);
1451
+ let editedData: Record<string, any> = this.parent.eventsData.filter((data: Record<string, any>) =>
1452
+ data[this.fields.id] === eveId)[0];
1453
+ if (isNullOrUndefined(editedData)) {
1454
+ editedData = this.parent.blockData.filter((data: Record<string, any>) =>
1455
+ data[this.fields.id] === eveId)[0];
1456
+ }
1457
+ eventObj = extend({}, editedData, eventObj) as Record<string, any>;
1458
+ if (eventObj[this.fields.isReadonly]) {
1459
+ return false;
1460
+ }
1461
+ if (this.parent.eventBase.checkOverlap(eventObj)) {
1462
+ return true;
1463
+ }
1464
+ let currentAction: CurrentAction;
1465
+ if (!isNullOrUndefined(editedData[this.fields.recurrenceRule])) {
1466
+ currentAction = this.parent.currentAction;
1467
+ eventObj.Guid = (<Record<string, any>>this.parent.activeEventData.event).Guid;
1468
+ if (this.parent.currentAction === 'EditOccurrence') {
1469
+ if (!eventObj[this.fields.recurrenceID]) {
1470
+ eventObj[this.fields.id] = this.parent.eventBase.getEventMaxID();
1471
+ eventObj.Guid = (<Record<string, any>>this.parent.activeEventData.event).Guid;
1472
+ } else {
1473
+ eveId = eventObj[this.fields.recurrenceID] as number;
1474
+ currentAction = null;
1475
+ }
1476
+ if (this.parent.enableRecurrenceValidation && this.editOccurrenceValidation(eveId, eventObj)) {
1477
+ return true;
1478
+ }
1479
+ }
1480
+ if (this.parent.currentAction === 'EditSeries' || eventObj[this.fields.id] !== editedData[this.fields.id]) {
1481
+ eventObj[this.fields.recurrenceID] = editedData[this.fields.id];
1482
+ } else if (this.parent.currentAction === 'EditFollowingEvents') {
1483
+ eventObj[this.fields.id] = this.parent.eventBase.getEventMaxID();
1484
+ eventObj[this.fields.followingID] = editedData[this.fields.id];
1485
+ }
1486
+ }
1487
+ if (isResourceEventExpand) {
1488
+ this.resourceSaveEvent(eventObj, 'Save', currentAction);
1489
+ } else {
1490
+ this.parent.saveEvent(eventObj, currentAction);
1491
+ }
1492
+ } else {
1493
+ this.parent.currentAction = 'Add';
1494
+ if (this.parent.eventBase.checkOverlap(eventObj)) {
1495
+ return true;
1496
+ }
1497
+ if (isResourceEventExpand) {
1498
+ this.resourceSaveEvent(eventObj, this.parent.currentAction);
1499
+ } else {
1500
+ eventObj[this.fields.id] = this.parent.eventBase.getEventMaxID();
1501
+ this.parent.addEvent(eventObj);
1502
+ }
1503
+ }
1504
+ return this.parent.uiStateValues.isBlock;
1505
+ }
1506
+
1507
+ private getResourceData(eventObj: Record<string, any>): string[] | number[] {
1508
+ let resourceData: string[] | number[] = null;
1509
+ if (!isNullOrUndefined(this.parent.resourceBase) && !isNullOrUndefined(this.parent.resourceBase.resourceCollection)
1510
+ && this.parent.resourceBase.resourceCollection.length > 0) {
1511
+ const lastResourceData: ResourcesModel = this.parent.resourceBase.resourceCollection.slice(-1)[0];
1512
+ resourceData = eventObj[lastResourceData.field] as string[] | number[];
1513
+ }
1514
+ return resourceData;
1515
+ }
1516
+
1517
+ public getObjectFromFormData(className: string): Record<string, any> {
1518
+ const formElement: HTMLInputElement[] = this.getFormElements(className);
1519
+ const eventObj: Record<string, any> = {};
1520
+ for (const currentElement of formElement) {
1521
+ const columnName: string = currentElement.name || this.getColumnName(currentElement);
1522
+ if (!isNullOrUndefined(columnName) && columnName !== '') {
1523
+ eventObj[`${columnName}`] = this.getValueFromElement(currentElement as HTMLElement);
1524
+ }
1525
+ }
1526
+ return eventObj;
1527
+ }
1528
+
1529
+ public setDefaultValueToObject(eventObj: Record<string, any>): void {
1530
+ if (!isNullOrUndefined(eventObj[this.fields.subject])) {
1531
+ eventObj[this.fields.subject] = eventObj[this.fields.subject] || this.parent.eventSettings.fields.subject.default
1532
+ || this.l10n.getConstant('addTitle');
1533
+ }
1534
+ if (!isNullOrUndefined(eventObj[this.fields.location])) {
1535
+ eventObj[this.fields.location] = eventObj[this.fields.location] || this.parent.eventSettings.fields.location.default;
1536
+ }
1537
+ if (!isNullOrUndefined(eventObj[this.fields.description])) {
1538
+ eventObj[this.fields.description] = eventObj[this.fields.description] || this.parent.eventSettings.fields.description.default;
1539
+ }
1540
+ }
1541
+
1542
+ private recurrenceValidation(startDate: Date, endDate: Date, alert: string): string {
1543
+ let alertMessage: string;
1544
+ const recEditor: RecurrenceEditor = this.recurrenceEditor;
1545
+ const interval: number = (this.getInstance('e-repeat-interval.e-numerictextbox') as unknown as NumericTextBox).value;
1546
+ if (alert !== this.l10n.getConstant('ok')) {
1547
+ const activeEvent: Record<string, any> = <Record<string, any>>this.parent.activeEventData.event;
1548
+ let excludedEvents: Record<string, any>[] = [];
1549
+ if ((this.parent.currentAction === 'EditSeries' || this.parent.currentAction === 'EditFollowingEvents')
1550
+ && !isNullOrUndefined(activeEvent)) {
1551
+ const eventStartTime: string = activeEvent[this.parent.eventFields.startTime] as string;
1552
+ const seriesEvents: Record<string, any>[] = this.parent.eventBase.getSeriesEvents(this.eventData, eventStartTime);
1553
+ if (seriesEvents.length > 0) {
1554
+ excludedEvents = this.parent.eventBase.getEditedOccurrences(seriesEvents, eventStartTime);
1555
+ } else {
1556
+ const event: Record<string, any> = this.parent.eventBase.getEventById(
1557
+ activeEvent[this.parent.eventFields.id] as string);
1558
+ excludedEvents = this.parent.eventBase.getEditedOccurrences([event], eventStartTime);
1559
+ }
1560
+ if (this.parent.currentAction === 'EditSeries'
1561
+ && !isNullOrUndefined(this.eventData[this.parent.eventFields.recurrenceException])) {
1562
+ excludedEvents.push(this.eventData);
1563
+ }
1564
+ }
1565
+ if (excludedEvents.length > 0) {
1566
+ alertMessage = 'seriesChangeAlert';
1567
+ }
1568
+ if ((this.getInstance('e-end-on-left .e-ddl .e-dropdownlist') as unknown as DropDownList).value === 'until' &&
1569
+ (this.getInstance('e-end-on-date .e-datepicker') as unknown as DatePicker).value < startDate) {
1570
+ alertMessage = 'wrongPattern';
1571
+ }
1572
+ if (isNullOrUndefined(alertMessage)) {
1573
+ let types: string[] = recEditor.value.split(';')[1].split('=')[1].split(',');
1574
+ const obj: Record<string, any> = { 'SU': 0, 'MO': 1, 'TU': 2, 'WE': 3, 'TH': 4, 'FR': 5, 'SA': 6 };
1575
+ const temp: number[] = [];
1576
+ const tempDiff: number[] = [];
1577
+ let tempValue: number[];
1578
+ switch (recEditor.value.split(';')[0].split('=')[1]) {
1579
+ case 'DAILY':
1580
+ if ((((endDate.getTime() - startDate.getTime()) / (1000 * 3600)) > (interval * 24))) {
1581
+ alertMessage = 'createError';
1582
+ }
1583
+ break;
1584
+ case 'WEEKLY':
1585
+ types = recEditor.value.split(';')[1].split('=')[1].split(',');
1586
+ for (let index: number = 0; index < types.length * (interval + 1); index++) {
1587
+ temp[parseInt(index.toString(), 10)] =
1588
+ (types.length > index) ? <number>obj[types[parseInt(index.toString(), 10)]] :
1589
+ temp[index - types.length] + (7 * interval);
1590
+ }
1591
+ tempValue = temp.sort((a: number, b: number) => a - b);
1592
+ for (let index: number = 1; index < tempValue.length; index++) {
1593
+ tempDiff.push(tempValue[parseInt(index.toString(), 10)] - tempValue[index - 1]);
1594
+ }
1595
+ if ((((endDate.getTime() - startDate.getTime()) / (1000 * 3600)) >= Math.min(...tempDiff) * 24)
1596
+ || isNullOrUndefined(interval)) {
1597
+ alertMessage = 'createError';
1598
+ }
1599
+ break;
1600
+ case 'MONTHLY':
1601
+ if (endDate.getTime() >= new Date(+startDate).setMonth(startDate.getMonth() + interval)) {
1602
+ alertMessage = 'createError';
1603
+ }
1604
+ break;
1605
+ case 'YEARLY':
1606
+ if (endDate.getTime() >= new Date(+startDate).setFullYear(startDate.getFullYear() + interval)) {
1607
+ alertMessage = 'createError';
1608
+ }
1609
+ break;
1610
+ }
1611
+ }
1612
+ } else {
1613
+ if (endDate.getTime() >= new Date(+startDate).setMonth(startDate.getMonth() + interval)) {
1614
+ alertMessage = 'createError';
1615
+ }
1616
+ if (isNullOrUndefined(alertMessage)) {
1617
+ this.parent.quickPopup.quickDialog.hide();
1618
+ }
1619
+ }
1620
+ if (isNullOrUndefined(interval)) {
1621
+ alertMessage = 'createError';
1622
+ }
1623
+ return alertMessage;
1624
+ }
1625
+
1626
+ private getRecurrenceIndex(recColl: Record<string, any>[], event: Record<string, any>): number {
1627
+ let recIndex: number;
1628
+ for (let index: number = 0; index < recColl.length; index++) {
1629
+ if (event[this.fields.startTime].valueOf() === recColl[parseInt(index.toString(), 10)][this.fields.startTime].valueOf()) {
1630
+ recIndex = index;
1631
+ break;
1632
+ }
1633
+ }
1634
+ return recIndex;
1635
+ }
1636
+
1637
+ private trimAllDay(data: Record<string, any>): void {
1638
+ if (data[this.fields.isAllDay]) {
1639
+ const temp: number = util.addDays(new Date(+data[this.fields.endTime]), -1).getTime();
1640
+ data[this.fields.endTime] = (+data[this.fields.startTime] > temp) ? data[this.fields.endTime] : new Date(temp);
1641
+ }
1642
+ }
1643
+
1644
+ public editOccurrenceValidation(eventId: string | number, currentData: Record<string, any>, editData?: Record<string, any>)
1645
+ : boolean {
1646
+ if (editData === void 0) { editData = this.eventData; }
1647
+ const recurColl: Record<string, any>[] = <Record<string, any>[]>this.parent.getOccurrencesByID(eventId);
1648
+ const excludedDatas: Record<string, any>[] = this.parent.eventsData.filter((data: Record<string, any>) =>
1649
+ data[this.fields.recurrenceID] === eventId) as Record<string, any>[];
1650
+ excludedDatas.map((data: Record<string, any>) => recurColl.push(extend({}, data) as Record<string, any>));
1651
+ currentData = extend({}, currentData) as Record<string, any>;
1652
+ this.trimAllDay(currentData);
1653
+ for (const data of recurColl) {
1654
+ this.trimAllDay(data);
1655
+ }
1656
+ this.parent.eventBase.sortByTime(recurColl);
1657
+ const index: number = this.getRecurrenceIndex(recurColl, editData);
1658
+ if (isNullOrUndefined(index)) {
1659
+ return false;
1660
+ }
1661
+ const currentStartTime: Date = new Date(+currentData[this.fields.startTime]);
1662
+ const currentEndTime: Date = new Date(+currentData[this.fields.endTime]);
1663
+ let nextStartTime: Date;
1664
+ let nextEndTime: Date;
1665
+ if (index !== recurColl.length - 1) {
1666
+ nextStartTime = new Date(+recurColl[index + 1][this.fields.startTime]);
1667
+ nextEndTime = new Date(+recurColl[index + 1][this.fields.endTime]);
1668
+ }
1669
+ const lastEndTime: Date = new Date(+recurColl[recurColl.length - 1][this.fields.endTime]);
1670
+ if (index === 0) {
1671
+ if (!isNullOrUndefined(recurColl[index + 1])) {
1672
+ if (!(nextStartTime.getTime() >= currentEndTime.getTime()) &&
1673
+ (util.resetTime(lastEndTime).getTime() >=
1674
+ util.resetTime(currentStartTime).getTime()) ||
1675
+ util.resetTime(lastEndTime).getTime() < util.resetTime(currentStartTime).getTime()) {
1676
+ this.parent.quickPopup.openRecurrenceValidationAlert('occurrenceAlert');
1677
+ return true;
1678
+ } else if (!(util.resetTime(currentStartTime).getTime() <
1679
+ util.resetTime(nextStartTime).getTime())) {
1680
+ this.parent.quickPopup.openRecurrenceValidationAlert('sameDayAlert');
1681
+ return true;
1682
+ }
1683
+ }
1684
+ return false;
1685
+ }
1686
+ else {
1687
+ const previousStartTime: Date = new Date(+recurColl[index - 1][this.fields.startTime]);
1688
+ const previousEndTime: Date = new Date(+recurColl[index - 1][this.fields.endTime]);
1689
+ if (index === recurColl.length - 1) {
1690
+ if (util.resetTime(new Date(+recurColl[(recurColl.length - 1) - index][this.fields.startTime])).getTime() >
1691
+ util.resetTime(currentStartTime).getTime()) {
1692
+ this.parent.quickPopup.openRecurrenceValidationAlert('occurrenceAlert');
1693
+ return true;
1694
+ }
1695
+ else if (!((previousEndTime.getTime() <= currentStartTime.getTime()) &&
1696
+ (util.resetTime(currentStartTime).getTime() > util.resetTime(previousStartTime).getTime()))) {
1697
+ this.parent.quickPopup.openRecurrenceValidationAlert('sameDayAlert');
1698
+ return true;
1699
+ }
1700
+ }
1701
+ else if (!(((
1702
+ util.resetTime(previousStartTime).getTime() < util.resetTime(currentStartTime).getTime()) ||
1703
+ util.resetTime(new Date(+recurColl[0][this.fields.startTime])).getTime() >
1704
+ util.resetTime(currentStartTime).getTime()) &&
1705
+ ((util.resetTime(nextStartTime).getTime() > util.resetTime(currentStartTime).getTime()) ||
1706
+ (lastEndTime.getTime() < currentStartTime.getTime())))) {
1707
+ this.parent.quickPopup.openRecurrenceValidationAlert('sameDayAlert');
1708
+ return true;
1709
+ }
1710
+ else if (!(previousEndTime.getTime() <= currentStartTime.getTime() && nextStartTime.getTime() >=
1711
+ currentEndTime.getTime()) || (util.resetTime(nextEndTime).getTime() <
1712
+ util.resetTime(currentStartTime).getTime()) ||
1713
+ (util.resetTime(previousStartTime).getTime() > util.resetTime(currentEndTime).getTime()) ||
1714
+ !(util.resetTime(currentStartTime).getTime() < util.resetTime(nextStartTime).getTime())) {
1715
+ this.parent.quickPopup.openRecurrenceValidationAlert('occurrenceAlert');
1716
+ return true;
1717
+ }
1718
+ }
1719
+ return false;
1720
+ }
1721
+
1722
+ private resourceSaveEvent(eventObj: Record<string, any>, action?: CurrentAction, currentAction?: CurrentAction): void {
1723
+ const lastResourceData: ResourcesModel = this.parent.resourceBase.resourceCollection.slice(-1)[0];
1724
+ let resourceData: string[] | number[] = eventObj[lastResourceData.field] as string[] | number[];
1725
+ resourceData = (resourceData instanceof Array) ? resourceData.reverse() : [resourceData].reverse();
1726
+ const lastLevel: TdData[] = this.parent.resourceBase.lastResourceLevel;
1727
+ const eventList: Record<string, any>[] = [];
1728
+ for (let i: number = 0; i < resourceData.length; i++) {
1729
+ const events: Record<string, any> = <Record<string, any>>extend({}, eventObj, null, true);
1730
+ events[this.fields.id] = this.parent.eventBase.getEventMaxID();
1731
+ const temp: Record<string, any>[] = [];
1732
+ const addValues: CallbackFunction = () => {
1733
+ if (action === 'Save' && i === resourceData.length - 1) {
1734
+ if (temp.length > 0) {
1735
+ temp[0][this.fields.id] = eventObj[this.fields.id];
1736
+ for (let k: number = 1; k < temp.length; k++) {
1737
+ temp[parseInt(k.toString(), 10)][this.fields.id] = this.parent.eventBase.getEventMaxID(i);
1738
+ eventList.push(temp[parseInt(k.toString(), 10)]);
1739
+ this.parent.saveEvent(temp[0], currentAction);
1740
+ }
1741
+ } else {
1742
+ events[this.fields.id] = eventObj[this.fields.id];
1743
+ this.parent.saveEvent(events, currentAction);
1744
+ }
1745
+ } else {
1746
+ if (temp.length > 0) {
1747
+ for (let j: number = 0; j < temp.length; j++) {
1748
+ temp[parseInt(j.toString(), 10)][this.fields.id] = this.parent.eventBase.getEventMaxID(j);
1749
+ eventList.push(temp[parseInt(j.toString(), 10)]);
1750
+ }
1751
+ } else {
1752
+ events[this.fields.id] = this.parent.eventBase.getEventMaxID(i);
1753
+ eventList.push(events);
1754
+ }
1755
+ }
1756
+ };
1757
+ if (this.parent.activeViewOptions.group.byGroupID && (!isNullOrUndefined(lastLevel))) {
1758
+ const lastResource: Record<string, any>[] = lastResourceData.dataSource as Record<string, any>[];
1759
+ const resCol: Record<string, any>[] = this.parent.resourceCollection as Record<string, any>[];
1760
+ let index: number;
1761
+ if (resCol.length > 1) {
1762
+ index =
1763
+ util.findIndexInData(lastResource, lastResourceData.idField, resourceData[parseInt(i.toString(), 10)] as string,
1764
+ events, resCol);
1765
+ } else {
1766
+ index =
1767
+ util.findIndexInData(lastResource, lastResourceData.idField, resourceData[parseInt(i.toString(), 10)] as string);
1768
+ }
1769
+ if (index < 0) {
1770
+ return;
1771
+ }
1772
+ const groupId: Record<string, any> =
1773
+ lastResource[parseInt(index.toString(), 10)][lastResourceData.groupIDField] as Record<string, any>;
1774
+ const filter: TdData = lastLevel.filter((obj: TdData) => obj.resourceData[lastResourceData.idField] ===
1775
+ resourceData[parseInt(i.toString(), 10)]).
1776
+ filter((obj: TdData) => obj.resourceData[lastResourceData.groupIDField] === groupId)[0];
1777
+ const groupOrder: number[] | string[] = filter.groupOrder;
1778
+ for (let index: number = 0; index < this.parent.resourceBase.resourceCollection.length; index++) {
1779
+ const field: string = this.parent.resourceBase.resourceCollection[parseInt(index.toString(), 10)].field;
1780
+ events[`${field}`] = ((groupOrder[parseInt(index.toString(), 10)] as any) instanceof Array) ? groupOrder[parseInt(index.toString(), 10)][0] :
1781
+ groupOrder[parseInt(index.toString(), 10)];
1782
+ }
1783
+ addValues();
1784
+ } else {
1785
+ for (let index: number = 0; index < this.parent.resourceBase.resourceCollection.length - 1; index++) {
1786
+ const field: string = this.parent.resourceBase.resourceCollection[parseInt(index.toString(), 10)].field;
1787
+ if (events[`${field}`] instanceof Array && (events[`${field}`] as Record<string, any>[]).length > 1) {
1788
+ for (let k: number = 0; k < (events[`${field}`] as Record<string, any>[]).length; k++) {
1789
+ const event: Record<string, any> = <Record<string, any>>extend({}, events, null, true);
1790
+ event[`${field}`] = (eventObj[`${field}`] as Record<string, any>)[parseInt(k.toString(), 10)];
1791
+ event[lastResourceData.field] = resourceData[parseInt(i.toString(), 10)];
1792
+ temp.push(event);
1793
+ }
1794
+ } else {
1795
+ if (temp.length === 0) {
1796
+ events[`${field}`] = (eventObj[`${field}`] instanceof Array) ?
1797
+ (eventObj[`${field}`] as Record<string, any>)[0] : eventObj[`${field}`];
1798
+ events[lastResourceData.field] = resourceData[parseInt(i.toString(), 10)];
1799
+ } else {
1800
+ for (let l: number = 0; l < temp.length; l++) {
1801
+ temp[parseInt(l.toString(), 10)][`${field}`] = (eventObj[`${field}`] instanceof Array) ?
1802
+ (eventObj[`${field}`] as Record<string, any>)[0] : eventObj[`${field}`];
1803
+ }
1804
+ }
1805
+ }
1806
+ }
1807
+ events[lastResourceData.field] = resourceData[parseInt(i.toString(), 10)];
1808
+ addValues();
1809
+ }
1810
+ }
1811
+ if (eventList.length > 0) {
1812
+ for (const event of eventList) {
1813
+ event[this.fields.recurrenceException] = null;
1814
+ event[this.fields.recurrenceID] = null;
1815
+ }
1816
+ this.parent.addEvent(eventList);
1817
+ }
1818
+ }
1819
+
1820
+ private getEventIdFromForm(): string {
1821
+ return this.element.querySelector('.' + cls.FORM_CLASS).getAttribute('data-id');
1822
+ }
1823
+
1824
+ private getFormElements(className: string): HTMLInputElement[] {
1825
+ let elements: HTMLInputElement[] = [];
1826
+ if (className === cls.EVENT_WINDOW_DIALOG_CLASS) {
1827
+ elements = [].slice.call(this.element.querySelectorAll('.' + EVENT_FIELD));
1828
+ } else {
1829
+ elements = [].slice.call(this.parent.element.querySelectorAll('.' + className + ' .' + EVENT_FIELD));
1830
+ }
1831
+ return elements;
1832
+ }
1833
+
1834
+ private getValueFromElement(element: HTMLElement): number | string | Date | boolean | string[] | number[] {
1835
+ let value: number | string | Date | boolean | string[] | number[];
1836
+ if (element.classList.contains('e-datepicker')) {
1837
+ value = ((element as EJ2Instance).ej2_instances[0] as DatePicker).value as Date;
1838
+ } else if (element.classList.contains('e-datetimepicker')) {
1839
+ value = ((element as EJ2Instance).ej2_instances[0] as DateTimePicker).value as Date;
1840
+ } else if (element.classList.contains('e-dropdownlist')) {
1841
+ value = ((element as EJ2Instance).ej2_instances[0] as DropDownList).value as string | number;
1842
+ } else if (element.classList.contains('e-multiselect')) {
1843
+ value = ((element as EJ2Instance).ej2_instances[0] as MultiSelect).value as string[] | number[];
1844
+ } else if (element.classList.contains('e-checkbox')) {
1845
+ value = ((element as EJ2Instance).ej2_instances[0] as CheckBox).checked as boolean;
1846
+ } else if (element.classList.contains('e-numerictextbox')) {
1847
+ value = ((element as EJ2Instance).ej2_instances[0] as NumericTextBox).value as number;
1848
+ } else {
1849
+ if ((element as HTMLInputElement).type === 'checkbox') {
1850
+ value = (element as HTMLInputElement).checked as boolean;
1851
+ } else {
1852
+ value = this.parent.enableHtmlSanitizer ?
1853
+ SanitizeHtmlHelper.sanitize((element as HTMLInputElement).value as string) : (element as HTMLInputElement).value;
1854
+ }
1855
+ }
1856
+ return value;
1857
+ }
1858
+
1859
+ private setValueToElement(element: HTMLElement, value: number | string | Date | boolean | number[] | string[]): void {
1860
+ if (element.classList.contains('e-datepicker')) {
1861
+ const instance: DatePicker = (element as EJ2Instance).ej2_instances[0] as DatePicker;
1862
+ instance.value = <Date>value;
1863
+ instance.dataBind();
1864
+ } else if (element.classList.contains('e-datetimepicker')) {
1865
+ const instance: DateTimePicker = (element as EJ2Instance).ej2_instances[0] as DateTimePicker;
1866
+ if (instance.element.classList.contains(cls.EVENT_WINDOW_START_CLASS)) {
1867
+ this.eventWindowTime.startTime = new Date('' + value);
1868
+ } else {
1869
+ this.eventWindowTime.endTime = new Date('' + value);
1870
+ }
1871
+ instance.value = <Date>value;
1872
+ instance.dataBind();
1873
+ } else if (element.classList.contains('e-dropdownlist')) {
1874
+ const instance: DropDownList = (element as EJ2Instance).ej2_instances[0] as DropDownList;
1875
+ instance.value = <string>value;
1876
+ instance.dataBind();
1877
+ } else if (element.classList.contains('e-multiselect')) {
1878
+ const instance: MultiSelect = (element as EJ2Instance).ej2_instances[0] as MultiSelect;
1879
+ instance.value = [];
1880
+ instance.value = <string[]>((value instanceof Array) ? value : [value]);
1881
+ instance.dataBind();
1882
+ } else if (element.classList.contains('e-checkbox')) {
1883
+ const instance: CheckBox = (element as EJ2Instance).ej2_instances[0] as CheckBox;
1884
+ instance.checked = <boolean>value;
1885
+ instance.dataBind();
1886
+ } else if (element.classList.contains('e-numerictextbox')) {
1887
+ const instance: NumericTextBox = (element as EJ2Instance).ej2_instances[0] as NumericTextBox;
1888
+ instance.value = <number>value;
1889
+ instance.dataBind();
1890
+ } else {
1891
+ if ((element as HTMLInputElement).type !== 'checkbox') {
1892
+ (element as HTMLInputElement).value = <string>value || '';
1893
+ } else {
1894
+ (element as HTMLInputElement).checked = <boolean>value;
1895
+ }
1896
+ }
1897
+ }
1898
+
1899
+ private setDefaultValueToElement(element: HTMLElement): void {
1900
+ if (element.classList.contains('e-datepicker')) {
1901
+ const instance: DatePicker = (element as EJ2Instance).ej2_instances[0] as DatePicker;
1902
+ instance.value = this.parent.getCurrentTime();
1903
+ instance.dataBind();
1904
+ } else if (element.classList.contains('e-datetimepicker')) {
1905
+ const instance: DateTimePicker = (element as EJ2Instance).ej2_instances[0] as DateTimePicker;
1906
+ const dateValue: Date = this.parent.getCurrentTime();
1907
+ this.eventWindowTime = { startTime: dateValue, endTime: dateValue };
1908
+ instance.value = dateValue;
1909
+ instance.dataBind();
1910
+ } else if (element.classList.contains('e-dropdownlist')) {
1911
+ const instance: DropDownList = (element as EJ2Instance).ej2_instances[0] as DropDownList;
1912
+ instance.value = null;
1913
+ instance.dataBind();
1914
+ } else if (element.classList.contains('e-multiselect')) {
1915
+ const instance: MultiSelect = (element as EJ2Instance).ej2_instances[0] as MultiSelect;
1916
+ instance.value = [];
1917
+ instance.dataBind();
1918
+ } else if (element.classList.contains('e-checkbox')) {
1919
+ const instance: CheckBox = (element as EJ2Instance).ej2_instances[0] as CheckBox;
1920
+ instance.checked = false;
1921
+ instance.dataBind();
1922
+ } else if (element.classList.contains('e-numerictextbox')) {
1923
+ const instance: NumericTextBox = (element as EJ2Instance).ej2_instances[0] as NumericTextBox;
1924
+ instance.value = null;
1925
+ instance.dataBind();
1926
+ } else {
1927
+ if ((element as HTMLInputElement).type === 'checkbox') {
1928
+ (element as HTMLInputElement).checked = false;
1929
+ } else {
1930
+ (element as HTMLInputElement).value = '';
1931
+ }
1932
+ }
1933
+ }
1934
+
1935
+ private getInstance(className: string): Record<string, any> {
1936
+ const element: HTMLElement = this.element.querySelector('.' + className) as HTMLElement;
1937
+ return element ? (element as EJ2Instance).ej2_instances[0] : null;
1938
+ }
1939
+
1940
+ private eventDelete(event: Event): void {
1941
+ if (this.isEnterKey) {
1942
+ this.isEnterKey = false;
1943
+ return;
1944
+ }
1945
+ switch (this.parent.currentAction) {
1946
+ case 'EditOccurrence':
1947
+ if (!isNullOrUndefined((<Record<string, any>>this.parent.activeEventData.event)[this.parent.eventFields.recurrenceRule])) {
1948
+ this.parent.currentAction = 'DeleteOccurrence';
1949
+ } else {
1950
+ this.parent.currentAction = 'Delete';
1951
+ }
1952
+ break;
1953
+ case 'EditSeries':
1954
+ this.parent.currentAction = 'DeleteSeries';
1955
+ break;
1956
+ case 'Save':
1957
+ this.parent.currentAction = 'Delete';
1958
+ break;
1959
+ case 'EditFollowingEvents':
1960
+ if (!isNullOrUndefined((<Record<string, any>>this.parent.activeEventData.event)[this.parent.eventFields.recurrenceRule])) {
1961
+ this.parent.currentAction = 'DeleteFollowingEvents';
1962
+ }
1963
+ break;
1964
+ }
1965
+ this.dialogEvent = event;
1966
+ this.isCrudAction = false;
1967
+ this.dialogObject.hide();
1968
+ this.parent.quickPopup.openDeleteAlert();
1969
+ }
1970
+
1971
+ public getRecurrenceEditorInstance(): RecurrenceEditor {
1972
+ if (this.parent.isAdaptive && !this.repeatDialogObject) {
1973
+ this.renderRepeatDialog();
1974
+ }
1975
+ return this.recurrenceEditor;
1976
+ }
1977
+
1978
+ private destroyComponents(): void {
1979
+ const formElements: HTMLInputElement[] = this.getFormElements(cls.EVENT_WINDOW_DIALOG_CLASS);
1980
+ for (const element of formElements) {
1981
+ let instance: Record<string, any>[];
1982
+ if (element.classList.contains('e-datetimepicker')) {
1983
+ instance = ((<HTMLElement>element) as EJ2Instance).ej2_instances;
1984
+ } else if (element.classList.contains('e-datepicker')) {
1985
+ instance = ((<HTMLElement>element) as EJ2Instance).ej2_instances;
1986
+ } else if (element.classList.contains('e-checkbox')) {
1987
+ instance = ((<HTMLElement>element) as EJ2Instance).ej2_instances;
1988
+ } else if (element.classList.contains('e-dropdownlist')) {
1989
+ instance = ((<HTMLElement>element) as EJ2Instance).ej2_instances;
1990
+ } else if (element.classList.contains('e-multiselect')) {
1991
+ instance = ((<HTMLElement>element) as EJ2Instance).ej2_instances;
1992
+ } else if (element.classList.contains('e-numerictextbox')) {
1993
+ instance = ((<HTMLElement>element) as EJ2Instance).ej2_instances;
1994
+ }
1995
+ if (instance && instance[0]) {
1996
+ (instance[0] as unknown as Schedule).destroy();
1997
+ }
1998
+ }
1999
+ if (this.buttonObj) {
2000
+ this.buttonObj.destroy();
2001
+ }
2002
+ }
2003
+
2004
+ private detachComponents(): void {
2005
+ const formElements: HTMLInputElement[] = this.getFormElements(cls.EVENT_WINDOW_DIALOG_CLASS);
2006
+ for (const element of formElements) {
2007
+ detach(element);
2008
+ }
2009
+ }
2010
+
2011
+ public destroy(isIgnore?: boolean): void {
2012
+ if (this.parent && !this.parent.isDestroyed) {
2013
+ this.parent.resetTemplates(['editorTemplate', 'editorHeaderTemplate', 'editorFooterTemplate']);
2014
+ }
2015
+ this.destroyComponents();
2016
+ if (this.recurrenceEditor) {
2017
+ this.recurrenceEditor.destroy();
2018
+ detach(this.recurrenceEditor.element);
2019
+ this.recurrenceEditor = null;
2020
+ }
2021
+ if (this.fieldValidator) {
2022
+ this.fieldValidator.destroy();
2023
+ this.fieldValidator = null;
2024
+ }
2025
+ if (this.repeatDialogObject) {
2026
+ this.repeatDialogObject.destroy();
2027
+ this.repeatDialogObject = null;
2028
+ }
2029
+ this.detachComponents();
2030
+ if (this.dialogObject) {
2031
+ if (this.dialogObject.element) {
2032
+ const form: HTMLFormElement = this.dialogObject.element.querySelector('form');
2033
+ util.removeChildren(form);
2034
+ detach(form);
2035
+ EventHandler.remove(this.dialogObject.element, 'keydown', this.preventEventSave);
2036
+ }
2037
+ this.dialogObject.destroy();
2038
+ this.dialogObject = null;
2039
+ }
2040
+ if (this.element) {
2041
+ remove(this.element);
2042
+ this.element = null;
2043
+ }
2044
+ if (!isIgnore) {
2045
+ this.l10n = null;
2046
+ this.parent = null;
2047
+ this.fields = null;
2048
+ this.buttonObj = null;
2049
+ this.repeatStatus = null;
2050
+ this.eventWindowTime = null;
2051
+ this.dialogEvent = null;
2052
+ }
2053
+ }
2054
+
2055
+ }