Customize Meeting Summary: September 25th

This post summarizes the Customize meeting from September 25th in the #core-customize Slack channel (Slack archive).

Participants: @westonruter, @melchoyce, @obenland, @sirjonathan, @joemcgill, @sayedwp, @jbpaul17. Misbehaving: @tracbot.

Discussion highlights

Drafting and Scheduling

Gallery widget

Customizer UX for themes

Bug scrub

  • Trac listing of the enhancements and feature requests milestoned for 4.9 for the team
  • #39930: docs changes, so changing this from enhancement task ticket
  • #28721: related to and will be resolved when #39896 is merged
  • #34843: will be resolved by #37661
  • #35827: no one working on this, so punting to Future Release
  • #40527: punting
  • #40922: punting
  • #37964: will be picked up by @sayedwp when #39896 is done
  • #38707: CSS highlight part is implemented, but “revisions, selection, per-page, pop-out” is not
    • “per-page” aspect has been yanked from consideration in the near future
    • will work on revisions, selection, and pop-out in a feature plugin outside of core
  • #39275: likely to be resolved in #39896
  • #40104: @bpayton hopes to have a patch up by Friday
  • Topic for future devchat: What is the difference between a feature request and a feature project. It’s not really formalized. Are we deeming “feature request” to be the same as “feature project”?

Next week’s meeting

The next meeting will take place on Monday, October 2, 17:00 UTC in the #core-customize Slack channel. Please feel free to drop in with any updates, questions, or tickets you’d like to discuss. If you have items to discuss but cannot make the meeting, please leave a comment on this post so that we can take them into account.

#4-9, #bug-scrub, #core-customize, #media-widgets, #summary

Customize Meeting Summary: September 18th

This post summarizes the Customize meeting from September 18th in the #core-customize Slack channel (Slack archive).

Participants: @westonruter, @jbpaul17, @melchoyce.

Discussion highlights

CodeMirror (“Better Code Editing“)

  • @melchoyce to review three assigned tickets, #41872 being most urgent and other tickets with @mentions
  • @westonruter: working on ensuring the new CodeMirror-enhanced Custom CSS is compatible with Jetpack
    • Created a reusable “code editor” customizer control so that Jetpack can extend it, also for other plugins to add their own code editor controls easily
    • Need support from the Jetpack team to review and finish off the initial PR that I opened
    • @melchoyce: I’ll ping Jetpack folks this week once we’re all back from the Automattic Grand Meetup (most should be back by Wednesday)

Drafting and Scheduling

  • Best to wrap UX work, as @sayedwp has gotten started on that this week
  • @westonruter to get latest code pushed up to the test environment for review
  • @melchoyce: realized earlier this week that the apps have a similar draft/publish flow
    • @jbpaul17: Are we aligned with the flow there and if not should we align with what they have or open an Issue for them to update to what we’re working on for core?
    • @melchoyce: We are pretty close, I’ll compare side by side this week

