Kurs "WordPress: Pierwsze kroki" (bezpłatna lekcja)

Jakiś czas temu pisałem jak można w WordPressie 4.7+ przywrócić w edytorze przyciski odpowiedzialne za justowanie i podkreślenie tekstu. Dziś pójdziemy o krok dalej – dodamy do edytora (wizualnego i tekstowego) własne przyciski.

Własne przyciski w edytorze WordPressa

Wprawdzie w edytorze – zarówno graficznym, jak i tekstowym – większość niezbędnych przycisków mamy w standardzie, to mogą się zdarzyć sytuacje, gdy w naszej codziennej pracy z WordPressem wykorzystujemy jakieś mniej typowe tagi HTML, krótki kody, czy… właściwie cokolwiek.

Ja sam dość często w swoich wpisach/artykułach wstawiam kod/skrypty, który pakuje między znaczniki <pre><code> i </code></pre>, dzięki czemu mają one swój oddzielny „kontener”.

Niestety, ale edytor graficzny (TinyMCE) w WordPressie w ogóle nie posiada w standardzie obsługi znacznika <code>, który dostępny jest tylko w edytorze tekstowym, ale tam dla odmiany nie ma przyciskuodpowiedzialnego za ustawienie tekstu preformatowanego, czyli znacznika/tagu <pre>.

Sam zazwyczaj wykorzystuje kombinację tych dwóch tagów/znaczników. Dlatego od dawna pomagam sobie w ten sposób, że mam w edytorze (jednym i drugim) dodatkowy przycisk, który zaznaczony tekst zamyka mi w tych znacznikach. I dziś właśnie pokaże na przykładzie tego rozwiązania jak można dodać własne przyciski (będzie sporo kodu, ale i przykład gotowego rozwiązania dla mniej technicznych).

Quicktags API, czyli edytor tekstowy

Zaczynamy od przycisku w edytorze tekstowym, bo dzięki Quicktags API jest to relatywnie proste zadania, które sprowadza się do dodania kilku linijek kodu, np. w pliku functions.php:

function webinsider_wp_add_custom_quicktags() {
    if ( wp_script_is( 'quicktags' ) ) {
        ?>
            <script type="text/javascript">
                // QTags.addButton( id, display, arg1, arg2, access_key, title, priority, instance );
                QTags.addButton( 'pre-code', 'PreCode', '<pre><code>', '</code></pre>', '', 'PreCode' );
            </script>
        <?php
    }
}
add_action( 'admin_print_footer_scripts', 'webinsider_wp_add_custom_quicktags' );

Powyższy kod sprawi, że w edytorze tekstowym pojawi się nam dodatkowy przycisk oznaczony jako „PreCode”, który przed i za zaznaczonym tekstem wstawi odpowiednio tagi/znaczniki otwierające, czyli <pre><code>, oraz zamykające, </code></pre> (oczywiście zarówno nazwę przycisku, jego lokalizację, jak i wartość do wstawienia przed i po możecie wstawić wedle Waszych potrzeb):

By dodać więcej przycisków, wystarczy powielić jedną linijkę kodu, która odpowiada za wyświetlenie i działanie przycisku:

//QTags.addButton( id, display, arg1, arg2, access_key, title, priority, instance );
QTags.addButton( 'przycisk1', 'Przycisk1', 'TxtPrzed1', 'TxtPo1', '', 'Przycisk1' );
QTags.addButton( 'przycisk2', 'Przycisk2', 'TxtPrzed2', 'TxtPo2', '', 'Przycisk2' );

Dla przykładu kilka domyślnych (wbudowanych w edytor tekstowy w WordPressie) Quicktagów:

Dodatkowe przyciski w TinyMCE, czyli zabawę czas zacząć

W przypadku edytora graficznego, czyli TinyMCE (edytor typu WYSIWYG – What You See Is What You Get) sytuacja trochę się komplikuje – być może (?) dałoby się to jakoś upakować do pliku functions.php, ale w tym przypadku zdecydowanie lepiej/wygodniej przygotować sobie odpowiednią wtyczkę (nie jest to w cale dużo bardziej skomplikowane).

Zaczynamy od przygotowania katalogu, np. „webinsider-wp-tinymce-custom-buttons”:

wp-config/plugins/webinsider-wp-tinymce-custom-buttons

Katalogu tym umieszczamy 3 pliki (2 obowiązkowe, jeden opcjonalny):

  • webinsider-wp-tinymce-custom-buttons.php
  • webinsider-wp-tinymce-precode-class.js
  • webinsider-wp-tinymce-custom-buttons.css

