WordPress TinyMCE Editor Tips | How to Add Custom Buttons, Styles, Dropdowns & Pop-ups

The release of WordPress 3.9 didn’t just update WordPress; it also came with the latest TinyMCE editor, version 4.0. This update marks big changes in the editor API, and there’s a lot of interesting things that you can achieve with the flexibility it provides.

To help you on your way, we’ve spent loads of time playing around with the editor to bring you an in-depth guide to making it your own. From adding your own buttons, implementing the editor in your comment section to form validation, if you’re interested in PHP and the TinyMCE editor then you’re sure to find something to interest you here.

This is quite an extensive article, so we’ve split it into distinct sections, each with their own subsections. If you know what you’re looking for, just click on the links to be taken right there!

Guide List

Creating Buttons Part 1

The code from the following examples may be also found on Github.

This section is rather long, so we’ve split it up into easy to manage blocks. Just click the link to jump to the appropriate section.

Declaring a new TinyMCE button

Let’s start with the basics – in order to make our buttons appear in the editor, we have to hook under the admin_head action:

add_action('admin_head', 'gavickpro_add_my_tc_button');

gavickpro_add_my_tc_button function should be as follows:

function gavickpro_add_my_tc_button() {
    global $typenow;
    // check user permissions
    if ( !current_user_can('edit_posts') && !current_user_can('edit_pages') ) {
   	return;
    }
    // verify the post type
    if( ! in_array( $typenow, array( 'post', 'page' ) ) )
        return;
	// check if WYSIWYG is enabled
	if ( get_user_option('rich_editing') == 'true') {
		add_filter("mce_external_plugins", "gavickpro_add_tinymce_plugin");
		add_filter('mce_buttons', 'gavickpro_register_my_tc_button');
	}
}

As you can see, the above function performs several important operations; it mainly checks user permissions and settings. If all conditions are met, then two filters are added: gavickpro_add_tinymce_plugin and gavickpro_register_my_tc_button.

The first of them is used to specify the path to the script with our plugin for TinyMCE:

function gavickpro_add_tinymce_plugin($plugin_array) {
   	$plugin_array['gavickpro_tc_button'] = plugins_url( '/text-button.js', __FILE__ ); // CHANGE THE BUTTON SCRIPT HERE
   	return $plugin_array;
}

The second, on the other hand, is used to add buttons in the editor – in this case we will add one button:

function gavickpro_register_my_tc_button($buttons) {
   array_push($buttons, "gavickpro_tc_button");
   return $buttons;
}

Button with text label

Now we may look at creating the code which is responsible for adding a button to the editor – we place the following code in the *.js file specified in the gavickpro_add_tinymce_plugin filter. This code adds a button, which when clicked will insert Hello World! text into the editor:

(function() {
    tinymce.PluginManager.add('gavickpro_tc_button', function( editor, url ) {
        editor.addButton( 'gavickpro_tc_button', {
            text: 'My test button',
            icon: false,
            onclick: function() {
                editor.insertContent('Hello World!');
            }
        });
    });
})();

This isn’t the most spectacular effect, but nevertheless, the first button that we’ve added to the TinyMCE editor works as expected:

TinyMCE 4 - text button

Button with standard icon

It’s time to change the look of our button and adjust it to match the appearance of the dashboard. For this purpose we use Dashicons – a set of icons in the form of the font used in the dashboard.

Simply change your code to:

(function() {
    tinymce.PluginManager.add('gavickpro_tc_button', function( editor, url ) {
        editor.addButton( 'gavickpro_tc_button', {
            title: 'My test button',
            icon: 'wp_code',
            onclick: function() {
                editor.insertContent('Hello World!');
            }
        });
    });
})();

Two things have changed:

  • The text property was replaced by the title property, so that the text disappears from the button and will now appear in the tooltip when you hover over it.
  • We defined the name of the icon used. Unfortunately, at least to my current understanding, without additional CSS you are limited to certain icons.

The effect in action:

TinyMCE 4 - button with standard icon

Button with custom icon from Dashicons

Let’s assume that we are stubborn and want an icon from the Dashicons set which is not defined in the code editor – for example, the WordPress logo icon.

Fortunately, the solution is quite simple – we need to attach some additional CSS code, which has the following structure:

i.mce-i-icon {
	font: 400 20px/1 dashicons;
	padding: 0;
	vertical-align: top;
	speak: none;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	margin-left: -2px;
	padding-right: 2px
}

We may do it easily, like this:

function gavickpro_tc_css() {
	wp_enqueue_style('gavickpro-tc', plugins_url('/style.css', __FILE__));
}

add_action('admin_enqueue_scripts', 'gavickpro_tc_css');

The above code will allow us to use any character class of dashicons-*. For those of you who are curious – we had to specify the mce-i-icon class, because the value of the icon is automatically appended to the mce-i- prefix. Now, we should change the JavaScript code to the following:

(function() {
    tinymce.PluginManager.add('gavickpro_tc_button', function( editor, url ) {
        editor.addButton( 'gavickpro_tc_button', {
            title: 'My test button',
            icon: 'icon dashicons-wordpress-alt',
            onclick: function() {
                editor.insertContent('Hello World!');
            }
        });
    });
})();

As you can see, we added icon as the first class (in order to get the mce-i-icon class), and then we add a dashicons-wordpress-alt class.

Our button now looks as follows:

TinyMCE 4 - button with Dashicons

The list of classes from the Dashicons set is available on the icon list page – All you need to do is click on the chosen icon, so that the CSS class associated with this icon will appear at the top.

Button with your own graphics for the icon

It may be the case that even Dashicons do not meet our specific needs in regards to the appearance of the icon. We would thus need to create our own graphics – preferably 2-3 times larger than the size of the button (I created a graphic of size 64x64px, which looks nice on a retina display) and define it as a background button in our CSS file:

i.gavickpro-own-icon {
	background-image: url('custom-icon.png');
}

We replace the JavaScript code to the following one in order to use a new class:

(function() {
    tinymce.PluginManager.add('gavickpro_tc_button', function( editor, url ) {
        editor.addButton( 'gavickpro_tc_button', {
            title: 'My test button',
            icon: 'icon gavickpro-own-icon',
            onclick: function() {
                editor.insertContent('Hello World!');
            }
        });
    });
})();

Thanks to this code, our button now uses our desired, nonstandard icon:

TinyMCE 4 - button with custom icon

Adding submenu to button

Our button already looks nice; however, it is still restricted to a single functionality. Fortunately, we may easily change that – we just need to make the following changes to our code:

(function() {
    tinymce.PluginManager.add('gavickpro_tc_button', function( editor, url ) {
        editor.addButton( 'gavickpro_tc_button', {
            title: 'My test button',
            type: 'menubutton',
            icon: 'icon gavickpro-own-icon',
            menu: [
            	{
            		text: 'Menu item I',
            		value: 'Text from menu item I',
            		onclick: function() {
            			editor.insertContent(this.value());
            		}
           		}
           ]
        });
    });
})();

First of all, we changed the type of button to menubutton; thanks to this, we may use the menu property, which includes the table for a submenu item. As you can see the submenu position includes text and the value is inserted by clicking (thanks to the function defined in the onclick feature).

Our button has changed its size as well:

TinyMCE 4 - button with submenu

Adding sub-submenu to button

The structure defined in the menu properties may be nested; just specify the menu property in the correct position:

