Zum Inhalt springen

Vorlagen-Teile

Modulare Vorlagenstruktur für einfache Wartung und Anpassung.

VidPly TYPO3 Extension Logo

Speicherort

Resources/Private/Partials/VidPly/

Verfügbare Teilvorlagen

1. Assets.html

Registriert CSS- und JavaScript-Assets bedingt

 
<f:render partial="VidPly/Assets" arguments="{
    needsPrivacyLayer: vidply.needsPrivacyLayer,
    needsVidPlay: vidply.needsVidPlay,
    needsPlaylist: vidply.needsPlaylist,
    needsHLS: vidply.needsHLS,
    needsDASH: vidply.needsDASH
}" />
 

Argumente:

  • needsPrivacyLayer - PrivacyLayer.js laden (externe Dienste)
  • needsVidPlay - VidPly-Kern laden (nativer Player)
  • needsPlaylist - PlaylistInit.js laden (Wiedergabelisten/Player-Initialisierung)
  • needsHLS - hls.js laden (HLS-Streaming)
  • needsDASH - dash.js laden (DASH-Streaming)

Wird immer geladen:

  • vidply.min.css - Player-Styling

Wird je nach Medientyp bedingt geladen:

  • privacy-layer.css - Stile der Datenschutzebene (nur externe Dienste)
  • PrivacyLayer.js - YouTube, Vimeo, SoundCloud
  • hls.min.js — Vendored hls.js 1.7.2 (nur HLS-Streams)
  • dash.all.min.js — eingebundenes „dash.js“ 5.2.1 (modernes UMD; nur DASH-Streams)
  • PlaylistInit.js - Wiedergabelisten oder Player-Initialisierung
  • vidply/vidply.esm.min.js - Nur nativer Player (plus Code-Split-Chunks)

Siehe Documentation/AssetLoading.md für Details zur Optimierung.

2. VideoSources.html

Rendert „<source>“-Elemente für Videoplayer

 
<f:render partial="VidPly/VideoSources" arguments="{
    videoUrl: vidply.videoUrl,
    playlistData: vidply.playlistData,
    sources: vidply.sources,
    mediaFiles: vidply.mediaFiles
}" />
 

Unterstützt:

  • Mehrere Quellformate mit Fallback-Reihenfolge (DASH → HLS → MP4/WebM)
  • Mehrere Qualitäts- und Formatoptionen
  • Playlist-Modus
  • Quellen für Audiodeskriptionen

3. AudioSources.html

Rendert „<source>“-Elemente für Audio-Player

 
<f:render partial="VidPly/AudioSources" arguments="{
    playlistData: vidply.playlistData,
    tracks: vidply.tracks,
    sources: vidply.sources,
    mediaFiles: vidply.mediaFiles
}" />
 

Unterstützt:

  • Mehrere Quellformate mit Fallback-Reihenfolge (DASH → HLS → MP3/OGG)
  • Wiedergabelisten-Modus
  • Format-Fallback

4. Tracks.html

Rendert Untertitel- und Kapitel<track>-Elemente

 
<f:render partial="VidPly/Tracks" arguments="{
    captions: vidply.captions,
    chapters: vidply.chapters,
    languageSelection: vidply.languageSelection
}" />
 

Wird von Video- und Audio-Playern gemeinsam genutzt. Unterstützt mehrere Sprachen und Titeltypen.

5. MetadataScripts.html

JSON-Payloads für Audiodeskription und Gebärdensprache (werden vom Player bei der Initialisierung gelesen – kein JSON-LD)

 
<f:render partial="VidPly/MetadataScripts" arguments="{
    uniqueId: vidply.uniqueId,
    audioDescriptionTracks: vidply.audioDescriptionTracks,
    audioDescription: vidply.audioDescription,
    signLanguage: vidply.signLanguage
}" />
 

Wird von Videoplayern für Metadaten zu Audiodeskriptions- und Gebärdensprachspuren verwendet.

 

SEO-JSON-LD (VideoObject / AudioObject) wird separat auf der Seite ausgegeben <head> über Partials/Page/StructuredDataVideo.html — siehe Entwickler-Schnellstart → Strukturierte Daten.

 

6. PrivacyLayer.html

