philipp-zettl commited on
Commit
009105c
·
verified ·
1 Parent(s): 82a58cc

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +244 -57
index.html CHANGED
@@ -3,7 +3,7 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Modern Countdown Timer</title>
7
  <script src="https://cdn.tailwindcss.com"></script>
8
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
  <style>
@@ -81,6 +81,30 @@
81
  border-color: #667eea;
82
  box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.2);
83
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  </style>
85
  </head>
86
  <body class="min-h-screen text-gray-800 font-sans">
@@ -89,7 +113,7 @@
89
  <div id="main-page" class="text-center max-w-3xl mx-auto">
90
  <div class="glass-card p-8 mb-8">
91
  <h1 class="text-4xl font-bold mb-4 text-gray-800">Countdown Timer</h1>
92
- <p class="text-lg text-gray-600 mb-8">Create and share beautiful countdowns with custom durations and animations</p>
93
 
94
  <form id="countdown-form" class="space-y-6">
95
  <div class="text-left">
@@ -98,26 +122,49 @@
98
  class="input-field w-full px-4 py-3 rounded-lg bg-white">
99
  </div>
100
 
101
- <div class="grid grid-cols-2 md:grid-cols-4 gap-4">
102
- <div class="text-left">
103
- <label for="days" class="block mb-2 text-gray-700">Days</label>
104
- <input type="number" id="days" min="0" value="0"
105
- class="input-field w-full px-4 py-3 rounded-lg bg-white">
106
- </div>
107
- <div class="text-left">
108
- <label for="hours" class="block mb-2 text-gray-700">Hours</label>
109
- <input type="number" id="hours" min="0" max="23" value="0"
110
- class="input-field w-full px-4 py-3 rounded-lg bg-white">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  </div>
 
 
 
112
  <div class="text-left">
113
- <label for="minutes" class="block mb-2 text-gray-700">Minutes</label>
114
- <input type="number" id="minutes" min="0" max="59" value="10"
115
- class="input-field w-full px-4 py-3 rounded-lg bg-white">
 
116
  </div>
117
- <div class="text-left">
118
- <label for="seconds" class="block mb-2 text-gray-700">Seconds</label>
119
- <input type="number" id="seconds" min="0" max="59" value="0"
120
- class="input-field w-full px-4 py-3 rounded-lg bg-white">
 
 
121
  </div>
122
  </div>
123
 
@@ -152,10 +199,10 @@
152
  <div class="glass-card p-6">
153
  <h2 class="text-2xl font-semibold mb-4 text-gray-800">How to Use</h2>
154
  <div class="text-left space-y-2 text-gray-600">
155
- <p>1. Set your countdown duration using days, hours, minutes and seconds</p>
156
  <p>2. Add a title and choose a finish animation</p>
157
  <p>3. Share the URL with others - all settings are included</p>
158
- <p class="mt-4 font-medium">Example URL: <code class="bg-gray-100 px-2 py-1 rounded">?title=New+Year&days=30&hours=12&animation=fireworks</code></p>
159
  </div>
160
  </div>
161
  </div>
@@ -184,6 +231,10 @@
184
  </div>
185
  </div>
186
 
 
 
 
 
187
  <div id="finished-message" class="hidden text-2xl font-bold mb-6">
188
  <div class="inline-block px-6 py-3 bg-indigo-600 text-white rounded-full">
189
  Time's Up!
@@ -199,20 +250,78 @@
199
 
200
  <script>
