Für die meisten gängigen Aktionen der Textverarbeitung stellt der TinyMCE-Editor in WordPress Buttons bereit. Es gibt aber Themes, die beispielsweise die Hervorhebung eines Textabschnittes durch festgelegtes HTML-Markup erlauben. Dieses Markup kann der Nutzer dann etwa über Shortcodes (keine gute Idee, da die Auflösung der Shortcodes nach einem Theme-Wechsel nicht mehr funktioniert) oder die Textansicht des Editors einfügen – eine schönere Lösung ist aber ein entsprechender Button im Editor.

Seit WordPress 4.8 gibt es eine JavaScript-API, um den TinyMCE-Editor zu verändern oder auch neue Instanzen nach Laden der Seite zu erstellen. Damit ist es relativ einfach, zusätzliche Buttons in den Editor einzufügen.

Wie das Ergebnis (ungefähr) aussehen soll

Ihr solltet natürlich darauf achten, dass die Editor-Toolbar nicht mit euren Buttons zugemüllt wird, weshalb wir ein Dropdown erstellen werden, das unseren Button beherbergt. Das folgende GIF zeigt ein Beispiel von so einem Dropdown – wir werden hier den Button Side note umsetzen, um einen oder mehrere Absätze als Seitennotiz anzeigen zu können.

Umsetzung des Ergebnisses

Dieser Artikel wird sich nicht um das Styling der Seitennotiz kümmern. Er behandelt lediglich die beiden folgenden Schritte:

  1. Hinzufügen des Buttons in die Editor-Toolbar.
  2. Erstellen des formatter-Eintrags, durch den das Markup eingefügt wird.

Doch zunächst der Rahmen für den gesamten folgenden Code. Dank der neuen API gibt es das jQuery-Event tinymce-editor-setup, auf das wir lauschen werden um beim Abfeuern des Events – nach Beginn der Initialisierung einer TinyMCE-Instanz, aber bevor das User-Interface erstellt wird – unseren Code auszuführen. Über das Event haben wir Zugriff auf das Editor-Objekt.

Anfang und Ende unseres fertigen Codes sehen so aus:

/**
* Listen to setup of a TinyMCE instance.
*/
jQuery(document).on('tinymce-editor-setup', function (event, editor) {

	/**
	* All following code comes here.
	*/
	
});Code-Sprache: JavaScript (javascript)

Alle weiteren Code-Stücke werden zwischen den geschweiften Klammern eingefügt.

Einfügen des Buttons in die Editor-Toolbar

Der komplette Code zum Einfügen des Buttons in die Toolbar sieht wie folgt aus:

/**
* Add the id of the soon-to-create button to the
* toolbar1.
*
* @type {string}
*/
editor.settings.toolbar1 += ',schlicht-formats';

/**
* Create the button.
*/
editor.addButton('schlicht-formats', {

	/**
	* It is a menubutton.
	*/
	type: 'menubutton',
	text: '»Schlicht« Formats',
	icon: false,

	/**
	* Add the menu item.
	*/
	menu: [
	{
		text: 'Side note',
		onclick: function () {
			/**
			* Toggle the custom side note format.
			*/
			editor.formatter.toggle('schlicht_side_note_format');
		}
	}
	]
});Code-Sprache: JavaScript (javascript)

Zuerst fügen wir die ID des Buttons zu dem String der Schaltflächen von der primären Toolbar des Editors ein (toolbar1) – wenn ihr den Button in die untere Toolbar einbetten möchtet, nutzt toolbar2.

Danach wird über editor.addButton der eigentliche Button erstellt. Dabei übergeben wir als ersten Parameter den zuvor verwendeten eindeutigen Bezeichner und als zweiten ein Objekt mit den Daten zu der Schaltfläche. Als type legen wir menubutton fest, da wir noch Unterpunkte erzeugen wollen. text beinhaltet die sichtbare Beschriftung (für die Übersetzbarkeit von JavaScript-String kann die Funktion wp_localize_script() verwendet werden) und ein Icon haben beziehungsweise brauchen wir nicht.

Im Bereich menu wird es nun interessant: wir erstellen den Unterpunkt Side note und definieren eine Aktion, die bei einem Klick auf den Button ausgeführt werden soll. Über editor.formatter.toggle wird der als Parameter angegebene Formatter-Eintrag an- und ausgeschaltet – im Fall unserer Side note soll dadurch das Hinzufügen beziehungsweise Entfernen eines div-Elements mit der Klasse side-note ausgelöst werden.