(function() {
    tinymce.PluginManager.add('gavickpro_tc_button', function( editor, url ) {
        editor.addButton( 'gavickpro_tc_button', {
            title: 'My test button',
            type: 'menubutton',
            icon: 'icon gavickpro-own-icon',
            menu: [
                {
                    text: 'Menu item I',
                    value: 'Text from menu item I',
                    onclick: function() {
                        editor.insertContent(this.value());
                    }
                },
                {
                    text: 'Menu item II',
                    value: 'Text from menu item II',
                    onclick: function() {
                        editor.insertContent(this.value());
                    },
                    menu: [
                        {
                            text: 'First submenu item',
                            value: 'Text from sub sub menu',
                            onclick: function(e) {
                                e.stopPropagation();
                                editor.insertContent(this.value());
                            }       
                        },
                        {
                            text: 'Second submenu item',
                            value: 'Text from sub sub menu',
                            onclick: function(e) {
                                e.stopPropagation();
                                editor.insertContent(this.value());
                            }       
                        }
                    ]
                },
                {
                    text: 'Menu item III',
                    value: 'Text from menu item III',
                    onclick: function() {
                        editor.insertContent(this.value());
                    }
                }
           ]
        });
    });
})();

Our button already has quite an enhanced menu:

TinyMCE 4 - button with sub-submenu

Unfortunately, we quickly noticed a small problem – if we click on, for example, “First submenu item”, then in our editor we will see:

TinyMCE 4 - event propagation problem

In short – clicking the sub-submenu item brings up the onclick action also used in the parent menu item. Fortunately, you can easily eliminate this issue – just use the stopPropagation method, which means that the event is not passed up the DOM tree:

onclick: function(e) {
    e.stopPropagation();
    editor.insertContent(this.value());
}

After this change, our sub-submenu items should correctly react when clicked.

Adding popup after clicking

So far, we have been limiting ourselves to inserting specific text values to the editor, but this will not always be a sufficient solution. Let’s do something that will enable the user to identify some of the added text – let’s use the popup that appears when you click on the button:

onclick: function() {
    editor.windowManager.open( {
        title: 'Insert h3 tag',
        body: [{
            type: 'textbox',
            name: 'title',
            label: 'Your title'
        }],
        onsubmit: function( e ) {
            editor.insertContent( '<h3>' + e.data.title + '</h3>');
        }
    });
}

The above code will cause a popup to display with an instruction to insert the content of the h3 index:

TinyMCE 4 - button with popup

As we can see the onsubmit property results in text being added to the editor after changes made by the user are accepted.

Popup enhancing

We may certainly create more enhanced popups:

TinyMCE 4 - button with complex popup

The above popup uses two fields of the textbox type and one of the listbox type:

onclick: function() {
    editor.windowManager.open( {
        title: 'Insert header tag',
        body: [{
            type: 'textbox',
            name: 'title',
            label: 'Your title'
        },
        {
            type: 'textbox',
            name: 'id',
            label: 'Header anchor'
        },
        {
            type: 'listbox', 
            name: 'level', 
            label: 'Header level', 
            'values': [
                {text: '<h3>', value: '3'},
                {text: '<h4>', value: '4'},
                {text: '<h5>', value: '5'},
                {text: '<h6>', value: '6'}
            ]
        }],
        onsubmit: function( e ) {
            editor.insertContent( '<h' + e.data.level + ' id="' + e.data.id + '">' + e.data.title + '</h' + e.data.level + '>');
        }
    });
}

The code from the following examples may be also found on Github.

Creating Buttons Part 2

Table of contents

The code from the following examples may be also found on Github.

Adding icons in submenu

Submenus can have icons added very easily – all that is required is that the icon attribute is defined in the object that creates the submenu item:

(function() {
    tinymce.PluginManager.add('gk_tc_button2', function( editor, url ) {
        editor.addButton( 'gk_tc_button2', {
            title: 'My test button',
            type: 'menubutton',
            icon: 'icon gk-own-icon',
            menu: [
                {
                    text: 'Menu item I',
                    value: 'Text from menu item I',
                    icon: 'icon dashicons-wordpress',
                    onclick: function() {
                        editor.insertContent(this.value());
                    }
                },
                {
                    text: 'Menu item II',
                    value: 'Text from menu item II',
                    icon: 'icon dashicons-wordpress-alt',
                    onclick: function() {
                        editor.insertContent(this.value());
                    },
                    menu: [
                        {
                            text: 'First submenu item',
                            value: 'Text from sub sub menu',
                            icon: 'icon dashicons-smiley',
                            onclick: function(e) {
                                e.stopPropagation();
                                editor.insertContent(this.value());
                            }
                        },
                        {
                            text: 'Second submenu item',
                            value: 'Text from sub sub menu',
                            icon: 'icon dashicons-edit',
                            onclick: function(e) {
                                e.stopPropagation();
                                editor.insertContent(this.value());
                            }
                        }
                    ]
                },
                {
                    text: 'Menu item III',
                    value: 'Text from menu item III',
                    icon: 'icon dashicons-tickets',
                    onclick: function() {
                        editor.insertContent(this.value());
                    }
                }
           ]
        });
    });
})();

You may see the effect below – icons have been added to each submenu item:

TinyMCE 4 - submenu items with icons

Multilingual support in plugins for TinyMCE

The first thought that came to mind when starting to create JS scripts with multilingual support in WordPress was to use the wp_localize_script function. However, this isn’t actually possible; the function is useless for TinyMCE plugins as the scripts of TinyMCE plugins aren’t added via the code page the standard way – they are instead added dynamically. Hence, we have to use another solution, namely the mce_external_languages filter. For this purpose we need to create a new function:

function gk_add_my_tc2_button_lang($locales) {
    $locales['gk_tc_button2'] = plugin_dir_path ( __FILE__ ) . 'translations.php';
    return $locales;
}

add_filter( 'mce_external_languages', 'gk_add_my_tc2_button_lang');

As you can see, the above function creates a new element of the $locales table, which indicates a translation file named translations.php placed in the plugin catalogue that adds buttons.

Thus, we have to again create a file:

<?php

if ( ! defined( 'ABSPATH' ) )
    exit;

if ( ! class_exists( '_WP_Editors' ) )
    require( ABSPATH . WPINC . '/class-wp-editor.php' );

function gk_tc_button_translation() {
    $strings = array(
        'button_label' => __('My test button I', 'gk_tc_button2'),
        'msg' => __('Hello World!!!!', 'gk_tc_button2')
    );

    $locale = _WP_Editors::$mce_locale;
    $translated = 'tinyMCE.addI18n("' . $locale . '.gk_tc_button", ' . json_encode( $strings ) . ");\n";

    return $translated;
}

$strings = gk_tc_button_translation();

The above file includes, besides the proper security, a function that generates a piece of JavaScript code for the TinyMCE editor – it will be an associative table of our translations. It’s worth paying attention to the line that assigns a value to the $translated variable –it includes the gk_tc_button element – as it’s the name of the object which will store your translations. We will make the references to its values as follows:

editor.getLang('OBJECT.KEY')

With a script that adds buttons we have only two phrases that can be translated – the explanation of the button itself and the text added to the editor after clicking the button:

(function() {
    tinymce.PluginManager.add('gk_tc_button1', function( editor, url ) {
        editor.addButton( 'gk_tc_button1', {
            title: editor.getLang('gk_tc_button.button_label'),
            icon: 'icon gk-own-icon',
            onclick: function() {
                editor.insertContent(editor.getLang('gk_tc_button.msg'));
            }
        });
    });
})();

Adding a second button

Sometimes for usability it may be necessary to avoid putting every required functionality under one button – its menu will be too large or too heavily nested as to be virtually impassable. The easiest way around this problem is to just add a second button that contains part of the required functionality.

For this purpose we have to modify some functions mentioned in the first part of this guide; specifically, functions that are attached to the mce_external_plugins and mce_buttons filters:

add_filter("mce_external_plugins", "gk_add_tinymce_plugin2");
add_filter('mce_buttons', 'gk_register_my_tc2_button');

The function that adds JS code will look as follows:

function gk_add_tinymce_plugin2($plugin_array) {
   	$plugin_array['gk_tc_button1'] = plugins_url( '/custom-icon-button.js', __FILE__ );
   	$plugin_array['gk_tc_button2'] = plugins_url( '/second-button.js', __FILE__ );
   	return $plugin_array;
}

We simply added another item in the $plugin_array associative table and changed the naming slightly – now each button has a common name ending with the button’s number – they will help us to distinguish our buttons from each other. The name of the scripts can be whatever you want.

