Einfache JavaScript-Tabs im WordPress-Backend

Standardmäßig wird beim Wechsel von Tabs im WordPress-Backend immer eine neue Seite aufgerufen. Mit nur wenigen Änderungen kann man eine JavaScript-Variante einbinden, wodurch der Wechsel zwischen den einzelnen Tabs wesentlich beschleunigt wird. In meinem nachfolgenden Beispiel geht das deshalb so schnell, weil sämtliche Inhalte aller Tabs direkt beim ersten Seitenaufruf geladen und lediglich per Ein- und Ausblenden entsprechender Inhalts-Container dargestellt werden.

Für ein Plugin, das für jede Unterseite einen eigenen Tab anzeigt, wollte ich einen Wechsel der Tabs per JavaScript bauen, da es sonst wesentlich länger dauern würde, sich durch alle Tabs zu klicken und deren Inhalt zu überprüfen. Dabei war es mir wichtig, dass die Tabs dem Standard-WordPress-Design entsprechend und sie somit erst einmal gar nicht von diesem zu unterscheiden sind.

Das HTML-Markup

Da mein JavaScript bestimmte CSS-Klassen benötigt, müssen diese ins HTML-Markup der Seite (bei mir eine Unterseite innerhalb von /wp-admin/tools.php). Daher fange ich mit diesem an. Es  ist in zwei Bereiche unterteilt, einmal die Tabs an sich und einmal deren Inhalt.

Die Tabs

Die Tabs sind folgendermaßen aufgebaut und entsprechen damit dem Standard-WordPress-Tab-Design:

<h2 class="nav-tab-wrapper">
	<a href="tools.php?page=my-plugin&tab=tab-1" class="nav-tab nav-tab-active" data-slug="<?php \esc_attr_e( 'tab-1', 'my-plugin' ); ?>"><?php \esc_html_e( 'Tab 1', 'my-plugin' ); ?></a>
	<a href="tools.php?page=my-plugin&tab=tab-2" class="nav-tab" data-slug="<?php \esc_attr_e( 'tab-2', 'my-plugin' ); ?>"><?php \esc_html_e( 'Tab 2', 'my-plugin' ); ?></a>
	<a href="tools.php?page=my-plugin&tab=tab-3" class="nav-tab" data-slug="<?php \esc_attr_e( 'tab-3', 'my-plugin' ); ?>"><?php \esc_html_e( 'Tab 3', 'my-plugin' ); ?></a>
</h2>

Als Ergebnis werden hier dann drei Tabs mit den Titeln „Tab 1“, „Tab 2“ und „Tab 3“ angezeigt. In meinem Plugin selbst werden diese natürlich automatisiert innerhalb einer Schleife generiert, daher sieht mein eigentlicher Code etwas anders aus und beispielsweise der Inhalt von data-slug ist eigentlich kein übersetzbarer Text, sondern der Slug der eigentlichen Unterseite, die der Tab bei mir repräsentiert.

Der erste Tab wird automatisch über die Klasse nav-tab-active als aktiv dargestellt.

Der Inhalt

Das HTML des Inhalts ist eine Eigenkreation, allerdings habe ich versucht, so nah wie möglich an der Benennung von WordPress zu bleiben, was die CSS-Klassen und -IDs angeht:

<div class="nav-tab-content nav-tab-content-active" id="nav-tab-content-<?php \esc_attr_e( 'tab-1', 'my-plugin' ); ?>">
	<p><?php \esc_html_e( 'Tab 1 Content', 'my-plugin' ); ?></p>
</div>

<div class="nav-tab-content" id="nav-tab-content-<?php \esc_attr_e( 'tab-2', 'my-plugin' ); ?>">
	<p><?php \esc_html_e( 'Tab 2 Content', 'my-plugin' ); ?></p>
</div>

<div class="nav-tab-content" id="nav-tab-content-<?php \esc_attr_e( 'tab-3', 'my-plugin' ); ?>">
	<p><?php \esc_html_e( 'Tab 3 Content', 'my-plugin' ); ?></p>
</div>

Der aktive Tab-Inhalt wird über die Klasse nav-tab-content-active gesteuert.

Das CSS

Da das JavaScript später beim Klick auf einen Tab lediglich CSS-Klassen hinzufügt oder entfernt, kümmert sich das CSS darum, dass nur die Elemente mit der jeweils aktiven Klasse (nav-tab-content-active) auch angezeigt werden. Dazu nutze ich folgenden kurzen CSS-Code:

.nav-tab-content {
	display: none;
 	margin-top: .5em;
}

.nav-tab-content-active {
	display: block;
}

Jeder Inhalt bekommt einen kleinen Abstand nach oben (Zeile 3) und wird erst einmal ausblendet (Zeile 2). Nur der aktive Inhalt wird dann anzeigt (Zeile 7).

Das JavaScript

Das Herzstück von JavaScript-Tabs – das JavaScript.

document.addEventListener( 'DOMContentLoaded', function() {
	var tabs = document.querySelectorAll( '.nav-tab' );
	var tab_contents = document.querySelectorAll( '.nav-tab-content' );
	
	for ( var _i = 0; _i < tabs.length; _i++ ) {
		tabs[ _i ].addEventListener( 'click', function( event ) {
			event.preventDefault();
			
			var current_target = event.currentTarget;
			var slug = current_target.getAttribute( 'data-slug' );
			
			// remove active class from any other nav tab
			for ( var _n = 0; _n < tabs.length; _n++ ) {
				tabs[ _n ].classList.remove( 'nav-tab-active' );
			}
			
			// add active class to the nav tab
			current_target.classList.add( 'nav-tab-active' );
			
			// remove active class from any other nav tab content
			for ( var _a = 0; _a < tab_contents.length; _a++ ) {
				tab_contents[ _a ].classList.remove( 'nav-tab-content-active' );
			}
			
			// add active class to the content of the tab
			document.getElementById( 'nav-tab-content-' + slug ).classList.add( 'nav-tab-content-active' );
			// set url in browser
			history.pushState( null, null, current_target.href );
		} );
	}
} );

