Files
flipbook-bundle/contao/templates/content_element/blatterbares_pdf.html.twig
T
Jürgen MummertandClaude Opus 5 204fee73f5 feat: optional fullscreen mode
New content element option "Vollbild-Schaltfläche anzeigen" (on by default).
The button only appears once the browser confirms it exposes the Fullscreen API
for ordinary elements -- iOS Safari offers it for video only, so there it stays
hidden rather than presenting a control that cannot work.

Fitting the book to the screen needed the layout to become height-aware. Page
size was derived from width alone, which at screen width puts an A4-proportioned
page well below the bottom of the viewport. In fullscreen the page now fits to
the available height and the narrower book is centred; pages re-render at the
new size through the existing generation-stamped path.

The height fit writes a max-width onto the stage, so in fullscreen the available
width is measured on the parent instead -- measuring the element we just
constrained would oscillate. Verified stable across repeated samples.

The resize handler body moved into relayout(), shared with the fullscreen
toggle. destroy() leaves fullscreen first so the browser is not left holding a
node that is about to go away.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 15:12:10 +02:00

54 lines
3.4 KiB
Twig

{% set hasPdf = pdfUrl|default('') is not empty %}
{# Stylesheets and the module script are registered by the controller so they
land in the document head once, no matter how many flipbooks a page holds. #}
<div
class="ce-blatterbares-pdf mod-pdf-flipbook is-loading"
data-pdf-flipbook-element="1"
data-pdf-url="{{ pdfUrl|default('')|e('html_attr') }}"
data-initial-pages="{{ initialRenderPages|default(4)|e('html_attr') }}"
data-start-mode="{{ startMode|default('center')|e('html_attr') }}"
data-split-spreads="{{ splitSpreads ? '1' : '0' }}"
data-show-navigation="{{ showNavigation ? '1' : '0' }}"
data-show-fullscreen="{{ showFullscreen ? '1' : '0' }}"
data-play-turn-sound="{{ ((playTurnSound is defined) ? playTurnSound : true) ? '1' : '0' }}"
data-i18n-loading="{{ 'MSC.flipbookLoading'|trans([], 'contao_default')|e('html_attr') }}"
data-i18n-error="{{ 'MSC.flipbookError'|trans([], 'contao_default')|e('html_attr') }}"
data-i18n-missing="{{ 'MSC.flipbookMissing'|trans([], 'contao_default')|e('html_attr') }}"
data-i18n-rendering="{{ 'MSC.flipbookRendering'|trans([], 'contao_default')|e('html_attr') }}"
data-i18n-blank="{{ 'MSC.flipbookBlank'|trans([], 'contao_default')|e('html_attr') }}"
data-i18n-page-label="{{ 'MSC.flipbookPageLabel'|trans([], 'contao_default')|e('html_attr') }}"
data-i18n-fullscreen-enter="{{ 'MSC.flipbookFullscreenEnter'|trans([], 'contao_default')|e('html_attr') }}"
data-i18n-fullscreen-exit="{{ 'MSC.flipbookFullscreenExit'|trans([], 'contao_default')|e('html_attr') }}"
role="region"
aria-label="{{ 'MSC.flipbookRegionLabel'|trans([], 'contao_default')|e('html_attr') }}"
tabindex="0"
>
<div class="mod-pdf-flipbook__status" data-flipbook-loader="1" aria-live="polite">{{ 'MSC.flipbookLoading'|trans([], 'contao_default') }}</div>
<div class="mod-pdf-flipbook__stage" data-flipbook-stage="1" style="visibility:hidden;opacity:0">
<div class="c-flipbook" data-flipbook-book="1"></div>
</div>
{% if showNavigation or showFullscreen %}
<div class="mod-pdf-flipbook__controls" data-flipbook-controls="1" role="group" aria-label="{{ 'MSC.flipbookNavLabel'|trans([], 'contao_default')|e('html_attr') }}" style="visibility:hidden;opacity:0">
{% if showNavigation %}
<button type="button" data-flipbook-prev="1">{{ 'MSC.flipbookPrev'|trans([], 'contao_default') }}</button>
<button type="button" data-flipbook-next="1">{{ 'MSC.flipbookNext'|trans([], 'contao_default') }}</button>
{% endif %}
{% if showFullscreen %}
{# Hidden until the module confirms the browser exposes the Fullscreen API. #}
<button type="button" class="mod-pdf-flipbook__fullscreen" data-flipbook-fullscreen="1" aria-pressed="false" hidden>{{ 'MSC.flipbookFullscreenEnter'|trans([], 'contao_default') }}</button>
{% endif %}
</div>
{% endif %}
{% if hasPdf %}
{# Canvas content is opaque to assistive technology and to the browser's
find-in-page, so the source file stays available as an equivalent. #}
<a class="mod-pdf-flipbook__download" href="{{ pdfUrl|e('html_attr') }}" download>{{ 'MSC.flipbookDownload'|trans([], 'contao_default') }}</a>
{% else %}
<p class="mod-pdf-flipbook__error">{{ 'MSC.flipbookNotConfigured'|trans([], 'contao_default') }}</p>
{% endif %}
</div>