DSGVO-Einwilligungslayer für externe Dienste

 
<f:render partial="VidPly/PrivacyLayer" arguments="{
    service: 'youtube',
    videoUrl: vidply.videoUrl,
    poster: vidply.poster,
    title: data.header,
    uniqueId: vidply.uniqueId,
    privacySettings: vidply.privacySettings.youtube
}" />
 

Zeigt eine Wiedergabetaste mit Datenschutzhinweis für YouTube, Vimeo und SoundCloud an. Verwendet die Datenbankeinstellungen aus der tx_mpcvidply_privacy_settings Tabelle, mit Fallback auf Übersetzungen aus der Sprachdatei. Lädt bei Einwilligung ein iframe.

Struktur der Datenschutzeinstellungen:

 
[
    'headline' => 'Optional headline',
    'intro_text' => 'Text before link',
    'outro_text' => 'Text after link',
    'policy_link' => 'https://...',
    'link_text' => 'Link text',
    'button_label' => 'Button aria-label'
]
 

7. MediaPlayer.html

Das Element „<video>“ bzw. „<audio>“ selbst

Player.html legt mediaKind auf audio oder video und rendert dieses Partial für beide. mediaKind ist zugleich der Elementname, also das Tag, das standardmäßig aria-label, das poster Attribut (nur Video), die Quellen-Partials und MetadataScripts.html (nur bei Video) leiten sich alle davon ab.

 
<f:variable name="mediaKind" value="video" />
<f:render partial="VidPly/MediaPlayer" arguments="{_all}" />
 

Es ersetzt das bisherige VideoPlayer.html und AudioPlayer.html, die abgesehen von diesen fünf Punkten identisch waren. Site-Pakete, die eines von beiden überschreiben, müssen stattdessen MediaPlayer.html stattdessen überschreiben.

Vorlagenstruktur

 
VidPly.html (Main)
├── layout = card|episodes → VidPly/EpisodeLayout.html
│   ├── VidPly/EpisodeCard.html (cover, episode number, title, date, duration, description)
│   └── VidPly/Player.html
└── VidPly/Player.html (wrapper + renderMode switch)
    ├── privacy → PrivacyLayer.html
    ├── mixedPlaylist → MixedPlaylistPlayer.html
    └── audio / video → MediaPlayer.html (mediaKind = audio|video)
        ├── VideoSources.html / AudioSources.html
        ├── Tracks.html
        └── MetadataScripts.html (video only)
    └── Assets.html (conditional JS/CSS)
 

Auf Seitenebene: Partials/Page/StructuredDataVideo.html (JSON-LD in <head>).

Anpassung

Überschreiben im Sitepackage

TypoScript:

 
tt_content.mpc_vidply {
    partialRootPaths.100 = EXT:your_sitepackage/Resources/Private/Partials/
}
 

Benutzerdefiniertes Partial erstellen:

 
your_sitepackage/
└── Resources/Private/Partials/VidPly/
    └── VideoSources.html  ← Your customization
 

Andere Partials bleiben unverändert.

Listenansicht- und Detailvorlagen

Speicherort: Resources/Private/Partials/Listview/ und Resources/Private/Templates/Listview.html / Detail.html

Partial / VorlageRolle
Listview/RowEin Regal oder eine Rasterzeile: Überschrift, Sortierung <select>, optionaler Paginierungs-Wrapper
Listview/RowListBodyGemeinsam genutzt <ul> für Raster oder Regal (mit oder ohne Paginierung verwendbar)
Listview/CardEinzelne Medienkarte (Poster, Titel, Interpret, Kategorie-Chips, Link)
Listview/ShelfArrowsSteuerelemente „Zurück/Weiter“ für das horizontale Regal

Auf dieselbe Weise überschreiben mit partialRootPaths für mpc_vidply Listansicht TypoScript, falls Ihr Sitepackage ein anderes Markup benötigt; behalten Sie data-* Attribute bei, wenn Sie auf Listview.js (Shelf, Sortierung, Paginierung).

Teilvorlagen für Episodenkarten

Werden verwendet, wenn das Feld „Layout“ des Inhaltselements (tx_mpcvidply_layout) auf „Episodenkarte“ oder „Episodenkarte mit Episodenliste“ eingestellt ist; default rendet den einfachen Player genau wie zuvor.

