@materializecss/materialize 2.0.1-alpha → 2.0.2-alpha
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.
- package/Gruntfile.js +5 -2
- package/dist/css/materialize.css +90 -86
- package/dist/css/materialize.min.css +2 -2
- package/dist/js/materialize.js +2797 -2705
- package/dist/js/materialize.min.js +2 -8967
- package/dist/js/materialize.min.js.map +1 -1
- package/package.json +1 -1
- package/sass/components/_collapsible.scss +0 -41
- package/sass/components/_global.scss +3 -2
- package/sass/components/_icons-material-design.scss +2 -1
- package/sass/components/_navbar.scss +6 -3
- package/sass/components/_sidenav.scss +66 -37
- package/sass/components/_theme_variables.scss +2 -2
- package/sass/components/_typography.scss +2 -2
- package/sass/components/forms/_input-fields.scss +4 -10
- package/sass/materialize.scss +0 -4
- package/src/autocomplete.ts +188 -94
- package/src/buttons.ts +225 -260
- package/src/cards.ts +5 -6
- package/src/carousel.ts +611 -542
- package/src/characterCounter.ts +50 -21
- package/src/chips.ts +152 -63
- package/src/collapsible.ts +97 -32
- package/src/component.ts +99 -10
- package/src/datepicker.ts +905 -726
- package/src/dropdown.ts +576 -484
- package/src/edges.ts +4 -4
- package/src/forms.ts +17 -14
- package/src/global.ts +55 -324
- package/src/materialbox.ts +354 -298
- package/src/modal.ts +296 -211
- package/src/parallax.ts +129 -105
- package/src/pushpin.ts +148 -103
- package/src/range.ts +166 -150
- package/src/scrollspy.ts +214 -174
- package/src/select.ts +434 -398
- package/src/sidenav.ts +447 -381
- package/src/slider.ts +421 -362
- package/src/tabs.ts +276 -222
- package/src/tapTarget.ts +246 -213
- package/src/timepicker.ts +738 -614
- package/src/toasts.ts +254 -230
- package/src/tooltip.ts +315 -252
- package/src/utils.ts +271 -0
- package/src/waves.ts +10 -10
package/src/datepicker.ts
CHANGED
|
@@ -1,9 +1,155 @@
|
|
|
1
|
-
import { Component } from "./component";
|
|
2
|
-
import { M } from "./global";
|
|
3
1
|
import { Modal } from "./modal";
|
|
2
|
+
import { Utils } from "./utils";
|
|
4
3
|
import { FormSelect } from "./select";
|
|
4
|
+
import { BaseOptions, Component, InitElements, MElement, I18nOptions } from "./component";
|
|
5
|
+
|
|
6
|
+
export interface DateI18nOptions extends I18nOptions {
|
|
7
|
+
previousMonth: string;
|
|
8
|
+
nextMonth: string;
|
|
9
|
+
months: string[];
|
|
10
|
+
monthsShort: string[];
|
|
11
|
+
weekdays: string[];
|
|
12
|
+
weekdaysShort: string[];
|
|
13
|
+
weekdaysAbbrev: string[];
|
|
14
|
+
};
|
|
5
15
|
|
|
6
|
-
|
|
16
|
+
export interface DatepickerOptions extends BaseOptions {
|
|
17
|
+
/**
|
|
18
|
+
* Automatically close picker when date is selected.
|
|
19
|
+
* @default false
|
|
20
|
+
*/
|
|
21
|
+
autoClose: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* The date output format for the input field value
|
|
24
|
+
* or a function taking the date and outputting the
|
|
25
|
+
* formatted date string.
|
|
26
|
+
* @default 'mmm dd, yyyy'
|
|
27
|
+
*/
|
|
28
|
+
format: string | ((d: Date) => string);
|
|
29
|
+
/**
|
|
30
|
+
* Used to create date object from current input string.
|
|
31
|
+
* @default null
|
|
32
|
+
*/
|
|
33
|
+
parse: ((value: string, format: string) => Date) | null;
|
|
34
|
+
/**
|
|
35
|
+
* The initial date to view when first opened.
|
|
36
|
+
* @default null
|
|
37
|
+
*/
|
|
38
|
+
defaultDate: Date | null;
|
|
39
|
+
/**
|
|
40
|
+
* Make the `defaultDate` the initial selected value.
|
|
41
|
+
* @default false
|
|
42
|
+
*/
|
|
43
|
+
setDefaultDate: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Prevent selection of any date on the weekend.
|
|
46
|
+
* @default false
|
|
47
|
+
*/
|
|
48
|
+
disableWeekends: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Custom function to disable certain days.
|
|
51
|
+
* @default null
|
|
52
|
+
*/
|
|
53
|
+
disableDayFn: ((day: Date) => boolean) | null;
|
|
54
|
+
/**
|
|
55
|
+
* First day of week (0: Sunday, 1: Monday etc).
|
|
56
|
+
* @default 0
|
|
57
|
+
*/
|
|
58
|
+
firstDay: number;
|
|
59
|
+
/**
|
|
60
|
+
* The earliest date that can be selected.
|
|
61
|
+
* @default null
|
|
62
|
+
*/
|
|
63
|
+
minDate: Date | null;
|
|
64
|
+
/**
|
|
65
|
+
* The latest date that can be selected.
|
|
66
|
+
* @default null
|
|
67
|
+
*/
|
|
68
|
+
maxDate: Date | null;
|
|
69
|
+
/**
|
|
70
|
+
* Number of years either side, or array of upper/lower range.
|
|
71
|
+
* @default 10
|
|
72
|
+
*/
|
|
73
|
+
yearRange: number | number[];
|
|
74
|
+
/**
|
|
75
|
+
* Sort year range in reverse order.
|
|
76
|
+
* @default false
|
|
77
|
+
*/
|
|
78
|
+
yearRangeReverse: boolean;
|
|
79
|
+
/**
|
|
80
|
+
* Changes Datepicker to RTL.
|
|
81
|
+
* @default false
|
|
82
|
+
*/
|
|
83
|
+
isRTL: boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Show month after year in Datepicker title.
|
|
86
|
+
* @default false
|
|
87
|
+
*/
|
|
88
|
+
showMonthAfterYear: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Render days of the calendar grid that fall in the next
|
|
91
|
+
* or previous month.
|
|
92
|
+
* @default false
|
|
93
|
+
*/
|
|
94
|
+
showDaysInNextAndPreviousMonths: boolean;
|
|
95
|
+
/**
|
|
96
|
+
* Specify a DOM element OR selector for a DOM element to render
|
|
97
|
+
* the calendar in, by default it will be placed before the input.
|
|
98
|
+
* @default null
|
|
99
|
+
*/
|
|
100
|
+
container: HTMLElement | string | null;
|
|
101
|
+
/**
|
|
102
|
+
* Show the clear button in the datepicker.
|
|
103
|
+
* @default false
|
|
104
|
+
*/
|
|
105
|
+
showClearBtn: boolean;
|
|
106
|
+
/**
|
|
107
|
+
* Internationalization options.
|
|
108
|
+
*/
|
|
109
|
+
i18n: Partial<DateI18nOptions>;
|
|
110
|
+
/**
|
|
111
|
+
* An array of string returned by `Date.toDateString()`,
|
|
112
|
+
* indicating there are events in the specified days.
|
|
113
|
+
* @default []
|
|
114
|
+
*/
|
|
115
|
+
events: string[];
|
|
116
|
+
/**
|
|
117
|
+
* Callback function when date is selected,
|
|
118
|
+
* first parameter is the newly selected date.
|
|
119
|
+
* @default null
|
|
120
|
+
*/
|
|
121
|
+
onSelect: ((selectedDate: Date) => void) | null;
|
|
122
|
+
/**
|
|
123
|
+
* Callback function when Datepicker is opened.
|
|
124
|
+
* @default null
|
|
125
|
+
*/
|
|
126
|
+
onOpen: (() => void) | null;
|
|
127
|
+
/**
|
|
128
|
+
* Callback function when Datepicker is closed.
|
|
129
|
+
* @default null
|
|
130
|
+
*/
|
|
131
|
+
onClose: (() => void) | null;
|
|
132
|
+
/**
|
|
133
|
+
* Callback function when Datepicker HTML is refreshed.
|
|
134
|
+
* @default null
|
|
135
|
+
*/
|
|
136
|
+
onDraw: (() => void) | null;
|
|
137
|
+
|
|
138
|
+
/** Field used for internal calculations DO NOT CHANGE IT */
|
|
139
|
+
minYear?: any;
|
|
140
|
+
/** Field used for internal calculations DO NOT CHANGE IT */
|
|
141
|
+
maxYear?: any;
|
|
142
|
+
/** Field used for internal calculations DO NOT CHANGE IT */
|
|
143
|
+
minMonth?: any;
|
|
144
|
+
/** Field used for internal calculations DO NOT CHANGE IT */
|
|
145
|
+
maxMonth?: any;
|
|
146
|
+
/** Field used for internal calculations DO NOT CHANGE IT */
|
|
147
|
+
startRange?: any;
|
|
148
|
+
/** Field used for internal calculations DO NOT CHANGE IT */
|
|
149
|
+
endRange?: any;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
let _defaults: DatepickerOptions = {
|
|
7
153
|
// Close when date is selected
|
|
8
154
|
autoClose: false,
|
|
9
155
|
// the default output format for the input field value
|
|
@@ -32,6 +178,7 @@ let _defaults = {
|
|
|
32
178
|
startRange: null,
|
|
33
179
|
endRange: null,
|
|
34
180
|
isRTL: false,
|
|
181
|
+
yearRangeReverse: false,
|
|
35
182
|
// Render the month after year in the calendar title
|
|
36
183
|
showMonthAfterYear: false,
|
|
37
184
|
// Render days of the calendar grid that fall in the next or previous month
|
|
@@ -88,810 +235,842 @@ let _defaults = {
|
|
|
88
235
|
onDraw: null
|
|
89
236
|
};
|
|
90
237
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
238
|
+
export class Datepicker extends Component<DatepickerOptions> {
|
|
239
|
+
declare el: HTMLInputElement
|
|
240
|
+
id: string;
|
|
241
|
+
/** If the picker is open. */
|
|
242
|
+
isOpen: boolean;
|
|
243
|
+
modal: Modal;
|
|
244
|
+
calendarEl: HTMLElement;
|
|
245
|
+
/** CLEAR button instance. */
|
|
246
|
+
clearBtn: HTMLElement;
|
|
247
|
+
/** DONE button instance */
|
|
248
|
+
doneBtn: HTMLElement;
|
|
249
|
+
cancelBtn: HTMLElement;
|
|
250
|
+
modalEl: HTMLElement;
|
|
251
|
+
yearTextEl: HTMLElement;
|
|
252
|
+
dateTextEl: HTMLElement;
|
|
253
|
+
/** The selected Date. */
|
|
254
|
+
date: Date;
|
|
255
|
+
formats: any;
|
|
256
|
+
calendars: any;
|
|
257
|
+
private _y: any;
|
|
258
|
+
private _m: any;
|
|
259
|
+
static _template: string;
|
|
260
|
+
|
|
261
|
+
constructor(el: HTMLInputElement, options: Partial<DatepickerOptions>) {
|
|
262
|
+
super(el, options, Datepicker);
|
|
263
|
+
(this.el as any).M_Datepicker = this;
|
|
264
|
+
|
|
265
|
+
this.options = {
|
|
266
|
+
...Datepicker.defaults,
|
|
267
|
+
...options
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
// make sure i18n defaults are not lost when only few i18n option properties are passed
|
|
271
|
+
if (!!options && options.hasOwnProperty('i18n') && typeof options.i18n === 'object') {
|
|
272
|
+
this.options.i18n = {...Datepicker.defaults.i18n, ...options.i18n};
|
|
273
|
+
}
|
|
126
274
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
275
|
+
// Remove time component from minDate and maxDate options
|
|
276
|
+
if (this.options.minDate) this.options.minDate.setHours(0, 0, 0, 0);
|
|
277
|
+
if (this.options.maxDate) this.options.maxDate.setHours(0, 0, 0, 0);
|
|
130
278
|
|
|
131
|
-
|
|
279
|
+
this.id = Utils.guid();
|
|
132
280
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
281
|
+
this._setupVariables();
|
|
282
|
+
this._insertHTMLIntoDOM();
|
|
283
|
+
this._setupModal();
|
|
284
|
+
this._setupEventHandlers();
|
|
137
285
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
286
|
+
if (!this.options.defaultDate) {
|
|
287
|
+
this.options.defaultDate = new Date(Date.parse(this.el.value));
|
|
288
|
+
}
|
|
141
289
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}
|
|
148
|
-
else {
|
|
149
|
-
this.gotoDate(defDate);
|
|
150
|
-
}
|
|
290
|
+
let defDate = this.options.defaultDate;
|
|
291
|
+
if (Datepicker._isDate(defDate)) {
|
|
292
|
+
if (this.options.setDefaultDate) {
|
|
293
|
+
this.setDate(defDate, true);
|
|
294
|
+
this.setInputValue();
|
|
151
295
|
}
|
|
152
296
|
else {
|
|
153
|
-
this.gotoDate(
|
|
297
|
+
this.gotoDate(defDate);
|
|
154
298
|
}
|
|
155
|
-
this.isOpen = false;
|
|
156
299
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
return _defaults;
|
|
300
|
+
else {
|
|
301
|
+
this.gotoDate(new Date());
|
|
160
302
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
303
|
+
this.isOpen = false;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
static get defaults() {
|
|
307
|
+
return _defaults;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Initializes instance of Datepicker.
|
|
312
|
+
* @param el HTML element.
|
|
313
|
+
* @param options Component options.
|
|
314
|
+
*/
|
|
315
|
+
static init(el: HTMLInputElement, options?: Partial<DatepickerOptions>): Datepicker;
|
|
316
|
+
/**
|
|
317
|
+
* Initializes instances of Datepicker.
|
|
318
|
+
* @param els HTML elements.
|
|
319
|
+
* @param options Component options.
|
|
320
|
+
*/
|
|
321
|
+
static init(els: InitElements<HTMLInputElement | MElement>, options?: Partial<DatepickerOptions>): Datepicker[];
|
|
322
|
+
/**
|
|
323
|
+
* Initializes instances of Datepicker.
|
|
324
|
+
* @param els HTML elements.
|
|
325
|
+
* @param options Component options.
|
|
326
|
+
*/
|
|
327
|
+
static init(els: HTMLInputElement | InitElements<HTMLInputElement | MElement>, options: Partial<DatepickerOptions> = {}): Datepicker | Datepicker[] {
|
|
328
|
+
return super.init(els, options, Datepicker);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
static _isDate(obj) {
|
|
332
|
+
return /Date/.test(Object.prototype.toString.call(obj)) && !isNaN(obj.getTime());
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
static _isWeekend(date) {
|
|
336
|
+
let day = date.getDay();
|
|
337
|
+
return day === 0 || day === 6;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
static _setToStartOfDay(date) {
|
|
341
|
+
if (Datepicker._isDate(date)) date.setHours(0, 0, 0, 0);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
static _getDaysInMonth(year, month) {
|
|
345
|
+
return [31, Datepicker._isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][
|
|
346
|
+
month
|
|
347
|
+
];
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
static _isLeapYear(year) {
|
|
351
|
+
// solution by Matti Virkkunen: http://stackoverflow.com/a/4881951
|
|
352
|
+
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
static _compareDates(a, b) {
|
|
356
|
+
// weak date comparison (use setToStartOfDay(date) to ensure correct result)
|
|
357
|
+
return a.getTime() === b.getTime();
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
static getInstance(el: HTMLElement): Datepicker {
|
|
361
|
+
return (el as any).M_Datepicker;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
destroy() {
|
|
365
|
+
this._removeEventHandlers();
|
|
366
|
+
this.modal.destroy();
|
|
367
|
+
this.modalEl.remove();
|
|
368
|
+
this.destroySelects();
|
|
369
|
+
(this.el as any).M_Datepicker = undefined;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
destroySelects() {
|
|
373
|
+
let oldYearSelect = this.calendarEl.querySelector('.orig-select-year');
|
|
374
|
+
if (oldYearSelect) {
|
|
375
|
+
FormSelect.getInstance(oldYearSelect as HTMLElement).destroy();
|
|
164
376
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
377
|
+
let oldMonthSelect = this.calendarEl.querySelector('.orig-select-month');
|
|
378
|
+
if (oldMonthSelect) {
|
|
379
|
+
FormSelect.getInstance(oldMonthSelect as HTMLElement).destroy();
|
|
168
380
|
}
|
|
381
|
+
}
|
|
169
382
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
383
|
+
_insertHTMLIntoDOM() {
|
|
384
|
+
if (this.options.showClearBtn) {
|
|
385
|
+
this.clearBtn.style.visibility = '';
|
|
386
|
+
this.clearBtn.innerText = this.options.i18n.clear;
|
|
173
387
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
388
|
+
this.doneBtn.innerText = this.options.i18n.done;
|
|
389
|
+
this.cancelBtn.innerText = this.options.i18n.cancel;
|
|
390
|
+
|
|
391
|
+
if (this.options.container) {
|
|
392
|
+
const optEl = this.options.container;
|
|
393
|
+
this.options.container =
|
|
394
|
+
optEl instanceof HTMLElement ? optEl : document.querySelector(optEl) as HTMLElement;
|
|
395
|
+
this.options.container.append(this.modalEl);
|
|
177
396
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
month
|
|
182
|
-
];
|
|
397
|
+
else {
|
|
398
|
+
//this.modalEl.before(this.el);
|
|
399
|
+
this.el.parentElement.appendChild(this.modalEl);
|
|
183
400
|
}
|
|
401
|
+
}
|
|
184
402
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
403
|
+
_setupModal() {
|
|
404
|
+
this.modalEl.id = 'modal-' + this.id;
|
|
405
|
+
this.modal = Modal.init(this.modalEl, {
|
|
406
|
+
onCloseEnd: () => {
|
|
407
|
+
this.isOpen = false;
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Gets a string representation of the selected date.
|
|
414
|
+
*/
|
|
415
|
+
toString(format: string | ((d: Date) => string) = null): string {
|
|
416
|
+
format = format || this.options.format;
|
|
417
|
+
if (typeof format === 'function') return format(this.date);
|
|
418
|
+
if (!Datepicker._isDate(this.date)) return '';
|
|
419
|
+
// String Format
|
|
420
|
+
const formatArray = format.split(/(d{1,4}|m{1,4}|y{4}|yy|!.)/g);
|
|
421
|
+
const formattedDate = formatArray
|
|
422
|
+
.map(label => this.formats[label] ? this.formats[label]() : label)
|
|
423
|
+
.join('');
|
|
424
|
+
return formattedDate;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Set a date on the datepicker.
|
|
429
|
+
* @param date Date to set on the datepicker.
|
|
430
|
+
* @param preventOnSelect Undocumented as of 5 March 2018.
|
|
431
|
+
*/
|
|
432
|
+
setDate(date: Date | string = null, preventOnSelect: boolean = false) {
|
|
433
|
+
if (!date) {
|
|
434
|
+
this.date = null;
|
|
435
|
+
this._renderDateDisplay();
|
|
436
|
+
return this.draw();
|
|
188
437
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
// weak date comparison (use setToStartOfDay(date) to ensure correct result)
|
|
192
|
-
return a.getTime() === b.getTime();
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
static getInstance(el) {
|
|
196
|
-
let domElem = !!el.jquery ? el[0] : el;
|
|
197
|
-
return domElem.M_Datepicker;
|
|
438
|
+
if (typeof date === 'string') {
|
|
439
|
+
date = new Date(Date.parse(date));
|
|
198
440
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
this._removeEventHandlers();
|
|
202
|
-
this.modal.destroy();
|
|
203
|
-
this.modalEl.remove();
|
|
204
|
-
this.destroySelects();
|
|
205
|
-
(this.el as any).M_Datepicker = undefined;
|
|
441
|
+
if (!Datepicker._isDate(date)) {
|
|
442
|
+
return;
|
|
206
443
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
FormSelect.getInstance(oldYearSelect).destroy();
|
|
212
|
-
}
|
|
213
|
-
let oldMonthSelect = this.calendarEl.querySelector('.orig-select-month');
|
|
214
|
-
if (oldMonthSelect) {
|
|
215
|
-
FormSelect.getInstance(oldMonthSelect).destroy();
|
|
216
|
-
}
|
|
444
|
+
let min = this.options.minDate,
|
|
445
|
+
max = this.options.maxDate;
|
|
446
|
+
if (Datepicker._isDate(min) && date < min) {
|
|
447
|
+
date = min;
|
|
217
448
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
if (this.options.showClearBtn) {
|
|
221
|
-
this.clearBtn.style.visibility = '';
|
|
222
|
-
this.clearBtn.innerText = this.options.i18n.clear;
|
|
223
|
-
}
|
|
224
|
-
this.doneBtn.innerText = this.options.i18n.done;
|
|
225
|
-
this.cancelBtn.innerText = this.options.i18n.cancel;
|
|
226
|
-
|
|
227
|
-
if (this.options.container) {
|
|
228
|
-
const optEl = this.options.container;
|
|
229
|
-
this.options.container =
|
|
230
|
-
optEl instanceof HTMLElement ? optEl : document.querySelector(optEl);
|
|
231
|
-
this.options.container.append(this.modalEl);
|
|
232
|
-
}
|
|
233
|
-
else {
|
|
234
|
-
//this.modalEl.before(this.el);
|
|
235
|
-
this.el.parentElement.appendChild(this.modalEl);
|
|
236
|
-
}
|
|
449
|
+
else if (Datepicker._isDate(max) && date > max) {
|
|
450
|
+
date = max;
|
|
237
451
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
245
|
-
});
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
toString(format: string | ((d: Date) => string) = null): string {
|
|
249
|
-
format = format || this.options.format;
|
|
250
|
-
if (typeof format === 'function') return format(this.date);
|
|
251
|
-
if (!Datepicker._isDate(this.date)) return '';
|
|
252
|
-
// String Format
|
|
253
|
-
const formatArray = format.split(/(d{1,4}|m{1,4}|y{4}|yy|!.)/g);
|
|
254
|
-
const formattedDate = formatArray
|
|
255
|
-
.map(label => this.formats[label] ? this.formats[label]() : label)
|
|
256
|
-
.join('');
|
|
257
|
-
return formattedDate;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
setDate(date, preventOnSelect: boolean = false) {
|
|
261
|
-
if (!date) {
|
|
262
|
-
this.date = null;
|
|
263
|
-
this._renderDateDisplay();
|
|
264
|
-
return this.draw();
|
|
265
|
-
}
|
|
266
|
-
if (typeof date === 'string') {
|
|
267
|
-
date = new Date(Date.parse(date));
|
|
268
|
-
}
|
|
269
|
-
if (!Datepicker._isDate(date)) {
|
|
270
|
-
return;
|
|
271
|
-
}
|
|
272
|
-
let min = this.options.minDate,
|
|
273
|
-
max = this.options.maxDate;
|
|
274
|
-
if (Datepicker._isDate(min) && date < min) {
|
|
275
|
-
date = min;
|
|
276
|
-
}
|
|
277
|
-
else if (Datepicker._isDate(max) && date > max) {
|
|
278
|
-
date = max;
|
|
279
|
-
}
|
|
280
|
-
this.date = new Date(date.getTime());
|
|
281
|
-
this._renderDateDisplay();
|
|
282
|
-
Datepicker._setToStartOfDay(this.date);
|
|
283
|
-
this.gotoDate(this.date);
|
|
284
|
-
if (!preventOnSelect && typeof this.options.onSelect === 'function') {
|
|
285
|
-
this.options.onSelect.call(this, this.date);
|
|
286
|
-
}
|
|
452
|
+
this.date = new Date(date.getTime());
|
|
453
|
+
this._renderDateDisplay();
|
|
454
|
+
Datepicker._setToStartOfDay(this.date);
|
|
455
|
+
this.gotoDate(this.date);
|
|
456
|
+
if (!preventOnSelect && typeof this.options.onSelect === 'function') {
|
|
457
|
+
this.options.onSelect.call(this, this.date);
|
|
287
458
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Sets current date as the input value.
|
|
463
|
+
*/
|
|
464
|
+
setInputValue() {
|
|
465
|
+
this.el.value = this.toString();
|
|
466
|
+
this.el.dispatchEvent(new CustomEvent('change', {detail: {firedBy: this}}));
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
_renderDateDisplay() {
|
|
470
|
+
let displayDate = Datepicker._isDate(this.date) ? this.date : new Date();
|
|
471
|
+
let i18n = this.options.i18n;
|
|
472
|
+
let day = i18n.weekdaysShort[displayDate.getDay()];
|
|
473
|
+
let month = i18n.monthsShort[displayDate.getMonth()];
|
|
474
|
+
let date = displayDate.getDate();
|
|
475
|
+
this.yearTextEl.innerHTML = displayDate.getFullYear().toString();
|
|
476
|
+
this.dateTextEl.innerHTML = `${day}, ${month} ${date}`;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Change date view to a specific date on the datepicker.
|
|
481
|
+
* @param date Date to show on the datepicker.
|
|
482
|
+
*/
|
|
483
|
+
gotoDate(date: Date) {
|
|
484
|
+
let newCalendar = true;
|
|
485
|
+
if (!Datepicker._isDate(date)) {
|
|
486
|
+
return;
|
|
292
487
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
488
|
+
if (this.calendars) {
|
|
489
|
+
let firstVisibleDate = new Date(this.calendars[0].year, this.calendars[0].month, 1),
|
|
490
|
+
lastVisibleDate = new Date(
|
|
491
|
+
this.calendars[this.calendars.length - 1].year,
|
|
492
|
+
this.calendars[this.calendars.length - 1].month,
|
|
493
|
+
1
|
|
494
|
+
),
|
|
495
|
+
visibleDate = date.getTime();
|
|
496
|
+
// get the end of the month
|
|
497
|
+
lastVisibleDate.setMonth(lastVisibleDate.getMonth() + 1);
|
|
498
|
+
lastVisibleDate.setDate(lastVisibleDate.getDate() - 1);
|
|
499
|
+
newCalendar =
|
|
500
|
+
visibleDate < firstVisibleDate.getTime() || lastVisibleDate.getTime() < visibleDate;
|
|
302
501
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
let firstVisibleDate = new Date(this.calendars[0].year, this.calendars[0].month, 1),
|
|
311
|
-
lastVisibleDate = new Date(
|
|
312
|
-
this.calendars[this.calendars.length - 1].year,
|
|
313
|
-
this.calendars[this.calendars.length - 1].month,
|
|
314
|
-
1
|
|
315
|
-
),
|
|
316
|
-
visibleDate = date.getTime();
|
|
317
|
-
// get the end of the month
|
|
318
|
-
lastVisibleDate.setMonth(lastVisibleDate.getMonth() + 1);
|
|
319
|
-
lastVisibleDate.setDate(lastVisibleDate.getDate() - 1);
|
|
320
|
-
newCalendar =
|
|
321
|
-
visibleDate < firstVisibleDate.getTime() || lastVisibleDate.getTime() < visibleDate;
|
|
322
|
-
}
|
|
323
|
-
if (newCalendar) {
|
|
324
|
-
this.calendars = [
|
|
325
|
-
{
|
|
326
|
-
month: date.getMonth(),
|
|
327
|
-
year: date.getFullYear()
|
|
328
|
-
}
|
|
329
|
-
];
|
|
330
|
-
}
|
|
331
|
-
this.adjustCalendars();
|
|
502
|
+
if (newCalendar) {
|
|
503
|
+
this.calendars = [
|
|
504
|
+
{
|
|
505
|
+
month: date.getMonth(),
|
|
506
|
+
year: date.getFullYear()
|
|
507
|
+
}
|
|
508
|
+
];
|
|
332
509
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
510
|
+
this.adjustCalendars();
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
adjustCalendars() {
|
|
514
|
+
this.calendars[0] = this.adjustCalendar(this.calendars[0]);
|
|
515
|
+
this.draw();
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
adjustCalendar(calendar) {
|
|
519
|
+
if (calendar.month < 0) {
|
|
520
|
+
calendar.year -= Math.ceil(Math.abs(calendar.month) / 12);
|
|
521
|
+
calendar.month += 12;
|
|
337
522
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
calendar.year -= Math.ceil(Math.abs(calendar.month) / 12);
|
|
342
|
-
calendar.month += 12;
|
|
343
|
-
}
|
|
344
|
-
if (calendar.month > 11) {
|
|
345
|
-
calendar.year += Math.floor(Math.abs(calendar.month) / 12);
|
|
346
|
-
calendar.month -= 12;
|
|
347
|
-
}
|
|
348
|
-
return calendar;
|
|
523
|
+
if (calendar.month > 11) {
|
|
524
|
+
calendar.year += Math.floor(Math.abs(calendar.month) / 12);
|
|
525
|
+
calendar.month -= 12;
|
|
349
526
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
527
|
+
return calendar;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
nextMonth() {
|
|
531
|
+
this.calendars[0].month++;
|
|
532
|
+
this.adjustCalendars();
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
prevMonth() {
|
|
536
|
+
this.calendars[0].month--;
|
|
537
|
+
this.adjustCalendars();
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
render(year, month, randId) {
|
|
541
|
+
let opts = this.options,
|
|
542
|
+
now = new Date(),
|
|
543
|
+
days = Datepicker._getDaysInMonth(year, month),
|
|
544
|
+
before = new Date(year, month, 1).getDay(),
|
|
545
|
+
data = [],
|
|
546
|
+
row = [];
|
|
547
|
+
Datepicker._setToStartOfDay(now);
|
|
548
|
+
if (opts.firstDay > 0) {
|
|
549
|
+
before -= opts.firstDay;
|
|
550
|
+
if (before < 0) {
|
|
551
|
+
before += 7;
|
|
552
|
+
}
|
|
354
553
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
554
|
+
let previousMonth = month === 0 ? 11 : month - 1,
|
|
555
|
+
nextMonth = month === 11 ? 0 : month + 1,
|
|
556
|
+
yearOfPreviousMonth = month === 0 ? year - 1 : year,
|
|
557
|
+
yearOfNextMonth = month === 11 ? year + 1 : year,
|
|
558
|
+
daysInPreviousMonth = Datepicker._getDaysInMonth(yearOfPreviousMonth, previousMonth);
|
|
559
|
+
let cells = days + before,
|
|
560
|
+
after = cells;
|
|
561
|
+
while (after > 7) {
|
|
562
|
+
after -= 7;
|
|
359
563
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
564
|
+
cells += 7 - after;
|
|
565
|
+
let isWeekSelected = false;
|
|
566
|
+
for (let i = 0, r = 0; i < cells; i++) {
|
|
567
|
+
let day = new Date(year, month, 1 + (i - before)),
|
|
568
|
+
isSelected = Datepicker._isDate(this.date)
|
|
569
|
+
? Datepicker._compareDates(day, this.date)
|
|
570
|
+
: false,
|
|
571
|
+
isToday = Datepicker._compareDates(day, now),
|
|
572
|
+
hasEvent = opts.events.indexOf(day.toDateString()) !== -1 ? true : false,
|
|
573
|
+
isEmpty = i < before || i >= days + before,
|
|
574
|
+
dayNumber = 1 + (i - before),
|
|
575
|
+
monthNumber = month,
|
|
576
|
+
yearNumber = year,
|
|
577
|
+
isStartRange = opts.startRange && Datepicker._compareDates(opts.startRange, day),
|
|
578
|
+
isEndRange = opts.endRange && Datepicker._compareDates(opts.endRange, day),
|
|
579
|
+
isInRange =
|
|
580
|
+
opts.startRange && opts.endRange && opts.startRange < day && day < opts.endRange,
|
|
581
|
+
isDisabled =
|
|
582
|
+
(opts.minDate && day < opts.minDate) ||
|
|
583
|
+
(opts.maxDate && day > opts.maxDate) ||
|
|
584
|
+
(opts.disableWeekends && Datepicker._isWeekend(day)) ||
|
|
585
|
+
(opts.disableDayFn && opts.disableDayFn(day));
|
|
586
|
+
|
|
587
|
+
if (isEmpty) {
|
|
588
|
+
if (i < before) {
|
|
589
|
+
dayNumber = daysInPreviousMonth + dayNumber;
|
|
590
|
+
monthNumber = previousMonth;
|
|
591
|
+
yearNumber = yearOfPreviousMonth;
|
|
592
|
+
} else {
|
|
593
|
+
dayNumber = dayNumber - days;
|
|
594
|
+
monthNumber = nextMonth;
|
|
595
|
+
yearNumber = yearOfNextMonth;
|
|
373
596
|
}
|
|
374
597
|
}
|
|
375
|
-
let previousMonth = month === 0 ? 11 : month - 1,
|
|
376
|
-
nextMonth = month === 11 ? 0 : month + 1,
|
|
377
|
-
yearOfPreviousMonth = month === 0 ? year - 1 : year,
|
|
378
|
-
yearOfNextMonth = month === 11 ? year + 1 : year,
|
|
379
|
-
daysInPreviousMonth = Datepicker._getDaysInMonth(yearOfPreviousMonth, previousMonth);
|
|
380
|
-
let cells = days + before,
|
|
381
|
-
after = cells;
|
|
382
|
-
while (after > 7) {
|
|
383
|
-
after -= 7;
|
|
384
|
-
}
|
|
385
|
-
cells += 7 - after;
|
|
386
|
-
let isWeekSelected = false;
|
|
387
|
-
for (let i = 0, r = 0; i < cells; i++) {
|
|
388
|
-
let day = new Date(year, month, 1 + (i - before)),
|
|
389
|
-
isSelected = Datepicker._isDate(this.date)
|
|
390
|
-
? Datepicker._compareDates(day, this.date)
|
|
391
|
-
: false,
|
|
392
|
-
isToday = Datepicker._compareDates(day, now),
|
|
393
|
-
hasEvent = opts.events.indexOf(day.toDateString()) !== -1 ? true : false,
|
|
394
|
-
isEmpty = i < before || i >= days + before,
|
|
395
|
-
dayNumber = 1 + (i - before),
|
|
396
|
-
monthNumber = month,
|
|
397
|
-
yearNumber = year,
|
|
398
|
-
isStartRange = opts.startRange && Datepicker._compareDates(opts.startRange, day),
|
|
399
|
-
isEndRange = opts.endRange && Datepicker._compareDates(opts.endRange, day),
|
|
400
|
-
isInRange =
|
|
401
|
-
opts.startRange && opts.endRange && opts.startRange < day && day < opts.endRange,
|
|
402
|
-
isDisabled =
|
|
403
|
-
(opts.minDate && day < opts.minDate) ||
|
|
404
|
-
(opts.maxDate && day > opts.maxDate) ||
|
|
405
|
-
(opts.disableWeekends && Datepicker._isWeekend(day)) ||
|
|
406
|
-
(opts.disableDayFn && opts.disableDayFn(day));
|
|
407
|
-
|
|
408
|
-
if (isEmpty) {
|
|
409
|
-
if (i < before) {
|
|
410
|
-
dayNumber = daysInPreviousMonth + dayNumber;
|
|
411
|
-
monthNumber = previousMonth;
|
|
412
|
-
yearNumber = yearOfPreviousMonth;
|
|
413
|
-
} else {
|
|
414
|
-
dayNumber = dayNumber - days;
|
|
415
|
-
monthNumber = nextMonth;
|
|
416
|
-
yearNumber = yearOfNextMonth;
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
598
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
row.push(this.renderDay(dayConfig));
|
|
436
|
-
|
|
437
|
-
if (++r === 7) {
|
|
438
|
-
data.push(this.renderRow(row, opts.isRTL, isWeekSelected));
|
|
439
|
-
row = [];
|
|
440
|
-
r = 0;
|
|
441
|
-
isWeekSelected = false;
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
return this.renderTable(opts, data, randId);
|
|
445
|
-
}
|
|
599
|
+
let dayConfig = {
|
|
600
|
+
day: dayNumber,
|
|
601
|
+
month: monthNumber,
|
|
602
|
+
year: yearNumber,
|
|
603
|
+
hasEvent: hasEvent,
|
|
604
|
+
isSelected: isSelected,
|
|
605
|
+
isToday: isToday,
|
|
606
|
+
isDisabled: isDisabled,
|
|
607
|
+
isEmpty: isEmpty,
|
|
608
|
+
isStartRange: isStartRange,
|
|
609
|
+
isEndRange: isEndRange,
|
|
610
|
+
isInRange: isInRange,
|
|
611
|
+
showDaysInNextAndPreviousMonths: opts.showDaysInNextAndPreviousMonths
|
|
612
|
+
};
|
|
446
613
|
|
|
447
|
-
|
|
448
|
-
let arr = [];
|
|
449
|
-
let ariaSelected = 'false';
|
|
450
|
-
if (opts.isEmpty) {
|
|
451
|
-
if (opts.showDaysInNextAndPreviousMonths) {
|
|
452
|
-
arr.push('is-outside-current-month');
|
|
453
|
-
arr.push('is-selection-disabled');
|
|
454
|
-
} else {
|
|
455
|
-
return '<td class="is-empty"></td>';
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
if (opts.isDisabled) {
|
|
459
|
-
arr.push('is-disabled');
|
|
460
|
-
}
|
|
614
|
+
row.push(this.renderDay(dayConfig));
|
|
461
615
|
|
|
462
|
-
if (
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
ariaSelected = 'true';
|
|
468
|
-
}
|
|
469
|
-
if (opts.hasEvent) {
|
|
470
|
-
arr.push('has-event');
|
|
471
|
-
}
|
|
472
|
-
if (opts.isInRange) {
|
|
473
|
-
arr.push('is-inrange');
|
|
474
|
-
}
|
|
475
|
-
if (opts.isStartRange) {
|
|
476
|
-
arr.push('is-startrange');
|
|
616
|
+
if (++r === 7) {
|
|
617
|
+
data.push(this.renderRow(row, opts.isRTL, isWeekSelected));
|
|
618
|
+
row = [];
|
|
619
|
+
r = 0;
|
|
620
|
+
isWeekSelected = false;
|
|
477
621
|
}
|
|
478
|
-
|
|
479
|
-
|
|
622
|
+
}
|
|
623
|
+
return this.renderTable(opts, data, randId);
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
renderDay(opts) {
|
|
627
|
+
let arr = [];
|
|
628
|
+
let ariaSelected = 'false';
|
|
629
|
+
if (opts.isEmpty) {
|
|
630
|
+
if (opts.showDaysInNextAndPreviousMonths) {
|
|
631
|
+
arr.push('is-outside-current-month');
|
|
632
|
+
arr.push('is-selection-disabled');
|
|
633
|
+
} else {
|
|
634
|
+
return '<td class="is-empty"></td>';
|
|
480
635
|
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
'</td>'
|
|
485
|
-
);
|
|
636
|
+
}
|
|
637
|
+
if (opts.isDisabled) {
|
|
638
|
+
arr.push('is-disabled');
|
|
486
639
|
}
|
|
487
640
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
641
|
+
if (opts.isToday) {
|
|
642
|
+
arr.push('is-today');
|
|
643
|
+
}
|
|
644
|
+
if (opts.isSelected) {
|
|
645
|
+
arr.push('is-selected');
|
|
646
|
+
ariaSelected = 'true';
|
|
647
|
+
}
|
|
648
|
+
if (opts.hasEvent) {
|
|
649
|
+
arr.push('has-event');
|
|
650
|
+
}
|
|
651
|
+
if (opts.isInRange) {
|
|
652
|
+
arr.push('is-inrange');
|
|
653
|
+
}
|
|
654
|
+
if (opts.isStartRange) {
|
|
655
|
+
arr.push('is-startrange');
|
|
656
|
+
}
|
|
657
|
+
if (opts.isEndRange) {
|
|
658
|
+
arr.push('is-endrange');
|
|
659
|
+
}
|
|
660
|
+
return (
|
|
661
|
+
`<td data-day="${opts.day}" class="${arr.join(' ')}" aria-selected="${ariaSelected}">` +
|
|
662
|
+
`<button class="datepicker-day-button" type="button" data-year="${opts.year}" data-month="${opts.month}" data-day="${opts.day}">${opts.day}</button>` +
|
|
663
|
+
'</td>'
|
|
664
|
+
);
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
renderRow(days, isRTL, isRowSelected) {
|
|
668
|
+
return (
|
|
669
|
+
'<tr class="datepicker-row' +
|
|
670
|
+
(isRowSelected ? ' is-selected' : '') +
|
|
671
|
+
'">' +
|
|
672
|
+
(isRTL ? days.reverse() : days).join('') +
|
|
673
|
+
'</tr>'
|
|
674
|
+
);
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
renderTable(opts, data, randId) {
|
|
678
|
+
return (
|
|
679
|
+
'<div class="datepicker-table-wrapper"><table cellpadding="0" cellspacing="0" class="datepicker-table" role="grid" aria-labelledby="' +
|
|
680
|
+
randId +
|
|
681
|
+
'">' +
|
|
682
|
+
this.renderHead(opts) +
|
|
683
|
+
this.renderBody(data) +
|
|
684
|
+
'</table></div>'
|
|
685
|
+
);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
renderHead(opts) {
|
|
689
|
+
let i,
|
|
690
|
+
arr = [];
|
|
691
|
+
for (i = 0; i < 7; i++) {
|
|
692
|
+
arr.push(
|
|
693
|
+
`<th scope="col"><abbr title="${this.renderDayName(opts, i)}">${this.renderDayName(
|
|
694
|
+
opts,
|
|
695
|
+
i,
|
|
696
|
+
true
|
|
697
|
+
)}</abbr></th>`
|
|
495
698
|
);
|
|
496
699
|
}
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
700
|
+
return '<thead><tr>' + (opts.isRTL ? arr.reverse() : arr).join('') + '</tr></thead>';
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
renderBody(rows) {
|
|
704
|
+
return '<tbody>' + rows.join('') + '</tbody>';
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
renderTitle(instance, c, year, month, refYear, randId) {
|
|
708
|
+
let i,
|
|
709
|
+
j,
|
|
710
|
+
arr,
|
|
711
|
+
opts = this.options,
|
|
712
|
+
isMinYear = year === opts.minYear,
|
|
713
|
+
isMaxYear = year === opts.maxYear,
|
|
714
|
+
html =
|
|
715
|
+
'<div id="' +
|
|
501
716
|
randId +
|
|
502
|
-
'">'
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
717
|
+
'" class="datepicker-controls" role="heading" aria-live="assertive">',
|
|
718
|
+
monthHtml,
|
|
719
|
+
yearHtml,
|
|
720
|
+
prev = true,
|
|
721
|
+
next = true;
|
|
722
|
+
|
|
723
|
+
for (arr = [], i = 0; i < 12; i++) {
|
|
724
|
+
arr.push(
|
|
725
|
+
'<option value="' +
|
|
726
|
+
(year === refYear ? i - c : 12 + i - c) +
|
|
727
|
+
'"' +
|
|
728
|
+
(i === month ? ' selected="selected"' : '') +
|
|
729
|
+
((isMinYear && i < opts.minMonth) || (isMaxYear && i > opts.maxMonth)
|
|
730
|
+
? 'disabled="disabled"'
|
|
731
|
+
: '') +
|
|
732
|
+
'>' +
|
|
733
|
+
opts.i18n.months[i] +
|
|
734
|
+
'</option>'
|
|
506
735
|
);
|
|
507
736
|
}
|
|
508
737
|
|
|
509
|
-
|
|
510
|
-
let i,
|
|
511
|
-
arr = [];
|
|
512
|
-
for (i = 0; i < 7; i++) {
|
|
513
|
-
arr.push(
|
|
514
|
-
`<th scope="col"><abbr title="${this.renderDayName(opts, i)}">${this.renderDayName(
|
|
515
|
-
opts,
|
|
516
|
-
i,
|
|
517
|
-
true
|
|
518
|
-
)}</abbr></th>`
|
|
519
|
-
);
|
|
520
|
-
}
|
|
521
|
-
return '<thead><tr>' + (opts.isRTL ? arr.reverse() : arr).join('') + '</tr></thead>';
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
renderBody(rows) {
|
|
525
|
-
return '<tbody>' + rows.join('') + '</tbody>';
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
renderTitle(instance, c, year, month, refYear, randId) {
|
|
529
|
-
let i,
|
|
530
|
-
j,
|
|
531
|
-
arr,
|
|
532
|
-
opts = this.options,
|
|
533
|
-
isMinYear = year === opts.minYear,
|
|
534
|
-
isMaxYear = year === opts.maxYear,
|
|
535
|
-
html =
|
|
536
|
-
'<div id="' +
|
|
537
|
-
randId +
|
|
538
|
-
'" class="datepicker-controls" role="heading" aria-live="assertive">',
|
|
539
|
-
monthHtml,
|
|
540
|
-
yearHtml,
|
|
541
|
-
prev = true,
|
|
542
|
-
next = true;
|
|
543
|
-
|
|
544
|
-
for (arr = [], i = 0; i < 12; i++) {
|
|
545
|
-
arr.push(
|
|
546
|
-
'<option value="' +
|
|
547
|
-
(year === refYear ? i - c : 12 + i - c) +
|
|
548
|
-
'"' +
|
|
549
|
-
(i === month ? ' selected="selected"' : '') +
|
|
550
|
-
((isMinYear && i < opts.minMonth) || (isMaxYear && i > opts.maxMonth)
|
|
551
|
-
? 'disabled="disabled"'
|
|
552
|
-
: '') +
|
|
553
|
-
'>' +
|
|
554
|
-
opts.i18n.months[i] +
|
|
555
|
-
'</option>'
|
|
556
|
-
);
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
monthHtml = '<select class="datepicker-select orig-select-month" tabindex="-1">'+arr.join('')+'</select>';
|
|
560
|
-
|
|
561
|
-
if (Array.isArray(opts.yearRange)) {
|
|
562
|
-
i = opts.yearRange[0];
|
|
563
|
-
j = opts.yearRange[1] + 1;
|
|
564
|
-
}
|
|
565
|
-
else {
|
|
566
|
-
i = year - opts.yearRange;
|
|
567
|
-
j = 1 + year + opts.yearRange;
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
for (arr = []; i < j && i <= opts.maxYear; i++) {
|
|
571
|
-
if (i >= opts.minYear) {
|
|
572
|
-
arr.push(`<option value="${i}" ${i === year ? 'selected="selected"' : ''}>${i}</option>`);
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
if (opts.yearRangeReverse) arr.reverse();
|
|
576
|
-
|
|
577
|
-
yearHtml = `<select class="datepicker-select orig-select-year" tabindex="-1">${arr.join('')}</select>`;
|
|
738
|
+
monthHtml = '<select class="datepicker-select orig-select-month" tabindex="-1">'+arr.join('')+'</select>';
|
|
578
739
|
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
html += yearHtml + monthHtml;
|
|
588
|
-
} else {
|
|
589
|
-
html += monthHtml + yearHtml;
|
|
590
|
-
}
|
|
591
|
-
html += '</div>';
|
|
592
|
-
|
|
593
|
-
if (isMinYear && (month === 0 || opts.minMonth >= month)) {
|
|
594
|
-
prev = false;
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
if (isMaxYear && (month === 11 || opts.maxMonth <= month)) {
|
|
598
|
-
next = false;
|
|
599
|
-
}
|
|
740
|
+
if (Array.isArray(opts.yearRange)) {
|
|
741
|
+
i = opts.yearRange[0];
|
|
742
|
+
j = opts.yearRange[1] + 1;
|
|
743
|
+
}
|
|
744
|
+
else {
|
|
745
|
+
i = year - opts.yearRange;
|
|
746
|
+
j = 1 + year + opts.yearRange;
|
|
747
|
+
}
|
|
600
748
|
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
next ? '' : ' is-disabled'
|
|
605
|
-
} btn-flat" type="button">${rightArrow}</button>`;
|
|
606
|
-
|
|
607
|
-
return (html += '</div>');
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
// refresh HTML
|
|
611
|
-
draw(force: boolean = false) {
|
|
612
|
-
if (!this.isOpen && !force) return;
|
|
613
|
-
let opts = this.options,
|
|
614
|
-
minYear = opts.minYear,
|
|
615
|
-
maxYear = opts.maxYear,
|
|
616
|
-
minMonth = opts.minMonth,
|
|
617
|
-
maxMonth = opts.maxMonth,
|
|
618
|
-
html = '',
|
|
619
|
-
randId;
|
|
620
|
-
|
|
621
|
-
if (this._y <= minYear) {
|
|
622
|
-
this._y = minYear;
|
|
623
|
-
if (!isNaN(minMonth) && this._m < minMonth) {
|
|
624
|
-
this._m = minMonth;
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
if (this._y >= maxYear) {
|
|
628
|
-
this._y = maxYear;
|
|
629
|
-
if (!isNaN(maxMonth) && this._m > maxMonth) {
|
|
630
|
-
this._m = maxMonth;
|
|
631
|
-
}
|
|
749
|
+
for (arr = []; i < j && i <= opts.maxYear; i++) {
|
|
750
|
+
if (i >= opts.minYear) {
|
|
751
|
+
arr.push(`<option value="${i}" ${i === year ? 'selected="selected"' : ''}>${i}</option>`);
|
|
632
752
|
}
|
|
753
|
+
}
|
|
754
|
+
if (opts.yearRangeReverse) arr.reverse();
|
|
633
755
|
|
|
634
|
-
|
|
635
|
-
'datepicker-title-' +
|
|
636
|
-
Math.random()
|
|
637
|
-
.toString(36)
|
|
638
|
-
.replace(/[^a-z]+/g, '')
|
|
639
|
-
.substr(0, 2);
|
|
640
|
-
|
|
641
|
-
for (let c = 0; c < 1; c++) {
|
|
642
|
-
this._renderDateDisplay();
|
|
643
|
-
html +=
|
|
644
|
-
this.renderTitle(
|
|
645
|
-
this,
|
|
646
|
-
c,
|
|
647
|
-
this.calendars[c].year,
|
|
648
|
-
this.calendars[c].month,
|
|
649
|
-
this.calendars[0].year,
|
|
650
|
-
randId
|
|
651
|
-
) + this.render(this.calendars[c].year, this.calendars[c].month, randId);
|
|
652
|
-
}
|
|
756
|
+
yearHtml = `<select class="datepicker-select orig-select-year" tabindex="-1">${arr.join('')}</select>`;
|
|
653
757
|
|
|
654
|
-
|
|
758
|
+
let leftArrow =
|
|
759
|
+
'<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M15.41 16.09l-4.58-4.59 4.58-4.59L14 5.5l-6 6 6 6z"/><path d="M0-.5h24v24H0z" fill="none"/></svg>';
|
|
760
|
+
html += `<button class="month-prev${
|
|
761
|
+
prev ? '' : ' is-disabled'
|
|
762
|
+
} btn-flat" type="button">${leftArrow}</button>`;
|
|
655
763
|
|
|
656
|
-
|
|
764
|
+
html += '<div class="selects-container">';
|
|
765
|
+
if (opts.showMonthAfterYear) {
|
|
766
|
+
html += yearHtml + monthHtml;
|
|
767
|
+
} else {
|
|
768
|
+
html += monthHtml + yearHtml;
|
|
769
|
+
}
|
|
770
|
+
html += '</div>';
|
|
657
771
|
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
FormSelect.init(yearSelect, {
|
|
662
|
-
classes: 'select-year',
|
|
663
|
-
dropdownOptions: { container: document.body, constrainWidth: false }
|
|
664
|
-
});
|
|
665
|
-
FormSelect.init(monthSelect, {
|
|
666
|
-
classes: 'select-month',
|
|
667
|
-
dropdownOptions: { container: document.body, constrainWidth: false }
|
|
668
|
-
});
|
|
772
|
+
if (isMinYear && (month === 0 || opts.minMonth >= month)) {
|
|
773
|
+
prev = false;
|
|
774
|
+
}
|
|
669
775
|
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
776
|
+
if (isMaxYear && (month === 11 || opts.maxMonth <= month)) {
|
|
777
|
+
next = false;
|
|
778
|
+
}
|
|
673
779
|
|
|
674
|
-
|
|
675
|
-
|
|
780
|
+
let rightArrow =
|
|
781
|
+
'<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"/><path d="M0-.25h24v24H0z" fill="none"/></svg>';
|
|
782
|
+
html += `<button class="month-next${
|
|
783
|
+
next ? '' : ' is-disabled'
|
|
784
|
+
} btn-flat" type="button">${rightArrow}</button>`;
|
|
785
|
+
|
|
786
|
+
return (html += '</div>');
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
// refresh HTML
|
|
790
|
+
draw(force: boolean = false) {
|
|
791
|
+
if (!this.isOpen && !force) return;
|
|
792
|
+
let opts = this.options,
|
|
793
|
+
minYear = opts.minYear,
|
|
794
|
+
maxYear = opts.maxYear,
|
|
795
|
+
minMonth = opts.minMonth,
|
|
796
|
+
maxMonth = opts.maxMonth,
|
|
797
|
+
html = '',
|
|
798
|
+
randId;
|
|
799
|
+
|
|
800
|
+
if (this._y <= minYear) {
|
|
801
|
+
this._y = minYear;
|
|
802
|
+
if (!isNaN(minMonth) && this._m < minMonth) {
|
|
803
|
+
this._m = minMonth;
|
|
676
804
|
}
|
|
677
805
|
}
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
this.
|
|
681
|
-
|
|
682
|
-
this._handleInputChangeBound = this._handleInputChange.bind(this);
|
|
683
|
-
this._handleCalendarClickBound = this._handleCalendarClick.bind(this);
|
|
684
|
-
this._finishSelectionBound = this._finishSelection.bind(this);
|
|
685
|
-
this._handleMonthChange = this._handleMonthChange.bind(this);
|
|
686
|
-
this._closeBound = this.close.bind(this);
|
|
687
|
-
|
|
688
|
-
this.el.addEventListener('click', this._handleInputClickBound);
|
|
689
|
-
this.el.addEventListener('keydown', this._handleInputKeydownBound);
|
|
690
|
-
this.el.addEventListener('change', this._handleInputChangeBound);
|
|
691
|
-
this.calendarEl.addEventListener('click', this._handleCalendarClickBound);
|
|
692
|
-
this.doneBtn.addEventListener('click', this._finishSelectionBound);
|
|
693
|
-
this.cancelBtn.addEventListener('click', this._closeBound);
|
|
694
|
-
|
|
695
|
-
if (this.options.showClearBtn) {
|
|
696
|
-
this._handleClearClickBound = this._handleClearClick.bind(this);
|
|
697
|
-
this.clearBtn.addEventListener('click', this._handleClearClickBound);
|
|
806
|
+
if (this._y >= maxYear) {
|
|
807
|
+
this._y = maxYear;
|
|
808
|
+
if (!isNaN(maxMonth) && this._m > maxMonth) {
|
|
809
|
+
this._m = maxMonth;
|
|
698
810
|
}
|
|
699
811
|
}
|
|
700
812
|
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
813
|
+
randId =
|
|
814
|
+
'datepicker-title-' +
|
|
815
|
+
Math.random()
|
|
816
|
+
.toString(36)
|
|
817
|
+
.replace(/[^a-z]+/g, '')
|
|
818
|
+
.substr(0, 2);
|
|
705
819
|
|
|
706
|
-
|
|
707
|
-
this.
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
return this.date.getDate();
|
|
718
|
-
},
|
|
719
|
-
dd: () => {
|
|
720
|
-
let d = this.date.getDate();
|
|
721
|
-
return (d < 10 ? '0' : '') + d;
|
|
722
|
-
},
|
|
723
|
-
ddd: () => {
|
|
724
|
-
return this.options.i18n.weekdaysShort[this.date.getDay()];
|
|
725
|
-
},
|
|
726
|
-
dddd: () => {
|
|
727
|
-
return this.options.i18n.weekdays[this.date.getDay()];
|
|
728
|
-
},
|
|
729
|
-
m: () => {
|
|
730
|
-
return this.date.getMonth() + 1;
|
|
731
|
-
},
|
|
732
|
-
mm: () => {
|
|
733
|
-
let m = this.date.getMonth() + 1;
|
|
734
|
-
return (m < 10 ? '0' : '') + m;
|
|
735
|
-
},
|
|
736
|
-
mmm: () => {
|
|
737
|
-
return this.options.i18n.monthsShort[this.date.getMonth()];
|
|
738
|
-
},
|
|
739
|
-
mmmm: () => {
|
|
740
|
-
return this.options.i18n.months[this.date.getMonth()];
|
|
741
|
-
},
|
|
742
|
-
yy: () => {
|
|
743
|
-
return ('' + this.date.getFullYear()).slice(2);
|
|
744
|
-
},
|
|
745
|
-
yyyy: () => {
|
|
746
|
-
return this.date.getFullYear();
|
|
747
|
-
}
|
|
748
|
-
};
|
|
820
|
+
for (let c = 0; c < 1; c++) {
|
|
821
|
+
this._renderDateDisplay();
|
|
822
|
+
html +=
|
|
823
|
+
this.renderTitle(
|
|
824
|
+
this,
|
|
825
|
+
c,
|
|
826
|
+
this.calendars[c].year,
|
|
827
|
+
this.calendars[c].month,
|
|
828
|
+
this.calendars[0].year,
|
|
829
|
+
randId
|
|
830
|
+
) + this.render(this.calendars[c].year, this.calendars[c].month, randId);
|
|
749
831
|
}
|
|
750
832
|
|
|
751
|
-
|
|
752
|
-
this.el.removeEventListener('click', this._handleInputClickBound);
|
|
753
|
-
this.el.removeEventListener('keydown', this._handleInputKeydownBound);
|
|
754
|
-
this.el.removeEventListener('change', this._handleInputChangeBound);
|
|
755
|
-
this.calendarEl.removeEventListener('click', this._handleCalendarClickBound);
|
|
756
|
-
}
|
|
833
|
+
this.destroySelects();
|
|
757
834
|
|
|
758
|
-
|
|
759
|
-
this.open();
|
|
760
|
-
}
|
|
835
|
+
this.calendarEl.innerHTML = html;
|
|
761
836
|
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
837
|
+
// Init Materialize Select
|
|
838
|
+
let yearSelect = this.calendarEl.querySelector('.orig-select-year') as HTMLSelectElement;
|
|
839
|
+
let monthSelect = this.calendarEl.querySelector('.orig-select-month') as HTMLSelectElement;
|
|
840
|
+
FormSelect.init(yearSelect, {
|
|
841
|
+
classes: 'select-year',
|
|
842
|
+
dropdownOptions: { container: document.body, constrainWidth: false }
|
|
843
|
+
});
|
|
844
|
+
FormSelect.init(monthSelect, {
|
|
845
|
+
classes: 'select-month',
|
|
846
|
+
dropdownOptions: { container: document.body, constrainWidth: false }
|
|
847
|
+
});
|
|
768
848
|
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
if (!target.classList.contains('is-disabled')) {
|
|
773
|
-
if (
|
|
774
|
-
target.classList.contains('datepicker-day-button') &&
|
|
775
|
-
!target.classList.contains('is-empty') &&
|
|
776
|
-
!target.parentElement.classList.contains('is-disabled')
|
|
777
|
-
) {
|
|
778
|
-
this.setDate(
|
|
779
|
-
new Date(
|
|
780
|
-
e.target.getAttribute('data-year'),
|
|
781
|
-
e.target.getAttribute('data-month'),
|
|
782
|
-
e.target.getAttribute('data-day')
|
|
783
|
-
)
|
|
784
|
-
);
|
|
785
|
-
if (this.options.autoClose) {
|
|
786
|
-
this._finishSelection();
|
|
787
|
-
}
|
|
788
|
-
}
|
|
789
|
-
else if (target.closest('.month-prev')) {
|
|
790
|
-
this.prevMonth();
|
|
791
|
-
}
|
|
792
|
-
else if (target.closest('.month-next')) {
|
|
793
|
-
this.nextMonth();
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
}
|
|
849
|
+
// Add change handlers for select
|
|
850
|
+
yearSelect.addEventListener('change', () => this._handleYearChange);
|
|
851
|
+
monthSelect.addEventListener('change', () => this._handleMonthChange);
|
|
797
852
|
|
|
798
|
-
|
|
799
|
-
this.
|
|
800
|
-
this.setInputValue();
|
|
801
|
-
this.close();
|
|
853
|
+
if (typeof this.options.onDraw === 'function') {
|
|
854
|
+
this.options.onDraw.call(this);
|
|
802
855
|
}
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
_setupEventHandlers() {
|
|
859
|
+
this.el.addEventListener('click', this._handleInputClick);
|
|
860
|
+
this.el.addEventListener('keydown', this._handleInputKeydown);
|
|
861
|
+
this.el.addEventListener('change', this._handleInputChange);
|
|
862
|
+
this.calendarEl.addEventListener('click', this._handleCalendarClick);
|
|
863
|
+
this.doneBtn.addEventListener('click', this._finishSelection);
|
|
864
|
+
this.cancelBtn.addEventListener('click', this.close);
|
|
865
|
+
|
|
866
|
+
if (this.options.showClearBtn) {
|
|
867
|
+
this.clearBtn.addEventListener('click', this._handleClearClick);
|
|
806
868
|
}
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
_setupVariables() {
|
|
872
|
+
const template = document.createElement('template');
|
|
873
|
+
template.innerHTML = Datepicker._template.trim();
|
|
874
|
+
this.modalEl = <HTMLElement>template.content.firstChild;
|
|
875
|
+
|
|
876
|
+
this.calendarEl = this.modalEl.querySelector('.datepicker-calendar');
|
|
877
|
+
this.yearTextEl = this.modalEl.querySelector('.year-text');
|
|
878
|
+
this.dateTextEl = this.modalEl.querySelector('.date-text');
|
|
879
|
+
if (this.options.showClearBtn) {
|
|
880
|
+
this.clearBtn = this.modalEl.querySelector('.datepicker-clear');
|
|
810
881
|
}
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
this.
|
|
882
|
+
this.doneBtn = this.modalEl.querySelector('.datepicker-done');
|
|
883
|
+
this.cancelBtn = this.modalEl.querySelector('.datepicker-cancel');
|
|
884
|
+
|
|
885
|
+
this.formats = {
|
|
886
|
+
d: () => {
|
|
887
|
+
return this.date.getDate();
|
|
888
|
+
},
|
|
889
|
+
dd: () => {
|
|
890
|
+
let d = this.date.getDate();
|
|
891
|
+
return (d < 10 ? '0' : '') + d;
|
|
892
|
+
},
|
|
893
|
+
ddd: () => {
|
|
894
|
+
return this.options.i18n.weekdaysShort[this.date.getDay()];
|
|
895
|
+
},
|
|
896
|
+
dddd: () => {
|
|
897
|
+
return this.options.i18n.weekdays[this.date.getDay()];
|
|
898
|
+
},
|
|
899
|
+
m: () => {
|
|
900
|
+
return this.date.getMonth() + 1;
|
|
901
|
+
},
|
|
902
|
+
mm: () => {
|
|
903
|
+
let m = this.date.getMonth() + 1;
|
|
904
|
+
return (m < 10 ? '0' : '') + m;
|
|
905
|
+
},
|
|
906
|
+
mmm: () => {
|
|
907
|
+
return this.options.i18n.monthsShort[this.date.getMonth()];
|
|
908
|
+
},
|
|
909
|
+
mmmm: () => {
|
|
910
|
+
return this.options.i18n.months[this.date.getMonth()];
|
|
911
|
+
},
|
|
912
|
+
yy: () => {
|
|
913
|
+
return ('' + this.date.getFullYear()).slice(2);
|
|
914
|
+
},
|
|
915
|
+
yyyy: () => {
|
|
916
|
+
return this.date.getFullYear();
|
|
817
917
|
}
|
|
918
|
+
};
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
_removeEventHandlers() {
|
|
922
|
+
this.el.removeEventListener('click', this._handleInputClick);
|
|
923
|
+
this.el.removeEventListener('keydown', this._handleInputKeydown);
|
|
924
|
+
this.el.removeEventListener('change', this._handleInputChange);
|
|
925
|
+
this.calendarEl.removeEventListener('click', this._handleCalendarClick);
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
_handleInputClick = () => {
|
|
929
|
+
this.open();
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
_handleInputKeydown = (e: KeyboardEvent) => {
|
|
933
|
+
if (Utils.keys.ENTER.includes(e.key)) {
|
|
934
|
+
e.preventDefault();
|
|
935
|
+
this.open();
|
|
818
936
|
}
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
_handleCalendarClick = (e) => {
|
|
940
|
+
if (!this.isOpen) return;
|
|
941
|
+
const target = <HTMLElement>(e.target);
|
|
942
|
+
if (!target.classList.contains('is-disabled')) {
|
|
943
|
+
if (
|
|
944
|
+
target.classList.contains('datepicker-day-button') &&
|
|
945
|
+
!target.classList.contains('is-empty') &&
|
|
946
|
+
!target.parentElement.classList.contains('is-disabled')
|
|
947
|
+
) {
|
|
948
|
+
this.setDate(
|
|
949
|
+
new Date(
|
|
950
|
+
e.target.getAttribute('data-year'),
|
|
951
|
+
e.target.getAttribute('data-month'),
|
|
952
|
+
e.target.getAttribute('data-day')
|
|
953
|
+
)
|
|
954
|
+
);
|
|
955
|
+
if (this.options.autoClose) {
|
|
956
|
+
this._finishSelection();
|
|
957
|
+
}
|
|
825
958
|
}
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
_handleInputChange(e: Event) {
|
|
829
|
-
let date;
|
|
830
|
-
// Prevent change event from being fired when triggered by the plugin
|
|
831
|
-
if (e['detail']?.firedBy === this) return;
|
|
832
|
-
if (this.options.parse) {
|
|
833
|
-
date = this.options.parse(this.el.value, this.options.format);
|
|
959
|
+
else if (target.closest('.month-prev')) {
|
|
960
|
+
this.prevMonth();
|
|
834
961
|
}
|
|
835
|
-
else {
|
|
836
|
-
|
|
962
|
+
else if (target.closest('.month-next')) {
|
|
963
|
+
this.nextMonth();
|
|
837
964
|
}
|
|
838
|
-
if (Datepicker._isDate(date)) this.setDate(date);
|
|
839
965
|
}
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
_handleClearClick = () => {
|
|
969
|
+
this.date = null;
|
|
970
|
+
this.setInputValue();
|
|
971
|
+
this.close();
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
_handleMonthChange = (e) => {
|
|
975
|
+
this.gotoMonth(e.target.value);
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
_handleYearChange = (e) => {
|
|
979
|
+
this.gotoYear(e.target.value);
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
// change view to a specific month (zero-index, e.g. 0: January)
|
|
983
|
+
gotoMonth(month) {
|
|
984
|
+
if (!isNaN(month)) {
|
|
985
|
+
this.calendars[0].month = parseInt(month, 10);
|
|
986
|
+
this.adjustCalendars();
|
|
847
987
|
}
|
|
988
|
+
}
|
|
848
989
|
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
this.
|
|
990
|
+
// change view to a specific full year (e.g. "2012")
|
|
991
|
+
gotoYear(year) {
|
|
992
|
+
if (!isNaN(year)) {
|
|
993
|
+
this.calendars[0].year = parseInt(year, 10);
|
|
994
|
+
this.adjustCalendars();
|
|
853
995
|
}
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
this.
|
|
862
|
-
|
|
863
|
-
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
_handleInputChange = (e: Event) => {
|
|
999
|
+
let date;
|
|
1000
|
+
// Prevent change event from being fired when triggered by the plugin
|
|
1001
|
+
if (e['detail']?.firedBy === this) return;
|
|
1002
|
+
if (this.options.parse) {
|
|
1003
|
+
date = this.options.parse(this.el.value,
|
|
1004
|
+
typeof this.options.format === "function"
|
|
1005
|
+
? this.options.format(new Date(this.el.value))
|
|
1006
|
+
: this.options.format);
|
|
864
1007
|
}
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
if (!this.isOpen) return;
|
|
868
|
-
this.isOpen = false;
|
|
869
|
-
if (typeof this.options.onClose === 'function') {
|
|
870
|
-
this.options.onClose.call(this);
|
|
871
|
-
}
|
|
872
|
-
this.modal.close();
|
|
873
|
-
return this;
|
|
1008
|
+
else {
|
|
1009
|
+
date = new Date(Date.parse(this.el.value));
|
|
874
1010
|
}
|
|
1011
|
+
if (Datepicker._isDate(date)) this.setDate(date);
|
|
1012
|
+
}
|
|
875
1013
|
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
1014
|
+
renderDayName(opts, day, abbr: boolean = false) {
|
|
1015
|
+
day += opts.firstDay;
|
|
1016
|
+
while (day >= 7) {
|
|
1017
|
+
day -= 7;
|
|
1018
|
+
}
|
|
1019
|
+
return abbr ? opts.i18n.weekdaysAbbrev[day] : opts.i18n.weekdays[day];
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
// Set input value to the selected date and close Datepicker
|
|
1023
|
+
_finishSelection = () => {
|
|
1024
|
+
this.setInputValue();
|
|
1025
|
+
this.close();
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
/**
|
|
1029
|
+
* Open datepicker.
|
|
1030
|
+
*/
|
|
1031
|
+
open = () => {
|
|
1032
|
+
if (this.isOpen) return;
|
|
1033
|
+
this.isOpen = true;
|
|
1034
|
+
if (typeof this.options.onOpen === 'function') {
|
|
1035
|
+
this.options.onOpen.call(this);
|
|
1036
|
+
}
|
|
1037
|
+
this.draw();
|
|
1038
|
+
this.modal.open(undefined);
|
|
1039
|
+
return this;
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
/**
|
|
1043
|
+
* Close datepicker.
|
|
1044
|
+
*/
|
|
1045
|
+
close = () => {
|
|
1046
|
+
if (!this.isOpen) return;
|
|
1047
|
+
this.isOpen = false;
|
|
1048
|
+
if (typeof this.options.onClose === 'function') {
|
|
1049
|
+
this.options.onClose.call(this);
|
|
1050
|
+
}
|
|
1051
|
+
this.modal.close();
|
|
1052
|
+
return this;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
static {
|
|
1056
|
+
Datepicker._template = `
|
|
1057
|
+
<div class="modal datepicker-modal">
|
|
1058
|
+
<div class="modal-content datepicker-container">
|
|
1059
|
+
<div class="datepicker-date-display">
|
|
1060
|
+
<span class="year-text"></span>
|
|
1061
|
+
<span class="date-text"></span>
|
|
1062
|
+
</div>
|
|
1063
|
+
<div class="datepicker-calendar-container">
|
|
1064
|
+
<div class="datepicker-calendar"></div>
|
|
1065
|
+
<div class="datepicker-footer">
|
|
1066
|
+
<button class="btn-flat datepicker-clear waves-effect" style="visibility: hidden;" type="button"></button>
|
|
1067
|
+
<div class="confirmation-btns">
|
|
1068
|
+
<button class="btn-flat datepicker-cancel waves-effect" type="button"></button>
|
|
1069
|
+
<button class="btn-flat datepicker-done waves-effect" type="button"></button>
|
|
892
1070
|
</div>
|
|
893
1071
|
</div>
|
|
894
1072
|
</div>
|
|
895
|
-
</div
|
|
896
|
-
|
|
897
|
-
}
|
|
1073
|
+
</div>
|
|
1074
|
+
</div>`;
|
|
1075
|
+
}
|
|
1076
|
+
}
|