diff options
Diffstat (limited to 'resources/assets/javascripts/studip-ui/date-picker.js')
| -rw-r--r-- | resources/assets/javascripts/studip-ui/date-picker.js | 166 |
1 files changed, 108 insertions, 58 deletions
diff --git a/resources/assets/javascripts/studip-ui/date-picker.js b/resources/assets/javascripts/studip-ui/date-picker.js index a9fc870..0393aac 100644 --- a/resources/assets/javascripts/studip-ui/date-picker.js +++ b/resources/assets/javascripts/studip-ui/date-picker.js @@ -1,26 +1,90 @@ // Setup Stud.IP's own datepicker extensions -export default { - selector: '.has-date-picker,[data-date-picker]', +function getValue(element) { + if (Datepicker.supportsNativeInput) { + return element.value; + } + + return $(element).datepicker('getDate'); +} + +function setValue(element, value) { + if (Datepicker.supportsNativeInput) { + element.value = value; + return; + } + + $(element).datepicker('setDate', value); +} + +function getOption(element, option) { + if (Datepicker.supportsNativeInput) { + return element.getAttribute(option) ?? null; + } + + const mapping = { + min: 'minDate', + max: 'maxDate', + }; + + return $(element).datepicker('option', mapping[option] ?? option); +} + +function setOption(element, option, value) { + if (Datepicker.supportsNativeInput) { + element.setAttribute(option, value); + return; + } + + const mapping = { + min: 'minDate', + max: 'maxDate', + }; + + $(element).datepicker('option', mapping[option] ?? option, value); +} + +const Datepicker = { + supportsNativeInput: (function () { + let input = document.createElement('input'); + input.setAttribute('type', 'date'); + + const invalid = 'not-a-valid-date'; + input.setAttribute('value', invalid); + + return input.value !== invalid; + })(), + selector: [ + '.has-date-picker', + '[data-date-picker]', + 'input[type="date"]', + ].join(','), // Initialize all datepickers that not yet been initialized (e.g. in dialogs) - init: function () { - $(this.selector).filter(function () { - return $(this).data('date-picker-init') === undefined; - }).each(function () { - $(this).data('date-picker-init', true).datepicker(); + init() { + Array.from(document.querySelectorAll(this.selector)).filter(node => { + return node.dataset.datePickerInit === undefined; + }).forEach(element => { + element.dataset.datePickerInit = true; + + if (!this.supportsNativeInput) { + $(element).datepicker(); + } + + this.refresh(element); + + element.addEventListener('change', event => { + this.refresh(event.target); + }); }); }, // Apply registered handlers. Take care: This happens upon before a // picker is shown as well as after a date has been selected. - refresh: function () { - $(this.selector).each(function () { - var element = this, - options = $(element).data().datePicker; - if (options) { - $.each(options, function (key, value) { - if (this.dataHandlers[key] !== undefined) { - this.dataHandlers[key].call(element, value); - } - }); + refresh(node) { + const options = node.dataset.datePicker !== undefined + ? JSON.parse(node.dataset.datePicker) + : {}; + Object.entries(options).forEach(([key, value]) => { + if (this.dataHandlers[key] !== undefined) { + this.dataHandlers[key](node, value); } }); }, @@ -30,16 +94,11 @@ export default { // the maximum allowed date the other date. // This will also set this date to the maximum allowed date if it // currently later than the allowed maximum date. - '<='(selector, offset) { - var this_date = $(this).datepicker('getDate'), - max_date = null, - temp, - adjustment = 0; - - if ($(this).data().datePicker.offset) { - temp = $(this).data().datePicker.offset; - adjustment = parseInt($(temp).val(), 10); - } + '<='(node, selector, offset = null) { + let this_date = getValue(node); + let max_date = null; + + offset = offset ?? node.dataset.datePicker?.offset ?? 0; // Get max date by either actual dates or maxDate options on // all matching elements @@ -47,7 +106,7 @@ export default { max_date = new Date(); } else { $(selector).each(function () { - var date = $(this).datepicker('getDate') || $(this).datepicker('option', 'maxDate'); + var date = getValue(this) ?? getOption(this, 'max'); if (date && (!max_date || date < max_date)) { max_date = new Date(date); } @@ -56,49 +115,41 @@ export default { // Set max date and adjust current date if neccessary if (max_date) { - max_date.setTime(max_date.getTime() - (offset || 0) * 24 * 60 * 60 * 1000); - - temp = new Date(max_date); - temp.setDate(temp.getDate() - adjustment); + max_date.setTime(max_date.getTime() - offset * 24 * 60 * 60 * 1000); if (this_date && this_date > max_date) { - $(this).datepicker('setDate', temp); + setValue(node, max_date); } - $(this).datepicker('option', 'maxDate', max_date); + setOption(node, 'max', max_date); } else { - $(this).datepicker('option', 'maxDate', null); + setOption(node, 'max', null); } }, // Ensure this date is earlier (<) than another date by setting the // maximum allowed date to the other date - 1 day. // This will also set this date to the maximum allowed date - 1 day // if it is currently later than the allowed maximum date. - '<'(selector) { - this['<='].call(this, selector, 1); + '<'(node, selector) { + this['<='](node, selector, 1); }, // Ensure this date is not earlier (>=) than another date by setting // the minimum allowed date to the other date. // This will also set this date to the minimum allowed date if it is // currently earlier than the allowed minimum date. - '>='(selector, offset) { - var this_date = $(this).datepicker('getDate'), - min_date = null, - temp, - adjustment = 0; - - if ($(this).data().datePicker.offset) { - temp = $(this).data().datePicker.offset; - adjustment = parseInt($(temp).val(), 10); - } + '>='(node, selector, offset = null) { + let this_date = getValue(node); + let min_date; + + offset = offset ?? node.dataset.datePicker?.offset ?? 0; // Get min date by either actual dates or minDate options on // all matching elements if (selector === 'today') { min_date = new Date(); } else { - $(selector).each(function () { - var date = $(this).datepicker('getDate') || $(this).datepicker('option', 'minDate'); + document.querySelectorAll(selector).forEach(n => { + var date = getValue(n) ?? getOption(n, 'min'); if (date && (!min_date || date > min_date)) { min_date = new Date(date); } @@ -107,26 +158,25 @@ export default { // Set min date and adjust current date if neccessary if (min_date) { - min_date.setTime(min_date.getTime() + (offset || 0) * 24 * 60 * 60 * 1000); - - temp = new Date(min_date); - temp.setDate(temp.getDate() + adjustment); + min_date.setTime(min_date.getTime() + offset * 24 * 60 * 60 * 1000); if (this_date && this_date < min_date) { - $(this).datepicker('setDate', temp); + setValue(node, min_date); } - $(this).datepicker('option', 'minDate', min_date); + setOption(node, 'min', min_date); } else { - $(this).datepicker('option', 'minDate', null); + setOption(node, 'min', null); } }, // Ensure this date is later (>) than another date by setting the // minimum allowed date to the other date + 1 day. // This will also set this date to the minimum allowed date + 1 day // if it is currently earlier than the allowed minimum date. - '>'(selector) { - this['>='].call(this, selector, 1); + '>'(node, selector) { + this['>='](node, selector, 1); } } }; + +export default Datepicker; |