Wenn ihr hier weitere Menüpunkt erstellen wollt, geht ihr einfach so vor:

menu: [
{
	text: 'Side note',
	onclick: function () {

		/**
		* Toggle the custom side note format.
		*/
		editor.formatter.toggle('schlicht_side_note_format');
	}
},
{
	text: 'Another button',
	onclick: function () {
		/**
		* Do things.
		*/
	}
}
]Code-Sprache: JavaScript (javascript)

Erstellen des Formatters

Ein aside-Element wäre semantisch für eine Randbemerkung natürlich schöner. Der TinyMCE hat allerdings seine Probleme mit p-Elementen innerhalb von aside, weshalb wir ein div als Wrapper-Element nutzen.

Die Registrierung des Formatters erfolgt mit folgendem Snippet:

/**
* Wait until the editor is initialized before
* registering style.
*
* Original hint from http://archive.tinymce.com/forum/viewtopic.php?pid=92762#p92762
* onInit is deprecated, so https://www.tinymce.com/docs/advanced/migration-guide-from-3.x/#eventhandling
*/
editor.on('init', function () {
	/**
	* Register the new format for the side note.
	*/
	editor.formatter.register('schlicht_side_note_format', {
		/**
		* It is the block element div.
		*/
		block: 'div',

		/**
		* The div element gets the class side-note.
		*/
		classes: 'side-note',

		/**
		* The div is the wrapper for other block elements
		* and does not replace them.
		*/
		wrapper: true
	});
});Code-Sprache: JavaScript (javascript)

Wir packen den Code in eine Funktion, die beim init-Event des Editors ausgeführt wird, da andernfalls editor.formatter noch nicht verfügbar ist. Über editor.formatter.register kann dann ein neuer Eintrag für den Formatter erstellt werden.

Über block legen wir das HTML-Element des Formats und über classes die side-note-Klasse für das div fest. Mit der Angabe von true für wrapper erreichen wir, dass dieses Element andere Blockelemente umschließt, statt sie zu ersetzen. Das bedeutet, wenn ein p-Element als Side note ausgezeichnet wird, wird das p erhalten bleiben und als neues Elternelement das div mit der Klasse side-note bekommen.

Und damit wären wir bereits am Ende angekommen – jetzt müsst ihr nur noch die entsprechenden CSS-Regeln für die side-note-Klasse schreiben. Mehr über die Möglichkeiten der TinyMCE-API könnt ihr in der offiziellen Dokumentation finden – manchmal ist die Suchmaschine eurer Wahl bei der abschließenden Lösung aber hilfreicher, habe ich jedenfalls für mich festgestellt 😉

Hier abschließend der komplette Code (auch als Gist):

/**
* Listen to setup of a TinyMCE instance.
*/
jQuery(document).on('tinymce-editor-setup', function (event, editor) {
	
	/**
	* Add the id of the soon-to-create button to the
	* toolbar1.
	*
	* @type {string}
	*/
	editor.settings.toolbar1 += ',schlicht-formats';

	/**
	* Create the button.
	*/
	editor.addButton('schlicht-formats', {
	
		/**
		* It is a menubutton.
		*/
		type: 'menubutton',
		text: '»Schlicht« Formats',
		icon: false,

		/**
		* Add the menu items.
		*/
		menu: [
		{
			text: 'Side note',
			onclick: function () {
				/**
				* Toggle the custom side note format.
				*/
				editor.formatter.toggle('schlicht_side_note_format');
				}
		}
		]
	});

	/**
	* Wait until the editor is initialized before
	* registering style.
	*
	* Original hint from http://archive.tinymce.com/forum/viewtopic.php?pid=92762#p92762
	* onInit is deprecated, so https://www.tinymce.com/docs/advanced/migration-guide-from-3.x/#eventhandling
	*/
	editor.on('init', function () {
		
		/**
		* Register the new format for the side note.
		*/
		editor.formatter.register('schlicht_side_note_format', {
		
			/**
			* It is the block element div.
			*/
			block: 'div',

			/**
			* The div element gets the class side-note.
			*/
			classes: 'side-note',

			/**
			* The div is the wrapper for other block elements
			* and does not replace them.
			*/
			wrapper: true
		});
	});
});Code-Sprache: JavaScript (javascript)