// Modern Mobile Enhancements // Clean, simple mobile-friendly functionality class ModernMobile { constructor() { this.init(); } init() { this.setupMobileTableLabels(); this.setupResponsiveNavigation(); this.setupFormEnhancements(); this.setupSmoothInteractions(); } // Add data labels for mobile table stacking setupMobileTableLabels() { const tables = document.querySelectorAll('.table'); tables.forEach(table => { const headers = Array.from(table.querySelectorAll('thead th')).map(th => th.textContent.trim()); const rows = table.querySelectorAll('tbody tr'); rows.forEach(row => { const cells = row.querySelectorAll('td'); cells.forEach((cell, index) => { if (headers[index]) { cell.setAttribute('data-label', headers[index]); } }); }); }); } // Enhanced mobile navigation setupResponsiveNavigation() { const navbar = document.querySelector('.navbar'); const toggler = document.querySelector('.navbar-toggler'); const collapse = document.querySelector('.navbar-collapse'); if (toggler && collapse) { // Smooth collapse animation toggler.addEventListener('click', () => { collapse.classList.toggle('show'); }); // Close menu when clicking outside document.addEventListener('click', (e) => { if (!navbar.contains(e.target) && collapse.classList.contains('show')) { collapse.classList.remove('show'); } }); } } // Form enhancements for better mobile UX setupFormEnhancements() { // Auto-focus first input on desktop if (window.innerWidth > 768) { const firstInput = document.querySelector('.form-control:not([readonly]):not([disabled])'); if (firstInput) { firstInput.focus(); } } // Enhanced form validation feedback const forms = document.querySelectorAll('form'); forms.forEach(form => { form.addEventListener('submit', (e) => { // Skip validation for file upload forms if (form.enctype === 'multipart/form-data') { console.log('Mobile: Skipping validation for file upload form'); return; } const invalidInputs = form.querySelectorAll(':invalid'); if (invalidInputs.length > 0) { e.preventDefault(); console.log('Mobile: Form validation failed, focusing on first invalid input'); invalidInputs[0].focus(); invalidInputs[0].scrollIntoView({ behavior: 'smooth', block: 'center' }); } }); }); // Floating labels effect const inputs = document.querySelectorAll('.form-control, .form-select'); inputs.forEach(input => { if (input.value) { input.parentElement.classList.add('has-value'); } input.addEventListener('blur', () => { if (input.value) { input.parentElement.classList.add('has-value'); } else { input.parentElement.classList.remove('has-value'); } }); }); } // Smooth interactions and feedback setupSmoothInteractions() { // Button click feedback const buttons = document.querySelectorAll('.btn'); buttons.forEach(button => { button.addEventListener('click', (e) => { if (!button.disabled) { button.style.transform = 'scale(0.95)'; setTimeout(() => { button.style.transform = ''; }, 100); } }); }); // Card hover enhancement const cards = document.querySelectorAll('.card'); cards.forEach(card => { card.addEventListener('mouseenter', () => { card.style.transform = 'translateY(-2px)'; }); card.addEventListener('mouseleave', () => { card.style.transform = ''; }); }); // Smooth scroll for anchor links const anchorLinks = document.querySelectorAll('a[href^="#"]'); anchorLinks.forEach(link => { link.addEventListener('click', (e) => { e.preventDefault(); const target = document.querySelector(link.getAttribute('href')); if (target) { target.scrollIntoView({ behavior: 'smooth' }); } }); }); } // Show toast notification showToast(message, type = 'info') { const toastContainer = document.getElementById('toast-container') || this.createToastContainer(); const toast = document.createElement('div'); toast.className = `alert alert-${type} alert-dismissible fade show`; toast.style.cssText = ` margin-bottom: 0.5rem; animation: slideInRight 0.3s ease; `; toast.innerHTML = ` ${message} `; toastContainer.appendChild(toast); // Auto-remove after 4 seconds setTimeout(() => { toast.classList.add('fade'); setTimeout(() => { if (toast.parentNode) { toast.parentNode.removeChild(toast); } }, 150); }, 4000); // Manual close const closeBtn = toast.querySelector('.btn-close'); closeBtn.addEventListener('click', () => { toast.classList.add('fade'); setTimeout(() => { if (toast.parentNode) { toast.parentNode.removeChild(toast); } }, 150); }); } createToastContainer() { const container = document.createElement('div'); container.id = 'toast-container'; container.style.cssText = ` position: fixed; top: 20px; right: 20px; z-index: 1050; max-width: 300px; `; document.body.appendChild(container); return container; } } // CSS for toast animations const style = document.createElement('style'); style.textContent = ` @keyframes slideInRight { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } .fade { opacity: 0 !important; transition: opacity 0.15s linear !important; } `; document.head.appendChild(style); // Initialize const modernMobile = new ModernMobile(); window.modernMobile = modernMobile;