Skip to content

Commit 2735282

Browse files
authored
Merge the "release/v2.0.0" branch to the "main" branch
This merge integrates the release/v2.0.0 branch, introducing a modular architecture refactor and a user-configurable 12/24-hour format toggle. This represents a focused evolution in code organization and user control while maintaining the existing feature set and container infrastructure established in previous releases. The application codebase has been restructured from a single-file implementation into a modular ES6 architecture. The clock module now handles all time formatting and display logic, supporting both 12-hour format with AM/PM indicators and 24-hour format. The preferences module manages user settings through localStorage integration and coordinates toggle switch interactions. The existing logging functionality has been relocated into the module structure without changes to its behavior. This modular organization improves code maintainability and establishes clear separation of concerns. The new format toggle feature provides users with immediate control over time display preferences. A toggle switch positioned in the top-right corner enables seamless switching between 12-hour and 24-hour formats. The switch includes visual polish with smooth slider animations and hover effects. User preferences are automatically saved to localStorage, ensuring the selected format persists across browser sessions without requiring manual configuration on each visit. The index.html file has been updated to support ES6 module loading and includes the toggle switch markup. The stylesheet additions provide clean, accessible styling for the toggle interface with appropriate transition effects. Minor production readiness improvements include setting the DEBUG flag to false for production builds and adding CONTRIBUTING.md to the dockerignore file to optimize build context. This release maintains backward compatibility in terms of deployment and core functionality while establishing a foundation for future feature development through the modular architecture. The version bump to 2.0.0 reflects the architectural restructuring and introduction of user-configurable preferences as a new capability category.
2 parents 86ac2c3 + c90d33e commit 2735282

File tree

8 files changed

+333
-83
lines changed

8 files changed

+333
-83
lines changed

.dockerignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,7 @@ Dockerfile
1111
LICENSE
1212

1313
# README
14-
README.md
14+
README.md
15+
16+
# Contributing
17+
CONTRIBUTING.md

assets/clock-icon.svg

Lines changed: 1 addition & 5 deletions
Loading

index.html

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,25 @@
2020
</head>
2121
<!-- Starting the <body> element -->
2222
<body>
23+
<!-- Creating a container for the toggle -->
24+
<div id="toggle-container">
25+
<!-- Adding the toggle labels -->
26+
<label for="format-toggle" class="toggle-label">12</label>
27+
<!-- Adding the toggle switch -->
28+
<label class="switch">
29+
<!-- Adding the toggle input -->
30+
<input type="checkbox" id="format-toggle" aria-label="Toggle between 12 and 24 hour format">
31+
<!-- Adding the toggle slider -->
32+
<span class="slider"></span>
33+
</label>
34+
<!-- Adding the toggle labels -->
35+
<label for="format-toggle" class="toggle-label">24</label>
36+
</div>
2337
<!-- Creating a container for the clock -->
24-
<div id="clock-box">
38+
<main id="clock-box">
2539
<!-- Adding the clock element -->
2640
<h1 id="clock" aria-live="polite"></h1>
27-
</div>
41+
</main>
2842
<!-- Linking the JavaScript file -->
2943
<script type="module" src="index.js" defer></script>
3044
</body>

index.js

Lines changed: 12 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -4,77 +4,18 @@
44

55
// Import the log function from the logs module
66
import { log } from "./modules/logs/index.js";
7+
// Import the loadSavedMode and listenForModeChanges functions from the preferences module
8+
import { loadSavedMode, listenForModeChanges } from "./modules/preferences/index.js";
79

8-
/**
9-
* Starts the digital clock with the specified interval.
10-
* If no interval is specified, it defaults to 1000 milliseconds (1 second).
11-
* @param {number} [interval=1000] - The interval in milliseconds to update the clock.
12-
* @returns {number} - The interval ID returned by setInterval.
13-
*/
14-
function startClock(interval = 1000) {
15-
// Get the clock element from the DOM
16-
const clock = document.getElementById("clock");
17-
18-
/**
19-
* Updates the clock element with the current time.
20-
* @returns {void}
21-
*/
22-
function update() {
23-
// Get the current date and time
24-
const now = new Date();
25-
26-
// Get the 24 hour format
27-
const hours24 = now.getHours();
28-
// Convert to 12 hour format and pad with leading zeros
29-
const hours12 = String(hours24 % 12 || 12).padStart(2, "0");
30-
// Get minutes, padded with leading zeros
31-
const minutes = String(now.getMinutes()).padStart(2, "0");
32-
// Get seconds, padded with leading zeros
33-
const seconds = String(now.getSeconds()).padStart(2, "0");
34-
// Determine AM or PM
35-
const ampm = hours24 >= 12 ? "PM" : "AM";
36-
37-
// Log the updated time
38-
log("debug", `Updating clock: ${hours12}:${minutes}:${seconds} ${ampm}`);
39-
40-
// Update the clock element's text content
41-
clock.textContent = `${hours12}:${minutes}:${seconds} ${ampm}`;
42-
43-
// Log success message
44-
log("debug", "Clock updated successfully.");
45-
46-
// Log trace message with current time details
47-
log("trace", `Current Time - Hours: ${hours12}, Minutes: ${minutes}, Seconds: ${seconds}, AM/PM: ${ampm}`);
48-
}
10+
// Log initialization message
11+
log("info", "Initializing Digital Clock Program...");
4912

50-
// If the clock element is not found, log an error
51-
if(!clock){
52-
log("error", "Clock element not found in the DOM.");
53-
return;
54-
}
55-
// else if the interval is less than or equal to 0, log an error
56-
else if(interval <= 0){
57-
log("error", "Interval must be greater than 0.");
58-
return;
59-
}
60-
// else start the clock and update it at the specified interval
61-
else{
62-
// Log info message
63-
log("info", "Clock element found.");
64-
// Log starting message
65-
log("info", `Starting clock.`);
66-
// Initial
67-
update();
68-
// Log success message
69-
log("info", "Clock started successfully.");
70-
// Log trace message
71-
log("trace", `Clock will update every ${interval} milliseconds.`);
72-
// Set interval to update the clock every specified milliseconds
73-
return setInterval(update, interval);
74-
};
75-
}
13+
// logging debug message about checking for saved clock mode
14+
log("debug", "Checking for saved clock mode in client-side storage...");
15+
// Load the saved clock mode from client-side storage
16+
loadSavedMode();
7617

