I recently worked on a case in the WordPress block editor in which I needed to add support for clipboard events in a media iframe. In this case, the iframe was being used inside a custom version of wp.media.view.MediaFrame
. While wp.media.view
does not natively support custom attributes on iframes, we can create our own custom media iframe with custom attributes.
If you have a WordPress installation up and running, you can find the code for wp.media.view.Iframe
in wp-includes/js/media-views.js. It should look like the following:
/**
* wp.media.view.Iframe
*
* @memberOf wp.media.view
*
* @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
*/
var Iframe = wp.media.View.extend(/** @lends wp.media.view.Iframe.prototype */{
className: 'media-iframe',
/**
* @return {wp.media.view.Iframe} Returns itself to allow chaining.
*/
render: function() {
this.views.detach();
this.$el.html( '<iframe src="' + this.controller.state().get('src') + '" />' );
this.views.render();
return this;
}
});
module.exports = Iframe;
I’ll admit I don’t love the implementation of iframes that we see above. Using jQuery to set the HTML of a WP core element while providing no filtering options seems less than friendly to developers.
For the specific task of adding support for clipboard-write
events I created a custom iframe implementation that is a near-duplicate of the WP core version, but renamed and with allow="clipboard-write"
included as an attribute of the iframe element:
/**
* wp.media.view.ClipboardWriteIframe
* A custom version of wp.media.view.Iframe,
* adding support for clipboard-write events
*
* @memberOf wp.media.view
*
* @class
* @augments wp.media.View
* @augments wp.Backbone.View
* @augments Backbone.View
*/
var ClipboardWriteIframe = wp.media.View.extend(/** @lends wp.media.view.ClipboardWriteIframe.prototype */{
className: 'media-iframe',
/**
* @return {wp.media.view.ClipboardWriteIframe} Returns itself to allow chaining.
*/
render: function() {
this.views.detach();
this.$el.html( '<iframe src="' + this.controller.state().get('src') + '" allow="clipboard-write"/>' );
this.views.render();
return this;
}
});
module.exports = ClipboardWriteIframe;
In the file where my custom wp.media.view.MediaFrame
exists, I found the iframeContent
method:
/**
* @param {Object} content
* @this wp.media.controller.Region
*/
iframeContent: function( content ) {
this.$el.addClass('hide-toolbar');
content.view = new wp.media.view.Iframe({
controller: this
});
},
Then I changed the method to use my custom ClipboardWriteIframe
class:
/**
* @param {Object} content
* @this wp.media.controller.Region
*/
iframeContent: function( content ) {
this.$el.addClass('hide-toolbar');
content.view = new ClipboardWriteIframe({
controller: this
});
},
While this was a fairly straightforward modification to make, it’s easy to see how one could further customize the attributes on a media iframe. In this implementation, we can add any static HTML attributes to the iframe element by simply hardcoding them in the iframe as I’ve done above with allow="clipboard-write"
. We could also add dynamic attributes similarly to how the src
attribute gets applied. For example, if we have an id
value held in state and we’d like to apply this to the iframe element, our changed line of code might look like the following:
this.$el.html('<iframe src="' + this.controller.state().get('src') + '"' + 'id="' + this.controller.state().get('id') + '"/>');
Typically I would avoid cloning and modifying WordPress core functionality. However, in this case it proved to be the best way of achieving a media iframe with custom attributes.