/** * Main application entry point for IntelSight website * Initializes all modules and coordinates application startup */ /** * Toggle tools grid visibility */ function toggleTools(button) { // Find the tools grid within the same product card const productCard = button.closest('.product-card'); const toolsGrid = productCard.querySelector('.tools-grid'); if (toolsGrid) { const isExpanded = toolsGrid.classList.contains('expanded'); const currentLang = getCurrentLanguage ? getCurrentLanguage() : 'de'; if (isExpanded) { toolsGrid.classList.remove('expanded'); toolsGrid.classList.add('collapsed'); button.setAttribute('data-expanded', 'false'); button.querySelector('span').textContent = currentLang === 'de' ? 'Details anzeigen' : 'Show Details'; } else { // Force browser reflow before adding expanded class toolsGrid.style.display = 'grid'; void toolsGrid.offsetHeight; // Trigger reflow toolsGrid.classList.remove('collapsed'); toolsGrid.classList.add('expanded'); button.setAttribute('data-expanded', 'true'); button.querySelector('span').textContent = currentLang === 'de' ? 'Details verbergen' : 'Hide Details'; // Ensure all tool cards are visible setTimeout(() => { const toolCards = toolsGrid.querySelectorAll('.tool-card'); toolCards.forEach((card, index) => { card.style.opacity = '1'; card.style.transform = 'translateY(0)'; }); }, 100); } } } /** * Application initialization */ const App = { /** * Initialize the entire application */ init() { // Check DOM ready state if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => this.start()); } else { // DOM is already ready this.start(); } }, /** * Start the application after DOM is ready */ start() { console.log('IntelSight Website Initializing...'); // Initialize modules in correct order try { // 1. Initialize translations first (needed by components) initTranslations(); console.log('✓ Translations initialized'); // 2. Initialize UI components Components.init(); console.log('✓ Components initialized'); // 3. Initialize animations Animations.init(); console.log('✓ Animations initialized'); // 4. Setup error handling this.setupErrorHandling(); // 5. Setup performance monitoring this.setupPerformanceMonitoring(); console.log('IntelSight Website Ready!'); } catch (error) { console.error('Failed to initialize application:', error); this.handleInitError(error); } }, /** * Setup global error handling */ setupErrorHandling() { window.addEventListener('error', (event) => { console.error('Global error:', event.error); // In production, this would send errors to monitoring service }); window.addEventListener('unhandledrejection', (event) => { console.error('Unhandled promise rejection:', event.reason); // In production, this would send errors to monitoring service }); }, /** * Setup performance monitoring */ setupPerformanceMonitoring() { // Monitor page load performance window.addEventListener('load', () => { if (window.performance && window.performance.timing) { const timing = window.performance.timing; const loadTime = timing.loadEventEnd - timing.navigationStart; console.log(`Page load time: ${loadTime}ms`); // Log other performance metrics const metrics = { domContentLoaded: timing.domContentLoadedEventEnd - timing.navigationStart, domComplete: timing.domComplete - timing.navigationStart, firstPaint: this.getFirstPaintTime() }; console.log('Performance metrics:', metrics); } }); }, /** * Get first paint time if available * @returns {number|null} First paint time in milliseconds */ getFirstPaintTime() { if (window.performance && window.performance.getEntriesByType) { const paintEntries = window.performance.getEntriesByType('paint'); const firstPaint = paintEntries.find(entry => entry.name === 'first-paint'); return firstPaint ? Math.round(firstPaint.startTime) : null; } return null; }, /** * Handle initialization errors * @param {Error} error - The error that occurred */ handleInitError(error) { // Create a fallback error message for users const errorContainer = document.createElement('div'); errorContainer.style.cssText = ` position: fixed; top: 20px; right: 20px; background: #ff4444; color: white; padding: 15px 20px; border-radius: 5px; z-index: 10000; max-width: 300px; box-shadow: 0 2px 10px rgba(0,0,0,0.2); `; errorContainer.textContent = 'Ein Fehler ist aufgetreten. Bitte laden Sie die Seite neu.'; document.body.appendChild(errorContainer); // Auto-remove after 5 seconds setTimeout(() => { errorContainer.remove(); }, 5000); } }; /** * Utility functions */ const Utils = { /** * Debounce function to limit function calls * @param {Function} func - Function to debounce * @param {number} wait - Wait time in milliseconds * @returns {Function} Debounced function */ debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; }, /** * Throttle function to limit function calls * @param {Function} func - Function to throttle * @param {number} limit - Time limit in milliseconds * @returns {Function} Throttled function */ throttle(func, limit) { let inThrottle; return function(...args) { if (!inThrottle) { func.apply(this, args); inThrottle = true; setTimeout(() => inThrottle = false, limit); } }; }, /** * Check if element is in viewport * @param {HTMLElement} element - Element to check * @returns {boolean} True if element is in viewport */ isInViewport(element) { const rect = element.getBoundingClientRect(); return ( rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth) ); }, /** * Load script dynamically * @param {string} src - Script source URL * @returns {Promise} Promise that resolves when script is loaded */ loadScript(src) { return new Promise((resolve, reject) => { const script = document.createElement('script'); script.src = src; script.onload = resolve; script.onerror = reject; document.head.appendChild(script); }); }, /** * Get cookie value by name * @param {string} name - Cookie name * @returns {string|null} Cookie value or null */ getCookie(name) { const value = `; ${document.cookie}`; const parts = value.split(`; ${name}=`); if (parts.length === 2) { return parts.pop().split(';').shift(); } return null; }, /** * Set cookie * @param {string} name - Cookie name * @param {string} value - Cookie value * @param {number} days - Days until expiration */ setCookie(name, value, days) { const date = new Date(); date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); const expires = `expires=${date.toUTCString()}`; document.cookie = `${name}=${value};${expires};path=/`; } }; // Make Utils globally available if needed window.Utils = Utils; // Start the application App.init();