@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,2528 @@
1
+ // eslint-disable-next-line @typescript-eslint/triple-slash-reference
2
+ /// <reference path='../calendar/calendar-model.d.ts'/>
3
+ import { EventHandler, Property, Internationalization, NotifyPropertyChanges, DateFormatOptions } from '@syncfusion/ej2-base';
4
+ import { KeyboardEvents, KeyboardEventArgs, Animation, EmitType, Event, extend, L10n, Browser, formatUnit } from '@syncfusion/ej2-base';
5
+ import { detach, addClass, removeClass, closest, attributes, Touch, SwipeEventArgs } from '@syncfusion/ej2-base';
6
+ import { isNullOrUndefined, setValue, getUniqueID, ModuleDeclaration } from '@syncfusion/ej2-base';
7
+ import { Popup } from '@syncfusion/ej2-popups';
8
+ import { Input, InputObject, IInput, FloatLabelType } from '@syncfusion/ej2-inputs';
9
+ import { ChangedEventArgs, CalendarView, Calendar, BlurEventArgs, FocusEventArgs, ClearedEventArgs } from '../calendar/calendar';
10
+ import { MaskPlaceholderModel } from '../common/maskplaceholder-model';
11
+ import { DatePickerModel } from './datepicker-model';
12
+
13
+
14
+ //class constant defination
15
+ const DATEWRAPPER: string = 'e-date-wrapper';
16
+ const ROOT: string = 'e-datepicker';
17
+ const LIBRARY: string = 'e-lib';
18
+ const CONTROL: string = 'e-control';
19
+ const POPUPWRAPPER: string = 'e-popup-wrapper';
20
+ const INPUTWRAPPER: string = 'e-input-group-icon';
21
+ const POPUP: string = 'e-popup';
22
+ const INPUTCONTAINER: string = 'e-input-group';
23
+ const INPUTFOCUS: string = 'e-input-focus';
24
+ const INPUTROOT: string = 'e-input';
25
+ const ERROR: string = 'e-error';
26
+ const ACTIVE: string = 'e-active';
27
+ const OVERFLOW: string = 'e-date-overflow';
28
+ const DATEICON: string = 'e-date-icon';
29
+ const CLEARICON: string = 'e-clear-icon';
30
+ const ICONS: string = 'e-icons';
31
+ const OPENDURATION: number = 300;
32
+ const OFFSETVALUE: number = 4;
33
+ const SELECTED: string = 'e-selected';
34
+ const FOCUSEDDATE: string = 'e-focused-date';
35
+ const NONEDIT: string = 'e-non-edit';
36
+ const containerAttr: string[] = ['title', 'class', 'style'];
37
+ export interface FormatObject {
38
+ /**
39
+ * Specifies the format in which the date format will process
40
+ */
41
+ skeleton?: string
42
+ }
43
+
44
+ /**
45
+ * Represents the DatePicker component that allows user to select
46
+ * or enter a date value.
47
+ * ```html
48
+ * <input id='datepicker'/>
49
+ * ```
50
+ * ```typescript
51
+ * <script>
52
+ * let datePickerObject:DatePicker = new DatePicker({ value: new Date() });
53
+ * datePickerObject.appendTo('#datepicker');
54
+ * </script>
55
+ * ```
56
+ */
57
+ @NotifyPropertyChanges
58
+ export class DatePicker extends Calendar implements IInput {
59
+ protected popupObj: Popup;
60
+ protected inputWrapper: InputObject;
61
+ private modal: HTMLElement;
62
+ protected inputElement: HTMLInputElement;
63
+ protected popupWrapper: HTMLElement;
64
+ protected changedArgs: ChangedEventArgs;
65
+ protected previousDate: Date;
66
+ private keyboardModules: KeyboardEvents;
67
+ private calendarKeyboardModules: KeyboardEvents;
68
+ protected previousElementValue: string;
69
+ protected ngTag: string;
70
+ protected dateTimeFormat: string;
71
+ protected inputElementCopy: HTMLElement;
72
+ protected inputValueCopy: Date;
73
+ protected l10n: L10n;
74
+ protected preventArgs: PopupObjectArgs;
75
+ private isDateIconClicked: boolean = false;
76
+ protected isAltKeyPressed: boolean = false;
77
+ private isInteracted: boolean = true;
78
+ private index: number;
79
+ private formElement: HTMLElement;
80
+ protected invalidValueString: string = null;
81
+ private checkPreviousValue: Date = null;
82
+ protected formatString: string;
83
+ protected inputFormatsString: string[];
84
+ protected tabIndex: string;
85
+ protected maskedDateValue: string = '';
86
+ private datepickerOptions: DatePickerModel;
87
+ protected defaultKeyConfigs: { [key: string]: string };
88
+ protected mobilePopupWrapper: HTMLElement;
89
+ protected preventChange: boolean = false;
90
+ protected isIconClicked : boolean = false;
91
+ protected isDynamicValueChanged: boolean = false;
92
+ protected moduleName: string = this.getModuleName();
93
+ protected isFocused: boolean = false;
94
+ protected touchModule: Touch;
95
+ protected touchStart: boolean;
96
+ protected iconRight: boolean;
97
+ protected isBlur: boolean = false;
98
+ private isKeyAction: boolean = false;
99
+ protected clearButton: HTMLElement;
100
+ /**
101
+ * Specifies the width of the DatePicker component.
102
+ *
103
+ * @default null
104
+ */
105
+ @Property(null)
106
+ public width: number | string;
107
+ /**
108
+ * Gets or sets the selected date of the Calendar.
109
+ *
110
+ * @default null
111
+ * @isGenericType true
112
+ * @deprecated
113
+ */
114
+ @Property(null)
115
+ public value: Date;
116
+ /**
117
+ * Specifies the root CSS class of the DatePicker that allows to
118
+ * customize the appearance by overriding the styles.
119
+ *
120
+ * @default null
121
+ */
122
+ @Property(null)
123
+ public cssClass: string;
124
+ /**
125
+ * Specifies the component to act as strict. So that, it allows to enter only a valid date value within a specified range or else it
126
+ * will resets to previous value. By default, strictMode is in false.
127
+ * it allows invalid or out-of-range date value with highlighted error class.
128
+ *
129
+ * @default false
130
+ * > For more details refer to
131
+ * [`Strict Mode`](../../datepicker/strict-mode/) documentation.
132
+ */
133
+ @Property(false)
134
+ public strictMode: boolean;
135
+ /**
136
+ * Specifies the format of the value that to be displayed in component. By default, the format is based on the culture. You can set
137
+ * the format to "format:'dd/MM/yyyy hh:mm'" or "format:{skeleton:'medium'}" either in string or object.
138
+ * > To know more about the date format standards, refer to the Internationalization Date Format
139
+ * [`Internationalization`](../../common/internationalization/#custom-formats) section.
140
+ *
141
+ * @default null
142
+ * @aspType string
143
+ */
144
+ @Property(null)
145
+ public format: string | FormatObject;
146
+ /**
147
+ * Specifies an array of acceptable date input formats for parsing user input.
148
+ *
149
+ * @default null
150
+ * @aspType string[]
151
+ */
152
+ @Property(null)
153
+ public inputFormats: string[] | FormatObject[];
154
+ /**
155
+ * Specifies the component to be disabled or not.
156
+ *
157
+ * @default true
158
+ */
159
+ @Property(true)
160
+ public enabled: boolean;
161
+ /**
162
+ * Specifies the component popup display full screen in mobile devices.
163
+ *
164
+ * @default false
165
+ */
166
+ @Property(false)
167
+ public fullScreenMode : boolean;
168
+ /**
169
+ * You can add the additional html attributes such as disabled, value etc., to the element.
170
+ * If you configured both property and equivalent html attribute then the component considers the property value.
171
+ * {% codeBlock src='datepicker/htmlAttributes/index.md' %}{% endcodeBlock %}
172
+ *
173
+ * @default {}
174
+ */
175
+ @Property({})
176
+ public htmlAttributes: { [key: string]: string };
177
+ /**
178
+ * Gets or sets multiple selected dates of the calendar.
179
+ *
180
+ * @default null
181
+ * @private
182
+ */
183
+ @Property(null)
184
+ public values: Date[];
185
+ /**
186
+ * Specifies the option to enable the multiple dates selection of the calendar.
187
+ *
188
+ * @default false
189
+ * @private
190
+ */
191
+ @Property(false)
192
+ public isMultiSelection: boolean;
193
+ /**
194
+ * Specifies whether to show or hide the clear icon in textbox.
195
+ *
196
+ * @default true
197
+ */
198
+ @Property(true)
199
+ public showClearButton: boolean;
200
+ /**
201
+ * > Support for `allowEdit` has been provided from
202
+ * [`v16.2.46`](https://ej2.syncfusion.com/angular/documentation/release-notes/16.2.46/#datepicker).
203
+ *
204
+ * Specifies whether the input textbox is editable or not. Here the user can select the value from the
205
+ * popup and cannot edit in the input textbox.
206
+ *
207
+ * @default true
208
+ */
209
+ @Property(true)
210
+ public allowEdit: boolean;
211
+ /**    
212
+ * Customizes the key actions in DatePicker.
213
+ * For example, when using German keyboard, the key actions can be customized using these shortcuts.
214
+ *
215
+ *
216
+ * Input Navigation
217
+ * <table>
218
+ * <tr>
219
+ * <td colSpan=1 rowSpan=1>
220
+ * Key action<br/></td><td colSpan=1 rowSpan=1>
221
+ * Key<br/></td></tr>
222
+ * <tr>
223
+ * <td colSpan=1 rowSpan=1>
224
+ * altUpArrow<br/></td><td colSpan=1 rowSpan=1>
225
+ * alt+uparrow<br/></td></tr>
226
+ * <tr>
227
+ * <td colSpan=1 rowSpan=1>
228
+ * altDownArrow<br/></td><td colSpan=1 rowSpan=1>
229
+ * alt+downarrow<br/></td></tr>
230
+ * <tr>
231
+ * <td colSpan=1 rowSpan=1>
232
+ * escape<br/></td><td colSpan=1 rowSpan=1>
233
+ * escape<br/></td></tr>
234
+ * </table>
235
+ *
236
+ * Calendar Navigation
237
+ * <table>
238
+ * <tr>
239
+ * <td colSpan=1 rowSpan=1>
240
+ * Key action<br/></td><td colSpan=1 rowSpan=1>
241
+ * Key<br/></td></tr>
242
+ * <tr>
243
+ * <td colSpan=1 rowSpan=1>
244
+ * controlUp<br/></td><td colSpan=1 rowSpan=1>
245
+ * ctrl+38<br/></td></tr>
246
+ * <tr>
247
+ * <td colSpan=1 rowSpan=1>
248
+ * controlDown<br/></td><td colSpan=1 rowSpan=1>
249
+ * ctrl+40<br/></td></tr>
250
+ * <tr>
251
+ * <td colSpan=1 rowSpan=1>
252
+ * moveDown<br/></td><td colSpan=1 rowSpan=1>
253
+ * downarrow<br/></td></tr>
254
+ * <tr>
255
+ * <td colSpan=1 rowSpan=1>
256
+ * moveUp<br/></td><td colSpan=1 rowSpan=1>
257
+ * uparrow<br/></td></tr>
258
+ * <tr>
259
+ * <td colSpan=1 rowSpan=1>
260
+ * moveLeft<br/></td><td colSpan=1 rowSpan=1>
261
+ * leftarrow<br/></td></tr>
262
+ * <tr>
263
+ * <td colSpan=1 rowSpan=1>
264
+ * moveRight<br/></td><td colSpan=1 rowSpan=1>
265
+ * rightarrow<br/></td></tr>
266
+ * <tr>
267
+ * <td colSpan=1 rowSpan=1>
268
+ * shiftPageUp<br/></td><td colSpan=1 rowSpan=1>
269
+ * shift+pageup<br/></td></tr>
270
+ * <tr>
271
+ * <td colSpan=1 rowSpan=1>
272
+ * shiftPageDown<br/></td><td colSpan=1 rowSpan=1>
273
+ * shift+pagedown<br/></td></tr>
274
+ * <tr>
275
+ * <tr>
276
+ * <td colSpan=1 rowSpan=1>
277
+ * select<br/></td><td colSpan=1 rowSpan=1>
278
+ * enter<br/></td></tr>
279
+ * <tr>
280
+ * <td colSpan=1 rowSpan=1>
281
+ * home<br/></td><td colSpan=1 rowSpan=1>
282
+ * home<br/></td></tr>
283
+ * <tr>
284
+ * <td colSpan=1 rowSpan=1>
285
+ * end<br/></td><td colSpan=1 rowSpan=1>
286
+ * end<br/></td></tr>
287
+ * <tr>
288
+ * <td colSpan=1 rowSpan=1>
289
+ * pageUp<br/></td><td colSpan=1 rowSpan=1>
290
+ * pageup<br/></td></tr>
291
+ * <tr>
292
+ * <td colSpan=1 rowSpan=1>
293
+ * pageDown<br/></td><td colSpan=1 rowSpan=1>
294
+ * pagedown<br/></td></tr>
295
+ * <td colSpan=1 rowSpan=1>
296
+ * controlHome<br/></td><td colSpan=1 rowSpan=1>
297
+ * ctrl+home<br/></td></tr>
298
+ * <tr>
299
+ * <td colSpan=1 rowSpan=1>
300
+ * controlEnd<br/></td><td colSpan=1 rowSpan=1>
301
+ * ctrl+end<br/></td></tr>
302
+ * <tr>
303
+ * <td colSpan=1 rowSpan=1>
304
+ * altUpArrow<br/></td><td colSpan=1 rowSpan=1>
305
+ * alt+uparrow<br/></td></tr>
306
+ * <tr>
307
+ * <td colSpan=1 rowSpan=1>
308
+ * spacebar<br/></td><td colSpan=1 rowSpan=1>
309
+ * space<br/></td></tr>
310
+ * <tr>
311
+ * <td colSpan=1 rowSpan=1>
312
+ * altRightArrow<br/></td><td colSpan=1 rowSpan=1>
313
+ * alt+rightarrow<br/></td></tr>
314
+ * <tr>
315
+ * <td colSpan=1 rowSpan=1>
316
+ * altLeftArrow<br/></td><td colSpan=1 rowSpan=1>
317
+ * alt+leftarrow<br/></td></tr>
318
+ * </table>
319
+ *
320
+ * {% codeBlock src='datepicker/keyConfigs/index.md' %}{% endcodeBlock %}
321
+ *
322
+ * @default null
323
+ * @deprecated
324
+ */
325
+ @Property(null)
326
+ public keyConfigs: { [key: string]: string };
327
+ /**
328
+      * Enable or disable persisting component's state between page reloads. If enabled, following list of states will be persisted.
329
+ * 1. value
330
+ *
331
+      * @default false
332
+ * @deprecated
333
+      */
334
+ @Property(false)
335
+ public enablePersistence: boolean;
336
+ /**
337
+ * specifies the z-index value of the datePicker popup element.
338
+ *
339
+ * @default 1000
340
+ * @aspType int
341
+ */
342
+ @Property(1000)
343
+ public zIndex: number;
344
+ /**
345
+ * Specifies the component in readonly state. When the Component is readonly it does not allow user input.
346
+ *
347
+ * @default false
348
+ */
349
+ @Property(false)
350
+ public readonly: boolean;
351
+ /**
352
+ * Specifies the placeholder text that displayed in textbox.
353
+ *
354
+ * @default null
355
+ */
356
+ @Property(null)
357
+ public placeholder: string;
358
+ /**
359
+ * Specifies the placeholder text to be floated.
360
+ * Possible values are:
361
+ * Never: The label will never float in the input when the placeholder is available.
362
+ * Always: The floating label will always float above the input.
363
+ * Auto: The floating label will float above the input after focusing or entering a value in the input.
364
+ *
365
+ * @default Syncfusion.EJ2.Inputs.FloatLabelType.Never
366
+ * @aspType Syncfusion.EJ2.Inputs.FloatLabelType
367
+ * @isEnumeration true
368
+ */
369
+ @Property('Never')
370
+ public floatLabelType: FloatLabelType | string;
371
+
372
+ /**
373
+ * By default, the date value will be processed based on system time zone.
374
+ * If you want to process the initial date value using server time zone
375
+ * then specify the time zone value to `serverTimezoneOffset` property.
376
+ *
377
+ * @default null
378
+ * @deprecated
379
+ */
380
+ @Property(null)
381
+ public serverTimezoneOffset: number;
382
+
383
+ /**
384
+ * By default, the popup opens while clicking on the datepicker icon.
385
+ * If you want to open the popup while focusing the date input then specify its value as true.
386
+ *
387
+ * @default false
388
+ */
389
+ @Property(false)
390
+ public openOnFocus : boolean;
391
+
392
+ /**
393
+ * Specifies whether it is a masked datepicker or not.
394
+ * By default the datepicker component render without masked input.
395
+ * If you need masked datepicker input then specify it as true.
396
+ *
397
+ * @default false
398
+ */
399
+ @Property(false)
400
+ public enableMask: boolean;
401
+
402
+ /**
403
+ * Specifies the mask placeholder to be displayed on masked datepicker.
404
+ *
405
+ * @default {day:'day' , month:'month', year: 'year', hour:'hour',minute:'minute',second:'second',dayOfTheWeek: 'day of the week'}
406
+ */
407
+ @Property({day: 'day' , month: 'month', year: 'year', hour: 'hour', minute: 'minute', second: 'second', dayOfTheWeek: 'day of the week'})
408
+ public maskPlaceholder: MaskPlaceholderModel;
409
+
410
+
411
+ /**
412
+ * Triggers when the popup is opened.
413
+ *
414
+ * @event open
415
+ */
416
+ @Event()
417
+ public open: EmitType<PreventableEventArgs | PopupObjectArgs>;
418
+
419
+ /**
420
+ * Triggers when datepicker value is cleared using clear button.
421
+ *
422
+ * @event cleared
423
+ */
424
+ @Event()
425
+ public cleared: EmitType<ClearedEventArgs>;
426
+
427
+ /**
428
+ * Triggers when the popup is closed.
429
+ *
430
+ * @event close
431
+ */
432
+ @Event()
433
+ public close: EmitType<PreventableEventArgs | PopupObjectArgs>;
434
+ /**
435
+ * Triggers when the input loses the focus.
436
+ *
437
+ * @event blur
438
+ */
439
+ @Event()
440
+ public blur: EmitType<BlurEventArgs>;
441
+ /**
442
+ * Triggers when the input gets focus.
443
+ *
444
+ * @event focus
445
+ */
446
+ @Event()
447
+ public focus: EmitType<FocusEventArgs>;
448
+ /**
449
+ * Triggers when the component is created.
450
+ *
451
+ * @event created
452
+ */
453
+ @Event()
454
+ public created: EmitType<Object>;
455
+ /**
456
+      * Triggers when the component is destroyed.
457
+ *
458
+      * @event destroyed
459
+      */
460
+ @Event()
461
+ public destroyed: EmitType<Object>;
462
+ /**
463
+ * Constructor for creating the widget.
464
+ *
465
+ * @param {DatePickerModel} options - Specifies the DatePicker model.
466
+ * @param {string | HTMLInputElement} element - Specifies the element to render as component.
467
+ * @private
468
+ */
469
+ public constructor(options?: DatePickerModel, element?: string | HTMLInputElement) {
470
+ super(options, element);
471
+ this.datepickerOptions = options;
472
+ }
473
+ /**
474
+ * To Initialize the control rendering.
475
+ *
476
+ * @returns {void}
477
+ * @private
478
+ */
479
+ public render(): void {
480
+ this.initialize();
481
+ this.bindEvents();
482
+ if (this.floatLabelType !== 'Never') {
483
+ Input.calculateWidth(this.inputElement, this.inputWrapper.container);
484
+ }
485
+ if (!isNullOrUndefined(this.inputWrapper.buttons[0]) && !isNullOrUndefined(this.inputWrapper.container.getElementsByClassName('e-float-text-overflow')[0]) && this.floatLabelType !== 'Never') {
486
+ this.inputWrapper.container.getElementsByClassName('e-float-text-overflow')[0].classList.add('e-icon');
487
+ }
488
+ if (!isNullOrUndefined(closest(this.element, 'fieldset') as HTMLFieldSetElement) && (closest(this.element, 'fieldset') as HTMLFieldSetElement).disabled) {
489
+ this.enabled = false;
490
+ }
491
+ this.renderComplete();
492
+ this.setTimeZone(this.serverTimezoneOffset);
493
+ }
494
+ protected setTimeZone(offsetValue: number ): void {
495
+ if (!isNullOrUndefined(this.serverTimezoneOffset) && this.value) {
496
+ const clientTimeZoneDiff: number = new Date().getTimezoneOffset() / 60;
497
+ const serverTimezoneDiff: number = offsetValue;
498
+ let timeZoneDiff: number = serverTimezoneDiff + clientTimeZoneDiff;
499
+ timeZoneDiff = this.isDayLightSaving() ? timeZoneDiff-- : timeZoneDiff;
500
+ this.value = new Date((this.value).getTime() + (timeZoneDiff * 60 * 60 * 1000));
501
+ this.updateInput();
502
+ this.changeTrigger(null);
503
+ }
504
+ }
505
+ protected isDayLightSaving(): boolean {
506
+ const firstOffset: number = new Date(this.value.getFullYear(), 0 , 1).getTimezoneOffset();
507
+ const secondOffset: number = new Date(this.value.getFullYear(), 6 , 1).getTimezoneOffset();
508
+ return (this.value.getTimezoneOffset() < Math.max(firstOffset, secondOffset));
509
+ }
510
+
511
+ protected setAllowEdit(): void {
512
+ if (this.allowEdit) {
513
+ if (!this.readonly) {
514
+ this.inputElement.removeAttribute('readonly');
515
+ }
516
+ } else {
517
+ attributes(this.inputElement, { 'readonly': '' });
518
+ }
519
+ this.updateIconState();
520
+ }
521
+ protected updateIconState(): void {
522
+ if (!this.allowEdit && this.inputWrapper && !this.readonly) {
523
+ if (this.inputElement.value === '') {
524
+ removeClass([this.inputWrapper.container], [NONEDIT]);
525
+ } else {
526
+ addClass([this.inputWrapper.container], [NONEDIT]);
527
+ }
528
+ } else if (this.inputWrapper) {
529
+ removeClass([this.inputWrapper.container], [NONEDIT]);
530
+ }
531
+ }
532
+ private initialize(): void {
533
+ this.checkInvalidValue(this.value);
534
+ if (this.enableMask) {
535
+ this.notify('createMask', {
536
+ module: 'MaskedDateTime'
537
+ });
538
+ }
539
+ this.createInput();
540
+ this.updateHtmlAttributeToWrapper();
541
+ this.setAllowEdit();
542
+ if (this.enableMask && !this.value && this.maskedDateValue && (this.floatLabelType === 'Always' || !this.floatLabelType || !this.placeholder)){
543
+ this.updateInput(true);
544
+ this.updateInputValue(this.maskedDateValue);
545
+ }
546
+ else if (!this.enableMask) {
547
+ this.updateInput(true);
548
+ }
549
+ this.previousElementValue = this.inputElement.value;
550
+ this.previousDate = !isNullOrUndefined(this.value) ? new Date(+this.value) : null;
551
+ this.inputElement.setAttribute('value', this.inputElement.value);
552
+
553
+ this.inputValueCopy = this.value;
554
+ }
555
+
556
+ private createInput(): void {
557
+ const ariaAttrs: object = {
558
+ 'aria-atomic': 'true', 'aria-expanded': 'false',
559
+ 'role': 'combobox', 'autocomplete': 'off', 'autocorrect': 'off',
560
+ 'autocapitalize': 'off', 'spellcheck': 'false', 'aria-invalid': 'false'
561
+ };
562
+ if (this.getModuleName() === 'datepicker') {
563
+ const l10nLocale: object = { placeholder: this.placeholder };
564
+ this.globalize = new Internationalization(this.locale);
565
+ this.l10n = new L10n('datepicker', l10nLocale, this.locale);
566
+ this.setProperties({ placeholder: this.placeholder || this.l10n.getConstant('placeholder') }, true);
567
+ }
568
+ if (this.fullScreenMode && Browser.isDevice){
569
+ this.cssClass += ' ' + 'e-popup-expand';
570
+ }
571
+ let updatedCssClassValues: string = this.cssClass;
572
+ if (!isNullOrUndefined(this.cssClass) && this.cssClass !== '') {
573
+ updatedCssClassValues = (this.cssClass.replace(/\s+/g, ' ')).trim();
574
+ }
575
+ const isBindClearAction: boolean = this.enableMask ? false : true;
576
+ this.inputWrapper = Input.createInput(
577
+ {
578
+ element: this.inputElement,
579
+ floatLabelType: this.floatLabelType,
580
+ bindClearAction: isBindClearAction,
581
+ properties: {
582
+ readonly: this.readonly,
583
+ placeholder: this.placeholder,
584
+ cssClass: updatedCssClassValues,
585
+ enabled: this.enabled,
586
+ enableRtl: this.enableRtl,
587
+ showClearButton: this.showClearButton
588
+ },
589
+ buttons: [INPUTWRAPPER + ' ' + DATEICON + ' ' + ICONS]
590
+ },
591
+ this.createElement
592
+ );
593
+ this.setWidth(this.width);
594
+ if (this.inputElement.name !== '') {
595
+ this.inputElement.setAttribute('name', '' + this.inputElement.getAttribute('name'));
596
+ } else {
597
+ this.inputElement.setAttribute('name', '' + this.element.id);
598
+ }
599
+ attributes(this.inputElement, <{ [key: string]: string }>ariaAttrs);
600
+ if (!this.inputElement.hasAttribute('aria-label')) {
601
+ this.inputElement.setAttribute('aria-label', this.getModuleName());
602
+ }
603
+ if (!this.enabled) {
604
+ this.inputElement.setAttribute('aria-disabled', 'true');
605
+ this.inputElement.tabIndex = -1;
606
+ } else {
607
+ this.inputElement.setAttribute('aria-disabled', 'false');
608
+ this.inputElement.setAttribute('tabindex', this.tabIndex);
609
+ }
610
+ Input.addAttributes({ 'aria-label': 'select', 'role': 'button' }, this.inputWrapper.buttons[0]);
611
+ addClass([this.inputWrapper.container], DATEWRAPPER);
612
+ }
613
+ protected updateInput(isDynamic: boolean = false, isBlur: boolean = false): void {
614
+ let formatOptions: DateFormatOptions;
615
+ if (this.value && !this.isCalendar()) {
616
+ this.disabledDates(isDynamic, isBlur);
617
+ }
618
+ if (isNaN(+new Date(this.checkValue(this.value)))) {
619
+ this.setProperties({ value: null }, true);
620
+ }
621
+ if (this.strictMode) {
622
+ //calls the Calendar processDate protected method to update the date value according to the strictMode true behaviour.
623
+ super.validateDate();
624
+ this.minMaxUpdates();
625
+ super.minMaxUpdate();
626
+ }
627
+ if (!isNullOrUndefined(this.value)) {
628
+ const dateValue: Date = this.value;
629
+ let dateString: string;
630
+ const tempFormat: string = !isNullOrUndefined(this.formatString) ? this.formatString : this.dateTimeFormat;
631
+ if (this.getModuleName() === 'datetimepicker') {
632
+ if (this.calendarMode === 'Gregorian') {
633
+ dateString = this.globalize.formatDate(this.value, {
634
+ format: tempFormat, type: 'dateTime', skeleton: 'yMd'
635
+ });
636
+ } else {
637
+ dateString = this.globalize.formatDate(this.value, {
638
+ format: tempFormat, type: 'dateTime', skeleton: 'yMd', calendar: 'islamic'
639
+ });
640
+ }
641
+ } else {
642
+ if (this.calendarMode === 'Gregorian') {
643
+ formatOptions = { format: this.formatString, type: 'dateTime', skeleton: 'yMd' };
644
+ } else {
645
+ formatOptions = { format: this.formatString, type: 'dateTime', skeleton: 'yMd', calendar: 'islamic' };
646
+ }
647
+ dateString = this.globalize.formatDate(this.value, formatOptions);
648
+ }
649
+ if ((+dateValue <= +this.max) && (+dateValue >= +this.min)) {
650
+ this.updateInputValue(dateString);
651
+ } else {
652
+ const value: boolean = (+dateValue >= +this.max || !+this.value) || (!+this.value || +dateValue <= +this.min);
653
+ if (!this.strictMode && value) {
654
+ this.updateInputValue(dateString);
655
+ }
656
+ }
657
+ }
658
+ if (isNullOrUndefined(this.value) && this.strictMode) {
659
+ if (!this.enableMask)
660
+ {
661
+ this.updateInputValue('');
662
+ }
663
+ else
664
+ {
665
+ this.updateInputValue(this.maskedDateValue);
666
+ this.notify('createMask', {
667
+ module: 'MaskedDateTime'
668
+ });
669
+ }
670
+ }
671
+ if (!this.strictMode && isNullOrUndefined(this.value) && this.invalidValueString) {
672
+ this.updateInputValue(this.invalidValueString);
673
+ }
674
+ this.changedArgs = { value: this.value };
675
+ this.errorClass();
676
+ this.updateIconState();
677
+ }
678
+ protected minMaxUpdates(): void {
679
+ if (!isNullOrUndefined(this.value) && this.value < this.min && this.min <= this.max && this.strictMode) {
680
+ this.setProperties({ value: this.min }, true);
681
+ this.changedArgs = { value: this.value };
682
+ } else {
683
+ if (!isNullOrUndefined(this.value) && this.value > this.max && this.min <= this.max && this.strictMode) {
684
+ this.setProperties({ value: this.max }, true);
685
+ this.changedArgs = { value: this.value };
686
+ }
687
+ }
688
+ }
689
+ private checkStringValue(val: string): Date {
690
+ let returnDate: Date = null;
691
+ let formatOptions: object = null;
692
+ let formatDateTime: object = null;
693
+ if (this.getModuleName() === 'datetimepicker') {
694
+ const culture: Internationalization = new Internationalization(this.locale);
695
+ if (this.calendarMode === 'Gregorian') {
696
+ formatOptions = { format: this.dateTimeFormat, type: 'dateTime', skeleton: 'yMd' };
697
+ formatDateTime = { format: culture.getDatePattern({ skeleton: 'yMd' }), type: 'dateTime' };
698
+ } else {
699
+ formatOptions = { format: this.dateTimeFormat, type: 'dateTime', skeleton: 'yMd', calendar: 'islamic' };
700
+ formatDateTime = { format: culture.getDatePattern({ skeleton: 'yMd' }), type: 'dateTime', calendar: 'islamic' };
701
+ }
702
+ } else {
703
+ if (this.calendarMode === 'Gregorian') {
704
+ formatOptions = { format: this.formatString, type: 'dateTime', skeleton: 'yMd' };
705
+ } else {
706
+ formatOptions = { format: this.formatString, type: 'dateTime', skeleton: 'yMd', calendar: 'islamic' };
707
+ }
708
+ }
709
+ returnDate = this.checkDateValue(this.globalize.parseDate(this.getAmPmValue(val), formatOptions));
710
+ if (isNullOrUndefined(returnDate) && (this.getModuleName() === 'datetimepicker')) {
711
+ returnDate = this.checkDateValue(this.globalize.parseDate(this.getAmPmValue(val), formatDateTime));
712
+ }
713
+ return returnDate;
714
+ }
715
+ protected checkInvalidValue(value: Date): void {
716
+ if (!(value instanceof Date) && !isNullOrUndefined(value)) {
717
+ let valueDate: Date = null;
718
+ let valueString: string = <string>value;
719
+ if (typeof value === 'number') {
720
+ valueString = (value as string).toString();
721
+ }
722
+ let formatOptions: object = null;
723
+ let formatDateTime: object = null;
724
+ if (this.getModuleName() === 'datetimepicker') {
725
+ const culture: Internationalization = new Internationalization(this.locale);
726
+ if (this.calendarMode === 'Gregorian') {
727
+ formatOptions = { format: this.dateTimeFormat, type: 'dateTime', skeleton: 'yMd' };
728
+ formatDateTime = { format: culture.getDatePattern({ skeleton: 'yMd' }), type: 'dateTime' };
729
+ } else {
730
+ formatOptions = { format: this.dateTimeFormat, type: 'dateTime', skeleton: 'yMd', calendar: 'islamic' };
731
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
732
+ formatDateTime = { format: culture.getDatePattern({ skeleton: 'yMd' }), type: 'dateTime', calendar: 'islamic' };
733
+ }
734
+ } else {
735
+ if (this.calendarMode === 'Gregorian') {
736
+ formatOptions = { format: this.formatString, type: 'dateTime', skeleton: 'yMd' };
737
+ } else {
738
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
739
+ formatOptions = { format: this.formatString, type: 'dateTime', skeleton: 'yMd', calendar: 'islamic' };
740
+ }
741
+ }
742
+ let invalid: boolean = false;
743
+ if (typeof valueString !== 'string') {
744
+ valueString = null;
745
+ invalid = true;
746
+ } else {
747
+ if (typeof valueString === 'string') {
748
+ valueString = valueString.trim();
749
+ }
750
+ valueDate = this.checkStringValue(valueString);
751
+ if (!valueDate) {
752
+ let extISOString: RegExp = null;
753
+ let basicISOString: RegExp = null;
754
+ // eslint-disable-next-line
755
+ extISOString = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/;
756
+ // eslint-disable-next-line
757
+ basicISOString = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/;
758
+ if ((!extISOString.test(valueString) && !basicISOString.test(valueString))
759
+ || (/^[a-zA-Z0-9- ]*$/).test(valueString) || isNaN(+new Date(this.checkValue(valueString)))) {
760
+ invalid = true;
761
+ } else {
762
+ valueDate = new Date(valueString);
763
+ }
764
+ }
765
+ }
766
+ if (invalid) {
767
+ if (!this.strictMode) {
768
+ this.invalidValueString = valueString;
769
+ }
770
+ this.setProperties({ value: null }, true);
771
+ } else {
772
+ this.setProperties({ value: valueDate }, true);
773
+ }
774
+ }
775
+ }
776
+ private bindInputEvent(): void {
777
+ if (!isNullOrUndefined(this.formatString) || this.enableMask) {
778
+ if (this.enableMask || this.formatString.indexOf('y') === -1) {
779
+ EventHandler.add(this.inputElement, 'input', this.inputHandler, this);
780
+ } else {
781
+ EventHandler.remove(this.inputElement, 'input', this.inputHandler);
782
+ }
783
+ }
784
+ }
785
+ protected bindEvents(): void {
786
+ EventHandler.add(this.inputWrapper.buttons[0], 'mousedown', this.dateIconHandler, this);
787
+ EventHandler.add(this.inputElement, 'mouseup', this.mouseUpHandler, this);
788
+ EventHandler.add(this.inputElement, 'focus', this.inputFocusHandler, this);
789
+ EventHandler.add(this.inputElement, 'blur', this.inputBlurHandler, this);
790
+ EventHandler.add(this.inputElement, 'keyup', this.keyupHandler, this);
791
+ if (this.enableMask){
792
+ EventHandler.add(this.inputElement, 'keydown', this.keydownHandler, this);
793
+ }
794
+ this.bindInputEvent();
795
+ // To prevent the twice triggering.
796
+ EventHandler.add(this.inputElement, 'change', this.inputChangeHandler, this);
797
+ if (this.showClearButton && this.inputWrapper.clearButton) {
798
+ EventHandler.add(this.inputWrapper.clearButton, 'mousedown touchstart', this.resetHandler, this);
799
+ }
800
+ if (this.formElement) {
801
+ EventHandler.add(this.formElement, 'reset', this.resetFormHandler, this);
802
+ }
803
+ this.defaultKeyConfigs = (extend(this.defaultKeyConfigs, this.keyConfigs) as { [key: string]: string });
804
+ this.keyboardModules = new KeyboardEvents(
805
+ <HTMLElement>this.inputElement,
806
+ {
807
+ eventName: 'keydown',
808
+ keyAction: this.inputKeyActionHandle.bind(this),
809
+ keyConfigs: this.defaultKeyConfigs
810
+ });
811
+ }
812
+
813
+ private keydownHandler(e: KeyboardEventArgs): void{
814
+ switch (e.code)
815
+ {
816
+ case 'ArrowLeft':
817
+ case 'ArrowRight' :
818
+ case 'ArrowUp':
819
+ case 'ArrowDown':
820
+ case 'Home':
821
+ case 'End':
822
+ case 'Backspace':
823
+ case 'Delete':
824
+ if (this.enableMask && !this.popupObj && !this.readonly)
825
+ {
826
+ if (e.code !== 'Delete' && e.code !== 'Backspace')
827
+ {
828
+ e.preventDefault();
829
+ }
830
+ this.notify('keyDownHandler', {
831
+ module: 'MaskedDateTime' ,
832
+ e: e
833
+ });
834
+ }
835
+ break;
836
+
837
+ default:
838
+ break;
839
+ }
840
+ }
841
+
842
+ protected unBindEvents() : void {
843
+ if (!isNullOrUndefined(this.inputWrapper))
844
+ {
845
+ EventHandler.remove(this.inputWrapper.buttons[0], 'mousedown', this.dateIconHandler);
846
+ }
847
+ EventHandler.remove(this.inputElement, 'mouseup', this.mouseUpHandler);
848
+ EventHandler.remove(this.inputElement, 'focus', this.inputFocusHandler);
849
+ EventHandler.remove(this.inputElement, 'blur', this.inputBlurHandler);
850
+ EventHandler.remove(this.inputElement, 'change', this.inputChangeHandler);
851
+ EventHandler.remove(this.inputElement, 'keyup', this.keyupHandler);
852
+ if (this.enableMask){
853
+ EventHandler.remove(this.inputElement, 'keydown', this.keydownHandler);
854
+ }
855
+ if (this.showClearButton && this.inputWrapper.clearButton) {
856
+ EventHandler.remove(this.inputWrapper.clearButton, 'mousedown touchstart', this.resetHandler);
857
+ }
858
+ if (this.formElement) {
859
+ EventHandler.remove(this.formElement, 'reset', this.resetFormHandler);
860
+ }
861
+ }
862
+ protected resetFormHandler(): void {
863
+ if (!this.enabled) {
864
+ return;
865
+ }
866
+ if (!this.inputElement.disabled) {
867
+ let value: string = this.inputElement.getAttribute('value');
868
+ if (this.element.tagName === 'EJS-DATEPICKER' || this.element.tagName === 'EJS-DATETIMEPICKER') {
869
+ value = '';
870
+ this.inputValueCopy = null;
871
+ this.inputElement.setAttribute('value', '');
872
+ }
873
+ this.setProperties({ value: this.inputValueCopy }, true);
874
+ this.restoreValue();
875
+ if (this.inputElement) {
876
+ this.updateInputValue(value);
877
+ this.errorClass();
878
+ }
879
+ }
880
+ }
881
+ protected restoreValue(): void {
882
+ this.currentDate = this.value ? this.value : new Date();
883
+ this.previousDate = this.value;
884
+ this.previousElementValue = (isNullOrUndefined(this.inputValueCopy)) ? '' :
885
+ this.globalize.formatDate(this.inputValueCopy, {
886
+ format: this.formatString, type: 'dateTime', skeleton: 'yMd'
887
+ });
888
+ }
889
+ private inputChangeHandler(e: MouseEvent): void {
890
+ if (!this.enabled) {
891
+ return;
892
+ }
893
+ e.stopPropagation();
894
+ }
895
+ private bindClearEvent(): void {
896
+ if (this.showClearButton && this.inputWrapper.clearButton) {
897
+ EventHandler.add(this.inputWrapper.clearButton, 'mousedown touchstart', this.resetHandler, this);
898
+ }
899
+ }
900
+ protected resetHandler(e?: MouseEvent): void {
901
+ if (!this.enabled) {
902
+ return;
903
+ }
904
+ e.preventDefault();
905
+ this.clear(e);
906
+ }
907
+ private mouseUpHandler(e? : MouseEvent): void{
908
+ if (this.enableMask)
909
+ {
910
+ e.preventDefault();
911
+ this.notify('setMaskSelection', {
912
+ module: 'MaskedDateTime'
913
+ });
914
+ }
915
+ }
916
+ private clear(event: MouseEvent): void {
917
+ this.setProperties({ value: null }, true);
918
+ if (!this.enableMask)
919
+ {
920
+ this.updateInputValue('');
921
+ }
922
+ const clearedArgs: ClearedEventArgs = {
923
+ event: event
924
+ };
925
+ this.trigger('cleared', clearedArgs);
926
+ this.invalidValueString = '';
927
+ this.updateInput();
928
+ this.popupUpdate();
929
+ this.changeEvent(event);
930
+ if (this.enableMask)
931
+ {
932
+ this.notify('clearHandler', {
933
+ module: 'MaskedDateTime'
934
+ });
935
+ }
936
+ if (closest(this.element, 'form')) {
937
+ const element: Element = this.element;
938
+ const keyupEvent: KeyboardEvent = document.createEvent('KeyboardEvent');
939
+ keyupEvent.initEvent('keyup', false, true);
940
+ element.dispatchEvent(keyupEvent);
941
+ }
942
+ }
943
+
944
+
945
+ private preventEventBubbling(e?: MouseEvent): void {
946
+ e.preventDefault();
947
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
948
+ (this as any).interopAdaptor.invokeMethodAsync('OnDateIconClick');
949
+ }
950
+
951
+ private updateInputValue(value?: string): void {
952
+ Input.setValue(value, this.inputElement, this.floatLabelType, this.showClearButton);
953
+ }
954
+
955
+ private dateIconHandler(e?: MouseEvent): void {
956
+ if (!this.enabled) {
957
+ return;
958
+ }
959
+ this.isIconClicked = true;
960
+ if (Browser.isDevice) {
961
+ this.inputElement.setAttribute('readonly', '');
962
+ this.inputElement.blur();
963
+ }
964
+ e.preventDefault();
965
+ if (!this.readonly) {
966
+ if (this.isCalendar()) {
967
+ this.hide(e);
968
+ } else {
969
+ this.isDateIconClicked = true;
970
+ this.show(null, e);
971
+ if (this.getModuleName() === 'datetimepicker') {
972
+ (this.inputElement as HTMLElement).focus();
973
+ }
974
+ (<HTMLElement>this.inputElement).focus();
975
+ addClass([this.inputWrapper.container], [INPUTFOCUS]);
976
+ addClass(this.inputWrapper.buttons, ACTIVE);
977
+ }
978
+ }
979
+ this.isIconClicked = false;
980
+ }
981
+ protected updateHtmlAttributeToWrapper(): void {
982
+ if (!isNullOrUndefined(this.htmlAttributes)) {
983
+ for (const key of Object.keys(this.htmlAttributes)) {
984
+ if (!isNullOrUndefined(this.htmlAttributes[`${key}`])) {
985
+ if (containerAttr.indexOf(key) > -1) {
986
+ if (key === 'class') {
987
+ const updatedClassValues : string = (this.htmlAttributes[`${key}`].replace(/\s+/g, ' ')).trim();
988
+ if (updatedClassValues !== '') {
989
+ addClass([this.inputWrapper.container], updatedClassValues.split(' '));
990
+ }
991
+ } else if (key === 'style') {
992
+ let setStyle: string = this.inputWrapper.container.getAttribute(key);
993
+ if (!isNullOrUndefined(setStyle)) {
994
+ if (setStyle.charAt(setStyle.length - 1) === ';') {
995
+ setStyle = setStyle + this.htmlAttributes[`${key}`];
996
+ } else {
997
+ setStyle = setStyle + ';' + this.htmlAttributes[`${key}`];
998
+ }
999
+ } else {
1000
+ setStyle = this.htmlAttributes[`${key}`];
1001
+ }
1002
+ this.inputWrapper.container.setAttribute(key, setStyle);
1003
+ } else {
1004
+ this.inputWrapper.container.setAttribute(key, this.htmlAttributes[`${key}`]);
1005
+ }
1006
+ }
1007
+ }
1008
+ }
1009
+ }
1010
+ }
1011
+
1012
+ protected updateHtmlAttributeToElement(): void {
1013
+ if ( !isNullOrUndefined(this.htmlAttributes)) {
1014
+ for (const key of Object.keys(this.htmlAttributes)) {
1015
+ if (containerAttr.indexOf(key) < 0 ) {
1016
+ this.inputElement.setAttribute(key, this.htmlAttributes[`${key}`]);
1017
+ }
1018
+ }
1019
+ }
1020
+ }
1021
+ private updateCssClass(newCssClass : string, oldCssClass : string) : void {
1022
+ if (!isNullOrUndefined(oldCssClass)) {
1023
+ oldCssClass = (oldCssClass.replace(/\s+/g, ' ')).trim();
1024
+ }
1025
+ if (!isNullOrUndefined(newCssClass)) {
1026
+ newCssClass = (newCssClass.replace(/\s+/g, ' ')).trim();
1027
+ }
1028
+ Input.setCssClass(newCssClass, [this.inputWrapper.container], oldCssClass);
1029
+ if (this.popupWrapper) {
1030
+ Input.setCssClass(newCssClass, [this.popupWrapper], oldCssClass);
1031
+ }
1032
+ }
1033
+ private calendarKeyActionHandle(e: KeyboardEventArgs): void {
1034
+ switch (e.action) {
1035
+ case 'escape':
1036
+ if (this.isCalendar()) {
1037
+ this.hide(e);
1038
+ } else {
1039
+ (this.inputWrapper.container.children[this.index] as HTMLElement).blur();
1040
+ }
1041
+ break;
1042
+ case 'enter':
1043
+ if (!this.isCalendar()) {
1044
+ this.show(null, e);
1045
+ } else {
1046
+ if (+this.value !== +this.currentDate && !this.isCalendar()) {
1047
+ (this.inputWrapper.container.children[this.index] as HTMLElement).focus();
1048
+ }
1049
+ }
1050
+ if (this.getModuleName() === 'datetimepicker') {
1051
+ this.inputElement.focus();
1052
+ }
1053
+ break;
1054
+ }
1055
+ }
1056
+ private inputFocusHandler(): void {
1057
+ this.isFocused = true;
1058
+ if (!this.enabled) {
1059
+ return;
1060
+ }
1061
+ if (this.enableMask && !this.inputElement.value && this.placeholder)
1062
+ {
1063
+ if (this.maskedDateValue && !this.value && (this.floatLabelType === 'Auto' || this.floatLabelType === 'Never' || this.placeholder))
1064
+ {
1065
+ this.updateInputValue(this.maskedDateValue);
1066
+ this.inputElement.selectionStart = 0;
1067
+ this.inputElement.selectionEnd = this.inputElement.value.length;
1068
+ }
1069
+ }
1070
+ if (this.enableMask && this.showClearButton && this.inputElement && this.inputElement.value === this.maskedDateValue && this.inputWrapper && this.inputWrapper.clearButton && !this.inputWrapper.clearButton.classList.contains('e-clear-icon-hide')) {
1071
+ this.inputWrapper.clearButton.classList.add('e-clear-icon-hide');
1072
+ }
1073
+ const focusArguments: BlurEventArgs = {
1074
+ model: this
1075
+ };
1076
+ this.isDateIconClicked = false;
1077
+ this.trigger('focus', focusArguments);
1078
+ this.updateIconState();
1079
+ if (this.openOnFocus && !this.isIconClicked) {
1080
+ this.show();
1081
+ }
1082
+ }
1083
+ private inputHandler(e?: any): void {
1084
+ this.isPopupClicked = false;
1085
+ if (this.enableMask)
1086
+ {
1087
+ if (!isNullOrUndefined(e) && !isNullOrUndefined(e.inputType) && e.inputType === 'insertFromPaste') {
1088
+ this.notify('maskPasteInputHandler', {
1089
+ module: 'MaskedDateTime'
1090
+ });
1091
+ }
1092
+ else {
1093
+ this.notify('inputHandler', {
1094
+ module: 'MaskedDateTime'
1095
+ });
1096
+ }
1097
+ }
1098
+ }
1099
+ private inputBlurHandler(e: MouseEvent): void {
1100
+ if (!this.enabled) {
1101
+ return;
1102
+ }
1103
+ this.strictModeUpdate();
1104
+ if (this.inputElement.value === '' && isNullOrUndefined(this.value)) {
1105
+ this.invalidValueString = null;
1106
+ this.updateInputValue('');
1107
+ }
1108
+ this.isBlur = true;
1109
+ this.updateInput(false, true);
1110
+ this.isBlur = false;
1111
+ this.popupUpdate();
1112
+ this.changeTrigger(e);
1113
+ if (this.enableMask && this.maskedDateValue && this.placeholder && this.floatLabelType !== 'Always' )
1114
+ {
1115
+ if (this.inputElement.value === this.maskedDateValue && !this.value && (this.floatLabelType === 'Auto' || this.floatLabelType === 'Never' || this.placeholder))
1116
+ {
1117
+ this.updateInputValue('');
1118
+ }
1119
+ }
1120
+ this.errorClass();
1121
+ if (this.isCalendar() && document.activeElement === this.inputElement) {
1122
+ this.hide(e);
1123
+ }
1124
+ if (this.getModuleName() === 'datepicker') {
1125
+ const blurArguments: BlurEventArgs = {
1126
+ model: this
1127
+ };
1128
+ this.trigger('blur', blurArguments);
1129
+ }
1130
+ if (this.isCalendar()) {
1131
+ this.defaultKeyConfigs = (extend(this.defaultKeyConfigs, this.keyConfigs) as { [key: string]: string });
1132
+ this.calendarKeyboardModules = new KeyboardEvents(<HTMLElement>this.calendarElement.children[1].firstElementChild, {
1133
+ eventName: 'keydown',
1134
+ keyAction: this.calendarKeyActionHandle.bind(this),
1135
+ keyConfigs: this.defaultKeyConfigs
1136
+ });
1137
+ }
1138
+ this.isPopupClicked = false;
1139
+ }
1140
+ private documentHandler(e: MouseEvent): void {
1141
+ if ((!isNullOrUndefined(this.popupObj) && !isNullOrUndefined(this.inputWrapper) && (this.inputWrapper.container.contains(<HTMLElement>e.target) && e.type !== 'mousedown' ||
1142
+ (this.popupObj.element && this.popupObj.element.contains(<HTMLElement>e.target)))) && e.type !== 'touchstart') {
1143
+ e.preventDefault();
1144
+ }
1145
+ const target: HTMLElement = <HTMLElement>e.target;
1146
+ if (!(closest(target, '.e-datepicker.e-popup-wrapper')) && !isNullOrUndefined(this.inputWrapper)
1147
+ && !(closest(target, '.' + INPUTCONTAINER) === this.inputWrapper.container)
1148
+ && (!target.classList.contains('e-day'))) {
1149
+ this.hide(e);
1150
+ if (target.classList.contains('e-dlg-overlay')) {
1151
+ e.preventDefault();
1152
+ } else {
1153
+ this.focusOut();
1154
+ }
1155
+ } else if (closest(target, '.e-datepicker.e-popup-wrapper')) {
1156
+ // Fix for close the popup when select the previously selected value.
1157
+ if ( target.classList.contains('e-day')
1158
+ && !isNullOrUndefined((e.target as HTMLElement).parentElement)
1159
+ && (e.target as HTMLElement).parentElement.classList.contains('e-selected')
1160
+ && closest(target, '.e-content')
1161
+ && closest(target, '.e-content').classList.contains('e-' + this.depth.toLowerCase())) {
1162
+ this.hide(e);
1163
+ } else if (closest(target, '.e-footer-container')
1164
+ && target.classList.contains('e-today')
1165
+ && target.classList.contains('e-btn')
1166
+ && (+new Date(+this.value) === +super.generateTodayVal(this.value))) {
1167
+ this.hide(e);
1168
+ }
1169
+ }
1170
+ }
1171
+
1172
+ protected inputKeyActionHandle(e: KeyboardEventArgs): void {
1173
+ const clickedView: string = this.currentView();
1174
+ switch (e.action) {
1175
+ case 'altUpArrow':
1176
+ this.isAltKeyPressed = false;
1177
+ this.hide(e);
1178
+ this.inputElement.focus();
1179
+ break;
1180
+ case 'altDownArrow':
1181
+ this.isAltKeyPressed = true;
1182
+ this.strictModeUpdate();
1183
+ this.updateInput();
1184
+ this.changeTrigger(e);
1185
+ if (this.getModuleName() === 'datepicker') {
1186
+ this.show(null, e);
1187
+ }
1188
+ break;
1189
+ case 'escape':
1190
+ this.hide(e);
1191
+ break;
1192
+ case 'enter':
1193
+ this.strictModeUpdate();
1194
+ this.updateInput();
1195
+ this.popupUpdate();
1196
+ this.changeTrigger(e);
1197
+ this.errorClass();
1198
+ if (!this.isCalendar() && document.activeElement === this.inputElement) {
1199
+ this.hide(e);
1200
+ }
1201
+ if (this.isCalendar()) {
1202
+ e.preventDefault();
1203
+ e.stopPropagation();
1204
+ }
1205
+ break;
1206
+ case 'tab':
1207
+ case 'shiftTab':
1208
+ {
1209
+ let start: number = this.inputElement.selectionStart;
1210
+ let end: number = this.inputElement.selectionEnd;
1211
+ if (this.enableMask && !this.popupObj && !this.readonly)
1212
+ {
1213
+ const length: number = this.inputElement.value.length;
1214
+ if ((start === 0 && end === length) || (end !== length && e.action === 'tab') || (start !== 0 && e.action === 'shiftTab'))
1215
+ {
1216
+ e.preventDefault();
1217
+ }
1218
+ this.notify('keyDownHandler', {
1219
+ module: 'MaskedDateTime' ,
1220
+ e: e
1221
+ });
1222
+ start = this.inputElement.selectionStart;
1223
+ end = this.inputElement.selectionEnd;
1224
+ }
1225
+ this.strictModeUpdate();
1226
+ this.updateInput();
1227
+ this.popupUpdate();
1228
+ this.changeTrigger(e);
1229
+ this.errorClass();
1230
+ if (this.enableMask)
1231
+ {
1232
+ this.inputElement.selectionStart = start ;
1233
+ this.inputElement.selectionEnd = end;
1234
+ }
1235
+ if (e.action === 'tab' && e.target === this.inputElement && this.isCalendar() && document.activeElement === this.inputElement) {
1236
+ e.preventDefault();
1237
+ this.headerTitleElement.focus();
1238
+ }
1239
+ if (e.action === 'shiftTab' && e.target === this.inputElement && this.isCalendar() && document.activeElement === this.inputElement) {
1240
+ this.hide(e);
1241
+ }
1242
+ break;
1243
+ }
1244
+ default:
1245
+ this.defaultAction(e);
1246
+ // Fix for close the popup when select the previously selected value.
1247
+ if (e.action === 'select' && clickedView === this.depth) {
1248
+ this.hide(e);
1249
+ }
1250
+ }
1251
+ }
1252
+ protected defaultAction(e: KeyboardEventArgs): void {
1253
+ this.previousDate = ((!isNullOrUndefined(this.value) && new Date(+this.value)) || null);
1254
+ if (this.isCalendar()) {
1255
+ super.keyActionHandle(e);
1256
+ if (this.isCalendar()) {
1257
+ attributes(this.inputElement, {
1258
+ 'aria-activedescendant': '' + this.setActiveDescendant()
1259
+ });
1260
+ }
1261
+ }
1262
+ }
1263
+ protected popupUpdate(): void {
1264
+ if ((isNullOrUndefined(this.value)) && (!isNullOrUndefined(this.previousDate)) ||
1265
+ (((this.getModuleName() !== 'datetimepicker') && (+this.value !== +this.previousDate)) || ((this.getModuleName() === 'datetimepicker') && (+this.value !== +this.previousDateTime)))) {
1266
+ if (this.popupObj) {
1267
+ if (this.popupObj.element.querySelectorAll('.' + SELECTED).length > 0) {
1268
+ removeClass(this.popupObj.element.querySelectorAll('.' + SELECTED), [SELECTED]);
1269
+ }
1270
+ }
1271
+ if (!isNullOrUndefined(this.value)) {
1272
+ if ((+this.value >= +this.min) && (+this.value <= +this.max)) {
1273
+ const targetdate: Date = new Date(this.checkValue(this.value));
1274
+ super.navigateTo('Month', targetdate);
1275
+ }
1276
+ }
1277
+ }
1278
+ }
1279
+ protected strictModeUpdate(): void {
1280
+ let format: string;
1281
+ const pattern: RegExp = /^y/ ;
1282
+ const charPattern: RegExp = /[^a-zA-Z]/;
1283
+ let formatOptions: DateFormatOptions;
1284
+ if (this.getModuleName() === 'datetimepicker') {
1285
+ format = !isNullOrUndefined(this.formatString) ? this.formatString : this.dateTimeFormat;
1286
+ } else if (!pattern.test(this.formatString) || charPattern.test(this.formatString)) {
1287
+ format = isNullOrUndefined(this.formatString) ? this.formatString : this.formatString.replace('dd', 'd');
1288
+ }
1289
+ if (!isNullOrUndefined(format)) {
1290
+ const len: number = format.split('M').length - 1;
1291
+ if (len < 3) {
1292
+ format = format.replace('MM', 'M');
1293
+ }
1294
+ }
1295
+ else {
1296
+ format = this.formatString;
1297
+ }
1298
+ let dateOptions: object;
1299
+ if (this.getModuleName() === 'datetimepicker') {
1300
+ if (this.calendarMode === 'Gregorian') {
1301
+ dateOptions = {
1302
+ format: !isNullOrUndefined(this.formatString) ? this.formatString : this.dateTimeFormat,
1303
+ type: 'dateTime', skeleton: 'yMd'
1304
+ };
1305
+ } else {
1306
+ dateOptions = {
1307
+ format: !isNullOrUndefined(this.formatString) ? this.formatString : this.dateTimeFormat,
1308
+ type: 'dateTime', skeleton: 'yMd', calendar: 'islamic'
1309
+ };
1310
+ }
1311
+
1312
+ } else {
1313
+ if (this.calendarMode === 'Gregorian') {
1314
+ formatOptions = { format: format, type: 'dateTime', skeleton: 'yMd' };
1315
+ } else {
1316
+ formatOptions = { format: format, type: 'dateTime', skeleton: 'yMd', calendar: 'islamic' };
1317
+ }
1318
+ dateOptions = formatOptions;
1319
+ }
1320
+ let date: Date;
1321
+ if (typeof this.inputElement.value === 'string') {
1322
+ this.inputElement.value = this.inputElement.value.trim();
1323
+ }
1324
+ if ((this.getModuleName() === 'datetimepicker')) {
1325
+ if (this.checkDateValue(this.globalize.parseDate(this.getAmPmValue(this.inputElement.value), dateOptions))) {
1326
+ date = this.globalize.parseDate(this.getAmPmValue(this.inputElement.value), dateOptions);
1327
+ } else {
1328
+ if (this.calendarMode === 'Gregorian') {
1329
+ formatOptions = { format: format, type: 'dateTime', skeleton: 'yMd' };
1330
+ } else {
1331
+ formatOptions = { format: format, type: 'dateTime', skeleton: 'yMd', calendar: 'islamic' };
1332
+ }
1333
+ date = this.globalize.parseDate(this.getAmPmValue(this.inputElement.value), formatOptions);
1334
+ }
1335
+ if ((isNullOrUndefined(date) || (typeof (date) === 'object' && isNaN(date.getTime())))
1336
+ && !isNullOrUndefined(this.inputFormatsString)) {
1337
+ for (const format of this.inputFormatsString) {
1338
+ let inputFormatOptions: DateFormatOptions;
1339
+ if (this.calendarMode === 'Gregorian') {
1340
+ inputFormatOptions = { format: format, type: 'dateTime', skeleton: 'yMd' };
1341
+ } else {
1342
+ inputFormatOptions = { format: format, type: 'dateTime', skeleton: 'yMd', calendar: 'islamic' };
1343
+ }
1344
+ date = this.globalize.parseDate(this.getAmPmValue(this.inputElement.value), inputFormatOptions);
1345
+ if (!isNullOrUndefined(date) && date instanceof Date && !isNaN(date.getTime())) {
1346
+ break;
1347
+ }
1348
+ }
1349
+ }
1350
+ } else {
1351
+ date = this.globalize.parseDate(this.getAmPmValue(this.inputElement.value), dateOptions);
1352
+ if ((isNullOrUndefined(date) || (typeof (date) === 'object' && isNaN(date.getTime())))
1353
+ && !isNullOrUndefined(this.inputFormatsString)) {
1354
+ for (const format of this.inputFormatsString) {
1355
+ let inputFormatOptions: DateFormatOptions;
1356
+ if (this.calendarMode === 'Gregorian') {
1357
+ inputFormatOptions = { format: format, type: 'dateTime', skeleton: 'yMd' };
1358
+ } else {
1359
+ inputFormatOptions = { format: format, type: 'dateTime', skeleton: 'yMd', calendar: 'islamic' };
1360
+ }
1361
+ date = this.globalize.parseDate(this.getAmPmValue(this.inputElement.value), inputFormatOptions);
1362
+ if (!isNullOrUndefined(date) && date instanceof Date && !isNaN(date.getTime())) {
1363
+ break;
1364
+ }
1365
+ }
1366
+ }
1367
+ date = (!isNullOrUndefined(date) && isNaN(+date)) ? null : date;
1368
+ if (!isNullOrUndefined(this.formatString) && this.inputElement.value !== '' && this.strictMode) {
1369
+ if ((this.isPopupClicked || (!this.isPopupClicked && this.inputElement.value === this.previousElementValue))
1370
+ && this.formatString.indexOf('y') === -1) {
1371
+ date.setFullYear(this.value.getFullYear());
1372
+ }
1373
+ }
1374
+ }
1375
+ // EJ2-35061 - To prevent change event from triggering twice when using strictmode and format property
1376
+ if ((this.getModuleName() === 'datepicker') && (this.value && !isNaN(+this.value)) && date) {
1377
+ date.setHours(this.value.getHours(), this.value.getMinutes(), this.value.getSeconds(), this.value.getMilliseconds());
1378
+ }
1379
+ if (this.strictMode && date) {
1380
+ this.updateInputValue(this.globalize.formatDate(date, dateOptions));
1381
+ if (this.inputElement.value !== this.previousElementValue) {
1382
+ this.setProperties({ value: date }, true);
1383
+ }
1384
+ } else if (!this.strictMode) {
1385
+ if (this.inputElement.value !== this.previousElementValue) {
1386
+ this.setProperties({ value: date }, true);
1387
+ }
1388
+ }
1389
+ if (this.strictMode && !date && this.inputElement.value === (this.enableMask ? this.maskedDateValue : '')) {
1390
+ this.setProperties({ value: null }, true);
1391
+ }
1392
+ if (isNaN(+this.value)) {
1393
+ this.setProperties({ value: null }, true);
1394
+ }
1395
+ if (isNullOrUndefined(this.value)) {
1396
+ this.currentDate = new Date(new Date().setHours(0, 0, 0, 0));
1397
+ }
1398
+ }
1399
+ private createCalendar(): void {
1400
+ this.popupWrapper = this.createElement('div', { className: '' + ROOT + ' ' + POPUPWRAPPER, id: this.inputElement.id + '_options' });
1401
+ this.popupWrapper.setAttribute( 'aria-label', this.element.id );
1402
+ this.popupWrapper.setAttribute( 'role', 'dialog' );
1403
+ if (!isNullOrUndefined(this.cssClass)) {
1404
+ this.popupWrapper.className += ' ' + this.cssClass;
1405
+ }
1406
+ if (Browser.isDevice) {
1407
+ this.modelHeader();
1408
+ this.modal = this.createElement('div');
1409
+ this.modal.className = '' + ROOT + ' e-date-modal';
1410
+ document.body.className += ' ' + OVERFLOW;
1411
+ this.modal.style.display = 'block';
1412
+ document.body.appendChild(this.modal);
1413
+ }
1414
+ //this.calendarElement represent the Calendar object from the Calendar class.
1415
+ this.calendarElement.querySelector('table tbody').className = '';
1416
+ this.popupObj = new Popup(this.popupWrapper as HTMLElement, {
1417
+ content: this.calendarElement,
1418
+ relateTo: Browser.isDevice ? document.body : this.inputWrapper.container,
1419
+ position: Browser.isDevice ? { X: 'center', Y: 'center' } : (this.enableRtl ? { X: 'right', Y: 'bottom' } : { X: 'left', Y: 'bottom' }),
1420
+ offsetY: OFFSETVALUE,
1421
+ targetType: 'container',
1422
+ enableRtl: this.enableRtl,
1423
+ zIndex: this.zIndex,
1424
+ collision: Browser.isDevice ? { X: 'fit', Y: 'fit' } : (this.enableRtl ? { X: 'fit', Y: 'flip' } : { X: 'flip', Y: 'flip' }),
1425
+ open: () => {
1426
+ if (Browser.isDevice && this.fullScreenMode) {
1427
+ this.iconRight = parseInt(window.getComputedStyle(this.calendarElement.querySelector('.e-header.e-month .e-prev')).marginRight, 10) > 16 ? true : false;
1428
+ this.touchModule = new Touch(<HTMLElement>this.calendarElement.querySelector('.e-content.e-month'), {
1429
+ swipe: this.CalendarSwipeHandler.bind(this)
1430
+ });
1431
+ EventHandler.add(<HTMLElement>this.calendarElement.querySelector('.e-content.e-month'), 'touchstart', this.TouchStartHandler, this);
1432
+ }
1433
+ if (this.getModuleName() !== 'datetimepicker') {
1434
+ if (document.activeElement !== this.inputElement) {
1435
+ this.defaultKeyConfigs = (extend(this.defaultKeyConfigs, this.keyConfigs) as { [key: string]: string });
1436
+ (<HTMLElement>this.calendarElement.children[1].firstElementChild).focus();
1437
+ this.calendarKeyboardModules = new KeyboardEvents(
1438
+ <HTMLElement>this.calendarElement.children[1].firstElementChild,
1439
+ {
1440
+ eventName: 'keydown',
1441
+ keyAction: this.calendarKeyActionHandle.bind(this),
1442
+ keyConfigs: this.defaultKeyConfigs
1443
+ });
1444
+ this.calendarKeyboardModules = new KeyboardEvents(
1445
+ <HTMLElement>this.inputWrapper.container.children[this.index],
1446
+ {
1447
+ eventName: 'keydown',
1448
+ keyAction: this.calendarKeyActionHandle.bind(this),
1449
+ keyConfigs: this.defaultKeyConfigs
1450
+ });
1451
+ }
1452
+ }
1453
+ }, close: () => {
1454
+ if (this.isDateIconClicked) {
1455
+ (this.inputWrapper.container.children[this.index] as HTMLElement).focus();
1456
+ }
1457
+ if (this.value) {
1458
+ this.disabledDates();
1459
+ }
1460
+ if (this.popupObj) {
1461
+ this.popupObj.destroy();
1462
+ }
1463
+ this.resetCalendar();
1464
+ detach(this.popupWrapper);
1465
+ this.popupObj = this.popupWrapper = null;
1466
+ this.preventArgs = null;
1467
+ this.calendarKeyboardModules = null;
1468
+ this.setAriaAttributes();
1469
+ }, targetExitViewport: () => {
1470
+ if (!Browser.isDevice) {
1471
+ this.hide();
1472
+ }
1473
+ }
1474
+ });
1475
+ this.popupObj.element.className += ' ' + this.cssClass;
1476
+ this.setAriaAttributes();
1477
+ }
1478
+
1479
+ protected getAmPmValue(date: string | null | undefined): string {
1480
+ try {
1481
+ if (typeof date === 'string' && date.trim() !== '') {
1482
+ // Replace am/pm variants with uppercase AM/PM
1483
+ return date.replace(/(am|pm|Am|aM|pM|Pm)/g, (match: string) => match.toLocaleUpperCase());
1484
+ }
1485
+ // If date is null, undefined, or an empty string, return a default value or empty string
1486
+ return '';
1487
+ } catch (error) {
1488
+ console.error('Error occurred while processing date:', error);
1489
+ return ''; // Return a default value in case of an error
1490
+ }
1491
+ }
1492
+
1493
+ private CalendarSwipeHandler(e: SwipeEventArgs): void {
1494
+ let direction: number = 0;
1495
+ if (this.iconRight) {
1496
+ switch (e.swipeDirection) {
1497
+ case 'Left':
1498
+ direction = 1;
1499
+ break;
1500
+ case 'Right':
1501
+ direction = -1;
1502
+ break;
1503
+ default:
1504
+ break;
1505
+ }
1506
+ } else {
1507
+ switch (e.swipeDirection) {
1508
+ case 'Up':
1509
+ direction = 1;
1510
+ break;
1511
+ case 'Down':
1512
+ direction = -1;
1513
+ break;
1514
+ default:
1515
+ break;
1516
+ }
1517
+ }
1518
+ if (this.touchStart) {
1519
+ if (direction === 1) {
1520
+ this.navigateNext(e);
1521
+ } else if (direction === -1) {
1522
+ this.navigatePrevious(e);
1523
+ }
1524
+ this.touchStart = false;
1525
+ }
1526
+ }
1527
+
1528
+ private TouchStartHandler(e: MouseEvent): void {
1529
+ this.touchStart = true;
1530
+ }
1531
+
1532
+ private setAriaDisabled(): void {
1533
+ if (!this.enabled) {
1534
+ this.inputElement.setAttribute('aria-disabled', 'true');
1535
+ this.inputElement.tabIndex = -1;
1536
+ } else {
1537
+ this.inputElement.setAttribute('aria-disabled', 'false');
1538
+ this.inputElement.setAttribute('tabindex', this.tabIndex);
1539
+ }
1540
+ }
1541
+ private modelHeader(): void {
1542
+ let dateOptions: DateFormatOptions;
1543
+ const modelHeader: HTMLElement = this.createElement('div', { className: 'e-model-header' });
1544
+ const yearHeading: HTMLElement = this.createElement('h1', { className: 'e-model-year' });
1545
+ const h2: HTMLElement = this.createElement('div');
1546
+ const daySpan: HTMLElement = this.createElement('span', { className: 'e-model-day' });
1547
+ const monthSpan: HTMLElement = this.createElement('span', { className: 'e-model-month' });
1548
+ if (this.calendarMode === 'Gregorian') {
1549
+ dateOptions = { format: 'y', skeleton: 'dateTime' };
1550
+ } else {
1551
+ dateOptions = { format: 'y', skeleton: 'dateTime', calendar: 'islamic' };
1552
+ }
1553
+ yearHeading.textContent = '' + this.globalize.formatDate(this.value || new Date(), dateOptions);
1554
+ if (this.calendarMode === 'Gregorian') {
1555
+ dateOptions = { format: 'E', skeleton: 'dateTime' };
1556
+ } else {
1557
+ dateOptions = { format: 'E', skeleton: 'dateTime', calendar: 'islamic' };
1558
+ }
1559
+ daySpan.textContent = '' + this.globalize.formatDate(this.value || new Date(), dateOptions) + ', ';
1560
+ if (this.calendarMode === 'Gregorian') {
1561
+ dateOptions = { format: 'MMM d', skeleton: 'dateTime' };
1562
+ } else {
1563
+ dateOptions = { format: 'MMM d', skeleton: 'dateTime', calendar: 'islamic' };
1564
+ }
1565
+ monthSpan.textContent = '' + this.globalize.formatDate(this.value || new Date(), dateOptions);
1566
+ if (this.fullScreenMode) {
1567
+ const modelCloseIcon: any = this.createElement('span', { className: 'e-popup-close' });
1568
+ EventHandler.add(modelCloseIcon, 'mousedown touchstart', this.modelCloseHandler, this);
1569
+ const modelTodayButton: Element = this.calendarElement.querySelector('button.e-today');
1570
+ h2.classList.add('e-day-wrapper');
1571
+ modelTodayButton.classList.add('e-outline');
1572
+ modelHeader.appendChild(modelCloseIcon);
1573
+ modelHeader.appendChild(modelTodayButton);
1574
+ }
1575
+ if (!this.fullScreenMode)
1576
+ {modelHeader.appendChild(yearHeading); }
1577
+ h2.appendChild(daySpan);
1578
+ h2.appendChild(monthSpan);
1579
+ modelHeader.appendChild(h2);
1580
+ this.calendarElement.insertBefore(modelHeader, this.calendarElement.firstElementChild);
1581
+ }
1582
+
1583
+ private modelCloseHandler(e: MouseEvent| TouchEvent): void {
1584
+ this.hide();
1585
+ }
1586
+
1587
+ protected changeTrigger(event?: MouseEvent | KeyboardEvent): void {
1588
+ if (this.inputElement.value !== this.previousElementValue) {
1589
+ if (((this.previousDate && this.previousDate.valueOf()) !== (this.value && this.value.valueOf()))) {
1590
+ if (this.isDynamicValueChanged && this.isCalendar()) {
1591
+ this.popupUpdate();
1592
+ }
1593
+ this.changedArgs.value = this.value;
1594
+ this.changedArgs.event = event || null;
1595
+ this.changedArgs.element = this.element;
1596
+ this.changedArgs.isInteracted = !isNullOrUndefined(event);
1597
+ if (this.isAngular && this.preventChange) {
1598
+ this.preventChange = false;
1599
+ } else {
1600
+ this.trigger('change', this.changedArgs);
1601
+ }
1602
+ this.previousElementValue = this.inputElement.value;
1603
+ this.previousDate = !isNaN(+new Date(this.checkValue(this.value))) ? new Date(this.checkValue(this.value)) : null;
1604
+ this.isInteracted = true;
1605
+ }
1606
+ }
1607
+ this.isKeyAction = false;
1608
+ }
1609
+
1610
+ protected navigatedEvent(eve: MouseEvent | KeyboardEvent| SwipeEventArgs): void {
1611
+ extend(this.navigatedArgs, { name: 'navigated', event: eve });
1612
+ this.trigger('navigated', this.navigatedArgs);
1613
+ }
1614
+ protected keyupHandler(e: KeyboardEventArgs): void {
1615
+ this.isKeyAction = (this.inputElement.value !== this.previousElementValue) ? true : false;
1616
+ if (this.enableMask && this.showClearButton && this.inputElement && this.inputElement.value === this.maskedDateValue && this.inputWrapper && this.inputWrapper.clearButton && !this.inputWrapper.clearButton.classList.contains('e-clear-icon-hide')) {
1617
+ this.inputWrapper.clearButton.classList.add('e-clear-icon-hide');
1618
+ }
1619
+ }
1620
+ protected changeEvent(event?: MouseEvent | KeyboardEvent | Event): void {
1621
+ if (!this.isIconClicked && !(this.isBlur || this.isKeyAction)) {
1622
+ this.selectCalendar(event);
1623
+ }
1624
+ if (((this.previousDate && this.previousDate.valueOf()) !== (this.value && this.value.valueOf()))) {
1625
+ this.changedArgs.event = event ? event : null;
1626
+ this.changedArgs.element = this.element;
1627
+ this.changedArgs.isInteracted = this.isInteracted;
1628
+ if (!this.isDynamicValueChanged) {
1629
+ if (this.isAngular) {
1630
+ this.previousDate = this.value && new Date(+this.value);
1631
+ }
1632
+ this.trigger('change', this.changedArgs);
1633
+ }
1634
+ this.previousDate = this.value && new Date(+this.value);
1635
+ if (!this.isDynamicValueChanged) {
1636
+ this.hide(event);
1637
+ }
1638
+ this.previousElementValue = this.inputElement.value;
1639
+ this.errorClass();
1640
+ }
1641
+ else if (event) {
1642
+ this.hide(event);
1643
+ }
1644
+ this.isKeyAction = false;
1645
+ }
1646
+
1647
+ public requiredModules(): ModuleDeclaration[] {
1648
+ const modules: ModuleDeclaration[] = [];
1649
+ if (this.calendarMode === 'Islamic') {
1650
+ modules.push({ args: [this], member: 'islamic', name: 'Islamic' });
1651
+ }
1652
+ if (this.enableMask)
1653
+ {
1654
+ modules.push({args: [this], member: 'MaskedDateTime'});
1655
+ }
1656
+ return modules;
1657
+ }
1658
+
1659
+ protected selectCalendar(e?: MouseEvent | KeyboardEvent | Event): void {
1660
+ let date: string;
1661
+ let tempFormat: string;
1662
+ let formatOptions: DateFormatOptions;
1663
+ if (this.getModuleName() === 'datetimepicker') {
1664
+ tempFormat = !isNullOrUndefined(this.formatString) ? this.formatString : this.dateTimeFormat;
1665
+ } else {
1666
+ tempFormat = this.formatString;
1667
+ }
1668
+ if (this.value) {
1669
+ if (this.getModuleName() === 'datetimepicker') {
1670
+ if (this.calendarMode === 'Gregorian') {
1671
+ formatOptions = { format: tempFormat, type: 'dateTime', skeleton: 'yMd' };
1672
+ } else {
1673
+ formatOptions = { format: tempFormat, type: 'dateTime', skeleton: 'yMd', calendar: 'islamic' };
1674
+ }
1675
+ date = this.globalize.formatDate(this.changedArgs.value, formatOptions);
1676
+ } else {
1677
+ if (this.calendarMode === 'Gregorian') {
1678
+ formatOptions = { format: this.formatString, type: 'dateTime', skeleton: 'yMd' };
1679
+ } else {
1680
+ formatOptions = { format: this.formatString, type: 'dateTime', skeleton: 'yMd', calendar: 'islamic' };
1681
+ }
1682
+ date = this.globalize.formatDate(this.changedArgs.value, formatOptions);
1683
+ }
1684
+ if (this.enableMask) {
1685
+ this.notify('createMask', {
1686
+ module: 'MaskedDateTime'
1687
+ });
1688
+ }
1689
+ }
1690
+ if (!isNullOrUndefined(date)) {
1691
+ this.updateInputValue(date);
1692
+ if (this.enableMask)
1693
+ {
1694
+ this.notify('setMaskSelection', {
1695
+ module: 'MaskedDateTime'
1696
+ });
1697
+ }
1698
+ }
1699
+ }
1700
+ protected isCalendar(): boolean {
1701
+ if (this.popupWrapper && this.popupWrapper.classList.contains('' + POPUPWRAPPER)) {
1702
+ return true;
1703
+ }
1704
+ return false;
1705
+ }
1706
+ protected setWidth(width: number | string): void {
1707
+ if (typeof width === 'number') {
1708
+ this.inputWrapper.container.style.width = formatUnit(this.width);
1709
+ } else if (typeof width === 'string') {
1710
+ this.inputWrapper.container.style.width = (width.match(/px|%|em/)) ? <string>(this.width) : <string>(formatUnit(this.width));
1711
+ } else {
1712
+ this.inputWrapper.container.style.width = '100%';
1713
+ }
1714
+ }
1715
+ /* eslint-disable valid-jsdoc, jsdoc/require-param */
1716
+ /**
1717
+ * Shows the Calendar.
1718
+ *
1719
+ * @returns {void}
1720
+ * @deprecated
1721
+ */
1722
+ public show(type?: null | string, e?: MouseEvent | KeyboardEvent | KeyboardEventArgs): void {
1723
+ if ((this.enabled && this.readonly) || !this.enabled || this.popupObj) {
1724
+ return;
1725
+ } else {
1726
+ let prevent: boolean = true;
1727
+ let outOfRange: Date;
1728
+ if (!isNullOrUndefined(this.value) && !(+this.value >= +new Date(this.checkValue(this.min))
1729
+ && +this.value <= +new Date(this.checkValue(this.max)))) {
1730
+ outOfRange = new Date(this.checkValue(this.value));
1731
+ this.setProperties({ 'value': null }, true);
1732
+ } else {
1733
+ outOfRange = this.value || null;
1734
+ }
1735
+ if (!this.isCalendar()) {
1736
+ super.render();
1737
+ this.setProperties({ 'value': outOfRange || null }, true);
1738
+ this.previousDate = outOfRange;
1739
+ this.createCalendar();
1740
+ }
1741
+ if (Browser.isDevice) {
1742
+ this.mobilePopupWrapper = this.createElement('div', { className: 'e-datepick-mob-popup-wrap'});
1743
+ document.body.appendChild(this.mobilePopupWrapper);
1744
+ }
1745
+ this.preventArgs = {
1746
+ preventDefault: (): void => {
1747
+ prevent = false;
1748
+ },
1749
+ popup: this.popupObj,
1750
+ event: e || null,
1751
+ cancel: false,
1752
+ appendTo: Browser.isDevice ? this.mobilePopupWrapper : document.body
1753
+ };
1754
+ const eventArgs: PopupObjectArgs = this.preventArgs;
1755
+ this.trigger('open', eventArgs, (eventArgs: PopupObjectArgs) => {
1756
+ this.preventArgs = eventArgs;
1757
+ if (prevent && !this.preventArgs.cancel) {
1758
+ addClass(this.inputWrapper.buttons, ACTIVE);
1759
+ this.preventArgs.appendTo.appendChild(this.popupWrapper);
1760
+ this.popupObj.refreshPosition(this.inputElement);
1761
+ const openAnimation: object = {
1762
+ name: 'FadeIn',
1763
+ duration: Browser.isDevice ? 0 : OPENDURATION
1764
+ };
1765
+ if (this.zIndex === 1000) {
1766
+ this.popupObj.show(new Animation(openAnimation), this.element);
1767
+ } else {
1768
+ this.popupObj.show(new Animation(openAnimation), null);
1769
+ }
1770
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1771
+ super.setOverlayIndex(this.mobilePopupWrapper, this.popupObj.element, this.modal, Browser.isDevice as any);
1772
+ this.setAriaAttributes();
1773
+ if (Browser.isDevice) {
1774
+ const dlgOverlay: any = this.createElement('div', { className: 'e-dlg-overlay'});
1775
+ dlgOverlay.style.zIndex = (this.zIndex - 1).toString();
1776
+ this.mobilePopupWrapper.appendChild(dlgOverlay);
1777
+ }
1778
+ } else {
1779
+ this.popupObj.destroy();
1780
+ this.popupWrapper = this.popupObj = null;
1781
+ }
1782
+ if (!isNullOrUndefined(this.inputElement) && this.inputElement.value === '') {
1783
+ if (!isNullOrUndefined(this.tableBodyElement) && this.tableBodyElement.querySelectorAll('td.e-selected').length > 0) {
1784
+ addClass([this.tableBodyElement.querySelector('td.e-selected')], FOCUSEDDATE);
1785
+ removeClass(this.tableBodyElement.querySelectorAll('td.e-selected'), SELECTED);
1786
+ }
1787
+ }
1788
+ EventHandler.add(document, 'mousedown touchstart', this.documentHandler, this);
1789
+ });
1790
+ }
1791
+ }
1792
+ /**
1793
+ * Hide the Calendar.
1794
+ *
1795
+ * @returns {void}
1796
+ * @deprecated
1797
+ */
1798
+ public hide(event?: MouseEvent | KeyboardEvent | Event): void {
1799
+ if (!isNullOrUndefined(this.popupWrapper)) {
1800
+ let prevent: boolean = true;
1801
+ this.preventArgs = {
1802
+ preventDefault: (): void => {
1803
+ prevent = false;
1804
+ },
1805
+ popup: this.popupObj,
1806
+ event: event || null,
1807
+ cancel: false
1808
+ };
1809
+ removeClass(this.inputWrapper.buttons, ACTIVE);
1810
+ removeClass([document.body], OVERFLOW);
1811
+ const eventArgs: PopupObjectArgs = this.preventArgs;
1812
+ if (this.isCalendar()) {
1813
+ this.trigger('close', eventArgs, (eventArgs: PopupObjectArgs) => {
1814
+ this.closeEventCallback(prevent, eventArgs);
1815
+ });
1816
+ } else {
1817
+ this.closeEventCallback(prevent, eventArgs);
1818
+ }
1819
+ } else {
1820
+ if (Browser.isDevice && this.allowEdit && !this.readonly) {
1821
+ this.inputElement.removeAttribute('readonly');
1822
+ }
1823
+ this.setAllowEdit();
1824
+ }
1825
+ }
1826
+ /* eslint-enable valid-jsdoc, jsdoc/require-param */
1827
+ private closeEventCallback(prevent: boolean, eventArgs: PopupObjectArgs): void {
1828
+ this.preventArgs = eventArgs;
1829
+ if (this.isCalendar() && (prevent && !this.preventArgs.cancel)) {
1830
+ this.popupObj.hide();
1831
+ this.isAltKeyPressed = false;
1832
+ this.keyboardModule.destroy();
1833
+ removeClass(this.inputWrapper.buttons, ACTIVE);
1834
+ }
1835
+ this.setAriaAttributes();
1836
+ if (Browser.isDevice && this.modal) {
1837
+ this.modal.style.display = 'none';
1838
+ this.modal.outerHTML = '';
1839
+ this.modal = null;
1840
+ }
1841
+ if (Browser.isDevice) {
1842
+ if (!isNullOrUndefined(this.mobilePopupWrapper) &&
1843
+ (prevent && (isNullOrUndefined(this.preventArgs) || !this.preventArgs.cancel))) {
1844
+ this.mobilePopupWrapper.remove();
1845
+ this.mobilePopupWrapper = null;
1846
+ }
1847
+ }
1848
+ EventHandler.remove(document, 'mousedown touchstart', this.documentHandler);
1849
+ if (Browser.isDevice && this.allowEdit && !this.readonly) {
1850
+ this.inputElement.removeAttribute('readonly');
1851
+ }
1852
+ this.setAllowEdit();
1853
+ }
1854
+ /* eslint-disable jsdoc/require-param */
1855
+ /**
1856
+ * Sets the focus to widget for interaction.
1857
+ *
1858
+ * @returns {void}
1859
+ */
1860
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1861
+ public focusIn(triggerEvent?: boolean): void {
1862
+ if (document.activeElement !== this.inputElement && this.enabled) {
1863
+ (<HTMLElement>this.inputElement).focus();
1864
+ addClass([this.inputWrapper.container], [INPUTFOCUS]);
1865
+ }
1866
+ }
1867
+ /* eslint-enable jsdoc/require-param */
1868
+ /**
1869
+ * Remove the focus from widget, if the widget is in focus state.
1870
+ *
1871
+ * @returns {void}
1872
+ */
1873
+ public focusOut(): void {
1874
+ if (document.activeElement === this.inputElement) {
1875
+ removeClass([this.inputWrapper.container], [INPUTFOCUS]);
1876
+ this.inputElement.blur();
1877
+ }
1878
+ }
1879
+ /* eslint-disable valid-jsdoc, jsdoc/require-returns-description */
1880
+ /**
1881
+ * Gets the current view of the DatePicker.
1882
+ *
1883
+ * @returns {string}
1884
+ * @deprecated
1885
+ */
1886
+ public currentView(): string {
1887
+ let currentView: string;
1888
+ if (this.calendarElement) {
1889
+ // calls the Calendar currentView public method
1890
+ currentView = super.currentView();
1891
+ }
1892
+ return currentView;
1893
+ }
1894
+ /* eslint-enable valid-jsdoc, jsdoc/require-returns-description */
1895
+ /**
1896
+ * Navigates to specified month or year or decade view of the DatePicker.
1897
+ *
1898
+ * @param {string} view - Specifies the view of the calendar.
1899
+ * @param {Date} date - Specifies the focused date in a view.
1900
+ * @returns {void}
1901
+ * @deprecated
1902
+ */
1903
+ public navigateTo(view: CalendarView, date: Date): void {
1904
+ if (this.calendarElement) {
1905
+ // calls the Calendar navigateTo public method
1906
+ super.navigateTo(view, date);
1907
+ }
1908
+ }
1909
+ /**
1910
+ * To destroy the widget.
1911
+ *
1912
+ * @returns {void}
1913
+ */
1914
+ public destroy(): void {
1915
+ this.unBindEvents();
1916
+ if (this.showClearButton) {
1917
+ this.clearButton = document.getElementsByClassName('e-clear-icon')[0] as HTMLElement;
1918
+ }
1919
+ super.destroy();
1920
+ Input.destroy({
1921
+ element: this.inputElement,
1922
+ floatLabelType: this.floatLabelType,
1923
+ properties: this.properties
1924
+ }, this.clearButton);
1925
+ if (!isNullOrUndefined(this.keyboardModules))
1926
+ {
1927
+ this.keyboardModules.destroy();
1928
+ }
1929
+ if (this.popupObj && this.popupObj.element.classList.contains(POPUP)) {
1930
+ super.destroy();
1931
+ }
1932
+ const ariaAttrs: object = {
1933
+ 'aria-atomic': 'true', 'aria-disabled': 'true',
1934
+ 'aria-expanded': 'false', 'role': 'combobox', 'autocomplete': 'off',
1935
+ 'autocorrect': 'off', 'autocapitalize': 'off', 'spellcheck': 'false'
1936
+ };
1937
+ if (this.inputElement.hasAttribute('aria-label')) {
1938
+ this.inputElement.removeAttribute('aria-label');
1939
+ }
1940
+ if (this.inputElement) {
1941
+ Input.removeAttributes(<{ [key: string]: string }>ariaAttrs, this.inputElement);
1942
+ if (!isNullOrUndefined(this.inputElementCopy.getAttribute('tabindex'))) {
1943
+ this.inputElement.setAttribute('tabindex', this.tabIndex);
1944
+ } else {
1945
+ this.inputElement.removeAttribute('tabindex');
1946
+ }
1947
+ EventHandler.remove(this.inputElement, 'blur', this.inputBlurHandler);
1948
+ EventHandler.remove(this.inputElement, 'focus', this.inputFocusHandler);
1949
+ this.ensureInputAttribute();
1950
+ }
1951
+ if (this.isCalendar()) {
1952
+ if (this.popupWrapper) {
1953
+ detach(this.popupWrapper);
1954
+ }
1955
+ this.popupObj = this.popupWrapper = null;
1956
+ this.keyboardModule.destroy();
1957
+ }
1958
+ if (this.ngTag === null) {
1959
+ if (this.inputElement) {
1960
+ if (!isNullOrUndefined(this.inputWrapper))
1961
+ {
1962
+ this.inputWrapper.container.insertAdjacentElement('afterend', this.inputElement);
1963
+ }
1964
+ removeClass([this.inputElement], [INPUTROOT]);
1965
+ }
1966
+ removeClass([this.element], [ROOT]);
1967
+ if (!isNullOrUndefined(this.inputWrapper))
1968
+ {
1969
+ detach(this.inputWrapper.container);
1970
+ }
1971
+ }
1972
+ if (this.formElement) {
1973
+ EventHandler.remove(this.formElement, 'reset', this.resetFormHandler);
1974
+ }
1975
+ this.inputWrapper = null;
1976
+ this.keyboardModules = null;
1977
+ }
1978
+
1979
+ protected ensureInputAttribute(): void {
1980
+ const prop: string[] = [];
1981
+ for (let i: number = 0; i < this.inputElement.attributes.length; i++) {
1982
+ prop[i as number] = this.inputElement.attributes[i as number].name;
1983
+ }
1984
+ for (let i: number = 0; i < prop.length; i++) {
1985
+ if (isNullOrUndefined(this.inputElementCopy.getAttribute(prop[i as number]))) {
1986
+ if (prop[i as number].toLowerCase() === 'value') {
1987
+ this.inputElement.value = '';
1988
+ }
1989
+ this.inputElement.removeAttribute(prop[i as number]);
1990
+ } else {
1991
+ if (prop[i as number].toLowerCase() === 'value') {
1992
+ this.inputElement.value = this.inputElementCopy.getAttribute(prop[i as number]);
1993
+ }
1994
+ this.inputElement.setAttribute(prop[i as number], this.inputElementCopy.getAttribute(prop[i as number]));
1995
+ }
1996
+ }
1997
+ }
1998
+ /**
1999
+ * Initialize the event handler
2000
+ *
2001
+ * @returns {void}
2002
+ * @private
2003
+ */
2004
+ protected preRender(): void {
2005
+ this.inputElementCopy = <HTMLElement>this.element.cloneNode(true);
2006
+ removeClass([this.inputElementCopy], [ROOT, CONTROL, LIBRARY]);
2007
+ this.inputElement = <HTMLInputElement>this.element;
2008
+ this.formElement = <HTMLFormElement>closest(this.inputElement, 'form');
2009
+ this.index = this.showClearButton ? 2 : 1;
2010
+ this.ngTag = null;
2011
+ if (this.element.tagName === 'EJS-DATEPICKER' || this.element.tagName === 'EJS-DATETIMEPICKER') {
2012
+ this.ngTag = this.element.tagName;
2013
+ this.inputElement = <HTMLInputElement>this.createElement('input');
2014
+ this.element.appendChild(this.inputElement);
2015
+ }
2016
+ if (this.element.getAttribute('id')) {
2017
+ if (this.ngTag !== null) {
2018
+ this.inputElement.id = this.element.getAttribute('id') + '_input';
2019
+ }
2020
+ } else {
2021
+ if (this.getModuleName() === 'datetimepicker') {
2022
+ this.element.id = getUniqueID('ej2-datetimepicker');
2023
+ if (this.ngTag !== null) {
2024
+ attributes(this.inputElement, { 'id': this.element.id + '_input' });
2025
+ }
2026
+ } else {
2027
+ this.element.id = getUniqueID('ej2-datepicker');
2028
+ if (this.ngTag !== null) {
2029
+ attributes(this.inputElement, { 'id': this.element.id + '_input' });
2030
+ }
2031
+ }
2032
+ }
2033
+ if (this.ngTag !== null) {
2034
+ this.validationAttribute(this.element, this.inputElement);
2035
+ }
2036
+ this.updateHtmlAttributeToElement();
2037
+ this.defaultKeyConfigs = this.getDefaultKeyConfig();
2038
+ this.checkHtmlAttributes(false);
2039
+ if (this.inputFormats) {
2040
+ this.checkInputFormats();
2041
+ }
2042
+ this.tabIndex = this.element.hasAttribute('tabindex') ? this.element.getAttribute('tabindex') : '0';
2043
+ this.element.removeAttribute('tabindex');
2044
+ super.preRender();
2045
+ }
2046
+ protected getDefaultKeyConfig(): { [key: string]: string } {
2047
+ this.defaultKeyConfigs = {
2048
+ altUpArrow: 'alt+uparrow',
2049
+ altDownArrow: 'alt+downarrow',
2050
+ escape: 'escape',
2051
+ enter: 'enter',
2052
+ controlUp: 'ctrl+38',
2053
+ controlDown: 'ctrl+40',
2054
+ moveDown: 'downarrow',
2055
+ moveUp: 'uparrow',
2056
+ moveLeft: 'leftarrow',
2057
+ moveRight: 'rightarrow',
2058
+ select: 'enter',
2059
+ home: 'home',
2060
+ end: 'end',
2061
+ pageUp: 'pageup',
2062
+ pageDown: 'pagedown',
2063
+ shiftPageUp: 'shift+pageup',
2064
+ shiftPageDown: 'shift+pagedown',
2065
+ controlHome: 'ctrl+home',
2066
+ controlEnd: 'ctrl+end',
2067
+ shiftTab: 'shift+tab',
2068
+ tab: 'tab'
2069
+ };
2070
+ return this.defaultKeyConfigs;
2071
+ }
2072
+ protected validationAttribute(target: HTMLElement, inputElement: Element): void {
2073
+ const nameAttribute: string = target.getAttribute('name') ? target.getAttribute('name') : target.getAttribute('id');
2074
+ inputElement.setAttribute('name', nameAttribute);
2075
+ target.removeAttribute('name');
2076
+ const attribute: string[] = ['required', 'aria-required', 'form'];
2077
+ for (let i: number = 0; i < attribute.length; i++) {
2078
+ if (isNullOrUndefined(target.getAttribute(attribute[i as number]))) {
2079
+ continue;
2080
+ }
2081
+ const attr: string = target.getAttribute(attribute[i as number]);
2082
+ inputElement.setAttribute(attribute[i as number], attr);
2083
+ target.removeAttribute(attribute[i as number]);
2084
+ }
2085
+ }
2086
+ protected checkFormat(): void {
2087
+ const culture: Internationalization = new Internationalization(this.locale);
2088
+ if (this.format) {
2089
+ if (typeof this.format === 'string') {
2090
+ this.formatString = this.format;
2091
+ } else if (this.format.skeleton !== '' && !isNullOrUndefined(this.format.skeleton)) {
2092
+ const skeletonString: string = this.format.skeleton;
2093
+ if (this.getModuleName() === 'datetimepicker') {
2094
+ this.formatString = culture.getDatePattern({ skeleton: skeletonString, type: 'dateTime' });
2095
+ } else {
2096
+ this.formatString = culture.getDatePattern({ skeleton: skeletonString, type: 'date' });
2097
+ }
2098
+ } else {
2099
+ if (this.getModuleName() === 'datetimepicker') {
2100
+ this.formatString = this.dateTimeFormat;
2101
+ } else {
2102
+ this.formatString = null;
2103
+ }
2104
+ }
2105
+ } else {
2106
+ this.formatString = null;
2107
+ }
2108
+ }
2109
+ protected checkInputFormats(): void {
2110
+ const culture: Internationalization = new Internationalization(this.locale);
2111
+ this.inputFormatsString = [];
2112
+ if (this.inputFormats) {
2113
+ for (const format of this.inputFormats) {
2114
+ let formatString: string = '';
2115
+ if (typeof format === 'string') {
2116
+ formatString = format;
2117
+ } else if (format.skeleton !== '' && !isNullOrUndefined(format.skeleton)) {
2118
+ const skeletonString: string = format.skeleton;
2119
+ if (this.getModuleName() === 'datetimepicker') {
2120
+ formatString = culture.getDatePattern({ skeleton: skeletonString, type: 'dateTime' });
2121
+ } else {
2122
+ formatString = culture.getDatePattern({ skeleton: skeletonString, type: 'date' });
2123
+ }
2124
+ }
2125
+ if (formatString) {
2126
+ this.inputFormatsString.push(formatString);
2127
+ }
2128
+ }
2129
+ if (this.inputFormatsString.length === 0) {
2130
+ this.inputFormatsString = null;
2131
+ }
2132
+ } else {
2133
+ this.inputFormatsString = null;
2134
+ }
2135
+ }
2136
+ private checkHtmlAttributes(dynamic: boolean): void {
2137
+ this.globalize = new Internationalization(this.locale);
2138
+ this.checkFormat();
2139
+ this.checkView();
2140
+ const attributes: string[] = dynamic ? isNullOrUndefined(this.htmlAttributes) ? [] : Object.keys(this.htmlAttributes) :
2141
+ ['value', 'min', 'max', 'disabled', 'readonly', 'style', 'name', 'placeholder', 'type'];
2142
+ let options: object;
2143
+ if (this.getModuleName() === 'datetimepicker') {
2144
+ if (this.calendarMode === 'Gregorian') {
2145
+ options = {
2146
+ format: !isNullOrUndefined(this.formatString) ? this.formatString : this.dateTimeFormat,
2147
+ type: 'dateTime', skeleton: 'yMd'
2148
+ };
2149
+ } else {
2150
+ options = {
2151
+ format: !isNullOrUndefined(this.formatString) ? this.formatString : this.dateTimeFormat,
2152
+ type: 'dateTime', skeleton: 'yMd', calendar: 'islamic'
2153
+ };
2154
+ }
2155
+
2156
+ } else {
2157
+ if (this.calendarMode === 'Gregorian') {
2158
+ options = { format: this.formatString, type: 'dateTime', skeleton: 'yMd' };
2159
+ } else {
2160
+ options = { format: this.formatString, type: 'dateTime', skeleton: 'yMd', calendar: 'islamic' };
2161
+ }
2162
+ }
2163
+ for (const prop of attributes) {
2164
+ if (!isNullOrUndefined(this.inputElement.getAttribute(prop))) {
2165
+ switch (prop) {
2166
+ case 'disabled':
2167
+ if (((isNullOrUndefined(this.datepickerOptions) || (this.datepickerOptions['enabled'] === undefined)) || dynamic)) {
2168
+ const enabled: boolean = this.inputElement.getAttribute(prop) === 'disabled' ||
2169
+ this.inputElement.getAttribute(prop) === '' ||
2170
+ this.inputElement.getAttribute(prop) === 'true' ? false : true;
2171
+ this.setProperties({ enabled: enabled }, !dynamic);
2172
+ }
2173
+ break;
2174
+ case 'readonly':
2175
+ if (((isNullOrUndefined(this.datepickerOptions) || (this.datepickerOptions['readonly'] === undefined)) || dynamic)) {
2176
+ const readonly: boolean = this.inputElement.getAttribute(prop) === 'readonly' ||
2177
+ this.inputElement.getAttribute(prop) === '' || this.inputElement.getAttribute(prop) === 'true' ? true : false;
2178
+ this.setProperties({ readonly: readonly }, !dynamic);
2179
+ }
2180
+ break;
2181
+ case 'placeholder':
2182
+ if (((isNullOrUndefined(this.datepickerOptions) || (this.datepickerOptions['placeholder'] === undefined)) || dynamic)) {
2183
+ this.setProperties({ placeholder: this.inputElement.getAttribute(prop) }, !dynamic);
2184
+ }
2185
+ break;
2186
+ case 'style':
2187
+ this.inputElement.setAttribute('style', '' + this.inputElement.getAttribute(prop));
2188
+ break;
2189
+ case 'name':
2190
+ this.inputElement.setAttribute('name', '' + this.inputElement.getAttribute(prop));
2191
+ break;
2192
+ case 'value':
2193
+ if (((isNullOrUndefined(this.datepickerOptions) || (this.datepickerOptions['value'] === undefined)) || dynamic)) {
2194
+ const value: string = this.inputElement.getAttribute(prop);
2195
+ this.setProperties(setValue(prop, this.globalize.parseDate(this.getAmPmValue(value), options), {}), !dynamic);
2196
+ }
2197
+ break;
2198
+ case 'min':
2199
+ if ((+this.min === +new Date(1900, 0, 1)) || dynamic) {
2200
+ const min: string = this.inputElement.getAttribute(prop);
2201
+ this.setProperties(setValue(prop, this.globalize.parseDate(this.getAmPmValue(min), options), {}), !dynamic);
2202
+ }
2203
+ break;
2204
+ case 'max':
2205
+ if ((+this.max === +new Date(2099, 11, 31)) || dynamic) {
2206
+ const max: string = this.inputElement.getAttribute(prop);
2207
+ this.setProperties(setValue(prop, this.globalize.parseDate(this.getAmPmValue(max), options), {}), !dynamic);
2208
+ }
2209
+ break;
2210
+ case 'type':
2211
+ if (this.inputElement.getAttribute(prop) !== 'text') {
2212
+ this.inputElement.setAttribute('type', 'text');
2213
+ }
2214
+ break;
2215
+ }
2216
+ }
2217
+ }
2218
+ }
2219
+ /**
2220
+ * To get component name.
2221
+ *
2222
+ * @returns {string} Returns the component name.
2223
+ * @private
2224
+ */
2225
+ protected getModuleName(): string {
2226
+ return 'datepicker';
2227
+ }
2228
+ private disabledDates(isDynamic: boolean = false, isBlur: boolean = false): void {
2229
+ let formatOptions: DateFormatOptions;
2230
+ let globalize: string;
2231
+ const valueCopy: Date = this.checkDateValue(this.value) ? new Date(+this.value) : new Date(this.checkValue(this.value));
2232
+ const previousValCopy: Date = this.previousDate;
2233
+ //calls the Calendar render method to check the disabled dates through renderDayCell event and update the input value accordingly.
2234
+ this.minMaxUpdates();
2235
+ if (!isDynamic || (isDynamic && !isNullOrUndefined(this.renderDayCell))) {
2236
+ super.render(); }
2237
+ this.previousDate = previousValCopy;
2238
+ const date: number = valueCopy && +(valueCopy);
2239
+ const dateIdString: string = '*[id^="/id"]'.replace('/id', '' + date);
2240
+ if (!this.strictMode) {
2241
+ if (typeof this.value === 'string' || ((typeof this.value === 'object') && (+this.value) !== (+valueCopy))) {
2242
+ this.setProperties({ value: valueCopy }, true);
2243
+ }
2244
+ }
2245
+ if (!isNullOrUndefined(this.calendarElement) && !isNullOrUndefined(this.calendarElement.querySelectorAll(dateIdString)[0])) {
2246
+ if (this.calendarElement.querySelectorAll(dateIdString)[0].classList.contains('e-disabled')) {
2247
+ if (!this.strictMode) {
2248
+ this.currentDate = new Date(new Date().setHours(0, 0, 0, 0));
2249
+ }
2250
+ }
2251
+ }
2252
+ let inputVal: string;
2253
+ if (this.getModuleName() === 'datetimepicker') {
2254
+ if (this.calendarMode === 'Gregorian') {
2255
+ globalize = this.globalize.formatDate(valueCopy, {
2256
+ format: !isNullOrUndefined(this.formatString) ? this.formatString : this.dateTimeFormat,
2257
+ type: 'dateTime', skeleton: 'yMd'
2258
+ });
2259
+ } else {
2260
+ globalize = this.globalize.formatDate(valueCopy, {
2261
+ format: !isNullOrUndefined(this.formatString) ? this.formatString : this.dateTimeFormat,
2262
+ type: 'dateTime', skeleton: 'yMd', calendar: 'islamic'
2263
+ });
2264
+ }
2265
+ inputVal = globalize;
2266
+ } else {
2267
+ if (this.calendarMode === 'Gregorian') {
2268
+ formatOptions = { format: this.formatString, type: 'dateTime', skeleton: 'yMd' };
2269
+ } else {
2270
+ formatOptions = { format: this.formatString, type: 'dateTime', skeleton: 'yMd', calendar: 'islamic' };
2271
+ }
2272
+ inputVal = this.globalize.formatDate(valueCopy, formatOptions);
2273
+ }
2274
+ if (!this.popupObj) {
2275
+ this.updateInputValue(inputVal);
2276
+ if (this.enableMask)
2277
+ {
2278
+ this.updateInputValue(this.maskedDateValue);
2279
+ this.notify('createMask', {
2280
+ module: 'MaskedDateTime', isBlur: isBlur
2281
+ });
2282
+ }
2283
+ }
2284
+ }
2285
+ private setAriaAttributes(): void {
2286
+ if (this.isCalendar()) {
2287
+ Input.addAttributes({ 'aria-expanded': 'true' }, this.inputElement);
2288
+ attributes(this.inputElement, { 'aria-owns': this.inputElement.id + '_options'});
2289
+ attributes(this.inputElement, { 'aria-controls': this.inputElement.id });
2290
+ if (this.value)
2291
+ {
2292
+ attributes(this.inputElement, { 'aria-activedescendant': '' + this.setActiveDescendant() });
2293
+ }
2294
+ } else {
2295
+ Input.addAttributes({ 'aria-expanded': 'false' }, this.inputElement);
2296
+ this.inputElement.removeAttribute('aria-owns');
2297
+ this.inputElement.removeAttribute('aria-controls');
2298
+ this.inputElement.removeAttribute( 'aria-activedescendant');
2299
+ }
2300
+ }
2301
+ protected errorClass(): void {
2302
+ const dateIdString: string = '*[id^="/id"]'.replace('/id', '' + (+this.value));
2303
+ const isDisabledDate: boolean = this.calendarElement &&
2304
+ this.calendarElement.querySelectorAll(dateIdString)[0] &&
2305
+ this.calendarElement.querySelectorAll(dateIdString)[0].classList.contains('e-disabled');
2306
+ if ((!isNullOrUndefined(this.value) && !isNullOrUndefined(this.min) &&
2307
+ !isNullOrUndefined(this.max) && !(new Date(this.value as Date).setMilliseconds(0) >=
2308
+ new Date(this.min as Date).setMilliseconds(0)
2309
+ && new Date(this.value as any).setMilliseconds(0) <= new Date(this.max as Date).setMilliseconds(0)))
2310
+ || (!this.strictMode && this.inputElement.value !== '' && this.inputElement.value !== this.maskedDateValue &&
2311
+ isNullOrUndefined(this.value) || isDisabledDate) || !this.isValidTime(this.value)) {
2312
+ addClass([this.inputWrapper.container], ERROR);
2313
+ attributes(this.inputElement, { 'aria-invalid': 'true' });
2314
+ } else if (!isNullOrUndefined(this.inputWrapper)) {
2315
+ removeClass([this.inputWrapper.container], ERROR);
2316
+ attributes(this.inputElement, { 'aria-invalid': 'false' });
2317
+ }
2318
+ }
2319
+
2320
+ protected isValidTime(value: Date): boolean {
2321
+ return true;
2322
+ }
2323
+ /**
2324
+ * Called internally if any of the property value changed.
2325
+ *
2326
+ * @param {DatePickerModel} newProp - Returns the dynamic property value of the component.
2327
+ * @param {DatePickerModel} oldProp - Returns the previous property value of the component.
2328
+ * @returns {void}
2329
+ * @private
2330
+ */
2331
+ public onPropertyChanged(newProp: DatePickerModel, oldProp: DatePickerModel): void {
2332
+ for (const prop of Object.keys(newProp)) {
2333
+ const openPopup: string[] = ['blur', 'change', 'cleared', 'close', 'created', 'destroyed', 'focus', 'navigated', 'open', 'renderDayCell'];
2334
+ if (openPopup.indexOf(prop) > 0 && this.isReact) {
2335
+ this.isDynamicValueChanged = true;
2336
+ }
2337
+ switch (prop) {
2338
+ case 'value':
2339
+ this.isDynamicValueChanged = true;
2340
+ this.isInteracted = false;
2341
+ this.invalidValueString = null;
2342
+ this.checkInvalidValue(newProp.value);
2343
+ newProp.value = this.value;
2344
+ this.previousElementValue = this.inputElement.value;
2345
+ if (isNullOrUndefined(this.value)) {
2346
+ if (this.enableMask) {
2347
+ this.updateInputValue(this.maskedDateValue);
2348
+ }
2349
+ else {
2350
+ this.updateInputValue('');
2351
+ }
2352
+ this.currentDate = new Date(new Date().setHours(0, 0, 0, 0));
2353
+ }
2354
+ this.updateInput(true);
2355
+ if (+this.previousDate !== +this.value) {
2356
+ this.changeTrigger(null);
2357
+ }
2358
+ this.isInteracted = true;
2359
+ this.preventChange = this.isAngular && this.preventChange ? !this.preventChange : this.preventChange;
2360
+ if (this.enableMask) {
2361
+ this.notify('createMask', {
2362
+ module: 'MaskedDateTime'
2363
+ });
2364
+ }
2365
+ break;
2366
+ case 'format':
2367
+ this.checkFormat();
2368
+ this.bindInputEvent();
2369
+ this.updateInput();
2370
+ if (this.enableMask) {
2371
+ this.notify('createMask', {
2372
+ module: 'MaskedDateTime'
2373
+ });
2374
+ if (!this.value)
2375
+ {
2376
+ this.updateInputValue(this.maskedDateValue);
2377
+ }
2378
+ }
2379
+ break;
2380
+ case 'inputFormats':
2381
+ this.checkInputFormats();
2382
+ break;
2383
+ case 'allowEdit':
2384
+ this.setAllowEdit();
2385
+ break;
2386
+ case 'placeholder':
2387
+ Input.setPlaceholder(this.placeholder, this.inputElement);
2388
+ break;
2389
+ case 'readonly':
2390
+ Input.setReadonly(this.readonly, this.inputElement);
2391
+ break;
2392
+ case 'enabled':
2393
+ Input.setEnabled(this.enabled, this.inputElement);
2394
+ this.setAriaDisabled();
2395
+ break;
2396
+ case 'htmlAttributes':
2397
+ this.updateHtmlAttributeToElement();
2398
+ this.updateHtmlAttributeToWrapper();
2399
+ this.checkHtmlAttributes(true);
2400
+ break;
2401
+ case 'locale':
2402
+ this.globalize = new Internationalization(this.locale);
2403
+ this.l10n.setLocale(this.locale);
2404
+ if (this.datepickerOptions && this.datepickerOptions.placeholder == null) {
2405
+ this.setProperties({ placeholder: this.l10n.getConstant('placeholder') }, true);
2406
+ Input.setPlaceholder(this.placeholder, this.inputElement);
2407
+ }
2408
+ this.updateInput();
2409
+ if (this.enableMask) {
2410
+ this.notify('createMask', {
2411
+ module: 'MaskedDateTime'
2412
+ });
2413
+ }
2414
+ break;
2415
+ case 'enableRtl':
2416
+ Input.setEnableRtl(this.enableRtl, [this.inputWrapper.container]);
2417
+ break;
2418
+ case 'start':
2419
+ case 'depth':
2420
+ this.checkView();
2421
+ if (this.calendarElement) {
2422
+ super.onPropertyChanged(newProp, oldProp);
2423
+ }
2424
+ break;
2425
+ case 'zIndex':
2426
+ this.setProperties({ zIndex: newProp.zIndex }, true);
2427
+ break;
2428
+ case 'cssClass':
2429
+ this.updateCssClass(newProp.cssClass, oldProp.cssClass);
2430
+ break;
2431
+ case 'showClearButton':
2432
+ Input.setClearButton(this.showClearButton, this.inputElement, this.inputWrapper);
2433
+ this.bindClearEvent();
2434
+ this.index = this.showClearButton ? 2 : 1;
2435
+ break;
2436
+ case 'strictMode':
2437
+ this.invalidValueString = null;
2438
+ this.updateInput();
2439
+ break;
2440
+ case 'width':
2441
+ this.setWidth(newProp.width);
2442
+ Input.calculateWidth(this.inputElement, this.inputWrapper.container);
2443
+ if (!isNullOrUndefined(this.inputWrapper.buttons[0]) && !isNullOrUndefined(this.inputWrapper.container.getElementsByClassName('e-float-text-overflow')[0]) && this.floatLabelType !== 'Never') {
2444
+ this.inputWrapper.container.getElementsByClassName('e-float-text-overflow')[0].classList.add('e-icon');
2445
+ }
2446
+ break;
2447
+ case 'floatLabelType':
2448
+ this.floatLabelType = newProp.floatLabelType;
2449
+ Input.removeFloating(this.inputWrapper);
2450
+ Input.addFloating(this.inputElement, this.floatLabelType, this.placeholder);
2451
+ if (!isNullOrUndefined(this.inputWrapper.buttons[0]) && !isNullOrUndefined(this.inputWrapper.container.getElementsByClassName('e-float-text-overflow')[0]) && this.floatLabelType !== 'Never') {
2452
+ this.inputWrapper.container.getElementsByClassName('e-float-text-overflow')[0].classList.add('e-icon');
2453
+ }
2454
+ break;
2455
+ case 'enableMask':
2456
+ if (this.enableMask) {
2457
+ this.notify('createMask', {
2458
+ module: 'MaskedDateTime'
2459
+ });
2460
+ this.updateInputValue(this.maskedDateValue);
2461
+ this.bindInputEvent();
2462
+ }
2463
+ else
2464
+ {
2465
+ if (this.inputElement.value === this.maskedDateValue)
2466
+ {
2467
+ this.updateInputValue('');
2468
+ }
2469
+ }
2470
+ break;
2471
+ default:
2472
+ if (this.calendarElement && this.isCalendar()) {
2473
+ super.onPropertyChanged(newProp, oldProp);
2474
+ }
2475
+ if (prop === 'min' && isNullOrUndefined(this.min)) {
2476
+ this.min = new Date(1900, 0, 1);
2477
+ }
2478
+ if (prop === 'max' && isNullOrUndefined(this.max)) {
2479
+ this.max = new Date(2099, 11, 31);
2480
+ }
2481
+ break;
2482
+ }
2483
+ if (!this.isDynamicValueChanged) {
2484
+ this.hide(null);
2485
+ }
2486
+ this.isDynamicValueChanged = false;
2487
+ }
2488
+ }
2489
+ /**
2490
+ * @private
2491
+ * @param {Date | Date[]} dates - Specifies the date or dates to be added to the values property of the Calendar.
2492
+ * @returns {void}
2493
+ */
2494
+ public addDate(dates: Date | Date[]): void {
2495
+ // no code
2496
+ }
2497
+ }
2498
+
2499
+ export interface PopupObjectArgs {
2500
+ /** Prevents the default action */
2501
+ preventDefault?: Function
2502
+ /**
2503
+ * Defines the DatePicker popup element.
2504
+ *
2505
+ * @deprecated
2506
+ */
2507
+ popup?: Popup
2508
+ /**
2509
+ * Illustrates whether the current action needs to be prevented or not.
2510
+ */
2511
+
2512
+ cancel?: boolean
2513
+ /**
2514
+ * Specifies the original event arguments.
2515
+ */
2516
+
2517
+ event?: MouseEvent | KeyboardEvent | Event
2518
+ /**
2519
+ * Specifies the node to which the popup element to be appended.
2520
+ */
2521
+ appendTo?: HTMLElement
2522
+ }
2523
+
2524
+ export interface PreventableEventArgs {
2525
+ /** Prevents the default action */
2526
+ preventDefault?: Function
2527
+
2528
+ }