Pierwszy (PHP) to podstawowy plik naszej wtyczki, odpowiedzialny za działanie całości. Plik JS (JavaScript) to wtyczka do edytora TinyMCE, odpowiedzialny za przycisk. Ostatni przycisk (CSS) jest opcjonalny, wykorzystywany do określenia aspektów wizualnych naszego przycisku (w tym konkretnym przypadku wykorzystamy tylko na potrzeby ikony).

Zaczynamy od głównego pliku naszej wtyczki, czyli webinsider-wp-tinymce-custom-buttons.php:

<?php
/**
 * Plugin Name: Webinsider WP: TinyMCE custom buttons
 * Plugin URI: https://webinsider.pl
 * Version: 1.0
 * Author: Webinsider
 * Author URI: https://webinsider.pl
 * Description: Add to TinyMCE (and standard WordPress editor) custom buttons
 * License: GPL2
 */
 
class Webinsider_WP_TinyMCE_Custom_Buttons_Class {
 
    function __construct() {
 
         if ( is_admin() ) {
            
            function webinsider_wp_tinymce_custom_buttons_add_plugin_precode( $plugin_js_file ) {
                $plugin_js_file[ 'webinsider_wp_tinymce_custom_buttons_add_plugin_precode_class' ] = plugin_dir_url( __FILE__ ) . 'webinsider-wp-tinymce-precode-class.js';
                return $plugin_js_file;
            }
            add_filter( 'mce_external_plugins', 'webinsider_wp_tinymce_custom_buttons_add_plugin_precode' );        
            
            function webinsider_wp_tinymce_custom_buttons_add_buttons( $tinymce_buttons ) {
                array_push( $tinymce_buttons, 'webinsider_wp_tinymce_custom_buttons_add_plugin_precode_class' );
                return $tinymce_buttons;
            }
            add_filter( 'mce_buttons_2', 'webinsider_wp_tinymce_custom_buttons_add_buttons' );
            
            function webinsider_wp_tinymce_custom_buttons_add_css() {
                wp_enqueue_style( 'webinsider_wp_tinymce_custom_buttons', plugins_url( 'webinsider-wp-tinymce-custom-buttons.css', __FILE__ ) );
            }
            add_action( 'admin_enqueue_scripts', 'webinsider_wp_tinymce_custom_buttons_add_css' );
            
            // Standardowy edytor HTML WordPressa
            function webinsider_wp_tinymce_custom_buttons_add_qtags() {
                    if ( wp_script_is( 'quicktags' ) ) {
                        ?>
                            <script type="text/javascript">
                                //QTags.addButton( id, display, arg1, arg2, access_key, title, priority, instance );
                                QTags.addButton( 'webinsider-wp-tinymce-custom-buttons-pre-code', 'PreCode', '<pre><code>', '</pre></code>', '', 'Pre + code tag' );
                            </script>
                        <?php
                    }
                }            
            add_action( 'admin_print_footer_scripts', 'webinsider_wp_tinymce_custom_buttons_add_qtags' );
        }
    } 
}
$webinsider_wp_tinymce_custom_buttons_class = new Webinsider_WP_TinyMCE_Custom_Buttons_Class;

Następnie tworzymy wtyczkę do edytora TinyMCE, czyli plik webinsider-wp-tinymce-precode-class.js:

(function() {
    tinymce.PluginManager.add( 'webinsider_wp_tinymce_custom_buttons_add_plugin_precode_class', function( editor, url ) {
        editor.addButton( 'webinsider_wp_tinymce_custom_buttons_add_plugin_precode_class', {
            title: 'Pre + code tag',
            text: 'PreCode',
            // https://developer.wordpress.org/resource/dashicons/#editor-code
            icon: 'icon dashicons-editor-code', 
            cmd: 'webinsider_wp_tinymce_custom_buttons_add_plugin_precode_class',
        } );
 
        editor.addCommand( 'webinsider_wp_tinymce_custom_buttons_add_plugin_precode_class', function() {
            var tekst = editor.selection.getContent( {
                'format': 'html'
            } );
            if ( tekst.length === 0 ) {
                alert( 'Najpierw zaznacz tekst' );
                return;
            }
            
            editor.execCommand( 'mceReplaceContent', false, '<pre><code>' + tekst + '</pre></code>' );
        } );

    } );
} )();

Na koniec jeszcze plik CSS (webinsider-wp-tinymce-custom-buttons.css), który w naszym przypadku będzie odpowiadał tylko za prawidłowe wyświetlenie ikony:

