Wordpress - Unable to add "code" button to TinyMCE toolbar

That is a very good question. I just tested your code locally and see the same result. A little digging reveals a twp-part problem.

wp-includes/class-wp-editor.php is a good read for TinyMCE customizations

WordPress 3.9 did update to TinyMCE 4.0 and the TinyMCE docs imply that the superscript button is now called "superscript" and not just "sup". Same for "subscript" versus "sub".

That change alone gets the superscript button working.

function my_mce_buttons_2($buttons) {   
    /**
     * Add in a core button that's disabled by default
     */
    $buttons[] = 'superscript';
    $buttons[] = 'code';     
    $buttons[] = 'hr';
    $buttons[] = 'fullscreen';

    return $buttons;
}
add_filter('mce_buttons_2', 'my_mce_buttons_2');

However, the "code" button requires the TinyMCE "code" plugin which doesn't ship with WordPress by default. Therefore you will have to download it and tell TinyMCE where to find it. Weirdly you can't download a specific plugin so I had to download the entire TinyMCE library and dig through the extracted files to find the /plugins/code/plugin.min.js file.

TinyMCE External Plugins

To activate the code button we're going to need to tell TinyMCE where to find this file. I'm going to put it in my theme's root folder because that was the easiest for me to test on to answer your question, but I don't think it is theme functionality and should probably be moved to a plugin or a site-specific mu-plugin.

Since it isn't included in the WordPress core, the code plugin is technically an external plugin. The mce_external_plugins filter accepts an array. There's a nice bit of docbloc explanation in the class-wp-editor.php file:

/**
 * Filter the list of TinyMCE external plugins.
 *
 * The filter takes an associative array of external plugins for
 * TinyMCE in the form 'plugin_name' => 'url'.
 *
 * The url should be absolute, and should include the js filename
 * to be loaded. For example:
 * 'myplugin' => 'http://mysite.com/wp-content/plugins/myfolder/mce_plugin.js'.
 *
 * If the external plugin adds a button, it should be added with
 * one of the 'mce_buttons' filters.
 *
 * @since 2.5.0
 *
 * @param array $external_plugins An array of external TinyMCE plugins.
 */

Now that we know which filter to target and what information to send we can send TinyMCE the info about our downloaded plugin file.

/*
 * The TinyMCE "Code" button is not included with WP by default
 */
function my_mce_external_plugins($plugins) {   

    $plugins['code'] = get_stylesheet_directory_uri() . '/code/plugin.min.js';
    return $plugins;
}
add_filter('mce_external_plugins', 'my_mce_external_plugins');

With both of these functions running I know see all 4 buttons in my TinyMCE visual editor.


Important to note:

I thought that the code button key in TinyMCE would enable adding HTML <code></code> tags around a selected block of text. That is not what it does. It allows you to edit the full HTML code of what TinyMCE is showing in the WYSIWYG field. (I was wondering why it needed a whole plugin... now I know.)

This is not useful at all in the context of WordPress, because you can already view the "Text" tab in WordPress the code view that follows all of the WordPress quirks like double new lines meaning a paragraph break, etc.

If you want inline <code></code> tags I ended up doing this:

// Callback function to filter the MCE settings
function squarecandy_tinymce_mce_before_init($init_array) {
    // Define the style_formats array
    $style_formats = array(
        array(
            'title' => 'code',
            'inline' => 'code',
            'classes' => 'tinymce-code',
            'wrapper' => false,
            'styles' => 'background-color: #eee',
        ),
        // add more styles here if you want to...
        // https://codex.wordpress.org/TinyMCE_Custom_Styles

    );
    // Insert the array, JSON ENCODED, into 'style_formats'
    $init_array['style_formats'] = json_encode($style_formats);
    return $init_array;
}
add_filter('tiny_mce_before_init','squarecandy_tinymce_mce_before_init');

It would be nicer to have a button for it, but this will work...

Tags:

Tinymce