Title: Media Widgets for Images, Video, and Audio
Author: Weston Ruter
Published: May 26, 2017
Last modified: September 25, 2017

---

 [  ](https://profiles.wordpress.org/westonruter/) [Weston Ruter](https://profiles.wordpress.org/westonruter/)
6:30 pm _on_ May 26, 2017     
Tags: [4.8 ( 31 )](https://make.wordpress.org/core/tag/4-8/),
[dev-notes ( 648 )](https://make.wordpress.org/core/tag/dev-notes/), [media-widgets ( 3 )](https://make.wordpress.org/core/tag/media-widgets/)

# Media Widgets for Images, Video, and Audio

As first introduced in the [Image Widget Merge Proposal](https://make.wordpress.org/core/2017/04/12/image-widget-merge-proposal/),
WordPress 4.8 includes media widgets ([#32417](https://core.trac.wordpress.org/ticket/32417))
for not only **images** ([#39993](https://core.trac.wordpress.org/ticket/39993))
but also **video** ([#39994](https://core.trac.wordpress.org/ticket/39994)) and **
audio** ([#39995](https://core.trac.wordpress.org/ticket/39995)), on top of an extensibleExtensible
This is the ability to add additional functionality to the code. Plugins extend 
the WordPress core software. base for introducing additional media widgets in the
future, such as for galleries and playlists. To quote [[40640]](https://core.trac.wordpress.org/changeset/40640):

> The last time a new widgetWidget A WordPress Widget is a small block that performs
> a specific function. You can add these widgets in sidebars also known as widget-
> ready areas on your web page. WordPress widgets were originally created to provide
> a simple and easy-to-use way of giving design and structure control of the WordPress
> theme to the user. was introduced, Vuvuzelas were a thing, Angry Birds started
> taking over phones, and WordPress stopped shipping with Kubrick. Seven years and
> 17 releases without new widgets have been enough, time to spice up your sidebarSidebar
> A sidebar in WordPress is referred to a widget-ready area used by WordPress themes
> to display information that is not a part of the main content. It is not always
> a vertical column on the side. It can be a horizontal rectangle below or above
> the content area, footer, header, or any where in the theme.!

Since widgets are a very old part of WordPress (since 2.2), widgets in coreCore 
Core is the set of software required to run WordPress. The Core Development Team
builds WordPress. have been very much entirely built using PHPPHP The web scripting
language in which WordPress is primarily architected. WordPress requires PHP 7.4
or higher with some Ajax sprinkled on top. In the time since `WP_Widget` was introduced
in 2.8, WordPress has made dramatic shifts toward developing interfaces in JavaScriptJavaScript
JavaScript or JS is an object-oriented computer programming language commonly used
to create interactive effects within web browsers. WordPress makes extensive use
of JS for a better user experience. While PHP is executed on the server, JS executes
within a user’s browser. [https://www.javascript.com](https://www.javascript.com/),
including with the CustomizerCustomizer Tool built into WordPress core that hooks
into most modern themes. You can use it to preview and modify many of your site’s
appearance settings. in 3.4 and the Media Library in 3.5, and more recently with
the focus on the REST APIREST API The REST API is an acronym for the RESTful Application
Program Interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data.
It is how the front end of an application (think “phone app” or “website”) can communicate
with the data store (think “database” or “file system”) [https://developer.wordpress.org/rest-api/](https://developer.wordpress.org/rest-api/)
and the editor ([Gutenberg](https://github.com/WordPress/gutenberg)).

Given that the media widgets are naturally interfacing with the media library JSJS
JavaScript, a web scripting language typically executed in the browser. Often used
for advanced user interfaces and behaviors., it is necessary that the media widgets
make use of JavaScript to construct their UIUI User interface instead of relying
on PHP. The media widgets fully reuse the existing media modal frames for not only
selecting the media to display but also to edit all of its properties: attachments
can be selected from the media library, while external media can be inserted by 
URLURL A specific web address of a website or web page on the Internet, such as 
a website’s URL www.wordpress.org.

Initial groundwork for shimming JavaScript into widgets was [added in 3.9](https://make.wordpress.org/core/2014/04/17/live-widget-previews-widget-management-in-the-customizer-in-wordpress-3-9/)
via the `widget-added` and `widget-updated` events, which are also being utilized
in 4.8 with the [Addition of TinyMCE to the Text Widget](https://make.wordpress.org/core/2017/05/23/addition-of-tinymce-to-the-text-widget/).
A more recent proposal for making JavaScript more of a first class citizen can be
found in [#33507](https://core.trac.wordpress.org/ticket/33507) and the media widgets
incorporate some of its patterns that were also prototyped in the [JS Widgets](https://github.com/xwp/wp-js-widgets)
pluginPlugin A plugin is a piece of software containing a group of functions that
can be added to a WordPress website. They can extend functionality or add new features
to your WordPress websites. WordPress plugins are written in the PHP programming
language and integrate seamlessly with WordPress. These can be free in the WordPress.
org Plugin Directory [https://wordpress.org/plugins/](https://wordpress.org/plugins/)
or can be cost-based plugin from a third-party.. The media widgets make use of a
Backbone View to manage the widget control’s UI and a Backbone Model for reading
and manipulating the widget instance data.

## Base Media Widget

PHP: [`wp-includes/widgets/class-wp-widget-media.php`](https://core.trac.wordpress.org/browser/trunk/src/wp-includes/widgets/class-wp-widget-media.php)

JS: [`wp-admin/js/widgets/media-widgets.js`](https://core.trac.wordpress.org/browser/trunk/src/wp-admin/js/widgets/media-widgets.js)

The three widgets all extend a `WP_Widget_Media` PHP abstract class; in JS the Backbone
view `wp.mediaWidgets.MediaWidgetControl` and `wp.mediaWidgets.MediaWidgetModel`
are extended. A unique aspect of how the media widgets work is how instance data
is validated and sanitized. Normally widgets utilize procedural code to sanitize
instances via a subclassed `WP_Widget::update()` method. The media widgets, however,
make use of a REST API schema returned from `WP_Widget_Media::get_instance_schema()`
to sanitize instances declaratively. The `WP_Widget_Media::update()` method iterates
over the schema and uses it to sanitize and validate the instance properties. (Adding
schemas to the base `WP_Widget` class is also proposed in [#35574](https://core.trac.wordpress.org/ticket/35574).)
The JSONJSON JSON, or JavaScript Object Notation, is a minimal, readable format 
for structuring data. It is used primarily to transmit data between a server and
web application, as an alternative to XML. schema is extended to include a couple
custom properties: `media_prop` provides the media JS property name that the widget
instance maps, and the `should_preview_update` flag indicates whether a change to
that prop should cause the control preview to re-render (this would be retired with
a ReactReact React is a JavaScript library that makes it easy to reason about, construct,
and maintain stateless and stateful user interfaces. [https://reactjs.org](https://reactjs.org/)
rewrite and/or leveraging of corresponding blocks in GutenbergGutenberg The Gutenberg
project is the new Editor Interface for WordPress. The editor improves the process
and experience of creating new content, making writing rich content much simpler.
It uses ‘blocks’ to add richness rather than shortcodes, custom HTML etc. [https://wordpress.org/gutenberg/](https://wordpress.org/gutenberg/)).

The `WP_Widget_Media` abstract class has one abstract method which subclasses must
implement: `WP_Widget_Media::render_media()`. This is the method that `WP_Widget_Media::
widget()` calls with the `$instance` props to render the media for a given widget
media type. Before the props are passed to the method, the `$instance` is applied
through  `widget_{$id_base}_instance` filters.

A media widget subclass should output additional JS templates as the control needs
by extending `WP_Widget_Media::render_control_template_scripts()`. Scripts that 
the widget control requires can be enqueued by extending `WP_Widget_Media::enqueue_admin_scripts()`;
this is also where the PHP exports can be done with calls to `wp_add_inline_script()`.

The REST API schema is exported from PHP to JS on the subclassed `MediaWidgetModel`
prototypes. Other properties on the prototypes which should be extended include `
l10n` and `mime_type`. The model subclasses are registered by assigning them to 
the `wp.mediaWidgets.modelConstructors` object, keyed by the widget ID base (e.g.`
media_image`, `media_video`, etc). In the same way, the Backbone View `wp.mediaWidgets.
MediaWidgetControl` is subclassed and registered by adding to the `wp.mediaWidgets.
controlConstructors` object, also keyed by widget ID base. This is similar to how
control types are registered in the Customizer.

The `MediaWidgetControl` and `MediaWidgetModel` will be instantiated once a widget
control is _expanded_. Their instances will be then added to the `wp.mediaWidgets.
widgetControls` object and `wp.mediaWidgets.modelCollection` respectively.

There is a subclass of a media controller and a couple media views in the `wp.mediaWidgets`
namespace. These extensions to media classes are needed due to current limitations
in media extensibility. They may be removed/reduced with improvements in [#40427](https://core.trac.wordpress.org/ticket/40427).

As with the incorporation of TinyMCE into the Text widget, the incorporation of 
the media library into the media widget has necessitated constructing the widget’s
form fields differently than how they are normally done. Widgets in core have historically
utilized static HTMLHTML HyperText Markup Language. The semantic scripting language
primarily used for outputting content in web browsers. for their control form fields.
Every time a user hits “Save” the form fields get sent in an Ajax request which 
passes them to the `WP_Widget::update()` method and then the Ajax response sends
back the output of `WP_Widget::form()` which then replaces the entire form. (Note
widgets in the Customizer behave differently since there is no Save button in the
widget, as updates are synced and previewed as changes are made; read more about
[Live Widget Previews](https://make.wordpress.org/core/2014/04/17/live-widget-previews-widget-management-in-the-customizer-in-wordpress-3-9/).)
This worked for static HTML forms in the past, but in the case of the media widgets
the UI built with JavaScript instead of server-side PHP.

To avoid having to rebuild the media preview every time the user hits Save on the
adminadmin (and super admin) screen, the media widget puts its UI elements outside
of the container that is “managed” by the server which gets replaced with each save.(
A similar approach has also been employed by the new TinyMCE-extended Text widget
in 4.8.) Since core does not yet represent a widget’s state in a JavaScript model(
again see [#33507](https://core.trac.wordpress.org/ticket/33507)), the media widget
syncs its `MediaWidgetModel` props with hidden inputs that get rendered by `WP_Media_Widget::
form()` in order to be sent to the server for preview and saving. The container 
for the media widget’s fields is `.media-widget-control` and the traditional container
for a widget’s input fields as rendered by `WP_Widget::form()` is `.widget-content`:

![](https://make.wordpress.org/core/files/2017/05/media-video-widget-dom.png)

For examples of how to implement media widgets, see the three implementations included
in 4.8 as follows.

## Image Widget

PHP: [`wp-includes/widgets/class-wp-widget-media-image.php`](https://core.trac.wordpress.org/browser/trunk/src/wp-includes/widgets/class-wp-widget-media-image.php)

JS: [`wp-admin/js/widgets/media-image-widget.js`](https://core.trac.wordpress.org/browser/trunk/src/wp-admin/js/widgets/media-image-widget.js)

  |  Field |  Type |  Default |  Description |  
 |  `attachment_id` |  integer |  `0` |  Attachment post ID |  
 |  `url` |  string |  `""` |  URL to the media file |  
 |  `title` |  string |  `""` |  Title for the widget |  
 |  `size` |  string |  `"medium"` |  Size |  
 |  `width` |  integer |  `0` |  Width |  
 |  `height` |  integer |  `0` |  Height |  
 |  `caption` |  string |  `""` |  Caption |  
 |  `alt` |  string |  `""` |  Alternative Text |  
 |  `link_type` |  string |  `"none"` |  Link To |  
 |  `link_url` |  string |  `""` |  URL |  
 |  `image_classes` |  string |  `""` |  Image CSSCSS Cascading Style Sheets. Class |  
 |  `link_classes` |  string |  `""` |  Link CSS Class |  
 |  `link_rel` |  string |  `""` |  Link Rel |  
 |  `link_target_blank` |  boolean |  `false` |  Open link in a new tab |  
 |  `image_title` |  string |  `""` |  Image Title Attribute |

## Video Widget

PHP: [`wp-includes/widgets/class-wp-widget-media-video.php`](https://core.trac.wordpress.org/browser/trunk/src/wp-includes/widgets/class-wp-widget-media-video.php)

JS: [`wp-admin/js/widgets/media-video-widget.js`](https://core.trac.wordpress.org/browser/trunk/src/wp-admin/js/widgets/media-video-widget.js)

The video widget allows for embeddable video formats to be selected from the media
library or linked to externally by URL. In addition, URLs to YouTube or Vimeo may
also be provided since the `video` shortcodeShortcode A shortcode is a placeholder
used within a WordPress post, page, or widget to insert a form or function generated
by a plugin in a specific location on your site. logic supports rendering them via
MediaElement.js. It is possible for plugins to add support for additional oEmbed
providers via [extending](https://core.trac.wordpress.org/ticket/40808#comment:9)
the video widget control’s `isHostedVideo` method; for more, see the Jetpack PR 
for [adding VideoPress support](https://github.com/Automattic/jetpack/pull/7215).

  |  Field |  Type |  Default |  Description |  
 |  `attachment_id` |  integer |  `0` |  Attachment post ID |  
 |  `url` |  string |  `""` |  URL to the media file |  
 |  `title` |  string |  `""` |  Title for the widget |  
 |  `preload` |  string |  `"metadata"` |  Preload |  
 |  `loop` |  boolean |  `false` |  LoopLoop The Loop is PHP code used by WordPress to display posts. Using The Loop, WordPress processes each post to be displayed on the current page, and formats it according to how it matches specified criteria within The Loop tags. Any HTML or PHP code in the Loop will be processed on each post. [https://codex.wordpress.org/The_Loop](https://codex.wordpress.org/The_Loop) |  
 |  `content` |  string |  `""` |  Tracks (subtitles, captions, descriptions, chapters, or metadata) |  
 |  `mp4` |  string |  `""` |  URL to the mp4 video source file |  
 |  `m4v` |  string |  `""` |  URL to the m4v video source file |  
 |  `webm` |  string |  `""` |  URL to the webm video source file |  
 |  `ogv` |  string |  `""` |  URL to the ogv video source file |  
 |  `flv` |  string |  `""` |  URL to the flv video source file |

Note that the presence of format-specific fields is dependent on what is returned
by `wp_get_video_extensions()`.

## Audio Widget

PHP: [`wp-includes/widgets/class-wp-widget-media-audio.php`](https://core.trac.wordpress.org/browser/trunk/src/wp-includes/widgets/class-wp-widget-media-audio.php)

JS: [`wp-admin/js/widgets/media-audio-widget.js`](https://core.trac.wordpress.org/browser/trunk/src/wp-admin/js/widgets/media-audio-widget.js)

The audio widget allows for embeddable audio formats to be selected from the media
library or linked to externally by URL. Note that there are no oEmbed audio formats
supported since the `audio` shortcode logic only supports rendering players for 
actual audio files.

  |  Field |  Type |  Default |  Description |  
 |  `attachment_id` |  integer |  `0` |  Attachment post ID |  
 |  `url` |  string |  `""` |  URL to the media file |  
 |  `title` |  string |  `""` |  Title for the widget |  
 |  `preload` |  string |  `"none"` |  Preload |  
 |  `loop` |  boolean |  `false` |  Loop |  
 |  `mp3` |  string |  `""` |  URL to the mp3 audio source file |  
 |  `ogg` |  string |  `""` |  URL to the ogg audio source file |  
 |  `m4a` |  string |  `""` |  URL to the m4a audio source file |  
 |  `wav` |  string |  `""` |  URL to the wav audio source file |

Note that the presence of format-specific fields is dependent on what is returned
by `wp_get_audio_extensions()`.

## Default Themes Updates

Themes that add custom styles to the MediaElement.js player (namely Twenty Thirteen
and Twenty Fourteen) were updated from just styling it within syndicated content,
to also include instances within widgets. Most themes don’t restrict styles for 
captioned images or media players to just post content, that is, limit CSS selectors
to classes output by `post_class()`. If your theme does, make sure to either remove
that constraint or include a `.widget` selector.

## Conclusion

The work on the new media widgets in core was conducted in the [Core Media Widgets](https://wordpress.org/plugins/wp-core-media-widgets/)
plugin and on its corresponding [wp-core-media-widgets](https://github.com/xwp/wp-core-media-widgets)
GitHubGitHub GitHub is a website that offers online implementation of git repositories
that can easily be shared, copied and modified by other developers. Public repositories
are free to host, private repositories require a paid subscription. GitHub introduced
the concept of the ‘pull request’ where code changes done in branches by contributors
can be reviewed and discussed before being merged by the repository owner. [https://github.com/](https://github.com/)
repo. Many of the decisions that were made in the architecture of the feature can
be found there in the GitHub [issues](https://github.com/xwp/wp-core-media-widgets/issues?q=is%3Aissue)
and [pull requests](https://github.com/xwp/wp-core-media-widgets/issues?q=is%3Apull-request).

Keep in mind that the media widgets will likely undergo many more changes with the
incorporation of the [Gutenberg editor](https://github.com/WordPress/gutenberg),
and that widgets themselves will likely see many changes to align with Gutenberg’s
editor blocks which are now being prototyped. Essentially if you can insert a given
type of blockBlock Block is the abstract term used to describe units of markup that,
composed together, form the content or layout of a webpage using the WordPress editor.
The idea combines concepts of what in the past may have achieved with shortcodes,
custom HTML, and embed discovery into a single consistent API and user experience.
into the editor, there should also be a widget available for representing the same
content.

[#4-8](https://make.wordpress.org/core/tag/4-8/), [#dev-notes](https://make.wordpress.org/core/tag/dev-notes/),
[#media-widgets](https://make.wordpress.org/core/tag/media-widgets/)

### Share this:

 * [  Threads ](https://make.wordpress.org/core/2017/05/26/media-widgets-for-images-video-and-audio/?share=threads)
 * [  Mastodon ](https://make.wordpress.org/core/2017/05/26/media-widgets-for-images-video-and-audio/?share=mastodon)
 * [  Bluesky ](https://make.wordpress.org/core/2017/05/26/media-widgets-for-images-video-and-audio/?share=bluesky)
 * [  X ](https://make.wordpress.org/core/2017/05/26/media-widgets-for-images-video-and-audio/?share=x)
 * [  Facebook ](https://make.wordpress.org/core/2017/05/26/media-widgets-for-images-video-and-audio/?share=facebook)
 * [  LinkedIn ](https://make.wordpress.org/core/2017/05/26/media-widgets-for-images-video-and-audio/?share=linkedin)

 1.  ![](https://secure.gravatar.com/avatar/1b897c989a31146a098d41d9cd07baf4895d40c47f959dd2f4bf023d973db012?
     s=32&d=mm&r=g)
 2.   [Lee Hodson](https://profiles.wordpress.org/leehodson/)  7:01 pm _on_ May 26,
     2017
 3.  A slight twist from the post but in many ways related to it, I would like to see
     [Admin Page Framework](https://github.com/michaeluno/admin-page-framework) (or
     similar) added to coreCore Core is the set of software required to run WordPress.
     The Core Development Team builds WordPress.. It seems odd to me that we have custom
     post types for the frontend and a framework to use to develop for the frontend
     but we are missing a proper core component framework to create adminadmin (and
     super admin) pages and add metaMeta Meta is a term that refers to the inside workings
     of a group. For us, this is the team that works on internal WordPress sites like
     WordCamp Central and Make WordPress. boxes to admin pages.
 4.  Michael Uno, the developer and maintainer of Admin Page Framework, is highly responsive
     to ideas and feature suggestions, which is one of the reasons I suggest this particular
     framework. Another reason for this suggestion is that it covers both admin pages
     and widgets.
 5.  I think we need a conversation not just around new widgets but around the framework
     used to create widgets and the possibility of incorporating a backend development
     framework into core. I vote for Admin Page Framework.
 6.  ![](https://secure.gravatar.com/avatar/7a36060ae08c0b5588810cd5e6ea430fe9b10ce7ca8debbe928a1e254e78b4d4?
     s=32&d=mm&r=g)
 7.   [Paul Biron](https://profiles.wordpress.org/pbiron/)  2:36 am _on_ May 27, 2017
 8.  hey, nice list of new/modified hooksHooks In WordPress theme and development, 
     hooks are functions that can be applied to an action or a Filter in WordPress.
     Actions are functions performed when a certain event occurs in WordPress. Filters
     allow you to modify certain functions. Arguments used to hook both filters and
     actions look the same. you have there 🙂
 9.   * ![](https://secure.gravatar.com/avatar/7a36060ae08c0b5588810cd5e6ea430fe9b10ce7ca8debbe928a1e254e78b4d4?
        s=32&d=mm&r=g)
      *  [Paul Biron](https://profiles.wordpress.org/pbiron/)  2:37 am _on_ May 27,
        2017
      * oops, replied to wrong post

Comments are closed.

# Post navigation

[← Tag Cloud widget changes in 4.8](https://make.wordpress.org/core/2017/05/26/tag-cloud-widget-changes-in-4-8/)

[WordPress 4.8 Field Guide →](https://make.wordpress.org/core/2017/05/26/wordpress-4-8-field-guide/)