OpenNIT

Quelltext des aktuellen Standes

Fassung 1.1.1

image_lightbox.php

3 KB
<?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') ?>">&times;</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>