ModeratorElection/frontend/generated/jar-resources/vaadin-time-picker/timepickerConnector.js
2024-06-06 17:45:46 +02:00

193 lines
7.6 KiB
JavaScript

import {
TEST_PM_TIME,
formatMilliseconds,
parseMillisecondsIntoInteger,
parseDigitsIntoInteger,
getAmString,
getPmString,
getSeparator,
searchAmOrPmToken
} from './helpers.js';
import { TimePicker } from '@vaadin/time-picker/src/vaadin-time-picker.js';
(function () {
const tryCatchWrapper = function (callback) {
return window.Vaadin.Flow.tryCatchWrapper(callback, 'Vaadin Time Picker');
};
// Execute callback when predicate returns true.
// Try again later if predicate returns false.
function when(predicate, callback, timeout = 0) {
if (predicate()) {
callback();
} else {
setTimeout(() => when(predicate, callback, 200), timeout);
}
}
function parseISO(text) {
// The default i18n parser of the web component is ISO 8601 compliant.
const timeObject = TimePicker.properties.i18n.value().parseTime(text);
// The web component returns an object with string values
// while the connector expects number values.
return {
hours: parseInt(timeObject.hours || 0),
minutes: parseInt(timeObject.minutes || 0),
seconds: parseInt(timeObject.seconds || 0),
milliseconds: parseInt(timeObject.milliseconds || 0)
}
};
window.Vaadin.Flow.timepickerConnector = {
initLazy: (timepicker) =>
tryCatchWrapper(function (timepicker) {
// Check whether the connector was already initialized for the timepicker
if (timepicker.$connector) {
return;
}
timepicker.$connector = {};
timepicker.$connector.setLocale = tryCatchWrapper(function (locale) {
// capture previous value if any
let previousValueObject;
if (timepicker.value && timepicker.value !== '') {
previousValueObject = parseISO(timepicker.value);
}
try {
// Check whether the locale is supported by the browser or not
TEST_PM_TIME.toLocaleTimeString(locale);
} catch (e) {
locale = 'en-US';
// FIXME should do a callback for server to throw an exception ?
throw new Error(
'vaadin-time-picker: The locale ' +
locale +
' is not supported, falling back to default locale setting(en-US).'
);
}
// 1. 24 or 12 hour clock, if latter then what are the am/pm strings ?
const pmString = getPmString(locale);
const amString = getAmString(locale);
// 2. What is the separator ?
const separator = getSeparator(locale);
const includeSeconds = function () {
return timepicker.step && timepicker.step < 60;
};
const includeMilliSeconds = function () {
return timepicker.step && timepicker.step < 1;
};
let cachedTimeString;
let cachedTimeObject;
timepicker.i18n = {
formatTime: tryCatchWrapper(function (timeObject) {
if (!timeObject) return;
const timeToBeFormatted = new Date();
timeToBeFormatted.setHours(timeObject.hours);
timeToBeFormatted.setMinutes(timeObject.minutes);
timeToBeFormatted.setSeconds(timeObject.seconds !== undefined ? timeObject.seconds : 0);
// the web component expects the correct granularity used for the time string,
// thus need to format the time object in correct granularity by passing the format options
let localeTimeString = timeToBeFormatted.toLocaleTimeString(locale, {
hour: 'numeric',
minute: 'numeric',
second: includeSeconds() ? 'numeric' : undefined
});
// milliseconds not part of the time format API
if (includeMilliSeconds()) {
localeTimeString = formatMilliseconds(localeTimeString, timeObject.milliseconds, amString, pmString);
}
return localeTimeString;
}),
parseTime: tryCatchWrapper(function (timeString) {
if (timeString && timeString === cachedTimeString && cachedTimeObject) {
return cachedTimeObject;
}
if (!timeString) {
// when nothing is returned, the component shows the invalid state for the input
return;
}
const amToken = searchAmOrPmToken(timeString, amString);
const pmToken = searchAmOrPmToken(timeString, pmString);
const numbersOnlyTimeString = timeString
.replace(amToken || '', '')
.replace(pmToken || '', '')
.trim();
// A regexp that allows to find the numbers with optional separator and continuing searching after it.
const numbersRegExp = new RegExp('([\\d\\u0660-\\u0669]){1,2}(?:' + separator + ')?', 'g');
let hours = numbersRegExp.exec(numbersOnlyTimeString);
if (hours) {
hours = parseDigitsIntoInteger(hours[0].replace(separator, ''));
// handle 12 am -> 0
// do not do anything if am & pm are not used or if those are the same,
// as with locale bg-BG there is always ч. at the end of the time
if (amToken !== pmToken) {
if (hours === 12 && amToken) {
hours = 0;
}
if (hours !== 12 && pmToken) {
hours += 12;
}
}
const minutes = numbersRegExp.exec(numbersOnlyTimeString);
const seconds = minutes && numbersRegExp.exec(numbersOnlyTimeString);
// detecting milliseconds from input, expects am/pm removed from end, eg. .0 or .00 or .000
const millisecondRegExp = /[[\.][\d\u0660-\u0669]{1,3}$/;
// reset to end or things can explode
let milliseconds = seconds && includeMilliSeconds() && millisecondRegExp.exec(numbersOnlyTimeString);
// handle case where last numbers are seconds and . is the separator (invalid regexp match)
if (milliseconds && milliseconds['index'] <= seconds['index']) {
milliseconds = undefined;
}
// hours is a number at this point, others are either arrays or null
// the string in [0] from the arrays includes the separator too
cachedTimeObject = hours !== undefined && {
hours: hours,
minutes: minutes ? parseDigitsIntoInteger(minutes[0].replace(separator, '')) : 0,
seconds: seconds ? parseDigitsIntoInteger(seconds[0].replace(separator, '')) : 0,
milliseconds:
minutes && seconds && milliseconds
? parseMillisecondsIntoInteger(milliseconds[0].replace('.', ''))
: 0
};
cachedTimeString = timeString;
return cachedTimeObject;
}
})
};
if (previousValueObject) {
when(
() => timepicker.$,
() => {
const newValue = timepicker.i18n.formatTime(previousValueObject);
// FIXME works but uses private API, needs fixes in web component
if (timepicker.inputElement.value !== newValue) {
timepicker.inputElement.value = newValue;
timepicker.$.comboBox.value = newValue;
}
}
);
}
});
})(timepicker)
};
})();