Den WordPress-Editor um einen eigenen Button erweitern

Die Erweiterung des Editors um eigene Buttons ist eine schöne und nutzerfreundliche Alternative zu Shortcodes oder dem Einfügen von Markup in der Textansicht.

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.
	 */
});

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');
			}
		}
	]
});

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.
			 */
		}
	}
]

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
	});
});

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
		});
	});
});

5 Kommentare

  1. Hallo Florian,
    gibt es schon Informationen dazu wie solche eigenen Buttons im neuen Editor (Gutenberg) vorgesehen sind? Ich überlege momentan ein Plugin zu schreiben, dass auch eigene Buttons benötigt, aber da es für mich selbst ist, frage ich mich, ob es sinnvoll ist auf Gutenberg zu warten.
    Grüße

      1. Hi Florian,

        danke für deine Antwort. Bisher bin ich davon ausgegangen, dass der Editor schon in 4.9 kommt.

        Dann ist ja gut 🙂 wird’s noch ein wenig dauern!

        Nadia

  2. Hi Florian,

    das ist mal eine spannende Sache, die ich so noch gar nicht auf dem Schirm hatte. Danke für den Hinweis.

    Ich verwende es auch mal direkt in einem aktuellen Projekt. Allerdings würde ich statt HTML-Tags gerne Shortcodes einfügen und such mir grade den Wolf in der Dokumentation. Du hast da nicht zufällig nen Link parat?

    Viele Grüße

    Philipp

    1. Hi Philipp,

      das wird über den Formatter vermutlich nicht funktionieren. Soweit ich weiß, ist der nur zum Einfügen von HTML. Wenn du wirklich Shortcodes brauchst und nicht das HTML einfügen kannst, das von den Shortcodes erzeugt wird, dann könnte dir vielleicht die Seite hier weiterhelfen: https://www.tinymce.com/docs/advanced/creating-a-custom-button/ (editor.insertContent).

      Wenn die Shortcodes aber zum Beispiel auch den aktuell ausgewählten Text umschließen können sollen, dann wüsste ich so jetzt auch nicht weiter – ich habe mich wirklich nur mit dieser Formatter-Option beschäftigt … 🙂

      Viele Grüße
      Florian

Schreibe einen Kommentar

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