219 lines
7.8 KiB
JavaScript
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());
|
|
}
|