WordPress 4.8 Field Guide

WordPress 4.8 is officially the best WordPress 2017 has seen!  Users will receive new and refined features focused on Editing and Customizing their sites while developers will be able to take advantage of 109 enhancements and features added.  Let’s look at the many improvements coming in 4.8…

 

Media Widgets

Not one, not two, but three new media widgets make their way into core. It’s like the AV crew just showed up and now the party can really begin. You get an audio widget. You get an image widget. You get a video widget. Check under your seat, media widgets for everyone!

Media Widgets for Images, Video, and Audio

 

Fabulously Rich Text Widget

Robin Hood has come to town and is handing out rich text editing to all the text widgets. No more having to manually type out your HTML in text widgets like it’s 2016.

Addition of TinyMCE to the Text Widget

 

Simpler Link Editing, Streamlined Browser Support, and Editor Instantiation via JS

Editing just got a lot easier, you can thank us later. But trust us that adding and managing links within the editor is now easier than ever. If you don’t trust us, then just try navigating in and out of links with your arrow keys. Pretty cool, huh? That’s the new TinyMCE inline element / link boundaries. As for the reduced browser support, let’s just say IE 8, 9, and 10 have been thanked for their service but can feel free to enjoy their retirement. Also, if bootstrapping the TinyMCE content editor dynamically via JS is your thing, then boy are you going to be excited!

Editor changes in 4.8

Editor API changes in 4.8

 

WMV and WMA get retirement packages

Remember Silverlight? Many browsers these days don’t. So the file formats which require the presence of the Silverlight plugin are being removed from core support. Files will still display as a download link, but will no longer be embedded automatically.

Removal of core embedding support for WMV and WMA file formats

 

Resizing the Customizer sidebar

If you have used the Customizer on a high-resolution screen, then you may have noticed that the Customizer sidebar… suboptimally narrow. The sidebar is now variable width based on screen size to help you receive the best editing experience possible.

Customizer sidebar width is now variable

 

WordCamps and meetups all up in your admin dashboard

One of the best things about WordPress is its community. You can now read about WordCamps and meetups in your area right within your dashboard. No more excuses for missing the speaker or volunteer deadlines now!

Nearby WordPress Events

Showing upcoming local events in wp-admin

 

Mu will really love these multisite changes

We know you love superheroes but is_super_admin() needs to go. So while we’re replacing that with appropriate capabilities, we’re also treating you to some new hooks and a new $network_id parameter that gets wide usage across several functions.

Multisite Focused Changes in 4.8

 

Accessibility: saving the best for last

As a part of ongoing efforts to improve accessibility in WordPress, 4.8 includes some changes to headings within admin screens. This is a continuation of the work started in 4.3 on restoring the H1 (heading level 1) to the admin screens and continued in 4.4 with the introduction of a better headings hierarchy. Also improved is the Tag Cloud widget, now swapping out the title attributes in favor of aria-label attributes.

Cleaner headings in the admin screens

Tag Cloud widget changes in 4.8

 

But Wait, There is More!

