Quantcast
Channel: WordPress
Viewing all articles
Browse latest Browse all 77

Adding your own buttons in TinyMCE 4.* editor - part 2

$
0
0
Adding your own buttons in TinyMCE 4.* editor - part 2

This entry is a continuation of our recent post focusing on adding your own buttons to the TinyMCE editor added in the WordPress 3.9. update release.

Table of contents

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

(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


Viewing all articles
Browse latest Browse all 77

Trending Articles