Update imprint data and remove trust indicators
- Fix impressum.html with correct HRB 110105 and Amtsgericht Düsseldorf - Add English versions of legal pages (impressum-en.html, datenschutz-en.html) - Correct company representatives to Hendrik Gebhardt & Monami Homma - Remove incorrect Marlon Paulse references and Wiesenstraße address - Remove trust-indicators section from website (HTML, CSS, JS) - Add mobile.css and related mobile navigation files 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Dieser Commit ist enthalten in:
196
js/mobile-nav.js
Normale Datei
196
js/mobile-nav.js
Normale Datei
@ -0,0 +1,196 @@
|
||||
/**
|
||||
* Mobile Navigation Handler
|
||||
* Clean, accessible mobile navigation implementation
|
||||
*/
|
||||
|
||||
class MobileNavigation {
|
||||
constructor() {
|
||||
this.menuToggle = document.querySelector('.mobile-menu-toggle');
|
||||
this.mobileMenu = document.querySelector('.nav-menu-mobile');
|
||||
this.overlay = document.querySelector('.mobile-menu-overlay');
|
||||
this.menuLinks = document.querySelectorAll('.nav-menu-mobile a');
|
||||
this.closeButton = document.querySelector('.mobile-menu-close');
|
||||
this.isOpen = false;
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
if (!this.menuToggle || !this.mobileMenu) return;
|
||||
|
||||
// Toggle button click
|
||||
this.menuToggle.addEventListener('click', () => this.toggleMenu());
|
||||
|
||||
// Close button click
|
||||
if (this.closeButton) {
|
||||
this.closeButton.addEventListener('click', () => this.closeMenu());
|
||||
}
|
||||
|
||||
// Overlay click closes menu
|
||||
this.overlay.addEventListener('click', () => this.closeMenu());
|
||||
|
||||
// Menu links click closes menu
|
||||
this.menuLinks.forEach(link => {
|
||||
link.addEventListener('click', () => this.closeMenu());
|
||||
});
|
||||
|
||||
// ESC key closes menu
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape' && this.isOpen) {
|
||||
this.closeMenu();
|
||||
}
|
||||
});
|
||||
|
||||
// Prevent body scroll when menu is open
|
||||
this.handleBodyScroll();
|
||||
}
|
||||
|
||||
toggleMenu() {
|
||||
this.isOpen ? this.closeMenu() : this.openMenu();
|
||||
}
|
||||
|
||||
openMenu() {
|
||||
this.isOpen = true;
|
||||
this.menuToggle.classList.add('active');
|
||||
this.mobileMenu.classList.add('active');
|
||||
this.overlay.classList.add('active');
|
||||
|
||||
// Update ARIA attributes
|
||||
this.menuToggle.setAttribute('aria-expanded', 'true');
|
||||
this.mobileMenu.setAttribute('aria-hidden', 'false');
|
||||
|
||||
// Prevent body scroll
|
||||
document.body.style.overflow = 'hidden';
|
||||
|
||||
// Focus management
|
||||
setTimeout(() => {
|
||||
const firstLink = this.mobileMenu.querySelector('a');
|
||||
if (firstLink) firstLink.focus();
|
||||
}, 300);
|
||||
}
|
||||
|
||||
closeMenu() {
|
||||
this.isOpen = false;
|
||||
this.menuToggle.classList.remove('active');
|
||||
this.mobileMenu.classList.remove('active');
|
||||
this.overlay.classList.remove('active');
|
||||
|
||||
// Update ARIA attributes
|
||||
this.menuToggle.setAttribute('aria-expanded', 'false');
|
||||
this.mobileMenu.setAttribute('aria-hidden', 'true');
|
||||
|
||||
// Restore body scroll
|
||||
document.body.style.overflow = '';
|
||||
|
||||
// Return focus to toggle button
|
||||
this.menuToggle.focus();
|
||||
}
|
||||
|
||||
handleBodyScroll() {
|
||||
// Save scroll position when menu opens
|
||||
let scrollPosition = 0;
|
||||
|
||||
const observer = new MutationObserver(() => {
|
||||
if (this.isOpen) {
|
||||
scrollPosition = window.pageYOffset;
|
||||
document.body.style.position = 'fixed';
|
||||
document.body.style.top = `-${scrollPosition}px`;
|
||||
document.body.style.width = '100%';
|
||||
} else {
|
||||
document.body.style.position = '';
|
||||
document.body.style.top = '';
|
||||
document.body.style.width = '';
|
||||
window.scrollTo(0, scrollPosition);
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(this.mobileMenu, {
|
||||
attributes: true,
|
||||
attributeFilter: ['class']
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Smooth scroll for anchor links
|
||||
class SmoothScroll {
|
||||
constructor() {
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
||||
anchor.addEventListener('click', (e) => {
|
||||
const href = anchor.getAttribute('href');
|
||||
if (href === '#') return;
|
||||
|
||||
e.preventDefault();
|
||||
const target = document.querySelector(href);
|
||||
|
||||
if (target) {
|
||||
const offset = 80; // Account for fixed navbar
|
||||
const targetPosition = target.offsetTop - offset;
|
||||
|
||||
window.scrollTo({
|
||||
top: targetPosition,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Responsive image loading
|
||||
class ResponsiveImages {
|
||||
constructor() {
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
// Check if user prefers reduced motion
|
||||
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||
|
||||
if (prefersReducedMotion) {
|
||||
// Disable animations
|
||||
document.documentElement.style.setProperty('--animation-duration', '0.01s');
|
||||
}
|
||||
|
||||
// Lazy load images on mobile
|
||||
if ('IntersectionObserver' in window && window.innerWidth <= 768) {
|
||||
const images = document.querySelectorAll('img[data-src]');
|
||||
|
||||
const imageObserver = new IntersectionObserver((entries) => {
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize on DOM load
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
new MobileNavigation();
|
||||
new SmoothScroll();
|
||||
new ResponsiveImages();
|
||||
|
||||
// Hide mobile menu button styles until JS loads
|
||||
document.documentElement.classList.add('js-loaded');
|
||||
});
|
||||
|
||||
// Handle orientation change
|
||||
window.addEventListener('orientationchange', () => {
|
||||
// Close mobile menu on orientation change
|
||||
const mobileNav = document.querySelector('.nav-menu-mobile');
|
||||
if (mobileNav && mobileNav.classList.contains('active')) {
|
||||
const event = new Event('click');
|
||||
document.querySelector('.mobile-menu-overlay').dispatchEvent(event);
|
||||
}
|
||||
});
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren