eis-website/js/script.js

342 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ===========================
// Dark Mode Toggle
// ===========================
// Sofort beim Laden: Dark Mode Preference wiederherstellen
// Ab 16:00 Uhr automatisch Dark Mode, sofern kein manueller Override gespeichert ist
(function() {
const saved = localStorage.getItem('darkMode');
const hour = new Date().getHours();
const autoDark = hour >= 16;
const useDark = saved !== null ? saved === 'true' : autoDark;
if (useDark) {
document.documentElement.classList.add('dark');
document.body.classList.add('dark');
}
})();
// Nach DOM Load: Event Listener attachen
document.addEventListener('DOMContentLoaded', function() {
const darkModeToggle = document.getElementById('dark-mode-toggle');
if (darkModeToggle) {
const icon = darkModeToggle.querySelector('.dark-mode-icon');
// Icon auf aktuellen Status setzen
const isDarkMode = localStorage.getItem('darkMode') === 'true';
icon.textContent = isDarkMode ? '☀️' : '🌙';
// Click-Handler
darkModeToggle.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
// Toggle Dark Mode
document.body.classList.toggle('dark');
document.documentElement.classList.toggle('dark');
// Manuellen Override in localStorage speichern
const darkModeState = document.body.classList.contains('dark');
localStorage.setItem('darkMode', darkModeState ? 'true' : 'false');
// Icon aktualisieren
icon.textContent = darkModeState ? '☀️' : '🌙';
});
}
// ===========================
// Hamburger Navigation
// ===========================
const navToggle = document.getElementById('nav-toggle');
const mainNav = document.getElementById('main-nav');
if (navToggle && mainNav) {
navToggle.addEventListener('click', function(e) {
e.stopPropagation();
const isOpen = mainNav.classList.toggle('open');
navToggle.classList.toggle('open', isOpen);
navToggle.setAttribute('aria-expanded', String(isOpen));
});
// Menü schließen wenn ein Link geklickt wird
mainNav.querySelectorAll('a').forEach(function(link) {
link.addEventListener('click', function() {
mainNav.classList.remove('open');
navToggle.classList.remove('open');
navToggle.setAttribute('aria-expanded', 'false');
});
});
// Menü schließen bei Klick außerhalb
document.addEventListener('click', function(e) {
if (!navToggle.contains(e.target) && !mainNav.contains(e.target)) {
mainNav.classList.remove('open');
navToggle.classList.remove('open');
navToggle.setAttribute('aria-expanded', 'false');
}
});
}
// ===========================
// Dropdown "Start" Touch/Click Toggle
// ===========================
const dropdowns = document.querySelectorAll('.nav-dropdown');
dropdowns.forEach(function(dd) {
const trigger = dd.querySelector('.nav-dropdown-trigger');
if (!trigger) return;
// Auf Touch-Geräten: Klick toggelt das Dropdown
trigger.addEventListener('click', function(e) {
// Nur wenn hover nicht greift (touch) oder Desktop-Klick direkt auf Trigger
const isMobile = window.matchMedia('(max-width: 768px)').matches;
if (!isMobile) {
// Desktop: navigate to index.html if it's a link click
return; // hover handles it
}
e.preventDefault();
// Im Hamburger-Menü: nichts tun (always open via CSS)
});
// Desktop: Dropdown per Klick schließen wenn man außerhalb klickt
document.addEventListener('click', function(e) {
if (!dd.contains(e.target)) {
dd.classList.remove('open');
}
});
});
// ===========================
// Active Navigation Highlighting
// ===========================
// Highlight active navigation link
const currentLocation = location.pathname.split('/').pop() || 'index.html';
const navLinks = document.querySelectorAll('nav a');
navLinks.forEach(link => {
const href = link.getAttribute('href');
if (href === currentLocation) {
link.classList.add('active');
} else {
link.classList.remove('active');
}
});
// Initialize lightbox gallery
initializeLightbox();
// Initialize contact form
initializeContactForm();
// ===========================
// Begrüssung nach Tageszeit (U13)
// ===========================
function aktualisiereUhrzeit() {
const el = document.getElementById('begruessung');
if (!el) return;
const jetzt = new Date();
const stunde = jetzt.getHours();
const minute = String(jetzt.getMinutes()).padStart(2, '0');
let gruss;
if (stunde < 12) {
gruss = 'Guten Morgen';
} else if (stunde < 17) {
gruss = 'Guten Mittag';
} else {
gruss = 'Guten Abend';
}
el.textContent = gruss + ', es ist ' + stunde + ':' + minute + ' Uhr';
}
aktualisiereUhrzeit();
setInterval(aktualisiereUhrzeit, 60000); // jede Minute aktualisieren
});
// ===========================
// Lightbox Gallery
// ===========================
function initializeLightbox() {
const galleryImages = document.querySelectorAll('.galerie img');
galleryImages.forEach(img => {
img.addEventListener('click', function() {
openLightbox(this.src);
});
});
}
function openLightbox(imageSrc) {
// Create overlay
const overlay = document.createElement('div');
overlay.className = 'lightbox-overlay';
// Create image container
const imgContainer = document.createElement('div');
imgContainer.style.position = 'relative';
// Create close button
const closeBtn = document.createElement('span');
closeBtn.className = 'lightbox-close';
closeBtn.innerHTML = '&times;';
closeBtn.addEventListener('click', function(e) {
e.stopPropagation();
overlay.remove();
});
// Create large image
const img = document.createElement('img');
img.src = imageSrc;
imgContainer.appendChild(closeBtn);
imgContainer.appendChild(img);
overlay.appendChild(imgContainer);
// Close on overlay click
overlay.addEventListener('click', function() {
overlay.remove();
});
// Close on Escape key
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
overlay.remove();
}
});
document.body.appendChild(overlay);
}
// ===========================
// Contact Form Handling
// ===========================
function initializeContactForm() {
const form = document.getElementById('contactForm');
if (!form) return;
// Live-Validierung: Fehler beim Verlassen des Feldes clearen
['name', 'email', 'subject', 'message'].forEach(function(id) {
const field = document.getElementById(id);
if (field) {
field.addEventListener('input', function() {
clearFieldError(id);
});
}
});
form.addEventListener('submit', function(e) {
e.preventDefault();
const name = document.getElementById('name').value.trim();
const email = document.getElementById('email').value.trim();
const subject = document.getElementById('subject').value.trim();
const message = document.getElementById('message').value.trim();
let valid = true;
// Name prüfen
if (!name) {
showFieldError('name', 'Bitte gib deinen Namen ein.');
valid = false;
} else {
clearFieldError('name');
}
// E-Mail prüfen
if (!email) {
showFieldError('email', 'Bitte gib deine E-Mail-Adresse ein.');
valid = false;
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
showFieldError('email', 'Die E-Mail-Adresse muss ein @ enthalten und gültig sein.');
valid = false;
} else {
clearFieldError('email');
}
// Betreff prüfen
if (!subject) {
showFieldError('subject', 'Bitte gib einen Betreff ein.');
valid = false;
} else {
clearFieldError('subject');
}
// Nachricht prüfen
if (!message) {
showFieldError('message', 'Bitte schreib uns eine Nachricht.');
valid = false;
} else if (message.length < 10) {
showFieldError('message', 'Die Nachricht sollte mindestens 10 Zeichen lang sein.');
valid = false;
} else {
clearFieldError('message');
}
if (!valid) return;
// Erfolg
form.reset();
['name', 'email', 'subject', 'message'].forEach(clearFieldError);
const formMessage = document.getElementById('formMessage');
if (formMessage) {
formMessage.innerHTML =
'<div class="form-success">' +
'<span class="form-success-icon">✅</span>' +
'<div>' +
'<strong>Danke für deine Nachricht!</strong><br>' +
'Wir melden uns bald bei dir. 💕' +
'</div>' +
'</div>';
formMessage.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
});
}
function showFieldError(fieldId, message) {
const field = document.getElementById(fieldId);
const errorEl = document.getElementById('error-' + fieldId);
if (field) field.classList.add('input-error');
if (errorEl) errorEl.textContent = message;
}
function clearFieldError(fieldId) {
const field = document.getElementById(fieldId);
const errorEl = document.getElementById('error-' + fieldId);
if (field) field.classList.remove('input-error');
if (errorEl) errorEl.textContent = '';
}
function showFormMessage(message, type) {
const formMessage = document.getElementById('formMessage');
if (!formMessage) return;
formMessage.textContent = message;
}
// ===========================
// Smooth Scroll (Progressive Enhancement)
// ===========================
document.addEventListener('click', function(e) {
if (e.target.tagName === 'A' && e.target.getAttribute('href').startsWith('#')) {
e.preventDefault();
const targetId = e.target.getAttribute('href').substring(1);
const targetElement = document.getElementById(targetId);
if (targetElement) {
targetElement.scrollIntoView({ behavior: 'smooth' });
}
}
});
// ===========================
// Utility: Log
// ===========================
console.log('✅ EIS Website erfolgreich geladen!');
console.log('📚 Veranstaltung: Entwicklung interaktiver Softwareanwendungen');
console.log('🏫 Institution: PH Weingarten');
console.log('👨‍🏫 Dozenten: Stefan Franke und Prof. Dr. Wolfgang Müller');