najina-poroka/js/main.js

219 lines
7.8 KiB
JavaScript

/**
* 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 = `<h3>Hvala za prijavo!</h3><p>Oglasili se vam bova v najkrajšem možnem času. Preverite svoj e-poštni nabiralnik.</p>`;
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 = `<p>Napaka: ${error.message}</p>`;
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());
}