Tab Swap: Technische Details
Technische Details zu Tab Swap: Signal object.view, ausgegebenes Inline-Script, die vier benötigten DOM-Elemente, PJAX-Neuausführung, Versionsprüfung, CSP-Nonce und Dateistruktur.
Tab Swap: Technische Details
Ablauf
graph TD
A["osTicket startet, Plugin bootstrap()"] --> B["checkVersion(): installed_version speichern"]
B --> C{"Enable Tab Swap an?"}
C -->|"Nein"| D["Kein Signal, kein Script"]
C -->|"Ja"| E["Signal object.view verbunden"]
E --> F{"Objekt ist ein Ticket?"}
F -->|"Nein"| G["Nichts passiert"]
F -->|"Ja"| H["Inline-Script wird ausgegeben"]
H --> I["Browser: Tabs tauschen"]
Plugin-Metadaten
| Eigenschaft | Wert |
|---|---|
| Plugin-ID | net.markus-michalski:tab-swap |
| Name | Tab Swap |
| Plugin-Klasse | TabSwapPlugin in class.TabSwapPlugin.php |
| Konfigurationsklasse | TabSwapConfig in config.php |
| Instanzen | Singleton: es gibt genau eine Instanz, enable() legt sie bei Bedarf an |
| PHP | >=7.4 (composer.json) |
Server-Seite
bootstrap()ruftcheckVersion()auf. Istinstalled_versionleer oder niedriger als die Version ausplugin.php, schreibtperformUpdate()die neue Version in die Konfiguration. Eine Meldung ins Error-Log gibt es nur, wenn die KonstanteDEBUGgesetzt und wahr ist.- Ist die Option Enable Tab Swap an, verbindet das Plugin
onObjectView()mit dem Signalobject.view. onObjectView()tut nur etwas, wenn das übergebene Objekt einTicketist (zum Beispiel keine Aufgabe). Dann wird das Script ausgegeben.- Das Plugin prüft keine Berechtigungen. Es gibt das Script für jede Ticket-Ansicht aus, in der das Signal auftritt. Ob der Tausch greift, entscheiden die Elemente im Browser (siehe unten).
- Es gibt keine Datenbanktabellen, keine Routen, keine Dateikopien und keine Änderungen an osTicket-Dateien.
Ausgegebenes Script
Das Plugin gibt ein Element der Form <script data-plugin="tab-swap" data-version="..." nonce="..."> aus:
data-versionenthältinstalled_version, aber nur, wenn der Wert dem MusterZahl.ZahloderZahl.Zahl.Zahlentspricht. Sonst wird1.0.0eingesetzt. Der Wert wird zusätzlich HTML-escaped.noncewird nur gesetzt, wenn die KonstanteCSP_NONCEdefiniert ist. Der Wert wird HTML-escaped.- Das Script ist fest im Plugin-Code hinterlegt und enthält keine Nutzereingaben.
Browser-Seite
Das Script wirkt erst, wenn alle Voraussetzungen erfüllt sind:
- Die Elemente
#post-reply-tab,#post-note-tab,#replyund#noteexistieren. - Beide Tabs sind sichtbar (
offsetParentist nichtnull).
Dann passiert Folgendes:
- Das
li-Element des Notiz-Tabs wird in#response-tabsvor daslides Antworten-Tabs verschoben. - Beim Antworten-Tab wird die Klasse
activeentfernt undaria-selected="false"gesetzt. Beim Notiz-Tab wirdactiveergänzt undaria-selected="true"gesetzt. #replybekommtdisplay: none,#notebekommtdisplay: block.
Der Tausch läuft pro Seitenaufbau einmal. Damit er auch bei später aufgebauten Seiten greift, nutzt das Script:
- einen
MutationObserver, der auf#post-reply-tabwartet und nach erfolgreichem Tausch endet, - einen direkten Aufruf und
DOMContentLoaded, pjax:successund, falls jQuery vorhanden ist, das Ereignisredraw.staff. In beiden Fällen wird der Zustand zurückgesetzt und der Tausch erneut ausgeführt.
jQuery ist nicht zwingend nötig. Fehlt es, entfällt nur die Reaktion auf redraw.staff.
Dateistruktur
tab-swap/
├── plugin.php # Plugin-Metadaten
├── class.TabSwapPlugin.php # Plugin-Klasse, Signal-Handler, Inline-Script
└── config.php # TabSwapConfig mit den zwei Feldern
Im Repository liegen zusätzlich composer.json, PHPUnit-Tests, CI-Workflow und Dokumentation. Die CI prüft Syntax und führt die Tests mit PHP 7.4 bis 8.3 aus.