277 Zeilen
8.8 KiB
JavaScript
277 Zeilen
8.8 KiB
JavaScript
/**
|
|
* 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(); |