
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, SoundCloudhls.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-Initialisierungvidply/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>überPartials/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 / Vorlage | Rolle |
|---|---|
Listview/Row | Ein Regal oder eine Rasterzeile: Überschrift, Sortierung <select>, optionaler Paginierungs-Wrapper |
Listview/RowListBody | Gemeinsam genutzt <ul> für Raster oder Regal (mit oder ohne Paginierung verwendbar) |
Listview/Card | Einzelne Medienkarte (Poster, Titel, Interpret, Kategorie-Chips, Link) |
Listview/ShelfArrows | Steuerelemente „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.
| Teil | Rolle |
|---|---|
VidPly/EpisodeLayout | Layout-Wrapper, lädt episode.min.css + EpisodeInit.min.js, rendert die Karte oder die Episodenliste sowie den Player |
VidPly/EpisodeList | Die <ol> der Episodenzeilen, die entweder separat oder innerhalb des Pager-Containers gerendert werden |
VidPly/EpisodeCover | Quadratisches Titelbild einer Folge |
VidPly/EpisodeCard | Runde 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_sort | Voreingestellte Reihenfolge: sorting (Reihenfolge der Medienelemente), date_desc, date_asc, title_asc. Wird serverseitig angewendet und in die <select> |
tx_mpcvidply_episode_pagination | Aktiviert die Paginierung; diese wird erst sichtbar, sobald mehr Episoden vorhanden sind, als auf eine Seite passen |
tx_mpcvidply_episode_per_page | Episoden 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.
| Attribut | Zweck |
|---|---|
data-mpc-episode-default-sort | Für den Abschnitt: die vom Editor vorab ausgewählte Reihenfolge, die beim <select> beim Laden |
data-mpc-episode-sort | Die Sortierreihenfolge <select> |
data-mpc-episode-list | Die <ol> deren <li> Kinder sortiert und paginiert werden |
data-mpc-episode-date / data-mpc-episode-sort-title | Sortierschlüssel pro Zeile (Y-m-d, leer, wenn nicht festgelegt) |
data-mpc-episode-paginate | Pager-Container; enthält data-mpc-episode-per-page sowie die Pager-Bezeichnungen |
data-mpc-episode-pager-nav | Leer <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.
| Attribut | Zweck |
|---|---|
data-mpc-episode-longdesc-toggle | Die 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-longdesc | Das 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:
| Attribut | Zweck |
|---|---|
data-mpc-episode-play | Kennzeichnet 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-index | Playlist-Titel, den die Schaltfläche auswählt (playlistManager.play(index)) |
data-mpc-episode-item | Zeilen-Wrapper. Erhält aria-current="true" solange sein Titel ausgewählt ist und dient als Klonquelle für die Karte |
data-mpc-episode-current | An 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.