WordPress plugins: Using shortcodes and popups

I made a plugin to render HTML before page content (see “How do I make a WordPress plugin?“), but I needed another one. This extension adds “see demo” blocks inside content. I just give links to preview, set image and eye-pleasing blocks appear in place of shortcodes.

The extension is available from a GitHub repository; you can go there to see every line of code. I will try to send it to plugin repository shortly.

Update: Plugin is already available here: https://wordpress.org/plugins/demo-shortcodes/. To install it from the dashboard, go to Plugins/Add New, change search criteria to Author and look for kantoniak.

Demo plugin preview

OK, let’s go!

Register shortcodes

There is a function to register shortcode [name][/name], you pass a handler function as an argument. Remember to return HTML as a result.

add_shortcode('name', 'handleShortcode');

function handleShortcode() {
  return 'Instead of shortcode';
}

Handle parameters

Handler function has two parameters. This first one is an array of attributes and the second one is content between tags.

add_shortcode('name', 'handleShortcode');

function handleShortcode($attributes, $content = '') {
 return '<pre>'. print_r($attributes) ."\n". $content .'</pre>';
}

Shortcodes will look like this: [tag attr="val"]content[/tag].

Create media button

Wait for media_buttons action and just render HTML. No idea why there is no function for that, button appearance should be standardized.

if (is_admin()) {
  add_action('media_buttons', 'addMediaButton');
}

function addMediaButton() {
  echo '<a href="#" id="plugin-slug-whatever" class="button"><span></span>label</a>';
}

Have you noticed that link has no href attribute? Usually, this button either opens a popup or directly modifies editor contents.

Adding media button to handle shortcodes.

It looks like this (grayed the rest a bit)

As a bonus CSS code to set button icon. That is why I inserted empty span in the code above.

// CSS to set a 16x16 icon
#plugin-slug-insert-whatever span {
  display: inline-block;
  height: 16px;
  width: 16px;
  margin: 5px 6px 0 0;
  vertical-align: top;
  background: url(../images/icon-16.png) no-repeat center center;
}

Display popup

WordPress uses a script called Thickbox. OK, WordPress itself switched to something else, but the majority of plugins use Thickbox. A typical approach would be:

  1. Embed Thickbox using provided function.
  2. Render the popup as a hidden block. You need to have a div nested inside, that’s how this library works.
  3. Give a link class thickbox and appropriate href attribute.
if (is_admin()) {
 add_action('media_buttons', 'addMediaButton');
}

function addMediaButton() {
 add_thickbox();
 require('template-popup.php');
 echo '<a href="#TB_inline?height=300&width=600&inlineId=the-popup" id="plugin-slug-insert-whatever" class="button"><span></span>label</a>';
}
<div style="display:none" id="the-popup" data-width="540" data-height="306"><div class="the-popup-content">
 <p>Popup contents...</p>
</div></div>

Thickbox will copy div.the-popup-content, just look inside the window when searching for elements:

jQuery('#TB_window .the-popup-content *')

There is a problem, though.

Set custom popup size

Thickbox popup does not set width and height correctly, instead, it stretches to take the whole window. It seems WordPress people don’t care – see #17249 in WordPress tracker.

I took the suggested fix and enhanced it with a bit of JS so you can use HTML5 data- attributes to set size. Just see the commit: d7cc745 Add admin popup framework. Works like a charm:

Popup with custom size

Only now have I noticed triple “insert” on the screen shot. Time for update 🙂

Inject text in the editor

Couldn’t be easier. In your script:

tinyMCE.activeEditor.execCommand('mceInsertContent', false, 'Your content');

Summary

That’s the end of recipes for today. See main PHP file here. You should be able to create a fully functional plugin with shortcodes now.

Resources