This is a short tutorial on extending the WordPress media modal with your own content. Here we add a button in the media upload image details section.

The wp.media class

When adding, choosing and editing images in WordPress, most of the time you will see a modal opening up. This can be for the upload, selecting an image from within a post, or checking image details in the media library. Each of these modals is part of wp.media in the wp scope/namespace.

According to the documentationwp.media is used to handle and control the admin media modal. For instance, custom image selector/uploader controls and meta boxes.”

Adding buttons to the modals

If you try extending the WordPress media modal with your own plugin or theme content, you best use JavaScript. I found a way that works for me. There may be other options, but I will describe how I added custom buttons to WordPress image details.

In this example, I will add a button after the main image details in the upload modal.

1) Finding the correct template

The most important detail to extend anything is to know where exactly you are trying to change content. In the beginning, it took me a while to find the correct templates. In the end I reverted to not searching the wp.media class itself, but to check in the developer console in my browser.

First, I check the class names within the modal itself. Usually the one before a headline is correct. But it doesn’t hurt to remember a view of them.

Then I look for the template scripts in the beginning of #wpcontent. There should be one which has the name of the just found classname. You can also find it by searching for some of the text within that template. Here for example, you could look for “Delete permanently” and you will find exactly those words in the script. (This means, you can also switch the order of those steps. You should just make sure the template class name is also available in your modal content.)

Then I check this resource: https://atimmer.github.io/wordpress-jsdoc/ It has all the needed docs and references. 
Within the main navigation “classes” you should find your template for wp.media.view.XXX. My class is tmpl-attachement-details –> so I am searching for wp.media.view.Attachment.Details

In there jump straight to the source and make sure there is a template I can extend:

For example: https://atimmer.github.io/wordpress-jsdoc/media_views_attachment_details.js.html line 9

I know, I am already sure there is a template due to the tmpl script. But it doesn’t hurt to make sure.

And now I can finally get into the view itself and can start writing the code.

2) Extending the template

In my JavaScript, I call and extend the found class with my new template content:

wp.media.view.Attachment.Details = wp.media.view.Attachment.Details.extend({
    template: function(view) {
        // tmpl-attachment-details
        const html = wp.media.template('attachment-details')(view); // the template to extend
        const dom = document.createElement('div');
        dom.innerHTML = html;

        // create image actions wrapper
        const details = dom.querySelector('.details');
        const actions = document.createElement('button'); // create new element
        actions.classList.add('anna-edit-button'); // add a class to the element for styling
        actions.setAttribute('id', this.model.attribute.id); // add the image-id using the attributes
        actions.innerHTML = 'Edit image'; // element text
        details.appendChild(actions); // add new element at the correct spot

        return dom.innerHTML;
    }
});

Now the template will include my button. (For the styling, you have to include your own CSS. This is not part of this description.)As we are within the class Attachment.Details, we can access all image attributes in our code. As an example, I used attribute.id for the button id. You can also use the image url, etc.

2.1 ) Adding click listeners

For now, the button looks nice and is at the right spot, but it doesn’t help much if it’s not clickable. The templates all have events and we need add our own listeners and actions.

wp.media.view.Attachment.Details = wp.media.view.Attachment.Details.extend({
    events = {
        ...wp.media.view.Attachment.Details.prototype.events, // keep all existing events
        'click .anna-edit-button' : 'photiniaEditAttachment', // add our own click listener
    }
    template: function(view) {
    ...
    }
});

2.2 ) Adding the listener method

And finally, I need the method called in my event listener. In this example I will trigger a console.log and a re-render. The re-render makes most sense if you actually edited the image. But maybe that’s what you want to do.

wp.media.view.Attachment.Details = wp.media.view.Attachment.Details.extend({
    photiniaEditAttachment: function(e)
        {
            const { id } = this.model.attributes;
            console.log( id )
            this.model.fetch({
                success: () => {
                    this.render();
                },
                error: (collection, response, options) => {
                    console.log('error fetching view model');
                }
            });
        },
    events = {
        ...
    }
    template: function(view) {
    ...
    }
});

That’s it. Now we added a button to the upload modal AttachmentDetails section and made that button clickable.

I hope this helps to create other template extensions and elements.