@ohos-ports/flowbite-datepicker 2.0.0-beta.0
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/.eslintignore +2 -0
- package/.eslintrc.js +73 -0
- package/.stylelintrc +12 -0
- package/CHANGELOG.md +72 -0
- package/LICENSE +21 -0
- package/README.md +71 -0
- package/demo/index.html +582 -0
- package/demo/live-demo.js +471 -0
- package/dist/DateRangePicker.cjs.js +2996 -0
- package/dist/DateRangePicker.esm.js +2994 -0
- package/dist/DateRangePicker.umd.js +3002 -0
- package/dist/Datepicker.cjs.js +2778 -0
- package/dist/Datepicker.esm.js +2776 -0
- package/dist/Datepicker.umd.js +2784 -0
- package/dist/css/datepicker-bs4.css +276 -0
- package/dist/css/datepicker-bs4.min.css +1 -0
- package/dist/css/datepicker-bs5.css +276 -0
- package/dist/css/datepicker-bs5.min.css +1 -0
- package/dist/css/datepicker-bulma.css +258 -0
- package/dist/css/datepicker-bulma.min.css +1 -0
- package/dist/css/datepicker-foundation.css +262 -0
- package/dist/css/datepicker-foundation.min.css +1 -0
- package/dist/css/datepicker.css +306 -0
- package/dist/css/datepicker.min.css +1403 -0
- package/dist/js/datepicker-full.js +2777 -0
- package/dist/js/datepicker-full.min.js +1 -0
- package/dist/js/datepicker.js +2569 -0
- package/dist/js/datepicker.min.js +1 -0
- package/dist/js/locales/ar-tn.js +15 -0
- package/dist/js/locales/ar.js +15 -0
- package/dist/js/locales/az.js +14 -0
- package/dist/js/locales/bg.js +14 -0
- package/dist/js/locales/bm.js +18 -0
- package/dist/js/locales/bn.js +19 -0
- package/dist/js/locales/br.js +18 -0
- package/dist/js/locales/bs.js +15 -0
- package/dist/js/locales/ca.js +18 -0
- package/dist/js/locales/cs.js +19 -0
- package/dist/js/locales/cy.js +14 -0
- package/dist/js/locales/da.js +19 -0
- package/dist/js/locales/de.js +18 -0
- package/dist/js/locales/el.js +16 -0
- package/dist/js/locales/en-AU.js +18 -0
- package/dist/js/locales/en-CA.js +18 -0
- package/dist/js/locales/en-GB.js +18 -0
- package/dist/js/locales/en-IE.js +17 -0
- package/dist/js/locales/en-NZ.js +17 -0
- package/dist/js/locales/en-ZA.js +17 -0
- package/dist/js/locales/eo.js +17 -0
- package/dist/js/locales/es.js +18 -0
- package/dist/js/locales/et.js +18 -0
- package/dist/js/locales/eu.js +18 -0
- package/dist/js/locales/fa.js +17 -0
- package/dist/js/locales/fi.js +17 -0
- package/dist/js/locales/fo.js +15 -0
- package/dist/js/locales/fr-CH.js +21 -0
- package/dist/js/locales/fr.js +18 -0
- package/dist/js/locales/gl.js +16 -0
- package/dist/js/locales/he.js +15 -0
- package/dist/js/locales/hi.js +18 -0
- package/dist/js/locales/hr.js +13 -0
- package/dist/js/locales/hu.js +18 -0
- package/dist/js/locales/hy.js +18 -0
- package/dist/js/locales/id.js +15 -0
- package/dist/js/locales/is.js +14 -0
- package/dist/js/locales/it-CH.js +20 -0
- package/dist/js/locales/it.js +18 -0
- package/dist/js/locales/ja.js +17 -0
- package/dist/js/locales/ka.js +17 -0
- package/dist/js/locales/kk.js +15 -0
- package/dist/js/locales/km.js +15 -0
- package/dist/js/locales/ko.js +18 -0
- package/dist/js/locales/lt.js +19 -0
- package/dist/js/locales/lv.js +18 -0
- package/dist/js/locales/me.js +17 -0
- package/dist/js/locales/mk.js +15 -0
- package/dist/js/locales/mn.js +17 -0
- package/dist/js/locales/mr.js +18 -0
- package/dist/js/locales/ms.js +15 -0
- package/dist/js/locales/nl-BE.js +18 -0
- package/dist/js/locales/nl.js +18 -0
- package/dist/js/locales/no.js +18 -0
- package/dist/js/locales/oc.js +17 -0
- package/dist/js/locales/pl.js +17 -0
- package/dist/js/locales/pt-BR.js +17 -0
- package/dist/js/locales/pt.js +18 -0
- package/dist/js/locales/ro.js +17 -0
- package/dist/js/locales/ru.js +18 -0
- package/dist/js/locales/si.js +18 -0
- package/dist/js/locales/sk.js +18 -0
- package/dist/js/locales/sl.js +15 -0
- package/dist/js/locales/sq.js +18 -0
- package/dist/js/locales/sr-latn.js +16 -0
- package/dist/js/locales/sr.js +16 -0
- package/dist/js/locales/sv.js +17 -0
- package/dist/js/locales/sw.js +15 -0
- package/dist/js/locales/ta.js +18 -0
- package/dist/js/locales/tg.js +19 -0
- package/dist/js/locales/th.js +14 -0
- package/dist/js/locales/tk.js +18 -0
- package/dist/js/locales/tr.js +17 -0
- package/dist/js/locales/uk.js +17 -0
- package/dist/js/locales/uz-cyrl.js +18 -0
- package/dist/js/locales/uz-latn.js +18 -0
- package/dist/js/locales/vi.js +16 -0
- package/dist/js/locales/zh-CN.js +19 -0
- package/dist/js/locales/zh-TW.js +18 -0
- package/dist/locales/index.cjs.js +1028 -0
- package/dist/locales/index.esm.js +1028 -0
- package/dist/main.cjs.js +2999 -0
- package/dist/main.esm.js +2994 -0
- package/dist/main.umd.js +3005 -0
- package/docs/.nojekyll +0 -0
- package/docs/README.md +266 -0
- package/docs/_sidebar.md +6 -0
- package/docs/api.md +284 -0
- package/docs/date-string+format.md +90 -0
- package/docs/i18n.md +99 -0
- package/docs/images/datepicker-inline.jpg +0 -0
- package/docs/images/datepicker.jpg +0 -0
- package/docs/images/multidate.jpg +0 -0
- package/docs/images/picker-structure.jpg +0 -0
- package/docs/images/rangepicker.jpg +0 -0
- package/docs/images/view-days.jpg +0 -0
- package/docs/images/view-decades.jpg +0 -0
- package/docs/images/view-months.jpg +0 -0
- package/docs/images/view-years.jpg +0 -0
- package/docs/index.html +26 -0
- package/docs/options.md +354 -0
- package/docs/overview.md +174 -0
- package/extras/twoDigitToFullYear/test/twoDigitToFullYear.js +58 -0
- package/extras/twoDigitToFullYear/twoDigitToFullYear.js +26 -0
- package/js/DateRangePicker.js +210 -0
- package/js/Datepicker.js +487 -0
- package/js/datepicker-full.js +5 -0
- package/js/events/functions.js +48 -0
- package/js/events/inputFieldListeners.js +206 -0
- package/js/events/otherListeners.js +15 -0
- package/js/events/pickerListeners.js +70 -0
- package/js/i18n/base-locales.js +13 -0
- package/js/i18n/locales/ar-tn.js +15 -0
- package/js/i18n/locales/ar.js +15 -0
- package/js/i18n/locales/az.js +14 -0
- package/js/i18n/locales/bg.js +14 -0
- package/js/i18n/locales/bm.js +18 -0
- package/js/i18n/locales/bn.js +19 -0
- package/js/i18n/locales/br.js +18 -0
- package/js/i18n/locales/bs.js +15 -0
- package/js/i18n/locales/ca.js +18 -0
- package/js/i18n/locales/cs.js +19 -0
- package/js/i18n/locales/cy.js +14 -0
- package/js/i18n/locales/da.js +19 -0
- package/js/i18n/locales/de.js +18 -0
- package/js/i18n/locales/el.js +16 -0
- package/js/i18n/locales/en-AU.js +18 -0
- package/js/i18n/locales/en-CA.js +18 -0
- package/js/i18n/locales/en-GB.js +18 -0
- package/js/i18n/locales/en-IE.js +17 -0
- package/js/i18n/locales/en-NZ.js +17 -0
- package/js/i18n/locales/en-ZA.js +17 -0
- package/js/i18n/locales/eo.js +17 -0
- package/js/i18n/locales/es.js +18 -0
- package/js/i18n/locales/et.js +18 -0
- package/js/i18n/locales/eu.js +18 -0
- package/js/i18n/locales/fa.js +17 -0
- package/js/i18n/locales/fi.js +17 -0
- package/js/i18n/locales/fo.js +15 -0
- package/js/i18n/locales/fr-CH.js +21 -0
- package/js/i18n/locales/fr.js +18 -0
- package/js/i18n/locales/gl.js +16 -0
- package/js/i18n/locales/he.js +15 -0
- package/js/i18n/locales/hi.js +18 -0
- package/js/i18n/locales/hr.js +13 -0
- package/js/i18n/locales/hu.js +18 -0
- package/js/i18n/locales/hy.js +18 -0
- package/js/i18n/locales/id.js +15 -0
- package/js/i18n/locales/is.js +14 -0
- package/js/i18n/locales/it-CH.js +20 -0
- package/js/i18n/locales/it.js +18 -0
- package/js/i18n/locales/ja.js +17 -0
- package/js/i18n/locales/ka.js +17 -0
- package/js/i18n/locales/kk.js +15 -0
- package/js/i18n/locales/km.js +15 -0
- package/js/i18n/locales/ko.js +18 -0
- package/js/i18n/locales/lt.js +19 -0
- package/js/i18n/locales/lv.js +18 -0
- package/js/i18n/locales/me.js +17 -0
- package/js/i18n/locales/mk.js +15 -0
- package/js/i18n/locales/mn.js +17 -0
- package/js/i18n/locales/mr.js +18 -0
- package/js/i18n/locales/ms.js +15 -0
- package/js/i18n/locales/nl-BE.js +18 -0
- package/js/i18n/locales/nl.js +18 -0
- package/js/i18n/locales/no.js +18 -0
- package/js/i18n/locales/oc.js +17 -0
- package/js/i18n/locales/pl.js +17 -0
- package/js/i18n/locales/pt-BR.js +17 -0
- package/js/i18n/locales/pt.js +18 -0
- package/js/i18n/locales/ro.js +17 -0
- package/js/i18n/locales/ru.js +18 -0
- package/js/i18n/locales/si.js +18 -0
- package/js/i18n/locales/sk.js +18 -0
- package/js/i18n/locales/sl.js +15 -0
- package/js/i18n/locales/sq.js +18 -0
- package/js/i18n/locales/sr-latn.js +16 -0
- package/js/i18n/locales/sr.js +16 -0
- package/js/i18n/locales/sv.js +17 -0
- package/js/i18n/locales/sw.js +15 -0
- package/js/i18n/locales/ta.js +18 -0
- package/js/i18n/locales/tg.js +19 -0
- package/js/i18n/locales/th.js +14 -0
- package/js/i18n/locales/tk.js +18 -0
- package/js/i18n/locales/tr.js +17 -0
- package/js/i18n/locales/uk.js +17 -0
- package/js/i18n/locales/uz-cyrl.js +18 -0
- package/js/i18n/locales/uz-latn.js +18 -0
- package/js/i18n/locales/vi.js +16 -0
- package/js/i18n/locales/zh-CN.js +19 -0
- package/js/i18n/locales/zh-TW.js +18 -0
- package/js/lib/date-format.js +185 -0
- package/js/lib/date.js +82 -0
- package/js/lib/dom.js +55 -0
- package/js/lib/event.js +68 -0
- package/js/lib/utils.js +61 -0
- package/js/main.js +4 -0
- package/js/options/defaultOptions.js +38 -0
- package/js/options/processOptions.js +263 -0
- package/js/picker/Picker.js +334 -0
- package/js/picker/templates/calendarWeeksTemplate.js +8 -0
- package/js/picker/templates/daysTemplate.js +8 -0
- package/js/picker/templates/pickerTemplate.js +23 -0
- package/js/picker/views/DaysView.js +250 -0
- package/js/picker/views/MonthsView.js +198 -0
- package/js/picker/views/View.js +55 -0
- package/js/picker/views/YearsView.js +170 -0
- package/package.json +81 -0
- package/postcss.config.js +5 -0
- package/rollup.config.js +75 -0
- package/sass/_mixins.scss +12 -0
- package/sass/datepicker-bs4.scss +91 -0
- package/sass/datepicker-bs5.scss +91 -0
- package/sass/datepicker-bulma.scss +69 -0
- package/sass/datepicker-foundation.scss +66 -0
- package/sass/datepicker.scss +436 -0
- package/sass/index-bs4.scss +5 -0
- package/sass/index-bs5.scss +5 -0
- package/sass/index-bulma.scss +6 -0
- package/sass/index-foundation.scss +3 -0
- package/scripts/build-css.js +39 -0
- package/scripts/build-locales.js +57 -0
- package/scripts/convert-bsdp-locales.js +65 -0
- package/scripts/minify-css.js +31 -0
- package/scripts/minify-js.js +17 -0
- package/style.css +10 -0
- package/tailwind.config.js +16 -0
- package/tailwind.css +1389 -0
- package/test/DateRangePicker/DateRangePicker.js +547 -0
- package/test/DateRangePicker/api-methods.js +415 -0
- package/test/DateRangePicker/date-selection.js +472 -0
- package/test/DateRangePicker/options.js +308 -0
- package/test/Datepicker/Datepicker-object.js +236 -0
- package/test/Datepicker/api-methods.js +328 -0
- package/test/_utils/date.js +102 -0
- package/test/_utils/dom.js +70 -0
- package/test/events.js +785 -0
- package/test/inline-mode.js +45 -0
- package/test/keyboard-operation/arrow-down.js +293 -0
- package/test/keyboard-operation/arrow-left.js +255 -0
- package/test/keyboard-operation/arrow-right.js +215 -0
- package/test/keyboard-operation/arrow-up.js +461 -0
- package/test/keyboard-operation/edit-mode.js +458 -0
- package/test/keyboard-operation/keyboard-operation.js +146 -0
- package/test/mouse-operation.js +580 -0
- package/test/options/before-show.js +635 -0
- package/test/options/bulma-datepicker.sublime-workspace +1280 -0
- package/test/options/buttons.js +383 -0
- package/test/options/date-restrictions.js +802 -0
- package/test/options/format.js +281 -0
- package/test/options/multidate.js +380 -0
- package/test/options/options.js +727 -0
- package/test/options/orientation.js +410 -0
- package/test/options/pick-levle+view.js +357 -0
- package/test/test.html +94 -0
- package/test/unit/DateRangePicker.js +192 -0
- package/test/unit/Datepicker.js +307 -0
- package/test/unit/_setup.js +28 -0
- package/test/unit/lib/date-format.js +310 -0
- package/test/unit/lib/date.js +211 -0
- package/test/unit/lib/dom.js +142 -0
- package/test/unit/lib/event.js +207 -0
- package/test/unit/lib/utils.js +135 -0
package/js/Datepicker.js
ADDED
|
@@ -0,0 +1,487 @@
|
|
|
1
|
+
import {lastItemOf, stringToArray, isInRange} from './lib/utils.js';
|
|
2
|
+
import {today} from './lib/date.js';
|
|
3
|
+
import {parseDate, formatDate} from './lib/date-format.js';
|
|
4
|
+
import {registerListeners, unregisterListeners} from './lib/event.js';
|
|
5
|
+
import {locales} from './i18n/base-locales.js';
|
|
6
|
+
import defaultOptions from './options/defaultOptions.js';
|
|
7
|
+
import processOptions from './options/processOptions.js';
|
|
8
|
+
import Picker from './picker/Picker.js';
|
|
9
|
+
import {triggerDatepickerEvent} from './events/functions.js';
|
|
10
|
+
import {onKeydown, onFocus, onMousedown, onClickInput, onPaste} from './events/inputFieldListeners.js';
|
|
11
|
+
import {onClickOutside} from './events/otherListeners.js';
|
|
12
|
+
|
|
13
|
+
function stringifyDates(dates, config) {
|
|
14
|
+
return dates
|
|
15
|
+
.map(dt => formatDate(dt, config.format, config.locale))
|
|
16
|
+
.join(config.dateDelimiter);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// parse input dates and create an array of time values for selection
|
|
20
|
+
// returns undefined if there are no valid dates in inputDates
|
|
21
|
+
// when origDates (current selection) is passed, the function works to mix
|
|
22
|
+
// the input dates into the current selection
|
|
23
|
+
function processInputDates(datepicker, inputDates, clear = false) {
|
|
24
|
+
const {config, dates: origDates, rangepicker} = datepicker;
|
|
25
|
+
if (inputDates.length === 0) {
|
|
26
|
+
// empty input is considered valid unless origiDates is passed
|
|
27
|
+
return clear ? [] : undefined;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const rangeEnd = rangepicker && datepicker === rangepicker.datepickers[1];
|
|
31
|
+
let newDates = inputDates.reduce((dates, dt) => {
|
|
32
|
+
let date = parseDate(dt, config.format, config.locale);
|
|
33
|
+
if (date === undefined) {
|
|
34
|
+
return dates;
|
|
35
|
+
}
|
|
36
|
+
if (config.pickLevel > 0) {
|
|
37
|
+
// adjust to 1st of the month/Jan 1st of the year
|
|
38
|
+
// or to the last day of the monh/Dec 31st of the year if the datepicker
|
|
39
|
+
// is the range-end picker of a rangepicker
|
|
40
|
+
const dt = new Date(date);
|
|
41
|
+
if (config.pickLevel === 1) {
|
|
42
|
+
date = rangeEnd
|
|
43
|
+
? dt.setMonth(dt.getMonth() + 1, 0)
|
|
44
|
+
: dt.setDate(1);
|
|
45
|
+
} else {
|
|
46
|
+
date = rangeEnd
|
|
47
|
+
? dt.setFullYear(dt.getFullYear() + 1, 0, 0)
|
|
48
|
+
: dt.setMonth(0, 1);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (
|
|
52
|
+
isInRange(date, config.minDate, config.maxDate)
|
|
53
|
+
&& !dates.includes(date)
|
|
54
|
+
&& !config.datesDisabled.includes(date)
|
|
55
|
+
&& !config.daysOfWeekDisabled.includes(new Date(date).getDay())
|
|
56
|
+
) {
|
|
57
|
+
dates.push(date);
|
|
58
|
+
}
|
|
59
|
+
return dates;
|
|
60
|
+
}, []);
|
|
61
|
+
if (newDates.length === 0) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (config.multidate && !clear) {
|
|
65
|
+
// get the synmetric difference between origDates and newDates
|
|
66
|
+
newDates = newDates.reduce((dates, date) => {
|
|
67
|
+
if (!origDates.includes(date)) {
|
|
68
|
+
dates.push(date);
|
|
69
|
+
}
|
|
70
|
+
return dates;
|
|
71
|
+
}, origDates.filter(date => !newDates.includes(date)));
|
|
72
|
+
}
|
|
73
|
+
// do length check always because user can input multiple dates regardless of the mode
|
|
74
|
+
return config.maxNumberOfDates && newDates.length > config.maxNumberOfDates
|
|
75
|
+
? newDates.slice(config.maxNumberOfDates * -1)
|
|
76
|
+
: newDates;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// refresh the UI elements
|
|
80
|
+
// modes: 1: input only, 2, picker only, 3 both
|
|
81
|
+
function refreshUI(datepicker, mode = 3, quickRender = true) {
|
|
82
|
+
const {config, picker, inputField} = datepicker;
|
|
83
|
+
if (mode & 2) {
|
|
84
|
+
const newView = picker.active ? config.pickLevel : config.startView;
|
|
85
|
+
picker.update().changeView(newView).render(quickRender);
|
|
86
|
+
}
|
|
87
|
+
if (mode & 1 && inputField) {
|
|
88
|
+
inputField.value = stringifyDates(datepicker.dates, config);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function setDate(datepicker, inputDates, options) {
|
|
93
|
+
let {clear, render, autohide} = options;
|
|
94
|
+
if (render === undefined) {
|
|
95
|
+
render = true;
|
|
96
|
+
}
|
|
97
|
+
if (!render) {
|
|
98
|
+
autohide = false;
|
|
99
|
+
} else if (autohide === undefined) {
|
|
100
|
+
autohide = datepicker.config.autohide;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const newDates = processInputDates(datepicker, inputDates, clear);
|
|
104
|
+
if (!newDates) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (newDates.toString() !== datepicker.dates.toString()) {
|
|
108
|
+
datepicker.dates = newDates;
|
|
109
|
+
refreshUI(datepicker, render ? 3 : 1);
|
|
110
|
+
triggerDatepickerEvent(datepicker, 'changeDate');
|
|
111
|
+
} else {
|
|
112
|
+
refreshUI(datepicker, 1);
|
|
113
|
+
}
|
|
114
|
+
if (autohide) {
|
|
115
|
+
datepicker.hide();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Class representing a date picker
|
|
121
|
+
*/
|
|
122
|
+
export default class Datepicker {
|
|
123
|
+
/**
|
|
124
|
+
* Create a date picker
|
|
125
|
+
* @param {Element} element - element to bind a date picker
|
|
126
|
+
* @param {Object} [options] - config options
|
|
127
|
+
* @param {DateRangePicker} [rangepicker] - DateRangePicker instance the
|
|
128
|
+
* date picker belongs to. Use this only when creating date picker as a part
|
|
129
|
+
* of date range picker
|
|
130
|
+
*/
|
|
131
|
+
constructor(element, options = {}, rangepicker = undefined) {
|
|
132
|
+
element.datepicker = this;
|
|
133
|
+
this.element = element;
|
|
134
|
+
|
|
135
|
+
// set up config
|
|
136
|
+
const config = this.config = Object.assign({
|
|
137
|
+
buttonClass: (options.buttonClass && String(options.buttonClass)) || 'button',
|
|
138
|
+
container: document.body,
|
|
139
|
+
defaultViewDate: today(),
|
|
140
|
+
maxDate: undefined,
|
|
141
|
+
minDate: undefined,
|
|
142
|
+
}, processOptions(defaultOptions, this));
|
|
143
|
+
this._options = options;
|
|
144
|
+
Object.assign(config, processOptions(options, this));
|
|
145
|
+
|
|
146
|
+
// configure by type
|
|
147
|
+
const inline = this.inline = element.tagName !== 'INPUT';
|
|
148
|
+
let inputField;
|
|
149
|
+
let initialDates;
|
|
150
|
+
|
|
151
|
+
if (inline) {
|
|
152
|
+
config.container = element;
|
|
153
|
+
initialDates = stringToArray(element.dataset.date, config.dateDelimiter);
|
|
154
|
+
delete element.dataset.date;
|
|
155
|
+
} else {
|
|
156
|
+
const container = options.container ? document.querySelector(options.container) : null;
|
|
157
|
+
if (container) {
|
|
158
|
+
config.container = container;
|
|
159
|
+
}
|
|
160
|
+
inputField = this.inputField = element;
|
|
161
|
+
inputField.classList.add('datepicker-input');
|
|
162
|
+
initialDates = stringToArray(inputField.value, config.dateDelimiter);
|
|
163
|
+
}
|
|
164
|
+
if (rangepicker) {
|
|
165
|
+
// check validiry
|
|
166
|
+
const index = rangepicker.inputs.indexOf(inputField);
|
|
167
|
+
const datepickers = rangepicker.datepickers;
|
|
168
|
+
if (index < 0 || index > 1 || !Array.isArray(datepickers)) {
|
|
169
|
+
throw Error('Invalid rangepicker object.');
|
|
170
|
+
}
|
|
171
|
+
// attach itaelf to the rangepicker here so that processInputDates() can
|
|
172
|
+
// determine if this is the range-end picker of the rangepicker while
|
|
173
|
+
// setting inital values when pickLevel > 0
|
|
174
|
+
datepickers[index] = this;
|
|
175
|
+
// add getter for rangepicker
|
|
176
|
+
Object.defineProperty(this, 'rangepicker', {
|
|
177
|
+
get() {
|
|
178
|
+
return rangepicker;
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// set initial dates
|
|
184
|
+
this.dates = [];
|
|
185
|
+
// process initial value
|
|
186
|
+
const inputDateValues = processInputDates(this, initialDates);
|
|
187
|
+
if (inputDateValues && inputDateValues.length > 0) {
|
|
188
|
+
this.dates = inputDateValues;
|
|
189
|
+
}
|
|
190
|
+
if (inputField) {
|
|
191
|
+
inputField.value = stringifyDates(this.dates, config);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const picker = this.picker = new Picker(this);
|
|
195
|
+
|
|
196
|
+
if (inline) {
|
|
197
|
+
this.show();
|
|
198
|
+
} else {
|
|
199
|
+
// set up event listeners in other modes
|
|
200
|
+
const onMousedownDocument = onClickOutside.bind(null, this);
|
|
201
|
+
const listeners = [
|
|
202
|
+
[inputField, 'keydown', onKeydown.bind(null, this)],
|
|
203
|
+
[inputField, 'focus', onFocus.bind(null, this)],
|
|
204
|
+
[inputField, 'mousedown', onMousedown.bind(null, this)],
|
|
205
|
+
[inputField, 'click', onClickInput.bind(null, this)],
|
|
206
|
+
[inputField, 'paste', onPaste.bind(null, this)],
|
|
207
|
+
[document, 'mousedown', onMousedownDocument],
|
|
208
|
+
[document, 'touchstart', onMousedownDocument],
|
|
209
|
+
[window, 'resize', picker.place.bind(picker)]
|
|
210
|
+
];
|
|
211
|
+
registerListeners(this, listeners);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Format Date object or time value in given format and language
|
|
217
|
+
* @param {Date|Number} date - date or time value to format
|
|
218
|
+
* @param {String|Object} format - format string or object that contains
|
|
219
|
+
* toDisplay() custom formatter, whose signature is
|
|
220
|
+
* - args:
|
|
221
|
+
* - date: {Date} - Date instance of the date passed to the method
|
|
222
|
+
* - format: {Object} - the format object passed to the method
|
|
223
|
+
* - locale: {Object} - locale for the language specified by `lang`
|
|
224
|
+
* - return:
|
|
225
|
+
* {String} formatted date
|
|
226
|
+
* @param {String} [lang=en] - language code for the locale to use
|
|
227
|
+
* @return {String} formatted date
|
|
228
|
+
*/
|
|
229
|
+
static formatDate(date, format, lang) {
|
|
230
|
+
return formatDate(date, format, lang && locales[lang] || locales.en);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Parse date string
|
|
235
|
+
* @param {String|Date|Number} dateStr - date string, Date object or time
|
|
236
|
+
* value to parse
|
|
237
|
+
* @param {String|Object} format - format string or object that contains
|
|
238
|
+
* toValue() custom parser, whose signature is
|
|
239
|
+
* - args:
|
|
240
|
+
* - dateStr: {String|Date|Number} - the dateStr passed to the method
|
|
241
|
+
* - format: {Object} - the format object passed to the method
|
|
242
|
+
* - locale: {Object} - locale for the language specified by `lang`
|
|
243
|
+
* - return:
|
|
244
|
+
* {Date|Number} parsed date or its time value
|
|
245
|
+
* @param {String} [lang=en] - language code for the locale to use
|
|
246
|
+
* @return {Number} time value of parsed date
|
|
247
|
+
*/
|
|
248
|
+
static parseDate(dateStr, format, lang) {
|
|
249
|
+
return parseDate(dateStr, format, lang && locales[lang] || locales.en);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* @type {Object} - Installed locales in `[languageCode]: localeObject` format
|
|
254
|
+
* en`:_English (US)_ is pre-installed.
|
|
255
|
+
*/
|
|
256
|
+
static get locales() {
|
|
257
|
+
return locales;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* @type {Boolean} - Whether the picker element is shown. `true` whne shown
|
|
262
|
+
*/
|
|
263
|
+
get active() {
|
|
264
|
+
return !!(this.picker && this.picker.active);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* @type {HTMLDivElement} - DOM object of picker element
|
|
269
|
+
*/
|
|
270
|
+
get pickerElement() {
|
|
271
|
+
return this.picker ? this.picker.element : undefined;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Set new values to the config options
|
|
276
|
+
* @param {Object} options - config options to update
|
|
277
|
+
*/
|
|
278
|
+
setOptions(options) {
|
|
279
|
+
const picker = this.picker;
|
|
280
|
+
const newOptions = processOptions(options, this);
|
|
281
|
+
Object.assign(this._options, options);
|
|
282
|
+
Object.assign(this.config, newOptions);
|
|
283
|
+
picker.setOptions(newOptions);
|
|
284
|
+
|
|
285
|
+
refreshUI(this, 3);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Show the picker element
|
|
290
|
+
*/
|
|
291
|
+
show() {
|
|
292
|
+
if (this.inputField) {
|
|
293
|
+
if (this.inputField.disabled) {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
if (this.inputField !== document.activeElement) {
|
|
297
|
+
this._showing = true;
|
|
298
|
+
this.inputField.focus();
|
|
299
|
+
delete this._showing;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
this.picker.show();
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Hide the picker element
|
|
307
|
+
* Not available on inline picker
|
|
308
|
+
*/
|
|
309
|
+
hide() {
|
|
310
|
+
if (this.inline) {
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
this.picker.hide();
|
|
314
|
+
this.picker.update().changeView(this.config.startView).render();
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Destroy the Datepicker instance
|
|
319
|
+
* @return {Detepicker} - the instance destroyed
|
|
320
|
+
*/
|
|
321
|
+
destroy() {
|
|
322
|
+
this.hide();
|
|
323
|
+
unregisterListeners(this);
|
|
324
|
+
this.picker.detach();
|
|
325
|
+
if (!this.inline) {
|
|
326
|
+
this.inputField.classList.remove('datepicker-input');
|
|
327
|
+
}
|
|
328
|
+
delete this.element.datepicker;
|
|
329
|
+
return this;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Get the selected date(s)
|
|
334
|
+
*
|
|
335
|
+
* The method returns a Date object of selected date by default, and returns
|
|
336
|
+
* an array of selected dates in multidate mode. If format string is passed,
|
|
337
|
+
* it returns date string(s) formatted in given format.
|
|
338
|
+
*
|
|
339
|
+
* @param {String} [format] - Format string to stringify the date(s)
|
|
340
|
+
* @return {Date|String|Date[]|String[]} - selected date(s), or if none is
|
|
341
|
+
* selected, empty array in multidate mode and untitled in sigledate mode
|
|
342
|
+
*/
|
|
343
|
+
getDate(format = undefined) {
|
|
344
|
+
const callback = format
|
|
345
|
+
? date => formatDate(date, format, this.config.locale)
|
|
346
|
+
: date => new Date(date);
|
|
347
|
+
|
|
348
|
+
if (this.config.multidate) {
|
|
349
|
+
return this.dates.map(callback);
|
|
350
|
+
}
|
|
351
|
+
if (this.dates.length > 0) {
|
|
352
|
+
return callback(this.dates[0]);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Set selected date(s)
|
|
358
|
+
*
|
|
359
|
+
* In multidate mode, you can pass multiple dates as a series of arguments
|
|
360
|
+
* or an array. (Since each date is parsed individually, the type of the
|
|
361
|
+
* dates doesn't have to be the same.)
|
|
362
|
+
* The given dates are used to toggle the select status of each date. The
|
|
363
|
+
* number of selected dates is kept from exceeding the length set to
|
|
364
|
+
* maxNumberOfDates.
|
|
365
|
+
*
|
|
366
|
+
* With clear: true option, the method can be used to clear the selection
|
|
367
|
+
* and to replace the selection instead of toggling in multidate mode.
|
|
368
|
+
* If the option is passed with no date arguments or an empty dates array,
|
|
369
|
+
* it works as "clear" (clear the selection then set nothing), and if the
|
|
370
|
+
* option is passed with new dates to select, it works as "replace" (clear
|
|
371
|
+
* the selection then set the given dates)
|
|
372
|
+
*
|
|
373
|
+
* When render: false option is used, the method omits re-rendering the
|
|
374
|
+
* picker element. In this case, you need to call refresh() method later in
|
|
375
|
+
* order for the picker element to reflect the changes. The input field is
|
|
376
|
+
* refreshed always regardless of this option.
|
|
377
|
+
*
|
|
378
|
+
* When invalid (unparsable, repeated, disabled or out-of-range) dates are
|
|
379
|
+
* passed, the method ignores them and applies only valid ones. In the case
|
|
380
|
+
* that all the given dates are invalid, which is distinguished from passing
|
|
381
|
+
* no dates, the method considers it as an error and leaves the selection
|
|
382
|
+
* untouched.
|
|
383
|
+
*
|
|
384
|
+
* @param {...(Date|Number|String)|Array} [dates] - Date strings, Date
|
|
385
|
+
* objects, time values or mix of those for new selection
|
|
386
|
+
* @param {Object} [options] - function options
|
|
387
|
+
* - clear: {boolean} - Whether to clear the existing selection
|
|
388
|
+
* defualt: false
|
|
389
|
+
* - render: {boolean} - Whether to re-render the picker element
|
|
390
|
+
* default: true
|
|
391
|
+
* - autohide: {boolean} - Whether to hide the picker element after re-render
|
|
392
|
+
* Ignored when used with render: false
|
|
393
|
+
* default: config.autohide
|
|
394
|
+
*/
|
|
395
|
+
setDate(...args) {
|
|
396
|
+
const dates = [...args];
|
|
397
|
+
const opts = {};
|
|
398
|
+
const lastArg = lastItemOf(args);
|
|
399
|
+
if (
|
|
400
|
+
typeof lastArg === 'object'
|
|
401
|
+
&& !Array.isArray(lastArg)
|
|
402
|
+
&& !(lastArg instanceof Date)
|
|
403
|
+
&& lastArg
|
|
404
|
+
) {
|
|
405
|
+
Object.assign(opts, dates.pop());
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
const inputDates = Array.isArray(dates[0]) ? dates[0] : dates;
|
|
409
|
+
setDate(this, inputDates, opts);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Update the selected date(s) with input field's value
|
|
414
|
+
* Not available on inline picker
|
|
415
|
+
*
|
|
416
|
+
* The input field will be refreshed with properly formatted date string.
|
|
417
|
+
*
|
|
418
|
+
* @param {Object} [options] - function options
|
|
419
|
+
* - autohide: {boolean} - whether to hide the picker element after refresh
|
|
420
|
+
* default: false
|
|
421
|
+
*/
|
|
422
|
+
update(options = undefined) {
|
|
423
|
+
if (this.inline) {
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
const opts = {clear: true, autohide: !!(options && options.autohide)};
|
|
428
|
+
const inputDates = stringToArray(this.inputField.value, this.config.dateDelimiter);
|
|
429
|
+
setDate(this, inputDates, opts);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Refresh the picker element and the associated input field
|
|
434
|
+
* @param {String} [target] - target item when refreshing one item only
|
|
435
|
+
* 'picker' or 'input'
|
|
436
|
+
* @param {Boolean} [forceRender] - whether to re-render the picker element
|
|
437
|
+
* regardless of its state instead of optimized refresh
|
|
438
|
+
*/
|
|
439
|
+
refresh(target = undefined, forceRender = false) {
|
|
440
|
+
if (target && typeof target !== 'string') {
|
|
441
|
+
forceRender = target;
|
|
442
|
+
target = undefined;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
let mode;
|
|
446
|
+
if (target === 'picker') {
|
|
447
|
+
mode = 2;
|
|
448
|
+
} else if (target === 'input') {
|
|
449
|
+
mode = 1;
|
|
450
|
+
} else {
|
|
451
|
+
mode = 3;
|
|
452
|
+
}
|
|
453
|
+
refreshUI(this, mode, !forceRender);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* Enter edit mode
|
|
458
|
+
* Not available on inline picker or when the picker element is hidden
|
|
459
|
+
*/
|
|
460
|
+
enterEditMode() {
|
|
461
|
+
if (this.inline || !this.picker.active || this.editMode) {
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
this.editMode = true;
|
|
465
|
+
this.inputField.classList.add('in-edit', 'border-brand');
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Exit from edit mode
|
|
470
|
+
* Not available on inline picker
|
|
471
|
+
* @param {Object} [options] - function options
|
|
472
|
+
* - update: {boolean} - whether to call update() after exiting
|
|
473
|
+
* If false, input field is revert to the existing selection
|
|
474
|
+
* default: false
|
|
475
|
+
*/
|
|
476
|
+
exitEditMode(options = undefined) {
|
|
477
|
+
if (this.inline || !this.editMode) {
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
const opts = Object.assign({update: false}, options);
|
|
481
|
+
delete this.editMode;
|
|
482
|
+
this.inputField.classList.remove('in-edit', 'border-brand');
|
|
483
|
+
if (opts.update) {
|
|
484
|
+
this.update(opts);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {limitToRange} from '../lib/utils.js';
|
|
2
|
+
import {addMonths, addYears} from '../lib/date.js';
|
|
3
|
+
|
|
4
|
+
export function triggerDatepickerEvent(datepicker, type) {
|
|
5
|
+
const detail = {
|
|
6
|
+
date: datepicker.getDate(),
|
|
7
|
+
viewDate: new Date(datepicker.picker.viewDate),
|
|
8
|
+
viewId: datepicker.picker.currentView.id,
|
|
9
|
+
datepicker,
|
|
10
|
+
};
|
|
11
|
+
datepicker.element.dispatchEvent(new CustomEvent(type, {detail}));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// direction: -1 (to previous), 1 (to next)
|
|
15
|
+
export function goToPrevOrNext(datepicker, direction) {
|
|
16
|
+
const {minDate, maxDate} = datepicker.config;
|
|
17
|
+
const {currentView, viewDate} = datepicker.picker;
|
|
18
|
+
let newViewDate;
|
|
19
|
+
switch (currentView.id) {
|
|
20
|
+
case 0:
|
|
21
|
+
newViewDate = addMonths(viewDate, direction);
|
|
22
|
+
break;
|
|
23
|
+
case 1:
|
|
24
|
+
newViewDate = addYears(viewDate, direction);
|
|
25
|
+
break;
|
|
26
|
+
default:
|
|
27
|
+
newViewDate = addYears(viewDate, direction * currentView.navStep);
|
|
28
|
+
}
|
|
29
|
+
newViewDate = limitToRange(newViewDate, minDate, maxDate);
|
|
30
|
+
datepicker.picker.changeFocus(newViewDate).render();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function switchView(datepicker) {
|
|
34
|
+
const viewId = datepicker.picker.currentView.id;
|
|
35
|
+
if (viewId === datepicker.config.maxView) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
datepicker.picker.changeView(viewId + 1).render();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function unfocus(datepicker) {
|
|
42
|
+
if (datepicker.config.updateOnBlur) {
|
|
43
|
+
datepicker.update({autohide: true});
|
|
44
|
+
} else {
|
|
45
|
+
datepicker.refresh('input');
|
|
46
|
+
datepicker.hide();
|
|
47
|
+
}
|
|
48
|
+
}
|