Continuing on the TinyMCE post I made earlier, I want to show you how to add a button on the TinyMCE editor for your custom shortcode. The idea for this came when I created a team member shortcode for a client.
Notice: This article was written in 2016. WordPress has changed a lot since then, so take this article with a grain of salt…
They needed a small and simple shortcode that will show image, title, some content and a link to a page or to some outside content. This is a trivial thing to do, but later on I had to explain to him how to use it, and I realized that adding shortcode via shortcode tags
[shortcode-name link="" bla=""]
Code language: JSON / JSON with Comments (json)
is not the most user-friendly way for a beginner to do. Or for non-beginner for that matter. With the rise of the page builders like Visual Composer, Divi builder, The Creator, and others, people got used to simple ‘just click’ way of doing things. I knew that I could add buttons to TinyMCE, and I remembered that I saw plugins adding their own buttons to the TinyMCE with modal windows, so I knew there’s got to be a way of achieving that.
There indeed was a way, and you can google a bunch of tutorials on how to add a button for shortcode. But I wanted to go a step further – add media from WordPress to your shortcode. You could even modify the code I’ll show you, to add links to pages (modifying the code from my first article here) and posts you made on WordPress. Endless possibilities indeed.
Paving the way
The first thing we’ll do is add our button in functions.php, include the necessary JavaScript file where our control will be located and add a localization – which is important if you want to use this in a plugin and want it to be translatable. The whole code is as follows
add_action( 'after_setup_theme', 'mytheme_theme_setup' );
if ( ! function_exists( 'mytheme_theme_setup' ) ) {
function mytheme_theme_setup() {
add_action( 'init', 'mytheme_buttons' );
}
}
/********* TinyMCE Buttons ***********/
if ( ! function_exists( 'mytheme_buttons' ) ) {
function mytheme_buttons() {
if ( ! current_user_can( 'edit_posts' ) && ! current_user_can( 'edit_pages' ) ) {
return;
}
if ( get_user_option( 'rich_editing' ) !== 'true' ) {
return;
}
add_filter( 'mce_external_plugins', 'mytheme_add_buttons' );
add_filter( 'mce_buttons', 'mytheme_register_buttons' );
}
}
if ( ! function_exists( 'mytheme_add_buttons' ) ) {
function mytheme_add_buttons( $plugin_array ) {
$plugin_array['mybutton'] = get_template_directory_uri().'/js/tinymce_buttons.js';
return $plugin_array;
}
}
if ( ! function_exists( 'mytheme_register_buttons' ) ) {
function mytheme_register_buttons( $buttons ) {
array_push( $buttons, 'mybutton' );
return $buttons;
}
}
add_action ( 'after_wp_tiny_mce', 'mytheme_tinymce_extra_vars' );
if ( !function_exists( 'mytheme_tinymce_extra_vars' ) ) {
function mytheme_tinymce_extra_vars() { ?>
<script type="text/javascript">
var tinyMCE_object = <?php echo json_encode(
array(
'button_name' => esc_html__('My button name', 'mythemeslug'),
'button_title' => esc_html__('The title of the pop up box', 'mythemeslug'),
'image_title' => esc_html__('Image', 'mythemeslug'),
'image_button_title' => esc_html__('Upload image', 'mythemeslug'),
)
);
?>;
</script><?php
}
}
Code language: PHP (php)
The first part is just adding our button (registering it with TinyMCE), the second part, with the function mytheme_tinymce_extra_vars(), is adding the object in which we’ll add our translatable strings that we can use in the tinymce_buttons.js file. Now you can skip this part out, but in that case, you will have names of your button, labels, etc. all fixed – not translatable. So I would go with this approach. We just created a PHP array, and encoded it to JSON, so that we can read it in our .js file later on.
Adding the button
The next thing we want to do is to add our button, that will open a modal window on click, with our options for our imaginary shortcode. On closing the modal the shortcode will be added to our content so that we won’t have to type anything manually. Remember, when adding a button, we need to keep the previously defined name the same – in our case, it’s ‘mybutton’. For every button you add, you add a separate code with that name. You can add image, like in the column button I showed you, but now we’ll just add a simple text with the button name. In tinymce_buttons.js file add
(function() {
tinymce.PluginManager.add('mybutton', function( editor, url ) {
editor.addButton( 'mybutton', {
text: tinyMCE_object.button_name,
icon: false,
onclick: function() {
editor.windowManager.open( {
title: tinyMCE_object.button_title,
body: [
{
type: 'textbox',
name: 'img',
label: tinyMCE_object.image_title,
value: '',
classes: 'my_input_image',
},
{
type: 'button',
name: 'my_upload_button',
label: '',
text: tinyMCE_object.image_button_title,
classes: 'my_upload_button',
},//new stuff!
{
type : 'listbox',
name : 'listbox',
label : 'listbox',
values : [
{ text: 'Test1', value: 'test1' },
{ text: 'Test2', value: 'test2' },
{ text: 'Test3', value: 'test3' }
],
value : 'test2' // Sets the default
},
{
type : 'combobox',
name : 'combobox',
label : 'combobox',
values : [
{ text: 'Test', value: 'test' },
{ text: 'Test2', value: 'test2' }
]
},
{
type : 'textbox',
name : 'textbox',
label : 'textbox',
tooltip: 'Some nice tooltip to use',
value : 'default value'
},
{
type : 'container',
name : 'container',
label : 'container',
html : '<h1>container<h1> is <i>ANY</i> html i guess...<br/><br/><pre>but needs some styling?!?</pre>'
},
{
type : 'tooltip',
name : 'tooltip',
label : 'tooltip ( you dont use it like this check textbox params )'
},
{
type : 'button',
name : 'button',
label : 'button ( i dont know the other params )',
text : 'My Button'
},
{
type : 'buttongroup',
name : 'buttongroup',
label : 'buttongroup ( i dont know the other params )',
items : [
{ text: 'Button 1', value: 'button1' },
{ text: 'Button 2', value: 'button2' }
]
},
{
type : 'checkbox',
name : 'checkbox',
label : 'checkbox ( it doesn`t seem to accept more than 1 )',
text : 'My Checkbox',
checked : true
},
{
type : 'colorbox',
name : 'colorbox',
label : 'colorbox ( i have no idea how it works )',
// text : '#fff',
values : [
{ text: 'White', value: '#fff' },
{ text: 'Black', value: '#000' }
]
},
{
type : 'colorpicker',
name : 'colorpicker',
label : 'colorpicker'
},
{
type : 'radio',
name : 'radio',
label : 'radio ( defaults to checkbox, or i`m missing something )',
text : 'My Radio Button'
}
],
onsubmit: function( e ) {
editor.insertContent( '[shortcode-name img="' + e.data.img + '" list="' + e.data.listbox + '" combo="' + e.data.combobox + '" text="' + e.data.textbox + '" check="' + e.data.checkbox + '" color="' + e.data.colorbox + '" color_2="' + e.data.colorpicker + '" radio="' + e.data.radio + '"]');
}
});
},
});
});
})();
Code language: JavaScript (javascript)
I’ve put all the controls I could find that would be useful. We have a textbox for writing simple text or pasting image URL, as I’ve intended here. Button or button groups for multiple buttons. An important thing to notice here is that you can add a custom class to your field using classes property. This will add a class that you can use (you’ll see this just in a second). We also have color picker, combo box, radio buttons, etc.
On submit you’ll notice that in the editor you’ll insert a shortcode tag, with your options inserted like
e.data.name
Code language: CSS (css)
The final step you’ll need to add after this code is a simple opening of the wp.media uploader on button click. Since our modal appears when we click the ‘My button name’ button, we need to add the on click event to our document object
jQuery(document).ready(function($){
$(document).on('click', '.mce-my_upload_button', upload_image_tinymce);
function upload_image_tinymce(e) {
e.preventDefault();
var $input_field = $('.mce-my_input_image');
var custom_uploader = wp.media.frames.file_frame = wp.media({
title: 'Add Image',
button: {
text: 'Add Image'
},
multiple: false
});
custom_uploader.on('select', function() {
var attachment = custom_uploader.state().get('selection').first().toJSON();
$input_field.val(attachment.url);
});
custom_uploader.open();
}
});
Code language: JavaScript (javascript)
Here we used the fact that we added a custom class to our button – this way we can attach to that specific class, and run our media chooser. The custom class that you add will get a ‘mce-‘ prefix, be sure not to leave this out.
And that’s it. Once you’ve placed all this you’ll have something like the following
Hope this tutorial helped you guys. If you have any questions feel free to ask them in the comments below. Happy coding!
Leave a Reply