Widgets

  • @westonruter: hoping to get the Core Media Widgets plugin updated with the new Gallery widget today for user testing so we can get it merged into core next week (#41914)

Bug scrub

Next week’s meeting

The next meeting will take place on Monday, September 25, 17:00 UTC in the #core-customize Slack channel. Please feel free to drop in with any updates, questions, or tickets you’d like to discuss. If you have items to discuss but cannot make the meeting, please leave a comment on this post so that we can take them into account.

#4-9, #bug-scrub, #core-customize, #media-widgets, #summary

Dev Chat Summary: September 20th (4.9 week 8)

This post summarizes the dev chat meeting from September 20th (agendaSlack archive).

4.9 schedule

  • 1 week until the feature project merge deadline, 2 weeks until Beta 1
  • Drafting and scheduling (#39896) has designs and is working through development
  • Gallery widget (#41914) is now available in the Core Media Widgets feature plugin, so please test that as we plan to merge it into core next week
  • Updating a plugin via ZIP (#9757) or drag/drop (#24579) is not getting any traction, so they will likely be punted
  • Review needed on #34115 to bring the ability to use oEmbed outside the context of posts
    • This allows the Text widget to have embeds in it, as well as to be able to remove the restriction on the Video widget to only show YouTube and Vimeo
  • Long list of Code Editor tickets that could use contributors
    • If you’re interested and capable with JS and playing with CodeMirror, #41873 is a great place to start
  • Any tickets related to goals in the 4.9 Goals post should be prioritized
  • Bug scrub post will be published with dates/times to scrub features and enhancements ahead of the Beta 1 deadline. If you’re interested in helping run a scrub, then please let @jbpaul17 know.
  • User testing needed on #39693, especially running it through a battery of theme switching tasks; the goal is to improve the “it just works” experience
    • Testing steps include installing a theme, populating sidebars with widgets, switching to another theme, and checking how the widgets appear in the newly switched theme
    • If you switch back to the old theme, the sidebar widgets get restored
    • Testing should be done when switching themes via the WP admin themes page, and also via live preview in the Customizer
    • Themes that have varying numbers of sidebars would be the key to test with. Switching from a theme with 2 sidebars, to one with 4, to another with 1, to another with 5, and so on.
    • If you want to have a public test environment set up with the patch to test, then please ping @westonruter

Editor update

General announcements

#4-9, #core, #core-editor, #dev-chat, #feature-oembed, #media-widgets, #security, #summary

Media Widgets for Images, Video, and Audio

As first introduced in the Image Widget Merge Proposal, WordPress 4.8 includes media widgets (#32417) for not only images (#39993) but also video (#39994) and audio (#39995), on top of an extensible base for introducing additional media widgets in the future, such as for galleries and playlists. To quote [40640]:

The last time a new widget 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 sidebar!

Since widgets are a very old part of WordPress (since 2.2), widgets in core have been very much entirely built using PHP 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 JavaScript, including with the Customizer in 3.4 and the Media Library in 3.5, and more recently with the focus on the REST API and the editor (Gutenberg).

Given that the media widgets are naturally interfacing with the media library JS, it is necessary that the media widgets make use of JavaScript to construct their UI 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 URL.

Initial groundwork for shimming JavaScript into widgets was added in 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. A more recent proposal for making JavaScript more of a first class citizen can be found in #33507 and the media widgets incorporate some of its patterns that were also prototyped in the JS Widgets plugin. 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
JS: 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.) The JSON 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 React rewrite and/or leveraging of corresponding blocks in 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.

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 HTML 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.) 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 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), 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:

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
JS: 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 CSS 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
JS: 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 shortcode logic supports rendering them via MediaElement.js. It is possible for plugins to add support for additional oEmbed providers via extending the video widget control’s isHostedVideo method; for more, see the Jetpack PR for adding VideoPress support.

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 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
JS: 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 plugin and on its corresponding wp-core-media-widgets GitHub repo. Many of the decisions that were made in the architecture of the feature can be found there in the GitHub issues and pull requests.

Keep in mind that the media widgets will likely undergo many more changes with the incorporation of the Gutenberg editor, 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 block into the editor, there should also be a widget available for representing the same content.

#4-8, #dev-notes, #media-widgets

Dev Chat Summary: May 10th (4.8 week 2)

This post summarizes the dev chat meeting from May 10th (agendaSlack archive).

4.8 Timing

  • Reminder of Beta 1 on Friday, the complete 4.8 schedule is on Make/Core
  • At this point we’re not trying to get anything in 4.8 besides the core media widgets, dashboard news upgrade, and the next version of TinyMCE (4.6.0)
  • Merge deadline goal to have the target features today (Wednesday, May 10th), and things generally closing on Friday, May 12th
  • Friday 8 PM UTC as pencils down and the beta packaging process / release to happen
  • We’ll schedule a post hoc debrief on our workflows to be more like Chrome, with frequent, major, auto-updates

4.8 Bug Scrubs

4.8 Dev Notes / Field Guide

  • Target to post Dev Notes shortly so they can be combined, published in, and communicated with the Field Guide when the Release Candidate ships around May 25th
  • Updated listing of Dev Notes needed and those responsible:
  • Per the Releasing Major Versions page, we should aim for Dev Notes around Beta 1 so let’s call that sometime next week as current focus is on actually getting to commit for Beta 1 this week

Customize, Editor, and REST API Updates

  • Customize: A general heads up to theme authors to please test the core medias widgets for compatibility issues. The sooner issues are identified the better to get them resolved before 4.8 ships.
  • Editor: They hope to tag a first pre-alpha release of the plugin this week, so keep your radars scanning for that notification to jump in to test and provide feedback there. If you’re curious how they’re building out the foundation of Gutenberg, then read “Editor: How Little Blocks Work“.
  • REST API: They would greatly appreciate any and all feedback on #38323, especially those of you familiar with meta. This isn’t crucial for 4.8, is crucial for many use cases and any help getting this into an upcoming release would be great.

#4-8, #core-customize, #core-editor, #core-restapi, #dev-chat, #media-widgets, #summary, #tinymce

Image Widget Merge Proposal


As part of this year’s Customization Focus, @westonruter, @obenland, @adamsilverstein, @timmydcrawford, @gonom9, and I have been working on creating an image widget for core. This new widget lets you quickly and easily add an image to your site’s widget areas.

You may have previously seen this come up as a media widget on Trac, before we decided to split the widget up into individual media-focused widgets. Having single widgets makes them more discoverable, and eases the way forward for similar blocks in the Editor. The image widget is the first in a series of media-focused widgets we’ll be introducing to core.

You can check out the widget on GitHub, install the plugin from WordPress.org, or check out the Trac ticket.

Why make an image widget?

People want to add images to their widget areas. Visit any subject blog across the internet and you’ll likely find images in the sidebars. People add photos of themselves along with bio blurbs, link to their books, promote upcoming events with graphics, partner with other blogs and exchange ads, and add call-to-actions using images.

The current process for adding an image to your widget areas is quite painful. You need to:

  1. Upload or select an image in your media library.
  2. Copy the image URL.
  3. Go to the widgets admin screen, or the widgets panel in the Customizer.
  4. Create a new Text widget.
  5. Add the image to the Text widget using HTML, which is often a barrier for new or non-technical site maintainers. (See #35243 for work to add a visual mode to Text widget.)

This is a huge barrier to what should be a relatively simple task. This new image widget makes it much easier to add an image to your widget areas by natively integrating with core’s media library.

How is it implemented?

There hasn’t been any new widget types added to core in a long time; the Custom Menu widget was the last widget added in WordPress 3.0—almost 7 years ago! (The core themes Twenty Eleven and Twenty Fourteen did include their Ephemera widgets since then.) Since widgets are a very old part of WordPress, widgets in core have been very much entirely built using PHP 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 JavaScript, including with the Customizer in 3.4 and the Media Library in 3.5, and more recently with the focus on the REST API.

Given that the media widgets are naturally interfacing with the media library JS, it is necessary that the media widgets make use of JavaScript to construct their UI instead of relying on PHP. Initial groundwork for shimming JavaScript into widgets was added in 3.9 via the widget-added and widget-updated events. A more recent proposal for making JavaScript more of a first class citizen can be found in #33507 and the media widgets incorporate some of its patterns that were also prototyped in the JS Widgets plugin. 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.

Another unique aspect of how the media widgets work is how instance data is sanitized. Normally widgets write 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.

Please test

Please test the image widget. For now, you can grab the latest version of the widget on GitHub. You can either check it out locally using Git, or download a zip by clicking “Clone or download” → “Download ZIP.” Alternately, you can download the nightly version of the plugin from the WordPress.org plugin directory.

#image-widget, #media-widgets