Zuerst einmal werden alle Tabs und deren Inhalte im DOM benötigt, da später durch alle iteriert werden muss (Zeile 2–3).

Dann erhält jeder Tab einen eigenen Klick-Eventlistener (Zeile 6), bei dessen Ausführung zuerst die standardmäßige Aktion (in diesem Fall der Aufruf des hinter href hinterlegten Links) deaktiviert (Zeile 7) und sein Slug-Attribut (data-slug) gespeichert wird (Zeile 10).

Daraufhin wird die CSS-Klasse zur Aktiv-Markierung von allen Tabs entfernt (Zeile 13–15) und dann nur diesem Tab, auf den geklickt wurde, wieder zugewiesen (Zeile 18).

Dasselbe wird für alle Inhalte gemacht (Zeile 21–23). Die Zuweisung der Klasse zur aktiven Anzeige wird beim Inhalt über eine ID gesteuert (Zeile 26), die sich aus der Zeichenkette nav-tab-content-  und dem Slug des Tabs zusammensetzt. In unserem Beispiel von oben wären mögliche IDs dann #nav-tab-content-tab-1, #nav-tab-content-tab-2 und #nav-tab-content-tab-3.

Als letztes wird noch die URL aktualisiert, damit sie beim Kopieren und Einfügen in einen neuen Browser-Tab direkt den richtigen Tab anzeigt (Zeile 28).

Das PHP

Die die letzte Funktion – die Anzeige des korrekten Tabs bei Übergabe der jeweiligen URL – muss noch ein bisschen PHP in das HTML eingebaut werden. So wird zuerst einmal der übergebene Parameter tab benötigt:

<?php $active_tab = $_GET['tab'] ?? ''; ?>

Dann muss die CSS-Klasse nav-tab-active abhängig vom Inhalt dieses Parameters dem richtigen Tab gegeben werden:

<h2 class="nav-tab-wrapper">
	<a href="tools.php?page=my-plugin&tab=tab-1" class="nav-tab<?php echo ( $active_tab === 'tab-1' || empty( $active_tab ) ? ' nav-tab-active' : '' ); ?>" data-slug="<?php \esc_attr_e( 'tab-1', 'my-plugin' ); ?>"><?php \esc_html_e( 'Tab 1', 'my-plugin' ); ?></a>
	<a href="tools.php?page=my-plugin&tab=tab-2" class="nav-tab<?php echo ( $active_tab === 'tab-2' ? ' nav-tab-active' : '' ); ?>" data-slug="<?php \esc_attr_e( 'tab-2', 'my-plugin' ); ?>"><?php \esc_html_e( 'Tab 2', 'my-plugin' ); ?></a>
	<a href="tools.php?page=my-plugin&tab=tab-3" class="nav-tab<?php echo ( $active_tab === 'tab-3' ? ' nav-tab-active' : '' ); ?>" data-slug="<?php \esc_attr_e( 'tab-3', 'my-plugin' ); ?>"><?php \esc_html_e( 'Tab 3', 'my-plugin' ); ?></a>
</h2>

Beim ersten Tab wird zusätzlich geprüft, ob überhaupt ein Parameter tab übergeben wird. Falls dies nicht der Fall ist, wird automatisch der erste Tab als aktiv markiert.

Ähnlich sieht es auch bei den Inhalten aus. Diese benötigen eine identische Abfrage. Lediglich die Klasse, die hinzugefügt wird, lautet nav-tab-content-active.

<div class="nav-tab-content<?php echo ( $active_tab === 'tab-1' || empty( $active_tab ) ? ' nav-tab-content-active' : '' ); ?>" id="nav-tab-content-<?php \esc_attr_e( 'tab-1', 'my-plugin' ); ?>">
	<p><?php \esc_html_e( 'Tab 1 Content', 'my-plugin' ); ?></p>
</div>

<div class="nav-tab-content<?php echo ( $active_tab === 'tab-2' ) ? ' nav-tab-content-active' : '' ); ?>" id="nav-tab-content-<?php \esc_attr_e( 'tab-2', 'my-plugin' ); ?>">
	<p><?php \esc_html_e( 'Tab 2 Content', 'my-plugin' ); ?></p>
</div>

<div class="nav-tab-content<?php echo ( $active_tab === 'tab-3' ) ? ' nav-tab-content-active' : '' ); ?>" id="nav-tab-content-<?php \esc_attr_e( 'tab-3', 'my-plugin' ); ?>">
	<p><?php \esc_html_e( 'Tab 3 Content', 'my-plugin' ); ?></p>
</div>

Fazit

Bereits mit wenigen Schritten hat man eine einfache, aber gleichzeitig schnelle JavaScript-Lösung für Tabs im WordPress-Backend. Diese sollte allerdings so nur verwendet werden, wenn sich die Menge der Inhalte in Grenzen hält. Falls nicht, empfehle ich, die Inhalte erst über JavaScript nachzuladen.

Generell dürfte diese Variante aber in vielen Fällen ausreichen und viel Zeit bei der Navigation durch die einzelnen Tabs sparen. ⚡

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.