|
@@ -103,7 +103,7 @@ function updateRelativeTimeForElements(elements)
|
|
|
if (timestamp === undefined)
|
|
|
continue
|
|
|
|
|
|
- element.innerText = relativeTimeSince(timestamp);
|
|
|
+ element.textContent = relativeTimeSince(timestamp);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -341,18 +341,110 @@ function afterContentReady(callback) {
|
|
|
contentReadyCallbacks.push(callback);
|
|
|
}
|
|
|
|
|
|
-function updateClocks(elements, formatter) {
|
|
|
- const currentDate = new Date();
|
|
|
- for (const elem of elements) {
|
|
|
- elem.textContent = formatter.format(currentDate);
|
|
|
+const weekDayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
|
|
|
+const monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
|
|
|
+
|
|
|
+function makeSettableTimeElement(element, hourFormat) {
|
|
|
+ const fragment = document.createDocumentFragment();
|
|
|
+ const hour = document.createElement('span');
|
|
|
+ const minute = document.createElement('span');
|
|
|
+ const amPm = document.createElement('span');
|
|
|
+ fragment.append(hour, document.createTextNode(':'), minute);
|
|
|
+
|
|
|
+ if (hourFormat == '12h') {
|
|
|
+ fragment.append(document.createTextNode(' '), amPm);
|
|
|
}
|
|
|
+
|
|
|
+ element.append(fragment);
|
|
|
+
|
|
|
+ return (date) => {
|
|
|
+ const hours = date.getHours();
|
|
|
+
|
|
|
+ if (hourFormat == '12h') {
|
|
|
+ amPm.textContent = hours < 12 ? 'AM' : 'PM';
|
|
|
+ hour.textContent = hours % 12 || 12;
|
|
|
+ } else {
|
|
|
+ hour.textContent = hours < 10 ? '0' + hours : hours;
|
|
|
+ }
|
|
|
+
|
|
|
+ const minutes = date.getMinutes();
|
|
|
+ minute.textContent = minutes < 10 ? '0' + minutes : minutes;
|
|
|
+ };
|
|
|
+};
|
|
|
+
|
|
|
+function timeInZone(now, zone) {
|
|
|
+ let timeInZone;
|
|
|
+
|
|
|
+ try {
|
|
|
+ timeInZone = new Date(now.toLocaleString('en-US', { timeZone: zone }));
|
|
|
+ } catch (e) {
|
|
|
+ // TODO: indicate to the user that this is an invalid timezone
|
|
|
+ console.error(e);
|
|
|
+ timeInZone = now
|
|
|
+ }
|
|
|
+
|
|
|
+ const diffInHours = Math.round((timeInZone.getTime() - now.getTime()) / 1000 / 60 / 60);
|
|
|
+
|
|
|
+ return { time: timeInZone, diffInHours: diffInHours };
|
|
|
}
|
|
|
|
|
|
function setupClocks() {
|
|
|
- const clockFormatter = new Intl.DateTimeFormat(undefined, {minute: "numeric", hour: "numeric"});
|
|
|
- const elements = document.getElementsByClassName("glance-clock");
|
|
|
- updateClocks(elements, clockFormatter)
|
|
|
- setInterval(() => {updateClocks(elements, clockFormatter)}, 1000);
|
|
|
+ const clocks = document.getElementsByClassName('clock');
|
|
|
+
|
|
|
+ if (clocks.length == 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const updateCallbacks = [];
|
|
|
+
|
|
|
+ for (var i = 0; i < clocks.length; i++) {
|
|
|
+ const clock = clocks[i];
|
|
|
+ const hourFormat = clock.dataset.hourFormat;
|
|
|
+ const localTimeContainer = clock.querySelector('[data-local-time]');
|
|
|
+ const localDateElement = localTimeContainer.querySelector('[data-date]');
|
|
|
+ const localWeekdayElement = localTimeContainer.querySelector('[data-weekday]');
|
|
|
+ const localYearElement = localTimeContainer.querySelector('[data-year]');
|
|
|
+ const timeZoneContainers = clock.querySelectorAll('[data-time-in-zone]');
|
|
|
+
|
|
|
+ const setLocalTime = makeSettableTimeElement(
|
|
|
+ localTimeContainer.querySelector('[data-time]'),
|
|
|
+ hourFormat
|
|
|
+ );
|
|
|
+
|
|
|
+ updateCallbacks.push((now) => {
|
|
|
+ setLocalTime(now);
|
|
|
+ localDateElement.textContent = now.getDate() + ' ' + monthNames[now.getMonth()];
|
|
|
+ localWeekdayElement.textContent = weekDayNames[now.getDay()];
|
|
|
+ localYearElement.textContent = now.getFullYear();
|
|
|
+ });
|
|
|
+
|
|
|
+ for (var z = 0; z < timeZoneContainers.length; z++) {
|
|
|
+ const timeZoneContainer = timeZoneContainers[z];
|
|
|
+ const diffElement = timeZoneContainer.querySelector('[data-time-diff]');
|
|
|
+
|
|
|
+ const setZoneTime = makeSettableTimeElement(
|
|
|
+ timeZoneContainer.querySelector('[data-time]'),
|
|
|
+ hourFormat
|
|
|
+ );
|
|
|
+
|
|
|
+ updateCallbacks.push((now) => {
|
|
|
+ const { time, diffInHours } = timeInZone(now, timeZoneContainer.dataset.timeInZone);
|
|
|
+ setZoneTime(time);
|
|
|
+ diffElement.textContent = (diffInHours <= 0 ? diffInHours : '+' + diffInHours) + 'h';
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const updateClocks = () => {
|
|
|
+ const now = new Date();
|
|
|
+
|
|
|
+ for (var i = 0; i < updateCallbacks.length; i++)
|
|
|
+ updateCallbacks[i](now);
|
|
|
+
|
|
|
+ setTimeout(updateClocks, (60 - now.getSeconds()) * 1000);
|
|
|
+ };
|
|
|
+
|
|
|
+ updateClocks();
|
|
|
}
|
|
|
|
|
|
async function setupPage() {
|