Roughly 217 bugs, 108 enhancements, 1 feature request, and 16 blessed tasks have been marked as closed in WordPress 4.8. Some additional ones to highlight include:

  • REST API: orderby normalization (#38693)
  • REST API: Add supports object to /types response (#39033)
  • New filter to disable auto-focus on the login screen (#40301)
  • Screencast.com was added as an oEmbed provider (#38367)
  • HHVM removed from the test matrix on Travis (#40548)
  • Bundled Themes now support the new media and updated text widgets (#40745)
  • Popular plugins feed has been removed from the dashboard (#40702)
  • Support added for Bosnian locale (bs_BA) in remove_accents() (#39658)
  • Easily enqueue WP_Editor JavaScript files using the new wp_enqueue_editor() (#35760)

New Action Hooks

  • deleted_blog (#25584)
  • print_default_editor_scripts (#35760)

New Filter Hooks

  • file_mod_allowed replaces disallow_file_mods (#38673)
  • minimum_site_name_length (#39676)
  • nav_menu_submenu_css_class (#36163)
  • page_menu_link_attributes (#40359)
  • post_date_column_status (#39545)
  • signup_site_meta (#39223)
  • signup_user_meta (#39223)
  • wp_doing_cron (#39591)
  • widget_text_content (#40772)
  • rest_oembed_ttl (#40450)
  • widget_{$this->id_base}_instance (#32417)

Modified Filter Hooks

  • widget_text_content (#40772)
  • {$type}_template (#39525)
  • display_media_states (#39628)
  • media_library_show_audio_playlist (#31071)
  • media_library_show_video_playlist (#31071)
  • rest_pre_insert_comment (#39578)
  • wp_is_large_network (#40489)

External Library Updates

  • TinyMCE was updated from version 4.5.6 to version 4.6.2 (see: #40859).
  • Twemoji was updated from version 2.2.2 to version 2.3.0 (see: #40858).
  • zxcvbn was updated from version 1.0 to version 4.4.1 (see: #31647).

Please, test your code. That bears repeating: Please, test your code. Fixing issues now, before 4.8 is released, helps you and helps millions of WordPress sites. Please. Test. Your. Code.

#4-8, #dev-notes, #field-guide

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.

Tag Cloud widget changes in 4.8

The Tag Cloud widget is still pretty popular and for a number of years, it has used title attributes to visually display the number of posts using a specific tag.

tag cloud in WordPress 4.7

Example of a title attribute displaying the number of items for a specific tag in WordPress 4.7

WordPress 4.8 removes these title attributes and replaces them with aria-label attributes with optional counts displayed in plain text.

Why it matters

Title attributes aren’t very accessible. Depending on the specific assistive technology and on user settings, they might be completely ignored. On touch devices, title attributes are a bit pointless.

The best option is not to rely on title attributes to convey important information to users. Information that is important enough should be available to all users.

In the last few releases, WordPress has been progressively removing many title attributes used in the admin screens (see: #24766). The same principle applies to the front end. The Tag Cloud widget is another step towards the progressive removal of title attributes in the front end where they’re used inappropriately.

What plugin or theme authors should know

There are no visual changes by default, other than the removal of the title attributes. There is a new option for developers though: tag counts can be displayed in plain text within the list of tags. Users will now find a checkbox in the widget interface, consistent with what other widgets already do (e.g., Archives and Categories widgets).

the tag cloud widget admin interface

The new option “Show tag counts” in the widget admin interface

Checking the “Show tag counts” option in the admin will make the Tag Cloud show the counts alongside each tag. The screenshot below compares the Tag Cloud with and without the counts displayed:
the Tag Cloud with and without tag counts

Themes can style the tag counts targeting the new CSS class tag-link-count. Also, note that wp_generate_tag_cloud() has a new show_count argument. Themes and plugins that filter the Tag Cloud arguments can use this new argument to force the tag counts to be displayed.

Theme authors are recommended to check how the tag counts look like in their themes and make small CSS adjustments if needed. And remember, the tag counts are not displayed by default! Users can enable and also disable them at any time.

Some technical details

The relevant changeset is [40816] and the related ticket is #35566. Behind the scenes, the tag cloud now attempts to determine whether to output the aria-label attribute, trying to respect the theme author’s intent.

By default, the Tag Cloud displays tags in different font sizes to visually represent how many times they’re used. When tags have a different font size, they visually convey important information that should also be available to assistive technologies.

Sometimes instead, theme authors set up the Tag Cloud to display all tags with the same font size. Twenty Sixteen, for example, displays all the tags with a “flat” styling. It does that by filtering the arguments passed to wp_generate_tag_cloud() and setting the smallest and largest arguments to the same value (note: this is the recommended way to output “flat” tags).

In order to always serve the same information to all users and try to respect the theme author’s intent, the aria-label that conveys the count information to assistive technologies gets printed out:

  • when tags have a different size
  • when the tag count is displayed in plain text (for example when users check the checkbox in the Tag Cloud widget), regardless of the tags font size

A quick update about title attributes

To give an idea of the progress done so far, here’s data from the WordPress codebase from version 4.0 to 4.7. Searching for occurrences of  title= (space-title-equal) only within .php files and only in the wp-admin directory:

WordPress 4.0: 157 results found in 37 files
WordPress 4.1: 156 results found in 37 files
WordPress 4.2: 146 results found in 35 files
WordPress 4.3: 101 results found in 30 files
WordPress 4.4: 97 results found in 32 files
WordPress 4.5: 21 results found in 12 files
WordPress 4.6: 19 results found in 11 files
WordPress 4.7: 17 results found in 9 files

Of the 17 title attributes in WordPress 4.7, four of them are legitimate because they’re used on <iframe> elements and most of the other ones are in files no longer used by core. Many of these occurrences were within loops so the number of title attributes actually output was higher, yet going from 157 down to a very few is wonderful progress.

As always, any comments and contribution to improving accessibility are welcome!

#4-8, #accessibility, #dev-notes

HHVM no longer part of WordPress core’s testing infrastructure

WordPress has never officially supported HHVM, but since WordPress 4.0 it has been compatible, largely thanks to the efforts of @wonderboymusic in #27881 and other tickets.

Many large scale sites which switched to HHVM around 2014 have since switched to PHP 7, and usage numbers of HHVM according to the wordpress.org update statistics indicate that HHVM powers only several dozen WordPress websites as of April 2017.

Core’s unit test suite when run on HHVM never actually passed (this may not be completely accurate, memories are hazy), often errored completely, and was always marked as an allowed failure. All of this, coupled with the disproportionately high amount of effort required to maintain the test and CI infrastructure for HHVM, means that WordPress core is no longer tested on HHVM as part of the Travis CI build. See #40548 for details.

If you’re running a WordPress website on HHVM, you should consider switching to PHP 7+ which is far more widely supported and tested, and offers all of the memory and performance benefits that HHVM pushed forward.

Dev Chat Summary: May 24th (4.8 week 4)

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

4.8 Timing

  • Beta 1 went out on Friday, May 12th; Beta 2 went out on Monday, May 22nd
  • RC1 is scheduled for Thursday, May 25th
  • With RC1 we’re aiming for a soft string freeze so that translators can work through all the new strings in 4.8
  • Should things continue to go to plan, RC2 would be next Thursday, June 1st

4.8 Bug Scrubs

4.8 Dev Notes / Field Guide

  • Goal is to have Dev Notes all done ASAP so we can assemble the Field Guide by RC1
  • Remaining Dev Notes to get published:
  • Listing of all tickets tagged with needs-dev-note

About Page

  • #40721: dev help needed writing copy for the Under the Hood section, please ping @melchoyce if you can help

#4-8, #dev-chat, #summary

Editor changes in 4.8

There are couple of noteworthy changes to the editor in WordPress 4.8.

A much better experience when trying to place the cursor around links. Try inserting a link, then move the cursor with the left and right arrow keys. You can clearly see when it is inside the link element and when it is before or after it.

Following the earlier announcement, support for Internet Explorer 8, 9, and 10 has been removed from the editor.

As always there have been a lot of improvements and bug fixes, upstream in TinyMCE, and in core.

#4-8, #editor

Week in Core, May 17th – 23th 2017

Welcome back the latest issue of Week in Core, covering changes [40771-40826]. Here are the highlights:

  • 56 commits
  • 75 contributors
  • 70 tickets created
  • 7 tickets reopened
  • 71 tickets closed

Ticket numbers based on trac timeline for the period above. The following is a summary of commits, organized by component.

Code Changes

Accessibility

Administration

  • Fix some HTML validation errors. [40823] #37004
  • Update the docs for wp_check_browser_version(). [40822] #40839
  • Dashboard: Change the cache key for dashboard RSS widget; remove the unnecessary database upgrade routine. [40803] #40702
  • Dashboard: Append the current locale to dashboard RSS widget cache key in wp_dashboard_rss_control(), for consistency with the changes to wp_dashboard_cached_rss_widget() in [33183] and [33192]. [40802] #32804, #40702
  • Dashboard: Don’t trigger an Events search when the search field is empty. [40799] #40816
  • Dashboard: Improve the Events widget spinner position after [40789]. [40794] #40735
  • Dashboard: Improve the handling of locations determined by geolocating the IP address and by entering a city name. Fix couple of edge cases, and some names. [40790] #40702
  • Dashboard: [40789] #40735
  • Dashboard: Combine methods to retreive IP [40781] #40702
  • Use consistent spacing for form elements in the Discussion Settings screen. [40779] #31594
  • Dashboard: Document request proxy for events. [40777] #40702
  • Dashboard: Properly localize data for events [40776] #40702
  • Dashboard: Always pass the IP when getting events [40774] #40702
  • Upgrade: Use correct commit no. to trigger upgrade [40773] #40702

Build/Test Tools

  • Remove mentions of HHVM from the test infrastructure on Travis for the 4.6 branch. [40818] #40548

Bundled Theme

  • Twenty Seventeen: Remove uneccessary return statement [40795] #40516

Customize

  • Docs: Improve phpdoc for WP_Customize_Manager, WP_Customize_Control, WP_Customize_Setting, and WP_Customize_Selective_Refresh. [40804] #39671
  • Docs: Add missing @since tags and phpdoc descriptions to the Custom_Image_Header class. [40788] #21785, #40231
  • Run a partial’s fallback behavior (full refresh) when selective refresh fails due to a script error. [40771] #27355, #40658

Help/About

I18N

  • Dashboard: Use get_user_locale() for the news feed cache key. [40793] #40417

Login and Registration

  • Add some margin to notices on the login screen so multiple notices remain separated. [40778] #39971

Media

Misc

  • Themes: Skip tests if ReflectionMethod::setAccessible is unavailable [40826] #
  • Post-4.8 Beta 2 bump. [40820] #
  • WordPress 4.8 Beta 2 ([40807] again) [40819] #
  • Revert [40807] unbumping from 4.8 Beta 2 back to Beta 1 due to aborted release. [40808] #
  • WordPress 4.8 Beta 2 [40807] #
  • Updates for 4.6. Merge of and to the 4.6 branch.

Quick/Bulk Edit

REST API

  • Fix changing parameters with set_param() for some requests. [40815] #40344
  • Avoid sending blank Last-Modified headers with authenticated requests. [40805] #40444
  • Do not set X-WP-Deprecated* headers as often. [40782] #40787

Themes

TinyMCE

  • Fix selecting the link node after creating a link by pasting an URL. [40801] #40818
  • Editor: When stripping paragraph tags, and there is a <br> at the beginning or the end, merge them and keep the paragraph, not the <br>. [40787] #37066
  • Fix pasting while an image with caption is selected. The image and the caption should be replaced with the pasted content. [40786] #40809
  • Provide styles for link and code boundaries. [40783] #40767

Users

  • Multisite: Handle both role change selections in site-users.php. [40780] #40113

Widgets

  • Further refine WP JS coding style in media widgets code. [40821] #32417
  • Remove core embedding support for WMV and WMA files since MediaElement.js has discontinued supporting them. [40813] #39994, #39995, #40819
  • Clarify some context information for translators. [40812] #32417, #39993, #39994, #39995
  • Remove unused JS variable to fix JSHint error introduced in [40640]. [40811] #39994
  • Introduce isHostedVideo method on VideoWidgetControl to allow plugins to extend for recognizing services beyond YouTube and Vimeo. [40810] #39994, #40808
  • Revert [40251] pending more accessible solution for showing default widget titles rather than using placeholders. [40806] #39909
  • Ensure title field for media widget will update with sanitized value after change event in addition to input event. [40785] #32417, #40805
  • Use “Add Audio” for button in Audio widget instead of generic “Add File”. [40784] #39995, #40797
  • Media: Trim whitespace in URLs provided for external embeds. [40772] #40771

Thanks to @4nickpick, @abhishekfdd, @adamsilverstein, @adamsoucie, @afercia, @arena, @arshidkv12, @azaozz, @BharatKambariya, @bradyvercher, @bridgetwillard, @coffee2code, @coreymckrill, @darshan02, @dd32, @desrosj, @emirpprime, @gma992, @iandunn, @iandunn, @iseulde, @Italian polyglots team, @iv3rson76, @jenblogs4u, @jeremyfelt, @jjcomack, @jnylen0, @joedolson, @joemcgill, @joen, @johnbillion, @juhise, @ketuchetan, @kraftbj, @leewillis77, @LiamMcArthur, @matveb, @melchoyce, @michalzuber, @michelleweber, @mihai2u, @MikeLittle, @mikeschroder, @mp518, @mrahmadawais, @netwe, @nitin, @kevadiya, @nobremarcos, @obenland, @ocean90, @odysseygate, @pento, @postpostmodern, @rellect, @rensw90, @rianrietveld, @riddhiehta02, @rmccue, @ryelle, @sagarjadhav, @sagarprajapati, @Samantha Miller., @sami.keijonen, @SergeyBiryukov, @sloisel, @sstoqnov, @stubgo, @swissspidy, @tejas5989, @timmydcrawford, @TimothyBlynJacobs, @topher1kenobe, @truongwp, @westonruter, and @zinigor for their contributions!

#week-in-core

JavaScript Chat Summary for May 23rd

Below is a summary of the discussion from yesterday’s JavaScript chat (agenda):

Introducing a JS module pattern to WordPress

@omarreiss helped lead the discussion and kick-started the conversation by opening a detailed and thoughtful ticket in trac (#40834) which introduces modules, their goals and how we could go about using them in core. The discussion was around considerations specific to WordPress and a need for modularity was mentioned – @westonruter called out this need for the Customizer,  see #30277. Ideas for code that could be extracted into modules included quickedit, core date utilities and wp.media.view.FocusManager.

The decision was made to move in the direction of using Webpack (and ES6 imports) as our bundler of choice, and to work first on switching out browserfy in our current build chain.

Choosing a future JavaScript framework

Discussion started on choosing a new framework for use in core. The main frameworks discussed so far were React and Vue. Attendees shared their hope, goals and criteria for choosing a new framework and mentioned: stability, longevity, mature, well-adopted, proven in a WordPress context, accommodating to accessibility requirements, interoperability with existing code, architected to support predictable data flows and composability, alignment with efforts like Calypso,  composable, extensible, testable and ease of developer adoption.

@kopepasah promoted Vue.js, saying he found it “much more approachable and highly extensible” and also “Vue single file component is amazingly organized and easy bundle and build.” See https://vuejs.org/v2/guide/single-file-components.html.

@rmccue pointed out that the React core development philosophies match up to ours quite well: https://facebook.github.io/react/contributing/design-principles.html

@afercia raised accessibility and wanted to know which framework was best suited to offer support, specifically in handling cases where direct DOM access and manipulation is needed.

@aduth shared the reasoning behind the choice of React for the Gutenberg project: https://github.com/WordPress/gutenberg/tree/master/element#why-react

As anticipated, the decision was not settled in the meeting and discussion will resume in next week’s meeting. Currently, React appears to be the favored candidate. Please add to the conversation in the comments below, and join us for further discussion at our next meeting, scheduled for May 30, 2017 at 13:00 UTC

For the full meeting notes, see the Slack logs.

#javascript, #summary

Dev Chat Agenda for May 24th (4.8 week 4)

This is the agenda for the weekly dev meeting on May 24, 2017 at 20:00 UTC:

If you have anything to propose to add to the agenda or specific items related to the above, please leave a comment below. See you there!

#4-8, #agenda, #dev-chat

Addition of TinyMCE to the Text Widget

In its first couple years, WordPress lacked rich/visual text editing. Before TinyMCE was incorporated in WordPress 2.0, users had to edit post content as raw HTML with some support from the Quicktags buttons. When widgets were introduced in WordPress 2.2, the Text widget was included which allowed a user to add content to their sidebar. Nevertheless, unlike the post editor, the Text widget did not incorporate TinyMCE, nor did it include Quicktags. For twelve years, since TinyMCE was added to core in 2005, users have had to hack around with HTML in their Text widgets to do things as simple as make text bold or add links. This has been featured even as recently as the 4.7 release video. Well, as of WordPress 4.8, the Text widget is finally getting the same treatment as the post editor with the introduction of TinyMCE for visual text editing, while still supporting raw HTML editing via a Text tab but now with the additional help of Quicktags:

Text widget: visual tab Text widget: text (HTML) tab

A primary reason for the long delay in incorporating TinyMCE into the Text widget was the difficulty of cleanly instantiating another copy of the WordPress visual editor dynamically after the page has loaded. Since WordPress 3.3 there has been the wp_editor() PHP function for instantiating an editor for the initial page load, but there was no facility for instantiating editors afterward, such as when adding a new Text widget to a sidebar. So in #35760 a new JS API was introduced for dynamically instantiating WP editors on the page: wp.editor.initialize(). This JS API is used for the new TinyMCE-powered Text widget; for more, please see Editor API changes in 4.8.

Note that by default the Text widget only features buttons for bold, italic, unordered list, ordered list, and link. If you want to add additional buttons to the toolbar, you may use a plugin to enqueue the following JS to add the blockquote button, for example:

jQuery( document ).on( 'tinymce-editor-setup', function( event, editor ) {
	if ( editor.settings.toolbar1 && -1 === editor.settings.toolbar1.indexOf( 'blockquote' ) ) {
		editor.settings.toolbar1 += ',blockquote';
	}
});

Likewise, a custom button can be added via code like:

jQuery( document ).on( 'tinymce-editor-setup', function( event, editor ) {
	editor.settings.toolbar1 += ',mybutton';
	editor.addButton( 'mybutton', {
		text: 'My button',
		icon: false,
		onclick: function () {
			editor.insertContent( 'Text from my button' );
		}
	});
});

A reason for why there is no “Add Media” button for the editor in the Text widget is that WordPress 4.8 also includes dedicated media widgets for adding images, video, and audio to sidebars. Another reason is a current technical limitation whereby arbitrary media embeds (oEmbeds) fail to work properly outside the context of post content (see #34115). For this reason if you try to embed a video or something else by pasting in a URL it will not currently expand into the embedded content. The same is true for shortcodes: they are not processed by default since many shortcodes presuppose a global $post as the context within which they expect to be running. Plugins may opt-in selectively to support individual shortcodes by filtering widget_text as they have had to do for many years now.

While not supporting shortcodes, the updated Text widget does have some of the same filters applying to it as the_content, in particular:

  • wpautop
  • wptexturize
  • capital_P_dangit
  • convert_smilies

The Text widget has supported a “filter” instance property which was reflected in the UI via a checkbox for whether or not to automatically add paragraphs and line break tags (wpautop). For the updated Text widget, this checkbox is removed entirely in favor of aligning its behavior with the post editor where this behavior is always enabled. These filters only apply on Text widgets that have been updated/touched after the 4.8 upgrade. When a Text widget is modified in 4.8, the filter instance prop gets set to a static string “content” and then it will apply a new widget_text_content filter which then apply the above functions to the widget text.

The incorporation of TinyMCE into the Text 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 TinyMCE is a JavaScript component. To avoid having to rebuild TinyMCE every time the user hits Save on the admin screen, the Text widget puts the title field and TinyMCE text field 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 media widgets in 4.8.) The fields in the Text widget’s UI sync with hidden inputs which get synchronized with the server; in the Customizer, changes to the TinyMCE field will be previewed after 1 second with denouncing. The container for the Text widget’s fields is .text-widget-fields and the traditional container for a widget’s input fields as rendered by WP_Widget::form() is .widget-content:

Themes should already account for the most common HTML elements within the text widgets and provide appropriate styles for them—the addition of the editor toolbar increases the likelihood its elements will be used in the future. Most default themes needed additional styles for ordered and unordered lists within widgets, so theme authors are encouraged to double-check their themes and test them with content in the text widget that includes markup provided by the editor toolbar.

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 in widgets can be found in #33507 and the media widgets incorporate some of its patterns that were also prototyped in the JS Widgets plugin. The synchronization of a widget’s state (instance properties) via hidden text fields can be eliminated once a widget’s state can be fully represented in a JavaScript model.

The Text widget is implemented as a Backbone.js view which is available at wp.textWidgets.TextWidgetControl. Instances of this view are then stored in the wp.textWidgets.widgetControls object. The widget’s control JS will only instantiate for a given widget once it is first expanded, when the widget-added event fires. What’s more is that the widget will only first initialize once the container is fully expanded since TinyMCE is not able to initialize properly inside of a container that is animating. In order to capture when TinyMCE inside the Text widget is initialized, you should use a TinyMCE event like tinymce-editor-setup. Note also that due the Document Object Model, when a widget is moved to a new location in a sidebar and this the TinyMCE iframe is moved in the DOM, this dynamically-created iframe is reloaded and thus emptied out. For this reason, every time a Text widget is moved to a new location the TinyMCE editor in the widget will be removed and then re-initialized. Keep this in mind when extending.

Keep also in mind that the Text widget 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.

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