201
  document.addEventListener('DOMContentLoaded', function() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
202
  // Check URL parameters
203
  const urlParams = new URLSearchParams(window.location.search);
204
- const hasParams = urlParams.has('days') || urlParams.has('hours') || urlParams.has('minutes') || urlParams.has('seconds');
 
205
 
206
- if (hasParams) {
207
- // Start countdown from URL params
208
  const title = urlParams.get('title') || 'Countdown';
209
- const days = parseInt(urlParams.get('days')) || 0;
210
- const hours = parseInt(urlParams.get('hours')) || 0;
211
- const minutes = parseInt(urlParams.get('minutes')) || 0;
212
- const seconds = parseInt(urlParams.get('seconds')) || 0;
213
  const animation = urlParams.get('animation') || 'fireworks';
214
 
215
- startCountdown(title, days, hours, minutes, seconds, animation);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
  }
217
 
218
  // Form submission
@@ -221,24 +330,74 @@
221
  e.preventDefault();
222
 
223
  const title = document.getElementById('title').value || 'Countdown';
224
- const days = parseInt(document.getElementById('days').value) || 0;
225
- const hours = parseInt(document.getElementById('hours').value) || 0;
226
- const minutes = parseInt(document.getElementById('minutes').value) || 0;
227
- const seconds = parseInt(document.getElementById('seconds').value) || 0;
228
  const animation = document.querySelector('input[name="animation"]:checked').value;
229
 
230
- // Update URL with parameters
231
- const params = new URLSearchParams();
232
- if (title !== 'Countdown') params.set('title', title);
233
- if (days > 0) params.set('days', days);
234
- if (hours > 0) params.set('hours', hours);
235
- if (minutes > 0) params.set('minutes', minutes);
236
- if (seconds > 0) params.set('seconds', seconds);
237
- params.set('animation', animation);
238
 
239
- window.history.pushState({}, '', `?${params.toString()}`);
240
-
241
- startCountdown(title, days, hours, minutes, seconds, animation);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
242
  });
243
 
244
  // New countdown button
@@ -248,31 +407,59 @@
248
  document.getElementById('countdown-page').classList.add('hidden');
249
  clearInterval(window.countdownInterval);
250
  document.getElementById('finished-message').classList.add('hidden');
 
251
  });
252
  });
253
 
254
- function startCountdown(title, days, hours, minutes, seconds, animationType) {
255
  // Switch to countdown page
256
  document.getElementById('main-page').classList.add('hidden');
257
  document.getElementById('countdown-page').classList.remove('hidden');
258
  document.getElementById('countdown-title').textContent = title;
259
  document.getElementById('finished-message').classList.add('hidden');
260
 
261
- // Calculate total seconds
262
- let totalSeconds = days * 86400 + hours * 3600 + minutes * 60 + seconds;
 
 
 
 
 
 
 
 
 
 
 
263
 
264
  // Start the countdown
265
  updateCountdownDisplay(totalSeconds);
266
 
267
- window.countdownInterval = setInterval(function() {
268
- totalSeconds--;
269
- updateCountdownDisplay(totalSeconds);
270
-
271
- if (totalSeconds <= 0) {
272
- clearInterval(window.countdownInterval);
273
- countdownFinished(animationType);
274
- }
275
- }, 1000);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
276
  }
277
 
278
  function updateCountdownDisplay(totalSeconds) {
@@ -364,5 +551,5 @@
364
  }
365
  }
366
  </script>
367
- <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=philipp-zettl/static-countdown" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
368
  </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Advanced Countdown Timer</title>
7
  <script src="https://cdn.tailwindcss.com"></script>
8
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
  <style>
 
81
  border-color: #667eea;
82
  box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.2);
83
  }
84
+ .tab-btn {
85
+ transition: all 0.3s ease;
86
+ border-bottom: 3px solid transparent;
87
+ }
88
+ .tab-btn.active {
89
+ border-bottom-color: #667eea;
90
+ color: #667eea;
91
+ font-weight: 600;
92
+ }
93
+ .datetime-input {
94
+ position: relative;
95
+ }
96
+ .datetime-input::-webkit-calendar-picker-indicator {
97
+ background: transparent;
98
+ bottom: 0;
99
+ color: transparent;
100
+ cursor: pointer;
101
+ height: auto;
102
+ left: 0;
103
+ position: absolute;
104
+ right: 0;
105
+ top: 0;
106
+ width: auto;
107
+ }
108
  </style>
109
  </head>
110
  <body class="min-h-screen text-gray-800 font-sans">
 
113
  <div id="main-page" class="text-center max-w-3xl mx-auto">
114
  <div class="glass-card p-8 mb-8">
115
  <h1 class="text-4xl font-bold mb-4 text-gray-800">Countdown Timer</h1>
116
+ <p class="text-lg text-gray-600 mb-8">Create countdowns by selecting a future date or setting duration</p>
117
 
118
  <form id="countdown-form" class="space-y-6">
119
  <div class="text-left">
 
