WordPress Custom Meta Box WYSIWYG Editor

Ok, I’m posting about this on my blog because I can’t believe it took me so long to find and figure this out.  Many of the links you pull up with Google point you to an older method which is a) complicated and b) doesn’t seem to be working for me anymore.  I said “so long” because apparently this other MUCH EASIER method has been around since WordPress 3.3 and I only just found out it exists at version 4.3!

The Old Way

You’d have to create a custom meta box on a custom post type edit screen was something like this:

1
2
3
4
5
6
7
function my_custom_metabox($post) {
    $my_meta_content = get_post_meta($post->ID, '_mymeta', TRUE);
    if (!$my_meta_content) $my_meta_content = '';
    wp_nonce_field( 'mypost_type'.$post->ID, 'my_meta_noncename');
echo '<div class="editor-toolbar">;' echo ' <a id="edButtonPreview1" class="edButtonPreview"></a>HTML'; echo ' <a id="edButtonHTML1" class="edButtonHTML active"></a>Visual'; echo '</div>';
echo '<div class="customEditor">'; echo '<textarea cols="40" name="my_meta" rows="5">'.$my_meta_content.'</textarea></div>
'
; }

Then you’d have to add your meta box:

1
2
3
4
function add_my_metabox(){
    add_meta_box('my_meta_section',__('My Meta Box'),'my_custom_metabox','mypost_type','normal','core');
}
add_action('admin_init','add_my_metabox');

And you’d have to print some jQuery into the footer of the edit post page:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// important: note the priority of 99, the js needs to be placed after tinymce loads
function my_admin_print_footer_scripts()
{
    ?><script type="text/javascript">/* <![CDATA[ */
        jQuery(function($)
        {
            var i=1;
            $('.customEditor textarea').each(function(e)
            {
                var id = $(this).attr('id');
 
                if (!id)
                {
                    id = 'customEditor-' + i++;
                    $(this).attr('id',id);
                }
 
                tinyMCE.execCommand('mceAddControl', false, id);
              });        
        });
             
     
     function toggleEditor(id, dir) {
        var id = 'customEditor-'+id;
        if (dir=="visual") {
            var cmd = 'mceAddControl';
            var cName1 = " active";
            var cName2 = "";
        } else {
            var cmd = 'mceRemoveControl';
            var cName1 = "";
            var cName2 = " active";
        }
        tinyMCE.execCommand(cmd, false, id);
        document.getElementById('edButtonPreview').className="edButtonPreview"+cName1;
        document.getElementById('edButtonHTML').className="edButtonHTML"+cName2;
     }  
    /* ]]> */</script><?php
}  
if ($pagenow=="post.php"){ add_action('admin_print_footer_scripts','my_admin_print_footer_scripts',99); }

And, lastly, you’d need some way to submit the content when the post is saved or published:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
add_action('save_post','save_my_custom_data');
function save_my_custom_data($post_id) {
// verify our nonce
if ( isset($_POST['my_meta_noncename'])) && !wp_verify_nonce( $_POST['my_meta_noncename'], 'mypost_type'.$post_id) ) {
    return $post_id;
}
// check permissions
if ( !current_user_can( 'edit_post', $post_id ) ) return $post_id;
// Ok we're good to go!
$post = get_post($post_id);
if ($post->post_type == 'mypost_type') {
    if (isset($_POST['my_meta'])) {
        update_post_meta($post_id, '_mymeta', $_POST['my_meta'] );
}

Like I said, it’s complicated and it also seems to have stopped working, at least in my plugin it stopped working in about WordPress 4.0 – the meta boxes still work, but there’s no WYSIWYG editor on them anymore and the tabs for “HTML” and “Visual” throw javascript errors.

The NEW Way

I’m hesitant to call this the “new” way seeing as it’s been around for over TEN releases of WordPress, but just about every tutorial I found was about how to do the method above, which is how my plugin ended up doing it that way. The good news is that all that madness is behind me! Here we go:

1. Forget about printing that jQuery script into the footer of your admin post screen. We don’t need it anymore!

2. Modify the custom meta function:

1
2
3
4
5
6
function my_custom_metabox($post) {
    $my_meta_content = get_post_meta($post->ID, '_mymeta', TRUE);
    if (!$my_meta_content) $my_meta_content = '';
    wp_nonce_field( 'mypost_type'.$post->ID, 'my_meta_noncename');
    wp_editor( $my_meta_content, 'my_meta', array('textarea_rows' => '5'));
}

3. There is no step three! Our existing nonce check and data pull from the textarea will still work. We’re done.

One BIG Gotcha

Because it uses the TinyMCE editor, which is instantiated via javascript at the end of the page load, there is one big problem with this. You can’t drag the custom meta box to a new location and continue using it. Moving TinyMCE editors around (because they move around in the DOM and apparently lose reference) makes them stop working. It’s probably why WordPress doesn’t let you drag the main post editing window around, the Visual editor would stop working!

I don’t know about you, but I don’t tend to drag the boxes around in the WordPress interface. And even if I do move them around, a quick page refresh makes the custom meta box editor work again, so in my opinion it’s not a deal-breaker. But you should at least be aware of it.

Full documentation on wp_editor() is here: https://codex.wordpress.org/Function_Reference/wp_editor

← Previous post

Next post →

1 Comment

  1. Greate article. Thank you.

Leave a Reply


Menu




Search

Posts

About

Comment1

Contact

Share

Share this On:

Google+ Reddit Stumble It Digg this! LinkedIn Pinterest Del.icio.us RSS Feed E-mail Link!