Codex

Interested in functions, hooks, classes, or methods? Check out the new WordPress Code Reference!

User:TV productions/Use WordPress dialogs in your TinyMCE plugin

This article is marked as in need of editing. You can help Codex by editing it.

Note: The contents on this page apply only to TinyMCE version < 4!


The WordPress dialog

Insert/edit link dialog

This page is about the WordPress modal dialog (in code referenced as WPDialog). This is the dialog window just like the Insert/edit link dialog on the post/page screen. There are some advantages to the WPDialog:

  • You can translate it with the standard L10n functions in php.
  • The dialog is not another html file, so you don't have to struggle with the right inclusion paths for styles and scripts.

I assume you know how to set up a basic TinyMCE plugin and that you have set up one. If not, read more about TinyMCE.

Open a WPDialog

To open a WPDialog, you have to insert the following piece of code in editor_plugin_src.js. This code opens the dialog, so place it where you want (probably in a command).

ed.windowManager.open({
    width : 480,
    height : 'auto',
    wpDialog: true,
    id : 'my-custom-wpdialog',
    title : 'My custom WPDialog'
    }, {
    plugin_url : url,
});

The arguments

width 
The width of the dialog in pixels. 480 is most cases also a good size.
height 
The height of the dialog in pixels. When you set height to 'auto', the dialog will fit to it's contents.
wpDialog 
This does the magic. When you set this to true, the dialog will be a WPDialog. This means you have to specify an id (see next argument).
id 
The id of the dialog. Remember it!
title 
The title of the dialog. For more information about translation, see further on.

The last part (plugin_url) is standard for TinyMCE dialogs.

The dialog content

Add the following function to the .php file where you've also defined the buttons for the TinyMCE Editor.

/*
 * Prints the contents of my custom wpdialog
 */
function my_custom_wpdialog_contents() {
    /* 
     * Enqueue and print your styles and scripts that are needed for the dialog
     * Use wp_enqueue_style/wp_enqueue_script and wp_print_styles/wp_print_scripts
     */
    wp_enqueue_style('my-custom-wpdialog-style', plugins_url('css/my-custom-dialog.css', __FILE__));
    wp_enqueue_script('my-custom-wpdialog-script', plugins_url('js/my-custom-dialog.js', __FILE__), array('jquery'));
    // Print style and script right now
    wp_print_styles('my-custom-wp-dialog-style');
    wp_print_scripts('my-custom-wp-dialog-script');
    
    // Print directly html
    ?>
<div style="display: none">
    <form id="my-custom-wpdialog" tabindex="-1">
        <p class="howto"><?php _e('This is a WPDialog!', 'textdomain');?></p>
        <div class="submitbox">
            <div id="my-custom-wpdialog-update">
                <input id="my-custom-wpdialog-submit" class="button-primary" type="submit" name="my-custom-wpdialog-submit" value="<?php _e('OK', 'textdomain'); ?>">
            </div>
            <div id="my-custom-wpdialog-cancel">
                <a class="submitdelete deletion" href="#"><?php _e('Cancel', 'textdomain')?></a>
            </div>
        </div>
    </form>
</div>
<?php
}
add_action('after_wp_tiny_mce', 'my_custom_wpdialog_contents');

This function is hooked to the after_wp_tiny_mce hook.
Next, we enqueue the styles and scripts that we gonna use with wp_enqueue_style and wp_enqueue_script. This is actually too late for WordPress to handle those scripts, so we have to print them by ourselves (with wp_print_styles and wp_print_scripts).
After that, we print the contents of the WPDialog. There are some important things about this piece of HTML:

  • It shouldn't be visible, so wrap it with a <div style="display:none"> tag.
  • The contents of the WPDialog should be within a <form> tag. The id of the this form tag should be the same as the id you passed trough by opening the WPDialog. In this example my-custom-wpdialog.
  • The tabindex of the form should be set to -1.
  • The buttons have an id, so it is easy to reference to them with JavaScript.

Styling

The styling of the WPDialog is of course all yours, but you can start here with some general styling rules.

#my-custom-wpdialog {
    background-color: #F5F5F5;
    font-size: 12px;
    line-height: 1.4em;
    margin: 5px;
    outline: none;
}

#my-custom-wpdialog .submitbox {
    font-size: 11px;
    height: 29px;
    overflow: auto;
    padding: 5px 10px;
}

The other classes, like submitdelete, are defined in wp-admin/css/colors-fresh.css

Save your stylesheet to css/my-custom-wpdialog.css, relative to the plugin directory.

Scripts

You probably want to insert something in the editor after the user selected something in the dialog box. If you need some data (like posts), use AJAX to retrieve it.

A basic setup for the javascript file is this