122
  class="input-field w-full px-4 py-3 rounded-lg bg-white">
123
  </div>
124
 
125
+ <div class="flex border-b border-gray-200 mb-6">
126
+ <button type="button" id="duration-tab" class="tab-btn active py-2 px-4">Duration</button>
127
+ <button type="button" id="datetime-tab" class="tab-btn py-2 px-4">Date & Time</button>
128
+ </div>
129
+
130
+ <div id="duration-inputs">
131
+ <div class="grid grid-cols-2 md:grid-cols-4 gap-4">
132
+ <div class="text-left">
133
+ <label for="days" class="block mb-2 text-gray-700">Days</label>
134
+ <input type="number" id="days" min="0" value="0"
135
+ class="input-field w-full px-4 py-3 rounded-lg bg-white">
136
+ </div>
137
+ <div class="text-left">
138
+ <label for="hours" class="block mb-2 text-gray-700">Hours</label>
139
+ <input type="number" id="hours" min="0" max="23" value="0"
140
+ class="input-field w-full px-4 py-3 rounded-lg bg-white">
141
+ </div>
142
+ <div class="text-left">
143
+ <label for="minutes" class="block mb-2 text-gray-700">Minutes</label>
144
+ <input type="number" id="minutes" min="0" max="59" value="10"
145
+ class="input-field w-full px-4 py-3 rounded-lg bg-white">
146
+ </div>
147
+ <div class="text-left">
148
+ <label for="seconds" class="block mb-2 text-gray-700">Seconds</label>
149
+ <input type="number" id="seconds" min="0" max="59" value="0"
150
+ class="input-field w-full px-4 py-3 rounded-lg bg-white">
151
+ </div>
152
  </div>
153
+ </div>
154
+
155
+ <div id="datetime-inputs" class="hidden">
156
  <div class="text-left">
157
+ <label for="target-datetime" class="block mb-2 text-gray-700">Target Date & Time</label>
158
+ <input type="datetime-local" id="target-datetime"
159
+ class="datetime-input input-field w-full px-4 py-3 rounded-lg bg-white"
160
+ min="">
161
  </div>
162
+ <div class="mt-4 text-left">
163
+ <label for="timezone" class="block mb-2 text-gray-700">Timezone</label>
164
+ <select id="timezone" class="input-field w-full px-4 py-3 rounded-lg bg-white">
165
+ <option value="local">Local Time</option>
166
+ <option value="utc">UTC</option>
167
+ </select>
168
  </div>
169
  </div>
170
 
 
199
  <div class="glass-card p-6">
200
  <h2 class="text-2xl font-semibold mb-4 text-gray-800">How to Use</h2>
201
  <div class="text-left space-y-2 text-gray-600">
202
+ <p>1. Choose between setting a duration or selecting a specific future date/time</p>
203
  <p>2. Add a title and choose a finish animation</p>
204
  <p>3. Share the URL with others - all settings are included</p>
205
+ <p class="mt-4 font-medium">Example URL: <code class="bg-gray-100 px-2 py-1 rounded">?title=New+Year&target=2024-01-01T00:00&timezone=utc&animation=fireworks</code></p>
206
  </div>
207
  </div>
208
  </div>
 
231
  </div>
232
  </div>
233
 
234
+ <div id="target-time-display" class="text-gray-600 mb-4">
235
+ Counting down to: <span id="target-time" class="font-medium"></span>
236
+ </div>
237
+
238
  <div id="finished-message" class="hidden text-2xl font-bold mb-6">
239
  <div class="inline-block px-6 py-3 bg-indigo-600 text-white rounded-full">
240
  Time's Up!
 
250
 
251
  <script>
