Technische Dokumentation – WP Presentation Builder Viewer
Übersicht
Diese Dokumentation beschreibt die wichtigsten JavaScript-Funktionen des WP Presentation Builder Viewers, insbesondere die Next-Action-Funktionalität.
Hauptklasse: WPPresentationPlayer
Constructor
Funktion: constructor(container, options)
Aufgabe: Initialisiert den Presentation Player mit allen benötigten Einstellungen
Parameter:
container(DOM Element) – Container-Element für die Präsentationoptions(Object) – Konfigurationsobjektoptions.slides(Array) – Array von Slide-Objektenoptions.settings(Object) – Präsentations-Einstellungenoptions.presentation_id(Number) – WordPress Post ID der Präsentation
Rückgabewert: Keine (Constructor)
Wichtige Properties:
this.slides– Array aller Slidesthis.currentSlide– Index des aktuellen Slides (0-basiert)this.isFullscreen– Boolean für Fullscreen-Statusthis.$container– jQuery-Objekt des Containers
Message-Handling
Window Message Listener
Funktion: Event Listener für window.addEventListener('message', ...)
Aufgabe: Empfängt Messages von externen Slides (iframe) und verarbeitet diese
Message Format:
{
source: 'wp_external_slide', // Identifiziert WP-Slides
type: 'show_subtitle', // Message-Typ
data: { // Payload
text: 'Untertitel Text',
next_action: 'fill_input',
action_selector: 'person',
input_value: 'Max Mustermann',
// weitere Parameter...
}
}
Verarbeitete Message-Typen:
next_slide– Nächster Slideprev_slide– Vorheriger Slideexit_presentation– Präsentation beendensubtitle_update– Untertitel aktualisierenshow_subtitle– Untertitel anzeigen + Next-Action ausführenexternal_slide_ready– Externer Slide geladen
Ablauf:
- Message empfangen
- Prüfen:
event.data.source === 'wp_external_slide' - Switch-Case basierend auf
event.data.type - Bei
show_subtitle:executeNextAction()aufrufen
Next-Action System
executeNextAction()
Funktion: executeNextAction(actionData)
Aufgabe: Dispatcher-Funktion die basierend auf next_action die entsprechende Action ausführt
Parameter:
actionData(Object) – Daten aus subtitle_rulesnext_action(String) – Action-Typ: ’next‘, ’slide‘, ‚click_link‘, ‚click_button‘, ‚fill_input‘, ’select_option‘, ’scroll‘, ‚mouse_trail‘action_selector(String) – CSS-Selector oder Element-Nameinput_value(String) – Wert für fill_inputselect_value(String) – Wert für select_optionscroll_pixels(Number) – Y-Position für scrollgoto_slide(Number) – Slide-Nummer für ’slide‘ actiontrail_from(String) – Start-Koordinaten für mouse_trailtrail_to(String) – End-Koordinaten für mouse_trail
Rückgabewert: Keine (void)
Verzögerung: 500ms setTimeout vor Ausführung
Action-Mapping:
'next'→nextSlide()'slide'→goToSlide(goto_slide - 1)'click_link'/'click_button'→executeClickAction(selector)'fill_input'→executeFillAction(selector, value)'select_option'→executeSelectAction(selector, value)'scroll'→executeScrollAction(pixels)'mouse_trail'→executeMouseTrailAction(from, to)
Beispiel:
executeNextAction({
next_action: 'fill_input',
action_selector: 'person',
input_value: 'Max Mustermann'
});
executeFillAction()
Funktion: executeFillAction(selector, value, retryCount = 0)
Aufgabe: Füllt ein Input- oder Textarea-Feld im iframe mit einem Wert aus
Parameter:
selector(String) – Element-Selector (name, id, CSS-Selector)value(String) – Einzutragender WertretryCount(Number, optional) – Anzahl bisheriger Versuche (für Retry-Logik)
Rückgabewert: Keine (void)
Ablauf:
- Sucht iframe:
.wp-slide-frame - Holt iframe Document:
iframe.contentDocument - Sucht Element mit 3 Strategien:
[name="${selector}"]– Nach name-AttributquerySelector(selector)– Als CSS-Selector#${selector}– Als ID mit #-Prefix
- Prüft ob Element INPUT oder TEXTAREA ist
- Fokussiert Element:
element.focus() - Setzt Wert:
element.value = value - Triggert Events:
new Event('input', { bubbles: true })new Event('change', { bubbles: true })
Retry-Mechanismus:
- Max. 3 Versuche bei nicht gefundenem Element
- Verzögerungen: 300ms, 600ms, 900ms
- Nach 3 Fehlversuchen: Listet alle verfügbaren Inputs auf
Beispiel:
executeFillAction('person', 'Max Mustermann');
// Sucht: input[name="person"] oder #person
// Trägt ein: "Max Mustermann"
executeClickAction()
Funktion: executeClickAction(selector)
Aufgabe: Klickt ein Element (Link, Button) im iframe
Parameter:
selector(String) – CSS-Selector oder Text-Inhalt
Rückgabewert: Keine (void)
Suchstrategien:
- CSS-Selector:
querySelector(selector) - Text-Content: Durchsucht alle
a, buttonnach Text
Beispiel:
executeClickAction('.submit-btn');
executeClickAction('Weiter'); // Klickt Button mit Text "Weiter"
executeSelectAction()
Funktion: executeSelectAction(selector, value)
Aufgabe: Wählt eine Option in einem Select-Dropdown
Parameter:
selector(String) – Select-Element (name, id, CSS-Selector)value(String) – Wert oder Text der zu wählenden Option
Rückgabewert: Keine (void)
Suchstrategien für Element:
select[name="${selector}"]select#${selector}- CSS-Selector:
querySelector(selector)
Suchstrategien für Option:
- Nach value:
element.value = value - Nach Text: Durchsucht
<option>-Elemente
Triggert: change Event
Beispiel:
executeSelectAction('country', 'AT'); // Wählt value="AT"
executeSelectAction('country', 'Österreich'); // Wählt nach Text
executeScrollAction()
Funktion: executeScrollAction(pixels)
Aufgabe: Scrollt das iframe zu einer bestimmten Y-Position
Parameter:
pixels(Number) – Y-Position in Pixeln
Rückgabewert: Keine (void)
Scroll-Verhalten: Smooth scrolling aktiviert
Beispiel:
executeScrollAction(500); // Scrollt zu Y=500px
executeMouseTrailAction()
Funktion: executeMouseTrailAction(from, to)
Aufgabe: Zeigt animierte Mausspur von Start- zu End-Position
Parameter:
from(String) – Start-Koordinaten „X,Y“ oder CSS-Selectorto(String) – End-Koordinaten „X,Y“ oder CSS-Selector
Rückgabewert: Keine (void)
Koordinaten-Formate:
- Pixel:
"100,200"= X:100px, Y:200px - Selector:
".my-button"= Zentrum des Elements
Animation:
- Dauer: 2 Sekunden
- Easing: ease-out
- Cursor-Darstellung: Roter Kreis (20px)
Beispiel:
executeMouseTrailAction('100,50', '300,400'); // Von Pixel zu Pixel
executeMouseTrailAction('.start-btn', '.end-btn'); // Von Element zu Element
parseCoordinates()
Funktion: parseCoordinates(input, iframeDoc)
Aufgabe: Konvertiert String (Koordinaten oder Selector) zu X/Y-Koordinaten
Parameter:
input(String) – „X,Y“ oder CSS-Selector oder TextiframeDoc(Document) – iframe Document-Objekt
Rückgabewert:
{x: Number, y: Number}– Koordinatennull– Bei Fehler
Strategien:
- Regex-Match für „100,200“ Format
- CSS-Selector:
querySelector(input) - Text-Suche in typischen Elementen
- Berechnet Zentrum des Elements via
getBoundingClientRect()
Beispiel:
parseCoordinates('100,200', iframeDoc); // → {x: 100, y: 200}
parseCoordinates('.my-button', iframeDoc); // → {x: 250, y: 150} (Zentrum)
Slide-Loading
loadSlide()
Funktion: loadSlide(index)
Aufgabe: Lädt einen Slide und registriert alle Event-Handler für subtitle_rules
Parameter:
index(Number) – Slide-Index (0-basiert)
Rückgabewert: Keine (void)
Ablauf:
- Validierung:
index >= 0 && index < slides.length - Stop AutoPlay Timer
- Fade-Out alter Slide (300ms)
- Warte 350ms
- Parse subtitle_rules (Array oder Object → Array)
- Bestimme Slide-Typ:
content,post,admin,external - Erstelle iframe oder Direct-Content
- Für externe Slides: Verwende Proxy mit subtitle_rules als Parameter
- Registriere Event-Handler
- Starte zeitbasierte subtitle_rules
- Update Counter & Progress
Slide-Typen:
content– Direkter HTML-Contentpost– WordPress Post/CPTadmin– WordPress Admin-Bereichexternal– Externe URL (mit Proxy)
Subtitle Rules Format:
[
{
type: 'input', // Event-Typ
action: 'person', // Feld-Name oder Element-ID
text: 'Name eingegeben',
next_action: 'fill_input',
action_selector: 'email',
input_value: 'max@example.com'
}
]
registerEventHandlers()
Funktion: registerEventHandlers($container, subtitleRules, $subtitleNav)
Aufgabe: Registriert alle Event-Handler für subtitle_rules im Slide-Container
Parameter:
$container(jQuery Object) – Container (Slide oder iframe body)subtitleRules(Array) – Array von subtitle_rule Objekten$subtitleNav(jQuery Object) – Subtitle-Element zum Updaten
Rückgabewert: Keine (void)
Registrierte Events:
1. Click auf [data-subtitle-action]
$container.find('[data-subtitle-action]').on('click', ...)
Matcht Rules mit type: 'click' und action === data-subtitle-action
2. Click auf Links (a[href])
$container.find('a[href]:not([data-subtitle-action])').on('click', ...)
Action-Key-Priorität: data-id > href > name > id > linkText
3. Input Events
$container.find('input[name], textarea[name], select[name]').on('input', ...)
Triggert bei Tippen
4. Change Events
$container.find('input[name], textarea[name], select[name]').on('change', ...)
Triggert bei Wert-Änderung + Feld verlassen
5. Focus Events
$container.find('input[name], textarea[name], select[name]').on('focus', ...)
Triggert wenn Feld aktiv wird
6. Blur Events
$container.find('input[name], textarea[name], select[name]').on('blur', ...)
Triggert wenn Feld verlassen wird
7. Button Clicks
$container.find('button, input[type=submit], input[type=button]').on('click', ...)
Action-Key: name oder Button-Text
processInputRule()
Funktion: processInputRule(eventType, $input, subtitleRules, $subtitleNav)
Aufgabe: Verarbeitet Input-Event und setzt Untertitel mit Platzhalter-Ersetzung
Parameter:
eventType(String) – Event-Typ: ‚input‘, ‚change‘, ‚focus‘, ‚blur‘$input(jQuery Object) – Input-ElementsubtitleRules(Array) – Array von Rules$subtitleNav(jQuery Object) – Subtitle-Element
Rückgabewert: Keine (void)
Platzhalter:
{value}– Aktueller Wert{fieldName}– name-Attribut{fieldType}– Feld-Typ (input type oder ’select‘){fieldId}– id-Attribut{placeholder}– placeholder-Text{selectedValue}– Wert der gewählten Option (bei select){selectedText}– Text der gewählten Option (bei select){eventType}– Event-Typ
Beispiel:
// Rule:
{
type: 'input',
action: 'person',
text: 'Name: {value}',
next_action: 'next'
}
// User tippt "Max" in input[name="person"]
// → Subtitle: "Name: Max"
Navigation
nextSlide()
Funktion: nextSlide()
Aufgabe: Geht zum nächsten Slide
Parameter: Keine
Rückgabewert: Keine (void)
Verhalten:
- Bei letztem Slide + Loop aktiviert: Springt zu Slide 0
- Bei letztem Slide ohne Loop: Keine Aktion
previousSlide()
Funktion: previousSlide()
Aufgabe: Geht zum vorherigen Slide
Parameter: Keine
Rückgabewert: Keine (void)
Verhalten:
- Bei erstem Slide + Loop aktiviert: Springt zu letztem Slide
- Bei erstem Slide ohne Loop: Keine Aktion
goToSlide()
Funktion: goToSlide(index)
Aufgabe: Springt zu einem bestimmten Slide
Parameter:
index(Number) – Slide-Index (0-basiert)
Rückgabewert: Keine (void)
Zusatz: Synchronized mit Presenter-Ansicht via BroadcastChannel
Datenfluss: subtitle_rules → next_action
1. PHP Backend (wp-presentation-builder.php)
// Slide-Meta speichern
subtitle_rules[] = [
'type' => 'input',
'action' => 'person',
'text' => 'Name eingegeben',
'next_action' => 'fill_input',
'action_selector' => 'email',
'input_value' => 'test@example.com'
]
2. PHP → JavaScript (generate_interactive_script)
var subtitleRules = <?php echo json_encode($subtitle_rules); ?>;
// Bei Input-Event:
window.parent.postMessage({
source: 'wp_external_slide',
type: 'show_subtitle',
data: {
text: rule.text,
next_action: rule.next_action,
action_selector: rule.action_selector,
input_value: rule.input_value
}
}, '*');
3. Viewer empfängt Message
window.addEventListener('message', function(event) {
if (event.data.source === 'wp_external_slide' &&
event.data.type === 'show_subtitle') {
// Setze Subtitle
$subtitle.text(event.data.data.text);
// Führe next_action aus
executeNextAction(event.data.data);
}
});
4. Next-Action Ausführung
executeNextAction(actionData) {
setTimeout(() => {
switch(actionData.next_action) {
case 'fill_input':
executeFillAction(
actionData.action_selector, // 'email'
actionData.input_value // 'test@example.com'
);
break;
}
}, 500);
}
5. Fill-Action im iframe
executeFillAction('email', 'test@example.com') {
// Finde Element
const element = iframeDoc.querySelector('[name="email"]');
// Setze Wert
element.value = 'test@example.com';
// Trigger Events
element.dispatchEvent(new Event('input'));
element.dispatchEvent(new Event('change'));
}
Debugging
Console Logs Hierarchie
Level 1: Message Empfang
🔔 Message Event empfangen: {hasData, source, type, fullData}
Level 2: Message Verarbeitung
📨 Message von externem Slide empfangen: {complete event.data}
📨 Message Type: "show_subtitle"
Level 3: Case Execution
🎯 show_subtitle Case erreicht!
📦 subtitleData: {complete data object}
Level 4: Element Suche
🔍 Suche .wp-subtitle Element: {found, count, element}
Level 5: Action Dispatch
✅ Subtitle von externem Slide gesetzt: "Text"
🎬 next_action: "fill_input"
🚀 Führe next_action aus: "fill_input"
Level 6: Action Execution
✍️ Fill Input: {selector: "person", value: "Max"}
🔍 executeFillAction aufgerufen (Versuch 1): {selector, value}
📺 iframe gefunden: true
📄 iframeDoc: vorhanden
📄 iframeDoc.readyState: complete
Level 7: Element Finding
🔎 Element per name gesucht: [name="person"] gefunden ✓
Level 8: Value Setting
✅ Element gefunden! Details: {tagName, type, name, id, currentValue, disabled, readOnly}
📝 Wert gesetzt: "Max"
✅ Events getriggert, finaler Wert: "Max"
Häufige Probleme
Problem: next_action wird nicht ausgeführt
Mögliche Ursachen:
- Message kommt nicht an → Prüfe: 🔔 Message Event
- Falscher source → Prüfe: event.data.source === ‚wp_external_slide‘
- Falscher type → Prüfe: event.data.type === ’show_subtitle‘
- Element nicht gefunden → Prüfe: 🔍 Suche .wp-subtitle Element
- next_action leer → Prüfe: 🎬 next_action
Problem: Input wird nicht befüllt
Mögliche Ursachen:
- Falscher selector → Prüfe HTML:
<input name="person"> - Element nicht im iframe → Prüfe: 📺 iframe gefunden
- Timing-Problem → Retry-Mechanismus sollte helfen
- Falsches Tag → Element muss INPUT oder TEXTAREA sein
Problem: Daten aus PHP kommen nicht an
Prüfpunkte:
- PHP:
echo json_encode($subtitle_rules)in generate_interactive_script - Browser-Quellcode: Suche „subtitleRules“ im Script
- Console:
subtitleRulesVariable ausgeben - Message: Prüfe ob alle Felder übertragen werden
Best Practices
Selector Naming
// Gut - Name-Attribut
<input name="person">
action_selector: "person"
// Gut - ID mit #
<input id="email">
action_selector: "#email"
// Gut - CSS Class
<input class="user-name">
action_selector: ".user-name"
// Vermeiden - Komplexe Selectors
action_selector: "div > form input:nth-child(3)"
Timing
- 500ms Delay bei executeNextAction → Zeit für Subtitle-Anzeige
- 300/600/900ms Retries bei executeFillAction → Zeit für DOM-Aufbau
- 2000ms Mouse Trail Animation → Sichtbar aber nicht zu langsam
Error Handling
- Immer console.log für erfolgreiche Actions
- console.warn für nicht gefundene Elemente
- console.error für schwere Fehler (kein iframe)
- Retry-Logik für Timing-Probleme
- Fallback-Suche mit mehreren Strategien
Versionierung
Aktuelle Version: 0.13.1
Changelog Next-Action Feature:
- v0.13.0: Basis next_action Implementierung (next, slide)
- v0.13.1: Erweiterte Actions (fill_input, click, select, scroll, mouse_trail)
- v0.13.1: Retry-Mechanismus für executeFillAction
- v0.13.1: Umfassendes Debug-Logging