'use strict'; // ==================================================================== // Toast Notification System // // Avaiable toast type: "success", "error", "info" // ==================================================================== function showToast(message, type = 'success', duration = 2000) { const container = document.getElementById('toast-container'); const toast = document.createElement('div'); toast.className = `toast ${type}`; toast.textContent = message; container.appendChild(toast); // Auto-hide after duration setTimeout(() => { toast.classList.add('hiding'); setTimeout(() => { container.removeChild(toast); }, 300); // Match animation duration }, duration); } // Expose globally for htmx responses to trigger window.showToast = showToast; // ==================================================================== // Close Dropdown on HTMX Navigation // ==================================================================== // Close any open
dropdowns(e.g., those controlled by Pico class) when htmx navigation starts document.body.addEventListener('htmx:beforeRequest', function(event) { document.querySelectorAll('details[open]').forEach(function(details) { details.removeAttribute('open'); }); }); // ==================================================================== // HTMX Error Handling // ==================================================================== // Handle HTMX errors (4xx, 5xx responses) // By default, HTMX ignores error responses and doesn't swap content. // We want to show the error page for 500 errors. document.body.addEventListener('htmx:responseError', function(event) { const statusCode = event.detail.xhr.status; if (statusCode >= 500) { // For 500 errors, replace the entire page with the error page document.open(); document.write(event.detail.xhr.response); document.close(); } else if (statusCode === 404) { // For 404, could also redirect or show custom message document.open(); document.write(event.detail.xhr.response); document.close(); } // For 4xx client errors, you might want different handling // e.g., show inline error messages }); // ==================================================================== // HTMX Loading Indicators (Pico's aria-busy) // ==================================================================== // When htmx makes a request, add aria-busy to the indicator element document.body.addEventListener('htmx:beforeRequest', function(event) { // htmx automatically adds 'htmx-request' class to elements with hx-indicator // We need to manually handle aria-busy for Pico CSS const elt = event.detail.elt; const indicator = elt.closest('form')?.querySelector('[aria-busy]') || elt; if (indicator && indicator.hasAttribute('aria-busy')) { indicator.setAttribute('aria-busy', 'true'); indicator.disabled = true; } }); document.body.addEventListener('htmx:afterRequest', function(event) { // Remove aria-busy after request completes const elt = event.detail.elt; const indicator = elt.closest('form')?.querySelector('[aria-busy]') || elt; if (indicator && indicator.hasAttribute('aria-busy')) { indicator.setAttribute('aria-busy', 'false'); indicator.disabled = false; } });