77-
// Log info initialization message
78-
log("info", "Initializing Digital Clock Program...");
79-
// Start the clock with default interval
80-
const intervalId = startClock();
18+
// logging debug message about setting up event listener for format toggle input
19+
log("debug", "Setting up event listener for format toggle input...");
20+
// Listen for changes to the format toggle input
21+
listenForModeChanges();

modules/clock/index.js

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// Digital Clock Program
2+
3+
// modules/clock/index.js
4+
5+
// Import the log function from the logs module
6+
import { log } from "../logs/index.js";
7+
8+
// Variable to store the current clock interval ID
9+
let currentClockID = null;
10+
11+
/**
12+
* Starts the clock with the specified interval.
13+
* @param {number} toggle_mode - The clock format to use, either 24 or 12.
14+
* @param {number} [interval=1000] - The interval at which to update the clock.
15+
* @returns {void}
16+
*/
17+
function startClock(toggle_mode, interval = 1000) {
18+
// Get the clock element from the DOM
19+
const clock = document.getElementById("clock");
20+
21+
/**
22+
* Updates the clock element with the current time based on the given time format.
23+
* If time_format is 24, the clock element's text content is updated with the 24 hour format.
24+
* If time_format is 12, the clock element's text content is updated with the 12 hour format.
25+
* @param {number} time_format - The clock format to use, either 24 or 12.
26+
* @returns {void}
27+
*/
28+
function update(time_format){
29+
// Get the current date and time
30+
const now = new Date();
31+
32+
// Extract hours
33+
const hours = now.getHours();
34+
// Extract minutes with leading zero
35+
const minutes = String(now.getMinutes()).padStart(2, "0");
36+
// Extract seconds with leading zero
37+
const seconds = String(now.getSeconds()).padStart(2, "0");
38+
// Initialize timeString variable to store formatted time
39+
let timeString = "";
40+
41+
// If time_format is 12, format time in 12 hour format
42+
if(time_format === 12){
43+
log("debug", "Formatting time in 12 hour format.");
44+
const hours12 = String(hours % 12 || 12).padStart(2, "0");
45+
const ampm = hours >= 12 ? "PM" : "AM";
46+
timeString = `${hours12}:${minutes}:${seconds} ${ampm}`;
47+
}
48+
// Else if time_format is 24, format time in 24 hour format
49+
else if(time_format === 24){
50+
log("debug", "Formatting time in 24 hour format.");
51+
const hours24 = String(hours).padStart(2, "0");
52+
timeString = `${hours24}:${minutes}:${seconds}`;
53+
}
54+
55+
log("debug", `Current time: ${timeString}`);
56+
// Update the clock element's text content with the formatted time
57+
clock.textContent = timeString;
58+
log("debug", "Time formatted and displayed on clock element.");
59+
log("trace", `Current time string: ${timeString}`);
60+
}
61+
62+
// If there is an existing clock interval, clear it
63+
if(currentClockID){
64+
clearInterval(currentClockID);
65+
log("info", "Cleared existing clock interval.");
66+
}
67+
// Else if there is no existing clock interval, log a debug message
68+
else if(!currentClockID){
69+
log("debug", "No existing clock interval found.");
70+
}
71+
// Else, log an error
72+
else{
73+
log("error", "Unexpected error checking existing clock interval.");
74+
}
75+
76+
// If the clock element is not found, log an error
77+
if(!clock){
78+
log("error", "Clock element not found in the DOM.");
79+
return;
80+
}
81+
// else if the interval is less than or equal to 0, log an error
82+
else if(interval <= 0){
83+
log("error", "Interval must be greater than 0.");
84+
return;
85+
}
86+
// else start the clock and update it at the specified interval
87+
else if(toggle_mode === 24){
88+
// Log success message
89+
log("info", "Clock element found.");
90+
// Log starting message
91+
log("info", `Starting clock with an interval of ${interval} milliseconds.`);
92+
// Log 24 hour format message
93+
log("info", "Using 24 hour format.");
94+
// Initial
95+
update(toggle_mode);
96+
// Set interval to update the clock every specified milliseconds
97+
currentClockID = setInterval(() => update(toggle_mode), interval);
98+
return;
99+
}
100+
else if(toggle_mode === 12){
101+
// Log success message
102+
log("info", "Clock element found.");
103+
// Log starting message
104+
log("info", `Starting clock with an interval of ${interval} milliseconds.`);
105+
// Log 12 hour format message
106+
log("info", "Using 12 hour format.");
107+
// Initial
108+
update(toggle_mode);
109+
// Set interval to update the clock every specified milliseconds
110+
currentClockID = setInterval(() => update(toggle_mode), interval);
111+
return;
112+
};
113+
};
114+
115+
// Export the startClock function
116+
export{
117+
startClock
118+
};

