This repository has been archived on 2026-02-15. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
BreakPilot Dev 19855efacc
Some checks failed
Tests / Go Tests (push) Has been cancelled
Tests / Python Tests (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / Go Lint (push) Has been cancelled
Tests / Python Lint (push) Has been cancelled
Tests / Security Scan (push) Has been cancelled
Tests / All Checks Passed (push) Has been cancelled
Security Scanning / Secret Scanning (push) Has been cancelled
Security Scanning / Dependency Vulnerability Scan (push) Has been cancelled
Security Scanning / Go Security Scan (push) Has been cancelled
Security Scanning / Python Security Scan (push) Has been cancelled
Security Scanning / Node.js Security Scan (push) Has been cancelled
Security Scanning / Docker Image Security (push) Has been cancelled
Security Scanning / Security Summary (push) Has been cancelled
CI/CD Pipeline / Go Tests (push) Has been cancelled
CI/CD Pipeline / Python Tests (push) Has been cancelled
CI/CD Pipeline / Website Tests (push) Has been cancelled
CI/CD Pipeline / Linting (push) Has been cancelled
CI/CD Pipeline / Security Scan (push) Has been cancelled
CI/CD Pipeline / Docker Build & Push (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / CI Summary (push) Has been cancelled
ci/woodpecker/manual/build-ci-image Pipeline was successful
ci/woodpecker/manual/main Pipeline failed
feat: BreakPilot PWA - Full codebase (clean push without large binaries)
All services: admin-v2, studio-v2, website, ai-compliance-sdk,
consent-service, klausur-service, voice-service, and infrastructure.
Large PDFs and compiled binaries excluded via .gitignore.
2026-02-11 13:25:58 +01:00

235 lines
5.4 KiB
JavaScript

/**
* BreakPilot Studio - Lightbox Module
*
* Vollbild-Bildvorschau und Modal-Funktionen:
* - Lightbox für Arbeitsblatt-Vorschauen
* - Keyboard-Navigation (Escape zum Schließen)
* - Click-outside zum Schließen
*
* Refactored: 2026-01-19
*/
// DOM-Referenzen
let lightboxEl = null;
let lightboxImg = null;
let lightboxCaption = null;
let lightboxClose = null;
// Callback für Close-Event
let onCloseCallback = null;
/**
* Initialisiert die Lightbox
* Sucht nach Standard-IDs oder erstellt das DOM
*/
export function initLightbox() {
lightboxEl = document.getElementById('lightbox');
lightboxImg = document.getElementById('lightbox-img');
lightboxCaption = document.getElementById('lightbox-caption');
lightboxClose = document.getElementById('lightbox-close');
// Falls keine Lightbox im DOM, erstelle sie
if (!lightboxEl) {
createLightboxDOM();
}
// Event-Listener
if (lightboxClose) {
lightboxClose.addEventListener('click', closeLightbox);
}
if (lightboxEl) {
lightboxEl.addEventListener('click', (ev) => {
// Schließen bei Klick auf Hintergrund
if (ev.target === lightboxEl) {
closeLightbox();
}
});
}
// Escape-Taste
document.addEventListener('keydown', (ev) => {
if (ev.key === 'Escape' && isLightboxOpen()) {
closeLightbox();
}
});
}
/**
* Erstellt das Lightbox-DOM dynamisch
*/
function createLightboxDOM() {
lightboxEl = document.createElement('div');
lightboxEl.id = 'lightbox';
lightboxEl.className = 'lightbox hidden';
lightboxEl.innerHTML = `
<div class="lightbox-content">
<button class="lightbox-close" id="lightbox-close">Schließen ✕</button>
<img id="lightbox-img" class="lightbox-img" src="" alt="Vorschau">
<div id="lightbox-caption" class="lightbox-caption"></div>
</div>
`;
document.body.appendChild(lightboxEl);
// Referenzen aktualisieren
lightboxImg = document.getElementById('lightbox-img');
lightboxCaption = document.getElementById('lightbox-caption');
lightboxClose = document.getElementById('lightbox-close');
// CSS injizieren falls nicht vorhanden
if (!document.getElementById('lightbox-styles')) {
const style = document.createElement('style');
style.id = 'lightbox-styles';
style.textContent = `
.lightbox {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.9);
z-index: 10000;
display: flex;
align-items: center;
justify-content: center;
opacity: 1;
transition: opacity 0.3s ease;
}
.lightbox.hidden {
display: none;
opacity: 0;
}
.lightbox-content {
position: relative;
max-width: 90%;
max-height: 90%;
}
.lightbox-img {
max-width: 100%;
max-height: 85vh;
object-fit: contain;
border-radius: 8px;
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.5);
}
.lightbox-close {
position: absolute;
top: -40px;
right: 0;
background: transparent;
border: none;
color: white;
font-size: 14px;
cursor: pointer;
padding: 8px 16px;
border-radius: 4px;
transition: background 0.2s;
}
.lightbox-close:hover {
background: rgba(255, 255, 255, 0.1);
}
.lightbox-caption {
color: white;
text-align: center;
margin-top: 12px;
font-size: 14px;
}
`;
document.head.appendChild(style);
}
}
/**
* Öffnet die Lightbox mit einem Bild
* @param {string} src - Bild-URL
* @param {string} [caption] - Optionale Bildunterschrift
*/
export function openLightbox(src, caption = '') {
if (!src) {
console.warn('openLightbox: No image source provided');
return;
}
// Lazy-Init falls noch nicht initialisiert
if (!lightboxEl) {
initLightbox();
}
if (lightboxImg) {
lightboxImg.src = src;
lightboxImg.alt = caption || 'Vorschau';
}
if (lightboxCaption) {
lightboxCaption.textContent = caption;
}
if (lightboxEl) {
lightboxEl.classList.remove('hidden');
// Body-Scroll verhindern
document.body.style.overflow = 'hidden';
}
}
/**
* Schließt die Lightbox
*/
export function closeLightbox() {
if (lightboxEl) {
lightboxEl.classList.add('hidden');
// Body-Scroll wiederherstellen
document.body.style.overflow = '';
}
if (lightboxImg) {
lightboxImg.src = '';
}
// Callback ausführen
if (onCloseCallback) {
onCloseCallback();
}
}
/**
* Prüft ob die Lightbox geöffnet ist
* @returns {boolean}
*/
export function isLightboxOpen() {
return lightboxEl && !lightboxEl.classList.contains('hidden');
}
/**
* Setzt einen Callback für das Close-Event
* @param {function} callback
*/
export function onClose(callback) {
onCloseCallback = callback;
}
/**
* Wechselt das Bild in der offenen Lightbox
* @param {string} src - Neue Bild-URL
* @param {string} [caption] - Neue Bildunterschrift
*/
export function changeLightboxImage(src, caption = '') {
if (lightboxImg) {
lightboxImg.src = src;
lightboxImg.alt = caption || 'Vorschau';
}
if (lightboxCaption) {
lightboxCaption.textContent = caption;
}
}
/**
* Setzt den Text des Close-Buttons
* @param {string} text - Der neue Text
*/
export function setCloseButtonText(text) {
if (lightboxClose) {
lightboxClose.textContent = text;
}
}