Now, we have added our plugins and we are now left with adding our buttons to the list of buttons in TinyMCE using the mce_buttons filter:

function gk_register_my_tc2_button($buttons) {
   array_push($buttons, "gk_tc_button1");
   array_push($buttons, "gk_tc_button2");
   return $buttons;
}

As you can see above, we again used the names that we are already familiar with. We may duplicate this schema as many times we want, though we have to remember not to overdo it as several plugins each adding a couple of buttons may effectively trash the editor. If possible, we should only create a small amount of buttons for our purposes, bearing in mind at the same time that we aren’t the only plugin authors that will be using this functionality.

The first script (custom-icon-button.js), in comparison to the previous one, has changed slightly – we changed the name to gk_tc_button1:

(function() {
    tinymce.PluginManager.add('gk_tc_button1', function( editor, url ) {
        editor.addButton( 'gk_tc_button1', {
            title: 'My test button I',
            icon: 'icon gk-own-icon',
            onclick: function() {
                editor.insertContent('Hello World I');
            }
        });
    });
})();

The second script (second-button.js) also has a new name:

function() {
    tinymce.PluginManager.add('gk_tc_button2', function( editor, url ) {
        editor.addButton( 'gk_tc_button2', {
            title: 'My test button II',
            icon: 'icon dashicons-wordpress',
            onclick: function() {
                editor.insertContent('Hello World II');
            }
        });
    });
})();

Two buttons should now appear in the editor:

TinyMCE 4 - two buttons

When there is no place for buttons

Buttons that have been recently added appear on the first visible button bar. However, sometimes there isn’t much space there to work with – fortunately, we may add our buttons to the second row; all we need to do is change the filter name from mce_buttons to mce_buttons_2 as follows:

add_filter('mce_buttons_2', 'gk_register_my_tc2_button');

TinyMCE 4 - second row of buttons

Moreover, we may even create another row of buttons, which doesn’t exist in a clean WordPress installation. Just use the mce_buttons_3 filter:

add_filter('mce_buttons_3', 'gk_register_my_tc2_button');

TinyMCE 4 - third row of buttons

Obviously the question immediately arises; exactly how many button rows are we able to create? Unfortunately, mce_buttons_10 doesn’t work as we may create a maximum of 4 rows in TinyMCE in WordPress. Hence, the last filter is mce_buttons_4.

When we place buttons in rows other than the first one, we should remember that these rows are hidden by default, so we need click the ‘expand’ button to see the other buttons. That’s why it’s better to place your buttons on the first row if possible; to ensure that they remain in easy reach.

Removing editor buttons

Removing existing buttons is very easy – instead of adding an element to the table, we just remove it.

function gk_remove_tmce_btns($buttons) {
 unset($buttons[0]);
 return $buttons;
 }

 add_filter('mce_buttons', 'gk_remove_tmce_btns');

The buttons are indexed in the table in the same order as they are visible in the editor. Thus, the above code will remove the button that adds the bold effect to the text.

wp_editor() and “teeny” mode

It may be the case that we decide to use the TinyMCE editor in another place besides the entries editor e.g. in the comments section. Then, the TinyMCE editor is usually invoked in a simplified mode called teeny:

wp_editor( '', 'comment', array(
'teeny' => true,
 'quicktags' => false,
 'media_buttons' => true
 ));

This mode is characterized by the simplified structure of the editor – restricted to just the one row of buttons.

It causes a change in the filters that we use. Instead of mce_buttons, mce_buttons_2, mce_buttons_3 and mce_buttons_4 filters we have just one; the teeny_mce_buttons filter.

Additionally, we may restrict loading plugins in this mode by using the teeny_mce_plugins filter.

So, if we would like to remove the first button from the editor, then we use the following code:

function remove_teeny_mce_btns($buttons) {
 unset($buttons[0]);
 return $buttons;
 }

 add_filter('teeny_mce_buttons', 'remove_teeny_mce_btns');

Several buttons in one – ButtonGroup

It could easily be argued that we’ve overdone it slightly by defining the separate scripts for just two buttons. If we want, we can create two buttons using just the one kind of button – ButtonGroup.

This kind of button has an items feature, which pulls the table that includes the objects defining the buttons:

(function() {
    tinymce.PluginManager.add('gk_tc_button2', function( editor, url ) {
        editor.addButton( 'gk_tc_button2', {
            title: 'My test button II',
            type: "buttongroup",
            items: [
           	        {
           	        	title: 'First button',
           	        	icon: 'icon dashicons-wordpress',
           	        	onclick: function() {
           	        	    editor.insertContent('Hello World I');
           	        	}
           	        },
           	        {
           	        	title: 'Second button',
           	        	type: 'menubutton',
           	        	icon: 'icon dashicons-wordpress-alt',
           	        	menu: [
	           	        	{
	           	        		text: "Item I"
	           	        	},
	           	        	{
	           	        		text: "Item II"
	           	        	}
           	        	]
           	        }
           	    ]
        });
    });
})();

As you can see, we may define any buttons using the one script only. Nevertheless, this solution has the visual problem:

TinyMCE 4 - group button CSS problem

Contrary to appearances, I have not placed the grouping button in the fourth row – it is in this position because of problems connected with styling. I fixed them with the following CSS code added to the style.css file:

.mce-toolbar .mce-container .mce-btn-group {
	display: inline-block;
}

Selection list – Listbox

The alternative for the menubutton is the selection list – listbox. Characteristic elements of the selection list are features such as fixedWidth and values. The first feature is responsible for limiting the displayed content to the appropriate width – the second feature, on the other hand, includes the list elements. Below you may find the example of the selection list adding a list of text generators such as lorem ipsum to the editor:

(function() {
    tinymce.PluginManager.add('gk_tc_button2', function( editor, url ) {
        editor.addButton( 'gk_tc_button2', {
            title: 'My test button II',
            type: "listbox",
            fixedWidth: true,
            text: 'Lorem ipsum',
            values: [{
            	text:'Lorem ipsum',
            	value:'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam dolor lacus, sodales ac massa nec, vulputate tempor libero. In in nunc ut odio ullamcorper venenatis id sed augue. Mauris eget sem aliquam, fermentum metus vitae, dapibus nibh. Ut lobortis egestas congue. In posuere velit vel nisl tincidunt, non mattis augue sagittis. Aenean mattis at enim ac facilisis. Sed dui eros, pretium eget sapien adipiscing, dictum molestie tortor. Aenean consequat accumsan est id vestibulum. Phasellus vulputate tellus ante, ac convallis erat sagittis et. Nulla id risus sed quam vestibulum blandit.',
                onclick: function() {
                    editor.insertContent(this.value());
                }
            },
            {
            	text:'Gangsta lorem ipsum',
                value: 'Lorizzle funky fresh dolor yippiyo amizzle, sheezy adipiscing elizzle. Nullam sapien away, funky fresh volutpizzle, bling bling i\'m in the shizzle, gravida vizzle, uhuh ... yih!. Shit shit fo shizzle. Sed erizzle. Own yo\' izzle dolor turpis tempizzle fo shizzle. Maurizzle black fo shizzle mah nizzle fo rizzle, mah home g-dizzle izzle gizzle. Crunk izzle tortizzle. Pellentesque bling bling uhuh ... yih! crackalackin. In hac break it down platea dictumst. Black daahng dawg. Curabitizzle yippiyo things, pretizzle black, mattis go to hizzle, eleifend vitae, nunc. Yo mamma suscipizzle. Integizzle semper velit go to hizzle.',
            	onclick: function() {
                    editor.insertContent(this.value());
                }
            },
            {
            	text:'Veggie ipsum',
            	value: 'Veggies es bonus vobis, proinde vos postulo essum magis kohlrabi welsh onion daikon amaranth tatsoi tomatillo melon azuki bean garlic. Gumbo beet greens corn soko endive gumbo gourd. Parsley shallot courgette tatsoi pea sprouts fava bean collard greens dandelion okra wakame tomato. Dandelion cucumber earthnut pea peanut soko zucchini.',
                onclick: function() {
                    editor.insertContent(this.value());
                }
            }]
        });
    });
})();

