HEX
Server: LiteSpeed
System: Linux srv1.dhviews.com 5.14.0-570.23.1.el9_6.x86_64 #1 SMP PREEMPT_DYNAMIC Tue Jun 24 11:27:16 EDT 2025 x86_64
User: bdedition (1723)
PHP: 7.4.33
Disabled: NONE
Upload Files
File: //home/bdedition/bddiary.com/assets/js/app.js
/*
  Professional JavaScript enhancements for Bootstrap 5+ design
  Additional functionality and UI improvements
*/

// Enhanced UI interactions
document.addEventListener('DOMContentLoaded', function() {
  
  // Smooth reveal animations for cards
  const observerOptions = {
    threshold: 0.1,
    rootMargin: '0px 0px -50px 0px'
  };

  const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        entry.target.classList.add('fade-in');
        observer.unobserve(entry.target);
      }
    });
  }, observerOptions);

  // Observe all cards for animation
  document.querySelectorAll('.card-custom').forEach(card => {
    observer.observe(card);
  });

  // Enhanced keyboard navigation
  document.addEventListener('keydown', function(e) {
    // ESC key to close any active states
    if (e.key === 'Escape') {
      const activeModals = document.querySelectorAll('.modal.show');
      activeModals.forEach(modal => {
        const modalInstance = bootstrap.Modal.getInstance(modal);
        if (modalInstance) {
          modalInstance.hide();
        }
      });
    }
    
    // Enter key on focused buttons
    if (e.key === 'Enter' && document.activeElement.classList.contains('btn')) {
      document.activeElement.click();
    }
  });

  // Professional loading states
  function setLoadingState(element, isLoading) {
    if (isLoading) {
      element.disabled = true;
      element.classList.add('btn-loading');
      const originalText = element.innerHTML;
      element.dataset.originalText = originalText;
      element.innerHTML = `<span class="spinner-border spinner-border-sm me-2" role="status"></span>Loading...`;
    } else {
      element.disabled = false;
      element.classList.remove('btn-loading');
      if (element.dataset.originalText) {
        element.innerHTML = element.dataset.originalText;
      }
    }
  }

  // Export enhanced loading function for use in main app
  window.setLoadingState = setLoadingState;

  // Enhanced tooltips
  const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
  const tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
    return new bootstrap.Tooltip(tooltipTriggerEl);
  });

  // Auto-hide alerts after delay
  document.querySelectorAll('.alert').forEach(alert => {
    setTimeout(() => {
      const alertInstance = new bootstrap.Alert(alert);
      alertInstance.close();
    }, 5000);
  });

  // Enhanced form validation
  const forms = document.querySelectorAll('form');
  forms.forEach(form => {
    form.addEventListener('submit', function(e) {
      if (!form.checkValidity()) {
        e.preventDefault();
        e.stopPropagation();
      }
      form.classList.add('was-validated');
    });
  });

  // Smooth scrolling to sections
  function scrollToSection(sectionId) {
    const section = document.getElementById(sectionId);
    if (section) {
      section.scrollIntoView({
        behavior: 'smooth',
        block: 'start'
      });
    }
  }

  window.scrollToSection = scrollToSection;

  // Performance optimization - lazy load images
  const images = document.querySelectorAll('img[data-src]');
  const imageObserver = new IntersectionObserver((entries, observer) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        const img = entry.target;
        img.src = img.dataset.src;
        img.removeAttribute('data-src');
        imageObserver.unobserve(img);
      }
    });
  });

  images.forEach(img => imageObserver.observe(img));

  // Add professional focus management
  let lastFocusedElement = null;
  
  document.addEventListener('focusin', function(e) {
    lastFocusedElement = e.target;
  });

  // Restore focus when modals close
  document.addEventListener('hidden.bs.modal', function() {
    if (lastFocusedElement) {
      lastFocusedElement.focus();
    }
  });
});

// Enhanced error handling
window.addEventListener('error', function(e) {
  console.error('JavaScript Error:', e.error);
  // Could show user-friendly error message here
});

// Professional resize handler
let resizeTimeout;
window.addEventListener('resize', function() {
  clearTimeout(resizeTimeout);
  resizeTimeout = setTimeout(function() {
    // Trigger custom resize event for canvas and other components
    window.dispatchEvent(new Event('optimizedResize'));
  }, 250);
});

// Export utilities for global use
window.UIUtils = {
  setLoadingState,
  scrollToSection,
  
  // Show professional notifications
  showNotification: function(message, type = 'info', duration = 3000) {
    const alertDiv = document.createElement('div');
    alertDiv.className = `alert alert-${type} alert-dismissible fade show position-fixed`;
    alertDiv.style.cssText = 'top: 20px; right: 20px; z-index: 1060; min-width: 300px;';
    alertDiv.innerHTML = `
      ${message}
      <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
    `;
    
    document.body.appendChild(alertDiv);
    
    setTimeout(() => {
      const alert = new bootstrap.Alert(alertDiv);
      alert.close();
    }, duration);
  },
  
  // Confirm dialog
  confirm: function(message, callback) {
    if (window.confirm(message)) {
      callback();
    }
  }
};