TeilRolle
VidPly/EpisodeLayoutLayout-Wrapper, lädt episode.min.css + EpisodeInit.min.js, rendert die Karte oder die Episodenliste sowie den Player
VidPly/EpisodeListDie <ol> der Episodenzeilen, die entweder separat oder innerhalb des Pager-Containers gerendert werden
VidPly/EpisodeCoverQuadratisches Titelbild einer Folge
VidPly/EpisodeCardRunde Wiedergabetaste neben Episodennummer, Titel, Veröffentlichungsdatum, Dauer, Beschreibung, Download-Link und dem Symbol zum Anzeigen der ausführlichen Beschreibung

EpisodeCard erfordert ein titleLevel Argument (3 für die Einzelkarte, 4 für Listenzeilen ), damit die Reihenfolge der Überschriften unterhalb der Kopfzeile des Inhaltselements lückenlos bleibt.

Die beiden Layouts

Beide beginnen mit derselben Karte: mpc-episode-cover neben mpc-episode-main, die den Kartentext auf den Player stapelt. Die Episodenkarte endet an dieser Stelle und zeigt vidply.episodeden ersten Eintrag an.

Die Episodenkarte mit Episodenliste fügt eine mpc-episode-list-section , das zu einer Zeile voller Breite darunter wechselt und jeden Datensatz in vidply.episodes als <ol> Reihe mpc-episode-item Zeilen. Die Karte fungiert dann als „Aktuell läuft“-Kopfzeile: EpisodeInit.js Bei jedem Titelwechsel wird die ausgewählte Zeile in diese Karte kopiert, sodass das Cover, der Titel, das Datum, die Dauer, die Kategorien und die Beschreibung immer zum aktuellen Titel im Player gehören. Durch das Kopieren bleibt das vom Server gerenderte Markup die einzige Quelle für die Episodendaten – nichts wird in JavaScript neu formatiert.

Da es sich bei der Liste um die Titelübersicht handelt, deaktiviert der Prozessor das eigene Wiedergabelisten-Fenster des Players (showPanel: false) und blendet dessen Umschaltknopf aus (playlistToggleButton: false) – andernfalls würden dieselben Datensätze zweimal von zwei verschiedenen Formatierern dargestellt.

Die Episodendaten stammen aus EpisodeListBuilder::build(), und zwar layoutbezogen, sodass die Episodenkarte keine Abfragen für Poster und Kategorien von Datensätzen durchführt, die sie niemals anzeigt. Datumsangaben, Laufzeiten und Downloadgrößen werden in PHP bereits für die Sprache der Website formatiert, sodass Vorlagen fertige Zeichenketten ausgeben.

Nur Datensätze, aus denen ein abspielbarer Titel entstanden ist, gelangen in vidply.episodes, was dafür sorgt, dass episode.index als Track-Index der Wiedergabeliste nutzbar bleibt: Ein Datensatz, dessen Quelle nicht aufgelöst werden kann, wird sofort aus beiden Listen entfernt.

Sortierung und Paginierung der Episodenliste

Die Liste verfügt über ein eigenes Sortier-Dropdown-Menü und, ab einer konfigurierbaren Seitengröße, über einen Pager – nach dem Vorbild der Listenansicht (Listview.js), der jedoch in EpisodeInit.js.

Beide wirken sich nur auf die Liste aus. episode.index bleibt der Titelindex der Wiedergabeliste unverändert, unabhängig davon, wie die Zeilen sortiert sind oder welche davon ausgeblendet sind, sodass der Player die Reihenfolge des Editors für „Nächster/Vorheriger“ und den automatischen Vorlauf beibehält. Das bedeutet auch, dass die „Aktuell abgespielte“-Karte als die Folge mit dem Index 0 (EpisodeListBuilder::resolveLeadEpisode()), nicht als erster Array-Eintrag.

Feld (tt_content)Wirkung
tx_mpcvidply_episode_sortVoreingestellte Reihenfolge: sorting (Reihenfolge der Medienelemente), date_desc, date_asc, title_asc. Wird serverseitig angewendet und in die <select>
tx_mpcvidply_episode_paginationAktiviert die Paginierung; diese wird erst sichtbar, sobald mehr Episoden vorhanden sind, als auf eine Seite passen
tx_mpcvidply_episode_per_pageEpisoden pro Seite, begrenzt auf 1–200 (Standard 10)

Folgen ohne Veröffentlichungsdatum werden in beiden Datumsmodi – sowohl auf dem Server als auch im Browser – an letzter Stelle sortiert, sodass ein unvollständiger Datensatz niemals an der Spitze einer „Neueste zuerst“-Liste steht. Bei Gleichstand wird auf den Titelindex zurückgegriffen.

