Seasonal Countdown Timers

Seasonal Countdown Timers

You have not added any timers. Go to the Data Configuration tab to create one.

Add / Edit Timer

Add Preset Timer (USA)

Manage Timers

No timers configured.

'; return; } sct_timers.forEach(timer => { const formattedDate = new Date(timer.date).toLocaleString('en-US', { dateStyle: 'short', timeStyle: 'short' }); const item = document.createElement('div'); item.className = 'sct-list-item'; item.innerHTML = `
${sct_escapeHTML(timer.name)}
${formattedDate}
`; sct_manageList.appendChild(item); }); } /** * Handles the save/update of a timer */ window.sct_saveTimer = function(event) { event.preventDefault(); if (!sct_eventName || !sct_eventDate || !sct_timerId) return; const id = sct_timerId.value; const name = sct_eventName.value; const date = sct_eventDate.value; if (!name || !date) return; if (id) { // Editing existing timer const timer = sct_timers.find(t => t.id == id); if (timer) { timer.name = name; timer.date = date; } } else { // Adding new timer const newTimer = { id: Date.now(), name: name, date: date }; sct_timers.push(newTimer); } sct_clearForm(); sct_renderDashboard(); sct_renderManageList(); } /** * Clears the "Add/Edit" form */ window.sct_clearForm = function() { if (sct_timerId) sct_timerId.value = ''; if (sct_eventName) sct_eventName.value = ''; if (sct_eventDate) sct_eventDate.value = ''; if (sct_timerForm) sct_timerForm.reset(); } /** * Populates the form to edit a timer */ window.sct_editTimer = function(id) { const timer = sct_timers.find(t => t.id === id); if (timer && sct_timerId && sct_eventName && sct_eventDate) { sct_timerId.value = timer.id; sct_eventName.value = timer.name; // Format for datetime-local input (YYYY-MM-DDTHH:MM) const localDate = new Date(timer.date); // Adjust for timezone offset localDate.setMinutes(localDate.getMinutes() - localDate.getTimezoneOffset()); sct_eventDate.value = localDate.toISOString().slice(0, 16); // Switch to config tab sct_switchTab(1); sct_eventName.focus(); } } /** * Deletes a timer */ window.sct_deleteTimer = function(id) { if (confirm("Are you sure you want to delete this timer?")) { sct_timers = sct_timers.filter(t => t.id !== id); sct_renderDashboard(); sct_renderManageList(); } } /** * Loads a preset date into the form */ window.sct_addPreset = function() { if (!sct_presetSelect || !sct_eventName || !sct_eventDate) return; const preset = sct_presetSelect.value; const now = new Date(); let year = now.getFullYear(); let targetDate; let name = ''; switch (preset) { case 'thanksgiving': // 4th Thursday of November name = 'Thanksgiving'; let firstNov = new Date(year, 10, 1); let firstThursOffset = (4 - firstNov.getDay() + 7) % 7; let thursDate = 1 + firstThursOffset + 21; // 1st + 3 weeks targetDate = new Date(year, 10, thursDate, 12, 0, 0); // 12:00 PM if (targetDate < now) { // If past, get next year's firstNov = new Date(year + 1, 10, 1); firstThursOffset = (4 - firstNov.getDay() + 7) % 7; thursDate = 1 + firstThursOffset + 21; targetDate = new Date(year + 1, 10, thursDate, 12, 0, 0); } break; case 'christmas': name = 'Christmas Day'; targetDate = new Date(year, 11, 25, 9, 0, 0); // 9:00 AM if (targetDate < now) { targetDate.setFullYear(year + 1); } break; case 'new_year': name = "New Year's Day"; targetDate = new Date(year + 1, 0, 1, 0, 0, 0); // Midnight break; case 'july_4th': name = 'Independence Day'; targetDate = new Date(year, 6, 4, 20, 0, 0); // 8:00 PM (Fireworks) if (targetDate < now) { targetDate.setFullYear(year + 1); } break; } sct_eventName.value = name; // Format for datetime-local input targetDate.setMinutes(targetDate.getMinutes() - targetDate.getTimezoneOffset()); sct_eventDate.value = targetDate.toISOString().slice(0, 16); sct_timerId.value = ''; // Ensure it's a new timer } // --- TAB & NAVIGATION FUNCTIONS --- window.sct_switchTab = function(tabIndex) { sct_currentTabIndex = tabIndex; sct_tabContents.forEach((content, index) => { content.classList.toggle('sct-active', index === tabIndex); }); sct_tabs.forEach((tab, index) => { tab.classList.toggle('sct-active', index === tabIndex); }); sct_updateNavButtons(); } window.sct_navigateTabs = function(direction) { if (direction === 'next' && sct_currentTabIndex < sct_numTabs - 1) { sct_switchTab(sct_currentTabIndex + 1); } else if (direction === 'prev' && sct_currentTabIndex > 0) { sct_switchTab(sct_currentTabIndex - 1); } } function sct_updateNavButtons() { sct_prevBtn.style.visibility = (sct_currentTabIndex === 0) ? 'hidden' : 'visible'; sct_nextBtn.style.visibility = (sct_currentTabIndex === sct_numTabs - 1) ? 'hidden' : 'visible'; } // --- PDF GENERATION --- window.sct_generatePdf = function() { if (typeof jspdf === 'undefined' || typeof jspdf.jsPDF === 'undefined') { alert('Error: PDF generation library (jsPDF) not loaded.'); return; } if (typeof window.jspdf.plugin.autotable === 'undefined') { alert('Error: PDF generation library (jsPDF-AutoTable) not loaded.'); return; } if (sct_timers.length === 0) { alert("You have no timers to download. Please add some timers first."); return; } try { const { jsPDF } = jspdf; const doc = new jsPDF(); doc.setFont('helvetica', 'bold'); doc.setFontSize(20); doc.setTextColor(varGet('--sct-primary-color', '#0073e6')); doc.text("My Countdown Timers", 105, 20, { align: 'center' }); doc.setFontSize(11); doc.setTextColor(varGet('--sct-text-color', '#333')); doc.text(`Total Timers: ${sct_timers.length}`, 14, 30); const tableColumn = ["Event Name", "Target Date & Time"]; const tableRows = []; sct_timers.forEach(timer => { const formattedDate = new Date(timer.date).toLocaleString('en-US', { dateStyle: 'full', timeStyle: 'short' }); tableRows.push([timer.name, formattedDate]); }); doc.autoTable({ head: [tableColumn], body: tableRows, startY: 40, theme: 'striped', headStyles: { fillColor: varGet('--sct-primary-color', '#0073e6'), textColor: varGet('--sct-text-light', '#fff') }, styles: { font: 'helvetica', cellPadding: 3 }, alternateRowStyles: { fillColor: varGet('--sct-light-primary', '#e6f1fc') } }); doc.save('my_countdown_timers.pdf'); } catch (e) { console.error("PDF Generation Error: ", e); alert("An error occurred while generating the PDF."); } } // --- UTILITY FUNCTIONS --- function varGet(varName, fallback = '#000') { try { return getComputedStyle(document.documentElement).getPropertyValue(varName).trim() || fallback; } catch (e) { return fallback; } } function sct_escapeHTML(str) { if (!str) return ''; return str.replace(/[&<>"']/g, function(m) { return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[m]; }); } // --- INITIALIZATION --- function sct_initTool() { sct_switchTab(0); // Set initial tab sct_renderDashboard(); sct_renderManageList(); sct_startTimerInterval(); } sct_initTool(); // Run the tool }); // End of DOMContentLoaded