Add/remove buttons in the WPBakery Page Builder’s TinyMCE editor

In this article I will discuss how a WordPress developer can choose which buttons are shown in the toolbars of a WPBakery Page Builder (formerly Visual Composer) TinyMCE editor.

The problem

In WordPress, the default WYSIWYG editor is TinyMCE. WordPress provides the tiny_mce_before_init filter to let the developer modify buttons and toolbars. This applies to editors for editing pages and posts.

In WPBakery Page Builder, when one uses the vc_map() function to register a shortcode, one can define a parameter with name content and type textarea_html. The input control for that parameter will be a TinyMCE editor shown in WPBakery Page Builder’s popup window. Unfortunately this editor is not currently affected by tiny_mce_before_init. In fact, after a decent amount of googling I could not find any filter, action or other API that lets you decide which buttons are visible in the editor.

So, to summarize the problem:

I needed to find a way to modify which buttons are shown, but only in the WPBakery Page Builder TinyMCE instance, and only in the editor that corresponds to my shortcode, so as not to interfere with any other plugins.

I decided to share the solution on the WordPress StackExchange site because it’s somewhat non-obvious. I’m also posting the solution here for SEO purposes :-p

There are two technical issues:

  1. As discussed above, the tiny_mce_before_init filter does not affect the TinyMCE editor that WPBakery Page Builder instantiates for parameters with param_name == 'content' and type == 'content_html'. The Page Builder frontend gets the TinyMCE HTML markup in a separate AJAX request. The editor’s instantiation does not benefit from the tinyMCEPreInit inline JavaScript array that the filter affects. The solution is to introduce a TinyMCE plugin that modifies the editor’s settings on the client side.
  2. Any TinyMCE plugin must be loaded after the editor itself (see here). Even though according to the wp_enqueue_script() documentation you would expect to be able to enqueue your plugin by setting a dependency to the built-in tiny_mce script, this does not work because TinyMCE is loaded differently. See here for a discussion of the problem and a solution.

The solution: Modify the WPBakery Page Builder TinyMCE with a JavaScript plugin

We’ll first bind to tiny_mce_before_init, but not to modify the buttons. We’ll only use it to add a custom TinyMCE plugin which all editors will run. Being the creative type, I’ll call it myplugin:

function filter_tiny_mce_before_init( $mceInit ) {
    $mceInit['plugins'] .= ',myplugin';
    return $mceInit;
}

add_filter( 'tiny_mce_before_init', 'filter_tiny_mce_before_init' );

Our plugin will first check to see if the current TinyMCE editor is a WPBakery Page Builder editor. Then it will use jQuery to determine if its corresponding shortcode starts with “myplugin”:

'use strict';
tinymce.PluginManager.add( 'myplugin',
    function(editor, url) {

        // skip editors that don't belong to the Page Builder
        if ( editor.id != 'wpb_tinymce_content' )
            return;

        // skip editors that don't belong to my shortcode
        if ( !jQuery( '#wpb_tinymce_content' ).parents(
            '[data-vc-shortcode^="myplugin"]' ).length )
            return;

        // these are the only buttons we'll show
        editor.settings.toolbar1 = 'bold,italic,underline,strikethrough,link,unlink,wp_fullscreen';
        editor.settings.toolbar2 = 'pastetext,removeformat,charmap';
    } );

You can of course adapt the above code to your needs. You can do other things with the editor object. If in doubt, consult the documentation.

Finally we’ll have to make sure that this plugin’s JavaScript is loaded after TinyMCE. It is ugly, but read here for why this is done:

function action_after_wp_tiny_mce() {
    printf( 
        '<script type="text/javascript" src="%s"></script>', 
        plugins_url( 'assets/scripts/myplugin-tinymce.js', __FILE__ ) );
}

add_action( 'after_wp_tiny_mce', 'action_after_wp_tiny_mce' );

“It works™”!

2 thoughts on “Add/remove buttons in the WPBakery Page Builder’s TinyMCE editor

Leave a Reply

Your email address will not be published.