// ==================== // MOBILE MENU TOGGLE // ==================== const menuToggle = document.getElementById('menuToggle'); const navbar = document.getElementById('navbar'); const navLinks = document.querySelectorAll('.nav-link'); // Toggle menu na klik hamburger gumba menuToggle.addEventListener('click', () => { menuToggle.classList.toggle('active'); navbar.classList.toggle('active'); }); // Zatvori menu kada se klikne na link navLinks.forEach(link => { link.addEventListener('click', () => { menuToggle.classList.remove('active'); navbar.classList.remove('active'); }); }); // Zatvori menu kada se klikne izvan document.addEventListener('click', (e) => { if (!e.target.closest('.header-container')) { menuToggle.classList.remove('active'); navbar.classList.remove('active'); } }); // ==================== // LAZY LOADING SLIKA SA INTERSECTION OBSERVER // ==================== const observerOptions = { root: null, rootMargin: '50px', threshold: 0.01 }; const imageObserver = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target; // Ako slika ima data-src, učitaj je if (img.dataset.src) { img.src = img.dataset.src; img.removeAttribute('data-src'); } // Dodaj loaded klasu za animaciju img.addEventListener('load', () => { img.classList.add('loaded'); }); // Prestani promatrati sliku imageObserver.unobserve(img); } }); }, observerOptions); // Promatraj sve slike sa loading="lazy" document.querySelectorAll('img[loading="lazy"]').forEach(img => { imageObserver.observe(img); // Ako je slika već učitana iz cache-a if (img.complete) { img.classList.add('loaded'); } }); // ==================== // LIGHTBOX GALERIJA // ==================== const lightbox = document.getElementById('lightbox'); const lightboxImg = document.querySelector('.lightbox-img'); const lightboxClose = document.querySelector('.lightbox-close'); const lightboxPrev = document.querySelector('.lightbox-prev'); const lightboxNext = document.querySelector('.lightbox-next'); // Selektuj sve elemente sa data-lightbox atributom (reference i modele dvoraca) const galleryItems = document.querySelectorAll('[data-lightbox]'); let currentImageIndex = 0; let allImages = []; // Inicijalizacija galerije function initGallery() { allImages = Array.from(galleryItems).map(item => ({ src: item.href, title: item.querySelector('img').alt })); } initGallery(); // Otvori lightbox galleryItems.forEach((item, index) => { item.addEventListener('click', (e) => { e.preventDefault(); currentImageIndex = index; openLightbox(); }); }); function openLightbox() { lightbox.classList.add('active'); lightboxImg.src = allImages[currentImageIndex].src; document.body.style.overflow = 'hidden'; } function closeLightbox() { lightbox.classList.remove('active'); document.body.style.overflow = 'auto'; } function showNextImage() { currentImageIndex = (currentImageIndex + 1) % allImages.length; lightboxImg.src = allImages[currentImageIndex].src; } function showPrevImage() { currentImageIndex = (currentImageIndex - 1 + allImages.length) % allImages.length; lightboxImg.src = allImages[currentImageIndex].src; } // Event listeneri za lightbox lightboxClose.addEventListener('click', closeLightbox); lightboxNext.addEventListener('click', (e) => { e.preventDefault(); showNextImage(); }); lightboxPrev.addEventListener('click', (e) => { e.preventDefault(); showPrevImage(); }); // Zatvori lightbox na ESC document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && lightbox.classList.contains('active')) { closeLightbox(); } }); // Zatvori lightbox na klik van slike lightbox.addEventListener('click', (e) => { if (e.target === lightbox) { closeLightbox(); } }); // Keyboard navigacija (strelice) document.addEventListener('keydown', (e) => { if (lightbox.classList.contains('active')) { if (e.key === 'ArrowRight') { showNextImage(); } else if (e.key === 'ArrowLeft') { showPrevImage(); } } }); // ==================== // KONTAKT FORMA // ==================== const kontaktForma = document.getElementById('kontaktForma'); if (kontaktForma) { kontaktForma.addEventListener('submit', function(e) { e.preventDefault(); // Prikupli podatke const formData = new FormData(this); const ime = this.querySelector('input[type="text"]').value; const email = this.querySelector('input[type="email"]').value; const poruka = this.querySelector('textarea').value; // Kreiraj mailto link sa podacima const subject = encodeURIComponent('Nova poruka sa web stranice'); const body = encodeURIComponent( `Ime: ${ime}\n` + `Email: ${email}\n` + `Poruka:\n${poruka}` ); // Otvori default email klijent window.location.href = `mailto:info@igpbozuric.hr?subject=${subject}&body=${body}`; // Opciono: prikaži potvrdu this.reset(); alert('Hvala na poruci! Kontaktirat ćemo vas uskoro.'); }); } // ==================== // SCROLL ANIMACIJE (FADE-IN) // ==================== const scrollObserverOptions = { threshold: 0.1, rootMargin: '0px 0px -50px 0px' }; const scrollObserver = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('fade-in'); scrollObserver.unobserve(entry.target); } }); }, scrollObserverOptions); // Primijeni na sve usluge kartice i sekcije document.querySelectorAll('.usluga-card, .gallery-item').forEach(element => { scrollObserver.observe(element); }); // ==================== // SMOOTH SCROLL ZA ANCHOR LINKOVE // ==================== document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function (e) { const href = this.getAttribute('href'); // Ignoriraj lightbox linkove if (href === '#') return; const target = document.querySelector(href); if (target) { e.preventDefault(); // Zatvori mobile meni ako je otvoren menuToggle.classList.remove('active'); navbar.classList.remove('active'); // Scroll sa offset za header const headerHeight = document.querySelector('.header').offsetHeight; const targetPosition = target.offsetTop - headerHeight; window.scrollTo({ top: targetPosition, behavior: 'smooth' }); } }); }); // ==================== // SCROLL NA VRH STRANICE // ==================== // Kreiraj gumb za vraćanje na vrh const scrollTopBtn = document.createElement('button'); scrollTopBtn.id = 'scrollTopBtn'; scrollTopBtn.innerHTML = '⬆️'; scrollTopBtn.style.cssText = ` position: fixed; bottom: 20px; right: 20px; //background-color: var(--primary-color); color: white; border: none; padding: 12px 16px; border-radius: 50%; font-size: 1.2rem; cursor: pointer; display: none; z-index: 99; transition: all 0.3s ease; `; document.body.appendChild(scrollTopBtn); // Prikaži/sakrij gumb ovisno o scroll poziciji window.addEventListener('scroll', () => { if (window.pageYOffset > 300) { scrollTopBtn.style.display = 'block'; } else { scrollTopBtn.style.display = 'none'; } }); // Scroll na vrh kad se klikne scrollTopBtn.addEventListener('click', () => { window.scrollTo({ top: 0, behavior: 'smooth' }); }); // ==================== // ANALYTICS I PERFORMANCE // ==================== // Sprječavanja CLS (Cumulative Layout Shift) - postavi min-height za slike function preventCLS() { document.querySelectorAll('.usluga-image img, .gallery-item img').forEach(img => { const observer = new IntersectionObserver(() => { if (img.complete) { img.style.aspectRatio = img.naturalWidth + ' / ' + img.naturalHeight; } }); observer.observe(img); }); } // Izvrši nakon učitavanja DOM-a if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', preventCLS); } else { preventCLS(); } // ==================== // PRISTUPAČNOST // ==================== // Postavi focus outline za keyboard navigaciju let isKeyboardNavigating = false; document.addEventListener('keydown', (e) => { if (e.key === 'Tab') { isKeyboardNavigating = true; } }); document.addEventListener('mousedown', () => { isKeyboardNavigating = false; }); // Prikaži focus outline samo za keyboard navigaciju const style = document.createElement('style'); style.innerHTML = ` *:focus-visible { outline: 3px solid var(--primary-color); outline-offset: 2px; } `; document.head.appendChild(style); // ==================== // PERFORMANCE MONITORING // ==================== // Prikupi performance podatke (opciono) if (window.performance && window.performance.timing) { window.addEventListener('load', () => { const perfData = window.performance.timing; const pageLoadTime = perfData.loadEventEnd - perfData.navigationStart; // Ovi podaci mogu biti poslani na analytics servis ako je potrebno console.log('Page Load Time:', pageLoadTime + 'ms'); }); } // ==================== // LOCAL STORAGE ZA POSTAVKE KORISNIKA // ==================== // Pamti zadnju otvorenu sekciju function saveScrollPosition() { localStorage.setItem('scrollPosition', window.pageYOffset); } // Vrati na zadnju poziciju function restoreScrollPosition() { const savedPosition = localStorage.getItem('scrollPosition'); if (savedPosition) { setTimeout(() => { window.scrollTo(0, parseInt(savedPosition)); }, 100); } } window.addEventListener('beforeunload', saveScrollPosition); window.addEventListener('load', restoreScrollPosition); // ==================== // INICIJALIZACIJA // ==================== console.log('IGP BOŽURIĆ - Pure HTML/CSS/JS website'); console.log('No frameworks, no plugins, pure vanilla JavaScript');