- Item 10: Convert to ES modules with import/export, single module entry point - Item 11: Replace inline styles with CSS classes (background overlay, card animations, highlight effect, config modal form elements) - Item 12: Move ConfigManager modal HTML from JS template literal to <template> element in index.html - Item 13: Replace deprecated url.parse() with new URL() in server.js and update route handlers to use searchParams - Item 14: Replace JSON.parse/stringify deep clone with structuredClone() - Item 15: Remove dead JSON-fixing regex code from departures.js route Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
169 lines
5.1 KiB
JavaScript
169 lines
5.1 KiB
JavaScript
/**
|
|
* clock.js - A modular clock component for displaying time and date
|
|
* Specifically configured for Stockholm, Sweden timezone
|
|
*/
|
|
|
|
class Clock {
|
|
constructor(options = {}) {
|
|
// Default options
|
|
this.options = {
|
|
elementId: 'clock',
|
|
timeFormat: 'HH:MM:SS',
|
|
dateFormat: 'WEEKDAY, MONTH DAY, YEAR',
|
|
timezone: 'Europe/Stockholm',
|
|
updateInterval: 1000, // Update every second
|
|
enableTimeSync: false, // Disable time sync by default to avoid CORS issues with local files
|
|
...options
|
|
};
|
|
|
|
this.element = document.getElementById(this.options.elementId);
|
|
if (!this.element) {
|
|
console.error(`Clock element with ID "${this.options.elementId}" not found`);
|
|
return;
|
|
}
|
|
|
|
// Create DOM structure
|
|
this.createClockElements();
|
|
|
|
// Start the clock
|
|
this.start();
|
|
|
|
// Sync with time server once a day (if enabled)
|
|
if (this.options.enableTimeSync) {
|
|
this.setupTimeSync();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create the DOM elements for the clock
|
|
*/
|
|
createClockElements() {
|
|
// Create container with appropriate styling
|
|
this.element.classList.add('clock-container');
|
|
|
|
// Create time element
|
|
this.timeElement = document.createElement('div');
|
|
this.timeElement.classList.add('clock-time');
|
|
this.element.appendChild(this.timeElement);
|
|
|
|
// Create a separate date element
|
|
this.dateElement = document.createElement('div');
|
|
this.dateElement.classList.add('clock-date');
|
|
this.element.appendChild(this.dateElement);
|
|
}
|
|
|
|
/**
|
|
* Start the clock with the specified update interval
|
|
*/
|
|
start() {
|
|
// Update immediately
|
|
this.update();
|
|
|
|
// Set interval for updates
|
|
this.intervalId = setInterval(() => this.update(), this.options.updateInterval);
|
|
}
|
|
|
|
/**
|
|
* Stop the clock
|
|
*/
|
|
stop() {
|
|
if (this.intervalId) {
|
|
clearInterval(this.intervalId);
|
|
this.intervalId = null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update the clock display
|
|
*/
|
|
update() {
|
|
const now = new Date();
|
|
|
|
// Format and display the time
|
|
this.timeElement.innerHTML = this.formatTime(now);
|
|
|
|
// Format and display the date (with a separator)
|
|
this.dateElement.textContent = " • " + this.formatDate(now);
|
|
|
|
// Make sure the date element is visible and inline
|
|
this.dateElement.style.display = 'inline-block';
|
|
}
|
|
|
|
/**
|
|
* Format the time according to the specified format
|
|
* @param {Date} date - The date object to format
|
|
* @returns {string} - The formatted time string
|
|
*/
|
|
formatTime(date) {
|
|
const options = {
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
second: '2-digit',
|
|
hour12: false,
|
|
timeZone: this.options.timezone
|
|
};
|
|
|
|
return date.toLocaleTimeString('sv-SE', options);
|
|
}
|
|
|
|
/**
|
|
* Format the date according to the specified format
|
|
* @param {Date} date - The date object to format
|
|
* @returns {string} - The formatted date string
|
|
*/
|
|
formatDate(date) {
|
|
const options = {
|
|
weekday: 'long',
|
|
year: 'numeric',
|
|
month: 'long',
|
|
day: 'numeric',
|
|
timeZone: this.options.timezone
|
|
};
|
|
|
|
return date.toLocaleDateString('sv-SE', options);
|
|
}
|
|
|
|
/**
|
|
* Set up time synchronization with a time server
|
|
* This will sync the time once a day to ensure accuracy
|
|
*/
|
|
setupTimeSync() {
|
|
// Function to sync time
|
|
const syncTime = async () => {
|
|
try {
|
|
// Check if we're running from a local file (which would cause CORS issues)
|
|
if (window.location.protocol === 'file:') {
|
|
console.log('Running from local file, skipping time sync to avoid CORS issues');
|
|
return;
|
|
}
|
|
|
|
// Use the WorldTimeAPI to get the current time for Stockholm
|
|
const response = await fetch('https://worldtimeapi.org/api/timezone/Europe/Stockholm');
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! Status: ${response.status}`);
|
|
}
|
|
|
|
const data = await response.json();
|
|
console.log('Time synced with WorldTimeAPI:', data);
|
|
|
|
// The API already returns the time in the correct timezone
|
|
// We just log it for verification purposes
|
|
} catch (error) {
|
|
console.log('Time sync skipped:', error.message);
|
|
}
|
|
};
|
|
|
|
// Sync immediately on load
|
|
syncTime();
|
|
|
|
// Then sync once a day (86400000 ms = 24 hours)
|
|
setInterval(syncTime, 86400000);
|
|
}
|
|
}
|
|
|
|
// ES module export
|
|
export { Clock };
|
|
|
|
// Keep window reference for backward compatibility
|
|
window.Clock = Clock;
|