modules/logs/index.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const DEBUG = false;
1313
* @param {string} type - The type of the log message.
1414
* @param {string} message - The message to be logged.
1515
*/
16-
export function log(type, message){
16+
function log(type, message){
1717
// Get the current timestamp in ISO format
1818
const timestamp = new Date().toISOString();
1919

@@ -43,4 +43,9 @@ export function log(type, message){
4343
else{
4444
loglevel.console(`[${timestamp}] [${loglevel.label}]: ${message}`);
4545
}
46-
}
46+
}
47+
48+
// Export the log function
49+
export{
50+
log
51+
};

modules/preferences/index.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Digital Clock Program
2+
3+
// modules/preferences/index.js
4+
5+
// Import the log function from the logs module
6+
import { log } from "../logs/index.js";
7+
// Import the startClock function from the clock module
8+
import { startClock } from "../clock/index.js";
9+
10+
// Get the format toggle input element from the DOM
11+
const toggleInput = document.getElementById("format-toggle");
12+
// Store the clock mode in localStorage
13+
const savedMode = localStorage.getItem("clockMode");
14+
15+
/**
16+
* Loads the saved clock mode from client-side storage and starts the clock accordingly.
17+
* If savedMode is "24", sets the toggle input to checked and starts the clock in 24 hour mode.
18+
* If savedMode is "12", sets the toggle input to unchecked and starts the clock in 12 hour mode.
19+
* If savedMode is null or undefined, defaults to starting the clock in 12 hour mode.
20+
* Logs debug messages when loading the saved mode from client-side storage and when starting the clock in the corresponding mode.
21+
* Logs a trace message with the saved mode retrieved from client-side storage.
22+
*/
23+
function loadSavedMode(){
24+
log("debug", "Loading saved clock mode from client-side storage...");
25+
// if savedMode is "24", set the toggle input to checked and start the clock in 24 hour mode
26+
if(savedMode === "24"){
27+
log("debug", "Found client-side save: Loading 24h mode.");
28+
toggleInput.checked = true;
29+
startClock(24);
30+
log("trace", `Saved mode retrieved: ${savedMode}`);
31+
return;
32+
}
33+
// else if savedMode is "12", set the toggle input to unchecked and start the clock in 12 hour mode
34+
else if(savedMode === "12" || !savedMode){
35+
log("debug", "Found client-side save: Loading 12h mode.");
36+
toggleInput.checked = false;
37+
startClock(12);
38+
log("trace", `Saved mode retrieved: ${savedMode}`);
39+
return;
40+
}
41+
}
42+
43+
/**
44+
* Adds an event listener to the toggle input for changes.
45+
* If the toggle input is checked, starts the clock in 24 hour mode and saves the mode to client-side storage.
46+
* If the toggle input is unchecked, starts the clock in 12 hour mode and saves the mode to client-side storage.
47+
* If an unexpected toggle input state is encountered, logs an error.
48+
*/
49+
function listenForModeChanges(){
50+
// Add event listener to the toggle input for changes
51+
toggleInput.addEventListener("change", (info) => {
52+
// If the toggle input is checked, start the clock in 24 hour mode
53+
if(info.target.checked){
54+
log("debug", "Switching to 24 hour format.");
55+
localStorage.setItem("clockMode", "24");
56+
startClock(24);
57+
log("trace", `Toggled to ${info.target.checked}`);
58+
}
59+
// Else, start the clock in 12 hour mode
60+
else if(!info.target.checked){
61+
log("debug", "Switching to 12 hour format.");
62+
localStorage.setItem("clockMode", "12");
63+
startClock(12);
64+
log("trace", `Toggled to ${info.target.checked}`);
65+
}
66+
// Else, log an error
67+
else{
68+
log("error", "Unexpected toggle input state.");
69+
log("trace", `Toggled to ${info.target.checked}`);
70+
}
71+
});
72+
}
73+
74+
// Export the functions to be used in other modules
75+
export{
76+
loadSavedMode,
77+
listenForModeChanges
78+
};

0 commit comments

Comments
 (0)