Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Worldview - Earth Data Visualization</title> | |
| <!-- Import FontAwesome for Icons --> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| :root { | |
| --bg-dark: #262b31; | |
| --bg-panel: #2c3238; | |
| --bg-header: #1a1d21; | |
| --text-main: #e0e0e0; | |
| --text-muted: #a0a0a0; | |
| --accent-color: #007bff; | |
| --accent-hover: #0056b3; | |
| --border-color: #444; | |
| --toolbar-height: 60px; | |
| --sidebar-width: 320px; | |
| --timeline-height: 80px; | |
| --transition-speed: 0.3s; | |
| } | |
| * { | |
| box-sizing: border-box; | |
| margin: 0; | |
| padding: 0; | |
| font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; | |
| } | |
| body { | |
| background-color: #000; | |
| color: var(--text-main); | |
| overflow: hidden; | |
| height: 100vh; | |
| width: 100vw; | |
| display: flex; | |
| flex-direction: column; | |
| } | |
| /* --- Header / Toolbar --- */ | |
| header { | |
| height: var(--toolbar-height); | |
| background-color: var(--bg-header); | |
| display: flex; | |
| align-items: center; | |
| padding: 0 10px; | |
| z-index: 100; | |
| box-shadow: 0 2px 10px rgba(0,0,0,0.5); | |
| border-bottom: 1px solid var(--border-color); | |
| } | |
| .wv-toolbar { | |
| display: flex; | |
| gap: 5px; | |
| margin-left: auto; | |
| } | |
| .wv-toolbar-button { | |
| background: var(--bg-panel); | |
| border: 1px solid var(--border-color); | |
| color: var(--text-main); | |
| width: 44px; | |
| height: 44px; | |
| border-radius: 4px; | |
| cursor: pointer; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| transition: all 0.2s; | |
| position: relative; | |
| } | |
| .wv-toolbar-button:hover { | |
| background-color: var(--accent-color); | |
| border-color: var(--accent-color); | |
| } | |
| .wv-toolbar-button svg { | |
| font-size: 18px; | |
| } | |
| .anycoder-credit { | |
| margin-right: 20px; | |
| font-size: 0.85rem; | |
| color: var(--text-muted); | |
| text-decoration: none; | |
| border: 1px solid var(--border-color); | |
| padding: 5px 10px; | |
| border-radius: 4px; | |
| transition: 0.2s; | |
| } | |
| .anycoder-credit:hover { | |
| color: #fff; | |
| border-color: #fff; | |
| } | |
| /* --- Main Layout --- */ | |
| #app { | |
| position: relative; | |
| flex: 1; | |
| display: flex; | |
| overflow: hidden; | |
| } | |
| /* --- Map Area --- */ | |
| #wv-map { | |
| flex: 1; | |
| position: relative; | |
| background: #0f1114; | |
| background-image: | |
| radial-gradient(circle at 50% 50%, rgba(20, 30, 48, 0.5) 0%, rgba(0,0,0,1) 100%), | |
| linear-gradient(rgba(255,255,255,0.03) 1px, transparent 1px), | |
| linear-gradient(90deg, rgba(255,255,255,0.03) 1px, transparent 1px); | |
| background-size: 100% 100%, 50px 50px, 50px 50px; | |
| overflow: hidden; | |
| } | |
| /* Abstract Globe Representation */ | |
| .globe-placeholder { | |
| position: absolute; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| width: 600px; | |
| height: 600px; | |
| border-radius: 50%; | |
| background: radial-gradient(circle at 30% 30%, #2a5298, #1e3c72); | |
| box-shadow: 0 0 50px rgba(0,0,0,0.8), inset -20px -20px 50px rgba(0,0,0,0.5); | |
| opacity: 0.8; | |
| animation: pulse 10s infinite alternate; | |
| } | |
| @keyframes pulse { | |
| 0% { transform: translate(-50%, -50%) scale(1); opacity: 0.8; } | |
| 100% { transform: translate(-50%, -50%) scale(1.02); opacity: 0.9; } | |
| } | |
| /* --- Sidebar --- */ | |
| #wv-sidebar { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| height: 100%; | |
| width: var(--sidebar-width); | |
| background-color: var(--bg-dark); | |
| border-right: 1px solid var(--border-color); | |
| z-index: 50; | |
| display: flex; | |
| flex-direction: column; | |
| transition: transform var(--transition-speed) ease; | |
| } | |
| #wv-sidebar.collapsed { | |
| transform: translateX(-100%); | |
| } | |
| .sidebar-header { | |
| height: 60px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| padding: 0 15px; | |
| background-color: var(--bg-header); | |
| border-bottom: 1px solid var(--border-color); | |
| } | |
| #wv-logo { | |
| width: 36px; | |
| height: 36px; | |
| background-color: #333; | |
| border-radius: 4px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| color: white; | |
| font-weight: bold; | |
| font-size: 10px; | |
| text-align: center; | |
| } | |
| .sidebar-collapse { | |
| background: none; | |
| border: none; | |
| color: var(--text-main); | |
| cursor: pointer; | |
| font-size: 1.2rem; | |
| } | |
| /* Sidebar Tabs */ | |
| .nav-tabs { | |
| display: flex; | |
| list-style: none; | |
| border-bottom: 1px solid var(--border-color); | |
| } | |
| .nav-item { | |
| flex: 1; | |
| text-align: center; | |
| } | |
| .sidebar-tab { | |
| display: block; | |
| padding: 12px; | |
| color: var(--text-muted); | |
| text-decoration: none; | |
| font-size: 0.9rem; | |
| cursor: pointer; | |
| border-bottom: 2px solid transparent; | |
| transition: 0.2s; | |
| } | |
| .sidebar-tab.active { | |
| color: var(--accent-color); | |
| border-bottom: 2px solid var(--accent-color); | |
| background: rgba(0, 123, 255, 0.05); | |
| } | |
| .sidebar-tab:hover { | |
| color: #fff; | |
| } | |
| /* Layer List */ | |
| #layers-scroll-container { | |
| flex: 1; | |
| overflow-y: auto; | |
| padding: 10px; | |
| } | |
| /* Custom Scrollbar */ | |
| #layers-scroll-container::-webkit-scrollbar { | |
| width: 6px; | |
| } | |
| #layers-scroll-container::-webkit-scrollbar-thumb { | |
| background: #555; | |
| border-radius: 3px; | |
| } | |
| /* Layer Groups */ | |
| .layer-group-case { | |
| margin-bottom: 10px; | |
| background: var(--bg-panel); | |
| border-radius: 4px; | |
| overflow: hidden; | |
| } | |
| .layer-group-header { | |
| padding: 10px; | |
| background: rgba(255,255,255,0.05); | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| cursor: pointer; | |
| user-select: none; | |
| } | |
| .layer-group-title { | |
| font-size: 0.95rem; | |
| font-weight: 600; | |
| } | |
| .category { | |
| list-style: none; | |
| padding: 0; | |
| display: block; /* Expanded by default */ | |
| } | |
| .category.hidden { | |
| display: none; | |
| } | |
| .layer-item { | |
| display: flex; | |
| align-items: center; | |
| padding: 8px 10px; | |
| border-bottom: 1px solid rgba(255,255,255,0.05); | |
| transition: background 0.2s; | |
| cursor: pointer; | |
| } | |
| .layer-item:hover { | |
| background: rgba(255,255,255,0.05); | |
| } | |
| .visibility { | |
| color: var(--text-muted); | |
| margin-right: 10px; | |
| cursor: pointer; | |
| width: 20px; | |
| text-align: center; | |
| } | |
| .visibility.active { | |
| color: #fff; | |
| } | |
| .layer-main h4 { | |
| font-size: 0.9rem; | |
| font-weight: normal; | |
| color: var(--text-main); | |
| } | |
| .instrument-collection { | |
| font-size: 0.75rem; | |
| color: var(--text-muted); | |
| margin-top: 2px; | |
| } | |
| /* Mobile Toggler */ | |
| .sidebar-expand { | |
| position: absolute; | |
| top: 10px; | |
| left: 10px; | |
| z-index: 60; | |
| } | |
| .sidebar-anchor { | |
| background: var(--bg-panel); | |
| color: white; | |
| padding: 8px 12px; | |
| border-radius: 4px; | |
| border: 1px solid var(--border-color); | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| cursor: pointer; | |
| text-decoration: none; | |
| font-size: 0.9rem; | |
| } | |
| /* --- Timeline --- */ | |
| .timeline-container { | |
| position: absolute; | |
| bottom: 0; | |
| left: 0; | |
| width: 100%; | |
| height: var(--timeline-height); | |
| background: var(--bg-panel); | |
| border-top: 1px solid var(--border-color); | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| padding: 0 20px; | |
| z-index: 90; | |
| } | |
| .timeline-date { | |
| font-size: 1.1rem; | |
| font-weight: bold; | |
| color: #fff; | |
| } | |
| .timeline-controls { | |
| display: flex; | |
| gap: 10px; | |
| } | |
| .control-btn { | |
| background: rgba(255,255,255,0.1); | |
| border: none; | |
| color: white; | |
| width: 36px; | |
| height: 36px; | |
| border-radius: 50%; | |
| cursor: pointer; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| transition: 0.2s; | |
| } | |
| .control-btn:hover { | |
| background: var(--accent-color); | |
| } | |
| /* --- Floating Buttons (Zoom/Measure) --- */ | |
| .floating-controls { | |
| position: absolute; | |
| bottom: 100px; | |
| right: 20px; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 10px; | |
| z-index: 80; | |
| } | |
| .floating-btn { | |
| width: 44px; | |
| height: 44px; | |
| background: var(--bg-panel); | |
| border: 1px solid var(--border-color); | |
| border-radius: 4px; | |
| color: white; | |
| cursor: pointer; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| box-shadow: 0 4px 6px rgba(0,0,0,0.3); | |
| transition: 0.2s; | |
| } | |
| .floating-btn:hover { | |
| background: var(--accent-color); | |
| } | |
| /* --- Toast Notification --- */ | |
| #toast-container { | |
| position: fixed; | |
| top: 80px; | |
| right: 20px; | |
| z-index: 200; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 10px; | |
| } | |
| .toast { | |
| background: rgba(30, 30, 30, 0.95); | |
| color: white; | |
| padding: 12px 20px; | |
| border-radius: 4px; | |
| border-left: 4px solid var(--accent-color); | |
| box-shadow: 0 5px 15px rgba(0,0,0,0.5); | |
| animation: slideIn 0.3s ease-out; | |
| max-width: 300px; | |
| font-size: 0.9rem; | |
| } | |
| @keyframes slideIn { | |
| from { transform: translateX(100%); opacity: 0; } | |
| to { transform: translateX(0); opacity: 1; } | |
| } | |
| /* --- Responsive --- */ | |
| @media (max-width: 768px) { | |
| .anycoder-credit { | |
| display: none; | |
| } | |
| .wv-toolbar-button { | |
| width: 38px; | |
| height: 38px; | |
| } | |
| .wv-toolbar-button span { | |
| display: none; | |
| } | |
| #wv-sidebar { | |
| width: 280px; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <!-- Header Toolbar --> | |
| <header> | |
| <div class="header-left"> | |
| <!-- Built with anycoder link --> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-credit"> | |
| Built with anycoder | |
| </a> | |
| </div> | |
| <div class="wv-toolbar"> | |
| <button type="button" id="wv-location-search-button" class="wv-toolbar-button" aria-label="Search places by location"> | |
| <i class="fa-solid fa-magnifying-glass-location"></i> | |
| </button> | |
| <button type="button" id="wv-share-button" class="wv-toolbar-button" aria-label="Share this map"> | |
| <i class="fa-solid fa-share-from-square"></i> | |
| </button> | |
| <button type="button" id="wv-proj-button" class="wv-toolbar-button" aria-label="Switch projection"> | |
| <i class="fa-solid fa-earth-asia"></i> | |
| </button> | |
| <button type="button" id="wv-info-button" class="wv-toolbar-button" aria-label="Information"> | |
| <i class="fa-solid fa-circle-info"></i> | |
| </button> | |
| </div> | |
| </header> | |
| <div id="app"> | |
| <!-- Mobile Sidebar Toggle --> | |
| <div class="sidebar-expand mobile"> | |
| <a id="accordion-toggler-button" class="sidebar-anchor" aria-label="Expand sidebar"> | |
| <i class="fa-solid fa-layer-group layer-icon"></i> | |
| <span class="layer-count mobile">9</span> | |
| </a> | |
| </div> | |
| <!-- Sidebar --> | |
| <section id="wv-sidebar"> | |
| <div class="sidebar-header"> | |
| <div id="wv-logo" title="Worldview">WV</div> | |
| <button id="sidebar-close" class="sidebar-collapse" aria-label="Hide sidebar"> | |
| <i class="fa-solid fa-xmark"></i> | |
| </button> | |
| </div> | |
| <ul class="nav-tabs"> | |
| <li class="nav-item"> | |
| <a id="layers-sidebar-tab" class="sidebar-tab first-tab active"> | |
| <i class="fa-solid fa-layer-group"></i> Layers | |
| </a> | |
| </li> | |
| <li class="nav-item"> | |
| <a id="events-sidebar-tab" class="sidebar-tab second-tab"> | |
| <i class="fa-solid fa-volcano"></i> Events | |
| </a> | |
| </li> | |
| </ul> | |
| <div class="tab-content"> | |
| <div id="layers-scroll-container"> | |
| <!-- Reference Layers Group --> | |
| <div class="layer-group-case"> | |
| <div class="layer-group-header" onclick="toggleGroup(this)"> | |
| <h3 class="layer-group-title">Reference</h3> | |
| <i class="fa-solid fa-caret-down"></i> | |
| </div> | |
| <ul class="category"> | |
| <li class="layer-item"> | |
| <div class="visibility" onclick="toggleVisibility(this)"> | |
| <i class="fa-solid fa-eye-slash"></i> | |
| </div> | |
| <div class="layer-main"> | |
| <h4>Place Labels</h4> | |
| <div class="instrument-collection">Sources: Esri, TomTom, Garmin...</div> | |
| </div> | |
| </li> | |
| <li class="layer-item"> | |
| <div class="visibility" onclick="toggleVisibility(this)"> | |
| <i class="fa-solid fa-eye-slash"></i> | |
| </div> | |
| <div class="layer-main"> | |
| <h4>Coastlines / Borders</h4> | |
| <div class="instrument-collection">© OpenStreetMap</div> | |
| </div> | |
| </li> | |
| <li class="layer-item"> | |
| <div class="visibility active" onclick="toggleVisibility(this)"> | |
| <i class="fa-solid fa-eye"></i> | |
| </div> | |
| <div class="layer-main"> | |
| <h4>Coastlines</h4> | |
| <div class="instrument-collection">© OpenStreetMap</div> | |
| </div> | |
| </li> | |
| </ul> | |
| </div> | |
| <!-- Base Layers Group --> | |
| <div class="layer-group-case"> | |
| <div class="layer-group-header" onclick="toggleGroup(this)"> | |
| <h3 class="layer-group-title">Base Layers</h3> | |
| <div class="layer-group-icons"> | |
| <i class="fa-solid fa-caret-down"></i> | |
| </div> | |
| </div> | |
| <ul class="category"> | |
| <li class="layer-item"> | |
| <div class="visibility" onclick="toggleVisibility(this)"> | |
| <i class="fa-solid fa-eye-slash"></i> | |
| </div> | |
| <div class="layer-main"> | |
| <h4>Corrected Reflectance (True Color)</h4> | |
| <div class="instrument-collection">PACE / OCI</div> | |
| </div> | |
| </li> | |
| <li class="layer-item"> | |
| <div class="visibility" onclick="toggleVisibility(this)"> | |
| <i class="fa-solid fa-eye-slash"></i> | |
| </div> | |
| <div class="layer-main"> | |
| <h4>Corrected Reflectance (True Color)</h4> | |
| <div class="instrument-collection">NOAA-21 / VIIRS</div> | |
| </div> | |
| </li> | |
| <li class="layer-item"> | |
| <div class="visibility" onclick="toggleVisibility(this)"> | |
| <i class="fa-solid fa-eye-slash"></i> | |
| </div> | |
| <div class="layer-main"> | |
| <h4>Corrected Reflectance (True Color)</h4> | |
| <div class="instrument-collection">NOAA-20 / VIIRS</div> | |
| </div> | |
| </li> | |
| <li class="layer-item"> | |
| <div class="visibility active" onclick="toggleVisibility(this)"> | |
| <i class="fa-solid fa-eye"></i> | |
| </div> | |
| <div class="layer-main"> | |
| <h4>Corrected Reflectance (True Color)</h4> | |
| <div class="instrument-collection">Terra / MODIS</div> | |
| <div class="badge rounded-pill bg-secondary">v6.1 NRT</div> | |
| </div> | |
| </li> | |
| </ul> | |
| </div> | |
| <div class="product-buttons"> | |
| <button type="button" class="wv-button layers-add"> | |
| <span class="button-text"><i class="fa-solid fa-plus"></i> Add Layers</span> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Map Area --> | |
| <div id="wv-map"> | |
| <div class="globe-placeholder"></div> | |
| <!-- Map Overlay UI --> | |
| <div id="ol-coords-case" class="wv-coords-container" style="position: absolute; top: 10px; right: 10px; background: rgba(0,0,0,0.6); padding: 5px; border-radius: 4px; font-family: monospace; font-size: 12px; pointer-events: none;"> | |
| <span class="map-coord">26.2589°, -63.2973°</span> | <span class="map-coord">EPSG:4326</span> | |
| </div> | |
| </div> | |
| <!-- Floating Controls --> | |
| <div class="floating-controls"> | |
| <button id="wv-measure-button" class="floating-btn" aria-label="Measure distances & areas"> | |
| <i class="fa-solid fa-ruler"></i> | |
| </button> | |
| <div class="wv-zoom-buttons-mobile" style="display: flex; flex-direction: column; gap: 5px;"> | |
| <button class="floating-btn wv-map-zoom-in"><i class="fa-solid fa-plus"></i></button> | |
| <button class="floating-btn wv-map-zoom-out"><i class="fa-solid fa-minus"></i></button> | |
| </div> | |
| </div> | |
| <!-- Timeline Footer --> | |
| <div class="timeline-container"> | |
| <div class="timeline-header-mobile"> | |
| <div class="timeline-date">2026 JAN 29</div> | |
| </div> | |
| <div class="timeline-controls"> | |
| <button class="control-btn" id="prev-day" aria-label="Previous Day"> | |
| <i class="fa-solid fa-chevron-left"></i> | |
| </button> | |
| <button class="control-btn" id="now-btn" aria-label="Go to Now"> | |
| <span style="font-size: 16px; font-weight: bold;">NOW</span> | |
| </button> | |
| <button class="control-btn" id="next-day" aria-label="Next Day" disabled style="opacity: 0.5;"> | |
| <i class="fa-solid fa-chevron-right"></i> | |
| </button> | |
| </div> | |
| <div class="animate-button"> | |
| <button class="control-btn" id="animate-toggle" aria-label="Set up animation" style="background: var(--accent-color);"> | |
| <i class="fa-solid fa-video"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Toast Container --> | |
| <div id="toast-container"></div> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', () => { | |
| // --- Sidebar Logic --- | |
| const sidebar = document.getElementById('wv-sidebar'); | |
| const toggleBtn = document.getElementById('accordion-toggler-button'); | |
| const closeBtn = document.getElementById('sidebar-close'); | |
| const layersTab = document.getElementById('layers-sidebar-tab'); | |
| const eventsTab = document.getElementById('events-sidebar-tab'); | |
| // Open Sidebar | |
| toggleBtn.addEventListener('click', (e) => { | |
| e.preventDefault(); | |
| // Check if we are on mobile, if so, just toggle class | |
| sidebar.classList.remove('collapsed'); | |
| }); | |
| // Close Sidebar | |
| closeBtn.addEventListener('click', () => { | |
| sidebar.classList.add('collapsed'); | |
| }); | |
| // Tab Switching (Visual only) | |
| layersTab.addEventListener('click', () => { | |
| layersTab.classList.add('active'); | |
| eventsTab.classList.remove('active'); | |
| showToast("Switched to Layers Tab"); | |
| }); | |
| eventsTab.addEventListener('click', () => { | |
| eventsTab.classList.add('active'); | |
| layersTab.classList.remove('active'); | |
| showToast("Switched to Events Tab (Mock)"); | |
| }); | |
| // --- Layer Interactions --- | |
| // Toggle Layer Visibility | |
| window.toggleVisibility = function(element) { | |
| const icon = element.querySelector('i'); | |
| const parentLi = element.closest('.layer-item'); | |
| if (element.classList.contains('active')) { | |
| element.classList.remove('active'); | |
| icon.classList.remove('fa-eye'); | |
| icon.classList.add('fa-eye-slash'); | |
| parentLi.style.opacity = '0.6'; | |
| } else { | |
| element.classList.add('active'); | |
| icon.classList.remove('fa-eye-slash'); | |
| icon.classList.add('fa-eye'); | |
| parentLi.style.opacity = '1'; | |
| } | |
| }; | |
| // Toggle Group Accordion | |
| window.toggleGroup = function(header) { | |
| const list = header.nextElementSibling; | |
| const icon = header.querySelector('.fa-caret-down, .fa-caret-right'); | |
| if (list.classList.contains('hidden')) { | |
| list.classList.remove('hidden'); | |
| if(icon) { | |
| icon.classList.remove('fa-caret-right'); | |
| icon.classList.add('fa-caret-down'); | |
| } | |
| } else { | |
| list.classList.add('hidden'); | |
| if(icon) { | |
| icon.classList.remove('fa-caret-down'); | |
| icon.classList.add('fa-caret-right'); | |
| } | |
| } | |
| }; | |
| // --- Toolbar Buttons --- | |
| document.getElementById('wv-location-search-button').addEventListener('click', () => { | |
| showToast("Search Location clicked"); | |
| }); | |
| document.getElementById('wv-share-button').addEventListener('click', () => { | |
| const url = window.location.href; | |
| navigator.clipboard.writeText(url).then(() => { | |
| showToast("Link copied to clipboard!"); | |
| }).catch(() => { | |
| showToast("Share functionality initialized."); | |
| }); | |
| }); | |
| document.getElementById('wv-proj-button').addEventListener('click', () => { | |
| showToast("Projection Switcher (Arctic/Antarctic/Geographic)"); | |
| }); | |
| document.getElementById('wv-info-button').addEventListener('click', () => { | |
| showToast("Worldview Information v8.3"); | |
| }); | |
| document.getElementById('wv-measure-button').addEventListener('click', () => { | |
| showToast("Measure Tool Activated"); | |
| }); | |
| // --- Timeline Logic --- | |
| const prevBtn = document.getElementById('prev-day'); | |
| const nextBtn = document.getElementById('next-day'); | |
| const dateDisplay = document.querySelector('.timeline-date'); | |
| const nowBtn = document.getElementById('now-btn'); | |
| const animBtn = document.getElementById('animate-toggle'); | |
| let currentDate = new Date("2026-01-29"); | |
| function updateDateDisplay() { | |
| const options = { year: 'numeric', month: 'short', day: 'numeric' }; | |
| dateDisplay.textContent = currentDate.toLocaleDateString('en-US', options).toUpperCase(); | |
| } | |
| prevBtn.addEventListener('click', () => { | |
| currentDate.setDate(currentDate.getDate() - 1); | |
| updateDateDisplay(); | |
| showToast("Going back one day..."); | |
| }); | |
| nextBtn.addEventListener('click', () => { | |
| // Simulating limit | |
| showToast("Future data not available"); | |
| }); | |
| nowBtn.addEventListener('click', () => { | |
| currentDate = new Date(); | |
| updateDateDisplay(); | |
| showToast("Moved to current date"); | |
| }); | |
| animBtn.addEventListener('click', () => { | |
| animBtn.style.background = animBtn.style.background === 'var(--accent-color)' ? '#d32f2f' : 'var(--accent-color)'; | |
| if(animBtn.style.background === '#d32f2f') { | |
| showToast("Animation Paused"); | |
| } else { | |
| showToast("Animation Started"); | |
| } | |
| }); | |
| // --- Helper: Toast Notification --- | |
| function showToast(message) { | |
| const container = document.getElementById('toast-container'); | |
| const toast = document.createElement('div'); | |
| toast.className = 'toast'; | |
| toast.textContent = message; | |
| container.appendChild(toast); | |
| // Remove after 3 seconds | |
| setTimeout(() => { | |
| toast.style.opacity = '0'; | |
| toast.style.transform = 'translateX(100%)'; | |
| toast.style.transition = 'all 0.3s ease-in'; | |
| setTimeout(() => toast.remove(), 300); | |
| }, 3000); | |
| } | |
| // Initialize state | |
| updateDateDisplay(); | |
| // Handle Resize logic for sidebar | |
| const handleResize = () => { | |
| if (window.innerWidth < 768) { | |
| sidebar.classList.add('collapsed'); | |
| } else { | |
| sidebar.classList.remove('collapsed'); | |
| } | |
| }; | |
| window.addEventListener('resize', handleResize); | |
| handleResize(); // Init | |
| }); | |
| </script> | |
| </body> | |
| </html> |