diff options
Diffstat (limited to 'resources/assets/javascripts')
| -rw-r--r-- | resources/assets/javascripts/bootstrap/application.js | 31 | ||||
| -rw-r--r-- | resources/assets/javascripts/studip-ui.js | 252 | ||||
| -rw-r--r-- | resources/assets/javascripts/studip-ui/abstract-picker.js | 64 | ||||
| -rw-r--r-- | resources/assets/javascripts/studip-ui/date-picker.js | 166 | ||||
| -rw-r--r-- | resources/assets/javascripts/studip-ui/datetime-picker.js | 40 | ||||
| -rw-r--r-- | resources/assets/javascripts/studip-ui/time-picker.js | 306 |
6 files changed, 552 insertions, 307 deletions
diff --git a/resources/assets/javascripts/bootstrap/application.js b/resources/assets/javascripts/bootstrap/application.js index cafd07e..05335bc 100644 --- a/resources/assets/javascripts/bootstrap/application.js +++ b/resources/assets/javascripts/bootstrap/application.js @@ -202,37 +202,6 @@ jQuery.extend(jQuery.ui.dialog.prototype.options, { * jQuery timepicker * ------------------------------------------------------------------------ */ -/* German translation for the jQuery Timepicker Addon */ -/* Written by Marvin */ -(function ($) { - $.timepicker.regional.de = { - timeOnlyTitle: 'Zeit wählen', - timeText: 'Zeit', - hourText: 'Stunde', - minuteText: 'Minute', - secondText: 'Sekunde', - millisecText: 'Millisekunde', - microsecText: 'Mikrosekunde', - timezoneText: 'Zeitzone', - currentText: 'Jetzt', - closeText: 'Fertig', - timeFormat: "HH:mm", - amNames: ['vorm.', 'AM', 'A'], - pmNames: ['nachm.', 'PM', 'P'], - isRTL: false, - showTimezone: false - }; - $.timepicker.setDefaults($.timepicker.regional.de); - - $(document).on('focus', '.has-time-picker', function () { - $(this).removeClass('has-time-picker').timepicker(); - }); - $(document).on('focus', '.has-time-picker-select', function () { - $(this).removeClass('has-time-picker-select').timepicker({controlType: 'select'}); - }); -}(jQuery)); - - (function ($) { $(document).on('focusout', '.studip-timepicker', function () { var time = $(this).val(); diff --git a/resources/assets/javascripts/studip-ui.js b/resources/assets/javascripts/studip-ui.js index 897604a..cc9f61e 100644 --- a/resources/assets/javascripts/studip-ui.js +++ b/resources/assets/javascripts/studip-ui.js @@ -45,140 +45,146 @@ import Timepicker from './studip-ui/time-picker.js'; 'use strict'; // Exit if datepicker is undefined (which it should never be) - if ($.datepicker === undefined) { + if (!Datepicker.supportsNativeInput && $.datepicker === undefined) { return; } - // Setup defaults and default locales - var defaults = {}, - locale = { - closeText: $gettext('Schließen'), - prevText: $gettext('Zurück'), - nextText: $gettext('Vor'), - currentText: $gettext('Jetzt'), - monthNames: [ - $gettext('Januar'), - $gettext('Februar'), - $gettext('März'), - $gettext('April'), - $gettext('Mai'), - $gettext('Juni'), - $gettext('Juli'), - $gettext('August'), - $gettext('September'), - $gettext('Oktober'), - $gettext('November'), - $gettext('Dezember') - ], - monthNamesShort: [ - $gettext('Jan'), - $gettext('Feb'), - $gettext('Mär'), - $gettext('Apr'), - $gettext('Mai'), - $gettext('Jun'), - $gettext('Jul'), - $gettext('Aug'), - $gettext('Sep'), - $gettext('Okt'), - $gettext('Nov'), - $gettext('Dez') - ], - dayNames: [ - $gettext('Sonntag'), - $gettext('Montag'), - $gettext('Dienstag'), - $gettext('Mittwoch'), - $gettext('Donnerstag'), - $gettext('Freitag'), - $gettext('Samstag') - ], - dayNamesShort: [ - $gettext('So'), - $gettext('Mo'), - $gettext('Di'), - $gettext('Mi'), - $gettext('Do'), - $gettext('Fr'), - $gettext('Sa') - ], - weekHeader: $gettext('Wo'), - dateFormat: 'dd.mm.yy', - firstDay: 1, - isRTL: false, - showMonthAfterYear: false, - yearSuffix: '', - changeMonth: true, - changeYear: true, - }; - // Set dayNamesMin to dayNamesShort since they are equal - locale.dayNamesMin = locale.dayNamesShort; - - - // Apply defaults including date picker handlers - defaults = Object.assign({}, locale, { - beforeShow (input) { - DatePicker.refresh(); - - if ($(input).parents('.ui-dialog').length > 0) { - return; + if (!Datepicker.supportsNativeInput) { + // Setup defaults and default locales + var defaults = {}, + locale = { + closeText: $gettext('Schließen'), + prevText: $gettext('Zurück'), + nextText: $gettext('Vor'), + currentText: $gettext('Jetzt'), + monthNames: [ + $gettext('Januar'), + $gettext('Februar'), + $gettext('März'), + $gettext('April'), + $gettext('Mai'), + $gettext('Juni'), + $gettext('Juli'), + $gettext('August'), + $gettext('September'), + $gettext('Oktober'), + $gettext('November'), + $gettext('Dezember') + ], + monthNamesShort: [ + $gettext('Jan'), + $gettext('Feb'), + $gettext('Mär'), + $gettext('Apr'), + $gettext('Mai'), + $gettext('Jun'), + $gettext('Jul'), + $gettext('Aug'), + $gettext('Sep'), + $gettext('Okt'), + $gettext('Nov'), + $gettext('Dez') + ], + dayNames: [ + $gettext('Sonntag'), + $gettext('Montag'), + $gettext('Dienstag'), + $gettext('Mittwoch'), + $gettext('Donnerstag'), + $gettext('Freitag'), + $gettext('Samstag') + ], + dayNamesShort: [ + $gettext('So'), + $gettext('Mo'), + $gettext('Di'), + $gettext('Mi'), + $gettext('Do'), + $gettext('Fr'), + $gettext('Sa') + ], + weekHeader: $gettext('Wo'), + dateFormat: 'dd.mm.yy', + firstDay: 1, + isRTL: false, + showMonthAfterYear: false, + yearSuffix: '', + changeMonth: true, + changeYear: true, + }; + // Set dayNamesMin to dayNamesShort since they are equal + locale.dayNamesMin = locale.dayNamesShort; + + + // Apply defaults including date picker handlers + defaults = Object.assign({}, locale, { + beforeShow (input) { + Datepicker.refresh(); + + if ($(input).parents('.ui-dialog').length > 0) { + return; + } + + $(input).css({ + 'position': 'relative', + 'z-index': 1002 + }); + }, + onSelect: function (value, instance) { + if (value !== instance.lastVal) { + $(this).change(); + } } - - $(input).css({ - 'position': 'relative', - 'z-index': 1002 - }); - }, - onSelect: function (value, instance) { - if (value !== instance.lastVal) { - $(this).change(); + }); + + $.datepicker.setDefaults(Object.assign({}, defaults, { + beforeShow (input) { + // Don't lose original behaviour + defaults.beforeShow(input); + + if ($(input).parents('.ui-dialog').length > 0) { + $('.ui-dialog-content').bind('scroll.datepicker-scroll', _.debounce($.proxy(DpHideOnScroll, null, input), 100, {leading:true, trailing:false})); + } + $(window).bind('scroll.datepicker-scroll', _.debounce($.proxy(DpHideOnScroll, null, input), 100, {leading:true, trailing:false})); + + if ($(input).closest('#sidebar').length === 0) { + return; + } + + const button = input.nextElementSibling; + if (button && button.matches('input[type="submit"]')) { + button.style.position = 'relative'; + button.style.zIndex = input.style.zIndex; + } + }, + onClose (date, inst) { + $(this).one('click.picker', function () { + $(this).datepicker('show'); + }).on('blur', function () { + $(this).off('click.picker'); + }); + + if ($(this).parents('.ui-dialog').length > 0) { + $('.ui-dialog-content').unbind('scroll.datepicker-scroll'); + } else { + $(window).unbind('scroll.datepicker-scroll'); + } } - } - }); + })); - $.datepicker.setDefaults(Object.assign({}, defaults, { - beforeShow (input) { - // Don't lose original behaviour - defaults.beforeShow(input); - - if ($(input).parents('.ui-dialog').length > 0) { - $('.ui-dialog-content').bind('scroll.datepicker-scroll', _.debounce($.proxy(DpHideOnScroll, null, input), 100, {leading:true, trailing:false})); - } - $(window).bind('scroll.datepicker-scroll', _.debounce($.proxy(DpHideOnScroll, null, input), 100, {leading:true, trailing:false})); - - if ($(input).closest('#sidebar').length === 0) { - return; - } - - const button = input.nextElementSibling; - if (button && button.matches('input[type="submit"]')) { - button.style.position = 'relative'; - button.style.zIndex = input.style.zIndex; - } - }, - onClose (date, inst) { - $(this).one('click.picker', function () { - $(this).datepicker('show'); - }).on('blur', function () { - $(this).off('click.picker'); - }); - - if ($(this).parents('.ui-dialog').length > 0) { - $('.ui-dialog-content').unbind('scroll.datepicker-scroll'); - } else { - $(window).unbind('scroll.datepicker-scroll'); - } + var DpHideOnScroll = function () { + var input = arguments[0]; + $(input).blur(); + $(input).datepicker('hide'); } - })); - - var DpHideOnScroll = function () { - var input = arguments[0]; - $(input).blur(); - $(input).datepicker('hide'); } // Attach global focus handler on date picker elements $(document).on('focus', Datepicker.selector, () => { + if (!$(event.target).is('input[type="date"]')) { + $(event.target).attr('type', 'date'); + } + Datepicker.init(); }); diff --git a/resources/assets/javascripts/studip-ui/abstract-picker.js b/resources/assets/javascripts/studip-ui/abstract-picker.js new file mode 100644 index 0000000..b046d9d --- /dev/null +++ b/resources/assets/javascripts/studip-ui/abstract-picker.js @@ -0,0 +1,64 @@ +class AbstractPicker +{ + static dataHandlers = {}; + + static supportsNativeInput() { + return true; + } + + static init() { + const initIndex = this.name.toLowerCase(); + + Array.from(document.querySelectorAll(this.selector)).filter(node => { + return node.dataset[initIndex] === undefined; + }).forEach(element => { + element.dataset[initIndex] = true; + + const picker = new this(element); + }); + + } + + node; + + constructor(node) { + if (new.target === AbstractPicker) { + throw new TypeError('Cannot construct an abstract picker'); + } + + if (this.constructor.selector === undefined) { + throw new Error('No selector getter defined'); + } + + if (this.constructor.datasetIndex === undefined) { + throw new Error('No datasetIndex getter defined'); + } + + this.node = node; + + this.setup(); + + this.refresh(); + node.addEventListener('change', () => this.refresh()); + } + + setup() { + } + + refresh() { + const options = this.node.dataset[this.constructor.datasetIndex] !== undefined + ? JSON.parse(this.node.dataset[this.constructor.datasetIndex]) + : {}; + + console.log('in refresh', options); + + Object.entries(options).forEach(([key, value]) => { + if (this.constructor.dataHandlers[key] !== undefined) { + console.log('match', key, value); + this.constructor.dataHandlers[key](this.node, value); + } + }); + } +} + +export default AbstractPicker; 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; diff --git a/resources/assets/javascripts/studip-ui/datetime-picker.js b/resources/assets/javascripts/studip-ui/datetime-picker.js index 0e8868a..cb05be0 100644 --- a/resources/assets/javascripts/studip-ui/datetime-picker.js +++ b/resources/assets/javascripts/studip-ui/datetime-picker.js @@ -15,15 +15,10 @@ export default { ].join(','), // Initialize all datetimepickers that not yet been initialized (e.g. in dialogs) init() { - const elements = Array.from(document.querySelectorAll(this.selector)).filter(node => { + Array.from(document.querySelectorAll(this.selector)).filter(node => { return node.dataset.datetimePickerInit === undefined; - }); - - elements.forEach(element => { + }).forEach(element => { element.dataset.datetimePickerInit = true; - element.addEventListener('change', event => { - this.refresh(event.target); - }); // Load and apply polyfill if necessary if (!this.supportsNativeInput) { @@ -32,26 +27,29 @@ export default { element.classList.add('hasTimepicker'); }); } - }); - $(this.selector).filter(function () { - return $(this).data('datetime-picker-init') === undefined; - }).each(function () { - $(this).data('datetime-picker-init', true).datetimepicker(); + this.refresh(element); + + element.addEventListener('change', event => { + this.refresh(event.target); + }); }); + // + // $(this.selector).filter(function () { + // return $(this).data('datetime-picker-init') === undefined; + // }).each(function () { + // $(this).data('datetime-picker-init', true).datetimepicker(); + // }); }, // Apply registered handlers. Take care: This happens upon before a // picker is shown as well as after a date has been selected. refresh(node) { - $(this.selector).each(function () { - var element = this, - options = $(element).data().datetimePicker; - if (options) { - $.each(options, function (key, value) { - if (this.dataHandlers[key] !== undefined) { - this.dataHandlers[key].call(element, value); - } - }); + const options = node.dataset.datetimePicker !== undefined + ? JSON.parse(node.dataset.datetimePicker) + : {}; + Object.entries(options).forEach(([key, value]) => { + if (this.dataHandlers[key] !== undefined) { + this.dataHandlers[key](node, value); } }); }, diff --git a/resources/assets/javascripts/studip-ui/time-picker.js b/resources/assets/javascripts/studip-ui/time-picker.js index 4f331c8..88515e2 100644 --- a/resources/assets/javascripts/studip-ui/time-picker.js +++ b/resources/assets/javascripts/studip-ui/time-picker.js @@ -1,85 +1,43 @@ -export default { - supportsNativeInput: (function () { - let input = document.createElement('input'); - input.setAttribute('type', 'time'); - - const invalid = 'not-a-time'; - input.setAttribute('value', invalid); - - return input.value !== invalid; - })(), - selector: [ - '.has-time-picker', - '[data-time-picker]', - 'input[type="time"]', - ].join(','), - // Initialize all datetimepickers that not yet been initialized (e.g. in dialogs) - init() { - const elements = Array.from(document.querySelectorAll(this.selector)).filter(node => { - return node.dataset.timePickerInit === undefined; - }); - - elements.forEach(element => { - element.dataset.timePickerInit = true; - element.addEventListener('change', event => { - this.refresh(event.target); - }); +import AbstractPicker from './abstract-picker.js'; - // Load and apply polyfill if necessary - if (!this.supportsNativeInput) { - import('time-input-polyfill').then(({default: TimePolyfill}) => { - new TimePolyfill(element); - element.classList.add('hasTimepicker'); - }); - } - }); - }, - // Apply registered handlers. Take care: This happens upon before a - // picker is shown as well as after a date has been selected. - refresh(node) { - const options = node.dataset.timePicker !== undefined - ? JSON.parse(node.dataset.timePicker) - : {}; - Object.entries(options).forEach(([key, value]) => { - if (this.dataHandlers[key] !== undefined) { - this.dataHandlers[key](node, value); - } - }); - }, - parseTime(time) { - const split = time.split(':'); - return { - hour: parseInt(split[0], 10), - minute: parseInt(split[1], 10) - }; - }, - createTime(hours, minutes, minute_offset = 0) { - // Adjust minutes if offset is given - minutes = minutes + minute_offset; - if (minutes >= 60) { - hours += 1; - minutes -= 60; - } else if (minutes < 0) { - hours -= 1; - minutes += 60; - } +const nativeSupport = (() => { + let input = document.createElement('input'); + input.setAttribute('type', 'time'); - // Sanitize hours - hours = Math.min(23, Math.max(0, hours)); + const invalid = 'not-a-time'; + input.setAttribute('value', invalid); - return ('0' + hours).slice(-2) + ':' + ('0' + minutes).slice(-2); - }, - // Define handlers for any data-time-picker option - dataHandlers: { + return input.value !== invalid; +})(); + +class Timepicker extends AbstractPicker +{ + static supportsNativeInput() { + return nativeSupport; + } + + static get selector() { + return [ + '.has-time-picker', + '[data-time-picker]', + 'input[type="time"]', + ].join(','); + } + + static get datasetIndex() { + return 'timePicker'; + } + + static dataHandlers = { // Ensure this time is not later (<=) than another time by setting // the maximum allowed time on the other time. // This will also set this time to the maximum allowed time if it is // currently later than the allowed maximum time. - '<='(node, selector, offset) { + '<='(node, selector, offset = null) { const this_time = node.value; let max_time = null; - offset = offset ?? node.dataset.offset ?? 0; + offset = offset ?? node.dataset.timepicker?.offset ?? 0; document.querySelectorAll(selector).forEach(n => { const time = n.value; @@ -117,7 +75,7 @@ export default { // 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. - '>='(node, selector, offset) { + '>='(node, selector, offset = null) { const this_time = node.value; let min_time = null; @@ -156,4 +114,204 @@ export default { this['>='](node, selector, 1); } } -}; + + static parseTime(time) { + const split = time.split(':'); + return { + hour: parseInt(split[0], 10), + minute: parseInt(split[1], 10) + }; + } + + static createTime(hours, minutes, minute_offset = 0) { + // Adjust minutes if offset is given + minutes = minutes + minute_offset; + if (minutes >= 60) { + hours += 1; + minutes -= 60; + } else if (minutes < 0) { + hours -= 1; + minutes += 60; + } + + // Sanitize hours + hours = Math.min(23, Math.max(0, hours)); + + return ('0' + hours).slice(-2) + ':' + ('0' + minutes).slice(-2); + } + + setup() { + super.setup(); + + // Load and apply polyfill if necessary + if (!Timepicker.supportsNativeInput) { + import('time-input-polyfill').then(({default: TimePolyfill}) => { + new TimePolyfill(this.node); + this.node.classList.add('has-time-picker'); + }); + } + } +} + +// const Timepicker = { +// supportsNativeInput: (function () { +// let input = document.createElement('input'); +// input.setAttribute('type', 'time'); +// +// const invalid = 'not-a-time'; +// input.setAttribute('value', invalid); +// +// return input.value !== invalid; +// })(), +// selector: [ +// '.has-time-picker', +// '[data-time-picker]', +// 'input[type="time"]', +// ].join(','), +// // Initialize all datetimepickers that not yet been initialized (e.g. in dialogs) +// init() { +// Array.from(document.querySelectorAll(this.selector)).filter(node => { +// return node.dataset.timePickerInit === undefined; +// }).forEach(element => { +// element.dataset.timePickerInit = true; +// +// // Load and apply polyfill if necessary +// if (!this.supportsNativeInput) { +// import('time-input-polyfill').then(({default: TimePolyfill}) => { +// new TimePolyfill(element); +// element.classList.add('hasTimepicker'); +// }); +// } +// +// 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(node) { +// const options = node.dataset.timePicker !== undefined +// ? JSON.parse(node.dataset.timePicker) +// : {}; +// Object.entries(options).forEach(([key, value]) => { +// if (this.dataHandlers[key] !== undefined) { +// this.dataHandlers[key](node, value); +// } +// }); +// }, +// parseTime(time) { +// const split = time.split(':'); +// return { +// hour: parseInt(split[0], 10), +// minute: parseInt(split[1], 10) +// }; +// }, +// createTime(hours, minutes, minute_offset = 0) { +// // Adjust minutes if offset is given +// minutes = minutes + minute_offset; +// if (minutes >= 60) { +// hours += 1; +// minutes -= 60; +// } else if (minutes < 0) { +// hours -= 1; +// minutes += 60; +// } +// +// // Sanitize hours +// hours = Math.min(23, Math.max(0, hours)); +// +// return ('0' + hours).slice(-2) + ':' + ('0' + minutes).slice(-2); +// }, +// // Define handlers for any data-time-picker option +// dataHandlers: { +// // Ensure this time is not later (<=) than another time by setting +// // the maximum allowed time on the other time. +// // This will also set this time to the maximum allowed time if it is +// // currently later than the allowed maximum time. +// '<='(node, selector, offset = null) { +// const this_time = node.value; +// let max_time = null; +// +// offset = offset ?? node.dataset.timepicker?.offset ?? 0; +// +// document.querySelectorAll(selector).forEach(n => { +// const time = n.value; +// if (time && (!max_time || time < max_time)) { +// max_time = time; +// } +// }); +// +// // Set max time and adjust current time if neccessary +// if (max_time) { +// const parsed = Timepicker.parseTime(max_time); +// max_time = Timepicker.createTime( +// parsed.hour, +// parsed.minute, +// -offset +// ); +// +// if (this_time && this_time > max_time) { +// node.value = max_time; +// } +// +// node.setAttribute('max', max_time); +// } else { +// node.removeAttribute('max'); +// } +// }, +// // 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. +// '<'(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. +// '>='(node, selector, offset = null) { +// const this_time = node.value; +// let min_time = null; +// +// offset = offset ?? node.dataset.offset ?? 0; +// +// document.querySelectorAll(selector).forEach(n => { +// const time = n.value; +// if (time && (!min_time || time < min_time)) { +// min_time = time; +// } +// }); +// +// // Set min time and adjust current time if neccessary +// if (min_time) { +// const parsed = Timepicker.parseTime(min_time); +// min_time = Timepicker.createTime( +// parsed.hour, +// parsed.minute, +// offset +// ); +// +// if (this_time && this_time < min_time) { +// node.value = min_time; +// } +// +// node.setAttribute('min', min_time); +// } else { +// node.removeAttribute('min'); +// } +// }, +// // 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. +// '>'(node, selector) { +// this['>='](node, selector, 1); +// } +// } +// }; + +export default Timepicker; |
