Mit Formular

This commit is contained in:
Thomas Spohr
2025-08-20 14:08:20 +02:00
parent 381b203e85
commit fc1de065c9
5 changed files with 240 additions and 120 deletions

View File

@@ -1,83 +1,141 @@
<?php defined('_JEXEC') or die; ?>
<style>
/* =========================
Layout-Container
========================= */
.pdf-tree-wrapper {
display: flex;
align-items: flex-start;
align-items: stretch; /* wichtig für scrollende Kinder */
gap: 1em;
background: #f9f9f9;
padding: 1em;
border: 1px solid #ddd;
border-radius: 6px;
box-shadow: 0 4px 10px rgba(0,0,0,0.05);
min-height: 0; /* erlaubt Overflow in Flex-Kindern */
}
/* Linke Spalte: Baum */
.pdf-tree-container {
flex: 0 0 30%;
max-height: 95vh;
max-height: calc(var(--vh, 100vh) - 160px); /* robust auf Desktop/iPad */
overflow: auto;
-webkit-overflow-scrolling: touch; /* smooth scroll iOS */
min-height: 0; /* wichtig für Scrollbar */
}
/* Rechte Spalte: Vorschau */
#pdf-preview {
flex: 1;
min-width: 800px;
height: 95vh;
flex: 1 1 auto;
min-width: 320px; /* iPad-freundlicher als 800px */
height: calc(var(--vh, 100vh) - 160px);
border: 1px solid #ccc;
background: #fff;
display: none;
display: none; /* wird erst bei Klick sichtbar */
min-height: 0;
position: relative;
}
/* Preview-Toolbar / Fallback-Link */
.preview-actions {
display: none;
align-items: center;
justify-content: space-between;
gap: .5rem;
padding: .5rem .75rem;
border-bottom: 1px solid #eee;
background: #fafafa;
}
.preview-actions a,
.preview-actions button {
font: inherit;
border: 1px solid #ccc;
background: #fff;
border-radius: 4px;
padding: .35rem .6rem;
}
/* iFrame */
#pdf-preview iframe {
width: 100%;
height: 100%;
height: calc(100% - 42px); /* Platz für .preview-actions */
border: none;
display: block;
}
.pdf-tree {
list-style: none;
margin: 0;
padding: 0;
}
.pdf-tree ul {
list-style: none;
margin-left: 1.5em;
padding: 0;
display: none;
}
.pdf-tree li {
margin: 0.3em 0;
}
/* =========================
Baum-Liste
========================= */
.pdf-tree { list-style: none; margin: 0; padding: 0; }
.pdf-tree ul { list-style: none; margin-left: 1.25em; padding: 0; display: none; }
.pdf-tree li { margin: 0.35em 0; }
/* Touch-freundliche Tap-Ziele */
.folder > .toggle {
cursor: pointer;
width: 1em;
display: inline-block;
width: 1.5em; /* größer für Finger */
display: inline-flex;
align-items: center;
justify-content: center;
user-select: none;
margin-right: .1em;
}
.folder > .folder-label { /* gesamten Text klickbar machen */
cursor: pointer;
user-select: none;
padding: .15rem .1rem; /* kleine Hitbox-Polster */
border-radius: 3px;
}
.folder > .folder-label:active { background: rgba(0,0,0,0.05); }
.pdf-tree .meta { color: #666; }
/* Optionale visuelle Trennung bei Dateien */
/* Datei-Link */
.file-link {
text-decoration: none;
color: #0366d6;
}
.file-link:hover {
text-decoration: underline;
}
.file-link:hover { text-decoration: underline; }
.file-link:active { opacity: .7; }
/* Buttons */
.expand-collapse {
margin-bottom: 0.5em;
display: flex;
gap: .5rem;
flex-wrap: wrap;
}
.expand-collapse button {
margin-right: 0.5em;
margin-right: 0; /* via gap */
font: inherit;
border: 1px solid #ccc;
background: #fff;
border-radius: 4px;
padding: .4rem .6rem;
}
/* Scrollbar-Optik (optional) */
.pdf-tree-container::-webkit-scrollbar { width: 10px; }
.pdf-tree-container::-webkit-scrollbar-thumb { background: rgba(0,0,0,.2); border-radius: 6px; }
/* =========================
Responsive: iPad Portrait / schmal
========================= */
@media (max-width: 1024px) {
.pdf-tree-wrapper { flex-direction: column; }
.pdf-tree-container,
#pdf-preview {
max-height: calc(var(--vh, 100vh) - 220px);
height: auto;
}
}
</style>
<!-- Buttons: Aus-/Einklappen -->
<div class="expand-collapse">
<button id="expand-all">ausklappen</button>
<button id="collapse-all">einklappen</button>
<button id="expand-all" type="button">ausklappen</button>
<button id="collapse-all" type="button">einklappen</button>
</div>
<!-- PDF-Baum und Vorschau -->
@@ -85,49 +143,98 @@
<div class="pdf-tree-container">
<?= ModEisAnzeigeHelper::renderTree($items); ?>
</div>
<div id="pdf-preview"></div>
<div id="pdf-preview">
<div class="preview-actions">
<span id="preview-filename" aria-live="polite"></span>
<a id="open-newtab" href="#" target="_blank" rel="noopener">in neuem Tab öffnen</a>
</div>
<!-- iFrame wird dynamisch eingesetzt -->
</div>
</div>
<script>
// --- echtes Viewport-Height-Polyfill (fix für Safari/macOS/iOS) ---
function setRealVh() {
const vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh * 100}px`);
}
setRealVh();
window.addEventListener('resize', setRealVh, { passive: true });
document.addEventListener('DOMContentLoaded', function () {
const preview = document.getElementById('pdf-preview');
if (!preview) return;
const treeContainer = document.querySelector('.pdf-tree-container');
const preview = document.getElementById('pdf-preview');
if (!treeContainer || !preview) return;
// (1) Verzeichnisse toggeln
document.querySelectorAll('.pdf-tree .toggle').forEach(toggle => {
toggle.addEventListener('click', () => {
const ul = toggle.closest('li').querySelector('ul');
if (ul) {
const visible = ul.style.display === 'block';
ul.style.display = visible ? 'none' : 'block';
toggle.textContent = visible ? '▶' : '▼';
}
});
});
const previewBar = preview.querySelector('.preview-actions');
const openNewTab = document.getElementById('open-newtab');
const previewName = document.getElementById('preview-filename');
// (2) Alle ausklappen
document.getElementById('expand-all')?.addEventListener('click', () => {
document.querySelectorAll('.pdf-tree ul').forEach(ul => ul.style.display = 'block');
document.querySelectorAll('.pdf-tree .toggle').forEach(t => t.textContent = '▼');
});
// --- (1) Verzeichnisse toggeln Caret und Label (Event Delegation, robust für iPad) ---
treeContainer.addEventListener('click', (ev) => {
const t = ev.target;
// (3) Alle einklappen
document.getElementById('collapse-all')?.addEventListener('click', () => {
document.querySelectorAll('.pdf-tree ul').forEach(ul => ul.style.display = 'none');
document.querySelectorAll('.pdf-tree .toggle').forEach(t => t.textContent = '▶');
});
// Toggle per Caret
if (t.classList.contains('toggle')) {
const li = t.closest('li.folder');
if (!li) return;
const ul = li.querySelector(':scope > ul');
if (!ul) return;
const visible = ul.style.display === 'block';
ul.style.display = visible ? 'none' : 'block';
t.textContent = visible ? '▶' : '▼';
return;
}
// (4) PDF-Vorschau
document.querySelectorAll('.pdf-tree .file-link').forEach(link => {
link.addEventListener('click', e => {
e.preventDefault();
preview.style.display = 'block';
preview.innerHTML = ''; // Vorherige Vorschau entfernen
const iframe = document.createElement('iframe');
iframe.src = link.href;
iframe.loading = 'lazy';
preview.appendChild(iframe);
});
});
// Toggle per Ordner-Label
if (t.classList.contains('folder-label')) {
const li = t.closest('li.folder');
if (!li) return;
const caret = li.querySelector(':scope > .toggle');
if (caret) caret.click();
return;
}
});
// --- (2) Alle ausklappen (mit Scroll-to-top) ---
document.getElementById('expand-all')?.addEventListener('click', () => {
document.querySelectorAll('.pdf-tree ul').forEach(ul => ul.style.display = 'block');
document.querySelectorAll('.pdf-tree .toggle').forEach(t => t.textContent = '▼');
treeContainer.scrollTo({ top: 0, behavior: 'instant' });
});
// --- (3) Alle einklappen ---
document.getElementById('collapse-all')?.addEventListener('click', () => {
document.querySelectorAll('.pdf-tree ul').forEach(ul => ul.style.display = 'none');
document.querySelectorAll('.pdf-tree .toggle').forEach(t => t.textContent = '▶');
});
// --- (4) PDF-Vorschau + Fallback-Link (iOS: iframe kann zickig sein) ---
treeContainer.addEventListener('click', (ev) => {
const a = ev.target.closest('.file-link');
if (!a) return;
ev.preventDefault();
preview.style.display = 'block';
previewBar.style.display = 'flex';
previewName.textContent = a.getAttribute('data-filename') || a.textContent.trim();
openNewTab.href = a.href;
// iFrame neu setzen
preview.querySelector('iframe')?.remove();
const iframe = document.createElement('iframe');
iframe.setAttribute('title', 'PDF-Vorschau');
iframe.src = a.href;
iframe.loading = 'lazy';
// iOS Fallback: Wenn Onload nicht in 1.5s triggert, Link oben verwenden
let loaded = false;
const t = setTimeout(() => { /* optional Hinweis einblenden */ }, 1500);
iframe.addEventListener('load', () => { loaded = true; clearTimeout(t); }, { once: true });
preview.appendChild(iframe);
}, { passive: false });
});
</script>