feat: Quellmaterial vom Live-Server — Seiten, Blog, CSS, Bilder
- _live_*.html: index, faq, ueber-uns, leistungen, kontakt (existierende Inhalte) - _quelle/blog/: 10 Blog-Artikel der bisherigen Seite - _quelle/legal/: Impressum, Datenschutz, Affiliate - _quelle/css/: styles.css (375 Design-Regeln) - _quelle/images/: 6 Bilder (Hero, Logo, DSGVO, Mobile, Kosten, Zeitersparnis) - ftp-creds via bsn-secrets gesichert
This commit is contained in:
@@ -0,0 +1,223 @@
|
||||
/**
|
||||
* IT-Hilfe Sofort - Main JavaScript
|
||||
* Cookie Consent, Mobile Navigation, Form Handling
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// ========================================
|
||||
// Cookie Consent Management (DSGVO)
|
||||
// ========================================
|
||||
const CookieConsent = {
|
||||
storageKey: 'it-hilfe-cookie-consent',
|
||||
|
||||
init() {
|
||||
const consent = this.getConsent();
|
||||
if (!consent) {
|
||||
this.showBanner();
|
||||
} else if (consent.analytics) {
|
||||
this.loadAnalytics();
|
||||
}
|
||||
},
|
||||
|
||||
getConsent() {
|
||||
try {
|
||||
return JSON.parse(localStorage.getItem(this.storageKey));
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
saveConsent(consent) {
|
||||
localStorage.setItem(this.storageKey, JSON.stringify(consent));
|
||||
},
|
||||
|
||||
showBanner() {
|
||||
const banner = document.getElementById('cookie-banner');
|
||||
if (banner) {
|
||||
banner.classList.remove('hidden');
|
||||
|
||||
document.getElementById('cookie-accept')?.addEventListener('click', () => {
|
||||
this.saveConsent({ essential: true, analytics: true, marketing: true });
|
||||
this.loadAnalytics();
|
||||
banner.classList.add('hidden');
|
||||
});
|
||||
|
||||
document.getElementById('cookie-essential')?.addEventListener('click', () => {
|
||||
this.saveConsent({ essential: true, analytics: false, marketing: false });
|
||||
banner.classList.add('hidden');
|
||||
});
|
||||
|
||||
document.getElementById('cookie-settings')?.addEventListener('click', () => {
|
||||
// TODO: Open settings modal
|
||||
alert('Cookie-Einstellungen werden in Kürze verfügbar sein.');
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
loadAnalytics() {
|
||||
// Placeholder for analytics loading (e.g., Matomo, Plausible)
|
||||
// Only loads after explicit consent
|
||||
console.log('Analytics geladen (nach Consent)');
|
||||
}
|
||||
};
|
||||
|
||||
// ========================================
|
||||
// Mobile Navigation
|
||||
// ========================================
|
||||
const MobileNav = {
|
||||
init() {
|
||||
const toggle = document.querySelector('.nav-toggle');
|
||||
const menu = document.querySelector('.nav-menu');
|
||||
|
||||
if (toggle && menu) {
|
||||
toggle.addEventListener('click', () => {
|
||||
menu.classList.toggle('active');
|
||||
toggle.setAttribute('aria-expanded',
|
||||
menu.classList.contains('active'));
|
||||
});
|
||||
|
||||
// Close menu on link click
|
||||
menu.querySelectorAll('a').forEach(link => {
|
||||
link.addEventListener('click', () => {
|
||||
menu.classList.remove('active');
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ========================================
|
||||
// Form Validation (Kontaktformular)
|
||||
// ========================================
|
||||
const FormHandler = {
|
||||
init() {
|
||||
const forms = document.querySelectorAll('form[data-validate]');
|
||||
forms.forEach(form => this.attachValidation(form));
|
||||
},
|
||||
|
||||
attachValidation(form) {
|
||||
form.addEventListener('submit', (e) => {
|
||||
const errors = this.validateForm(form);
|
||||
if (errors.length > 0) {
|
||||
e.preventDefault();
|
||||
this.showErrors(form, errors);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
validateForm(form) {
|
||||
const errors = [];
|
||||
const required = form.querySelectorAll('[required]');
|
||||
|
||||
required.forEach(field => {
|
||||
if (!field.value.trim()) {
|
||||
errors.push({
|
||||
field: field.name,
|
||||
message: 'Dieses Feld ist erforderlich'
|
||||
});
|
||||
}
|
||||
|
||||
if (field.type === 'email' && field.value) {
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(field.value)) {
|
||||
errors.push({
|
||||
field: field.name,
|
||||
message: 'Bitte geben Sie eine gültige E-Mail-Adresse ein'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Check consent checkbox
|
||||
const consent = form.querySelector('input[name="datenschutz"]');
|
||||
if (consent && !consent.checked) {
|
||||
errors.push({
|
||||
field: 'datenschutz',
|
||||
message: 'Sie müssen der Datenschutzerklärung zustimmen'
|
||||
});
|
||||
}
|
||||
|
||||
return errors;
|
||||
},
|
||||
|
||||
showErrors(form, errors) {
|
||||
// Remove existing errors
|
||||
form.querySelectorAll('.error-message').forEach(el => el.remove());
|
||||
form.querySelectorAll('.error').forEach(el => el.classList.remove('error'));
|
||||
|
||||
errors.forEach(error => {
|
||||
const field = form.querySelector(`[name="${error.field}"]`);
|
||||
if (field) {
|
||||
field.classList.add('error');
|
||||
const errorEl = document.createElement('small');
|
||||
errorEl.className = 'error-message';
|
||||
errorEl.textContent = error.message;
|
||||
errorEl.style.color = '#dc2626';
|
||||
errorEl.style.fontSize = '0.875rem';
|
||||
field.parentNode.insertBefore(errorEl, field.nextSibling);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// ========================================
|
||||
// Lazy Loading Images
|
||||
// ========================================
|
||||
const LazyLoader = {
|
||||
init() {
|
||||
if ('IntersectionObserver' in window) {
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
const img = entry.target;
|
||||
img.src = img.dataset.src;
|
||||
img.removeAttribute('data-src');
|
||||
observer.unobserve(img);
|
||||
}
|
||||
});
|
||||
}, { rootMargin: '50px' });
|
||||
|
||||
document.querySelectorAll('img[data-src]').forEach(img => {
|
||||
observer.observe(img);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ========================================
|
||||
// Smooth Scroll for Anchor Links
|
||||
// ========================================
|
||||
const SmoothScroll = {
|
||||
init() {
|
||||
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
||||
anchor.addEventListener('click', function(e) {
|
||||
const targetId = this.getAttribute('href');
|
||||
if (targetId === '#') return;
|
||||
|
||||
const target = document.querySelector(targetId);
|
||||
if (target) {
|
||||
e.preventDefault();
|
||||
target.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'start'
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// ========================================
|
||||
// Initialize All Modules
|
||||
// ========================================
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
CookieConsent.init();
|
||||
MobileNav.init();
|
||||
FormHandler.init();
|
||||
LazyLoader.init();
|
||||
SmoothScroll.init();
|
||||
});
|
||||
|
||||
})();
|
||||
Reference in New Issue
Block a user