Ausgeblendete Zeilen tragen das hidden Attribut, wodurch sie aus der Tabulatorreihenfolge und dem Barrierefreiheitsbaum entfernt werden; die Überschrift behält die vollständige Episodenanzahl bei, während der Seitenzähler die aktuelle Seite angibt. Beim Seitenwechsel springt der Fokus auf die erste Zeile der neuen Seite, und bei einem Titelwechsel wird die Seite mit der aktiven Zeile angezeigt – so wird die Liste mitgeführt, wenn man automatisch über das Ende einer Seite hinausblättert.

AttributZweck
data-mpc-episode-default-sortFür den Abschnitt: die vom Editor vorab ausgewählte Reihenfolge, die beim <select> beim Laden
data-mpc-episode-sortDie Sortierreihenfolge <select>
data-mpc-episode-listDie <ol> deren <li> Kinder sortiert und paginiert werden
data-mpc-episode-date / data-mpc-episode-sort-titleSortierschlüssel pro Zeile (Y-m-d, leer, wenn nicht festgelegt)
data-mpc-episode-paginatePager-Container; enthält data-mpc-episode-per-page sowie die Pager-Bezeichnungen
data-mpc-episode-pager-navLeer <nav> Die Schaltflächen werden in

„Downloads“ in der Episodenliste

episode.downloadUrl und episode.downloadInfo („MP3, 7,4 MB“) werden für Einträge mit der Option „Download zulassen“ ausgefüllt – jedoch nur im Episodenlisten-Layout einer Wiedergabeliste. Da sich dort jede Episode auf der Seite befindet, ermöglicht ein Link pro Zeile den Besuchern, jede beliebige Episode zu speichern, ohne sie zuvor auswählen zu müssen.

Bei jeder anderen Kombination erfolgt der Download über die Schaltfläche in der Steuerleiste des Players, die die Datei aus dem ausgewählten Titel der Wiedergabeliste abruft (track.downloadUrl / downloadFormat / downloadFileSize, siehe DownloadResolver::enrichTrack()). Das ist auch der Grund, warum die Episodenkarte keinen Link anzeigt: Sie zeigt eine bestimmte Episode an, während sich der Player möglicherweise bereits auf einer anderen befindet; daher wäre ein vom Server gerenderter Link dort veraltet.

In jedem Fall wird genau eine Bedienmöglichkeit angeboten: buildPlaylistData() nur Gruppen downloadButton: true außerhalb des Layouts der Episodenliste.

Die Größe wird anhand des Speicherplatzbedarfs gemessen (ResourceStorage::getFileInfo()), nicht aus sys_file.size: Eine Datei, die ohne Neuindizierung ersetzt wurde, würde andernfalls mit der Größe ihres Vorgängers angezeigt werden. Durch die Übergabe derselben Byteanzahl an den Player bleiben beide Beschriftungen übereinstimmend, und es entfällt die HEAD Anfrage, die die Schaltfläche ansonsten senden würde. Kann der Speicher nicht antworten, greift die Zeilenbeschriftung auf das Format allein zurück und der Player misst die Datei selbst.

Innerhalb einer Zeile benötigt der Link position: relative und ein z-index oberhalb des gestreckten Overlays der Wiedergabetaste, da sonst das zeilenbreite Wiedergabeziel deren Klicks verschluckt.

Die ausführliche Beschreibung eines Mediums

long_description ist der RTE-Text des Mediums. Die Detailseite zeigt ihn vollständig an; die Karte und jede Listenzeile bieten ihn stattdessen als Ausklappfeld an, sodass eine lange Episodenliste übersichtlich bleibt. Die Schaltfläche erscheint bei Datensätzen, bei denen das Feld ausgefüllt ist – es gibt keinen Editor-Schalter dafür.

Beide Hälften werden vom Server gerendert: Das Panel wird mit dem hidden Attribut und EpisodeInit.js klappt erst hidden, aria-expanded und die Schaltflächenbeschriftung. Das Panel enthält keine id und die Schaltfläche keine aria-controls: Die „Aktuell abgespielte“-Karte ist ein Klon einer Listenzeile, daher würde eine ID hier im Dokument doppelt vorkommen, sobald ein Titel ausgewählt wird. aria-expanded Eine Schaltfläche, auf die unmittelbar ihr Panel folgt, drückt dieselbe Beziehung ohne dieses Risiko aus, weshalb das Panel auch innerhalb der mpc-episode-body und nicht über eine Referenz gesucht wird.