252
  document.addEventListener('DOMContentLoaded', function() {
253
+ // Set min datetime to now
254
+ const now = new Date();
255
+ const timezoneOffset = now.getTimezoneOffset() * 60000;
256
+ const localISOTime = new Date(now - timezoneOffset).toISOString().slice(0, 16);
257
+ document.getElementById('target-datetime').min = localISOTime;
258
+
259
+ // Tab switching
260
+ const durationTab = document.getElementById('duration-tab');
261
+ const datetimeTab = document.getElementById('datetime-tab');
262
+ const durationInputs = document.getElementById('duration-inputs');
263
+ const datetimeInputs = document.getElementById('datetime-inputs');
264
+
265
+ durationTab.addEventListener('click', function() {
266
+ durationTab.classList.add('active');
267
+ datetimeTab.classList.remove('active');
268
+ durationInputs.classList.remove('hidden');
269
+ datetimeInputs.classList.add('hidden');
270
+ });
271
+
272
+ datetimeTab.addEventListener('click', function() {
273
+ datetimeTab.classList.add('active');
274
+ durationTab.classList.remove('active');
275
+ datetimeInputs.classList.remove('hidden');
276
+ durationInputs.classList.add('hidden');
277
+ });
278
+
279
  // Check URL parameters
280
  const urlParams = new URLSearchParams(window.location.search);
281
+ const hasDurationParams = urlParams.has('days') || urlParams.has('hours') || urlParams.has('minutes') || urlParams.has('seconds');
282
+ const hasDatetimeParam = urlParams.has('target');
283
 
284
+ if (hasDurationParams || hasDatetimeParam) {
 
285
  const title = urlParams.get('title') || 'Countdown';
 
 
 
 
286
  const animation = urlParams.get('animation') || 'fireworks';
287
 
288
+ if (hasDatetimeParam) {
289
+ // Start countdown from datetime
290
+ const target = urlParams.get('target');
291
+ const timezone = urlParams.get('timezone') || 'local';
292
+
293
+ // Switch to datetime tab
294
+ datetimeTab.click();
295
+
296
+ // Set the datetime input
297
+ document.getElementById('target-datetime').value = target;
298
+ document.getElementById('timezone').value = timezone;
299
+
300
+ // Calculate time remaining
301
+ const targetDate = new Date(target);
302
+ const now = new Date();
303
+ let diffInSeconds = Math.floor((targetDate - now) / 1000);
304
+
305
+ if (diffInSeconds > 0) {
306
+ startCountdown(title, diffInSeconds, animation, targetDate, timezone);
307
+ } else {
308
+ // If time is in the past, show finished state
309
+ document.getElementById('main-page').classList.add('hidden');
310
+ document.getElementById('countdown-page').classList.remove('hidden');
311
+ document.getElementById('countdown-title').textContent = title;
312
+ document.getElementById('finished-message').classList.remove('hidden');
313
+ countdownFinished(animation);
314
+ }
315
+ } else {
316
+ // Start countdown from duration params
317
+ const days = parseInt(urlParams.get('days')) || 0;
318
+ const hours = parseInt(urlParams.get('hours')) || 0;
319
+ const minutes = parseInt(urlParams.get('minutes')) || 0;
320
+ const seconds = parseInt(urlParams.get('seconds')) || 0;
321
+
322
+ const totalSeconds = days * 86400 + hours * 3600 + minutes * 60 + seconds;
323
+ startCountdown(title, totalSeconds, animation);
324
+ }
325
  }
326
 
327
  // Form submission
 
330
  e.preventDefault();
331
 
332
  const title = document.getElementById('title').value || 'Countdown';
 
 
 
 
333
  const animation = document.querySelector('input[name="animation"]:checked').value;
334
 
335
+ // Check which tab is active
336
+ const isDurationTabActive = durationTab.classList.contains('active');
 
 
 
 
 
 
337
 
338
+ if (isDurationTabActive) {
339
+ // Duration mode
340
+ const days = parseInt(document.getElementById('days').value) || 0;
341
+ const hours = parseInt(document.getElementById('hours').value) || 0;
342
+ const minutes = parseInt(document.getElementById('minutes').value) || 0;
343
+ const seconds = parseInt(document.getElementById('seconds').value) || 0;
344
+
345
+ const totalSeconds = days * 86400 + hours * 3600 + minutes * 60 + seconds;
346
+
347
+ // Update URL with parameters
348
+ const params = new URLSearchParams();
349
+ if (title !== 'Countdown') params.set('title', title);
350
+ if (days > 0) params.set('days', days);
351
+ if (hours > 0) params.set('hours', hours);
352
+ if (minutes > 0) params.set('minutes', minutes);
353
+ if (seconds > 0) params.set('seconds', seconds);
354
+ params.set('animation', animation);
355
+
356
+ window.history.pushState({}, '', `?${params.toString()}`);
357
+
358
+ startCountdown(title, totalSeconds, animation);
359
+ } else {
360
+ // Datetime mode
361
+ const targetDatetime = document.getElementById('target-datetime').value;
362
+ const timezone = document.getElementById('timezone').value;
363
+
364
+ if (!targetDatetime) {
365
+ alert('Please select a future date and time');
366
+ return;
367
+ }
368
+
369
+ // Calculate time remaining
370
+ let targetDate = new Date(targetDatetime);
371
+ const now = new Date();
372
+ let diffInSeconds = Math.floor((targetDate - now) / 1000);
373
+
374
+ if (diffInSeconds <= 0) {
375
+ alert('Please select a time in the future');
376
+ return;
377
+ }
378
+
379
+ // Format target date for URL
380
+ let targetForUrl;
381
+ if (timezone === 'utc') {
382
+ targetForUrl = targetDate.toISOString().slice(0, 16);
383
+ } else {
384
+ // Local time - need to adjust for timezone offset
385
+ const timezoneOffset = now.getTimezoneOffset() * 60000;
386
+ const localISOTime = new Date(targetDate.getTime() - timezoneOffset).toISOString().slice(0, 16);
387
+ targetForUrl = localISOTime;
388
+ }
389
+
390
+ // Update URL with parameters
391
+ const params = new URLSearchParams();
392
+ if (title !== 'Countdown') params.set('title', title);
393
+ params.set('target', targetForUrl);
394
+ params.set('timezone', timezone);
395
+ params.set('animation', animation);
396
+
397
+ window.history.pushState({}, '', `?${params.toString()}`);
398
+
399
+ startCountdown(title, diffInSeconds, animation, targetDate, timezone);
400
+ }
401
  });