As you can see, the content of list of elements is very similar to the list that is used in a submenu button.

The effect is as follows:

TinyMCE 4 - listbox

Adding the TinyMCE Editor to the Comments Section

It may be that you wish to display a WYSIWYG editor instead of the standard comments editor in the comments section. Fortunately, we can achieve this very easily with just a slight modification to the functions.php file of our theme.

To start, we just need to add the following fragment of code:

function gk_comment_form( $fields ) {
    ob_start();
    wp_editor( '', 'comment', array( 'teeny' => true ));
    $fields['comment_field'] = ob_get_clean();
    return $fields;
}
add_filter( 'comment_form_defaults', 'gk_comment_form' );

As you can see, we use the commentformdefaults filter as well as the function to catch the output in PHP. As a result, we are able to replace the standard field with the content of the TinyMCE comment editor.

Another important thing is the use of TinyMCE’s teeny mode. This mode allows you to display a simplified version of the editor.

Of course, the code presented above is a very basic configuration, which will display the editor in its base form, as shown below:

As you can see we will need a few amendments to make the editor look more presentable and functional. Let's start with the size of the editor – by default it displays 10 lines for the text-editing area, as seen in the screenshot above; this is too much for most people. Thankfully, we need only change the wp_editor function to the following:

wp_editor( '', 'comment', array(
'teeny' => true,
'textarea_rows' => 5
));

To reduce the number of text lines to 5 using the textarea_rows option. Thanks to this changed, the editor looks much better:

Another issue is the ability for users to insert images – most often we won’t want our users to take up too much space on the server with unnecessary additional resources, so it’s worth disabling the button for adding media – to do this we may use the media_buttons option:

wp_editor( '', 'comment', array(
'teeny' => true,
'textarea_rows' => 5,
'media_buttons' => false
));

Our editor is already starting to look quite neat once this item is removed:

There is a small visual issue here – one of the icons does not fit with the width of the comments area – so you’ll have to throw away the least needed button – personally I would remove the button that adds the strikethrough to the text; to do this we’ll use the mceteenybuttons filter and remove the fifth button from the list:

add_filter( 'teeny_mce_buttons', 'gk_comment_form_no_strikethrough');
function gk_comment_form_no_strikethrough($buttons) {
	unset($buttons[4]);
	return $buttons;
}

Thanks to the above modifications, our editor now looks neat and tidy and takes up the minimal space:

There remains one more addition – fullscreen mode, which by default looks like this:

We may also use Distarction Free Writing mode by adding another option – dfw:

wp_editor( '', 'comment', array(
'teeny' => true,
'textarea_rows' => 5,
'media_buttons' => false,
'dfw' => true
));

Which makes the full-screen mode look and feel slightly better, at least in my opinion!

It has a visible way to return to the normal editing mode, unlike the standard full-screen mode, which can reduce confusion.

Finally, if we wanted to reduce the size of the editor even further we could remove the tab with the choice between WYSIWYG mode and text – for this purpose we may use the option quicktags:

wp_editor( '', 'comment', array(
'teeny' => true,
'textarea_rows' => 5,
'media_buttons' => false,
'dfw' => true,
'quicktags' => false
));

The result is the most stripped-down version of the WYSIWYG editor possible in the comments:

Adding Buttons to Fullscreen Mode

WordPress has for some time offered a full-screen mode when creating posts or pages, which allows you to focus solely on writing (in some editors this mode is called “Zen mode” or simply “Distraction Free Writing”). If you or your users are interested in utilizing the full-screen option, it’s worth learning how to add your own buttons to this mode of the editor to enhance or simplify the writing experience. However, we must stress that adding buttons to the full-screen editor is quite different to adding buttons to the standard TinyMCE editor.

Let’s start with the basic framework of the plugin:

add_action('admin_head', 'wordup_add_fullscreen_button');
add_action('admin_enqueue_scripts', 'wordup_add_css');
function wordup_add_fullscreen_button() {
  global $typenow;
  // sprawdzamy czy user ma uprawnienia do edycji postów/podstron
  if ( !current_user_can('edit_posts') && !current_user_can('edit_pages') )
    return;
  // weryfikujemy typ wpisu
  if( ! in_array( $typenow, array( 'post', 'page' ) ) )
    return;
  // sprawdzamy czy user ma włączony edytor WYSIWYG
  if ( get_user_option('rich_editing') == 'true') {
     add_filter( 'wp_fullscreen_buttons', 'wordup_add_button_to_fullscreen_editor' );
  }
}
function wordup_add_button_to_fullscreen_editor( $buttons ){
    return $buttons;
}
function wordup_add_css() {
    wp_enqueue_style('wordup-tinymce', plugins_url('/style.css', __FILE__));
}

In fact, the above code is very similar to the code that we used when creating standard plugins for TinyMCE. The main difference is the following line:

add_filter( 'wp_fullscreen_buttons', 'wordup_add_button_to_fullscreen_editor' );

Which is responsible for adding our button – as you can see we’ve used the wpfullscreenbuttons filter instead of the standard one: mce_buttons.

The big differences don’t become noticeable until we start defining the button – we add our button by creating an appropriate associative array:

function wordup_add_button_to_fullscreen_editor( $buttons ){
    $buttons['IKONA'] = array(
        'title' => 'NAZWA',
        'onclick' => "AKCJA",
        'both' => false
    );

	return $buttons;
}

As we can see the above definition of the button includes its icon name, which is also the name of the button and its identifier in the list of full-screen buttons in the editor. The title field defines the hint which will be displayed when the cursor hovers on our button. In the onclick field we define the JavaScript code which will be run after the button is clicked – due to this we won’t use an external JS file; instead, we will define the button’s behavior just once, in the array. The last field, both, is a flag that determines whether our button will be visible in both editor modes – either both the visual and text mode, or just visually.

Let’s start with the basic version of the button working only in the editor’s visual mode:

function wordup_add_button_to_fullscreen_editor( $buttons ){
    $buttons['icon dashicons-wordpress'] = array(
        'title' => 'WordPress button',
        'onclick' => "tinyMCE.activeEditor.insertContent('Hello World!');",
        'both' => false
    );
    return $buttons;
}

We wrote the above code bearing in mind the fact that my base plugin code includes an instruction to get icons from Dashicons; that’s why I named my plugin icon dashicons-wordpress. We achieve access to the editor with a tinyMCE.activeEditor object, which is an alias for the tinyMCE.editors[0] object. After loading the plugin our full screen editor looks as follows:

But what if we want our button to appear in the text-mode of the full-screen editor? It would initially seem that you’d only need to replace the both flag with true:

function wordup_add_button_to_fullscreen_editor( $buttons ){
    $buttons['icon dashicons-wordpress'] = array(
        'title' => 'WordPress button',
        'onclick' => "tinyMCE.activeEditor.insertContent('Hello World!');",
        'both' => true
    );
    return $buttons;
}

But after making this change, our button actually appears in the second tab and does not work when we click it. This is due to the fact that the text mode does not use the TinyMCE editor, so it requires additional manual JavaScript code to handle the action on click. The proper code of the text editor should instead be as follows:

function wordup_add_button_to_fullscreen_editor( $buttons ){
    $buttons['icon dashicons-wordpress'] = array(
        'title' => 'WordPress button',
        'onclick' => "if(tinyMCE.activeEditor) {
          tinyMCE.activeEditor.insertContent('Hello World!');
        } else {
          var cursor = jQuery('#content').prop('selectionStart');
          if(!cursor) cursor = 0;
          var content = jQuery('#content').val();
          var textBefore = content.substring(0,  cursor );
          var textAfter  = content.substring( cursor, content.length );
          jQuery('#content').val( textBefore + 'Hello World!' + textAfter );
        }",
        'both' => true
    );
    return $buttons;
}

