horizontal-seasonal-hours-c.../clock.js

245 lines
7.3 KiB
JavaScript

const DEFAULT_OPTIONS = {showSeconds: true}
const HOUR_NAMES = [
"Candle", "Ice", "Comet", "Owl", "Yarn", "Mist",
"Sprout", "Rainbow", "Worm", "Rabbit", "Blossom", "Nest",
"Coral", "Cherry", "Bee", "Melon", "Seashell", "Dragon",
"Chestnut", "Kite", "Mushroom", "Lightning", "Mountain", "Lantern",
];
const HOUR_WIDTH = 70;
const HOUR_ICONS = [
"🕯️️", "❄️️", "☄️️", "🦉️", "🧶️", "🌫️️",
"🌱️", "🌈️", "🪱️", "🐇️", "🌸️", "🪺️",
"🪸️", "🍒️", "🐝️", "🍉️", "🐚️", "🐉️",
"🌰️", "🪁️", "🍄️", "⚡️️", "⛰️️", "🏮️",
];
const loadSettings = () => {
var loadedOpts;
try {
var data = localStorage.getItem("options");
console.debug("Loaded", data);
loadedOpts = JSON.parse(data);
} catch (e) {
loadedOpts = null;
}
console.debug("Parsed as", loadedOpts);
return loadedOpts || DEFAULT_OPTIONS;
};
const saveSettings = () => {
console.debug("Saving", options)
localStorage.setItem("options", JSON.stringify(options));
};
const zeroPad = (num, numZeros) => {
if (num == 0) {
return "".padStart(numZeros, "0")
}
var an = Math.abs (num);
var digitCount = 1 + Math.floor (Math.log (an) / Math.LN10);
if (digitCount >= numZeros) {
return String(num);
}
var zeroString = Math.pow (10, numZeros - digitCount).toString ().substr (1);
return num < 0 ? "-" + zeroString + an : zeroString + an;
};
const updateClock = () => {
var docCenter = document.body.offsetWidth / 2;
var momentNow = moment();
var momentUTC = momentNow.utc();
var utcHour = momentUTC.hours();
var utcMinute = momentUTC.minutes();
var momentLocal = momentNow.tz(options.timezone);
var localHour = momentLocal.hours();
var localMinute = momentLocal.minutes();
currentTimeContainer.innerHTML = (
HOUR_ICONS[utcHour]
+ "<br>"
+ momentLocal.locale(options.locale).format(options.showSeconds ? "LTS" : "LT")
+ "<br>"
+ HOUR_NAMES[utcHour]
);
var utcOffset = (
24 * HOUR_WIDTH
+ utcHour * HOUR_WIDTH
+ utcMinute * HOUR_WIDTH / 60
);
var localOffset = (
24 * HOUR_WIDTH
+ localHour * HOUR_WIDTH
+ localMinute * HOUR_WIDTH / 60
);
utcHourContainer.style.left = (docCenter - utcOffset - HOUR_WIDTH / 2) + "px";
hourNameContainer.style.left = (docCenter - utcOffset) + "px";
hourIconContainer.style.left = (docCenter - utcOffset) + "px";
localHourContainer.style.left = (docCenter - localOffset - HOUR_WIDTH / 2) + "px";
marker.style.left = docCenter + "px";
for (var nameSpan of document.getElementsByClassName("active")) {
nameSpan.classList.remove("active");
}
var currentNameSpan = document.getElementById("h-present-" + utcHour);
currentNameSpan.classList.add("active");
};
const showSettingsPanel = () => {
settingsPanel.style.display = "block";
};
const hideSettingsPanel = () => {
settingsPanel.style.display = "none";
};
const createClock = () => {
for (round = 0; round < 3; round++) {
let prefix;
switch (round) {
case 0:
prefix = "past";
break;
case 1:
prefix = "present";
break;
case 2:
prefix = "future";
break;
}
for (hour = 0; hour < 24; hour++) {
var nameClass;
if (hour < 6) {
nameClass = "winter";
} else if (hour < 12) {
nameClass = "spring";
} else if (hour < 18) {
nameClass = "summer";
} else {
nameClass = "autumn";
}
let utcSpan = document.createElement("span");
utcSpan.id = "u-" + prefix + "-" + hour;
utcSpan.innerHTML = "U " + zeroPad(hour, 2);
utcHourContainer.appendChild(utcSpan);
let localSpan = document.createElement("span");
localSpan.id = "l-" + prefix + "-" + hour;
localSpan.innerHTML = zeroPad(hour, 2);
localHourContainer.appendChild(localSpan);
let hourNameSpan = document.createElement("span");
hourNameSpan.id = "h-" + prefix + "-" + hour;
hourNameSpan.classList.add(nameClass);
hourNameSpan.innerHTML = HOUR_NAMES[hour];
hourNameContainer.appendChild(hourNameSpan);
let hourIconSpan = document.createElement("span");
hourIconSpan.id = "i-" + prefix + "-" + hour;
hourIconSpan.classList.add(nameClass);
hourIconSpan.innerHTML = HOUR_ICONS[hour];
hourIconContainer.appendChild(hourIconSpan);
}
}
};
const initSettings = () => {
var timeZoneSelector = document.getElementById("timezone-selector");
if (!options.timezone) {
options.timezone = moment.tz.guess();
}
for (tzname of moment.tz.names()) {
var tzElem = document.createElement("option");
tzElem.innerHTML = tzname;
if (tzname == options.timezone) {
tzElem.selected = true;
}
timeZoneSelector.appendChild(tzElem);
}
timeZoneSelector.addEventListener("change", () => {
options.timezone = timeZoneSelector.value;
console.log(options)
updateClock();
saveSettings();
})
var localeSelector = document.getElementById("locale-selector");
if (!options.locale) {
options.locale = moment.locale();
}
for (localename of moment.locales()) {
var locElem = document.createElement("option");
locElem.innerHTML = localename;
if (localename == options.locale) {
locElem.selected = true;
}
localeSelector.appendChild(locElem);
}
localeSelector.addEventListener("change", () => {
options.locale = localeSelector.value;
updateClock();
saveSettings();
});
var showSecondsOption = document.getElementById("show-seconds-option");
showSecondsOption.checked = options.showSeconds;
showSecondsOption.addEventListener("click", () => {
options.showSeconds = showSecondsOption.checked;
updateClock();
saveSettings();
});
showSettingsButton.addEventListener("click", showSettingsPanel);
closeSettingsButton.addEventListener("click", hideSettingsPanel);
}
const run = () => {
document.documentElement.style.setProperty("--hour-width", HOUR_WIDTH + "px");
createClock();
initSettings();
addEventListener("resize", updateClock);
updateClock();
setInterval(updateClock, 1000);
}
var options = loadSettings();
let utcHourContainer = document.getElementById("utc-hours-inner");
let hourNameContainer = document.getElementById("hour-names-inner");
let hourIconContainer = document.getElementById("hour-icons-inner");
let localHourContainer = document.getElementById("local-hours-inner");
let currentTimeContainer = document.getElementById("current-time");
let showSettingsButton = document.getElementById("settings-button");
let closeSettingsButton = document.getElementById("settings-close");
let settingsPanel = document.getElementById("settings-wrapper")
let marker = document.getElementById("marker");
run();