var myCustomWPDialog;
(function($) {
    var input = {};
    myCustomWPDialog = {

        init : function() {
            input.dialog = $('#my-custom-wpdialog');
            input.submit = $('#my-custom-wpdialog-submit');
            input.submit.click(function(e) {
                myCustomWPDialog.submit();
                e.preventDefault();
            });
            input.cancel = $('#my-custom-wpdialog-cancel')
            input.cancel.click(function(e) {
                myCustomWPDialog.close();
                e.preventDefault();
            });

            // Bind a function to the wpdialogbeforeopen event of the dialog, 
            // use the next line and replace callback with your actually function.
            // input.dialog.bind('wpdialogbeforeopen', callback);
            // Bind a function to the wpdialogrefresh event
            // input.dialog.bind('wpdialogrefresh', callback);
            // Bind a function to the wpdialogclose event
            // input.dialog.bind('wpdialogclose', callback);
        },

        submit : function() {
            if (tinyMCE && tinyMCE.activeEditor) {
                tinyMCE.activeEditor.selection.setContent("This is a test string");
            }
            myCustomWPDialog.close();
        },

        close : function() {
            if (myCustomWPDialog.isMCE())
                tinyMCEPopup.close();
            else
                input.dialog.wpdialog('close');
        },

        isMCE : function() {
            return tinyMCEPopup && (ed = tinyMCEPopup.editor) && !ed.isHidden();
        }
    };
    $(document).ready(myCustomWPDialog.init);
})(jQuery)
myCustomWPDialog 
This is the public namespace of the functions for this dialog. Make sure it is unique.
input 
This is a helper variable. This contains all the input elements of the dialog, including the form.

This file inserts the string This is a test string into the editor. If you want to do more, check out the tinymce.Editor class on tinymce.com.

Save your javascript as js/my-custom-wpdialog.js, relative to the plugin directory. For more info, study wp-includes/js/wplink.js

Translating for TinyMCE plugins

You probably want your dialog to be translated. The contents of the WPDialog are translated with PHP (see The dialog content).

But if you want to translate strings you use in the JavaScript of the TinyMCE plugin, you can't print them somewhere directly with PHP. Lucky enough, WordPress' implementation of TinyMCE makes it possible to translate those with PHP.

Translating the strings

Create a new file, called something like my-cusom-wpdialog-langs.php and open it. Insert the following code.

// This file is based on wp-includes/js/tinymce/langs/wp-langs.php


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

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

function my_custom_wpdialog_translation() {
    $strings = array(
        'dlg_title' => __('My custom WPDialog', 'textdomain'),
    );
    $locale = _WP_Editors::$mce_locale;
    $translated = 'tinyMCE.addI18n("' . $locale . '.my_custom_wpdialog", ' . json_encode( $strings ) . ");\n";

     return $translated;
}

$strings = my_custom_wpdialog_translation();

What the code does

The code first checks if the file is included by WordPress. If not, it exits. Next, it checks if the class _WP_Editors exists. If not, the class is loaded (from wp-includes/class-wp-editor.php).

We wrap the translation in a function (this to make sure there are no global variables) called my_custom_wpdialog_translation (make sure your function is unique). Here you translate your strings with a associative array. The key in this array is also the key you will use later on to get the translation. Then we retrieve the locale for the editor and we build some JavaScript. We use the tinyMCE.addI18n JavaScript function to add the translated strings to the editor. Some information about the arguments:

"' . $locale . '.my_custom_wpdialog" 
This is the "textdomain" of the translation. It should look like "en.my_custom_wpdialog" (the language, in this case en, is set to the value of the variable $locale). We use my_custom_wpdialog as "textdomain".
json_encode( $strings ) 
This converts the translated strings to JavaScript.

That bit of JavaScript code is returned by the function.

You can see that on the last line of the file, our function my_custom_wp_dialog_translation is called and that the translated strings are saved in the global variable $strings. (The variable has to be called $strings, or it won't work.

For more examples of a file with translations, see wp-includes/js/tinymce/langs/wp-langs.php

Load your translation

Now we only have to load your translated strings at the right moment. This is done by using the mce_external_languages filter. Insert the following code in the file where you also register your TinyMCE plugin. (i.e. the file with the function that is hooked to the mce_external_plugins filter)

function my_custom_wpdialog_add_locale($locales) {
    $locales ['My-Custom_WPDialog'] = plugin_dir_path ( __FILE__ ) . 'my-custom-wpdialog-langs.php';
    return $locales;
}
add_filter('mce_external_languages', 'my_custom_wpdialog_add_locale');

Replace My-Custom-WPDialog with your identifier of your plugin and make sure the path to my-cusomt-wpdialog-langs.php is correct.

Source