First of all, we check whether the tinyMCE.activeEditor object exists – after switching to a text editor, this object is empty which allows us to easily tell if the full screen editor mode is activated. Then, we use the JavaScript API that allows us to read the cursor position in the textarea field, which in the case of a full screen editor has a content ID. Based on the position of the cursor, we may now divide the content of a text field to two strings – before and after the cursor. Then we insert our text between them and the resulting text is placed back in the box.

Enabling the StyleSelect Control

The styleselect control, which allows easy formatting of the selected text, is hidden by default in the TinyMCE editor. The reasoning behind this decision is that the control duplicates the functionality of the other buttons and is thus superfluous. However, with a little bit of modification, it can be used for your own purposes.

Let’s start from the beginning; activating the styleselect control. All you need to do is use the filter mcebuttons2 and add the styleselect element to the top of the list of buttons:

add_filter('mce_buttons_2', 'gk_activate_styleselect');
function gk_activate_styleselect($buttons) {
   array_unshift( $buttons, 'styleselect' );
   return $buttons;
}

As a result, a new selection list will appear in the editor:

Looking at the content, we can see that many of the available styling methods are combined with the default styling formats, which makes everything a little hard to keep track of. Fortunately, we may easily change it, making this control the easiest way for wrapping a selected text fragment with your own HTML tags.

To do this we need to modify the default settings of the TinyMCE editor using the tinymcebefore_init filter:

function gk_own_styles($config) {
    $temp_array = array(
        array(
            'title' => 'Testimonial',
            'block' => 'blockquote',
            'classes' => 'testimonial'
        ),
        array(
            'title' => 'Info block',
            'block' => 'p',
            'classes' => 'info-block'
        )       
    );
    $config['style_formats'] = json_encode( $temp_array );
    return $config;
}
add_filter('tiny_mce_before_init', 'gk_own_styles');

As you can see in the style_formats settings we define our own array in the JSON format. Each element of the array contains three main properties – the name of the submenu item (title),the name of the HTML tag (block) and the CSS class to be added to this marker (classes).

In effect, we we have a selection list with our own definitions:

Now, when you select some text and click a styling method in HTML we may see the effect of the styleselect control:

Enabling Other Buttons Hidden By Default

In the entry connected with the styleselect I explained how to enable this disabled by default button. TinyMCE has lots of other buttons disabled in this ways. In this entry I will show you how to enable them.

Well, it is enough to add to the table with the list of buttons the string of characters with the name of a hidden button:

function dziudek_tc_more_buttons($buttons) {
    array_push($buttons, 'fontselect');

    return $buttons;
}
add_filter("mce_buttons_3", "dziudek_tc_more_buttons");

In the above example, we activate the fontselect button in the third line of buttons, which allows us to choose the typeface used in the selected text:

tinymce-hidden-buttons-1

Above, you may find a list of disabled in this way buttons (I omitted visualaid button, as it seems not to work at all):

fontsizeselect

Another control associated with the typeface – this time with its size:

tinymce-hidden-buttons-2

styleselect

The control already known from another entry.

backcolor

This control allows us to specify the background color under the text:

tinymce-hidden-buttons-3

newdocument

Thanks to this control, we may quickly clear the content of the editor – all the entered text will disappear after clicking on it:

tinymce-hidden-buttons-4

cut i copy

These two controls, which as the name suggests, are associated with cutting and copying text, unfortunately will work only in those browsers that can access the clipboard through the JavaScript API:

tinymce-hidden-buttons-5

charmap

After clicking on this control, the table of custom characters will appear:

tinymce-hidden-buttons-6

hr

The control which allows to insert a horizontal line marker to the text:

tinymce-hidden-buttons-7

Summary

As we can see, most of these controls are disabled – most of them do not offer useful functionalities. In my opinion, the only controls that are notable are as follows:

  • charmap – useful if you cannot remember all HTML entities,
  • hr – if you are using the HR tag as a visual separator in your articles

Other controls can be useful only if we have a very stubborn customer, who wants to be able to easily control the style of the text inside the editor without the use of CSS code (I strongly discourage, but we have our ups and downs). Cut, copy and newdocument are basically controls only for those who are not able to acquire the keyboard shortcuts, but I hope that they are a small fraction of WordPress users.

Adding Form Validation to a Popup

When creating a popup with settings that is assigned to one of our buttons in the TinyMCE editor, it is prudent to implement data validation in the popup’s fields to prevent a user from entering invalid or incorrect data. A simple data validation check can easily be created, though if you also want to highlight the incorrect fields to help the user fix the data then a little more effort and workarounds will need to be employed.

tinymce-popup-validation

We’ll start with our base code – let’s say that our popup comes with two fields: width and height; and that they have the onsubmit action defined in their functionality in the following manner:

onsubmit: function(e) {
    editor.insertContent('Lorem ipsum: ' + e.data.width + ' x ' + e.data.height + '.');
}

The implementation of basic validation in this situation is very easy – we check values of fields and depending on criteria fulfilled, we send data from a popup or not using return false, for blocking sending a popup:

onsubmit: function(e) {
    if(e.data.width === '' || e.data.height === '') {
        return false;
    }
    editor.insertContent('Lorem ipsum: ' + e.data.width + ' x ' + e.data.height + '.');
}

Unfortunately, this validation method has a serious issue; a user will not know why there form was not sent, and can’t fix any issues. Therefore, we should display an appropriate message – we may use an alert function or, even better, use a message window that is built-in with TinyMCE:

onsubmit: function(e) {
    if(e.data.width === '' || e.data.height === '') {
        editor.windowManager.alert('Please, fill in all fields in a popup.');
        return false;
    }
    editor.insertContent('Lorem ipsum: ' + e.data.width + ' x ' + e.data.height + '.');
}

After seeing such information a user should be aware that something is wrong with the data inserted in the fields, but it is worth highlighting the incorrect fields so that the user knows exactly what needs correcting. In order to make it work, we will have to create a more sophisticated code that will allow us to add a frame around elements that are incorrect.

I have searched for an elegant solution to this issue, but it unfortunately was not possible to achieve without utilizing some object’s properties that, based on their names, should be private. From what I could gather, there is no more convenient method available.

We need a handle for the form fields displayed in a popup, so let’s start with that. To achieve this, we’ll have to make a request to a built-in feature that returns the ID of the displayed popup:

var window_id = this._id;

With this ID, we may now load the fields of the form:

var inputs = jQuery('#' + window_id + '-body').find('.mce-formitem input');

Now we have handles for the form fields, we may assign a border-color to them:

if(e.data.width === '') {
    $(inputs.get(0)).css('border-color', 'red');
}

In the above example, we’ll add a red frame to the first text field in a form.

To keep things clear for the user, we might want to make a frame disappear from the field once it is clicked, so we change:

{
    type: 'textbox',
    name: 'height',
    label: 'Height'
},

to:

{
    type: 'textbox',
    name: 'height',
    label: 'Height',
    onclick: function(e) {
        jQuery(e.target).css('border-color', '');
    }
},

Unfortunately, from my observations it seems that the onclick event is the only one that works – so we cannot use the onblur or onfocus events.

Once we’ve done all these steps, our onsubmit code may look as follows:

onsubmit: function(e) {
    if(e.data.width === '' || e.data.height === '') {
        var window_id = this._id;
        var inputs = jQuery('#' + window_id + '-body').find('.mce-formitem input');

        editor.windowManager.alert('Please fill in all fields in a popup.');

        if(e.data.width === '') {
            $(inputs.get(0)).css('border-color', 'red');
        }

        if(e.data.height === '') {
            $(inputs.get(1)).css('border-color', 'red');
        }

        return false;
    }
    editor.insertContent('Lorem ipsum: ' + e.data.width + ' x ' + e.data.height + '.');
}

What if we need more events for form elements?

It is clear that the default events in TinyMCE do not give us much freedeom to create diverse popups with complex logic. Luckily, there is a workaround we can use if we need to an additional event e.g. onblur or onfocus to our fields.

