@syncfusion/ej2-calendars 30.1.37 → 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 (53) hide show
  1. package/.eslintrc.json +263 -0
  2. package/dist/ej2-calendars.min.js +1 -1
  3. package/dist/ej2-calendars.umd.min.js +1 -1
  4. package/dist/global/ej2-calendars.min.js +1 -1
  5. package/dist/global/index.d.ts +1 -1
  6. package/dist/ts/calendar/calendar-model.d.ts +340 -0
  7. package/dist/ts/calendar/calendar.d.ts +733 -0
  8. package/dist/ts/calendar/calendar.ts +3009 -0
  9. package/dist/ts/calendar/index.d.ts +6 -0
  10. package/dist/ts/calendar/index.ts +6 -0
  11. package/dist/ts/calendar/islamic.d.ts +28 -0
  12. package/dist/ts/calendar/islamic.ts +597 -0
  13. package/dist/ts/common/index.d.ts +5 -0
  14. package/dist/ts/common/index.ts +5 -0
  15. package/dist/ts/common/maskplaceholder-model.d.ts +57 -0
  16. package/dist/ts/common/maskplaceholder.d.ts +45 -0
  17. package/dist/ts/common/maskplaceholder.ts +54 -0
  18. package/dist/ts/datepicker/datepicker-model.d.ts +364 -0
  19. package/dist/ts/datepicker/datepicker.d.ts +583 -0
  20. package/dist/ts/datepicker/datepicker.ts +2528 -0
  21. package/dist/ts/datepicker/index.d.ts +5 -0
  22. package/dist/ts/datepicker/index.ts +5 -0
  23. package/dist/ts/daterangepicker/daterangepicker-model.d.ts +496 -0
  24. package/dist/ts/daterangepicker/daterangepicker.d.ts +857 -0
  25. package/dist/ts/daterangepicker/daterangepicker.ts +5096 -0
  26. package/dist/ts/daterangepicker/index.d.ts +5 -0
  27. package/dist/ts/daterangepicker/index.ts +5 -0
  28. package/dist/ts/datetimepicker/datetimepicker-model.d.ts +479 -0
  29. package/dist/ts/datetimepicker/datetimepicker.d.ts +626 -0
  30. package/dist/ts/datetimepicker/datetimepicker.ts +2212 -0
  31. package/dist/ts/datetimepicker/index.d.ts +5 -0
  32. package/dist/ts/datetimepicker/index.ts +5 -0
  33. package/dist/ts/index.d.ts +9 -0
  34. package/dist/ts/index.ts +9 -0
  35. package/dist/ts/maskbase/index.d.ts +5 -0
  36. package/dist/ts/maskbase/index.ts +5 -0
  37. package/dist/ts/maskbase/interface.d.ts +28 -0
  38. package/dist/ts/maskbase/interface.ts +29 -0
  39. package/dist/ts/maskbase/masked-date-time.d.ts +77 -0
  40. package/dist/ts/maskbase/masked-date-time.ts +1013 -0
  41. package/dist/ts/timepicker/index.d.ts +5 -0
  42. package/dist/ts/timepicker/index.ts +5 -0
  43. package/dist/ts/timepicker/timepicker-model.d.ts +393 -0
  44. package/dist/ts/timepicker/timepicker.d.ts +681 -0
  45. package/dist/ts/timepicker/timepicker.ts +2944 -0
  46. package/package.json +59 -16
  47. package/styles/daterangepicker/_fluent2-definition.scss +2 -1
  48. package/styles/daterangepicker/fluent2.css +2 -1
  49. package/styles/datetimepicker/_fluent2-definition.scss +1 -1
  50. package/styles/datetimepicker/fluent2.css +1 -1
  51. package/styles/fluent2-lite.css +3 -2
  52. package/styles/fluent2.css +3 -2
  53. package/tslint.json +111 -0
