This repository has been archived on 2024-10-24. You can view files and clone it, but cannot push or open issues or pull requests.
fradrive-old/frontend/src/utils/form/datepicker.js

115 lines
4.0 KiB
JavaScript

import datetime from 'tail.datetime';
import dateFormat from 'dateformat';
import { Utility } from '../../core/utility';
const FORM_DATE_FORMAT = 'yyyy-mm-dd"T"HH:MM:ss';
/* TODO:
- DONE define a map of form id to instance lists
- DONE define a function that formats all dates of a form with a specified id
- WIP call this function where formdata appears in mass-input.js, async-form.js and async-table.js
*/
const DATEPICKER_UTIL_SELECTOR = 'input[type="date"], input[type="time"], input[type="datetime-local"]';
const DATEPICKER_INITIALIZED_CLASS = 'datepicker--initialized';
const DATEPICKER_CONFIG = {
'global': {
locale: 'de', // TODO: hardcoded
weekStart: 1, // TODO: hardcoded
stayOpen: true, // to prevent the instance from closing when selecting a date before selecting a time
closeButton: false,
dateFormat: 'dd.mm.YYYY', // TODO: hardcoded, get from setting
},
'datetime-local': {},
'date': {
timeFormat: false,
},
'time': {
dateFormat: false,
},
};
@Utility({
selector: DATEPICKER_UTIL_SELECTOR,
})
export class Datepicker {
// singleton Map that maps a formID to a Map of Datepicker objects
static datepickerCollections;
datepickerInstance;
_element;
constructor(element) {
if (!element) {
throw new Error('Datepicker utility needs to be passed an element!');
}
if (element.classList.contains(DATEPICKER_INITIALIZED_CLASS)) {
return false;
}
// initialize datepickerCollections singleton if not already done
if (!Datepicker.datepickerCollections) {
Datepicker.datepickerCollections = new Map();
}
this._element = element;
// get all relevant config options for this datepicker type
const datepickerGlobalConfig = DATEPICKER_CONFIG['global'];
const datepickerConfig = DATEPICKER_CONFIG[this._element.getAttribute('type')];
if (!datepickerConfig) {
throw new Error('Datepicker utility called on unsupported element!');
}
// initialize tail.datetime (datepicker) instance
this.datepickerInstance = datetime(this._element, { ...datepickerGlobalConfig, ...datepickerConfig });
// register this datepicker instance with the formID of the given element in the datepicker collection
const formID = this._element.form.id;
const elemID = this._element.id;
if (!Datepicker.datepickerCollections.has(formID)) {
// insert a new key value pair if the formID key is not there already
Datepicker.datepickerCollections.set(formID, new Map([[elemID, this]]));
} else {
// otherwise, insert this instance into the Map
Datepicker.datepickerCollections.get(formID).set(elemID, this);
}
// mark the form input element as initialized
this._element.classList.add(DATEPICKER_INITIALIZED_CLASS);
// close the instance if something other than the instance was clicked (i.e. if the target is not within the datepicker instance and if any previously clicked calendar view was replaced (is not in the window anymore) because it was clicked). YES, I KNOW
window.addEventListener('click', event => {
if (!this.datepickerInstance.dt.contains(event.target) && window.document.contains(event.target)) {
this.datepickerInstance.close();
}
});
// close the datepicker on escape keydown events
this._element.addEventListener('keydown', event => {
if (event.keyCode === 27) {
this.datepickerInstance.close();
}
});
// format the date value of the form input element of this datepicker before form submission
this._element.form.addEventListener('submit', () => this.formatElementValue());
}
destroy() {
this.datepickerInstance.destroy();
}
/**
* Formats the value of this input element from datepicker format (i.e. DATEPICKER_CONFIG.dateFormat + " " + datetime.defaults.timeFormat) to Uni2work internal date format (i.e. FORM_DATE_FORMAT) required for form submission
*/
formatElementValue() {
if (!this.datepickerInstance.select || !this._element.value) return;
this._element.value = dateFormat(this.datepickerInstance.select, FORM_DATE_FORMAT);
}
}