A popup created in TinyMCE requests the repaint event at least twice – by hooking on to this event we can overcome some of the limitations of our popup.

Here’s an example of such an implementation, where we add the onfocus and onblur events to the first field in a form:

onrepaint: function(e) {
    var window_id = this._id;

    if(!jQuery('#' + window_id).hasClass('form-initialized')) {
        jQuery('#' + window_id).addClass('form-initialized');

        var inputs = jQuery('#' + window_id + '-body').find('.mce-formitem input');

        jQuery(inputs.get(0)).blur(function() {
            console.log('blur');
        });

        jQuery(inputs.get(0)).focus(function() {
            console.log('focus');
        });
    }
},

I would like to make you aware at this point that requesting the repaint event a few times is a sensitive matter – therefore, in the above code I created a simple mechanism for checking whether it was requested once only. After the first request of this function, there is a form-initialized class that is added to the popup that prevents our code from being requested again. Thanks to this, we will avoid among other things problems with double-added events.

By using the above method, we may create diverse logic for our form in a popup. The main burden we must deal with is access to the form’s fields – various fields types have various classes and we not only have to select everything correctly, but also use it appropriately too.

It does not change the fact that creating validation for TinyMCE popup content is possible, however, in the case of more complex forms, it requires complex code to overcome since the TinyMCE API is lacking in this regard.

The End…For Now

This tutorial is huge, complex, and took a very long time to write, yet it only scratches the surface of the TinyMCE API. We’ll continue to experiment with the editor, and add any new information here so that it can be shared with the world! We hope this tutorial has proven useful, and if there’s something you’d like us to look at in a future article just leave a comment and we’ll see what we can do.

