Files
web7sys/website-7sys/script.js
2024-11-03 05:57:56 +01:00

329 lines
11 KiB
JavaScript

document.addEventListener('DOMContentLoaded', () => {
initThemeToggle();
initSmoothScroll();
initFormValidation();
initAnimations();
initScrollProgress();
initStarryBackground();
initCookieConsent();
});
function initThemeToggle() {
const themeToggle = document.getElementById('theme-toggle');
const body = document.body;
const icon = themeToggle.querySelector('i');
// Check for saved theme preference
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
body.className = savedTheme;
updateIcon(savedTheme === 'light-theme');
}
// Theme toggle functionality
themeToggle.addEventListener('click', () => {
const isLight = body.classList.toggle('light-theme');
localStorage.setItem('theme', isLight ? 'light-theme' : 'dark-theme');
updateIcon(isLight);
});
function updateIcon(isLight) {
icon.className = isLight ? 'fas fa-moon' : 'fas fa-sun';
icon.style.animation = 'iconBounce 0.5s ease';
setTimeout(() => icon.style.animation = '', 500);
}
}
function initScrollProgress() {
const progressBar = document.querySelector('.scroll-progress');
window.addEventListener('scroll', () => {
const winScroll = document.body.scrollTop || document.documentElement.scrollTop;
const height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
const scrolled = (winScroll / height) * 100;
progressBar.style.transform = `scaleX(${scrolled / 100})`;
});
}
function initStarryBackground() {
const starsContainer = document.querySelector('.stars');
const numStars = 50;
// Create stars
for (let i = 0; i < numStars; i++) {
const star = document.createElement('div');
star.className = 'star';
star.style.width = Math.random() * 3 + 'px';
star.style.height = star.style.width;
star.style.left = Math.random() * 100 + '%';
star.style.top = Math.random() * 100 + '%';
star.style.animationDelay = Math.random() * 2 + 's';
starsContainer.appendChild(star);
}
}
function initSmoothScroll() {
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
const headerOffset = 60;
const elementPosition = target.getBoundingClientRect().top;
const offsetPosition = elementPosition + window.pageYOffset - headerOffset;
window.scrollTo({
top: offsetPosition,
behavior: 'smooth'
});
}
});
});
}
function initFormValidation() {
const form = document.querySelector('.contact-form');
if (!form) return;
const inputs = {
name: form.querySelector('#name'),
email: form.querySelector('#email'),
phone: form.querySelector('#phone'),
message: form.querySelector('#message')
};
const submitButton = form.querySelector('.submit-button');
const buttonText = submitButton.querySelector('.button-text');
const loadingSpinner = submitButton.querySelector('.loading-spinner');
const feedbackDiv = form.querySelector('.form-feedback');
const messageCounter = form.querySelector('.char-counter');
// Initialize character counter
if (inputs.message && messageCounter) {
const maxLength = inputs.message.getAttribute('maxlength');
updateCharCounter(inputs.message.value.length, maxLength);
inputs.message.addEventListener('input', (e) => {
const length = e.target.value.length;
updateCharCounter(length, maxLength);
});
}
function updateCharCounter(current, max) {
messageCounter.textContent = `${current} / ${max}`;
// Add visual feedback when approaching limit
if (current >= max * 0.9) {
messageCounter.style.color = 'var(--error-red)';
} else if (current >= max * 0.8) {
messageCounter.style.color = 'var(--warning-yellow)';
} else {
messageCounter.style.color = 'var(--text-muted)';
}
}
// Real-time validation
Object.values(inputs).forEach(input => {
if (!input) return;
['input', 'blur'].forEach(eventType => {
input.addEventListener(eventType, () => {
validateInput(input);
updateSubmitButton();
});
});
// Add focus effects
input.addEventListener('focus', () => {
input.closest('.input-wrapper').classList.add('focused');
});
input.addEventListener('blur', () => {
input.closest('.input-wrapper').classList.remove('focused');
});
});
function validateInput(input) {
if (!input.required && input.value === '') {
// Optional fields are valid when empty
const wrapper = input.closest('.input-wrapper');
wrapper.classList.remove('invalid', 'valid');
return true;
}
const isValid = input.checkValidity();
const wrapper = input.closest('.input-wrapper');
wrapper.classList.toggle('invalid', !isValid);
wrapper.classList.toggle('valid', isValid);
// Show validation message
let errorMessage = '';
if (!isValid) {
if (input.validity.valueMissing) {
errorMessage = 'Dieses Feld ist erforderlich';
} else if (input.validity.typeMismatch) {
errorMessage = 'Bitte geben Sie ein gültiges Format ein';
} else if (input.validity.patternMismatch) {
errorMessage = input.title;
} else if (input.validity.tooShort) {
const minLength = input.getAttribute('minlength');
errorMessage = `Mindestens ${minLength} Zeichen erforderlich`;
}
}
let errorElement = wrapper.querySelector('.error-message');
if (!errorElement && errorMessage) {
errorElement = document.createElement('div');
errorElement.className = 'error-message';
wrapper.appendChild(errorElement);
}
if (errorElement) {
if (errorMessage) {
errorElement.textContent = errorMessage;
errorElement.style.display = 'flex';
} else {
errorElement.style.display = 'none';
}
}
return isValid;
}
function updateSubmitButton() {
const requiredInputs = Object.values(inputs).filter(input => input && input.required);
const isFormValid = requiredInputs.every(input => input.checkValidity());
submitButton.disabled = !isFormValid;
// Visual feedback
submitButton.classList.toggle('ready', isFormValid);
}
form.addEventListener('submit', async (e) => {
e.preventDefault();
const requiredInputs = Object.values(inputs).filter(input => input && input.required);
if (!requiredInputs.every(input => validateInput(input))) {
showFeedback('Bitte füllen Sie alle Pflichtfelder korrekt aus.', false);
return;
}
// Show loading state
submitButton.disabled = true;
buttonText.style.opacity = '0';
loadingSpinner.style.display = 'block';
try {
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 1500));
showFeedback('Vielen Dank für Ihre Nachricht! Wir werden uns in Kürze bei Ihnen melden.', true);
form.reset();
// Reset validation states
Object.values(inputs).forEach(input => {
if (!input) return;
const wrapper = input.closest('.input-wrapper');
wrapper.classList.remove('valid', 'invalid', 'focused');
const errorElement = wrapper.querySelector('.error-message');
if (errorElement) {
errorElement.style.display = 'none';
}
});
// Reset character counter
if (messageCounter) {
updateCharCounter(0, inputs.message.getAttribute('maxlength'));
}
} catch (error) {
showFeedback('Es ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut.', false);
} finally {
// Reset button state
submitButton.disabled = false;
buttonText.style.opacity = '1';
loadingSpinner.style.display = 'none';
submitButton.classList.remove('ready');
}
});
function showFeedback(message, isSuccess) {
feedbackDiv.textContent = message;
feedbackDiv.className = `form-feedback ${isSuccess ? 'success' : 'error'}`;
feedbackDiv.style.display = 'block';
// Scroll feedback into view
feedbackDiv.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
// Animate feedback
feedbackDiv.style.animation = 'scaleIn 0.3s ease forwards';
// Auto-hide feedback after 5 seconds
setTimeout(() => {
feedbackDiv.style.animation = 'fadeOut 0.3s ease forwards';
setTimeout(() => {
feedbackDiv.style.display = 'none';
}, 300);
}, 5000);
}
}
function initAnimations() {
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('visible');
// Add stagger effect to child elements
const children = entry.target.querySelectorAll('.animate-stagger');
children.forEach((child, index) => {
child.style.animationDelay = `${index * 0.1}s`;
child.classList.add('visible');
});
observer.unobserve(entry.target);
}
});
}, observerOptions);
// Observe elements
document.querySelectorAll('.service-card, .vision-item, .fade-in-scroll').forEach(el => {
observer.observe(el);
});
}
function initCookieConsent() {
const cookieConsent = document.getElementById('cookie-consent');
const acceptButton = document.getElementById('accept-cookies');
const rejectButton = document.getElementById('reject-cookies');
// Check if user has already made a choice
const cookieChoice = localStorage.getItem('cookieChoice');
if (!cookieChoice) {
setTimeout(() => {
cookieConsent.style.display = 'flex';
cookieConsent.style.animation = 'slideUp 0.5s ease forwards';
}, 1000);
}
acceptButton.addEventListener('click', () => {
localStorage.setItem('cookieChoice', 'accepted');
hideCookieConsent();
});
rejectButton.addEventListener('click', () => {
localStorage.setItem('cookieChoice', 'rejected');
hideCookieConsent();
});
function hideCookieConsent() {
cookieConsent.style.animation = 'slideDown 0.5s ease forwards';
setTimeout(() => {
cookieConsent.style.display = 'none';
}, 500);
}
}