Quelltext des aktuellen Standes
<?php
/**
* Wiederverwendbare Bild-Lightbox.
*
* Klick auf ein Personen-/Karten-Avatarbild (Klassen cb-person-avatar-img,
* cb-card-avatar-img, cb-list-avatar-img) öffnet es vergrößert. Funktioniert
* per Event-Delegation auch für nachgeladene Inhalte und verhindert dabei die
* Navigation, falls das Bild in einem Link liegt.
*
* Nutzung im Template: <?= $this->partial('image_lightbox') ?>
* Aus JS optional: itLightbox(src, alt)
*/
if (defined('IT_IMAGE_LIGHTBOX_RENDERED')) {
return;
}
define('IT_IMAGE_LIGHTBOX_RENDERED', true);
?>
<div class="it-lightbox-overlay" id="itLightboxOverlay" aria-hidden="true">
<button type="button" class="it-lightbox-close" data-lightbox-close aria-label="<?= $this->te('Schließen') ?>">×</button>
<img class="it-lightbox-img" id="itLightboxImg" src="" alt="">
</div>
<style>
/* Avatarbilder als anklickbar kennzeichnen */
.cb-person-avatar-img,
.cb-card-avatar-img,
.cb-list-avatar-img,
.cb-contact-avatar-img,
.cb-company-logo { cursor: zoom-in; }
.it-lightbox-overlay {
position: fixed; inset: 0; z-index: 1100;
background: rgba(15, 23, 42, 0.8);
display: none; align-items: center; justify-content: center;
padding: 2rem; cursor: zoom-out;
}
.it-lightbox-overlay.open { display: flex; }
.it-lightbox-img {
max-width: 90vw; max-height: 90vh;
width: auto; height: auto;
border-radius: 0.5rem; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
background: var(--color-bg); object-fit: contain;
animation: itLightboxPop 0.15s ease;
}
@keyframes itLightboxPop { from { transform: scale(0.94); opacity: 0; } to { transform: scale(1); opacity: 1; } }
.it-lightbox-close {
position: absolute; top: 1rem; right: 1.25rem;
background: none; border: none; color: var(--color-on-accent); font-size: 2.25rem;
line-height: 1; cursor: pointer; opacity: 0.85;
}
.it-lightbox-close:hover { opacity: 1; }
</style>
<script>
(function () {
var overlay = document.getElementById('itLightboxOverlay');
var img = document.getElementById('itLightboxImg');
if (!overlay || !img) return;
function open(src, alt) {
if (!src) return;
img.src = src;
img.alt = alt || '';
overlay.classList.add('open');
overlay.setAttribute('aria-hidden', 'false');
}
function close() {
overlay.classList.remove('open');
overlay.setAttribute('aria-hidden', 'true');
img.src = '';
}
window.itLightbox = open;
// Capture-Phase: vor etwaigen Link-/Karten-Handlern; verhindert Navigation.
document.addEventListener('click', function (e) {
var target = e.target.closest('.cb-person-avatar-img, .cb-card-avatar-img, .cb-list-avatar-img, .cb-contact-avatar-img, .cb-company-logo');
if (!target) return;
e.preventDefault();
e.stopPropagation();
open(target.getAttribute('src'), target.getAttribute('alt'));
}, true);
overlay.addEventListener('click', function (e) {
if (e.target === overlay || e.target.hasAttribute('data-lightbox-close')) close();
});
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape' && overlay.classList.contains('open')) close();
});
})();
</script>