WordPress TinyMCE Editor Tips | How to Add Custom Buttons, Styles, Dropdowns & Pop-ups 4.845 (96.78%) 87 votes
Share
This article was first published October 6th, 2014
  • Shamai

    This is amazing stuff!! i made a button that allow for adding divs of columns. but its hard to exit a column when you are in one. know how i can make it clickable or get you outside the column div. sometimes pressing enter twice jumps out of it.

  • sha

    Thanks a lot for this amazing tutorial. It’s clear and useful. Thanks again!

  • TATAR

    It was very helpful.But I have a question
    I’ve added the font selection button, and a list of desired fonts have been added.
    I want when I click on a font from the list of fonts, a style sheet to be added to the header.
    For example, when I click on the “Open Sans” font, style sheet below to be added to the header.

    And when I click on the “Abel” font,style sheet below to be added to the header:

    And so

  • KatArt Graphics

    Great post! Is there a list of the default TinyMCE icons or the default WordPress TinyMCE icons? I noticed in your example you use ‘wp_code’ which I assume is a WordPress version of the TinyMCE icon ‘code’. I think I know how to call the default TinyMCE icons, but where do I find the default WordPress icons?

  • Mark Kaplun

    Wow this truly rocks, not only the best tutorial out there, (kind of easy) but very complete. Saved me at least a day maybe two of hard work if I had to piece all the information by myself.

  • L. F.

    I get this error: custom.js:113 Uncaught ReferenceError: tinymce is not defined, any thoughts as why this is occuring

    here is the code I am using:
    // button short code text editor

    tinymce.PluginManager.add(‘gavickpro_tc_button’, function( editor, url ) {
    editor.addButton( ‘gavickpro_tc_button’, {
    title : ‘Add a theme button’,
    type: ‘menubutton’,
    text: ‘Theme button’,
    icon: false,
    menu: [
    {
    text: ‘Add a theme button’,
    onclick: function() {
    editor.windowManager.open( {
    title: ‘Insert button info’,
    body: [{
    type: ‘textbox’,
    name: ‘url’,
    label: ‘Link URL’
    },
    {
    type: ‘textbox’,
    name: ‘button_text’,
    label: ‘Button Text’
    },
    {
    type: ‘listbox’,
    name: ‘style’,
    label: ‘Button Style’,
    ‘values’: [
    {text: ‘Blue’, value: ‘btn’},
    {text: ‘Green’, value: ‘btn-2’}
    ]
    }],
    onsubmit: function( e ) {
    editor.insertContent( ‘‘ + e.data.button_text + ‘‘);
    }
    });
    }
    }
    ]
    });

  • Ben Lowbridge

    Very good tutorial. It helped me quite a bit!

    However, I am having trouble with getting the icons to load on my submenu. I am following exactly with that section of the tutorial. Is there any other way of doing this?

    • Ben Lowbridge

      I have it sorted thanks to Jean Sébastien Teitgen

  • Jonathan Wilson

    Your class names makes me want to gag. “wordup_add_button_to_fullscreen_editor”, and “gavickpro-own-icon” seriously dude? Are you trying to make it hard to follow along. How about just “myIcon” or “myButton” so I can concentrate of what you are doing instead of concentrating on keeping you class names strait. Keep it simple. That said. Thanks for the help

  • Jean Sébastien Teitgen

    Hi ! Where can i find a list of available wp icons as dashicons classes don’t actually work for tinymce (e.g.:

    dashicons-tag )? Thank’s

  • I’m having issues adding the buttons — I follow the tutorial exactly, but I get a blank bar in the editor, and TinyMCE never loads. When I remove the custom code, everything is fine. What is the cause of this?

  • Naruto

    Thanks!

  • I have a similar issue, how could I add the custom buttons to the comment form?

  • Jvandemerwe

    This is a great tutorial. It really helped me to understand how to implement some new buttons in my WordPress website. Thank you.

  • talha1989

    Such a nice Tutorial. Used it. Thank you very much.

  • Hi thanks for the very in-depth tutorial. But I’m having issues with the code. When I tried it, I lost all access to the visual editor. I could still see the code in the text editor, but the visual part was blank.

    • I’m having this issue as well. Any luck in resolving it?

      • Christiano da silva

        Check if your plugin.js file is loaded at all. Maybe try to change “plugins_url( ‘/text-button.js’, __FILE__ );” to “get_template_directory_uri() . ‘/text-button.js’; – That solved it for me.

    • Mikołaj Śliwiński

      Check errors in developer tools in your browser. In chrome f12 -> console tab.

  • Great work. Any thoughts on how to replace the native modal window with a Twitter Bootstrap modal window?

  • Lay

    This tutorial is amazing, completely solved my questions!

  • 0Neji

    Fantastic article. I’m using it to create a ‘Shortcodes’ button plugin which can be set up via PHP using a simple array.

    I do have one quick question on this – is there a list of the field ‘types’ available? So atm, I’ve seen that there is ‘textbox’ and ‘listbox’, possibly ‘checkbox’ – but how much flexibility is there? What other fields are available?

    I’m pretty sure it won’t be available but I have the idea of using a post search field within the model that pops up, I think I’d need to extend this myself but it would be awesome if it was already available.

  • I’ve seen a couple of others ask this question, but no response. Hoping to get some assistance:

    CAN the TinyMCE custom buttons be added to the text mode of the editor as well as the visual? I want to be able to add in shortcodes. But I have some code on certain pages that preclude me from being able to use the visual editor (it strips my code, rendering it useless), so I have to remain in text mode at all times.

  • Great article. Do tinyMCE have any way to use fieldsets? I’m working on a plugin to embed Google Maps and there are lots of fields, I’m not happy with the mess of buttons and fields.

  • Richard Light

    Hi, your hint on how to get a handle on the form elements is really useful – although presumably at the mercy of any future rewrites. I was hoping to use this information to update elements of the form based on user selections, but I can’t see any way to alter a form control value, once it has been specified in the body array when opening the window. It would be ideal if the form controls were updateable objects.

    Anyway, I have addressed my problem by making initial choices on a first dialogue, and then getting it to create a second dialogue based on those choices.

    Couldn’t have done it – or even got close – without your help.

  • bilal ahmad

    Hi,
    can anyone let me know how to create checkbox dynamically means create multiple checkbox field ?. Hope fully you guys help me.

    Thank

  • Mike Alexeenko

    Thank you for such a detailed explanation with screen shots and examples.
    You`ve made my working day much easier and saved much efforts.

  • Ben Ben

    Amazing! Is it possible to make those custom buttons show also on the front-end (with rich text form fields for example)?

    • I’m curious about this as well. Getting it to display on bbpress and comments would be a lifesaver.

    • THW

      I am running WP 4.5.3 with bbPress. I, too, would like to know what has to be done. I tried using the TeenyMCE but this didn’t work either.

      Would it be an addition to the child-theme/functions.php or would this want to be added to the plugin’s code somewhere?

      You say to do the following for Teeny but I am uncertain what to do to get it into bbPress.

      wp_editor( ”, ‘comment’, array(
      ‘teeny’ => true,
      ‘quicktags’ => false,
      ‘media_buttons’ => true
      ));

      Also, would we need to add a line like or is it already considered this due to the code’s nature?

      ‘tinymce’ => true,

  • Hey, thanks for that awesome tutorial.
    I have no idea why, but for some reason it does not work for me at all :( after implanting the code all my editor buttons just vanish along with existing editor content. any ideas?
    *All plugins are deactivated, so there is no conflict.

    • I have the exact same issue. Did you ever come to a resolution on this?

  • Alessio Ragni

    Oh my god! This post is amazing! Thanks gavick you save my life today :)

  • Ronz

    Is it possible tu add a button for shortcode with parameters that depends on a plugin ?
    For exemple chose the id of a post. Having a list of post when clicking on button and select from list the good value for the shortcode to finaly get [shortcode=”123″] where 123 is the id of the post selected.
    Maybe it is possible to register the *.js with a *.php who will generate the js code ?

    • Hello,

      It won’t be possible in many cases, because while creating a new post item it’s ID is unknown

  • Please make sure if your comments allows the html tags, because it seemst that they are filtered before publishing a comment.

  • How can I add color picker to Added pop up window?
    No You have:

    editor.windowManager.open(
    { title: ‘Insert header tag’,
    body: [{
    type: ‘textbox’, name: ‘title’, label: ‘Your title’ },
    { type: ‘textbox’, name: ‘id’, label: ‘Header anchor’

    etc.

    I’d like to ue header anchor as color picker.
    How can I do this? Is this even posible?
    Cheers :)

    • Hello,

      Unfortunately as I remember using the color picker control in the tinymce is not easy and will need probably a lot of custom JS code :/

  • Hi!

    This is absolutely fantastic. I am wanting to use something similar in my own plugin, but am coming stuck on one point. In section 9 (https://www.gavick.com/blog/wordpress-tinymce-custom-buttons#tc-section-9) you add a drop down menu to the popup. Do you know if it is possible to add a drop down menu that uses a post type as its data source? So, if I wanted to include a staff member profile, for example, it would list all of the posts in my “staff-member” custom post type, and I could select the one I wanted? I have found a near identical tutorial, but that is missing that same titbit of information. Any assistance would be fantastic.

    • Hello,

      The only idea which I have is creating a PHP code which will create a global JS code with object for the dropdown and then inject this object instead of array in the configuration.

  • Hello,

    As I remember it was possible to use more controls from this list (not all but some of them worked): http://www.tinymce.com/wiki.php/api4:namespace.tinymce.ui

  • We are using the BR tag and it is working fine – it creates new lines:

    [ulist style="4"]item1item2item3[/ulist]

  • Juan

    Great great tutorial,
    Question: I see that you are using two different form fields on your managerWindow, one is textbox, the other is listbox. Are there more kind of form fields I could use? I have been searching but couldn’t find anything about it.
    Thanks in advance!

  • SoaresPT

    Thanks for the amazing tutorial!! I’ve been searching this for quite some time and finally found a simple way to do it :D I got a question though i wanted to make the button insert the JW Player embed code. Something like this:

    //Starts here

    jwplayer(‘playeroebgkxXeMSjP’).setup({
    file: ‘url-to-movie’,
    });

    //End here

    Ok ignore the comments of course :P But I think when there’s lots of ‘ and ” it breaks the code. Is there any way to do this? Thanks!

    • Hello,

      Did you tried to escape the quotes inside the code by changing it to ” or ‘ ?

      • SoaresPT

        Yeah gonna give that a try :D Also how do you insert a blank line? I’ve tried

        editor.insertContent(”);
        editor.insertContent(”);

        The first one doesn’t do anything the second one inserts an html code. I wanted to make it formatted inseat of making the button write everything in 1 line.
        Thanks

  • Could you provide me a live example of this issue?

  • Curvinho

    Thanks for the awesome tutorial, it helped a lot with my website.
    I just have one issue now.
    Since wordpress updated for 4.1 the tinymce in the comment section (added as you’ve showed here) is having its contents removed (all html, as far as I’ve noticed) upon submission.
    Now I’m losing all paragraphs and customization, such as lists, headings and such.
    I was wondering ig you knew a solution for that?

  • A much cleaner way is to use the ‘media_buttons’ hook and create another ‘Add Media’ type button. Far less javascript involved and the button is then available in both Visual and Text tabs and Comments by default. You can even have it automatically create the list of shortcodes from any registered shortcodes in the $shortcodes_tags array with a simple foreach loop.

    See…
    http://wpsnipp.com/index.php/functions-php/update-automatically-create-media_buttons-for-shortcode-selection/

  • Matt

    This doesn’t seem to work for me…. don’t seem to be getting any syntax errors but for some reason the TinyMCE visual editor doesn’t seem to be displaying anymore only the text editor seems to be working, any ideas?

    • I have the same problem of a totally blank editor dashboard in WP-admin. Any ideas why this is happening?

  • Thank you for the informative article. This is along the lines of what I have been looking all over the web for. I have a couple questions at this time.

    You mention the “Visual” editor. Does this also add the button to the Text editor? If not, can you point me in the right direction to add a button to the Text Editor side (or preferably both.)

    Also some of the code at Adding the TinyMCE Editor to the Comments Section and below seems to have been converted to &gt and &lt etc. is this done on accident?

    Thank you again for your time and knowledge that you have shared.

  • I’ve described the selected text wraping into HTML in my article: http://dziudek.pl/wtyczki/tinymce-zarzadzanie-stanami-przyciskow – please use google translate to translate it from polish.

  • I think that you should consult this issue with the plugin author – because most probably it is a problem with the plugin code.

  • Excellent and very complete tutorial !
    It is a bit sad some code snippet contains html entity that we have to convert (exemple

    wp_editor( '', 'comment', array(
    'teeny' => true,
    'textarea_rows' => 5,
    'media_buttons' => false,
    'dfw' => true
    ));)
    but very nice article anyway :D

    EDIT : How would you wrap selected text into JTML elements without pop ups ?

  • cupi

    Hi,

    very good tutorial! I miss one thing. How can I get the button to widget area with black studio tinymce? By post and page editor in visual mode I can see my button, but by widget visual editor not. What do I have to add and where?

    Many thanks for reply!

    • Hello,

      Could you better explain your issue?

      • cupi

        I have an extension plugin Black Studio TinyMce which is good for text editing in widget area. I miss there a button (shortcode) which I created according to this manual. This button is normally visible in posts or pages editing Tinymce editor. I was surprised, when could I see my button in posts and pages (heading of tinymce control line) heading area, but not in a widget area, where I use Black Studio TinyMce. For example I can see other buttons in widget area like from plugin Easy Bootstrap Shortcode. I could not find the way to see my button visible also in widget area.

        Here had somebody same Problem, which was fixed from Youtube plugin author. I could not find the diffrence to my code, what am I missing for button support in widget area?

        Question is, when you install Black Studion TinyMce plugin, can you see your shortcode button in widget area. I know my shortodes are supported, but only the button not visible.

        Nothing more than this code I have in my plugin:
        add_action(‘admin_head’, ‘pepa_add_my_tc_button’);

        function pepa_add_my_tc_button() {
        global $typenow;

        if ( !current_user_can(‘edit_posts’) && !current_user_can(‘edit_pages’) ) {
        return;
        }

        if( ! in_array( $typenow, array( ‘post’, ‘page’ ) ) )
        return;

        if ( get_user_option(‘rich_editing’) == ‘true’) {
        add_filter(“mce_external_plugins”, “pepa_add_tinymce_plugin”);
        add_filter(‘mce_buttons’, ‘pepa_register_my_tc_button’);
        }
        }

        function pepa_add_tinymce_plugin($plugin_array) {
        $plugin_array[‘pepa_tc_button’] = plugins_url( ‘/pepa-anim.js’, __FILE__ );
        return $plugin_array;
        }

        function pepa_register_my_tc_button($buttons) {
        array_push($buttons, “pepa_tc_button”);
        return $buttons;
        }

        add_action(‘admin_enqueue_scripts’, ‘pepa_tc_css’);
        function pepa_tc_css() {
        wp_enqueue_style(‘pepa-tc’, plugins_url(‘/style.css’, __FILE__));
        }

        add_filter( ‘mce_external_languages’, ‘pepa_add_my_tc2_button_lang’);
        function pepa_add_my_tc2_button_lang($locales) {
        $locales[‘pepa_tc_button2’] = plugin_dir_path ( __FILE__ ) . ‘translations.php’;
        return $locales;
        }

  • Very good!

  • Wow, this is exactly what I needed! Thanks for the extremely thorough write up!

  • rase;

    first of all you have make an awesome post actually it’s a life saver for me.
    Can you help me please.By following your this article ii have successfully able to add text and more.
    but can you show us how to add a image upload inside this popup and add uploaded file to tinyMCE editor please please please.

    • Dziudek

      Sorry but it is a topic for a separate article, and currently I’m too busy to write it :/

  • Great tutorial. Worked perfectly!
    For anyone interested in using a custom icon using a font. I used my own custom icon by building a font on FontStruct then added the icon using this in my CSS :
    @font-face {
    font-family: ‘myfont’;
    src: url(‘../../fonts/myfont.ttf’) format(‘truetype’);
    font-weight: normal;
    font-style: normal;
    font-variant: normal;
    }
    i.myfont-button-icon:before {
    font-size: 24px;
    font-family: ‘myfont’;
    content: ‘6d’; /* represents the lower case ‘m’ */
    }
    Since there was only one glyph in the font. It downloads as fast as a PNG but allows more flexibility.

    In the Javascript:

    icon: ‘icon myfont-button-icon’

  • Dimitri

    very useful tutorial.

    I have one question about editor.addButton and value string. How to have line breaks in value.

    I’d like to ouput in wp editor like:

    [shortcode]
    [shortcode_1]
    [/shortcode_1]
    [/shortcode]

    i try with /n in value strings, but doesn’t work, if someone have tips.

    Thanks

  • tatti vitorino

    Dziudek, I already replied here thanking you for this awesome tutorial, and I’d like to apologize for any language mistakes as english is not my native language.

    What I want now is to share what I as able to achieve with the knowledge you provided us and to help others that may run into the same problems I did when implementing the functionalities I needed for my project.

    I created a Plugin ( https://github.com/tattivitorino/wp_custom_button_shortcode ) that adds a shortcode for a Custom Button. This button needed a few styles and a link to a file for download, meaning a regular tag with classes, href and an tag for the icon.

    The Plugin does the follow:

    1. Creates a button in the TinyMCE Editor toolbar which has a custom icon that is similar to the final button
    2. This button opens a popup window with the settings for the final button ( the
    tag class, the tag class and href file)
    3. In the popup I was able to add a button that opens the WP Media Library and after selecting, the file url shows in the next textbox
    4. Closing the popup a wp.mce.view is created in the editor area to show the final button itself, not the shortcode

    The main problem I had was the TinyMCE Documentation which is horrible, horrible, horrible! I wanted to check the list of options we can send as args for the body object in the popup options (textboxes, listboxes, buttons, checkboxes), they simply does not show these anywhere in the Docs. I could only do what I did with the help of many other tutorials and articles over the web. Starting from this one!!!

    So, anyway, my intention is not publishing this plugin as you will see I didn’t internationalize it and I also know the code maybe could be better organized (yes, I am quite new to WP) but I just wanted to share this knowledge with you and even help someone in need.

    In the source code you will find a readme.txt with more details as well as the most relevant articles and tutorials I utilized. I also tried my best commenting the code so everything is clear when someone reads the sources.

    My best Regards!!
    Tatti

  • Shmoo

    Hello this is a long post with lots of features and information, thanks for that :)

    Just curious is there also a possibility to ‘grab’ something that is selected inside the editor windows let’s say text or an image and while selected, if you press a custom button the selected area will get wrapped between a div element while the selected content stays the same.

    I would like to create a two column promotional div that people can use by just selecting the content the want to wrap in inside the left or right column.

    Thanks,

  • Dziudek

    You have few ways i.e.:

    * generate the button script in your PHP file instead of using separate JS file
    * generate a JSON file via PHP and then load it in your script
    * transfer data using the translation objects.

    • Ale

      Thank you, really thank you very much, helped me a lot !!!

    • Ali

      Hi, can you describe the first way please? (with a simple example)

      • Sorry but deeper describing it is a place for a specific article not a comment.

  • Ale

    Hello, thank for this info. if I want to pull information from php in my button??

  • tatti

    hi, i am new to WP and this is an awesome tutorial, thank you sooooo much for your time and effort to share this knowledge with us!!!!!

  • piet

    Hello, thank for this great tip, but is it compatible for Joomla, or it is just for WordPress ?

    Regard.

    • Dziudek

      It is only for WordPress.

  • Thank you so much for this walkthrough. Very well done and incredibly helpful.

  • romi

    You use the tinymce editor buttons, but if i need a button above the editor, beside the media button, how do i make it to open the menu?


    // Add button above the editor
    function register_button_above_the_editor() {
    echo 'Some button';
    }
    add_action( 'media_buttons', 'register_button_above_the_editor' );

  • Dziudek

    Hello,

    Sorry but I don’t understand – why do you want to use a PHP variable in the JS code?

  • Lucho

    First of all, thanks you for the hard work!

    It’s great to have updated information!

    I’ve tried you code for adding a button but i came across with an error in your code and wanted to share with you so you tell me if i’m wrong.

    In the .js when you create the button’s view you use:

    tinymce.PluginManager.add(‘gavickpro_tc_button’, function( editor, url ) { …

    instead of “gavickpro_tc_button”, you should use the string you set on your $plugin_array[‘gavickpro_tc_pro’]. Or i’m missing something.

    Thanks you again for this big effort.

  • DomainN

    In Detail Description ! Great Work !

    How to Declaring a new TinyMCE button in WordPress theme ?

    How to declare the script path in WordPress theme?

    • I just did it like I would include CSS files in my theme. Follow the functions.php code as above, and when it comes to the mce_external_plugins filter, do something like this:

      $plugin_array['larks_column_buttons'] = get_template_directory_uri() . '/js/admin_mce.js';

  • Thank you so much for this! Very comprehensive explanations.

  • George

    Thank you for this exhaustive article.

    Great work!

    It allowed me to simplify a lot of the code I am using for adding the editor in the comments area.

    What has me stumped is adding the editor in the messages textarea of Buddypress.

    The editor is added just fine, and the message goes through on submit, but the textarea is not wrapped in the wp-editor-container div, it is missing the wp_print_styles(‘editor-buttons’) command, and generally it seems to have been loaded in an incomplete fashion, as if the code for loading a single instance of the editor (public static function editor( $content, $editor_id, $settings = array() ) ) has not been executed properly.

    Any ideas what could be causing the problem?

    Some missing global perhaps, because buddypress is loaded?

    I would greatly appreciate any suggestions you might have.

    Thank you.