(function () { var root = document.getElementById('glass-gallery'); if (!root || root.dataset.ggReady === '1') return; root.dataset.ggReady = '1'; var images = [ { src: 'https://xiavi.ir/home/wp-content/uploads/2026/10/بدون-خواب-طرح-اول-25متری.jpg', alt: 'پلان خانه بدون اتاق خواب طرح 1 با زیربنای 53 مترمربع' }, { src: 'https://xiavi.ir/home/wp-content/uploads/2026/10/بدون-خواب-طرح-دوم-16متری.jpg', alt: 'پلان خانه بدون اتاق خواب طرح 2 با زیربنای 32 مترمربع' }, { src: 'https://xiavi.ir/home/wp-content/uploads/2026/10/soon.jpg', alt: 'پلان خانه بدون اتاق خواب طرح 3 با زیربنای 32 مترمربع' }, { src: 'https://xiavi.ir/home/wp-content/uploads/2026/10/soon.jpg', alt: 'پلان خانه بدون اتاق خواب طرح 4 با زیربنای 53 مترمربع' } ]; var track = root.querySelector('.gg-track'); var viewport = root.querySelector('.gg-viewport'); var dots = root.querySelector('.gg-dots'); var counter = root.querySelector('.gg-counter'); var lightbox = root.querySelector('.gg-lightbox'); var lbImage = root.querySelector('.gg-lb-image'); var lbCaption = root.querySelector('.gg-lb-caption'); var lbCounter = root.querySelector('.gg-lb-counter'); var closeButton = root.querySelector('.gg-lb-close'); var current = 0; var lbOpen = false; var previousFocus = null; var previousOverflow = ''; var suppressViewportClickUntil = 0; function number(n) { return String(n).padStart(2, '0'); } /* ساخت اسلایدها و نشانگرها */ images.forEach(function (item, index) { var slide = document.createElement('div'); slide.className = 'gg-slide'; var button = document.createElement('button'); button.type = 'button'; button.className = 'gg-image-button'; button.setAttribute( 'aria-label', 'نمایش بزرگ تصویر ' + (index + 1) ); var img = document.createElement('img'); img.src = item.src; img.alt = item.alt; img.loading = index === 0 ? 'eager' : 'lazy'; img.decoding = 'async'; img.draggable = false; var hint = document.createElement('span'); hint.className = 'gg-image-hint'; hint.textContent = 'برای بزرگ‌نمایی لمس کنید'; button.appendChild(img); button.appendChild(hint); button.addEventListener('click', function () { if (Date.now() < suppressViewportClickUntil) return; openLightbox(index, button); }); slide.appendChild(button); track.appendChild(slide); var dot = document.createElement('button'); dot.type = 'button'; dot.className = 'gg-dot'; dot.setAttribute('aria-label', 'تصویر ' + (index + 1)); dot.addEventListener('click', function () { goTo(index); }); dots.appendChild(dot); }); /* تغییر تصویر در هر دو حالت */ function goTo(index) { current = (index + images.length) % images.length; var slideWidth = viewport.getBoundingClientRect().width; track.style.transform = 'translate3d(' + (current * slideWidth) + 'px, 0, 0)'; Array.prototype.forEach.call(dots.children, function (dot, i) { dot.setAttribute( 'aria-current', i === current ? 'true' : 'false' ); }); counter.textContent = number(current + 1) + ' / ' + number(images.length); if (lbOpen) updateLightbox(); } function updateLightbox() { var item = images[current]; lbImage.src = item.src; lbImage.alt = item.alt; lbCaption.textContent = item.alt; lbCounter.textContent = number(current + 1) + ' / ' + number(images.length); } /* باز کردن لایت‌باکس */ function openLightbox(index, focusEl) { if (lbOpen) { goTo(index); return; } previousFocus = focusEl || document.activeElement; previousOverflow = document.documentElement.style.overflow; lbOpen = true; goTo(index); updateLightbox(); lightbox.classList.add('is-open'); lightbox.setAttribute('aria-hidden', 'false'); document.documentElement.style.overflow = 'hidden'; closeButton.focus(); } /* بستن لایت‌باکس */ function closeLightbox() { if (!lbOpen) return; lbOpen = false; lightbox.classList.remove('is-open'); lightbox.setAttribute('aria-hidden', 'true'); document.documentElement.style.overflow = previousOverflow; if (previousFocus && typeof previousFocus.focus === 'function') { previousFocus.focus(); } } /* دکمه‌های گالری */ root.querySelector('.gg-prev').addEventListener('click', function () { goTo(current - 1); }); root.querySelector('.gg-next').addEventListener('click', function () { goTo(current + 1); }); /* دکمه‌های لایت‌باکس */ root.querySelector('.gg-lb-prev').addEventListener('click', function (e) { e.stopPropagation(); goTo(current - 1); }); root.querySelector('.gg-lb-next').addEventListener('click', function (e) { e.stopPropagation(); goTo(current + 1); }); closeButton.addEventListener('click', closeLightbox); lightbox.addEventListener('click', function (e) { if (e.target === lightbox) { closeLightbox(); } }); root.querySelector('.gg-lb-figure').addEventListener('click', function (e) { e.stopPropagation(); }); /* کلیدهای صفحه‌کلید */ document.addEventListener('keydown', function (e) { if (!lbOpen) return; if (e.key === 'Escape') { closeLightbox(); } else if (e.key === 'ArrowLeft') { goTo(current + 1); } else if (e.key === 'ArrowRight') { goTo(current - 1); } }); /* * سوایپ لمسی: * کشیدن به چپ = تصویر بعدی * کشیدن به راست = تصویر قبلی * * touchstart / touchend برای موبایل * pointer events برای ماوس و قلم */ function enableSwipe(element, isLightbox) { var startX = 0; var startY = 0; var startTime = 0; var active = false; var pointerId = null; var moved = false; function isEnabled() { return !isLightbox || lbOpen; } function begin(x, y) { if (!isEnabled()) return; startX = x; startY = y; startTime = Date.now(); active = true; moved = false; } function finish(x, y) { if (!active || !isEnabled()) { active = false; return; } active = false; var dx = x - startX; var dy = y - startY; var elapsed = Date.now() - startTime; /* حداقل جابه‌جایی افقی و جلوگیری از تشخیص اسکرول عمودی */ if (Math.abs(dx) < 45) return; if (Math.abs(dx) 800) return; moved = true; if (!isLightbox) { suppressViewportClickUntil = Date.now() + 500; } if (dx < 0) { goTo(current + 1); } else { goTo(current - 1); } } /* لمس موبایل */ element.addEventListener('touchstart', function (e) { if (!isEnabled()) return; if (!e.touches || e.touches.length !== 1) { active = false; return; } begin( e.touches[0].clientX, e.touches[0].clientY ); }, { passive: true }); element.addEventListener('touchend', function (e) { if (!e.changedTouches || e.changedTouches.length !== 1) { active = false; return; } finish( e.changedTouches[0].clientX, e.changedTouches[0].clientY ); }, { passive: true }); element.addEventListener('touchcancel', function () { active = false; }, { passive: true }); /* ماوس و قلم */ element.addEventListener('pointerdown', function (e) { if (e.pointerType === 'touch') return; if (e.pointerType === 'mouse' && e.button !== 0) return; if (!isEnabled()) return; pointerId = e.pointerId; begin(e.clientX, e.clientY); }); element.addEventListener('pointerup', function (e) { if (e.pointerType === 'touch') return; if (pointerId === null || e.pointerId !== pointerId) return; pointerId = null; finish(e.clientX, e.clientY); }); element.addEventListener('pointercancel', function () { pointerId = null; active = false; }); /* پس از سوایپ، کلیک ناخواسته روی پلان باز نشود */ if (!isLightbox) { element.addEventListener('click', function (e) { if (Date.now() < suppressViewportClickUntil) { e.preventDefault(); e.stopPropagation(); if (e.stopImmediatePropagation) { e.stopImmediatePropagation(); } } }, true); } } /* سوایپ روی گالری و روی تصویر بزرگ */ enableSwipe(viewport, false); enableSwipe(lightbox, true); /* افکت نور متحرک */ var card = root.querySelector('.gg-card'); card.addEventListener('pointermove', function (e) { if (e.pointerType === 'touch') return; var rect = card.getBoundingClientRect(); card.style.setProperty( '--gg-x', ((e.clientX - rect.left) / rect.width * 100) + '%' ); card.style.setProperty( '--gg-y', ((e.clientY - rect.top) / rect.height * 100) + '%' ); }); card.addEventListener('pointerleave', function () { card.style.setProperty('--gg-x', '50%'); card.style.setProperty('--gg-y', '30%'); }); /* حفظ موقعیت اسلاید پس از تغییر اندازه صفحه */ var resizeTimer; window.addEventListener('resize', function () { clearTimeout(resizeTimer); resizeTimer = setTimeout(function () { goTo(current); }, 100); }); /* نمایش تصویر اول */ goTo(0); })();