From 7b18208092fe318d30f9ba813a1300a7b6edf543 Mon Sep 17 00:00:00 2001 From: Roshan Bhagtani Date: Sun, 26 Oct 2025 21:15:11 +0530 Subject: [PATCH] feat: Add reset button and light/dark mode toggle --- incrementing-counter/index.html | 37 +++++++++------ incrementing-counter/script.js | 82 +++++++++++++++++++++++++++------ incrementing-counter/style.css | 64 +++++++++++++++++++++++-- 3 files changed, 152 insertions(+), 31 deletions(-) diff --git a/incrementing-counter/index.html b/incrementing-counter/index.html index 8bab33f..8204b21 100644 --- a/incrementing-counter/index.html +++ b/incrementing-counter/index.html @@ -8,23 +8,30 @@ Increment Counter -
- -
- Twitter Followers -
+ -
- -
- YouTube Subscribers -
+
+
+ +
+ Twitter Followers +
+ +
+ +
+ YouTube Subscribers +
-
- -
- Facebook Fans +
+ +
+ Facebook Fans +
+ + + - + \ No newline at end of file diff --git a/incrementing-counter/script.js b/incrementing-counter/script.js index 1bb0837..3fa4e06 100644 --- a/incrementing-counter/script.js +++ b/incrementing-counter/script.js @@ -1,21 +1,77 @@ const counters = document.querySelectorAll('.counter') +const resetBtn = document.getElementById('reset-btn'); +const themeToggle = document.getElementById('theme-toggle'); // Select the toggle button +const body = document.body; -counters.forEach(counter => { - counter.innerText = '0' +// The main function that starts the counter animation +function startCounter() { + counters.forEach(counter => { + // Clear any running timers + if (counter.timer) { + clearTimeout(counter.timer); + } + + // Reset the inner text to '0' before starting + counter.innerText = '0'; + + const updateCounter = () => { + const target = +counter.getAttribute('data-target') + const c = +counter.innerText + const increment = target / 200 + + if(c < target) { + // Update the text and schedule the next update + counter.innerText = `${Math.ceil(c + increment)}` + counter.timer = setTimeout(updateCounter, 1) // Store the timer ID + } else { + // Set the final target value + counter.innerText = target + } + } + + // Start the animation for the current counter + updateCounter() + }) +} - const updateCounter = () => { - const target = +counter.getAttribute('data-target') - const c = +counter.innerText - const increment = target / 200 +// --- Reset Logic --- - if(c < target) { - counter.innerText = `${Math.ceil(c + increment)}` - setTimeout(updateCounter, 1) - } else { - counter.innerText = target +function resetCounters() { + counters.forEach(counter => { + // 1. Stop any current animations + if (counter.timer) { + clearTimeout(counter.timer); } + + // 2. Reset the display value to zero + counter.innerText = '0'; + }); + + // 3. Restart the entire animation process after a short delay + setTimeout(startCounter, 50); +} + + +// --- Theme Toggle Logic --- + +themeToggle.addEventListener('click', () => { + // Toggle the dark-mode class on the body element + body.classList.toggle('dark-mode'); + + // Change the button icon for better UI feedback + if (body.classList.contains('dark-mode')) { + themeToggle.innerText = '☀️'; // Change to Sun icon for light mode + } else { + themeToggle.innerText = '🌙'; // Change to Moon icon for dark mode } +}); + + +// --- Event Listeners and Initial Run --- + +// Start the animation when the page loads +startCounter(); - updateCounter() -}) \ No newline at end of file +// Listen for the reset button click +resetBtn.addEventListener('click', resetCounters); \ No newline at end of file diff --git a/incrementing-counter/style.css b/incrementing-counter/style.css index 082d1fd..9a8a8a1 100644 --- a/incrementing-counter/style.css +++ b/incrementing-counter/style.css @@ -5,17 +5,37 @@ } body { + /* LIGHT MODE DEFAULTS */ background-color: #8e44ad; color: #fff; font-family: 'Roboto Mono', sans-serif; display: flex; + flex-direction: column; align-items: center; justify-content: center; height: 100vh; overflow: hidden; margin: 0; + transition: background-color 0.3s, color 0.3s; /* Smooth transition */ } +/* --- DARK MODE STYLES --- */ +body.dark-mode { + background-color: #1a1a1a; + color: #f1c40f; /* Yellow text for dark mode contrast */ +} + +body.dark-mode .btn { + background-color: #f1c40f; /* Yellow button */ + color: #1a1a1a; +} + +body.dark-mode .btn:hover { + background-color: #e6b908; +} +/* --- End Dark Mode Styles --- */ + + .counter-container { display: flex; flex-direction: column; @@ -29,8 +49,46 @@ body { margin-top: 10px; } +/* --- Button Styles --- */ +.btn { + background-color: #47bcf3; + color: white; + border: none; + padding: 10px 20px; + margin-top: 20px; + border-radius: 5px; + font-size: 1rem; + cursor: pointer; + transition: transform 0.1s ease, background-color 0.3s ease; +} + +.btn:active { + transform: scale(0.95); +} + +.btn:hover { + background-color: #38a5d3; +} + +/* --- Theme Toggle Button Styles --- */ +.theme-toggle { + position: absolute; + top: 20px; + right: 20px; + margin: 0; /* Override margin-top */ + width: 50px; + height: 50px; + border-radius: 50%; + font-size: 1.5rem; + padding: 0; + line-height: 50px; /* Center icon vertically */ + z-index: 10; +} +/* --- End Theme Toggle Styles --- */ + + @media (max-width: 580px) { - body { - flex-direction: column; + .counter-container { + margin: 15px; } -} +} \ No newline at end of file