aboutsummaryrefslogtreecommitdiff
path: root/resources/assets/javascripts/studip-ui/time-picker.js
diff options
context:
space:
mode:
Diffstat (limited to 'resources/assets/javascripts/studip-ui/time-picker.js')
-rw-r--r--resources/assets/javascripts/studip-ui/time-picker.js306
1 files changed, 232 insertions, 74 deletions
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;