i.mce-i-icon {
    font: normal 20px/1 'dashicons';
}

Po zapisaniu i aktywacji wtyczki powinien pojawić się dodatkowy przycisk – zarówno w edytorze graficznym (TinyMCE):

Jak i w standardowym edytorze tekstowym (HTML):

Własny przycisk odpowiedzialny za wstawianie linków

Pomyślałem, że dobrze będzie od razu pokazać jak można rozbudować rozwiązanie o dodatkowe przyciski. W tym celu dodamy jeszcze jeden przycisk, który będzie odpowiedzialny za wstawienie znaczków HTML odpowiedzialnych za link (hiperłącze).

W tym przypadku – oprócz zaznaczonego tekstu – będziemy jeszcze potrzebowali dodatkowe okno dialogowe, gdzie będzie można wpisać adres URL naszego donośnika, który – w naszym przykładzie – dodatkowo otrzyma parametr odpowiedzialny za otwieranie odnośników w nowym oknie (karcie) przeglądarki.

Wersja podstawowa, dla edytora tekstowego (HTML), do wstawienia np. do pliku functions.php może wyglądać tak:

function webinsider_wp_add_custom_quicktags() {
    if ( wp_script_is( 'quicktags' ) ) {
        ?>
            <script type="text/javascript">
                // QTags.addButton( id, display, arg1, arg2, access_key, title, priority, instance );
                QTags.addButton( 'pre-code', 'PreCode', '<pre><code>', '</code></pre>', '', 'PreCode' );
                QTags.addButton( 'webinsider-wp-tinymce-custom-buttons-link-target', 'LinkTarget', webinsider_wp_add_custom_quicktags_add_link );
                
                function webinsider_wp_add_custom_quicktags_add_link_selected_txt() {
                    var tekst = document.getElementById( 'content' );
                        return tekst.value.substring( tekst.selectionStart, tekst.selectionEnd );
                }
                                                
                function webinsider_wp_add_custom_quicktags_add_link() {
                    var tekst = webinsider_wp_add_custom_quicktags_add_link_selected_txt();
                    var url = prompt( 'Podaj adres (URL)', '' );
                            
                    if ( webinsider_wp_add_custom_quicktags_add_link ) {
                        QTags.insertContent( '<a href="' + url + '" target="_blank">' + tekst + '</a>' );
                    }
                }
            </script>
        <?php
    }
}
add_action( 'admin_print_footer_scripts', 'webinsider_wp_add_custom_quicktags' );

W przypadku gdy zdecydujemy się na rozwiązanie przez wtyczkę, dzięki czemu dodatkowe przyciski pojawią się nie tylko w edytorze tekstowym, ale i graficznym (TinyMCE) musimy zmodyfikować podstawowy plik wtyczki (webinsider-wp-tinymce-custom-buttons.php).

Tak będzie teraz wyglądał fragment odpowiedzialny m.in. za przygotowanie obsługi wtyczki do TinyMCE:

function webinsider_wp_tinymce_custom_buttons_add_plugin_precode( $plugin_js_file ) {
    $plugin_js_file[ 'webinsider_wp_tinymce_custom_buttons_add_plugin_precode_class' ] = plugin_dir_url( __FILE__ ) . 'webinsider-wp-tinymce-precode-class.js';
    return $plugin_js_file;
}
add_filter( 'mce_external_plugins', 'webinsider_wp_tinymce_custom_buttons_add_plugin_precode' );

function webinsider_wp_tinymce_custom_buttons_add_plugin_link( $plugin_js_file ) {
    $plugin_js_file[ 'webinsider_wp_tinymce_custom_buttons_add_plugin_link_class' ] = plugin_dir_url( __FILE__ ) . 'webinsider-wp-tinymce-link-class.js';
    return $plugin_js_file;
}
add_filter( 'mce_external_plugins', 'webinsider_wp_tinymce_custom_buttons_add_plugin_link' );

function webinsider_wp_tinymce_custom_buttons_add_buttons( $tinymce_buttons ) {
    array_push( $tinymce_buttons, 'webinsider_wp_tinymce_custom_buttons_add_plugin_precode_class' );
    array_push( $tinymce_buttons, 'webinsider_wp_tinymce_custom_buttons_add_plugin_link_class' );
    return $tinymce_buttons;
}
add_filter( 'mce_buttons_2', 'webinsider_wp_tinymce_custom_buttons_add_buttons' );

