From 1564d96b0168c2acc4146b4163f76cdf43280ae2 Mon Sep 17 00:00:00 2001 From: Juergen Date: Mon, 13 Apr 2026 22:18:45 +0200 Subject: [PATCH] fix: polish initial flipbook reveal and update third-party metadata --- THIRD_PARTY_LICENSES.md | 2 +- .../blatterbares_pdf.html.twig | 12 +++--- public/assets/flipbook-module.css | 31 ++++++++++++++ public/assets/flipbook-module.js | 41 +++++++++++++++++++ 4 files changed, 79 insertions(+), 7 deletions(-) diff --git a/THIRD_PARTY_LICENSES.md b/THIRD_PARTY_LICENSES.md index 949c6a0..766861e 100644 --- a/THIRD_PARTY_LICENSES.md +++ b/THIRD_PARTY_LICENSES.md @@ -6,7 +6,7 @@ This bundle contains the following third-party open source libraries in `public/ - Project: https://github.com/mozilla/pdf.js - Package: `pdfjs-dist` -- Version: `4.9.155` +- Version: `5.6.205` - License: Apache-2.0 ## flipbook-js diff --git a/contao/templates/content_element/blatterbares_pdf.html.twig b/contao/templates/content_element/blatterbares_pdf.html.twig index 5e37380..11101f4 100644 --- a/contao/templates/content_element/blatterbares_pdf.html.twig +++ b/contao/templates/content_element/blatterbares_pdf.html.twig @@ -1,7 +1,7 @@ {% set hasPdf = pdfUrl|default('') is not empty %}
PDF wird geladen ...
-
+ {% if showNavigation %} -
+ @@ -28,6 +28,6 @@ {% endif %}
- - - + + + diff --git a/public/assets/flipbook-module.css b/public/assets/flipbook-module.css index 003a323..8cabf40 100644 --- a/public/assets/flipbook-module.css +++ b/public/assets/flipbook-module.css @@ -13,11 +13,24 @@ } .mod-pdf-flipbook__status { + display: inline-flex; + align-items: center; + gap: 0.55rem; margin-bottom: 0.8rem; font-size: 0.92rem; color: var(--flipbook-text); } +.mod-pdf-flipbook__status::before { + content: ''; + width: 0.9rem; + height: 0.9rem; + border: 2px solid rgba(48, 45, 41, 0.25); + border-top-color: rgba(48, 45, 41, 0.85); + border-radius: 50%; + animation: mod-pdf-flipbook-spin 0.75s linear infinite; +} + .mod-pdf-flipbook__status.is-hidden { display: none; } @@ -26,18 +39,29 @@ color: #9f1f1f; } +.mod-pdf-flipbook__status.is-error::before { + display: none; +} + .mod-pdf-flipbook__stage { position: relative; width: 100%; margin: 0 auto; background: #e0e0e0; z-index: 1; + transition: opacity 1.3s ease 0.5s; } .mod-pdf-flipbook .c-flipbook { max-width: 100%; } +.mod-pdf-flipbook .c-flipbook.is-booting, +.mod-pdf-flipbook .c-flipbook.is-booting .c-flipbook__page, +.mod-pdf-flipbook .c-flipbook.is-booting .c-flipbook__page::before { + transition: none !important; +} + .mod-pdf-flipbook .c-flipbook__page { background: #fefdf9; overflow: hidden; @@ -73,6 +97,7 @@ display: flex; gap: 0.6rem; margin-top: 0.9rem; + transition: opacity 1.3s ease 0.5s; } .mod-pdf-flipbook__error { @@ -85,3 +110,9 @@ justify-content: space-between; } } + +@keyframes mod-pdf-flipbook-spin { + to { + transform: rotate(360deg); + } +} diff --git a/public/assets/flipbook-module.js b/public/assets/flipbook-module.js index c8c2d36..2bb44a7 100644 --- a/public/assets/flipbook-module.js +++ b/public/assets/flipbook-module.js @@ -36,6 +36,8 @@ class PdfFlipbookModule { this.root = root; this.dependencies = dependencies; this.pdfUrl = (root.dataset.pdfUrl || '').trim(); + this.root.classList.add('is-loading'); + this.root.classList.remove('is-ready'); this.initialPages = Number.isFinite(parsedInitialPages) ? Math.min(4, Math.max(2, parsedInitialPages)) : 4; @@ -47,6 +49,7 @@ class PdfFlipbookModule { this.loader = root.querySelector('[data-flipbook-loader="1"]'); this.stage = root.querySelector('[data-flipbook-stage="1"]'); this.bookElement = root.querySelector('[data-flipbook-book="1"]'); + this.controlsElement = root.querySelector('[data-flipbook-controls="1"]'); this.nextButton = this.showNavigation ? root.querySelector('[data-flipbook-next="1"]') : null; this.prevButton = this.showNavigation ? root.querySelector('[data-flipbook-prev="1"]') : null; @@ -76,6 +79,7 @@ class PdfFlipbookModule { if (!this.pdfUrl) { this.setStatus('Keine PDF-Datei gefunden.', true); + this.root.classList.remove('is-loading'); return; } @@ -94,12 +98,47 @@ class PdfFlipbookModule { this.bindTouchSwipe(); this.bindResize(); this.queuePages(this.getLazyCandidates()); + await this.showReadyState(); this.setStatus(''); } catch { this.setStatus('PDF konnte nicht geladen werden.', true); + this.root.classList.remove('is-loading'); } } + async showReadyState() { + await new Promise((resolve) => { + window.requestAnimationFrame(() => { + window.requestAnimationFrame(resolve); + }); + }); + + if (this.bookElement) { + this.bookElement.classList.remove('is-booting'); + } + + this.root.classList.remove('is-loading'); + this.root.classList.add('is-ready'); + + if (this.stage) { + this.stage.style.visibility = 'visible'; + } + + if (this.controlsElement) { + this.controlsElement.style.visibility = 'visible'; + } + + window.requestAnimationFrame(() => { + if (this.stage) { + this.stage.style.opacity = '1'; + } + + if (this.controlsElement) { + this.controlsElement.style.opacity = '1'; + } + }); + } + async loadPdf() { const loadingTask = this.dependencies.pdfjsLib.getDocument({ url: this.pdfUrl, @@ -178,6 +217,8 @@ class PdfFlipbookModule { initializeFlipbook() { const startsWithDoubleSpread = this.startMode === 'spread'; + this.bookElement.classList.add('is-booting'); + this.flipbook = new this.dependencies.FlipBook(this.bookElement, { nextButton: this.nextButton, previousButton: this.prevButton,