AttributZweck
data-mpc-episode-longdesc-toggleDie Schaltfläche zum Ein- und Ausblenden. Enthält data-mpc-episode-label-more / -less für die beiden Zustände und data-mpc-episode-title für den barrierefreien Namen
data-mpc-episode-longdescDas Panel, das über das hidden Attribut

Innerhalb einer Zeile benötigen die Schaltfläche und der Bereich ein z-index über dem „Play“- Overlay. Ohne dieses verschluckt das zeilenweite „Play“-Ziel die Klicks, und der erweiterte Text kann weder ausgewählt noch als Link angeklickt werden.

Wenn Sie die Karte überschreiben, behalten Sie diese Hooks bei – EpisodeInit.js ist darauf angewiesen:

AttributZweck
data-mpc-episode-playKennzeichnet die Wiedergabetaste. Klicks werden delegiert, sodass eine geklonte Schaltfläche ohne Neuinitialisierung funktioniert. Innerhalb einer Zeile ::after erstreckt sich über die gesamte Zeile – derselbe Trick wie bei Bootstrap .stretched-link in den Teasern, weshalb die Zeile position: relative
data-mpc-episode-indexPlaylist-Titel, den die Schaltfläche auswählt (playlistManager.play(index))
data-mpc-episode-itemZeilen-Wrapper. Erhält aria-current="true" solange sein Titel ausgewählt ist und dient als Klonquelle für die Karte
data-mpc-episode-currentAn der Wurzel: Index der Titel, den die Karte aktuell anzeigt. Wird gerendert als 0 , sodass beim ersten Rendern nichts ausgetauscht werden muss

Klassennamen folgen dem Bootstrap-Muster (mpc-episode, mpc-episode-cover, mpc-episode-body, mpc-episode-play, …) mit dem Layout als Modifikator am Stammelement (mpc-episode-layout-card, mpc-episode-layout-episodes). Das Bildmaterial befindet sich in mpc-episode-cover und alles andere in mpc-episode-main, sodass der Player an der Wiedergabetaste ausgerichtet ist und nicht am Bild. Listenzeilen verkleinern das Cover und die Wiedergabeblase, indem sie --mpc-vidply-episode-cover und --mpc-vidply-episode-play-size, weshalb eine in die Karte geklonte Zeile in voller Größe angezeigt wird.

Die Überschriftenebenen unterscheiden sich zwischen den beiden Positionen – titleLevel 3 für die Karte, 4 für Zeilen — daher übernimmt der Klon das Tag des Titels, den er ersetzt, anstatt die Zeile <h4> bis zum oberen Rand des Elements zu übernehmen.

Zwei Dinge, die Sie beachten sollten, wenn Sie das Design einer Zeile anpassen: Der Wiedergabeknopf darf keinen transform, da ein transformiertes Element zum umschließenden Block seines eigenen Overlays wird und der Klickbereich beim Hover wieder auf die Blase zurückspringen würde (stattdessen übernehmen der Hover- und die :focus-within Zustände der Zeile übernehmen stattdessen die Affordanz). Und das Overlay überdeckt den Text der Zeile, sodass es nicht möglich ist, die Kurzbeschreibung einer Zeile mit der Maus auszuwählen – derselbe Kompromiss, den auch die Teaser eingehen. Die erweiterte lange Beschreibung bildet die Ausnahme: Sie wird über das Overlay angehoben und bleibt auswählbar.

Vorteile

  • Einzige Zuständigkeit – Jedes Teilelement hat einen klaren Zweck
  • Wiederverwendbarkeit – Verfolgt Teilelemente, die von Video und Audio gemeinsam genutzt werden
  • Einfaches Überschreiben – Passen Sie nur das an, was Sie benötigen
  • Wartbarkeit – Änderungen beschränken sich auf bestimmte Dateien
  • Lesbarkeit – Die Hauptvorlage wurde von 250 auf 130 Zeilen reduziert

Keine kompatibilitätsbrechenden Änderungen

Durch die Refaktorisierung bleiben HTML-Ausgabe und Funktionalität unverändert. Bestehende Konfigurationen funktionieren ohne Änderungen.

Seite teilen