How to handle WordPress media frame events using vanilla JavaScript

I’m building a custom WordPress theme and need to integrate the media library functionality in the admin area using pure JavaScript instead of jQuery.

My Problem:
Most tutorials show how to handle media frame events with jQuery like this:

// jQuery approach that I want to convert
mediaFrame.on('select', function() {
    // Handle selected media
});

What I’ve Attempted:
I tried several vanilla JavaScript approaches to listen for the select event:

// Attempt 1: Direct assignment
mediaFrame.select = function() {
    console.log('Media selected');
};

// Attempt 2: Standard event property
mediaFrame.onselect = function() {
    console.log('Media selected');
};

// Attempt 3: Event listener method
mediaFrame.addEventListener('select', function() {
    console.log('Media selected');
});

The third approach throws an error: mediaFrame.addEventListener is not a function

None of these methods work. The media frame object doesn’t seem to follow standard DOM event handling patterns. How can I properly bind to WordPress media library events using vanilla JavaScript without relying on jQuery? I specifically need to detect when a user selects an image from the media popup.

The confusion happens because WordPress media library runs on Backbone.js, not regular DOM elements. When you use wp.media(), you’re dealing with a Backbone view that has its own events. Your third attempt was close but targeted the wrong thing. The media frame uses Backbone’s event handling, so stick with .on() like the previous answer showed. But if you need to handle multiple events or want more control, you can bind to the frame’s state changes:

var mediaFrame = wp.media({
    title: 'Choose Image',
    multiple: false
});

// Listen for state changes
mediaFrame.state('library').on('select', function() {
    var selection = mediaFrame.state().get('selection');
    // Process selection
});

This gives you direct access to the library state and works great for custom media workflows. Just remember - WordPress media components follow Backbone patterns, not native browser APIs.

the mediaFrame object isn’t a DOM element, so addEventListener won’t work. Instead, just use .on('select', callback) directly on the frame like this: mediaFrame.on('select', function() {...})—that’s the right way to go with vanilla JS!

WordPress media frame uses Backbone.js for events, not regular DOM events. You need to use Backbone’s event methods instead. Here’s how to do it with plain JavaScript:

var mediaFrame = wp.media({
    title: 'Select Media',
    multiple: false
});

// Bind to the 'select' event using Backbone's on method
mediaFrame.on('select', function() {
    var attachment = mediaFrame.state().get('selection').first().toJSON();
    console.log('Selected media:', attachment);
    // Handle your selected media here
});

mediaFrame.open();

The key difference: WordPress media frame extends Backbone.Events, so it uses .on() and .off() for event binding instead of standard DOM methods. This works perfectly with vanilla JavaScript - no jQuery needed.