/** * main.js * Glavna JavaScript datoteka za spletno stran "Brezplačno snemanje poroke". * * Funkcionalnosti: * 1. Inicializacija vseh skript po nalaganju DOM-a. * 2. Upravljanje animacij elementov ob drsanju strani (Intersection Observer). * 3. Implementacija gladkega drsanja za interne povezave. * 4. Interaktivni parallax efekt v "hero" sekciji, ki se odziva na premik miške. * 5. Napredna validacija in pošiljanje kontaktnega obrazca preko Fetch API. */ // Počakamo, da se celoten HTML dokument naloži, preden zaženemo skripte. document.addEventListener('DOMContentLoaded', () => { // Inicializacija vseh glavnih funkcij initScrollAnimations(); initSmoothScrolling(); initHeroParallaxEffect(); initContactFormHandler(); console.log("Stran je pripravljena in vsi interaktivni elementi so aktivirani."); }); /** * Funkcija za inicializacijo animacij ob drsanju (Fade-in efekt). * Uporablja Intersection Observer API za optimalno delovanje. * Elementi z razredom .animate-on-scroll bodo postali vidni, ko vstopijo v vidno polje. */ function initScrollAnimations() { const animatedElements = document.querySelectorAll('.animate-on-scroll'); if (!animatedElements.length) return; const observerOptions = { root: null, // opazujemo glede na vidno polje brskalnika rootMargin: '0px', threshold: 0.1 // sproži se, ko je vsaj 10% elementa vidnega }; const observer = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('is-visible'); observer.unobserve(entry.target); // prenehamo opazovati, da se animacija zgodi samo enkrat } }); }, observerOptions); animatedElements.forEach(element => { observer.observe(element); }); } /** * Funkcija za implementacijo gladkega drsanja do sidrnih točk. * Vsi linki, ki se začnejo z '#', bodo sprožili gladko drsenje namesto skoka. */ function initSmoothScrolling() { const internalLinks = document.querySelectorAll('a[href^="#"]'); internalLinks.forEach(link => { link.addEventListener('click', function(e) { e.preventDefault(); const targetId = this.getAttribute('href'); const targetElement = document.querySelector(targetId); if (targetElement) { targetElement.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); }); } /** * Funkcija za parallax efekt v "hero" sekciji, ki se odziva na premik miške. * Predpostavlja obstoj elementa z ID-jem #hero-section in elementa v njem z razredom .hero-background. */ function initHeroParallaxEffect() { const heroSection = document.querySelector('#hero-section'); const heroBackground = document.querySelector('.hero-background'); if (!heroSection || !heroBackground) return; const parallaxStrength = 15; // Manjša vrednost = bolj subtilen efekt heroSection.addEventListener('mousemove', (e) => { const { clientWidth, clientHeight } = heroSection; const x = (e.clientX / clientWidth) - 0.5; const y = (e.clientY / clientHeight) - 0.5; // Uporabimo transform za premik, kar je bolj učinkovito za animacije heroBackground.style.transform = ` translateX(${-x * parallaxStrength}px) translateY(${-y * parallaxStrength}px) scale(1.05)`; // Rahlo povečamo ozadje, da robovi niso vidni }); heroSection.addEventListener('mouseleave', () => { // Obnovimo pozicijo, ko miška zapusti območje heroBackground.style.transform = 'translate(0, 0) scale(1.05)'; }); } /** * Funkcija za upravljanje kontaktnega obrazca. * Vključuje validacijo na strani odjemalca in pošiljanje podatkov preko Fetch API. * Predpostavlja, da ima obrazec ID #contact-form in da ga upravlja Netlify. */ function initContactFormHandler() { const form = document.querySelector('#contact-form'); if (!form) return; const submitButton = form.querySelector('button[type="submit"]'); const formResponseEl = document.querySelector('#form-response'); // Element za prikaz sporočil form.addEventListener('submit', function(e) { e.preventDefault(); // 1. Validacija polj if (!validateForm(form)) { return; // Ustavi pošiljanje, če validacija ne uspe } // 2. Priprava podatkov za pošiljanje const formData = new FormData(form); const originalButtonText = submitButton.textContent; submitButton.disabled = true; submitButton.textContent = 'Pošiljanje...'; // 3. Pošiljanje preko Fetch API (prilagojeno za Netlify Forms) fetch('/', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams(formData).toString() }) .then(response => { if (response.ok) { // Uspešno poslano form.style.display = 'none'; // Skrij obrazec formResponseEl.innerHTML = `

Hvala za prijavo!

Oglasili se vam bova v najkrajšem možnem času. Preverite svoj e-poštni nabiralnik.

`; formResponseEl.classList.add('success'); formResponseEl.style.display = 'block'; } else { // Napaka pri pošiljanju throw new Error('Prišlo je do napake pri pošiljanju. Poskusite znova.'); } }) .catch(error => { formResponseEl.innerHTML = `

Napaka: ${error.message}

`; formResponseEl.classList.add('error'); formResponseEl.style.display = 'block'; }) .finally(() => { // Ponastavi gumb samo v primeru napake, saj ob uspehu formo skrijemo if (form.style.display !== 'none') { submitButton.disabled = false; submitButton.textContent = originalButtonText; } }); }); } /** * Pomožna funkcija za validacijo polj v obrazcu. * @param {HTMLFormElement} form - Obrazec, ki ga validiramo. * @returns {boolean} - Vrne `true`, če so vsa polja veljavna, sicer `false`. */ function validateForm(form) { let isValid = true; const requiredFields = form.querySelectorAll('[required]'); // Najprej počistimo vse prejšnje napake form.querySelectorAll('.error-message').forEach(el => el.remove()); form.querySelectorAll('.is-invalid').forEach(el => el.classList.remove('is-invalid')); requiredFields.forEach(field => { let error = null; if (field.value.trim() === '') { error = 'To polje je obvezno.'; } else if (field.type === 'email' && !isValidEmail(field.value)) { error = 'Prosimo, vnesite veljaven e-poštni naslov.'; } else if (field.type === 'date' && new Date(field.value) < new Date()) { error = 'Datum poroke ne more biti v preteklosti.'; } if (error) { isValid = false; field.classList.add('is-invalid'); const errorElement = document.createElement('span'); errorElement.className = 'error-message'; errorElement.textContent = error; // Vstavi sporočilo o napaki za poljem field.parentNode.insertBefore(errorElement, field.nextSibling); } }); return isValid; } /** * Pomožna funkcija za preverjanje veljavnosti e-poštnega naslova. * @param {string} email - E-poštni naslov za preverjanje. * @returns {boolean} */ function isValidEmail(email) { const regex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; return regex.test(String(email).toLowerCase()); }