/* global window, document */
(function () {
'use strict';
var Luxtools = window.Luxtools || (window.Luxtools = {});
// ============================================================
// Lightbox Module
// ============================================================
Luxtools.Lightbox = (function () {
var lb = null;
var img = null;
var cap = null;
var items = [];
var index = 0;
// Zoom/pan state
var scale = 1;
var panX = 0;
var panY = 0;
var minScale = 1;
var maxScale = 5;
var isPanning = false;
var panStartX = 0;
var panStartY = 0;
// History state
var pushedHistory = false;
var closingFromPopstate = false;
function ensureElement() {
if (lb) return;
lb = document.createElement('div');
lb.className = 'luxtools-lightbox';
lb.setAttribute('role', 'dialog');
lb.setAttribute('aria-modal', 'true');
lb.setAttribute('aria-hidden', 'true');
lb.innerHTML =
'
' +
'';
document.body.appendChild(lb);
img = lb.querySelector('img.luxtools-lightbox-img');
cap = lb.querySelector('.luxtools-lightbox-caption');
lb.addEventListener('click', onClick);
}
function clampIndex(n) {
if (n < 0) return items.length - 1;
if (n >= items.length) return 0;
return n;
}
function applyTransform() {
if (scale <= 1 && panX === 0 && panY === 0) {
img.style.transform = '';
} else {
img.style.transform = 'scale(' + scale + ') translate(' + panX + 'px, ' + panY + 'px)';
}
img.style.cursor = scale > 1 ? 'grab' : '';
}
function resetZoom() {
scale = 1;
panX = 0;
panY = 0;
applyTransform();
}
function render() {
var it = items[index];
img.src = it.full;
img.setAttribute('data-luxtools-index', String(index));
if (cap) cap.textContent = (it.name || '').trim();
resetZoom();
}
function next() {
index = clampIndex(index + 1);
render();
}
function prev() {
index = clampIndex(index - 1);
render();
}
// Event handlers
function onWheel(e) {
e.preventDefault();
var delta = e.deltaY > 0 ? -0.15 : 0.15;
scale = Math.max(minScale, Math.min(maxScale, scale + delta));
if (scale <= 1) { panX = 0; panY = 0; }
applyTransform();
}
function onDblClick(e) {
e.preventDefault();
if (scale > 1) {
scale = 1;
panX = 0;
panY = 0;
} else {
scale = 2.5;
}
applyTransform();
}
function onMouseDown(e) {
if (scale > 1 && e.button === 0) {
isPanning = true;
panStartX = e.clientX - panX * scale;
panStartY = e.clientY - panY * scale;
img.style.cursor = 'grabbing';
e.preventDefault();
}
}
function onMouseMove(e) {
if (isPanning && scale > 1) {
panX = (e.clientX - panStartX) / scale;
panY = (e.clientY - panStartY) / scale;
applyTransform();
img.style.cursor = 'grabbing';
}
}
function onMouseUp() {
isPanning = false;
img.style.cursor = scale > 1 ? 'grab' : '';
}
function onKeyDown(e) {
if (!lb || !lb.classList.contains('is-open')) return;
var key = e.key || '';
if (key === 'Escape') {
e.preventDefault();
close();
} else if (key === 'ArrowRight') {
e.preventDefault();
next();
} else if (key === 'ArrowLeft') {
e.preventDefault();
prev();
}
}
function onPopState() {
if (!lb || !lb.classList.contains('is-open')) return;
closingFromPopstate = true;
try { close(); } finally { closingFromPopstate = false; }
}
function onClick(e) {
var t = e.target;
if (!t || !t.getAttribute) return;
var action = t.getAttribute('data-luxtools-action') || '';
if (action === 'close') { e.preventDefault(); close(); return; }
if (action === 'next') { e.preventDefault(); next(); return; }
if (action === 'prev') { e.preventDefault(); prev(); return; }
if (t.closest && t.closest('button.luxtools-lightbox-zone')) return;
if (t.closest && t.closest('img.luxtools-lightbox-img')) return;
e.preventDefault();
close();
}
function attachListeners() {
document.addEventListener('keydown', onKeyDown, true);
window.addEventListener('popstate', onPopState, true);
img.addEventListener('wheel', onWheel, { passive: false });
img.addEventListener('dblclick', onDblClick);
img.addEventListener('mousedown', onMouseDown);
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
}
function detachListeners() {
document.removeEventListener('keydown', onKeyDown, true);
window.removeEventListener('popstate', onPopState, true);
img.removeEventListener('wheel', onWheel);
img.removeEventListener('dblclick', onDblClick);
img.removeEventListener('mousedown', onMouseDown);
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
}
function open(galleryEl, startEl) {
var links = galleryEl.querySelectorAll('a.luxtools-gallery-item[data-luxtools-full]');
items = [];
links.forEach(function (a) {
var full = a.getAttribute('data-luxtools-full') || a.getAttribute('href') || '';
var name = a.getAttribute('data-luxtools-name') || a.getAttribute('title') || '';
if (!full) return;
items.push({ el: a, full: full, name: name });
});
if (!items.length) return;
index = 0;
for (var i = 0; i < items.length; i++) {
if (items[i].el === startEl) { index = i; break; }
}
ensureElement();
pushedHistory = false;
closingFromPopstate = false;
lb.classList.add('is-open');
lb.setAttribute('aria-hidden', 'false');
try { document.documentElement.classList.add('luxtools-noscroll'); } catch (e) {}
try { document.body.style.overflow = 'hidden'; } catch (e) {}
attachListeners();
try {
if (window.history && window.history.pushState) {
window.history.pushState({ luxtoolsLightbox: 1 }, '', window.location.href);
pushedHistory = true;
}
} catch (e) {}
render();
}
function close() {
if (!lb) return;
lb.classList.remove('is-open');
lb.setAttribute('aria-hidden', 'true');
try { document.documentElement.classList.remove('luxtools-noscroll'); } catch (e) {}
try { document.body.style.overflow = ''; } catch (e) {}
img.src = '';
resetZoom();
detachListeners();
if (pushedHistory && !closingFromPopstate) {
try {
if (window.history && window.history.state && window.history.state.luxtoolsLightbox === 1) {
window.history.back();
}
} catch (e) {}
}
items = [];
}
return {
open: open,
close: close
};
})();
})();