@@ -0,0 +1,3009 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
2
+ import { Component, EventHandler, Internationalization, ModuleDeclaration } from '@syncfusion/ej2-base';
3
+ import { INotifyPropertyChanged, KeyboardEvents, L10n, SwipeEventArgs } from '@syncfusion/ej2-base';
4
+ import { NotifyPropertyChanges, KeyboardEventArgs, BaseEventArgs } from '@syncfusion/ej2-base';
5
+ import { cldrData, getDefaultDateObject, rippleEffect } from '@syncfusion/ej2-base';
6
+ import { removeClass, detach, closest, addClass, attributes } from '@syncfusion/ej2-base';
7
+ import { getValue, getUniqueID, extend, Browser } from '@syncfusion/ej2-base';
8
+ import { Property, Event, EmitType, isNullOrUndefined, throwError } from '@syncfusion/ej2-base';
9
+ import { CalendarModel, CalendarBaseModel } from './calendar-model';
10
+ import { Islamic, IslamicDateArgs } from './index';
11
+
12
+
13
+ /**
14
+ * Specifies the view of the calendar.
15
+ */
16
+ export type CalendarView = 'Month' | 'Year' | 'Decade';
17
+
18
+ export type CalendarType = 'Islamic' | 'Gregorian';
19
+
20
+ export type DayHeaderFormats = 'Short' | 'Narrow' | 'Abbreviated' | 'Wide';
21
+
22
+
23
+ /**
24
+ * Specifies the rule for defining the first week of the year.
25
+ */
26
+ export type WeekRule = 'FirstDay' | 'FirstFullWeek' | 'FirstFourDayWeek';
27
+
28
+ //class constant defination.
29
+ const OTHERMONTH: string = 'e-other-month';
30
+ const OTHERDECADE: string = 'e-other-year';
31
+ const ROOT: string = 'e-calendar';
32
+ const DEVICE: string = 'e-device';
33
+ const HEADER: string = 'e-header';
34
+ const RTL: string = 'e-rtl';
35
+ const CONTENT: string = 'e-content';
36
+ const CONTENTTABLE: string = 'e-calendar-content-table';
37
+ const YEAR: string = 'e-year';
38
+ const MONTH: string = 'e-month';
39
+ const DECADE: string = 'e-decade';
40
+ const ICON: string = 'e-icons';
41
+ const PREVICON: string = 'e-prev';
42
+ const NEXTICON: string = 'e-next';
43
+ const PREVSPAN: string = 'e-date-icon-prev';
44
+ const NEXTSPAN: string = 'e-date-icon-next ';
45
+ const ICONCONTAINER: string = 'e-icon-container';
46
+ const DISABLED: string = 'e-disabled';
47
+ const OVERLAY: string = 'e-overlay';
48
+ const WEEKEND: string = 'e-weekend';
49
+ const WEEKNUMBER: string = 'e-week-number';
50
+ const SELECTED: string = 'e-selected';
51
+ const FOCUSEDDATE: string = 'e-focused-date';
52
+ const FOCUSEDCELL: string = 'e-focused-cell';
53
+ const OTHERMONTHROW: string = 'e-month-hide';
54
+ const TODAY: string = 'e-today';
55
+ const TITLE: string = 'e-title';
56
+ const LINK: string = 'e-day';
57
+ const CELL: string = 'e-cell';
58
+ const WEEKHEADER: string = 'e-week-header';
59
+ const ZOOMIN: string = 'e-zoomin';
60
+ const FOOTER: string = 'e-footer-container';
61
+ const BTN: string = 'e-btn';
62
+ const FLAT: string = 'e-flat';
63
+ const CSS: string = 'e-css';
64
+ const PRIMARY: string = 'e-primary';
65
+ const DAYHEADERLONG: string = 'e-calendar-day-header-lg';
66
+ const dayMilliSeconds: number = 86400000;
67
+ const minutesMilliSeconds: number = 60000;
68
+
69
+ /**
70
+ *
71
+ * @private
72
+ */
73
+ @NotifyPropertyChanges
74
+ export class CalendarBase extends Component<HTMLElement> implements INotifyPropertyChanged {
75
+ protected headerElement: HTMLElement;
76
+ protected contentElement: HTMLElement;
77
+ private calendarEleCopy: HTMLElement;
78
+ protected table: HTMLElement;
79
+ protected tableHeadElement: HTMLElement;
80
+ protected tableBodyElement: Element;
81
+ protected nextIcon: HTMLElement;
82
+ protected previousIcon: HTMLElement;
83
+ protected headerTitleElement: HTMLElement;
84
+ protected todayElement: HTMLElement;
85
+ protected footer: HTMLElement;
86
+ protected keyboardModule: KeyboardEvents;
87
+ protected globalize: Internationalization;
88
+ public islamicModule: Islamic;
89
+ protected currentDate: Date;
90
+ protected navigatedArgs: NavigatedEventArgs;
91
+ protected renderDayCellArgs: RenderDayCellEventArgs;
92
+ protected effect: string = '';
93
+ protected previousDate: Date;
94
+ protected previousValues: number;
95
+ protected navigateHandler: Function;
96
+ protected navigatePreviousHandler: Function;
97
+ protected navigateNextHandler: Function;
98
+ protected l10: L10n;
99
+ protected todayDisabled: boolean;
100
+ protected nextIconClicked: boolean;
101
+ protected previousIconClicked: boolean;
102
+ protected tabIndex: string;
103
+ protected todayDate: Date;
104
+ protected islamicPreviousHeader: string;
105
+ protected calendarElement: HTMLElement;
106
+ protected isPopupClicked: boolean = false;
107
+ protected isDateSelected: boolean = true;
108
+ private serverModuleName: string;
109
+ protected timezone: string;
110
+ protected defaultKeyConfigs: { [key: string]: string };
111
+ protected previousDateTime: Date;
112
+ protected isTodayClicked: boolean = false;
113
+ protected todayButtonEvent: MouseEvent | KeyboardEvent;
114
+ protected preventChange: boolean = false;
115
+ protected previousDates: boolean = false;
116
+ /**
117
+ * Gets or sets the minimum date that can be selected in the Calendar.
118
+ *
119
+ * @default new Date(1900, 00, 01)
120
+ * @deprecated
121
+ */
122
+ @Property(new Date(1900, 0, 1))
123
+ public min: Date;
124
+ /**
125
+ * Specifies the component to be disabled or not.
126
+ *
127
+ * @default true
128
+ */
129
+ @Property(true)
130
+ public enabled: boolean;
131
+ /**
132
+ * Specifies the root CSS class of the Calendar that allows to
133
+ * customize the appearance by overriding the styles.
134
+ *
135
+ * @default null
136
+ */
137
+ @Property(null)
138
+ public cssClass: string;
139
+ /**
140
+ * Gets or sets the maximum date that can be selected in the Calendar.
141
+ *
142
+ * @default new Date(2099, 11, 31)
143
+ * @deprecated
144
+ */
145
+ @Property(new Date(2099, 11, 31))
146
+ public max: Date;
147
+ /**
148
+ * Gets or sets the Calendar's first day of the week. By default, the first day of the week will be based on the current culture.
149
+ *
150
+ * @default 0
151
+ * @aspType int
152
+ * @deprecated
153
+ * > For more details about firstDayOfWeek refer to
154
+ * [`First day of week`](../../calendar/how-to/first-day-of-week#change-the-first-day-of-the-week) documentation.
155
+ */
156
+ @Property(null)
157
+ public firstDayOfWeek: number;
158
+ /**
159
+ * Gets or sets the Calendar's Type like gregorian or islamic.
160
+ *
161
+ * @default Gregorian
162
+ * @deprecated
163
+ */
164
+ @Property('Gregorian')
165
+ public calendarMode: CalendarType;
166
+ /**
167
+ * Specifies the initial view of the Calendar when it is opened.
168
+ * With the help of this property, initial view can be changed to year or decade view.
169
+ *
170
+ * @default Month
171
+ * @deprecated
172
+ *
173
+ * <table>
174
+ * <tr>
175
+ * <td colSpan=1 rowSpan=1>
176
+ * View<br/></td><td colSpan=1 rowSpan=1>
177
+ * Description<br/></td></tr>
178
+ * <tr>
179
+ * <td colSpan=1 rowSpan=1>
180
+ * Month<br/></td><td colSpan=1 rowSpan=1>
181
+ * Calendar view shows the days of the month.<br/></td></tr>
182
+ * <tr>
183
+ * <td colSpan=1 rowSpan=1>
184
+ * Year<br/></td><td colSpan=1 rowSpan=1>
185
+ * Calendar view shows the months of the year.<br/></td></tr>
186
+ * <tr>
187
+ * <td colSpan=1 rowSpan=1>
188
+ * Decade<br/></td><td colSpan=1 rowSpan=1>
189
+ * Calendar view shows the years of the decade.<br/></td></tr>
190
+ * </table>
191
+ *
192
+ * > For more details about start refer to
193
+ * [`calendarView`](../../calendar/calendar-views#view-restriction)documentation.
194
+ */
195
+ @Property('Month')
196
+ public start: CalendarView;
197
+ /**
198
+ * Sets the maximum level of view such as month, year, and decade in the Calendar.
199
+ * Depth view should be smaller than the start view to restrict its view navigation.
200
+ *
201
+ * @default Month
202
+ * @deprecated
203
+ *
204
+ * <table>
205
+ * <tr>
206
+ * <td colSpan=1 rowSpan=1>
207
+ * view<br/></td><td colSpan=1 rowSpan=1>
208
+ * Description<br/></td></tr>
209
+ * <tr>
210
+ * <td colSpan=1 rowSpan=1>
211
+ * Month<br/></td><td colSpan=1 rowSpan=1>
212
+ * Calendar view shows up to the days of the month.<br/></td></tr>
213
+ * <tr>
214
+ * <td colSpan=1 rowSpan=1>
215
+ * Year<br/></td><td colSpan=1 rowSpan=1>
216
+ * Calendar view shows up to the months of the year.<br/></td></tr>
217
+ * <tr>
218
+ * <td colSpan=1 rowSpan=1>
219
+ * Decade<br/></td><td colSpan=1 rowSpan=1>
220
+ * Calendar view shows up to the years of the decade.<br/></td></tr>
221
+ * </table>
222
+ *
223
+ * > For more details about depth refer to
224
+ * [`calendarView`](../../calendar/calendar-views#view-restriction)documentation.
225
+ */
226
+ @Property('Month')
227
+ public depth: CalendarView;
228
+ /**
229
+ * Determines whether the week number of the year is to be displayed in the calendar or not.
230
+ *
231
+ * @default false
232
+ * @deprecated
233
+ * > For more details about weekNumber refer to
234
+ * [`Calendar with week number`](../../calendar/how-to/render-the-calendar-with-week-numbers)documentation.
235
+ */
236
+ @Property(false)
237
+ public weekNumber: boolean;
238
+ /**
239
+ * Specifies the rule for defining the first week of the year.
240
+ *
241
+ * @default FirstDay
242
+ */
243
+ @Property('FirstDay')
244
+ public weekRule: WeekRule;
245
+ /**
246
+      * Specifies whether the today button is to be displayed or not.
247
+ *
248
+      * @default true
249
+ * @deprecated
250
+      */
251
+ @Property(true)
252
+ public showTodayButton: boolean;
253
+ /**
254
+ * Specifies the format of the day that to be displayed in header. By default, the format is ‘short’.
255
+ * Possible formats are:
256
+ * * `Short` - Sets the short format of day name (like Su ) in day header.
257
+ * * `Narrow` - Sets the single character of day name (like S ) in day header.
258
+ * * `Abbreviated` - Sets the min format of day name (like Sun ) in day header.
259
+ * * `Wide` - Sets the long format of day name (like Sunday ) in day header.
260
+ *
261
+ * @default Short
262
+ * @deprecated
263
+ */
264
+ @Property('Short')
265
+ public dayHeaderFormat: DayHeaderFormats;
266
+ /**
267
+      * Enable or disable persisting component's state between page reloads. If enabled, following list of states will be persisted.
268
+ * 1. value
269
+ *
270
+      * @default false
271
+ * @deprecated
272
+      */
273
+ @Property(false)
274
+ public enablePersistence: boolean;
275
+ /**    
276
+ * Customizes the key actions in Calendar.
277
+ * For example, when using German keyboard, the key actions can be customized using these shortcuts.
278
+ *
279
+ * <table>
280
+ * <tr>
281
+ * <td colSpan=1 rowSpan=1>
282
+ * Key action<br/></td><td colSpan=1 rowSpan=1>
283
+ * Key<br/></td></tr>
284
+ * <tr>
285
+ * <td colSpan=1 rowSpan=1>
286
+ * controlUp<br/></td><td colSpan=1 rowSpan=1>
287
+ * ctrl+38<br/></td></tr>
288
+ * <tr>
289
+ * <td colSpan=1 rowSpan=1>
290
+ * controlDown<br/></td><td colSpan=1 rowSpan=1>
291
+ * ctrl+40<br/></td></tr>
292
+ * <tr>
293
+ * <td colSpan=1 rowSpan=1>
294
+ * select<br/></td><td colSpan=1 rowSpan=1>
295
+ * enter<br/></td></tr>
296
+ * <tr>
297
+ * <td colSpan=1 rowSpan=1>
298
+ * home<br/></td><td colSpan=1 rowSpan=1>
299
+ * home<br/></td></tr>
300
+ * <tr>
301
+ * <td colSpan=1 rowSpan=1>
302
+ * end<br/></td><td colSpan=1 rowSpan=1>
303
+ * end<br/></td></tr>
304
+ * <tr>
305
+ * <td colSpan=1 rowSpan=1>
306
+ * pageUp<br/></td><td colSpan=1 rowSpan=1>
307
+ * pageup<br/></td></tr>
308
+ * <tr>
309
+ * <td colSpan=1 rowSpan=1>
310
+ * pageDown<br/></td><td colSpan=1 rowSpan=1>
311
+ * pagedown<br/></td></tr>
312
+ * <tr>
313
+ * <td colSpan=1 rowSpan=1>
314
+ * shiftPageUp<br/></td><td colSpan=1 rowSpan=1>
315
+ * shift+pageup<br/></td></tr>
316
+ * <tr>
317
+ * <td colSpan=1 rowSpan=1>
318
+ * shiftPageDown<br/></td><td colSpan=1 rowSpan=1>
319
+ * shift+pagedown<br/></td></tr>
320
+ * <tr>
321
+ * <td colSpan=1 rowSpan=1>
322
+ * controlHome<br/></td><td colSpan=1 rowSpan=1>
323
+ * ctrl+home<br/></td></tr>
324
+ * <tr>
325
+ * <td colSpan=1 rowSpan=1>
326
+ * controlEnd<br/></td><td colSpan=1 rowSpan=1>
327
+ * ctrl+end<br/></td></tr>
328
+ * <tr>
329
+ * <td colSpan=1 rowSpan=1>
330
+ * altUpArrow<br/></td><td colSpan=1 rowSpan=1>
331
+ * alt+uparrow<br/></td></tr>
332
+ * <tr>
333
+ * <td colSpan=1 rowSpan=1>
334
+ * spacebar<br/></td><td colSpan=1 rowSpan=1>
335
+ * space<br/></td></tr>
336
+ * <tr>
337
+ * <td colSpan=1 rowSpan=1>
338
+ * altRightArrow<br/></td><td colSpan=1 rowSpan=1>
339
+ * alt+rightarrow<br/></td></tr>
340
+ * <tr>
341
+ * <td colSpan=1 rowSpan=1>
342
+ * altLeftArrow<br/></td><td colSpan=1 rowSpan=1>
343
+ * alt+leftarrow<br/></td></tr>
344
+ * <tr>
345
+ * <td colSpan=1 rowSpan=1>
346
+ * moveDown<br/></td><td colSpan=1 rowSpan=1>
347
+ * downarrow<br/></td></tr>
348
+ * <tr>
349
+ * <td colSpan=1 rowSpan=1>
350
+ * moveUp<br/></td><td colSpan=1 rowSpan=1>
351
+ * uparrow<br/></td></tr>
352
+ * <tr>
353
+ * <td colSpan=1 rowSpan=1>
354
+ * moveLeft<br/></td><td colSpan=1 rowSpan=1>
355
+ * leftarrow<br/></td></tr>
356
+ * <tr>
357
+ * <td colSpan=1 rowSpan=1>
358
+ * moveRight<br/></td><td colSpan=1 rowSpan=1>
359
+ * rightarrow<br/></td></tr>
360
+ * </table>
361
+ *
362
+ * {% codeBlock src='calendar/keyConfigs/index.md' %}{% endcodeBlock %}
363
+ *
364
+ * @default null
365
+ * @deprecated
366
+ */
367
+ @Property(null)
368
+ public keyConfigs: { [key: string]: string };
369
+ /**
370
+ * By default, the date value will be processed based on system time zone.
371
+ * If you want to process the initial date value using server time zone
372
+ * then specify the time zone value to `serverTimezoneOffset` property.
373
+ *
374
+ * @default null
375
+ * @deprecated
376
+ */
377
+ @Property(null)
378
+ public serverTimezoneOffset: number;
379
+ /**
380
+ * Triggers when Calendar is created.
381
+ *
382
+ * @event created
383
+ */
384
+ @Event()
385
+ public created: EmitType<Object>;
386
+ /**
387
+      * Triggers when Calendar is destroyed.
388
+ *
389
+      * @event destroyed
390
+      */
391
+ @Event()
392
+ public destroyed: EmitType<Object>;
393
+
394
+ /**
395
+ * Triggers when the Calendar is navigated to another level or within the same level of view.
396
+ *
397
+ * @event navigated
398
+ */
399
+ @Event()
400
+ public navigated: EmitType<NavigatedEventArgs>;
401
+ /**
402
+ * Triggers when each day cell of the Calendar is rendered.
403
+ *
404
+ * @event renderDayCell
405
+ */
406
+ @Event()
407
+ public renderDayCell: EmitType<RenderDayCellEventArgs>;
408
+ /**
409
+ * Initialized new instance of Calendar Class.
410
+ * Constructor for creating the widget
411
+ *
412
+ * @param {CalendarBaseModel} options - Specifies the CalendarBase model.
413
+ * @param {string | HTMLElement} element - Specifies the element to render as component.
414
+ * @private
415
+ */
416
+ public constructor(options?: CalendarBaseModel, element?: string | HTMLElement) {
417
+ super(options, element);
418
+ }
419
+ /**
420
+ * To Initialize the control rendering.
421
+ *
422
+ * @returns {void}
423
+ * @private
424
+ */
425
+ protected render(): void {
426
+ this.rangeValidation(this.min, this.max);
427
+ this.calendarEleCopy = <HTMLElement>this.element.cloneNode(true);
428
+ if (this.calendarMode === 'Islamic') {
429
+ if (+(this.min.setSeconds(0)) === +new Date(1900, 0, 1, 0, 0, 0)) {
430
+ this.min = new Date(1941, 12, 18);
431
+ }
432
+ if (+this.max === +new Date(2099, 11, 31)) {
433
+ this.max = new Date(2068, 2, 4);
434
+ }
435
+ }
436
+ this.globalize = new Internationalization(this.locale);
437
+ if (isNullOrUndefined(this.firstDayOfWeek) || this.firstDayOfWeek > 6 || this.firstDayOfWeek < 0) {
438
+ this.setProperties({ firstDayOfWeek: this.globalize.getFirstDayOfWeek() }, true);
439
+ }
440
+ this.todayDisabled = false;
441
+ this.todayDate = new Date(new Date().setHours(0, 0, 0, 0));
442
+ if (this.getModuleName() === 'calendar') {
443
+ this.element.classList.add(ROOT);
444
+ if (this.enableRtl) {
445
+ this.element.classList.add(RTL);
446
+ }
447
+ if (Browser.isDevice) {
448
+ this.element.classList.add(DEVICE);
449
+ }
450
+ attributes(this.element, <{ [key: string]: string }>{
451
+ 'data-role': 'calendar'
452
+ });
453
+ this.tabIndex = this.element.hasAttribute('tabindex') ? this.element.getAttribute('tabindex') : '0';
454
+ this.element.setAttribute('tabindex', this.tabIndex);
455
+ } else {
456
+ this.calendarElement = this.createElement('div');
457
+ this.calendarElement.classList.add(ROOT);
458
+ if (this.enableRtl) {
459
+ this.calendarElement.classList.add(RTL);
460
+ }
461
+ if (Browser.isDevice) {
462
+ this.calendarElement.classList.add(DEVICE);
463
+ }
464
+ attributes(this.calendarElement, <{ [key: string]: string }>{
465
+ 'data-role': 'calendar'
466
+ });
467
+ }
468
+ if (!isNullOrUndefined(closest(this.element, 'fieldset') as HTMLFieldSetElement) && (closest(this.element, 'fieldset') as HTMLFieldSetElement).disabled) {
469
+ this.enabled = false;
470
+ }
471
+ this.createHeader();
472
+ this.createContent();
473
+ this.wireEvents();
474
+ }
475
+
476
+ protected rangeValidation(min: Date, max: Date): void {
477
+ if (isNullOrUndefined(min)) {
478
+ this.setProperties({ min: new Date(1900, 0, 1) }, true);
479
+ }
480
+ if (isNullOrUndefined(max)) {
481
+ this.setProperties({ max: new Date(2099, 11, 31) }, true);
482
+ }
483
+ }
484
+
485
+ protected getDefaultKeyConfig(): { [key: string]: string } {
486
+ this.defaultKeyConfigs = {
487
+ controlUp: 'ctrl+38',
488
+ controlDown: 'ctrl+40',
489
+ moveDown: 'downarrow',
490
+ moveUp: 'uparrow',
491
+ moveLeft: 'leftarrow',
492
+ moveRight: 'rightarrow',
493
+ select: 'enter',
494
+ home: 'home',
495
+ end: 'end',
496
+ pageUp: 'pageup',
497
+ pageDown: 'pagedown',
498
+ shiftPageUp: 'shift+pageup',
499
+ shiftPageDown: 'shift+pagedown',
500
+ controlHome: 'ctrl+home',
501
+ controlEnd: 'ctrl+end',
502
+ altUpArrow: 'alt+uparrow',
503
+ spacebar: 'space',
504
+ altRightArrow: 'alt+rightarrow',
505
+ altLeftArrow: 'alt+leftarrow'
506
+ };
507
+ return this.defaultKeyConfigs;
508
+ }
509
+
510
+ protected validateDate(value?: Date): void {
511
+ this.setProperties({ min: this.checkDateValue(new Date(this.checkValue(this.min))) }, true);
512
+ this.setProperties({ max: this.checkDateValue(new Date(this.checkValue(this.max))) }, true);
513
+ this.currentDate = this.currentDate ? this.currentDate : new Date(new Date().setHours(0, 0, 0, 0));
514
+ if (!isNullOrUndefined(value) && this.min <= this.max && value >= this.min && value <= this.max) {
515
+ this.currentDate = new Date(this.checkValue(value));
516
+ }
517
+ }
518
+
519
+ protected setOverlayIndex(popupWrapper: HTMLElement, popupElement: HTMLElement, modal: HTMLElement, isDevice: boolean): void {
520
+ if (isDevice && !isNullOrUndefined(popupElement) && !isNullOrUndefined(modal) && !isNullOrUndefined(popupWrapper)) {
521
+ const index: number = parseInt(popupElement.style.zIndex, 10) ? parseInt(popupElement.style.zIndex, 10) : 1000;
522
+ modal.style.zIndex = (index - 1).toString();
523
+ popupWrapper.style.zIndex = index.toString();
524
+ }
525
+ }
526
+
527
+ protected minMaxUpdate(value?: Date): void {
528
+ if (!(+this.min <= +this.max)) {
529
+ this.setProperties({ min: this.min }, true);
530
+ addClass([this.element], OVERLAY);
531
+ } else {
532
+ removeClass([this.element], OVERLAY);
533
+ }
534
+ this.min = isNullOrUndefined(this.min) || !(+this.min) ? this.min = new Date(1900, 0, 1) : this.min;
535
+ this.max = isNullOrUndefined(this.max) || !(+this.max) ? this.max = new Date(2099, 11, 31) : this.max;
536
+ if (+this.min <= +this.max && value && +value <= +this.max && +value >= +this.min) {
537
+ this.currentDate = new Date(this.checkValue(value));
538
+ } else {
539
+ if (+this.min <= +this.max && !value && +this.currentDate > +this.max) {
540
+ this.currentDate = new Date(this.checkValue(this.max));
541
+ } else {
542
+ if (+this.currentDate < +this.min) {
543
+ this.currentDate = new Date(this.checkValue(this.min));
544
+ }
545
+ }
546
+ }
547
+ }
548
+
549
+
550
+
551
+ protected createHeader(): void {
552
+ const ariaPrevAttrs: Object = {
553
+ 'aria-disabled': 'false',
554
+ 'aria-label': 'previous month'
555
+ };
556
+ const ariaNextAttrs: Object = {
557
+ 'aria-disabled': 'false',
558
+ 'aria-label': 'next month'
559
+
560
+ };
561
+ const ariaTitleAttrs: Object = {
562
+ 'aria-atomic': 'true', 'aria-live': 'assertive'
563
+ };
564
+ const tabIndexAttr: Object = {'tabindex': '0'};
565
+ this.headerElement = this.createElement('div', { className: HEADER });
566
+ const iconContainer: HTMLElement = this.createElement('div', { className: ICONCONTAINER });
567
+ this.previousIcon = this.createElement('button', { className: '' + PREVICON, attrs: { type: 'button' } });
568
+ rippleEffect(this.previousIcon, {
569
+ duration: 400,
570
+ selector: '.e-prev',
571
+ isCenterRipple: true
572
+ });
573
+ attributes(this.previousIcon, <{ [key: string]: string }>ariaPrevAttrs);
574
+ attributes(this.previousIcon, <{ [key: string]: string }>tabIndexAttr);
575
+ this.nextIcon = this.createElement('button', { className: '' + NEXTICON, attrs: { type: 'button' } });
576
+ rippleEffect(this.nextIcon, {
577
+ selector: '.e-next',
578
+ duration: 400,
579
+ isCenterRipple: true
580
+ });
581
+ if (this.getModuleName() === 'daterangepicker') {
582
+ attributes(this.previousIcon, {tabIndex: '-1'});
583
+ attributes(this.nextIcon, {tabIndex: '-1'});
584
+ }
585
+ attributes(this.nextIcon, <{ [key: string]: string }>ariaNextAttrs);
586
+ attributes(this.nextIcon, <{ [key: string]: string }>tabIndexAttr);
587
+ this.headerTitleElement = this.createElement('div', { className: '' + LINK + ' ' + TITLE });
588
+ attributes(this.headerTitleElement, <{ [key: string]: string }>ariaTitleAttrs);
589
+ attributes(this.headerTitleElement, <{ [key: string]: string }>tabIndexAttr);
590
+ this.headerElement.appendChild(this.headerTitleElement);
591
+ this.previousIcon.appendChild(this.createElement('span', { className: '' + PREVSPAN + ' ' + ICON }));
592
+ this.nextIcon.appendChild(this.createElement('span', { className: '' + NEXTSPAN + ' ' + ICON }));
593
+ iconContainer.appendChild(this.previousIcon);
594
+ iconContainer.appendChild(this.nextIcon);
595
+ this.headerElement.appendChild(iconContainer);
596
+ if (this.getModuleName() === 'calendar') {
597
+ this.element.appendChild(this.headerElement);
598
+ } else {
599
+ this.calendarElement.appendChild(this.headerElement);
600
+ }
601
+ this.adjustLongHeaderSize();
602
+ }
603
+ protected createContent(): void {
604
+ this.contentElement = this.createElement('div', { className: CONTENT });
605
+ this.table = this.createElement('table', { attrs: { 'class': CONTENTTABLE, 'tabIndex': '0', 'role': 'grid', 'aria-activedescendant': '', 'aria-labelledby': this.element.id } });
606
+ if (this.getModuleName() === 'calendar') {
607
+ this.element.appendChild(this.contentElement);
608
+ } else {
609
+ this.calendarElement.appendChild(this.contentElement);
610
+ }
611
+
612
+ this.contentElement.appendChild(this.table);
613
+ this.createContentHeader();
614
+ this.createContentBody();
615
+ if (this.showTodayButton) {
616
+ this.createContentFooter();
617
+ }
618
+ if (this.getModuleName() !== 'daterangepicker') {
619
+ EventHandler.add(this.table, 'focus', this.addContentFocus, this);
620
+ EventHandler.add(this.table, 'blur', this.removeContentFocus, this);
621
+ }
622
+ }
623
+ private addContentFocus(args: any): void {
624
+ const focusedDate: Element = this.tableBodyElement.querySelector('tr td.e-focused-date');
625
+ const selectedDate: Element = this.tableBodyElement.querySelector('tr td.e-selected');
626
+ if (!isNullOrUndefined(selectedDate)) {
627
+ selectedDate.classList.add(FOCUSEDCELL);
628
+ }
629
+ else if (!isNullOrUndefined(focusedDate)) {
630
+ focusedDate.classList.add(FOCUSEDCELL);
631
+ }
632
+ }
633
+ private removeContentFocus(args: any): void {
634
+ const focusedDate: Element = !isNullOrUndefined(this.tableBodyElement) ? this.tableBodyElement.querySelector('tr td.e-focused-date') : null;
635
+ const selectedDate: Element = !isNullOrUndefined(this.tableBodyElement) ? this.tableBodyElement.querySelector('tr td.e-selected') : null;
636
+ if (!isNullOrUndefined(selectedDate)) {
637
+ selectedDate.classList.remove(FOCUSEDCELL);
638
+ }
639
+ else if (!isNullOrUndefined(focusedDate)) {
640
+ focusedDate.classList.remove(FOCUSEDCELL);
641
+ }
642
+ }
643
+ protected getCultureValues(): string[] {
644
+ const culShortNames: string[] = [];
645
+ let cldrObj: string[];
646
+ const dayFormat: string = !isNullOrUndefined(this.dayHeaderFormat) ? 'days.stand-alone.' + this.dayHeaderFormat.toLowerCase() : null;
647
+ if ((this.locale === 'en' || this.locale === 'en-US') && !isNullOrUndefined(dayFormat)) {
648
+ cldrObj = <string[]>(getValue(dayFormat, getDefaultDateObject()));
649
+ } else {
650
+ cldrObj = <string[]>(this.getCultureObjects(cldrData, '' + this.locale));
651
+ }
652
+ if (!isNullOrUndefined(cldrObj)) {
653
+ for (const obj of Object.keys(cldrObj)) {
654
+ culShortNames.push(getValue(obj, cldrObj));
655
+ }
656
+ }
657
+ return culShortNames;
658
+ }
659
+ protected toCapitalize(text: string): string {
660
+ return !isNullOrUndefined(text) && text.length ? text[0].toUpperCase() + text.slice(1) : text;
661
+ }
662
+ protected createContentHeader(): void {
663
+ if (this.getModuleName() === 'calendar') {
664
+ if (!isNullOrUndefined(this.element.querySelectorAll('.e-content .e-week-header')[0])) {
665
+ detach(this.element.querySelectorAll('.e-content .e-week-header')[0]);
666
+ }
667
+ } else {
668
+ if (!isNullOrUndefined(this.calendarElement.querySelectorAll('.e-content .e-week-header')[0])) {
669
+ detach(this.calendarElement.querySelectorAll('.e-content .e-week-header')[0]);
670
+ }
671
+ }
672
+ const daysCount: number = 6;
673
+ let html: string = '';
674
+ if (this.firstDayOfWeek > 6 || this.firstDayOfWeek < 0) {
675
+ this.setProperties({ firstDayOfWeek: 0 }, true);
676
+ }
677
+ this.tableHeadElement = this.createElement('thead', { className: WEEKHEADER });
678
+ if (this.weekNumber) {
679
+ html += '<th class="e-week-number" aria-hidden="true"></th>';
680
+ if (this.getModuleName() === 'calendar') {
681
+ addClass([this.element], '' + WEEKNUMBER);
682
+ } else {
683
+ addClass([this.calendarElement], '' + WEEKNUMBER);
684
+ }
685
+ }
686
+ const shortNames: string[] = this.getCultureValues().length > 0 &&
687
+ this.getCultureValues() ? this.shiftArray(((this.getCultureValues().length > 0 &&
688
+ this.getCultureValues())), this.firstDayOfWeek) : null;
689
+ if (!isNullOrUndefined(shortNames)) {
690
+ for (let days: number = 0; days <= daysCount; days++) {
691
+ html += '<th class="">' + this.toCapitalize(shortNames[days as number]) + '</th>';
692
+ }
693
+ }
694
+ html = '<tr>' + html + '</tr>';
695
+ this.tableHeadElement.innerHTML = html;
696
+ this.table.appendChild(this.tableHeadElement);
697
+ }
698
+ protected createContentBody(): void {
699
+ if (this.getModuleName() === 'calendar') {
700
+ if (!isNullOrUndefined(this.element.querySelectorAll('.e-content tbody')[0])) {
701
+ detach(this.element.querySelectorAll('.e-content tbody')[0]);
702
+ }
703
+ } else {
704
+ if (!isNullOrUndefined(this.calendarElement.querySelectorAll('.e-content tbody')[0])) {
705
+ detach(this.calendarElement.querySelectorAll('.e-content tbody')[0]);
706
+ }
707
+ }
708
+ switch (this.start) {
709
+ case 'Year':
710
+ this.renderYears();
711
+ break;
712
+ case 'Decade':
713
+ this.renderDecades();
714
+ break;
715
+ default:
716
+ this.renderMonths();
717
+ }
718
+ }
719
+ protected updateFooter(): void {
720
+ this.todayElement.textContent = this.l10.getConstant('today');
721
+ this.todayElement.setAttribute('aria-label', this.l10.getConstant('today'));
722
+ this.todayElement.setAttribute('tabindex', '0');
723
+ }
724
+ protected createContentFooter(): void {
725
+ if (this.showTodayButton) {
726
+ const minimum: Date = new Date(+this.min);
727
+ const maximum: Date = new Date(+this.max);
728
+ const l10nLocale: object = { today: 'Today' };
729
+ this.globalize = new Internationalization(this.locale);
730
+ this.l10 = new L10n(this.getModuleName(), l10nLocale, this.locale);
731
+ this.todayElement = this.createElement('button', { attrs: { role: 'button' } });
732
+ rippleEffect(this.todayElement);
733
+ this.updateFooter();
734
+ addClass([this.todayElement], [BTN, TODAY, FLAT, PRIMARY, CSS]);
735
+ if ((!(+new Date(minimum.setHours(0, 0, 0, 0)) <= +this.todayDate &&
736
+ +this.todayDate <= +new Date(maximum.setHours(0, 0, 0, 0)))) || (this.todayDisabled)) {
737
+ addClass([this.todayElement], DISABLED);
738
+ }
739
+ this.footer = this.createElement('div', { className: FOOTER });
740
+ this.footer.appendChild(this.todayElement);
741
+ if (this.getModuleName() === 'calendar') {
742
+ this.element.appendChild(this.footer);
743
+ }
744
+ if (this.getModuleName() === 'datepicker') {
745
+ this.calendarElement.appendChild(this.footer);
746
+ }
747
+ if (this.getModuleName() === 'datetimepicker') {
748
+ this.calendarElement.appendChild(this.footer);
749
+ }
750
+ if (!this.todayElement.classList.contains(DISABLED)) {
751
+ EventHandler.add(this.todayElement, 'click', this.todayButtonClick, this);
752
+ }
753
+ }
754
+ }
755
+ protected wireEvents(id?: string, ref?: object, keyConfig?: { [key: string]: string }, moduleName?: string): void {
756
+ EventHandler.add(this.headerTitleElement, 'click', this.navigateTitle, this);
757
+ this.defaultKeyConfigs = (extend(this.defaultKeyConfigs, this.keyConfigs) as { [key: string]: string });
758
+ if (this.getModuleName() === 'calendar') {
759
+ this.keyboardModule = new KeyboardEvents(
760
+ <HTMLElement>this.element,
761
+ {
762
+ eventName: 'keydown',
763
+ keyAction: this.keyActionHandle.bind(this),
764
+ keyConfigs: this.defaultKeyConfigs
765
+ });
766
+ } else {
767
+ this.keyboardModule = new KeyboardEvents(
768
+ <HTMLElement>this.calendarElement,
769
+ {
770
+ eventName: 'keydown',
771
+ keyAction: this.keyActionHandle.bind(this),
772
+ keyConfigs: this.defaultKeyConfigs
773
+ });
774
+ }
775
+ }
776
+ protected dateWireEvents(id?: string, ref?: object, keyConfig?: { [key: string]: string }, moduleName?: string): void {
777
+ this.defaultKeyConfigs = this.getDefaultKeyConfig();
778
+ this.defaultKeyConfigs = (extend(this.defaultKeyConfigs, keyConfig) as { [key: string]: string });
779
+ this.serverModuleName = moduleName;
780
+ }
781
+ protected todayButtonClick(e?: MouseEvent | KeyboardEvent, value?: Date, isCustomDate?: boolean): void {
782
+ if (this.showTodayButton) {
783
+ if (this.currentView() === this.depth) {
784
+ this.effect = '';
785
+ } else {
786
+ this.effect = 'e-zoomin';
787
+ }
788
+ if (this.getViewNumber(this.start) >= this.getViewNumber(this.depth)) {
789
+ this.navigateTo(this.depth, new Date(this.checkValue(value)), isCustomDate);
790
+ } else {
791
+ this.navigateTo('Month', new Date(this.checkValue(value)), isCustomDate);
792
+ }
793
+ }
794
+ }
795
+ protected resetCalendar(): void {
796
+ this.calendarElement && detach(this.calendarElement);
797
+ this.tableBodyElement && detach(this.tableBodyElement);
798
+ this.table && detach(this.table);
799
+ this.tableHeadElement && detach(this.tableHeadElement);
800
+ this.nextIcon && detach(this.nextIcon);
801
+ this.previousIcon && detach(this.previousIcon);
802
+ this.footer && detach(this.footer);
803
+ this.todayElement = null;
804
+ this.renderDayCellArgs = null;
805
+ this.calendarElement = this.tableBodyElement = this.footer = this.tableHeadElement =
806
+ this.nextIcon = this.previousIcon = this.table = null;
807
+ }
808
+ protected keyActionHandle(e: KeyboardEventArgs, value?: Date, multiSelection?: boolean): void {
809
+ if (this.calendarElement === null && e.action === 'escape') {
810
+ return;
811
+ }
812
+ const focusedDate: Element = this.tableBodyElement.querySelector('tr td.e-focused-date');
813
+ let selectedDate: Element;
814
+ if (multiSelection) {
815
+ if (!isNullOrUndefined(focusedDate) && +value === parseInt(focusedDate.getAttribute('id').split('_')[0], 10)) {
816
+ selectedDate = focusedDate;
817
+ } else {
818
+ selectedDate = this.tableBodyElement.querySelector('tr td.e-selected');
819
+ }
820
+ } else {
821
+ selectedDate = this.tableBodyElement.querySelector('tr td.e-selected');
822
+ }
823
+ let view: number = this.getViewNumber(this.currentView());
824
+ const depthValue: number = this.getViewNumber(this.depth);
825
+ const levelRestrict: boolean = (view === depthValue && this.getViewNumber(this.start) >= depthValue);
826
+ this.effect = '';
827
+ switch (e.action) {
828
+ case 'moveLeft':
829
+ if (this.getModuleName() !== 'daterangepicker' && !isNullOrUndefined((e.target as any))) {
830
+ this.keyboardNavigate(-1, view, e, this.max, this.min);
831
+ e.preventDefault();
832
+ }
833
+ break;
834
+ case 'moveRight':
835
+ if (this.getModuleName() !== 'daterangepicker' && !isNullOrUndefined((e.target as any))) {
836
+ this.keyboardNavigate(1, view, e, this.max, this.min);
837
+ e.preventDefault();
838
+ }
839
+ break;
840
+ case 'moveUp':
841
+ if (this.getModuleName() !== 'daterangepicker' && !isNullOrUndefined((e.target as any))) {
842
+ if (view === 0) {
843
+ this.keyboardNavigate(-7, view, e, this.max, this.min); // move the current date to the previous seven days.
844
+ } else {
845
+ this.keyboardNavigate(-4, view, e, this.max, this.min); // move the current year to the previous four days.
846
+ }
847
+ e.preventDefault();
848
+ }
849
+ break;
850
+ case 'moveDown':
851
+ if (this.getModuleName() !== 'daterangepicker' && !isNullOrUndefined((e.target as any))) {
852
+ if (view === 0) {
853
+ this.keyboardNavigate(7, view, e, this.max, this.min);
854
+ } else {
855
+ this.keyboardNavigate(4, view, e, this.max, this.min);
856
+ }
857
+ e.preventDefault();
858
+ }
859
+ break;
860
+ case 'select':
861
+ if (e.target === this.headerTitleElement){
862
+ this.navigateTitle(e);
863
+ }
864
+ else if (e.target === this.previousIcon && !(e.target as HTMLElement).className.includes(DISABLED)) {
865
+ this.navigatePrevious(e);
866
+ }
867
+ else if (e.target === this.nextIcon && !(e.target as HTMLElement).className.includes(DISABLED)) {
868
+ this.navigateNext(e);
869
+ }
870
+ else if (e.target === this.todayElement && !(e.target as HTMLElement).className.includes(DISABLED)) {
871
+ this.todayButtonClick(e, value);
872
+ if (this.getModuleName() === 'datepicker' || this.getModuleName() === 'datetimepicker') {
873
+ if ((this as any).isAngular) {
874
+ (this as any).inputElement.focus();
875
+ } else {
876
+ (this as any).element.focus();
877
+ }
878
+ }
879
+ } else {
880
+ const element: Element = !isNullOrUndefined(focusedDate) ? focusedDate : selectedDate;
881
+ if (!isNullOrUndefined(element) && !element.classList.contains(DISABLED)) {
882
+ if (levelRestrict) {
883
+ // eslint-disable-next-line radix
884
+ const d: Date = new Date(parseInt('' + (element).id, 0));
885
+ this.selectDate(e, d, (element));
886
+ if (this.getModuleName() === 'datepicker' || this.getModuleName() === 'datetimepicker') {
887
+ if ((this as any).isAngular) {
888
+ (this as any).inputElement.focus();
889
+ } else {
890
+ (this as any).element.focus();
891
+ }
892
+ }
893
+ } else {
894
+ if ( !(e.target as HTMLElement).className.includes(DISABLED)){
895
+ this.contentClick(null, --view, (element), value);
896
+ }
897
+ }
898
+ }
899
+ }
900
+ break;
901
+ case 'controlUp':
902
+ this.title();
903
+ e.preventDefault();
904
+ break;
905
+ case 'controlDown':
906
+ if (!isNullOrUndefined(focusedDate) && !levelRestrict || !isNullOrUndefined(selectedDate) && !levelRestrict) {
907
+ this.contentClick(null, --view, (focusedDate || selectedDate), value);
908
+ }
909
+ e.preventDefault();
910
+ break;
911
+ case 'home':
912
+ this.currentDate = this.firstDay(this.currentDate);
913
+ detach(this.tableBodyElement);
914
+ if (view === 0) {
915
+ this.renderMonths(e);
916
+ } else if (view === 1) {
917
+ this.renderYears(e);
918
+ } else {
919
+ this.renderDecades(e);
920
+ }
921
+ e.preventDefault();
922
+ break;
923
+ case 'end':
924
+ this.currentDate = this.lastDay(this.currentDate, view);
925
+ detach(this.tableBodyElement);
926
+ if (view === 0) {
927
+ this.renderMonths(e);
928
+ } else if (view === 1) {
929
+ this.renderYears(e);
930
+ } else {
931
+ this.renderDecades(e);
932
+ }
933
+ e.preventDefault();
934
+ break;
935
+ case 'pageUp':
936
+ this.addMonths(this.currentDate, -1);
937
+ this.navigateTo('Month', this.currentDate);
938
+ e.preventDefault();
939
+ break;
940
+ case 'pageDown':
941
+ this.addMonths(this.currentDate, 1);
942
+ this.navigateTo('Month', this.currentDate);
943
+ e.preventDefault();
944
+ break;
945
+ case 'shiftPageUp':
946
+ this.addYears(this.currentDate, -1);
947
+ this.navigateTo('Month', this.currentDate);
948
+ e.preventDefault();
949
+ break;
950
+ case 'shiftPageDown':
951
+ this.addYears(this.currentDate, 1);
952
+ this.navigateTo('Month', this.currentDate);
953
+ e.preventDefault();
954
+ break;
955
+ case 'controlHome':
956
+ this.navigateTo('Month', new Date(this.currentDate.getFullYear(), 0, 1));
957
+ e.preventDefault();
958
+ break;
959
+ case 'controlEnd':
960
+ this.navigateTo('Month', new Date(this.currentDate.getFullYear(), 11, 31));
961
+ e.preventDefault();
962
+ break;
963
+ case 'tab':
964
+ if ((this.getModuleName() === 'datepicker' || this.getModuleName() === 'datetimepicker') && e.target === this.todayElement) {
965
+ e.preventDefault();
966
+ if ((this as any).isAngular) {
967
+ (this as any).inputElement.focus();
968
+ } else {
969
+ (this as any).element.focus();
970
+ }
971
+ (this as any).hide();
972
+ }
973
+ break;
974
+ case 'shiftTab':
975
+ if ((this.getModuleName() === 'datepicker' || this.getModuleName() === 'datetimepicker') && e.target === this.headerTitleElement) {
976
+ e.preventDefault();
977
+ if ((this as any).isAngular) {
978
+ (this as any).inputElement.focus();
979
+ } else {
980
+ (this as any).element.focus();
981
+ }
982
+ (this as any).hide();
983
+ }
984
+ break;
985
+ case 'escape':
986
+ if ((this.getModuleName() === 'datepicker' || this.getModuleName() === 'datetimepicker') && (e.target === this.headerTitleElement || e.target === this.previousIcon || e.target === this.nextIcon || e.target === this.todayElement)) {
987
+ (this as any).hide();
988
+ }
989
+ break;
990
+ }
991
+ }
992
+
993
+ protected keyboardNavigate(number: number, currentView: number, e: KeyboardEvent, max: Date, min: Date): void {
994
+ const date: Date = new Date(this.checkValue(this.currentDate));
995
+ switch (currentView) {
996
+ case 2:
997
+ this.addYears(this.currentDate, number);
998
+ if (this.isMonthYearRange(this.currentDate)) {
999
+ detach(this.tableBodyElement);
1000
+ this.renderDecades(e);
1001
+ } else {
1002
+ this.currentDate = date;
1003
+ }
1004
+ break;
1005
+ case 1:
1006
+ this.addMonths(this.currentDate, number);
1007
+ if (this.calendarMode === 'Gregorian') {
1008
+ if (this.isMonthYearRange(this.currentDate)) {
1009
+ detach(this.tableBodyElement);
1010
+ this.renderYears(e);
1011
+ } else {
1012
+ this.currentDate = date;
1013
+ }
1014
+ } else {
1015
+ if (this.isMonthYearRange(this.currentDate)) {
1016
+ detach(this.tableBodyElement);
1017
+ this.renderYears(e);
1018
+ } else {
1019
+ this.currentDate = date;
1020
+ }
1021
+ }
1022
+ break;
1023
+ case 0:
1024
+ this.addDay(this.currentDate, number, e, max, min);
1025
+ if (this.isMinMaxRange(this.currentDate)) {
1026
+ detach(this.tableBodyElement);
1027
+ this.renderMonths(e);
1028
+ } else {
1029
+ this.currentDate = date;
1030
+ }
1031
+ break;
1032
+ }
1033
+ }
1034
+
1035
+ /**
1036
+ * Initialize the event handler
1037
+ *
1038
+ * @param {Date} value - Specifies value of date.
1039
+ * @returns {void}
1040
+ * @private
1041
+ */
1042
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1043
+ protected preRender(value?: Date): void {
1044
+ this.navigatePreviousHandler = this.navigatePrevious.bind(this);
1045
+ this.navigateNextHandler = this.navigateNext.bind(this);
1046
+ this.defaultKeyConfigs = this.getDefaultKeyConfig();
1047
+ this.navigateHandler = (e: MouseEvent): void => {
1048
+ this.triggerNavigate(e);
1049
+ };
1050
+ }
1051
+ protected minMaxDate(localDate: Date): Date {
1052
+ const currentDate: Date = new Date(new Date(+localDate).setHours(0, 0, 0, 0));
1053
+ const minDate: Date = new Date(new Date(+this.min).setHours(0, 0, 0, 0));
1054
+ const maxDate: Date = new Date(new Date(+this.max).setHours(0, 0, 0, 0));
1055
+ if (+currentDate === +minDate || +currentDate === +maxDate) {
1056
+ if (+localDate < +this.min) {
1057
+ localDate = new Date(+this.min);
1058
+ }
1059
+ if (+localDate > +this.max) {
1060
+ localDate = new Date(+this.max);
1061
+ }
1062
+ }
1063
+ return localDate;
1064
+ }
1065
+ protected renderMonths(e?: Event, value?: Date, isCustomDate?: boolean): void {
1066
+ const numCells: number = this.weekNumber ? 8 : 7;
1067
+ let tdEles: HTMLElement[];
1068
+ if (this.calendarMode === 'Gregorian') {
1069
+ tdEles = this.renderDays(this.currentDate, value, null, null, isCustomDate, e);
1070
+ } else {
1071
+ tdEles = !isNullOrUndefined(this.islamicModule) ? this.islamicModule.islamicRenderDays(this.currentDate, value) : null;
1072
+ }
1073
+ this.createContentHeader();
1074
+ if (this.calendarMode === 'Gregorian') {
1075
+ this.renderTemplate(tdEles, numCells, MONTH, e, value);
1076
+ } else if (!isNullOrUndefined(this.islamicModule)) {
1077
+ this.islamicModule.islamicRenderTemplate(tdEles, numCells, MONTH, e, value);
1078
+ }
1079
+ }
1080
+ protected renderDays(currentDate: Date, value?: Date, multiSelection?: boolean, values?:
1081
+ Date[], isTodayDate?: boolean, e?: Event): HTMLElement[] {
1082
+ const tdEles: HTMLElement[] = [];
1083
+ const cellsCount: number = 42;
1084
+ const todayDate: Date = isTodayDate ? new Date(+currentDate) : this.getDate(new Date(), this.timezone);
1085
+ let localDate: Date = new Date(this.checkValue(currentDate));
1086
+ let minMaxDate: Date;
1087
+ const currentMonth: number = localDate.getMonth();
1088
+ this.titleUpdate(currentDate, 'days');
1089
+ const d: Date = localDate;
1090
+ localDate = new Date(d.getFullYear(), d.getMonth(), 0, d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
1091
+ while (localDate.getDay() !== this.firstDayOfWeek) {
1092
+ this.setStartDate(localDate, -1 * dayMilliSeconds);
1093
+ }
1094
+ for (let day: number = 0; day < cellsCount; ++day) {
1095
+ const weekEle: HTMLElement = this.createElement('td', { className: CELL });
1096
+ const weekAnchor: HTMLElement = this.createElement('span');
1097
+ if (day % 7 === 0 && this.weekNumber) {
1098
+ // 6 days are added to get Last day of the week and 3 days are added to get middle day of the week.
1099
+ const numberOfDays : number = this.weekRule === 'FirstDay' ? 6 : (this.weekRule === 'FirstFourDayWeek' ? 3 : 0);
1100
+ const finalDate : Date = new Date(localDate.getFullYear(), localDate.getMonth(), (localDate.getDate() + numberOfDays));
1101
+ weekAnchor.textContent = '' + this.getWeek(finalDate);
1102
+ weekEle.appendChild(weekAnchor);
1103
+ addClass([weekEle], '' + WEEKNUMBER);
1104
+ tdEles.push(weekEle);
1105
+ }
1106
+ minMaxDate = new Date(+localDate);
1107
+ localDate = this.minMaxDate(localDate);
1108
+ const dateFormatOptions: object = { type: 'dateTime', skeleton: 'full' };
1109
+ const date: Date = this.globalize.parseDate(this.globalize.formatDate(localDate, dateFormatOptions), dateFormatOptions);
1110
+ const tdEle: HTMLElement = this.dayCell(localDate);
1111
+ const title: string = this.globalize.formatDate(localDate, { type: 'date', skeleton: 'full' });
1112
+ const dayLink: HTMLElement = this.createElement('span');
1113
+ dayLink.textContent = this.globalize.formatDate(localDate, { format: 'd', type: 'date', skeleton: 'yMd'});
1114
+ const disabled: boolean = (this.min > localDate) || (this.max < localDate);
1115
+ if (disabled) {
1116
+ addClass([tdEle], DISABLED);
1117
+ addClass([tdEle], OVERLAY);
1118
+ } else {
1119
+ dayLink.setAttribute('title', '' + title);
1120
+ }
1121
+ if (currentMonth !== localDate.getMonth()) {
1122
+ addClass([tdEle], OTHERMONTH);
1123
+ dayLink.setAttribute('aria-disabled', 'true');
1124
+ }
1125
+ if (localDate.getDay() === 0 || localDate.getDay() === 6) {
1126
+ addClass([tdEle], WEEKEND);
1127
+ }
1128
+ tdEle.appendChild(dayLink);
1129
+ this.renderDayCellArgs = {
1130
+ date: localDate,
1131
+ isDisabled: false,
1132
+ element: tdEle,
1133
+ isOutOfRange: disabled
1134
+ };
1135
+ const argument: RenderDayCellEventArgs = this.renderDayCellArgs;
1136
+ this.renderDayCellEvent(argument);
1137
+ if (argument.isDisabled) {
1138
+ const selectDate: Date = new Date(this.checkValue(value));
1139
+ const argsDate: Date = new Date(this.checkValue(argument.date));
1140
+ if (multiSelection) {
1141
+ if (!isNullOrUndefined(values) && values.length > 0) {
1142
+ for (let index: number = 0; index < values.length; index++) {
1143
+ const localDateString: number =
1144
+ +new Date(this.globalize.formatDate(argument.date, { type: 'date', skeleton: 'yMd' }));
1145
+ const tempDateString: number =
1146
+ +new Date(this.globalize.formatDate(values[index as number], { type: 'date', skeleton: 'yMd' }));
1147
+ if (localDateString === tempDateString) {
1148
+ values.splice(index, 1);
1149
+ index = -1;
1150
+ }
1151
+ }
1152
+ }
1153
+ } else if (selectDate && +selectDate === +argsDate) {
1154
+ this.setProperties({ value: null }, true);
1155
+ }
1156
+ }
1157
+ if (this.renderDayCellArgs.isDisabled && !tdEle.classList.contains(SELECTED)) {
1158
+ addClass([tdEle], DISABLED);
1159
+ addClass([tdEle], OVERLAY);
1160
+ dayLink.setAttribute('aria-disabled', 'true');
1161
+ if (+this.renderDayCellArgs.date === +this.todayDate) {
1162
+ this.todayDisabled = true;
1163
+ }
1164
+ }
1165
+ const otherMnthBool: boolean = tdEle.classList.contains(OTHERMONTH);
1166
+ const disabledCls: boolean = tdEle.classList.contains(DISABLED);
1167
+ if (!disabledCls) {
1168
+ EventHandler.add(tdEle, 'click', this.clickHandler, this);
1169
+ }
1170
+ // to set the value as null while setting the disabled date onProperty change.
1171
+ // if (args.isDisabled && +this.value === +args.date) {
1172
+ // this.setProperties({ value: null }, true);
1173
+ // }
1174
+ let currentTarget: any;
1175
+ if ( !isNullOrUndefined(e) && e.type === 'click') {
1176
+ currentTarget = e.currentTarget; }
1177
+ if (multiSelection && !isNullOrUndefined(values) && !disabledCls) {
1178
+ for (let tempValue: number = 0; tempValue < values.length; tempValue++) {
1179
+ const type: string = (this.calendarMode === 'Gregorian') ? 'gregorian' : 'islamic';
1180
+ const formatOptions: object = { format: null, type: 'date', skeleton: 'short', calendar: type };
1181
+ const localDateString: string = this.globalize.formatDate(localDate, formatOptions);
1182
+ const tempDateString: string = this.globalize.formatDate(values[tempValue as number], formatOptions);
1183
+ if ((localDateString === tempDateString && this.getDateVal(localDate, values[tempValue as number]))
1184
+ || (this.getDateVal(localDate, value))) {
1185
+ addClass([tdEle], SELECTED);
1186
+ } if (!isNullOrUndefined(currentTarget) && currentTarget.innerText === tdEle.innerText &&
1187
+ this.previousDates && tdEle.classList.contains(SELECTED) && currentTarget.classList.contains(SELECTED)) {
1188
+ removeClass([tdEle], SELECTED);
1189
+ this.previousDates = false;
1190
+ const copyValues: Date[] = this.copyValues(values);
1191
+ for (let i: number = 0; i < copyValues.length; i++) {
1192
+ const type: string = (this.calendarMode === 'Gregorian') ? 'gregorian' : 'islamic';
1193
+ const formatOptions: object = { format: null, type: 'date', skeleton: 'short', calendar: type };
1194
+ const localDateString: string = this.globalize.formatDate(date, formatOptions);
1195
+ const tempDateString: string = this.globalize.formatDate(copyValues[i as number], formatOptions);
1196
+ if (localDateString === tempDateString) {
1197
+ const index: number = copyValues.indexOf(copyValues[i as number]);
1198
+ copyValues.splice(index, 1);
1199
+ values.splice(index, 1);
1200
+ }
1201
+ }
1202
+ this.setProperties({ values: copyValues }, true);
1203
+ } else {
1204
+ this.updateFocus(otherMnthBool, disabledCls, localDate, tdEle, currentDate);
1205
+ }
1206
+ }
1207
+ if (values.length <= 0) {
1208
+ this.updateFocus(otherMnthBool, disabledCls, localDate, tdEle, currentDate);
1209
+ }
1210
+ } else if (!disabledCls && this.getDateVal(localDate, value)) {
1211
+ addClass([tdEle], SELECTED);
1212
+ }
1213
+ this.updateFocus(otherMnthBool, disabledCls, localDate, tdEle, currentDate);
1214
+ if (!isNullOrUndefined(date) && date.getFullYear() === todayDate.getFullYear() && date.getMonth() === todayDate.getMonth()
1215
+ && date.getDate() === todayDate.getDate()) {
1216
+ addClass([tdEle], TODAY);
1217
+ }
1218
+ tdEles.push(this.renderDayCellArgs.element);
1219
+ localDate = new Date(+minMaxDate);
1220
+ this.addDay(localDate, 1, null, this.max, this.min);
1221
+ }
1222
+ return tdEles;
1223
+ }
1224
+ protected updateFocus(otherMonth: boolean, disabled: boolean, localDate: Date, tableElement: HTMLElement, currentDate: Date): void {
1225
+ if (currentDate.getDate() === localDate.getDate() && !otherMonth && !disabled) {
1226
+ addClass([tableElement], FOCUSEDDATE);
1227
+ } else {
1228
+ // eslint-disable-next-line radix
1229
+ if (currentDate >= this.max && parseInt(tableElement.id, 0) === +this.max && !otherMonth && !disabled) {
1230
+ addClass([tableElement], FOCUSEDDATE);
1231
+ }
1232
+ // eslint-disable-next-line radix
1233
+ if (currentDate <= this.min && parseInt(tableElement.id, 0) === +this.min && !otherMonth && !disabled) {
1234
+ addClass([tableElement], FOCUSEDDATE);
1235
+ }
1236
+ }
1237
+ }
1238
+ protected renderYears(e?: Event, value?: Date): void {
1239
+ this.removeTableHeadElement();
1240
+ const numCells: number = 4;
1241
+ const tdEles: HTMLElement[] = [];
1242
+ const valueUtil: boolean = isNullOrUndefined(value);
1243
+ const curDate: Date = new Date(this.checkValue(this.currentDate));
1244
+ const mon: number = curDate.getMonth();
1245
+ const yr: number = curDate.getFullYear();
1246
+ const localDate: Date = curDate;
1247
+ const curYrs: number = localDate.getFullYear();
1248
+ const minYr: number = new Date(this.checkValue(this.min)).getFullYear();
1249
+ const minMonth: number = new Date(this.checkValue(this.min)).getMonth();
1250
+ const maxYr: number = new Date(this.checkValue(this.max)).getFullYear();
1251
+ const maxMonth: number = new Date(this.checkValue(this.max)).getMonth();
1252
+ localDate.setMonth(0);
1253
+ this.titleUpdate(this.currentDate, 'months');
1254
+ localDate.setDate(1);
1255
+ for (let month: number = 0; month < 12; ++month) {
1256
+ const tdEle: HTMLElement = this.dayCell(localDate);
1257
+ const dayLink: HTMLElement = this.createElement('span');
1258
+ const localMonth: boolean = (value && (value).getMonth() === localDate.getMonth());
1259
+ const select: boolean = (value && (value).getFullYear() === yr && localMonth);
1260
+ const title: string = this.globalize.formatDate(localDate, { type: 'date', format: 'MMM y' });
1261
+ dayLink.textContent = this.toCapitalize(this.globalize.formatDate(localDate, {
1262
+ format: null, type: 'dateTime', skeleton: 'MMM'
1263
+ }));
1264
+ if ((this.min && (curYrs < minYr || (month < minMonth && curYrs === minYr))) || (
1265
+ this.max && (curYrs > maxYr || (month > maxMonth && curYrs >= maxYr)))) {
1266
+ addClass([tdEle], DISABLED);
1267
+ } else if (!valueUtil && select) {
1268
+ addClass([tdEle], SELECTED);
1269
+ } else {
1270
+ if (localDate.getMonth() === mon && this.currentDate.getMonth() === mon) {
1271
+ addClass([tdEle], FOCUSEDDATE);
1272
+ }
1273
+ }
1274
+ localDate.setDate(1);
1275
+ localDate.setMonth(localDate.getMonth() + 1);
1276
+ if (!tdEle.classList.contains(DISABLED)) {
1277
+ EventHandler.add(tdEle, 'click', this.clickHandler, this);
1278
+ dayLink.setAttribute('title', '' + title);
1279
+ }
1280
+ tdEle.appendChild(dayLink);
1281
+ tdEles.push(tdEle);
1282
+ }
1283
+ this.renderTemplate(tdEles, numCells, YEAR, e, value);
1284
+ }
1285
+ protected renderDecades(e?: Event, value?: Date): void {
1286
+ this.removeTableHeadElement();
1287
+ const numCells: number = 4;
1288
+ const yearCell: number = 12;
1289
+ const tdEles: HTMLElement[] = [];
1290
+ const localDate: Date = new Date(this.checkValue(this.currentDate));
1291
+ localDate.setMonth(0);
1292
+ localDate.setDate(1);
1293
+ const localYr: number = localDate.getFullYear();
1294
+ const startYr: Date = new Date(localDate.setFullYear((localYr - localYr % 10)));
1295
+ const endYr: Date = new Date(localDate.setFullYear((localYr - localYr % 10 + (10 - 1))));
1296
+ const startFullYr: number = startYr.getFullYear();
1297
+ const endFullYr: number = endYr.getFullYear();
1298
+ const startHdrYr: string = this.globalize.formatDate(startYr, {
1299
+ format: null, type: 'dateTime', skeleton: 'y'
1300
+ });
1301
+ const endHdrYr: string = this.globalize.formatDate(endYr, { format: null, type: 'dateTime', skeleton: 'y' });
1302
+ this.headerTitleElement.textContent = startHdrYr + ' - ' + (endHdrYr);
1303
+ const start: Date = new Date(localYr - (localYr % 10) - 1, 0, 1);
1304
+ const startYear: number = start.getFullYear();
1305
+ for (let rowIterator: number = 0; rowIterator < yearCell; ++rowIterator) {
1306
+ const year: number = startYear + rowIterator;
1307
+ localDate.setFullYear(year);
1308
+ const tdEle: HTMLElement = this.dayCell(localDate);
1309
+ const dayLink: HTMLElement = this.createElement('span');
1310
+ dayLink.textContent = this.globalize.formatDate(localDate, {
1311
+ format: null, type: 'dateTime', skeleton: 'y'
1312
+ });
1313
+ if ((year < startFullYr) || (year > endFullYr)) {
1314
+ addClass([tdEle], OTHERDECADE);
1315
+ dayLink.setAttribute('aria-disabled', 'true');
1316
+ if (!isNullOrUndefined(value) && localDate.getFullYear() === (value).getFullYear()) {
1317
+ addClass([tdEle], SELECTED);
1318
+ }
1319
+ if (year < new Date(this.checkValue(this.min)).getFullYear() ||
1320
+ year > new Date(this.checkValue(this.max)).getFullYear()) {
1321
+ addClass([tdEle], DISABLED);
1322
+ }
1323
+ } else if (year < new Date(this.checkValue(this.min)).getFullYear() ||
1324
+ year > new Date(this.checkValue(this.max)).getFullYear()) {
1325
+ addClass([tdEle], DISABLED);
1326
+ } else if (!isNullOrUndefined(value) && localDate.getFullYear() === (value).getFullYear()) {
1327
+ addClass([tdEle], SELECTED);
1328
+ } else {
1329
+ if (localDate.getFullYear() === this.currentDate.getFullYear() && !tdEle.classList.contains(DISABLED)) {
1330
+ addClass([tdEle], FOCUSEDDATE);
1331
+ }
1332
+ }
1333
+ if (!tdEle.classList.contains(DISABLED)) {
1334
+ EventHandler.add(tdEle, 'click', this.clickHandler, this);
1335
+ dayLink.setAttribute('title', '' + dayLink.textContent);
1336
+ }
1337
+ tdEle.appendChild(dayLink);
1338
+ tdEles.push(tdEle);
1339
+ }
1340
+ this.renderTemplate(tdEles, numCells, 'e-decade', e, value);
1341
+ }
1342
+ protected dayCell(localDate: Date): HTMLElement {
1343
+ const type: string = (this.calendarMode === 'Gregorian') ? 'gregorian' : 'islamic';
1344
+ const dateFormatOptions: object = { skeleton: 'full', type: 'dateTime', calendar: type };
1345
+ const date: Date = this.globalize.parseDate(this.globalize.formatDate(localDate, dateFormatOptions), dateFormatOptions);
1346
+ let value: number ;
1347
+ if (!isNullOrUndefined(date)){
1348
+ value = date.valueOf();
1349
+ }
1350
+ const attrs: Object = {
1351
+ className: CELL, attrs: { 'id': '' + getUniqueID('' + value)}
1352
+ };
1353
+ return this.createElement('td', attrs);
1354
+ }
1355
+ protected firstDay(date: Date): Date {
1356
+ const collection: Element[] = this.currentView() !== 'Decade' ? <NodeListOf<HTMLTableDataCellElement> & Element[]>
1357
+ this.tableBodyElement.querySelectorAll('td:not(.' + OTHERMONTH + '):not(.' + WEEKNUMBER + ')') :
1358
+ <NodeListOf<HTMLTableDataCellElement> & Element[]>
1359
+ this.tableBodyElement.querySelectorAll('td' + ':not(.' + OTHERDECADE + '');
1360
+ if (collection.length) {
1361
+ for (let i: number = 0; i < collection.length; i++) {
1362
+ if (!collection[i as number].classList.contains(DISABLED)) {
1363
+ // eslint-disable-next-line radix
1364
+ date = new Date(parseInt(collection[i as number].id, 0));
1365
+ break;
1366
+ }
1367
+ }
1368
+ }
1369
+ return date;
1370
+ }
1371
+ protected lastDay(date: Date, view: number): Date {
1372
+ const lastDate: Date = new Date(date.getFullYear(), date.getMonth() + 1, 0);
1373
+ if (view !== 2) {
1374
+ const timeOffset: number = Math.abs(lastDate.getTimezoneOffset() - this.firstDay(date).getTimezoneOffset());
1375
+ if (timeOffset) {
1376
+ lastDate.setHours(this.firstDay(date).getHours() + (timeOffset / 60));
1377
+ }
1378
+ return this.findLastDay(lastDate);
1379
+ } else {
1380
+ return this.findLastDay(this.firstDay(lastDate));
1381
+ }
1382
+ }
1383
+ protected checkDateValue(value: Date): Date {
1384
+ return (!isNullOrUndefined(value) && value instanceof Date && !isNaN(+value)) ? value : null;
1385
+ }
1386
+ protected findLastDay(date: Date): Date {
1387
+ const collection: Element[] = this.currentView() === 'Decade' ? <NodeListOf<HTMLTableDataCellElement> & Element[]>
1388
+ this.tableBodyElement.querySelectorAll('td' + ':not(.' + OTHERDECADE + '') :
1389
+ <NodeListOf<HTMLTableDataCellElement> & Element[]>
1390
+ this.tableBodyElement.querySelectorAll('td:not(.' + OTHERMONTH + '):not(.' + WEEKNUMBER + ')');
1391
+ if (collection.length) {
1392
+ for (let i: number = collection.length - 1; i >= 0; i--) {
1393
+ if (!collection[i as number].classList.contains(DISABLED)) {
1394
+ // eslint-disable-next-line radix
1395
+ date = new Date(parseInt(collection[i as number].id, 0));
1396
+ break;
1397
+ }
1398
+ }
1399
+ }
1400
+ return date;
1401
+ }
1402
+ protected removeTableHeadElement(): void {
1403
+ if (this.getModuleName() === 'calendar') {
1404
+ if (!isNullOrUndefined(this.element.querySelectorAll('.e-content table thead')[0])) {
1405
+ detach(this.tableHeadElement);
1406
+ }
1407
+ } else {
1408
+ if (!isNullOrUndefined(this.calendarElement.querySelectorAll('.e-content table thead')[0])) {
1409
+ detach(this.tableHeadElement);
1410
+ }
1411
+ }
1412
+
1413
+ }
1414
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1415
+ protected renderTemplate(elements: HTMLElement[], count: number, classNm: string, e?: Event, value?: Date): void {
1416
+ const view: number = this.getViewNumber(this.currentView());
1417
+ let trEle: HTMLElement;
1418
+ this.tableBodyElement = this.createElement('tbody');
1419
+ this.table.appendChild(this.tableBodyElement);
1420
+ removeClass([this.contentElement, this.headerElement], [MONTH, DECADE, YEAR]);
1421
+ addClass([this.contentElement, this.headerElement], [classNm]);
1422
+ const weekNumCell: number = 41;
1423
+ const numberCell: number = 35;
1424
+ const otherMonthCell: number = 6;
1425
+ let row: number = count;
1426
+ let rowIterator: number = 0;
1427
+ for (let dayCell: number = 0; dayCell < elements.length / count; ++dayCell) {
1428
+ trEle = this.createElement('tr');
1429
+ for (rowIterator = 0 + rowIterator; rowIterator < row; rowIterator++) {
1430
+ if (!elements[rowIterator as number].classList.contains('e-week-number') && !isNullOrUndefined(elements[rowIterator as number].children[0])) {
1431
+ addClass([elements[rowIterator as number].children[0]], [LINK]);
1432
+ rippleEffect(<HTMLElement>elements[rowIterator as number].children[0], {
1433
+ duration: 600,
1434
+ isCenterRipple: true
1435
+ });
1436
+ }
1437
+ trEle.appendChild(elements[rowIterator as number]);
1438
+ if (this.weekNumber && rowIterator === otherMonthCell + 1 && elements[otherMonthCell + 1].classList.contains(OTHERMONTH)) {
1439
+ addClass([trEle], OTHERMONTHROW);
1440
+ }
1441
+ if (!this.weekNumber && rowIterator === otherMonthCell && elements[otherMonthCell as number].
1442
+ classList.contains(OTHERMONTH)) {
1443
+ addClass([trEle], OTHERMONTHROW);
1444
+ }
1445
+ if (this.weekNumber) {
1446
+ if (rowIterator === weekNumCell && elements[weekNumCell as number].classList.contains(OTHERMONTH)) {
1447
+ addClass([trEle], OTHERMONTHROW);
1448
+ }
1449
+ } else {
1450
+ if (rowIterator === numberCell && elements[numberCell as number].classList.contains(OTHERMONTH)) {
1451
+ addClass([trEle], OTHERMONTHROW);
1452
+ }
1453
+ }
1454
+ }
1455
+ row = row + count;
1456
+ rowIterator = rowIterator + 0;
1457
+ this.tableBodyElement.appendChild(trEle);
1458
+ }
1459
+ this.table.querySelector('tbody').className = this.effect;
1460
+ if (this.calendarMode === 'Gregorian') {
1461
+ this.iconHandler();
1462
+ } else {
1463
+ this.islamicModule.islamicIconHandler();
1464
+ }
1465
+
1466
+ if (view !== this.getViewNumber(this.currentView()) || (view === 0 && view !== this.getViewNumber(this.currentView()))) {
1467
+ this.navigateHandler(e);
1468
+ }
1469
+ this.setAriaActiveDescendant();
1470
+ }
1471
+ protected clickHandler(e: MouseEvent, value: Date): void {
1472
+ this.clickEventEmitter(e);
1473
+ const eve: Element = <HTMLElement>e.currentTarget;
1474
+ const view: number = this.getViewNumber(this.currentView());
1475
+ if (eve.classList.contains(OTHERMONTH)) {
1476
+ this.contentClick(e, 0, null, value);
1477
+ } else if (view === this.getViewNumber(this.depth) && this.getViewNumber(this.start) >= this.getViewNumber(this.depth)) {
1478
+ this.contentClick(e, 1, null, value);
1479
+ } else if (2 === view) {
1480
+ this.contentClick(e, 1, null, value);
1481
+ } else if (!eve.classList.contains(OTHERMONTH) && view === 0) {
1482
+ this.selectDate(e, this.getIdValue(e, null), null);
1483
+ } else {
1484
+ this.contentClick(e, 0, eve, value);
1485
+ }
1486
+ if (this.getModuleName() === 'calendar') {
1487
+ this.table.focus();
1488
+ }
1489
+ }
1490
+ // Content click event handler required for extended components
1491
+ protected clickEventEmitter(e: MouseEvent): void {
1492
+ e.preventDefault();
1493
+ }
1494
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1495
+ protected contentClick(e?: MouseEvent, view?: number, element?: Element, value?: Date): void {
1496
+ const currentView: number = this.getViewNumber(this.currentView());
1497
+ const d: Date = this.getIdValue(e, element);
1498
+ switch (view) {
1499
+ case 0:
1500
+ if (currentView === this.getViewNumber(this.depth) && this.getViewNumber(this.start) >= this.getViewNumber(this.depth)) {
1501
+ detach(this.tableBodyElement);
1502
+ this.currentDate = d;
1503
+ this.effect = ZOOMIN;
1504
+ this.renderMonths(e);
1505
+ } else {
1506
+
1507
+ if (this.calendarMode === 'Gregorian') {
1508
+ this.currentDate.setMonth(d.getMonth());
1509
+ if (d.getMonth() > 0 && this.currentDate.getMonth() !== d.getMonth()) {
1510
+ this.currentDate.setDate(0);
1511
+ }
1512
+ this.currentDate.setFullYear(d.getFullYear());
1513
+ } else {
1514
+ this.currentDate = d;
1515
+ }
1516
+
1517
+ this.effect = ZOOMIN;
1518
+ detach(this.tableBodyElement);
1519
+ this.renderMonths(e);
1520
+ }
1521
+ break;
1522
+ case 1:
1523
+ if (currentView === this.getViewNumber(this.depth) && this.getViewNumber(this.start) >= this.getViewNumber(this.depth)) {
1524
+ this.selectDate(e, d, null);
1525
+ } else {
1526
+ if (this.calendarMode === 'Gregorian') {
1527
+ this.currentDate.setFullYear(d.getFullYear());
1528
+ } else {
1529
+ this.islamicPreviousHeader = this.headerElement.textContent;
1530
+ const islamicDate: IslamicDateArgs = this.islamicModule.getIslamicDate(d);
1531
+ this.currentDate = this.islamicModule.toGregorian(islamicDate.year, islamicDate.month, 1);
1532
+ }
1533
+ this.effect = ZOOMIN;
1534
+ detach(this.tableBodyElement);
1535
+ this.renderYears(e);
1536
+ }
1537
+ }
1538
+ }
1539
+ protected switchView(view: number, e?: Event, multiSelection?: boolean, isCustomDate?: boolean): void {
1540
+ switch (view) {
1541
+ case 0:
1542
+ detach(this.tableBodyElement);
1543
+ this.renderMonths(e, null, isCustomDate);
1544
+ break;
1545
+ case 1:
1546
+ detach(this.tableBodyElement);
1547
+ this.renderYears(e);
1548
+ break;
1549
+ case 2:
1550
+ detach(this.tableBodyElement);
1551
+ this.renderDecades(e);
1552
+ }
1553
+ }
1554
+ /**
1555
+ * To get component name
1556
+ *
1557
+ * @returns {string} Returns the component name.
1558
+ * @private
1559
+ */
1560
+ protected getModuleName(): string {
1561
+ return 'calendar';
1562
+ }
1563
+ /**
1564
+ *
1565
+ * @returns {void}
1566
+ * @deprecated
1567
+ */
1568
+ public requiredModules(): ModuleDeclaration[] {
1569
+ const modules: ModuleDeclaration[] = [];
1570
+ if (this.calendarMode === 'Islamic') {
1571
+ modules.push({ args: [this], member: 'islamic', name: 'Islamic' });
1572
+ }
1573
+
1574
+ return modules;
1575
+ }
1576
+ /* eslint-disable valid-jsdoc, jsdoc/require-returns-description */
1577
+ /**
1578
+ * Gets the properties to be maintained upon browser refresh.
1579
+ *
1580
+ * @returns {string}
1581
+ */
1582
+ public getPersistData(): string {
1583
+ const keyEntity: string[] = ['value'];
1584
+ return this.addOnPersist(keyEntity);
1585
+ }
1586
+ /* eslint-enable valid-jsdoc, jsdoc/require-returns-description */
1587
+ /**
1588
+ * Called internally if any of the property value changed.
1589
+ *
1590
+ * @param {CalendarBaseModel} newProp - Returns the dynamic property value of the component.
1591
+ * @param {CalendarBaseModel} oldProp - Returns the previous property value of the component.
1592
+ * @param {boolean} multiSelection - - Specifies whether multiple date selection is enabled or not.
1593
+ * @param {Date[]} values - Specifies the dates.
1594
+ * @returns {void}
1595
+ * @private
1596
+ */
1597
+ public onPropertyChanged(newProp: CalendarBaseModel, oldProp: CalendarBaseModel, multiSelection?: boolean, values?: Date[]): void {
1598
+ this.effect = '';
1599
+ for (const prop of Object.keys(newProp)) {
1600
+ switch (prop) {
1601
+ case 'enableRtl':
1602
+ if (newProp.enableRtl) {
1603
+ if (this.getModuleName() === 'calendar') {
1604
+ this.element.classList.add('e-rtl');
1605
+ } else {
1606
+ this.calendarElement.classList.add('e-rtl');
1607
+ }
1608
+ } else {
1609
+ if (this.getModuleName() === 'calendar') {
1610
+ this.element.classList.remove('e-rtl');
1611
+ } else {
1612
+ this.calendarElement.classList.remove('e-rtl');
1613
+ }
1614
+ }
1615
+ break;
1616
+ case 'dayHeaderFormat':
1617
+ this.getCultureValues();
1618
+ if (this.getModuleName() !== 'datepicker') {
1619
+ this.createContentHeader();
1620
+ } else if (this.calendarElement) {
1621
+ this.createContentHeader();
1622
+ }
1623
+ this.adjustLongHeaderSize();
1624
+ break;
1625
+ case 'min':
1626
+ case 'max':
1627
+ this.rangeValidation(this.min, this.max);
1628
+ if (prop === 'min') {
1629
+ this.setProperties({ min: this.checkDateValue(new Date(this.checkValue(newProp.min))) }, true);
1630
+ } else {
1631
+ this.setProperties({ max: this.checkDateValue(new Date(this.checkValue(newProp.max))) }, true);
1632
+ }
1633
+ this.setProperties({ start: this.currentView() }, true);
1634
+ if (this.tableBodyElement) {
1635
+ detach(this.tableBodyElement);
1636
+ }
1637
+ this.minMaxUpdate();
1638
+ if (multiSelection) {
1639
+ this.validateValues(multiSelection, values);
1640
+ }
1641
+ if (this.getModuleName() !== 'datepicker') {
1642
+ this.createContentBody();
1643
+ } else if (this.calendarElement) {
1644
+ this.createContentBody();
1645
+ }
1646
+ if ((this.todayDate < this.min || this.max < this.todayDate) && (this.footer) && (this.todayElement)) {
1647
+ detach(this.todayElement);
1648
+ detach(this.footer);
1649
+ this.todayElement = this.footer = null;
1650
+ this.createContentFooter();
1651
+ } else {
1652
+ if ((this.footer) && (this.todayElement) && this.todayElement.classList.contains('e-disabled')) {
1653
+ removeClass([this.todayElement], DISABLED);
1654
+ detach(this.todayElement);
1655
+ detach(this.footer);
1656
+ this.todayElement = this.footer = null;
1657
+ this.createContentFooter();
1658
+ }
1659
+ }
1660
+ break;
1661
+ case 'start':
1662
+ case 'depth':
1663
+ case 'weekNumber':
1664
+ case 'firstDayOfWeek':
1665
+ case 'weekRule':
1666
+ this.checkView();
1667
+ if (this.getModuleName() !== 'datepicker') {
1668
+ this.createContentHeader();
1669
+ this.createContentBody();
1670
+ } else if (this.calendarElement) {
1671
+ this.createContentHeader();
1672
+ this.createContentBody();
1673
+ }
1674
+ break;
1675
+
1676
+ case 'locale':
1677
+ this.globalize = new Internationalization(this.locale);
1678
+ if (this.getModuleName() !== 'datepicker') {
1679
+ this.createContentHeader();
1680
+ this.createContentBody();
1681
+ } else if (this.calendarElement) {
1682
+ this.createContentHeader();
1683
+ this.createContentBody();
1684
+ }
1685
+ if (this.getModuleName() === 'calendar') {
1686
+ const l10nLocale: object = { today: 'Today' };
1687
+ this.l10 = new L10n(this.getModuleName(), l10nLocale, this.locale);
1688
+ }
1689
+ this.l10.setLocale(this.locale);
1690
+ if (this.showTodayButton) {
1691
+ this.updateFooter();
1692
+ }
1693
+ break;
1694
+ case 'showTodayButton':
1695
+ if (newProp.showTodayButton) {
1696
+ this.createContentFooter();
1697
+ } else {
1698
+ if (!isNullOrUndefined(this.todayElement) && !isNullOrUndefined(this.footer)) {
1699
+ detach(this.todayElement);
1700
+ detach(this.footer);
1701
+ this.todayElement = this.footer = undefined;
1702
+ }
1703
+ }
1704
+ this.setProperties({ showTodayButton: newProp.showTodayButton }, true);
1705
+ break;
1706
+ }
1707
+ }
1708
+ }
1709
+ /**
1710
+ * values property updated with considered disabled dates of the calendar.
1711
+ *
1712
+ * @param {boolean} multiSelection - Specifies whether multiple date selection is enabled.
1713
+ * @param {Date[]} values - Specifies the dates to validate.
1714
+ * @returns {void}
1715
+ */
1716
+ protected validateValues(multiSelection?: boolean, values?: Date[]): void {
1717
+ if (multiSelection && !isNullOrUndefined(values) && values.length > 0) {
1718
+ const copyValues: Date[] = this.copyValues(values);
1719
+ for (let skipIndex: number = 0; skipIndex < copyValues.length; skipIndex++) {
1720
+ const tempValue: Date = copyValues[skipIndex as number];
1721
+ const type: string = (this.calendarMode === 'Gregorian') ? 'gregorian' : 'islamic';
1722
+ let tempValueFormat: object;
1723
+ let tempValueString: string;
1724
+ let tempValueDate: object;
1725
+ if (this.calendarMode === 'Gregorian') {
1726
+ tempValueFormat = { type: 'date', skeleton: 'yMd' };
1727
+ tempValueString = this.globalize.formatDate(tempValue, tempValueFormat);
1728
+ tempValueDate = this.globalize.parseDate(tempValueString, tempValueFormat);
1729
+ } else {
1730
+ tempValueFormat = { type: 'date', skeleton: 'yMd', calendar: 'islamic' };
1731
+ tempValueString = this.globalize.formatDate(tempValue, tempValueFormat);
1732
+ tempValueDate = this.globalize.parseDate(tempValueString, tempValueFormat);
1733
+ }
1734
+ const minFormatOption: object = { type: 'date', skeleton: 'yMd', calendar: type };
1735
+ const minStringValue: string = this.globalize.formatDate(this.min, minFormatOption);
1736
+ const minString: string = minStringValue;
1737
+ const maxFormatOption: object = { type: 'date', skeleton: 'yMd', calendar: type };
1738
+ const maxStringValue: string = this.globalize.formatDate(this.max, maxFormatOption);
1739
+ const maxString: string = maxStringValue;
1740
+ const minDate: object = this.globalize.parseDate(minString, minFormatOption);
1741
+ const maxDate: object = this.globalize.parseDate(maxString, maxFormatOption);
1742
+
1743
+ if (+tempValueDate < +minDate || +tempValueDate > +maxDate) {
1744
+ copyValues.splice(skipIndex, 1);
1745
+ skipIndex = -1;
1746
+ }
1747
+ }
1748
+ this.setProperties({ values: copyValues }, true);
1749
+ }
1750
+ }
1751
+ protected setValueUpdate(): void {
1752
+ if (!isNullOrUndefined(this.tableBodyElement)) {
1753
+ detach(this.tableBodyElement);
1754
+ this.setProperties({ start: this.currentView() }, true);
1755
+ this.createContentBody();
1756
+ }
1757
+ }
1758
+ protected copyValues(values: Date[]): Date[] {
1759
+ const copyValues: Date[] = [];
1760
+ if (!isNullOrUndefined(values) && values.length > 0) {
1761
+ for (let index: number = 0; index < values.length; index++) {
1762
+ copyValues.push(new Date(+values[index as number]));
1763
+ }
1764
+ }
1765
+ return copyValues;
1766
+ }
1767
+ protected titleUpdate(date: Date, view: string): void {
1768
+ const globalize: Internationalization = new Internationalization(this.locale);
1769
+ let dayFormatOptions: string;
1770
+ let monthFormatOptions: string;
1771
+ const type: string = (this.calendarMode === 'Gregorian') ? 'gregorian' : 'islamic';
1772
+ if (this.calendarMode === 'Gregorian') {
1773
+ dayFormatOptions = globalize.formatDate(date, { type: 'dateTime', skeleton: 'yMMMM', calendar: type });
1774
+ monthFormatOptions = globalize.formatDate(date, {
1775
+ format: null, type: 'dateTime', skeleton: 'y', calendar: type
1776
+ });
1777
+ } else {
1778
+
1779
+ dayFormatOptions = globalize.formatDate(date, { type: 'dateTime', format: 'MMMM y', calendar: type });
1780
+ monthFormatOptions = globalize.formatDate(date, { type: 'dateTime', format: 'y', calendar: type });
1781
+ }
1782
+ switch (view) {
1783
+ case 'days':
1784
+ this.headerTitleElement.textContent = this.toCapitalize(dayFormatOptions);
1785
+ break;
1786
+ case 'months':
1787
+ this.headerTitleElement.textContent = monthFormatOptions;
1788
+ }
1789
+ }
1790
+ protected setActiveDescendant(): string {
1791
+ let id: string;
1792
+ const focusedEle: Element = this.tableBodyElement.querySelector('tr td.e-focused-date');
1793
+ const selectedEle: Element = this.tableBodyElement.querySelector('tr td.e-selected');
1794
+ const type: string = (this.calendarMode === 'Gregorian') ? 'gregorian' : 'islamic';
1795
+ let title: string;
1796
+ const view: string = this.currentView();
1797
+ if (view === 'Month') {
1798
+ title = this.globalize.formatDate(this.currentDate, { type: 'date', skeleton: 'full', calendar: type });
1799
+ } else if (view === 'Year') {
1800
+ if (type !== 'islamic') {
1801
+ title = this.globalize.formatDate(this.currentDate, { type: 'date', skeleton: 'yMMMM', calendar: type });
1802
+ } else {
1803
+ title = this.globalize.formatDate(this.currentDate, { type: 'date', skeleton: 'GyMMM', calendar: type });
1804
+ }
1805
+ } else {
1806
+ title = this.globalize.formatDate(this.currentDate, {
1807
+ format: null, type: 'date', skeleton: 'y', calendar: type
1808
+ });
1809
+ }
1810
+ if (selectedEle || focusedEle) {
1811
+ if (!isNullOrUndefined(selectedEle)) {
1812
+ selectedEle.setAttribute('aria-selected', 'true');
1813
+ }
1814
+ (focusedEle || selectedEle).setAttribute('aria-label', title);
1815
+ id = (focusedEle || selectedEle).getAttribute('id');
1816
+
1817
+ }
1818
+ return id;
1819
+ }
1820
+ protected iconHandler(): void {
1821
+ new Date(this.checkValue(this.currentDate)).setDate(1);
1822
+ switch (this.currentView()) {
1823
+ case 'Month':
1824
+ this.previousIconHandler(this.compareMonth(new Date(this.checkValue(this.currentDate)), this.min) < 1);
1825
+ this.nextIconHandler(this.compareMonth(new Date(this.checkValue(this.currentDate)), this.max) > -1);
1826
+ break;
1827
+ case 'Year':
1828
+ this.previousIconHandler(this.compareYear(new Date(this.checkValue(this.currentDate)), this.min) < 1);
1829
+ this.nextIconHandler(this.compareYear(new Date(this.checkValue(this.currentDate)), this.max) > -1);
1830
+ break;
1831
+ case 'Decade':
1832
+ this.previousIconHandler(this.compareDecade(new Date(this.checkValue(this.currentDate)), this.min) < 1);
1833
+ this.nextIconHandler(this.compareDecade(new Date(this.checkValue(this.currentDate)), this.max) > -1);
1834
+ }
1835
+ }
1836
+ /**
1837
+ * Destroys the widget.
1838
+ *
1839
+ * @returns {void}
1840
+ */
1841
+ public destroy(): void {
1842
+ if (this.getModuleName() === 'calendar' && this.element) {
1843
+ removeClass([this.element], [ROOT]);
1844
+ } else {
1845
+ if (this.calendarElement && this.element) {
1846
+ removeClass([this.element], [ROOT]);
1847
+ }
1848
+ }
1849
+ if (this.getModuleName() === 'calendar' && this.element) {
1850
+ if (!isNullOrUndefined(this.headerTitleElement)) {
1851
+ EventHandler.remove(this.headerTitleElement, 'click', this.navigateTitle);
1852
+ }
1853
+ if (this.todayElement) {
1854
+ EventHandler.remove(this.todayElement, 'click', this.todayButtonClick);
1855
+ }
1856
+ this.previousIconHandler(true);
1857
+ this.nextIconHandler(true);
1858
+ this.keyboardModule.destroy();
1859
+ this.element.removeAttribute('data-role');
1860
+ if (!isNullOrUndefined(this.calendarEleCopy.getAttribute('tabindex'))) {
1861
+ this.element.setAttribute('tabindex', this.tabIndex);
1862
+ } else {
1863
+ this.element.removeAttribute('tabindex');
1864
+ }
1865
+ }
1866
+ if (this.element) {
1867
+ this.element.innerHTML = '';
1868
+ }
1869
+ this.todayElement = null;
1870
+ this.tableBodyElement = null;
1871
+ this.todayButtonEvent = null;
1872
+ this.renderDayCellArgs = null;
1873
+ this.headerElement = null;
1874
+ this.nextIcon = null;
1875
+ this.table = null;
1876
+ this.tableHeadElement = null;
1877
+ this.previousIcon = null;
1878
+ this.headerTitleElement = null;
1879
+ this.footer = null;
1880
+ this.contentElement = null;
1881
+ super.destroy();
1882
+ }
1883
+ protected title(e?: Event): void {
1884
+ let currentView: number = this.getViewNumber(this.currentView());
1885
+ this.effect = ZOOMIN;
1886
+ this.switchView(++currentView, e);
1887
+ }
1888
+ protected getViewNumber(stringVal: string): number {
1889
+ if (stringVal === 'Month') {
1890
+ return 0;
1891
+ } else if (stringVal === 'Year') {
1892
+ return 1;
1893
+ } else {
1894
+ return 2;
1895
+ }
1896
+ }
1897
+ protected navigateTitle(e?: Event): void {
1898
+ e.preventDefault();
1899
+ this.title(e);
1900
+ }
1901
+ protected previous(): void {
1902
+ this.effect = '';
1903
+ const currentView: number = this.getViewNumber(this.currentView());
1904
+ switch (this.currentView()) {
1905
+ case 'Month':
1906
+ this.addMonths(this.currentDate, -1);
1907
+ this.switchView(currentView);
1908
+ break;
1909
+ case 'Year':
1910
+ this.addYears(this.currentDate, -1);
1911
+ this.switchView(currentView);
1912
+ break;
1913
+ case 'Decade':
1914
+ this.addYears(this.currentDate, -10);
1915
+ this.switchView(currentView);
1916
+ break;
1917
+ }
1918
+ }
1919
+ protected navigatePrevious(e: MouseEvent | KeyboardEvent | SwipeEventArgs): void {
1920
+ !Browser.isDevice && (e as MouseEvent | KeyboardEvent).preventDefault();
1921
+ if (this.calendarMode === 'Gregorian') {
1922
+ this.previous();
1923
+ } else {
1924
+ this.islamicModule.islamicPrevious();
1925
+ }
1926
+
1927
+ this.triggerNavigate(e);
1928
+ }
1929
+ protected next(): void {
1930
+ this.effect = '';
1931
+ const currentView: number = this.getViewNumber(this.currentView());
1932
+ switch (this.currentView()) {
1933
+ case 'Month':
1934
+ this.addMonths(this.currentDate, 1);
1935
+ this.switchView(currentView);
1936
+ break;
1937
+ case 'Year':
1938
+ this.addYears(this.currentDate, 1);
1939
+ this.switchView(currentView);
1940
+ break;
1941
+ case 'Decade':
1942
+ this.addYears(this.currentDate, 10);
1943
+ this.switchView(currentView);
1944
+ break;
1945
+ }
1946
+ }
1947
+ protected navigateNext(eve: MouseEvent | KeyboardEvent | SwipeEventArgs): void {
1948
+ !Browser.isDevice && (eve as MouseEvent | KeyboardEvent).preventDefault();
1949
+ if (this.calendarMode === 'Gregorian') {
1950
+ this.next();
1951
+ } else {
1952
+ this.islamicModule.islamicNext();
1953
+ }
1954
+ this.triggerNavigate(eve);
1955
+ }
1956
+ /**
1957
+ * This method is used to navigate to the month/year/decade view of the Calendar.
1958
+ *
1959
+ * @param {string} view - Specifies the view of the Calendar.
1960
+ * @param {Date} date - Specifies the focused date in a view.
1961
+ * @param {boolean} isCustomDate - Specifies whether the calendar is rendered with custom today date or not.
1962
+ * @returns {void}
1963
+ */
1964
+ public navigateTo(view: CalendarView, date: Date, isCustomDate?: boolean): void {
1965
+ if (+date >= +this.min && +date <= +this.max) {
1966
+ this.currentDate = date;
1967
+ }
1968
+ if (+date <= +this.min) {
1969
+ this.currentDate = new Date(this.checkValue(this.min));
1970
+ }
1971
+ if (+date >= +this.max) {
1972
+ this.currentDate = new Date(this.checkValue(this.max));
1973
+ }
1974
+ if ((this.getViewNumber(this.depth) >= this.getViewNumber(view))) {
1975
+ if ((this.getViewNumber(this.depth) <= this.getViewNumber(this.start))
1976
+ || this.getViewNumber(this.depth) === this.getViewNumber(view)) {
1977
+ view = this.depth;
1978
+ }
1979
+ }
1980
+ this.switchView(this.getViewNumber(view), null, null, isCustomDate);
1981
+ }
1982
+ /* eslint-disable valid-jsdoc, jsdoc/require-returns-description */
1983
+ /**
1984
+ * Gets the current view of the Calendar.
1985
+ *
1986
+ * @returns {string}
1987
+ */
1988
+ public currentView(): string {
1989
+ if (!isNullOrUndefined(this.contentElement) && this.contentElement.classList.contains(YEAR)) {
1990
+ return 'Year';
1991
+ } else if (!isNullOrUndefined(this.contentElement) && this.contentElement.classList.contains(DECADE)) {
1992
+ return 'Decade';
1993
+ } else {
1994
+ return 'Month';
1995
+ }
1996
+ }
1997
+ /* eslint-enable valid-jsdoc, jsdoc/require-returns-description */
1998
+ protected getDateVal(date: Date, value: Date): boolean {
1999
+ return (!isNullOrUndefined(value) && date.getDate() === (value).getDate()
2000
+ && date.getMonth() === (value).getMonth() && date.getFullYear() === (value).getFullYear());
2001
+ }
2002
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2003
+ protected getCultureObjects(ld: Object, c: string): Object {
2004
+ const gregorianFormat: string = !isNullOrUndefined(this.dayHeaderFormat) ? '.dates.calendars.gregorian.days.format.' + this.dayHeaderFormat.toLowerCase() : null;
2005
+ const islamicFormat: string = !isNullOrUndefined(this.dayHeaderFormat) ? '.dates.calendars.islamic.days.format.' + this.dayHeaderFormat.toLowerCase() : null;
2006
+ const mainVal: string = 'main.';
2007
+ if (this.calendarMode === 'Gregorian') {
2008
+ return getValue(mainVal + '' + this.locale + gregorianFormat, ld);
2009
+ } else {
2010
+ return getValue('main.' + '' + this.locale + islamicFormat, ld);
2011
+ }
2012
+ }
2013
+ protected getWeek(d: Date): number {
2014
+ const currentDate: number = new Date(this.checkValue(d)).valueOf();
2015
+ const date: number = new Date(d.getFullYear(), 0, 1).valueOf();
2016
+ return Math.ceil((((currentDate - date) + dayMilliSeconds) / dayMilliSeconds) / 7);
2017
+ }
2018
+ protected setStartDate(date: Date, time: number): void {
2019
+ const tzOffset: number = date.getTimezoneOffset();
2020
+ const d: Date = new Date(date.getTime() + time);
2021
+ const tzOffsetDiff: number = d.getTimezoneOffset() - tzOffset;
2022
+ date.setTime(d.getTime() + tzOffsetDiff * minutesMilliSeconds);
2023
+ }
2024
+ protected addMonths(date: Date, i: number): void {
2025
+ if (this.calendarMode === 'Gregorian') {
2026
+ const day: number = date.getDate();
2027
+ date.setDate(1);
2028
+ date.setMonth(date.getMonth() + i);
2029
+ date.setDate(Math.min(day, this.getMaxDays(date)));
2030
+ } else {
2031
+ const islamicDate: IslamicDateArgs = this.islamicModule.getIslamicDate(date);
2032
+ this.currentDate = this.islamicModule.toGregorian(islamicDate.year, (islamicDate.month) + i, 1);
2033
+ }
2034
+ }
2035
+ protected addYears(date: Date, i: number): void {
2036
+ if (this.calendarMode === 'Gregorian') {
2037
+ const day: number = date.getDate();
2038
+ date.setDate(1);
2039
+ date.setFullYear(date.getFullYear() + i);
2040
+ date.setDate(Math.min(day, this.getMaxDays(date)));
2041
+ } else {
2042
+ const islamicDate: IslamicDateArgs = this.islamicModule.getIslamicDate(date);
2043
+ this.currentDate = this.islamicModule.toGregorian(islamicDate.year + i, (islamicDate.month), 1);
2044
+ }
2045
+ }
2046
+ protected getIdValue(e: MouseEvent | TouchEvent | KeyboardEvent, element: Element): Date {
2047
+ let eve: Element;
2048
+ if (e) {
2049
+ eve = <Element>e.currentTarget;
2050
+ } else {
2051
+ eve = element;
2052
+ }
2053
+ const type: string = (this.calendarMode === 'Gregorian') ? 'gregorian' : 'islamic';
2054
+ const dateFormatOptions: object = { type: 'dateTime', skeleton: 'full', calendar: type };
2055
+ // eslint-disable-next-line radix
2056
+ const dateString: string = this.globalize.formatDate(new Date(parseInt('' + eve.getAttribute('id'), 0)), dateFormatOptions);
2057
+ const date: Date = this.globalize.parseDate(dateString, dateFormatOptions);
2058
+ const value: number = date.valueOf() - date.valueOf() % 1000;
2059
+ return new Date(value);
2060
+ //return this.globalize.parseDate(dateString, dateFormatOptions);
2061
+ }
2062
+ protected adjustLongHeaderSize(): void {
2063
+ removeClass([this.element], DAYHEADERLONG);
2064
+ if (this.dayHeaderFormat === 'Wide') {
2065
+ addClass([this.getModuleName() === 'calendar' ? this.element : this.calendarElement], DAYHEADERLONG);
2066
+ }
2067
+ }
2068
+ protected selectDate(e: MouseEvent | KeyboardEventArgs, date: Date, node: Element, multiSelection?: boolean, values?: Date[]): void {
2069
+ const element: Element = node || <Element>e.currentTarget;
2070
+ this.isDateSelected = false;
2071
+ if (this.currentView() === 'Decade') {
2072
+ this.setDateDecade(this.currentDate, date.getFullYear());
2073
+ } else if (this.currentView() === 'Year') {
2074
+ this.setDateYear(this.currentDate, date);
2075
+ } else {
2076
+ if (multiSelection && !this.checkPresentDate(date, values)) {
2077
+ const copyValues: Date[] = this.copyValues(values);
2078
+ if (!isNullOrUndefined(values) && copyValues.length > 0) {
2079
+ copyValues.push(new Date(this.checkValue(date)));
2080
+ this.setProperties({ values: copyValues }, true);
2081
+ this.setProperties({ value: values[values.length - 1] }, true);
2082
+ } else {
2083
+ this.setProperties({ values: [new Date(this.checkValue(date))] }, true);
2084
+ }
2085
+ } else {
2086
+ this.setProperties({ value: new Date(this.checkValue(date)) }, true);
2087
+ }
2088
+ this.currentDate = new Date(this.checkValue(date));
2089
+ }
2090
+ let tableBodyElement: Element = closest(element, '.' + ROOT);
2091
+ if (isNullOrUndefined(tableBodyElement)) {
2092
+ tableBodyElement = this.tableBodyElement;
2093
+ }
2094
+ if (!multiSelection && !isNullOrUndefined(tableBodyElement.querySelector('.' + SELECTED))) {
2095
+ removeClass([tableBodyElement.querySelector('.' + SELECTED)], SELECTED);
2096
+ }
2097
+ if (!multiSelection && !isNullOrUndefined(tableBodyElement.querySelector('.' + FOCUSEDDATE))) {
2098
+ removeClass([tableBodyElement.querySelector('.' + FOCUSEDDATE)], FOCUSEDDATE);
2099
+ }
2100
+ if (!multiSelection && !isNullOrUndefined(tableBodyElement.querySelector('.' + FOCUSEDCELL))) {
2101
+ removeClass([tableBodyElement.querySelector('.' + FOCUSEDCELL)], FOCUSEDCELL);
2102
+ }
2103
+ if (multiSelection) {
2104
+ const copyValues: Date[] = this.copyValues(values);
2105
+ const collection: Element[] = Array.prototype.slice.call(this.tableBodyElement.querySelectorAll('td'));
2106
+ for (let index: number = 0; index < collection.length; index++) {
2107
+ const tempElement: Element = tableBodyElement.querySelectorAll('td' + '.' + FOCUSEDDATE)[0];
2108
+ const selectedElement: Element = tableBodyElement.querySelectorAll('td' + '.' + SELECTED)[0];
2109
+ if (collection[index as number] === tempElement) {
2110
+ removeClass([collection[index as number]], FOCUSEDDATE);
2111
+ }
2112
+ if (collection[index as number] === selectedElement &&
2113
+ !this.checkPresentDate(new Date(parseInt(selectedElement.getAttribute('id').split('_')[0], 10)), values)) {
2114
+ removeClass([collection[index as number]], SELECTED);
2115
+ }
2116
+ }
2117
+ if (element.classList.contains(SELECTED)) {
2118
+ removeClass([element], SELECTED);
2119
+ for (let i: number = 0; i < copyValues.length; i++) {
2120
+ const type: string = (this.calendarMode === 'Gregorian') ? 'gregorian' : 'islamic';
2121
+ const formatOptions: object = { format: null, type: 'date', skeleton: 'short', calendar: type };
2122
+ const localDateString: string = this.globalize.formatDate(date, formatOptions);
2123
+ const tempDateString: string = this.globalize.formatDate(copyValues[i as number], formatOptions);
2124
+ if (localDateString === tempDateString) {
2125
+ const index: number = copyValues.indexOf(copyValues[i as number]);
2126
+ copyValues.splice(index, 1);
2127
+ addClass([element], FOCUSEDDATE);
2128
+ }
2129
+ }
2130
+ this.setProperties({ values: copyValues }, true);
2131
+ } else {
2132
+ addClass([element], SELECTED);
2133
+ }
2134
+ } else {
2135
+ addClass([element], SELECTED);
2136
+ }
2137
+ this.isDateSelected = true;
2138
+ }
2139
+ protected checkPresentDate(dates: Date, values: Date[]): boolean {
2140
+ let previousValue: boolean = false;
2141
+ if (!isNullOrUndefined(values)) {
2142
+ for (let checkPrevious: number = 0; checkPrevious < values.length; checkPrevious++) {
2143
+ const type: string = (this.calendarMode === 'Gregorian') ? 'gregorian' : 'islamic';
2144
+ const localDateString: string = this.globalize.formatDate(dates, {
2145
+ format: null, type: 'date', skeleton: 'short', calendar: type
2146
+ });
2147
+ const tempDateString: string = this.globalize.formatDate(values[checkPrevious as number], {
2148
+ format: null, type: 'date', skeleton: 'short', calendar: type
2149
+ });
2150
+ if (localDateString === tempDateString) {
2151
+ previousValue = true;
2152
+ }
2153
+ }
2154
+ }
2155
+ return previousValue;
2156
+ }
2157
+
2158
+ protected setAriaActiveDescendant(): void {
2159
+ attributes(this.table, {
2160
+ 'aria-activedescendant': '' + this.setActiveDescendant()
2161
+ });
2162
+ }
2163
+ protected previousIconHandler(disabled: boolean): void {
2164
+ if (disabled) {
2165
+ if (!isNullOrUndefined(this.previousIcon)) {
2166
+ EventHandler.remove(this.previousIcon, 'click', this.navigatePreviousHandler);
2167
+
2168
+ addClass([this.previousIcon], '' + DISABLED);
2169
+ addClass([this.previousIcon], '' + OVERLAY);
2170
+ this.previousIcon.setAttribute('aria-disabled', 'true');
2171
+ }
2172
+ } else {
2173
+ EventHandler.add(this.previousIcon, 'click', this.navigatePreviousHandler);
2174
+ removeClass([this.previousIcon], '' + DISABLED);
2175
+ removeClass([this.previousIcon], '' + OVERLAY);
2176
+ this.previousIcon.setAttribute('aria-disabled', 'false');
2177
+ }
2178
+ }
2179
+ protected renderDayCellEvent(args: RenderDayCellEventArgs): void {
2180
+ extend(this.renderDayCellArgs, { name: 'renderDayCell' });
2181
+ this.trigger('renderDayCell', args);
2182
+ }
2183
+ protected navigatedEvent(eve: MouseEvent | KeyboardEvent| SwipeEventArgs): void {
2184
+ extend(this.navigatedArgs, { name: 'navigated', event: eve });
2185
+ this.trigger('navigated', this.navigatedArgs);
2186
+ }
2187
+ protected triggerNavigate(event: MouseEvent | KeyboardEvent | SwipeEventArgs): void {
2188
+ this.navigatedArgs = { view: this.currentView(), date: this.currentDate };
2189
+ this.navigatedEvent(event);
2190
+ }
2191
+
2192
+ protected nextIconHandler(disabled: boolean): void {
2193
+ if (disabled) {
2194
+ if (!isNullOrUndefined(this.previousIcon)) {
2195
+ EventHandler.remove(this.nextIcon, 'click', this.navigateNextHandler);
2196
+ addClass([this.nextIcon], DISABLED);
2197
+ addClass([this.nextIcon], OVERLAY);
2198
+ this.nextIcon.setAttribute('aria-disabled', 'true');
2199
+ }
2200
+ } else {
2201
+ EventHandler.add(this.nextIcon, 'click', this.navigateNextHandler);
2202
+ removeClass([this.nextIcon], DISABLED);
2203
+ removeClass([this.nextIcon], OVERLAY);
2204
+ this.nextIcon.setAttribute('aria-disabled', 'false');
2205
+ }
2206
+ }
2207
+ protected compare(startDate: Date, endDate: Date, modifier: number): number {
2208
+ let start: number = endDate.getFullYear();
2209
+ let end: number;
2210
+ let result: number;
2211
+ end = start;
2212
+ result = 0;
2213
+ if (modifier) {
2214
+ start = start - start % modifier;
2215
+ end = start - start % modifier + modifier - 1;
2216
+ }
2217
+ if (startDate.getFullYear() > end) {
2218
+ result = 1;
2219
+ } else if (startDate.getFullYear() < start) {
2220
+ result = -1;
2221
+ }
2222
+ return result;
2223
+ }
2224
+ protected isMinMaxRange(date: Date): boolean {
2225
+ return +date >= +this.min && +date <= +this.max;
2226
+ }
2227
+
2228
+ protected isMonthYearRange(date: Date): boolean {
2229
+ if (this.calendarMode === 'Gregorian') {
2230
+ return date.getMonth() >= this.min.getMonth()
2231
+ && date.getFullYear() >= this.min.getFullYear()
2232
+ && date.getMonth() <= this.max.getMonth()
2233
+ && date.getFullYear() <= this.max.getFullYear();
2234
+
2235
+ } else {
2236
+ const islamicDate: IslamicObject = this.islamicModule.getIslamicDate(date);
2237
+ return (islamicDate.month >= (this.islamicModule.getIslamicDate(new Date(1941, 12, 18))).month)
2238
+ && islamicDate.year >= (<IslamicObject>(this.islamicModule.getIslamicDate(new Date(1941, 12, 18)))).year
2239
+ && islamicDate.month <= (<IslamicObject>(this.islamicModule.getIslamicDate(new Date(2068, 2, 4)))).month
2240
+ && islamicDate.year <= (<IslamicObject>(this.islamicModule.getIslamicDate(new Date(2068, 2, 4)))).year;
2241
+ }
2242
+ }
2243
+
2244
+ protected compareYear(start: Date, end: Date): number {
2245
+ return this.compare(start, end, 0);
2246
+ }
2247
+ protected compareDecade(start: Date, end: Date): number {
2248
+ return this.compare(start, end, 10);
2249
+ }
2250
+ protected shiftArray(array: string[], i: number): string[] {
2251
+ return array.slice(i).concat(array.slice(0, i));
2252
+ }
2253
+ protected addDay(date: Date, i: number, e: KeyboardEvent, max: Date, min: Date): void {
2254
+ let column: number = i;
2255
+ const value: Date = new Date(+date);
2256
+ if (!isNullOrUndefined(this.tableBodyElement) && !isNullOrUndefined(e)) {
2257
+ while (this.findNextTD(new Date(+date), column, max, min)) {
2258
+ column += i;
2259
+ }
2260
+ const rangeValue: Date = new Date(value.setDate(value.getDate() + column));
2261
+ column = (+rangeValue > +max || +rangeValue < +min) ? column === i ? i - i : i : column;
2262
+ }
2263
+ date.setDate(date.getDate() + column);
2264
+ }
2265
+ protected findNextTD(date: Date, column: number, max: Date, min: Date): boolean {
2266
+ const value: Date = new Date(date.setDate(date.getDate() + column));
2267
+ let collection: Element[] = [];
2268
+ let isDisabled: boolean = false;
2269
+ if ((!isNullOrUndefined(value) && value.getMonth()) === (!isNullOrUndefined(this.currentDate) && this.currentDate.getMonth())) {
2270
+ let tdEles: Element[];
2271
+ if (this.calendarMode === 'Gregorian') {
2272
+ tdEles = this.renderDays(value);
2273
+ } else {
2274
+ tdEles = this.islamicModule.islamicRenderDays(this.currentDate, value);
2275
+ }
2276
+
2277
+ collection = tdEles.filter((element: Element) => {
2278
+ return element.classList.contains(DISABLED);
2279
+ });
2280
+ } else {
2281
+ collection = <NodeListOf<HTMLTableDataCellElement> & Element[]>this.tableBodyElement.querySelectorAll('td.' + DISABLED);
2282
+ }
2283
+ if (+value <= (+(max)) && +value >= (+(min))) {
2284
+ if (collection.length) {
2285
+ for (let i: number = 0; i < collection.length; i++) {
2286
+ // eslint-disable-next-line radix
2287
+ isDisabled = (+value === +new Date(parseInt(collection[i as number].id, 0))) ? true : false;
2288
+ if (isDisabled) {
2289
+ break;
2290
+ }
2291
+ }
2292
+ }
2293
+ }
2294
+ return isDisabled;
2295
+ }
2296
+ protected getMaxDays(d: Date): number {
2297
+ let date: number;
2298
+ const tmpDate: Date = new Date(this.checkValue(d));
2299
+ date = 28;
2300
+ const month: number = tmpDate.getMonth();
2301
+ while (tmpDate.getMonth() === month) {
2302
+ ++date;
2303
+ tmpDate.setDate(date);
2304
+ }
2305
+ return date - 1;
2306
+ }
2307
+ protected setDateDecade(date: Date, year: number): void {
2308
+ date.setFullYear(year);
2309
+ this.setProperties({ value: new Date(this.checkValue(date)) }, true);
2310
+ }
2311
+ protected setDateYear(date: Date, value: Date): void {
2312
+ date.setFullYear(value.getFullYear(), value.getMonth(), date.getDate());
2313
+ if (value.getMonth() !== date.getMonth()) {
2314
+ date.setDate(0);
2315
+ this.currentDate = new Date(this.checkValue(value));
2316
+ }
2317
+ this.setProperties({ value: new Date(this.checkValue(date)) }, true);
2318
+ }
2319
+ protected compareMonth(start: Date, end: Date): number {
2320
+ let result: number;
2321
+ if (start.getFullYear() > end.getFullYear()) {
2322
+ result = 1;
2323
+ } else if (start.getFullYear() < end.getFullYear()) {
2324
+ result = -1;
2325
+ } else {
2326
+ result = start.getMonth() === end.getMonth() ? 0 : start.getMonth() > end.getMonth() ? 1 : -1;
2327
+ }
2328
+ return result;
2329
+ }
2330
+ protected checkValue(inValue: string | Date | number): string {
2331
+ if (inValue instanceof Date) {
2332
+ return (inValue.toUTCString());
2333
+ } else {
2334
+ return ('' + inValue);
2335
+ }
2336
+ }
2337
+ protected checkView(): void {
2338
+ if (this.start !== 'Decade' && this.start !== 'Year') {
2339
+ this.setProperties({ start: 'Month' }, true);
2340
+ }
2341
+ if (this.depth !== 'Decade' && this.depth !== 'Year') {
2342
+ this.setProperties({ depth: 'Month' }, true);
2343
+ }
2344
+ if (this.getViewNumber(this.depth) > this.getViewNumber(this.start)) {
2345
+ this.setProperties({ depth: 'Month' }, true);
2346
+ }
2347
+ }
2348
+ protected getDate(date: Date, timezone: string): Date {
2349
+ if (timezone) {
2350
+ date = new Date(date.toLocaleString('en-US', { timeZone: timezone }));
2351
+ }
2352
+ return date;
2353
+ }
2354
+ }
2355
+
2356
+ /**
2357
+ * Represents the Calendar component that allows the user to select a date.
2358
+ * ```html
2359
+ * <div id="calendar"/>
2360
+ * ```
2361
+ * ```typescript
2362
+ * <script>
2363
+ * var calendarObj = new Calendar({ value: new Date() });
2364
+ * calendarObj.appendTo("#calendar");
2365
+ * </script>
2366
+ * ```
2367
+ */
2368
+
2369
+ @NotifyPropertyChanges
2370
+ export class Calendar extends CalendarBase {
2371
+ protected changedArgs: ChangedEventArgs;
2372
+ protected changeHandler: Function;
2373
+
2374
+ /**
2375
+ * Gets or sets the selected date of the Calendar.
2376
+ *
2377
+ * @default null
2378
+ * @isGenericType true
2379
+ * @deprecated
2380
+ */
2381
+ @Property(null)
2382
+ public value: Date;
2383
+
2384
+ /**
2385
+ * Gets or sets multiple selected dates of the calendar.
2386
+ * {% codeBlock src='calendar/values/index.md' %}{% endcodeBlock %}
2387
+ *
2388
+ * @default null
2389
+ */
2390
+ @Property(null)
2391
+ public values: Date[];
2392
+
2393
+ /**
2394
+ * Specifies the option to enable the multiple dates selection of the calendar.
2395
+ *
2396
+ * @default false
2397
+ */
2398
+ @Property(false)
2399
+ public isMultiSelection: boolean;
2400
+
2401
+ /**
2402
+ * Triggers when the Calendar value is changed.
2403
+ *
2404
+ * @event change
2405
+ */
2406
+ @Event()
2407
+ public change: EmitType<ChangedEventArgs>;
2408
+ /**
2409
+ * Initialized new instance of Calendar Class.
2410
+ * Constructor for creating the widget
2411
+ *
2412
+ * @param {CalendarModel} options - Specifies the Calendar model.
2413
+ * @param {string | HTMLElement} element - Specifies the element to render as component.
2414
+ * @private
2415
+ */
2416
+ public constructor(options?: CalendarModel, element?: string | HTMLElement) {
2417
+ super(options, element);
2418
+ }
2419
+ /**
2420
+ * To Initialize the control rendering.
2421
+ *
2422
+ * @returns {void}
2423
+ * @private
2424
+ */
2425
+ protected render(): void {
2426
+ if (this.calendarMode === 'Islamic' && this.islamicModule === undefined) {
2427
+ throwError('Requires the injectable Islamic modules to render Calendar in Islamic mode');
2428
+ }
2429
+ if (this.isMultiSelection && typeof this.values === 'object' && !isNullOrUndefined(this.values) && this.values.length > 0) {
2430
+ const tempValues: number[] = [];
2431
+ const copyValues: Date[] = [];
2432
+ for (let limit: number = 0; limit < this.values.length; limit++) {
2433
+ if (tempValues.indexOf(+this.values[limit as number]) === -1) {
2434
+ tempValues.push(+this.values[limit as number]);
2435
+ copyValues.push(this.values[limit as number]);
2436
+ }
2437
+ }
2438
+ this.setProperties({ values: copyValues }, true);
2439
+ for (let index: number = 0; index < this.values.length; index++) {
2440
+ if (!this.checkDateValue(this.values[index as number])) {
2441
+ if (typeof (this.values[index as number]) === 'string' && this.checkDateValue(new Date(this.checkValue(this.values[index as number])))) {
2442
+ const copyDate: Date = new Date(this.checkValue(this.values[index as number]));
2443
+ this.values.splice(index, 1);
2444
+ this.values.splice(index, 0, copyDate);
2445
+ } else {
2446
+ this.values.splice(index, 1);
2447
+ }
2448
+ }
2449
+ }
2450
+ this.setProperties({ value: this.values[this.values.length - 1] }, true);
2451
+ this.previousValues = this.values.length;
2452
+ }
2453
+ this.validateDate();
2454
+ this.minMaxUpdate();
2455
+ if (this.getModuleName() === 'calendar') {
2456
+ this.setEnable(this.enabled);
2457
+ this.setClass(this.cssClass);
2458
+ }
2459
+ super.render();
2460
+ if (this.getModuleName() === 'calendar') {
2461
+ const form: Element = closest(this.element, 'form');
2462
+ if (form) {
2463
+ EventHandler.add(form, 'reset', this.formResetHandler.bind(this));
2464
+ }
2465
+ this.setTimeZone(this.serverTimezoneOffset);
2466
+ }
2467
+ this.renderComplete();
2468
+ }
2469
+ protected setEnable(enable: boolean): void {
2470
+ if (!enable) {
2471
+ addClass([this.element], DISABLED);
2472
+ } else {
2473
+ removeClass([this.element], DISABLED);
2474
+ }
2475
+ }
2476
+ protected setClass(newCssClass: string, oldCssClass?: string): void {
2477
+ if (!isNullOrUndefined(oldCssClass)) {
2478
+ oldCssClass = (oldCssClass.replace(/\s+/g, ' ')).trim();
2479
+ }
2480
+ if (!isNullOrUndefined(newCssClass)) {
2481
+ newCssClass = (newCssClass.replace(/\s+/g, ' ')).trim();
2482
+ }
2483
+ if (!isNullOrUndefined(oldCssClass) && oldCssClass !== '') {
2484
+ removeClass([this.element], oldCssClass.split(' '));
2485
+ }
2486
+ if (!isNullOrUndefined(newCssClass)) {
2487
+ addClass([this.element], newCssClass.split(' '));
2488
+ }
2489
+ }
2490
+ protected isDayLightSaving(): boolean {
2491
+ const secondOffset: number = new Date(this.value.getFullYear(), 6 , 1).getTimezoneOffset();
2492
+ const firstOffset: number = new Date(this.value.getFullYear(), 0 , 1).getTimezoneOffset();
2493
+ return (this.value.getTimezoneOffset() < Math.max(firstOffset, secondOffset));
2494
+ }
2495
+ protected setTimeZone(offsetValue: number ): void {
2496
+ if (!isNullOrUndefined(this.serverTimezoneOffset) && this.value) {
2497
+ const serverTimezoneDiff: number = offsetValue;
2498
+ const clientTimeZoneDiff: number = new Date().getTimezoneOffset() / 60;
2499
+ let timeZoneDiff: number = serverTimezoneDiff + clientTimeZoneDiff;
2500
+ timeZoneDiff = this.isDayLightSaving() ? timeZoneDiff-- : timeZoneDiff;
2501
+ this.value = new Date(this.value.getTime() + (timeZoneDiff * 60 * 60 * 1000));
2502
+ }
2503
+ }
2504
+ protected formResetHandler(): void {
2505
+ this.setProperties({ value: null }, true);
2506
+ }
2507
+ protected validateDate(): void {
2508
+ if (typeof this.value === 'string') {
2509
+ this.setProperties({ value: this.checkDateValue(new Date(this.checkValue(this.value))) }, true); // persist the value property.
2510
+ }
2511
+ super.validateDate(this.value);
2512
+ if (!isNullOrUndefined(this.value) && this.min <= this.max && this.value >= this.min && this.value <= this.max) {
2513
+ this.currentDate = new Date(this.checkValue(this.value));
2514
+ }
2515
+ if (isNaN(+this.value)) {
2516
+ this.setProperties({ value: null }, true);
2517
+ }
2518
+ }
2519
+ protected minMaxUpdate(): void {
2520
+ if (this.getModuleName() === 'calendar') {
2521
+ if (!isNullOrUndefined(this.value) && this.value <= this.min && this.min <= this.max) {
2522
+ this.setProperties({ value: this.min }, true);
2523
+ this.changedArgs = { value: this.value };
2524
+ } else {
2525
+ if (!isNullOrUndefined(this.value) && this.value >= this.max && this.min <= this.max) {
2526
+ this.setProperties({ value: this.max }, true);
2527
+ this.changedArgs = { value: this.value };
2528
+ }
2529
+ }
2530
+ }
2531
+ if (this.getModuleName() !== 'calendar' && !isNullOrUndefined(this.value)) {
2532
+ if (!isNullOrUndefined(this.value) && this.value < this.min && this.min <= this.max) {
2533
+ super.minMaxUpdate(this.min);
2534
+ } else {
2535
+ if (!isNullOrUndefined(this.value) && this.value > this.max && this.min <= this.max) {
2536
+ super.minMaxUpdate(this.max);
2537
+ }
2538
+ }
2539
+ } else {
2540
+ super.minMaxUpdate(this.value);
2541
+ }
2542
+ }
2543
+
2544
+ protected generateTodayVal(value: Date) : Date {
2545
+ let tempValue: Date = new Date();
2546
+ if (!isNullOrUndefined(this.timezone)) {
2547
+ tempValue = super.getDate(tempValue, this.timezone);
2548
+ }
2549
+ if (value && isNullOrUndefined(this.timezone)) {
2550
+ tempValue.setHours(value.getHours());
2551
+ tempValue.setMinutes(value.getMinutes());
2552
+ tempValue.setSeconds(value.getSeconds());
2553
+ tempValue.setMilliseconds(value.getMilliseconds());
2554
+ } else {
2555
+ tempValue = new Date(tempValue.getFullYear(), tempValue.getMonth(), tempValue.getDate(), 0, 0, 0, 0);
2556
+ }
2557
+ return tempValue;
2558
+ }
2559
+
2560
+ protected todayButtonClick(e?: MouseEvent | KeyboardEvent): void {
2561
+ if (this.showTodayButton) {
2562
+ const tempValue: Date = this.generateTodayVal(this.value);
2563
+ this.setProperties({ value: tempValue }, true);
2564
+ this.isTodayClicked = true;
2565
+ this.todayButtonEvent = e;
2566
+ if (this.isMultiSelection) {
2567
+ const copyValues: Date[] = this.copyValues(this.values);
2568
+ if (!super.checkPresentDate(tempValue, this.values)) {
2569
+ copyValues.push(tempValue);
2570
+ this.setProperties({ values: copyValues });
2571
+ }
2572
+ }
2573
+ super.todayButtonClick(e, new Date(+this.value));
2574
+ }
2575
+ }
2576
+ protected keyActionHandle(e: KeyboardEventArgs): void {
2577
+ super.keyActionHandle(e, this.value, this.isMultiSelection);
2578
+ }
2579
+ /**
2580
+ * Initialize the event handler
2581
+ *
2582
+ * @returns {void}
2583
+ * @private
2584
+ */
2585
+ protected preRender(): void {
2586
+ this.changeHandler = (e: MouseEvent): void => {
2587
+ this.triggerChange(e);
2588
+ };
2589
+ this.checkView();
2590
+ super.preRender(this.value);
2591
+ }
2592
+ /**
2593
+ * @returns {void}
2594
+ * @deprecated
2595
+ */
2596
+ public createContent(): void {
2597
+ this.previousDate = this.value;
2598
+ this.previousDateTime = this.value;
2599
+ super.createContent();
2600
+ }
2601
+ protected minMaxDate(localDate: Date): Date {
2602
+ return super.minMaxDate(localDate);
2603
+ }
2604
+ protected renderMonths(e?: Event, value?: Date, isCustomDate?: boolean): void {
2605
+ super.renderMonths(e, this.value, isCustomDate);
2606
+ }
2607
+ protected renderDays(currentDate: Date, value?: Date, isMultiSelect?: boolean, values?:
2608
+ Date[], isCustomDate?: boolean, e?: Event): HTMLElement[] {
2609
+ const tempDays: HTMLElement[] = super.renderDays(currentDate, this.value, this.isMultiSelection, this.values, isCustomDate, e);
2610
+ if (this.isMultiSelection) {
2611
+ super.validateValues(this.isMultiSelection, this.values);
2612
+ }
2613
+ return tempDays;
2614
+ }
2615
+ protected renderYears(e?: Event): void {
2616
+ if (this.calendarMode === 'Gregorian') {
2617
+ super.renderYears(e, this.value);
2618
+ } else {
2619
+ this.islamicModule.islamicRenderYears(e, this.value);
2620
+ }
2621
+
2622
+ }
2623
+ protected renderDecades(e?: Event): void {
2624
+ if (this.calendarMode === 'Gregorian') {
2625
+ super.renderDecades(e, this.value);
2626
+ } else {
2627
+ this.islamicModule.islamicRenderDecade(e, this.value);
2628
+ }
2629
+ }
2630
+ protected renderTemplate(elements: HTMLElement[], count: number, classNm: string, e?: Event): void {
2631
+ if (this.calendarMode === 'Gregorian') {
2632
+ super.renderTemplate(elements, count, classNm, e, this.value);
2633
+ } else {
2634
+ this.islamicModule.islamicRenderTemplate(elements, count, classNm, e, this.value);
2635
+ }
2636
+ this.changedArgs = { value: this.value, values: this.values };
2637
+ e && e.type === 'click' && (e.currentTarget as HTMLElement).classList.contains(OTHERMONTH) ? this.changeHandler(e) : this.changeHandler();
2638
+ }
2639
+ protected clickHandler(e: MouseEvent): void {
2640
+ const eve: Element = <HTMLElement>e.currentTarget;
2641
+ this.isPopupClicked = true;
2642
+ if (eve.classList.contains(OTHERMONTH)) {
2643
+ if (this.isMultiSelection) {
2644
+ const copyValues: Date[] = this.copyValues(this.values);
2645
+ if (copyValues.toString().indexOf(this.getIdValue(e, null).toString()) === -1) {
2646
+ copyValues.push(this.getIdValue(e, null));
2647
+ this.setProperties({ values: copyValues }, true);
2648
+ this.setProperties({ value: this.values[this.values.length - 1] }, true);
2649
+ }
2650
+ else {
2651
+ this.previousDates = true;
2652
+ }
2653
+ } else {
2654
+ this.setProperties({ value: this.getIdValue(e, null) }, true);
2655
+ }
2656
+ }
2657
+ const storeView: string = this.currentView();
2658
+ super.clickHandler(e, this.value);
2659
+ if (this.isMultiSelection && this.currentDate !== this.value &&
2660
+ !isNullOrUndefined(this.tableBodyElement.querySelectorAll('.' + FOCUSEDDATE)[0]) && storeView === 'Year') {
2661
+ this.tableBodyElement.querySelectorAll('.' + FOCUSEDDATE)[0].classList.remove(FOCUSEDDATE);
2662
+ }
2663
+ }
2664
+
2665
+ protected switchView(view: number, e?: Event, isMultiSelection?: boolean, isCustomDate?: boolean): void {
2666
+ super.switchView(view, e, this.isMultiSelection, isCustomDate);
2667
+ }
2668
+ /**
2669
+ * To get component name
2670
+ *
2671
+ * @returns {string} Return the component name.
2672
+ * @private
2673
+ */
2674
+ protected getModuleName(): string {
2675
+ super.getModuleName();
2676
+ return 'calendar';
2677
+ }
2678
+ /* eslint-disable valid-jsdoc, jsdoc/require-returns-description */
2679
+ /**
2680
+ * Gets the properties to be maintained upon browser refresh.
2681
+ *
2682
+ * @returns {string}
2683
+ */
2684
+ public getPersistData(): string {
2685
+ super.getPersistData();
2686
+ const keyEntity: string[] = ['value', 'values'];
2687
+ return this.addOnPersist(keyEntity);
2688
+ }
2689
+ /* eslint-enable valid-jsdoc, jsdoc/require-returns-description */
2690
+ /**
2691
+ * Called internally if any of the property value changed.
2692
+ *
2693
+ * @param {CalendarModel} newProp - Returns the dynamic property value of the component.
2694
+ * @param {CalendarModel} oldProp - Returns the previous property value of the component.
2695
+ * @returns {void}
2696
+ * @private
2697
+ */
2698
+ public onPropertyChanged(newProp: CalendarModel, oldProp: CalendarModel): void {
2699
+ this.effect = '';
2700
+ this.rangeValidation(this.min, this.max);
2701
+ for (const prop of Object.keys(newProp)) {
2702
+ switch (prop) {
2703
+ case 'value':
2704
+ if (this.isDateSelected) {
2705
+ if (typeof newProp.value === 'string') {
2706
+ this.setProperties({ value: new Date(this.checkValue(newProp.value)) }, true);
2707
+ } else {
2708
+ newProp.value = new Date(this.checkValue(newProp.value));
2709
+ }
2710
+ if (isNaN(+this.value)) {
2711
+ this.setProperties({ value: oldProp.value }, true);
2712
+ }
2713
+ this.update();
2714
+ }
2715
+ break;
2716
+ case 'values':
2717
+ if (this.isDateSelected) {
2718
+ if (typeof newProp.values === 'string' || typeof newProp.values === 'number') {
2719
+ this.setProperties({ values: null }, true);
2720
+ } else {
2721
+ const copyValues: Date[] = this.copyValues(this.values);
2722
+ for (let index: number = 0; index < copyValues.length; index++) {
2723
+ const tempDate: Date = copyValues[index as number];
2724
+ if (this.checkDateValue(tempDate) && !super.checkPresentDate(tempDate, copyValues)) {
2725
+ copyValues.push(tempDate);
2726
+ }
2727
+ }
2728
+ this.setProperties({ values: copyValues }, true);
2729
+ if (this.values.length > 0) {
2730
+ this.setProperties({ value: newProp.values[newProp.values.length - 1] }, true);
2731
+ }
2732
+ }
2733
+ this.validateValues(this.isMultiSelection, this.values);
2734
+ this.update();
2735
+ }
2736
+ break;
2737
+ case 'isMultiSelection':
2738
+ if (this.isDateSelected) {
2739
+ this.setProperties({ isMultiSelection: newProp.isMultiSelection }, true);
2740
+ this.update();
2741
+ }
2742
+ break;
2743
+ case 'enabled':
2744
+ this.setEnable(this.enabled);
2745
+ break;
2746
+ case 'cssClass':
2747
+ if (this.getModuleName() === 'calendar') {
2748
+ this.setClass(newProp.cssClass, oldProp.cssClass);
2749
+ }
2750
+ break;
2751
+ default:
2752
+ super.onPropertyChanged(newProp, oldProp, this.isMultiSelection, this.values);
2753
+ }
2754
+ }
2755
+ this.preventChange = this.isAngular && this.preventChange ? !this.preventChange : this.preventChange;
2756
+ }
2757
+
2758
+ /**
2759
+ * Destroys the widget.
2760
+ *
2761
+ * @returns {void}
2762
+ */
2763
+ public destroy(): void {
2764
+ super.destroy();
2765
+ if (this.getModuleName() === 'calendar') {
2766
+ this.changedArgs = null;
2767
+ const form: Element = closest(this.element, 'form');
2768
+ if (form) {
2769
+ EventHandler.remove(form, 'reset', this.formResetHandler.bind(this));
2770
+ }
2771
+ }
2772
+ }
2773
+ /**
2774
+ * This method is used to navigate to the month/year/decade view of the Calendar.
2775
+ *
2776
+ * @param {string} view - Specifies the view of the Calendar.
2777
+ * @param {Date} date - Specifies the focused date in a view.
2778
+ * @param {boolean} isCustomDate - Specifies whether the calendar is rendered with custom today date or not.
2779
+ * @returns {void}
2780
+ * @deprecated
2781
+ */
2782
+ public navigateTo(view: CalendarView, date: Date, isCustomDate?: boolean): void {
2783
+ this.minMaxUpdate();
2784
+ super.navigateTo(view, date, isCustomDate);
2785
+ }
2786
+ /* eslint-disable valid-jsdoc, jsdoc/require-returns-description */
2787
+ /**
2788
+ * Gets the current view of the Calendar.
2789
+ *
2790
+ * @returns {string}
2791
+ * @deprecated
2792
+ */
2793
+ public currentView(): string {
2794
+ return super.currentView();
2795
+ }
2796
+ /* eslint-enable valid-jsdoc, jsdoc/require-returns-description */
2797
+ /**
2798
+ * This method is used to add the single or multiple dates to the values property of the Calendar.
2799
+ *
2800
+ * @param {Date | Date[]} dates - Specifies the date or dates to be added to the values property of the Calendar.
2801
+ * @returns {void}
2802
+ * @deprecated
2803
+ */
2804
+ public addDate(dates: Date | Date[]): void {
2805
+ if (typeof dates !== 'string' && typeof dates !== 'number') {
2806
+ let copyValues: Date[] = this.copyValues(this.values);
2807
+ if (typeof dates === 'object' && (<Date[]>(dates)).length > 0) {
2808
+ const tempDates: Date[] = <Date[]>dates;
2809
+ for (let i: number = 0; i < tempDates.length; i++) {
2810
+ if (this.checkDateValue(tempDates[i as number]) && !super.checkPresentDate(tempDates[i as number], copyValues)) {
2811
+ if (!isNullOrUndefined(copyValues) && copyValues.length > 0) {
2812
+ copyValues.push(tempDates[i as number]);
2813
+ } else {
2814
+ copyValues = [new Date(+tempDates[i as number])];
2815
+ }
2816
+ }
2817
+ }
2818
+ } else {
2819
+ if (this.checkDateValue(<Date>dates) && !super.checkPresentDate(<Date>dates, copyValues)) {
2820
+ if (!isNullOrUndefined(copyValues) && copyValues.length > 0) {
2821
+ copyValues.push(<Date>(dates));
2822
+ } else {
2823
+ copyValues = [new Date(+dates)];
2824
+ }
2825
+ }
2826
+ }
2827
+ this.setProperties({ values: copyValues }, true);
2828
+ if (this.isMultiSelection) {
2829
+ this.setProperties({ value: this.values[this.values.length - 1] }, true);
2830
+ }
2831
+ this.validateValues(this.isMultiSelection, copyValues);
2832
+ this.update();
2833
+ this.changedArgs = { value: this.value, values: this.values };
2834
+ this.changeHandler();
2835
+ }
2836
+ }
2837
+ /**
2838
+ * This method is used to remove the single or multiple dates from the values property of the Calendar.
2839
+ *
2840
+ * @param {Date | Date[]} dates - Specifies the date or dates which need to be removed from the values property of the Calendar.
2841
+ * @returns {void}
2842
+ * @deprecated
2843
+ */
2844
+ public removeDate(dates: Date | Date[]): void {
2845
+ if (typeof dates !== 'string' && typeof dates !== 'number' && !isNullOrUndefined(this.values) && this.values.length > 0) {
2846
+ const copyValues: Date[] = this.copyValues(this.values);
2847
+ if (typeof dates === 'object' && ((<Date[]>(dates)).length > 0)) {
2848
+ const tempDates: Date[] = <Date[]>dates;
2849
+ for (let index: number = 0; index < tempDates.length; index++) {
2850
+ for (let i: number = 0; i < copyValues.length; i++) {
2851
+ if (+copyValues[i as number] === +tempDates[index as number]) {
2852
+ copyValues.splice(i, 1);
2853
+ }
2854
+ }
2855
+ }
2856
+ } else {
2857
+ for (let i: number = 0; i < copyValues.length; i++) {
2858
+ if (+copyValues[i as number] === +dates) {
2859
+ copyValues.splice(i, 1);
2860
+ }
2861
+ }
2862
+ }
2863
+ this.setProperties({ values: copyValues }, false);
2864
+ this.update();
2865
+ if (this.isMultiSelection) {
2866
+ this.setProperties({ value: this.values[this.values.length - 1] }, true);
2867
+ }
2868
+ this.changedArgs = { value: this.value, values: this.values };
2869
+ this.changeHandler();
2870
+ }
2871
+ }
2872
+
2873
+ /**
2874
+ * To set custom today date in calendar
2875
+ *
2876
+ * @param {Date} date - Specifies date value to be set.
2877
+ * @private
2878
+ * @returns {void}
2879
+ */
2880
+ public setTodayDate(date: Date): void {
2881
+ const todayDate: Date = new Date(+date);
2882
+ this.setProperties({ value: todayDate }, true);
2883
+ super.todayButtonClick(null, todayDate, true);
2884
+ }
2885
+
2886
+ protected update(): void {
2887
+ this.validateDate();
2888
+ this.minMaxUpdate();
2889
+ super.setValueUpdate();
2890
+ }
2891
+ protected selectDate(e: MouseEvent | KeyboardEventArgs, date: Date, element: Element): void {
2892
+ super.selectDate(e, date, element, this.isMultiSelection, this.values);
2893
+ if (this.isMultiSelection && !isNullOrUndefined(this.values) && this.values.length > 0) {
2894
+ this.setProperties({ value: this.values[this.values.length - 1] }, true);
2895
+ }
2896
+ this.changedArgs = { value: this.value, values: this.values };
2897
+ this.changeHandler(e);
2898
+ }
2899
+
2900
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2901
+ protected changeEvent(e: Event): void {
2902
+ if ((this.value && this.value.valueOf()) !== (this.previousDate && +this.previousDate.valueOf())
2903
+ || this.isMultiSelection) {
2904
+ if (this.isAngular && this.preventChange) {
2905
+ this.preventChange = false;
2906
+ } else {
2907
+ this.trigger('change', this.changedArgs);
2908
+ }
2909
+ this.previousDate = new Date(+this.value);
2910
+ }
2911
+ }
2912
+
2913
+ protected triggerChange(e: MouseEvent | KeyboardEvent): void {
2914
+ if (!isNullOrUndefined(this.todayButtonEvent) && this.isTodayClicked) {
2915
+ e = this.todayButtonEvent;
2916
+ this.isTodayClicked = false;
2917
+ }
2918
+ this.changedArgs.event = e || null;
2919
+ this.changedArgs.isInteracted = !isNullOrUndefined(e);
2920
+ if (!isNullOrUndefined(this.value)) {
2921
+ this.setProperties({ value: this.value }, true);
2922
+ }
2923
+ // eslint-disable-next-line
2924
+ if (!this.isMultiSelection && +this.value !== Number.NaN && (!isNullOrUndefined(this.value) &&
2925
+ !isNullOrUndefined(this.previousDate) || this.previousDate === null
2926
+ && !isNaN(+this.value))) {
2927
+ this.changeEvent(e);
2928
+ } else if (!isNullOrUndefined(this.values) && this.previousValues !== this.values.length) {
2929
+ this.changeEvent(e);
2930
+ this.previousValues = this.values.length;
2931
+ }
2932
+
2933
+ }
2934
+
2935
+ }
2936
+
2937
+ export interface NavigatedEventArgs extends BaseEventArgs {
2938
+ /** Defines the current view of the Calendar. */
2939
+ view?: string
2940
+ /** Defines the focused date in a view. */
2941
+ date?: Date
2942
+ /**
2943
+ * Specifies the original event arguments.
2944
+ */
2945
+ event?: KeyboardEvent | MouseEvent | Event
2946
+
2947
+ }
2948
+
2949
+ export interface RenderDayCellEventArgs extends BaseEventArgs {
2950
+ /** Specifies whether to disable the current date or not. */
2951
+ isDisabled?: boolean
2952
+ /** Specifies the day cell element. */
2953
+ element?: HTMLElement
2954
+ /** Defines the current date of the Calendar. */
2955
+ date?: Date
2956
+ /** Defines whether the current date is out of range (less than min or greater than max) or not. */
2957
+ isOutOfRange?: boolean
2958
+ }
2959
+ export interface ChangedEventArgs extends BaseEventArgs {
2960
+ /** Defines the selected date of the Calendar.
2961
+ *
2962
+ * @isGenericType true
2963
+ */
2964
+ value?: Date
2965
+
2966
+ /** Defines the multiple selected date of the Calendar. */
2967
+ values?: Date[]
2968
+
2969
+ /**
2970
+ * Specifies the original event arguments.
2971
+ */
2972
+ event?: KeyboardEvent | MouseEvent | Event
2973
+
2974
+ /** Defines the element. */
2975
+ element?: HTMLElement | HTMLInputElement
2976
+
2977
+ /**
2978
+ * If the event is triggered by interaction, it returns true. Otherwise, it returns false.
2979
+ */
2980
+ isInteracted?: boolean
2981
+ }
2982
+
2983
+ export interface IslamicObject {
2984
+ year: number
2985
+ date: number
2986
+ month: number
2987
+ }
2988
+
2989
+ /**
2990
+ * Defines the argument for the focus event.
2991
+ */
2992
+ export interface FocusEventArgs {
2993
+ model?: Object
2994
+ }
2995
+
2996
+ /**
2997
+ * Defines the argument for the blur event.
2998
+ */
2999
+ export interface BlurEventArgs {
3000
+ model?: Object
3001
+ }
3002
+
3003
+ export interface ClearedEventArgs {
3004
+ /**
3005
+ * Specifies the original event arguments.
3006
+ */
3007
+ event?: MouseEvent | Event
3008
+
3009
+ }