// Opcjonalnie, gdy CSS (np. ikona):
function webinsider_wp_tinymce_custom_buttons_add_css() {
    wp_enqueue_style( 'webinsider_wp_tinymce_custom_buttons', plugins_url( 'webinsider-wp-tinymce-custom-buttons.css', __FILE__ ) );
}
add_action( 'admin_enqueue_scripts', 'webinsider_wp_tinymce_custom_buttons_add_css' );

Do tego fragment odpowiedzialny za przyciski w edytorze tekstowym również musimy „trochę” zmodyfikować:

// Standardowy edytor HTML WordPressa
function webinsider_wp_tinymce_custom_buttons_add_qtags() {
    if ( wp_script_is( 'quicktags' ) ) {
        ?>
            <script type="text/javascript">
                //QTags.addButton( id, display, arg1, arg2, access_key, title, priority, instance );
                QTags.addButton( 'webinsider-wp-tinymce-custom-buttons-pre-code', 'PreCode', '<pre><code>', '</pre></code>', '', 'Pre + code tag' );
                QTags.addButton( 'webinsider-wp-tinymce-custom-buttons-link-target', 'LinkTarget', webinsider_wp_tinymce_custom_buttons_add_qtags_add_link );
                
                function webinsider_wp_tinymce_custom_buttons_add_qtags_add_link_selected_txt() {
                    var tekst = document.getElementById( 'content' );
                    return tekst.value.substring( tekst.selectionStart, tekst.selectionEnd );
                }
                                
                function webinsider_wp_tinymce_custom_buttons_add_qtags_add_link() {
                    var tekst = webinsider_wp_tinymce_custom_buttons_add_qtags_add_link_selected_txt();
                    var url = prompt( 'Podaj adres (URL)', '' );
                    
                    if ( webinsider_wp_tinymce_custom_buttons_add_qtags_add_link ) {
                        QTags.insertContent( '<a href="' + url + '" target="_blank">' + tekst + '</a>' );
                    }
                }
            </script>
        <?php
    }
}            
add_action( 'admin_print_footer_scripts', 'webinsider_wp_tinymce_custom_buttons_add_qtags' );

Na koniec tworzymy jeszcze dodatkowy plik z wtyczką (pluginem) do TinyMCE, czyli webinsider-wp-tinymce-link-class.js:

(function() {
    tinymce.PluginManager.add( 'webinsider_wp_tinymce_custom_buttons_add_plugin_link_class', function( editor, url ) {
        editor.addButton( 'webinsider_wp_tinymce_custom_buttons_add_plugin_link_class', {
            title: 'Wstaw link',
            text: 'Link',
            // https://developer.wordpress.org/resource/dashicons/#editor-code
            icon: 'icon dashicons-admin-links', 
            cmd: 'webinsider_wp_tinymce_custom_buttons_add_plugin_link_class',
        } );
 
        editor.addCommand( 'webinsider_wp_tinymce_custom_buttons_add_plugin_link_class', function() {
            var tekst = editor.selection.getContent( {
                'format': 'html'
            } );
            if ( tekst.length === 0 ) {
                alert( 'Najpierw zaznacz tekst' );
                return;
            }
            
            var url = prompt('Podaj adres (URL)');
            if ( !url ) {
                // User cancelled - exit
                return;
            }
            if (url.length === 0) {
                // User didn't enter anything - exit
                return;
            }
            
            editor.execCommand('mceReplaceContent', false, '<a href="' + url + '" target="_blank">' + tekst + '</a>');
        } );    

    } );
} )();

W tym momencie mamy 2 przyciski. W edytorze graficznym (TinyMCE):

Jak i tekstowym:

Gotowa wtyczka dla… mniej cierpliwych

Oczywiście w repetytorium WordPressa znajdziecie też gotowe rozwiązania (wtyczki), które pozwalają za pomocą odpowiednio przygotowanego formularza dodać własny przycisk do obu edytorów.

Jedną z takich wtyczek jest Visual Editor Custom Buttons:

Może nie mamy tu tylu możliwości co w przypadku samodzielne przygotowanego rozwiązania (szytego na miarę), ale jeśli ktoś nie czuje się na siłach, to czemu nie skorzystać z tego typu rozwiązań…

(!) Zgłoś błąd na stronie
Pomogłem? To może postawisz mi wirtualną kawę?
LUTy dla D-Cinelike (DJI Mini 3 Pro, DJI Avata, OSMO Pocket) od MiniFly
Wdrożenie Omnibusa w sklepie na WooCommerce
Jak (legalnie) latać dronem w Kategorii Otwartej
Kurs "WordPress: Pierwsze kroki" (bezpłatna lekcja)
Patryk
Kurs "WordPress: Pierwsze kroki" (na dobry początek)