TinyMCE Dynamic Buttons/Methods

I’m attempting to create a WordPress plugin which allows you to easily add a dropdown menu with items in for inserting shortcodes. To do this, I need to ‘hook’ into TinyMCE, registering a custom plugin. My plan is to allow users to setup the shortcode menu items using a simple PHP array.

The following class is instantiated which registers a new button and the plugin script:

Read More
<?php

namespace PaperMoonShortcodeButtons;

defined('ABSPATH') or die('Access Denied');

class TinyMce {

    public function __construct()
    {
        $this->add_actions();
        $this->add_filters();
    }

    private function add_actions()
    {
        add_action('admin_head', [$this, 'print_config']);
    }

    public function print_config()
    {
        $shortcodes_config = include PMSB_PLUGIN_PATH . 'lib/shortcodes-config.php'; ?>

        <script type='text/javascript' id="test">
            var pmsb = {
                'config': <?php echo json_encode($shortcodes_config); ?>
            };
        </script> <?php
    }

    private function add_filters()
    {
        add_filter('mce_buttons', [$this, 'register_buttons']);
        add_filter('mce_external_plugins', [$this, 'register_plugins']);
    }

    public function register_buttons($buttons)
    {
        array_push($buttons, 'shortcodebuttons');

        return $buttons;
    }

    public function register_plugins($plugin_array)
    {
        $plugin_array['shortcodebuttons'] = PMSB_PLUGIN_URL . 'assets/js/tinymce.shortcodebuttons.js';

        return $plugin_array;
    }

}

A user would create a PHP array like so (which is included in the above class and output as a javascript variable in the header):

<?php

return [
    [
        'title'     => 'Test Shortcode',
        'slug'      => 'text_shortcode',
        'fields'    => [
            'type'  => 'text',
            'name'  => 'textboxName',
            'label' => 'Text',
            'value' => '30'
        ]
    ],
    [
        'title'     => 'Test Shortcode2',
        'slug'      => 'text_shortcode2',
        'fields'    => [
            'type'  => 'text',
            'name'  => 'textboxName2',
            'label' => 'Text2',
            'value' => '30'
        ]
    ]
];

Finally, here’s the actual plugin script:

"use strict";

(function() {
    tinymce.PluginManager.add('shortcodebuttons', function(editor, url) {
        var menu = [];

        var open_dialog = function(i)
        {
            console.log(pmsb.config[i]);

            editor.windowManager.open({
                title: pmsb.config[i].title,
                body: pmsb.config[i].fields,
                onsubmit: function(e) {
                    editor.insertContent('[' + pmsb.config[i].slug + ' textbox="' + e.data.textboxName + '" multiline="' + e.data.multilineName + '" listbox="' + e.data.listboxName + '"]');
                }
            });
        }

        for(let i = 0; i <= pmsb.config.length - 1; i++) {
            menu[i] = {
                text: pmsb.config[i].title,
                onclick: function() {
                    open_dialog(i)
                }
            }
        }

        console.log(menu);

        editor.addButton('shortcodebuttons', {
            text: 'Shortcodes',
            icon: false,
            type: 'menubutton',
            menu: menu
        });
    });
})();

The button registers fine, the menu items also register fine but when it comes to click on to open up a modal window, I get this error:

Uncaught Error: Could not find control by type: text

I think it’s something to do with the fact that the ‘fields’ is coming from a function which, for some reason, TinyMCE doesn’t like – even though it’s built correctly.

I had thought of doing this a different way – by creating a PHP file which outputs the correct JS but if I do that, I can’t register it as a TinyMCE plugin when using the mce_external_plugins action hook.

I found another question which ran in to the same problem with no answer.

I’ve really hit a wall with this one, any help would be hugely appreciated!

Related posts

1 comment

  1. Well, the typical thing happened – as soon as I post the question, I stumble upon the answer. Maybe I need to get myself a rubber desk duck?

    Anyway, the clue is in the error message. Despite having looked at quite a number of tutorials which all suggest using ‘text’ as the control type, it’s actually ‘textbox’. I’m guessing this is a more recent change in TinyMCE and the tutorials I was looking at were a bit older.

    I searched for yet another tutorial and found the answer staring me right in the face.

Comments are closed.