From 781f050dfcd2f1a9dbc6bac2af468fd4db8637cd Mon Sep 17 00:00:00 2001 From: Juergen Date: Mon, 13 Apr 2026 22:00:39 +0200 Subject: [PATCH] feat: add optional page-turn sound toggle and refine flipbook UI --- contao/dca/tl_content.php | 10 +++++++- contao/languages/de/tl_content.php | 1 + contao/languages/en/tl_content.php | 1 + .../blatterbares_pdf.html.twig | 7 +++--- public/assets/audio/turn.mp3 | Bin 0 -> 2784 bytes public/assets/flipbook-module.css | 3 +++ public/assets/flipbook-module.js | 22 ++++++++++++++++++ .../BlatterbaresPdfController.php | 1 + 8 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 public/assets/audio/turn.mp3 diff --git a/contao/dca/tl_content.php b/contao/dca/tl_content.php index de0c3cd..02f9ab9 100644 --- a/contao/dca/tl_content.php +++ b/contao/dca/tl_content.php @@ -2,7 +2,7 @@ declare(strict_types=1); -$GLOBALS['TL_DCA']['tl_content']['palettes']['blatterbares_pdf'] = '{type_legend},type,headline;{flipbook_legend},flipbookPdfSrc,flipbookInitialPages,flipbookStartMode,flipbookShowNavigation;{template_legend:hide},customTpl;{protected_legend:hide},protected;{expert_legend:hide},cssID;{invisible_legend:hide},invisible,start,stop'; +$GLOBALS['TL_DCA']['tl_content']['palettes']['blatterbares_pdf'] = '{type_legend},type,headline;{flipbook_legend},flipbookPdfSrc,flipbookInitialPages,flipbookStartMode,flipbookShowNavigation,flipbookPlaySound;{template_legend:hide},customTpl;{protected_legend:hide},protected;{expert_legend:hide},cssID;{invisible_legend:hide},invisible,start,stop'; $GLOBALS['TL_DCA']['tl_content']['fields']['flipbookPdfSrc'] = [ 'label' => &$GLOBALS['TL_LANG']['tl_content']['flipbookPdfSrc'], @@ -39,3 +39,11 @@ $GLOBALS['TL_DCA']['tl_content']['fields']['flipbookShowNavigation'] = [ 'eval' => ['tl_class' => 'w50 m12'], 'sql' => ['type' => 'string', 'length' => 1, 'fixed' => true, 'default' => '1'], ]; + +$GLOBALS['TL_DCA']['tl_content']['fields']['flipbookPlaySound'] = [ + 'label' => &$GLOBALS['TL_LANG']['tl_content']['flipbookPlaySound'], + 'exclude' => true, + 'inputType' => 'checkbox', + 'eval' => ['tl_class' => 'w50 m12'], + 'sql' => ['type' => 'string', 'length' => 1, 'fixed' => true, 'default' => '1'], +]; diff --git a/contao/languages/de/tl_content.php b/contao/languages/de/tl_content.php index ab84d4c..f7d31d6 100644 --- a/contao/languages/de/tl_content.php +++ b/contao/languages/de/tl_content.php @@ -16,3 +16,4 @@ $GLOBALS['TL_LANG']['tl_content']['flipbookStartModeOptions'] = [ 'spread' => 'als Doppelseite starten', ]; $GLOBALS['TL_LANG']['tl_content']['flipbookShowNavigation'] = ['Navigation anzeigen', 'Zeigt Vor-/Zurueck-Buttons unter dem Flipbook an.']; +$GLOBALS['TL_LANG']['tl_content']['flipbookPlaySound'] = ['Blättersound abspielen', 'Spielt beim Blättern einen Sound ab.']; diff --git a/contao/languages/en/tl_content.php b/contao/languages/en/tl_content.php index f59c0f2..db5fbb6 100644 --- a/contao/languages/en/tl_content.php +++ b/contao/languages/en/tl_content.php @@ -16,3 +16,4 @@ $GLOBALS['TL_LANG']['tl_content']['flipbookStartModeOptions'] = [ 'spread' => 'Start with double-page spread', ]; $GLOBALS['TL_LANG']['tl_content']['flipbookShowNavigation'] = ['Show navigation', 'Displays previous/next buttons below the flipbook.']; +$GLOBALS['TL_LANG']['tl_content']['flipbookPlaySound'] = ['Play page-turn sound', 'Plays a sound effect while turning pages.']; diff --git a/contao/templates/content_element/blatterbares_pdf.html.twig b/contao/templates/content_element/blatterbares_pdf.html.twig index 1377f9f..5e37380 100644 --- a/contao/templates/content_element/blatterbares_pdf.html.twig +++ b/contao/templates/content_element/blatterbares_pdf.html.twig @@ -7,6 +7,7 @@ data-initial-pages="{{ initialRenderPages|default(4)|e('html_attr') }}" data-start-mode="{{ startMode|default('center')|e('html_attr') }}" data-show-navigation="{{ showNavigation ? '1' : '0' }}" + data-play-turn-sound="{{ ((playTurnSound is defined) ? playTurnSound : true) ? '1' : '0' }}" tabindex="0" >
PDF wird geladen ...
@@ -27,6 +28,6 @@ {% endif %} - - - + + + diff --git a/public/assets/audio/turn.mp3 b/public/assets/audio/turn.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..9236a75bae96d358277f62faca6468fab35c758d GIT binary patch literal 2784 zcmb`}c{G&!9|!QUGgL-~F)el`Y3^7O!nKU8P{Ys=Vi@9Tq@qFD(`X@*vfsvX8I-83 z8OxBZM3$70eQU&wJ@ed|drs&4&hM|^IrsNE=Q+=F&hwo2_wy{D=X?NW93Auv&X4HJ zIo`+FU?3299K_3k;LznjbDZUH;UI8b;t1zR;mG1B;CRke%|Ykr;^^ZT;`qk3z_G%y z$+61;aB$X=v@x+Y*FtKbQ2eA{r9g$1c&p?=Jo(%@9%pzw{B`2L_5f3oTR-1V9%B$l zM8MeZ)&699W{@kuq|-$a=hYJ3ZhL?b2m1>B8x2H%W_>JqYzx*)-?%_z+J*TM9|tt2 z_^+By&8K1NzPBZ(N0qDUmpenL^$nNwEys zM~N7P_M-Z2UpB+R&yLc1aWe4Kd5Kx1YQuI0GeEY%rOKvzT6M<9$5-b0v_eMY^={Sy zi%TP;UQbdek!-&X0D>_LoY z16d%iOLn?c>SvmG3E3qFOIbWb$(&XMrY=u7n{NTkYxEHXMJLL+78FklDs^70sKY2% zk7!z4Qa5Ksvk71)Z)H-!MZuxCVc{y=DM8QQ^YQo_Kn?b6IanEe|Fmh8GWkesDY_jB z5#yEcOBK@I_fqX(+wH-${TEBc{-XMi7RpNfsHjPp3L_#KR5ZeSY6dQU$l9>noQ+F) zq;;(#8NZN0rQY_nuvVI{+A}#dz8PXveJiSj3iTO z?2lI?x7k!G`SI$@GZfc0%hr1ulBv=lesSkcQU30iP|<9dW81@WX|<>F_L45~P&k%; z*^$p|k)N^mfo8KGLdz5X?hiJ=MANsVs+(z2!hHvU<-WwWU5AZBf#K@CyG9HC8Pwui zSY;|gQp(aJ|ETJ7Cw&0{jdzm|i1x_%*yGACcsw3NtzI=*jjdMqxFRdmG(yJ5#>-$$ zl@zMqNEs?KQjpyHT9LNut7X9~3>yxg#APH>@EOmbb5-8YsQMALJHUM5=7db-+Rn#W zPWR6OJ2cvz%{Hu1o*at7-o!Xo6wLUQ+P*g8nT@T#uuR$`1lH;qc&Q|>C4tfxz zL2>6RFt{dO+M*XHhX<37Oa+b8j}ZW-Hk~ag4zFFeiURc$dG9?|JTrUu45iB06$$1c zyT8+BKcs$2a*;#^P)QRcEiAq>NXR7Oa_0?O+k=f|<7mgSPS>%56@ckYpF2cpu7lbb zg9Jl8=3S@3uC#`%BZ<&?UiCPA?bBJoUbCg8wfFZt#)iB0=8loN(k?XGBb4kAQaNbH zA>7L&KKF4|J)_G=W?%wyC0j)-W~PKhXeO^EiKjwj->)r|s{altUfH1Ka{qrEyHkkd z5yiLfe~%n?hFG#jyN0WjU1VyapGsUw0+^|Emj20{9@!)kPiWe1@z1P=8- zvG7+AEzN?}As_bbrj=v3bv~aO+<3@5^>BgpkS^Zwgg{Zp>lp=Y<$CmVcJtAmx*ou7*6pi<`f?zr6On zJIcbNZZ>=y9Q@p?OIEgCi6993qEDyI*e(WB$!>l0dA@5QZ~@XS$o zKHPp6WTi5mD7&+wsf1|?)Kj??93UGOMkurdcAo;D;!3#r>rfQCLI-AZ?t;^rd@W)JY%UWLfc3=hb^**kmnX(~<&l zto9*wT*BfCWQvd@x=+L?r7zEd&oV)Ro6nMZaHrWFj1F)np2z(W2yEvn($9XkYdkQ5 zxw4+M@<$w=5U%OcBiv+sbuq?p<<)yjq_SeZ0DD`rxghKViS~8k(TmhSU+Ka`ki|s~ zHRVt49yE$2<}1stD>!lccL{c}xoymqOFsXasavbRT0;rcL=6OjL!|mTS@ww3kcNluk!WpgUOt&}ZpAGKGD5P}4tjMo5DiM|b6b%2A^4g2zuK;$VVu|3eOU4rFoXK<<3_ HAJ_j4uHi3w literal 0 HcmV?d00001 diff --git a/public/assets/flipbook-module.css b/public/assets/flipbook-module.css index e2a5f23..003a323 100644 --- a/public/assets/flipbook-module.css +++ b/public/assets/flipbook-module.css @@ -31,6 +31,7 @@ width: 100%; margin: 0 auto; background: #e0e0e0; + z-index: 1; } .mod-pdf-flipbook .c-flipbook { @@ -67,6 +68,8 @@ } .mod-pdf-flipbook__controls { + position: relative; + z-index: 20; display: flex; gap: 0.6rem; margin-top: 0.9rem; diff --git a/public/assets/flipbook-module.js b/public/assets/flipbook-module.js index 7a33b2c..c8c2d36 100644 --- a/public/assets/flipbook-module.js +++ b/public/assets/flipbook-module.js @@ -2,6 +2,7 @@ const MODULE_SELECTOR = '[data-pdf-flipbook-element="1"]'; const PDF_MODULE_URL = '/bundles/flipbook/assets/vendor/pdf.min.mjs'; const PDF_WORKER_URL = '/bundles/flipbook/assets/vendor/pdf.worker.min.mjs'; const FLIPBOOK_MODULE_URL = '/bundles/flipbook/assets/vendor/flipbook.esm.min.js'; +const TURN_SOUND_URL = '/bundles/flipbook/assets/audio/turn.mp3'; const INIT_MARKER = 'pdfFlipbookInitialized'; const BOOTSTRAP_MARKER = '__mummertPdfFlipbookBootstrapBound'; @@ -39,6 +40,7 @@ class PdfFlipbookModule { ? Math.min(4, Math.max(2, parsedInitialPages)) : 4; this.showNavigation = root.dataset.showNavigation === '1'; + this.playTurnSoundEnabled = root.dataset.playTurnSound !== '0'; this.startMode = (root.dataset.startMode === 'spread' || root.dataset.startMode === 'cover') ? 'spread' : 'center'; @@ -57,6 +59,7 @@ class PdfFlipbookModule { this.renderInProgress = false; this.resizeTimer = null; this.touchStart = null; + this.turnSound = this.playTurnSoundEnabled ? this.createTurnSound() : null; this.aspectRatio = 1.4142; this.pageWidth = 0; this.pageHeight = 0; @@ -185,11 +188,30 @@ class PdfFlipbookModule { width: '100%', height: `${this.pageHeight}px`, onPageTurn: () => { + this.playTurnSound(); this.queuePages(this.getLazyCandidates()); }, }); } + createTurnSound() { + const audio = new Audio(TURN_SOUND_URL); + audio.preload = 'auto'; + + return audio; + } + + playTurnSound() { + if (!this.playTurnSoundEnabled || !this.turnSound) { + return; + } + + this.turnSound.currentTime = 0; + + this.turnSound.play().catch(() => { + }); + } + bindKeyboard() { this.root.addEventListener('pointerdown', () => { this.root.focus(); diff --git a/src/Controller/ContentElement/BlatterbaresPdfController.php b/src/Controller/ContentElement/BlatterbaresPdfController.php index 62f2537..7932d70 100644 --- a/src/Controller/ContentElement/BlatterbaresPdfController.php +++ b/src/Controller/ContentElement/BlatterbaresPdfController.php @@ -19,6 +19,7 @@ class BlatterbaresPdfController extends AbstractContentElementController { $template->set('pdfUrl', $this->resolvePdfUrl($model)); $template->set('showNavigation', '1' === (string) ($model->flipbookShowNavigation ?? '1')); + $template->set('playTurnSound', '1' === (string) ($model->flipbookPlaySound ?? '1')); $template->set('initialRenderPages', $this->normalizeInitialRenderPages((string) ($model->flipbookInitialPages ?? '4'))); $template->set('startMode', $this->normalizeStartMode((string) ($model->flipbookStartMode ?? 'center')));