Remember the old “Add Media” button, right above the TinyMCE classic editor? I need it back.
Some of the functionality I offer in my themes and plugins – eCards, WP Property Drive, Foundry – is the option to attach (not insert) images to a custom post type. Then, in the front-end, I display them in a nice carousel. I held onto the old editor for a long time, but it’s now time to let go and implement the “Add Media” in a metabox.
I’ll call the button “Manage Media“. It allows a user to attach images, delete images, and re-order them. I’ll start with adding a regular metabox to a fictional property
post type:
<?php
/**
* Register custom meta boxes.
*
* This function registers a custom meta box for the 'property' post type,
* which allows users to input property details.
*
*/
function add_meta_boxes() {
add_meta_box( 'my_meta_box', 'Property Details', 'property_metabox_callback', [ 'property' ], 'normal', 'high' );
}
// Hook the 'add_meta_boxes' function to the WordPress action.
add_action( 'add_meta_boxes', 'add_meta_boxes' );
<?php
/**
* Callback function for the 'my_meta_box' custom meta box.
*
* This function is responsible for rendering the content of the custom meta box.
* It displays a "Manage Media" button and includes a nonce field for security.
*
* @param WP_Post $post The current post object.
*
*/
function property_metabox_callback( $post ) {
// Add a nonce field for security.
wp_nonce_field( 'property', 'property_nonce' );
// Get the post ID.
$post_id = $post->ID;
// Output the HTML content for the meta box.
?>
<p>
<a href="#" class="my-manage-media-button button button-secondary">Manage Media</a>
</p>
<?php
}
As there is no saving option, I don’t need to add an action for saving.
Next, I need to add the JavaScript functionality, and I opted for vanilla JavaScript (no jQuery dependency) and the wp.media.controller.Library
library, which is a state for choosing an attachment or group of attachments from the media library:
/**
* Add event listeners for managing media in the WordPress admin area.
*
* This code adds event listeners to handle media management in the WordPress admin area.
* Specifically, it opens the media manager when the "Manage Media" button is clicked.
*
*/
document.addEventListener('DOMContentLoaded', function () {
// Find the "Manage Media" button.
const uploadButton = document.querySelector('.my-manage-media-button');
// Check if the button exists.
if (uploadButton) {
// Add a click event listener to the button.
uploadButton.addEventListener('click', function (e) {
e.preventDefault();
// Create a WordPress media manager instance.
const cpUploader = wp.media({
button: {
text: 'Close'
},
states: [
new wp.media.controller.Library({
title: 'Manage media (upload, delete, reorder)',
filterable: 'all',
sortable: true,
multiple: true,
selectedImageId: 0,
library: wp.media.query({
type: 'image',
})
})
]
});
// Handle the "select" event when media is selected.
cpUploader.on('select', function () {
// Get the selected attachment.
const attachment = cpUploader.state().get('selection').first().toJSON();
// No need to handle the selected attachment here, but you can add code as needed.
});
// Open the media manager.
cpUploader.open();
});
}
});
This JavaScript file is enqueued in the Dashboard only, and optionally, if the post type matches what I need:
<?php
/**
* Enqueue scripts and styles for the admin area.
*
* This function enqueues the necessary scripts and styles for the admin area,
* specifically for the 'property' post type. It checks if the 'wp_enqueue_media'
* action has been executed and enqueues media scripts if not. It also enqueues a
* custom JavaScript file for managing media.
*
*/
function my_admin_enqueue_scripts() {
// Check if 'wp_enqueue_media' action has been executed and the post type is 'property'.
if ( ! did_action( 'wp_enqueue_media' ) && (string) get_post_type() === 'property' ) {
wp_enqueue_media();
}
// Check if the post type is 'property' and enqueue the custom JavaScript file.
if ( (string) get_post_type() === 'property' ) {
wp_enqueue_script( 'manage-media', plugins_url( 'assets/js/admin-media.js', __FILE__ ), [], '1.0.0', true );
}
}
// Hook the 'my_admin_enqueue_scripts' function to the WordPress action.
add_action( 'admin_enqueue_scripts', 'my_admin_enqueue_scripts' );
The resulting media window will not allow for image insertion, only for uploading, deleting, and re-ordering (note the greyed-out “Close” button):
Photo by Roman Kraft on Unsplash