• Skip to primary navigation
  • Skip to main content
Sal Ferrarello
  • About Sal Ferrarello
  • Speaking
  • Connect
    Mastodon GitHub Twitter (inactive)
You are here: Home / Programming / Move Toolset Metabox Above WYSIWYG Editor
Screenshot of Toolset Metabox Above WYSIWYG Editor

Move Toolset Metabox Above WYSIWYG Editor

Last updated on May 15, 2017 by Sal Ferrarello

I recently had a request to move a WordPress custom metabox created with the Toolset Types plugin above the WYSIWYG Editor (a.k.a. Visual Editor).

While this seems like a simple request, as so often happens in programming this was more complex than expected.

Comic showing the difficulty of a programming task is often unintuitive.

The Solution

The solution is to check the global variable $wp_meta_boxes early (specifically just before the WYSIWYG editor, on the edit_form_after_title hook).

If your metabox appears in $wp_meta_boxes, you output it early and then remove the metabox from $wp_meta_boxes (so it doesn’t display a second time).

This code was funded by Blinebury Design. Thanks to their generosity, this code is now available on GitHub (or you can copy it from below).

If you find this code useful, you might want to send them a tweet of thanks.

Moving Your Metabox

In addition to the plugin code, you’ll need to add a code snippet to tell the plugin which metabox to move.

Step 1: Find the Group ID of Your Metabox

When editing the metabox in Toolset Types, find the group_id value in the URL.

Screenshot of a Toolset Types Metabox URL with Group ID 4

In this screenshot, the group_id is 4.

Step 2: Add the Configuration Code

You can add this code in your theme’s functions.php (or in a mu-plugin).

add_filter( 'fe_tmm_move_metabox_after_title_ids', function ( $group_ids ) {
    // Add 4 to the list of Group IDs to move above the WYSIWYG editor (by default this list is empty).
    $group_ids[] = 4;

    return $group_ids;
} );    

Plugin Code

This is the code available on GitHub at salcode/toolset-metabox-move-above-wysiwyg. This code needs to be running, in addition to the configuration code you created above.

<?php
/**
 * Plugin Name: Move Toolset Metabox Above WYSIWYG Editor
 * Plugin URI: http://salferrarello.com/move-toolset-metabox-above-wysiwyg-editor/
 * Description: Allows moving metaboxes created with the Toolset plugin above the WYSIWYG editor, with the filter <strong>fe_tmm_move_metabox_after_title_ids</strong>. Example: <code>add_filter( 'fe_tmm_move_metabox_after_title_ids', function ( $ids ) { $ids[] = 1813; return $group_ids; } );</code>
 * Version: 1.0.0
 * Author: Sal Ferrarello
 * Author URI: http://salferrarello.com/
 * Text Domain: toolset-metabox-move-above-wysiwyg
 * Domain Path: /languages
 *
 * Example filter to move Toolset metaboxes 1813 and 1820 above the WYSIWYG editor.
 * add_filter( 'fe_tmm_move_metabox_after_title_ids', function ( $group_ids ) {
 *  $group_ids[] = 1813;  // Move group id 1813 above the WYSIWYG editor.
 *  $group_ids[] = 1820;  // Move group id 1820 above the WYSIWYG editor.
 *  return $group_ids;
 * } );
 *
 * @package toolset-metabox-move-above-wysiwyg
 */

// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
    die;
}

add_action( 'edit_form_after_title', 'fe_tmm_move_metabox_after_title' );
/**
 * Move a Metabox created with the Toolset plugin after the title on the editor page.
 *
 * In other words, move the metabox above the WYSIWYG editor.
 *
 * @hook filter fe_tmm_move_metabox_after_title_ids An array of metabox Group IDs to move below the title.
 */
function fe_tmm_move_metabox_after_title() {
    global $post, $wp_meta_boxes;
    $group_ids = apply_filters( 'fe_tmm_move_metabox_after_title_ids', array() );

    $post_type = get_post_type( $post );
    // Contexts are: [ 'normal', 'advanced' ].
    $context = 'normal'; // Toolset Types uses a context of 'normal', from available context
    // Priorities are: [ 'default', 'high', 'low' ].
    $priority = 'high';  // Toolset Types uses a priority of 'high'.

    foreach ( $wp_meta_boxes[ $post_type ][ $context ][ $priority ] as $key => $metabox ) {
        if ( 'wpcf-group-' === substr( $key, 0, 11 ) && in_array( $wp_meta_boxes[ $post_type ][ $context ][ $priority ][ $key ]['args']['id'], $group_ids, true ) ) {
            $box = $wp_meta_boxes[ $post_type ][ $context ][ $priority ][ $key ];
            // Render the single metabox.
            fe_tmm_do_single_meta_box( $box, get_current_screen(), $post );
            // Remove the metabox we rendered for $wp_meta_boxes, to prevent rendering a second time.
            unset( $wp_meta_boxes[ $post_type ][ $context ][ $priority ][ $key ] );
        }
    }
}

/**
 * Display a Single Metabox
 *
 * This code is taken from the do_meta_boxes() function in
 * /wp-admin/includes/template.php
 *
 * @param array $box An associative array defining a single metabox.
 * @param string|WP_Screen $screen  Screen identifier
 * @param mixed $object  gets passed to the box callback function as first parameter.
 */
function fe_tmm_do_single_meta_box( $box, $screen, $object ) {
    $page = $screen->id;
    $hidden_class = '';
    echo '<div id="' . $box['id'] . '" class="postbox ' . postbox_classes($box['id'], $page) . $hidden_class . '" ' . '>' . "\n";
    if ( 'dashboard_browser_nag' != $box['id'] ) {
        $widget_title = $box[ 'title' ];

        if ( is_array( $box[ 'args' ] ) && isset( $box[ 'args' ][ '__widget_basename' ] ) ) {
            $widget_title = $box[ 'args' ][ '__widget_basename' ];
            // Do not pass this parameter to the user callback function.
            unset( $box[ 'args' ][ '__widget_basename' ] );
        }

        echo '<button type="button" class="handlediv button-link" aria-expanded="true">';
        echo '<span class="screen-reader-text">' . sprintf( __( 'Toggle panel: %s' ), $widget_title ) . '</span>';
        echo '<span class="toggle-indicator" aria-hidden="true"></span>';
        echo '</button>';
    }
    echo "<h2 class='hndle'><span>{$box['title']}</span></h2>\n";
    echo '<div class="inside">' . "\n";
    call_user_func($box['callback'], $object, $box);
    echo "</div>\n";
    echo "</div>\n";
}
Sal Ferrarello
Sal Ferrarello (@salcode)
Sal is a PHP developer with a focus on the WordPress platform. He is a conference speaker with a background including Piano Player, Radio DJ, Magician/Juggler, Beach Photographer, and High School Math Teacher. Sal can be found professionally at WebDevStudios, where he works as a senior backend engineer.

Share this post:

Share on TwitterShare on FacebookShare on LinkedInShare on EmailShare on Reddit

Filed Under: Programming Tagged With: Toolset Types, WordPress, WordPress Plugin

Reader Interactions

Comments

  1. Guido says

    October 13, 2021 at 1:29 pm

    Hi,

    This doesn’t seem to work with Gutenberg. Is there a solution for that?

    Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Copyright © 2023 · Bootstrap4 Genesis on Genesis Framework · WordPress · Log in