402
 
403
  // New countdown button
 
407
  document.getElementById('countdown-page').classList.add('hidden');
408
  clearInterval(window.countdownInterval);
409
  document.getElementById('finished-message').classList.add('hidden');
410
+ document.getElementById('target-time-display').classList.add('hidden');
411
  });
412
  });
413
 
414
+ function startCountdown(title, totalSeconds, animationType, targetDate = null, timezone = null) {
415
  // Switch to countdown page
416
  document.getElementById('main-page').classList.add('hidden');
417
  document.getElementById('countdown-page').classList.remove('hidden');
418
  document.getElementById('countdown-title').textContent = title;
419
  document.getElementById('finished-message').classList.add('hidden');
420
 
421
+ // Show target time if available
422
+ if (targetDate) {
423
+ let displayDate;
424
+ if (timezone === 'utc') {
425
+ displayDate = targetDate.toUTCString();
426
+ } else {
427
+ displayDate = targetDate.toLocaleString();
428
+ }
429
+ document.getElementById('target-time').textContent = displayDate;
430
+ document.getElementById('target-time-display').classList.remove('hidden');
431
+ } else {
432
+ document.getElementById('target-time-display').classList.add('hidden');
433
+ }
434
 
435
  // Start the countdown
436
  updateCountdownDisplay(totalSeconds);
437
 
438
+ if (targetDate) {
439
+ // For datetime mode, we need to recalculate the remaining time each second
440
+ // to account for any time drift
441
+ window.countdownInterval = setInterval(function() {
442
+ const now = new Date();
443
+ totalSeconds = Math.floor((targetDate - now) / 1000);
444
+ updateCountdownDisplay(totalSeconds);
445
+
446
+ if (totalSeconds <= 0) {
447
+ clearInterval(window.countdownInterval);
448
+ countdownFinished(animationType);
449
+ }
450
+ }, 1000);
451
+ } else {
452
+ // For duration mode, simple countdown is sufficient
453
+ window.countdownInterval = setInterval(function() {
454
+ totalSeconds--;
455
+ updateCountdownDisplay(totalSeconds);
456
+
457
+ if (totalSeconds <= 0) {
458
+ clearInterval(window.countdownInterval);
459
+ countdownFinished(animationType);
460
+ }
461
+ }, 1000);
462
+ }
463
  }
464
 
465
  function updateCountdownDisplay(totalSeconds) {
 
551
  }
552
  }
553
  </script>
554
+ </body>
555
  </html>