/* Base JavaScript Utilities */ document.addEventListener('DOMContentLoaded', function() { // Initialize tooltips and popovers initializeBootstrap(); // Setup flash message auto-close setupFlashMessages(); // Setup theme toggle if available setupThemeToggle(); }); /** * Initialize Bootstrap tooltips and popovers */ function initializeBootstrap() { // Initialize all tooltips const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')); tooltipTriggerList.map(function (tooltipTriggerEl) { return new bootstrap.Tooltip(tooltipTriggerEl); }); // Initialize all popovers const popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]')); popoverTriggerList.map(function (popoverTriggerEl) { return new bootstrap.Popover(popoverTriggerEl); }); } /** * Auto-close flash messages after 5 seconds */ function setupFlashMessages() { const alerts = document.querySelectorAll('.alert'); alerts.forEach(function(alert) { setTimeout(function() { const bsAlert = new bootstrap.Alert(alert); bsAlert.close(); }, 5000); }); } /** * Setup theme toggle functionality */ function setupThemeToggle() { const themeToggle = document.getElementById('theme-toggle'); if (!themeToggle) return; const currentTheme = localStorage.getItem('theme') || 'light'; applyTheme(currentTheme); themeToggle.addEventListener('click', function() { const newTheme = currentTheme === 'light' ? 'dark' : 'light'; applyTheme(newTheme); localStorage.setItem('theme', newTheme); }); } /** * Apply theme to document */ function applyTheme(theme) { const html = document.documentElement; if (theme === 'dark') { html.setAttribute('data-bs-theme', 'dark'); } else { html.removeAttribute('data-bs-theme'); } } /** * Display a toast notification */ function showToast(message, type = 'info') { const toastHtml = ` `; const toastContainer = document.querySelector('.toast-container') || createToastContainer(); toastContainer.insertAdjacentHTML('beforeend', toastHtml); const toastElement = toastContainer.lastElementChild; const toast = new bootstrap.Toast(toastElement); toast.show(); toastElement.addEventListener('hidden.bs.toast', function() { toastElement.remove(); }); } /** * Create toast container if it doesn't exist */ function createToastContainer() { const container = document.createElement('div'); container.className = 'toast-container position-fixed bottom-0 end-0 p-3'; document.body.appendChild(container); return container; } /** * Debounce function for input handlers */ function debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } /** * Throttle function for scroll/resize handlers */ function throttle(func, limit) { let inThrottle; return function(...args) { if (!inThrottle) { func.apply(this, args); inThrottle = true; setTimeout(() => inThrottle = false, limit); } }; }