Addition of TinyMCE to the Text Widget

Note: Update: A follow-up post has been published regarding Fixes to Text widget and introduction of Custom HTML widget in 4.8.1.

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 both the filter instance property and a new visual property will be set to true and then it will apply a new widget_text_content filter which then apply the above functions to the widget text. For Text widgets created prior to 4.8, they will be opened in a legacy mode with the old behavior when it is determined that TinyMCE could mutate the content undesirably; such legacy instances will be saved with visual=false instance property. Read more about Fixes to Text widget and introduction of Custom HTML widget in 4.8.1.

Important: When pasting HTML into the “Text” (HTML) tab of the Text widget, any extraneous line breaks should be removed or else unwanted paragraphs and line beaks may result. This is particularly important when you paste in script or style tags (as in the case of 3rd-party JavaScript embeds), since auto-inserted paragraphs will cause script errors; this will be fixed in #2833. This behavior aligns with longstanding behavior in the post editor, so it is not new, although it does differ from how the Text widget has previously behaved. As noted above, for previously-existing Text widgets that had the “auto-add paragraphs” checkbox unchecked (and thus the filter instance prop set to false), the previous behavior of not doing wpautop will be maintained: only once the widgets are modified will any extraneous line breaks need to be removed. Any such Text widgets created prior to 4.8 will be go into a legacy mode as of 4.8.1 to prevent any data loss. Going forward, arbitrary HTML should be placed into the new Custom HTML widget instead.

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

Multisite Focused Changes in 4.8

Here’s an overview of the developer facing changes made in multisite for the 4.8 cycle. If you’re interested in more detail, checkout the full list of tickets.

New capabilities

As part of the goal to remove all calls to is_super_admin() in favor of capability checks, two new meta capabilities have been introduced in this release:

  • upgrade_network is used to determine whether a user can access the Network Upgrade page in the network admin. Related to this, the capability is also checked to determine whether to show the notice that a network upgrade is required. The capability is not mapped, so it is only granted to network administrators. See #39205 for background discussion.
  • setup_network is used to determine whether a user can setup multisite, i.e. access the Network Setup page. Before setting up a multisite, the capability is mapped to the manage_options capability, so that it is granted to administrators. Once multisite is setup, it is mapped to manage_network_options, so that it is granted to network administrators. See #39206 for background discussion.

Both capabilities work in a backward-compatible fashion, so no changes should be required in plugins that deal with those areas. The capabilities however allow more fine-grained control about access to their specific areas. As an additional reminder: Usage of is_super_admin(), while not throwing a notice, is discouraged. If you need to check whether a network administrator has access to specific functionality in your plugin, use one of the existing network capabilities or a custom capability. See #37616 for the ongoing task.

New Hooks

  • deleted_blog fires after a site has been deleted. See #25584
  • signup_site_meta filters site meta in wpmu_signup_blog(). See #39223
  • signup_user_meta filters user meta in wpmu_signup_user(). See #39223
  • minimum_site_name_length filters the minimum number of characters that can be used for new site signups. See #39676

Network-specific site and user count control

With WordPress 4.8, several functions related to network site and user counts now support an additional $network_id parameter that allows to read and update those counts on a different network than the current one. While this mostly increases general flexibility, the new parameter can be leveraged to fix inconsistencies, for example prior to 4.8 the creation of a new site on another network would falsely trigger a recalculation of the current network instead of the network being actually modified. See #38699 for the bug ticket and resulting task.

The functions that now support a $network_id parameter are:

  • get_blog_count(). See #37865.
  • get_user_count(). See #37866.
  • wp_update_network_site_counts(). See #37528.
  • wp_update_network_user_counts(). See #40349.
  • wp_update_network_counts(). See #40386.
  • wp_maybe_update_network_site_counts(). See #40384.
  • wp_maybe_update_network_user_counts(). See #40385.
  • wp_is_large_network(). The filter wp_is_large_network now passes the network ID as fourth parameter as well. See #40489.

#4-8, #dev-notes, #multisite

Removal of core embedding support for WMV and WMA file formats

With the introduction of the video widget (#39994) and audio widget (#39995) it was discovered that the WMV and WMA file formats are no longer supported by MediaElement.js as of v3. While core is currently shipping with MediaElement.js v2.22, these file formats only play if the Silverlight plugin is installed, something which is less and less common since the plugin is no longer supported as of Chrome 45 and as of Firefox 52. So with the planned upgrade of MediaElement.js from 2.22 to 4.x (see #39686), it is a good time with the WP 4.8 major release to remove support for the formats. This has been done in [40813] for #40819.

Plugins may continue to add embedding support for these file formats by re-adding them via the wp_video_extensions and wp_audio_extensions filters, for example:

function add_wmv_to_wp_video_extensions( $extensions ) {
    $extensions[] = 'wmv';
    return $extensions;
}
add_filter( 'wp_video_extensions', 'add_wmv_to_wp_video_extensions' );

function add_wma_to_wp_audio_extensions( $extensions ) {
    $extensions[] = 'wma';
    return $extensions;
}
add_filter( 'wp_audio_extensions', 'add_wma_to_wp_audio_extensions' );

Plugins would also need to implement fallback rendering routines via the wp_video_shortcode_override and wp_audio_shortcode_override filters, or else use a different library than MediaElement.js altogether via the wp_video_shortcode_library and wp_audio_shortcode_library filters.

Note that there is no functional difference before and after the removal of WMA and WMV support. When MediaElement.js doesn’t support a format, it displays a download link. Before and after [40813], the following is ho  the audio and video shortcodes look like with WMA and WMV files respectively:

In the admin, the functional difference is that these formats are not listed as being available for selection in the Video and Audio widgets. Additionally, when you Add Media in the post editor, there is now no option to embed the player for these formats; only a link to the media will be provided, just as when attempting to add non-media files to content.

#4-8, #core-media, #dev-notes, #mediaelement

Cleaner headings in the admin screens

One of the most common needs for accessibility is providing tools to effectively navigate through content. Users of assistive technologies use headings as the predominant mechanism for finding page information. Headings provide document structure. Assistive technologies can list all the headings in a page to help users navigate and jump to different sections, like in a table of contents. For this reason, headings should contain just the heading text.

For a number of years, the main headings in the admin screens have been used to contain extraneous content, most notably the “Add new” button. WordPress 4.8 aims to fix this.

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.

What plugin or theme authors should know

If your plugin or theme follows the previous WordPress pattern of adding extraneous content to the main heading, please update your plugin or theme to make the heading cleaner. All you need to do is move the extraneous content outside of the heading. WordPress 4.8 ships with new CSS rules to take care of the new markup structure and in most cases, no additional changes will be required.

Of course, it’s impossible to cover all edge cases. If your plugin or theme uses additional content in the area next to the admin screens main heading, please double check now and be prepared to upgrade your markup and CSS to account for the cleaner headings. The relevant area is highlighted in the screenshot below and it applies to almost all the admin screens.

example of a main heading in the admin screens

Need more details?

If you need more details about the markup and CSS changes, please do have a look at the tracking ticket #26601 and the first changeset [38983], followed by several other ones all listed in the main ticket.

Get ahead of 4.8 and update now!

The power of the Web is in its universality. Help us to make the Web a place designed to work for all people. Any feedback and thoughts are more than welcome, please let us know in the comments below.

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

Customizer sidebar width is now variable

A common request for the Customizer has been to grant more room for the controls that appear in its sidebar. Ticket #32296 was created to allow the sidebar pane to be user-resizable with a grabber just like the Dev Tools pane in Chrome can be resized. After a lot of back and forth, the scope was reduced to remove the user-resizable aspect and to instead address a more fundamental issue that the sidebar is exceedingly and unnecessarily narrow on high-resolution displays. So while 4.8 doesn’t include a user-resizable controls pane, there is still a feature plugin for possible future merge. Important to that end, the changes that have been merged begin to introduce the fundamental prerequisite for a variable-width sidebar pane: responsive controls.

As can be seen in [40511] and [40567], no longer should Customizer controls assume that their container will always be 300px wide. Given the new responsive breakpoints for high-resolution screens, the pane can now be between 300px and 600px wide depending on the screen width. And actually this has already been the case on smaller screens (e.g. mobile) where the preview and pane aren’t shown at the same time; it now also applies to very large screens where there is ample space for both the preview and a wider pane.

Custom controls in plugins and themes should utilize alternative approaches to doing layout than using pixel widths. Use of percentage-based widths or flexbox will help ensure that controls will appear properly in larger displays, while also making controls future-compatible when the sidebar width could be user-resizable.

#4-8, #customize, #dev-notes

Recent updates to the unit testing infrastructure

Several changes have made their way into WordPress’ unit test suite and its infrastructure recently. If you maintain a WordPress project (such as a plugin or website) that has its own test coverage, you may be interested in porting some of these changes to your test suite too. Here’s a round-up:

  • Tests which require Multisite to be enabled, or tests which should be excluded from running when Multisite is enabled, can now be placed into the new ms-required and ms-excluded groups to skip them automatically when the test requires Multisite to be in use, or when it requires Multisite to not be in use, respectively. In addition, the default configuration in phpunit.xml now excludes such test groups as appropriate without them being marked as skipped, which removes unwanted noise from PHPUnit’s reporting when run in verbose mode. See #40531.

Note: Please note that this usage example has been updated from a previous version of this post.

Example usage:

/**
 * @group ms-required
 */
function test_something_on_multisite() {
	// Run your Multisite-only assertions here
}

/**
 * @group ms-excluded
 */
function test_something_without_multisite() {
	// Run your single-site-only assertions here
}
  • XDebug is now disabled when running tests on Travis in order to speed up the builds. This resulted in a huge reduction in build times, up to 40% in some cases. See #39978.
  • The PHPUnit version used when running tests on Travis is now explicitly coupled to the PHP version in order to avoid incompatibilities such as the one caused when PHPUnit 6 was rolled out. See [40269] for the main change and #40100 and #40086 for more info.
  • A compatibility shim for PHPUnit 6+ has been added, which means the test suite will no longer cause fatal errors if you want to update to PHPUnit 6+ locally or, for example, you want to require it through a Composer dependency. See #39822.
  • Several tests which were previously skipped when the environment wasn’t suitable will now cause failures, for example tests which depend on constants such as DISALLOW_FILE_MODS not being set. This is to avoid hiding tests that never run and therefore never fail if the assertions contained within them would otherwise fail. If the core test suite begins failing on your local environment as a result, you should address the cause. See #40533.
  • The number of PHP versions which older branches are tested against on Travis has been significantly reduced in order to speed up build times for patch releases. This is most beneficial when security fixes are released and backported. As a general rule, branch builds except the latest branch are now only tested on the oldest supported version (5.2), the latest in the 5.x branch, and the latest in the 7.x branch. See #40407.

#dev-notes

WordPress 4.7 Field Guide

WordPress 4.7 is shaping up to be the best WordPress yet!  Users will receive new and refined features that make it easier to “Make your site, YOUR site”, and developers will be able to take advantage of 173 enhancements and feature requests added.  Let’s look at the many improvements coming in 4.7…

RESTing, RESTing: 1, 2, 3

The foundation for RESTful APIs has been in core since 4.4, and 4.7 sees the addition of Content Endpoints after a healthy discussion. We’ve defined four success metrics as part of the merge discussion and you can help by building themes and plugins on top of the API, using the API in custom development projects, and utilizing the API for a feature project, core features, or patches. So, dive in, start playing around, and let us know what you build!

https://make.wordpress.org/core/2016/10/08/rest-api-merge-proposal-part-2-content-api/

 

It don’t mean a thing, if you ain’t got a theme

No matter if you are building themes for public consumption, as a bespoke project for a major public company, or anything in between WordPress 4.7 has something to help you.

https://make.wordpress.org/core/2016/11/29/theming-with-twenty-seventeen/

https://make.wordpress.org/core/2016/11/26/video-headers-in-4-7/

https://make.wordpress.org/core/?p=20650

https://make.wordpress.org/core/2016/11/10/visible-edit-shortcuts-in-the-customizer-preview/

https://make.wordpress.org/core/2016/11/07/whitespace-changes-in-navigation-for-4-7/

https://make.wordpress.org/core/2016/11/03/post-type-templates-in-4-7/

https://make.wordpress.org/core/2016/11/03/new-post-type-labels-in-4-7/

https://make.wordpress.org/core/2016/09/09/new-functions-hooks-and-behaviour-for-theme-developers-in-wordpress-4-7/

The Voyages of USS Media

Two notable changes, enhanced PDF support in the media library and changes to the default fallbacks for image alt attributes, are explained in separate posts.

https://make.wordpress.org/core/2016/11/15/enhanced-pdf-support-4-7/

https://make.wordpress.org/core/2016/11/11/improving-accessibility-of-image-alternative-text-in-4-7/

Media also received other exciting enhancements and bug fixes you should check out.

Around the World

The way users understand the words on WordPress are important and now users will be able to select their personal preferred language.

https://make.wordpress.org/core/2016/11/07/user-admin-languages-and-locale-switching-in-4-7/

 

For Whom Customization Tolls

The customize component will now support the ability to create pages within live preview during site setup; will have a faster, smoother, and more accessible navigation; will automatically persist your changes in the background while you browse your site and switch themes; and will let you fine-tune your site with custom CSS.

https://make.wordpress.org/core/?p=20534

https://make.wordpress.org/core/2016/10/12/customize-changesets-technical-design-decisions/

https://make.wordpress.org/core/2016/09/28/changes-to-customizer-sliding-panelssections-in-wordpress-4-7/

https://make.wordpress.org/core/2016/11/26/extending-the-custom-css-editor/

 

Reading, Writing and Teriffic

Whether you’re creating content in the WordPress Admin or concerned about comment moderation, we’ve got updates that will be sure to please you.

https://make.wordpress.org/core/2016/10/28/editor-changes-in-4-7/

https://make.wordpress.org/core/2016/10/11/comment-allowed-checks-in-wordpress-4-7/

 

The Foundation of WordPress

For those who like to get “under the hood” of WordPress, we’ve got some improvements that will hopefully make your life easier.

https://make.wordpress.org/core/2016/11/07/changed-loading-order-for-current-user-in-4-7/

https://make.wordpress.org/core/2016/11/04/multisite-focused-changes-in-4-7/

https://make.wordpress.org/core/2016/11/03/attributes-for-resource-hints-in-4-7/

https://make.wordpress.org/core/2016/11/02/wp_list_sort-and-wp_list_util-in-4-7/

https://make.wordpress.org/core/2016/10/29/wp_taxonomy-in-4-7/

https://make.wordpress.org/core/2016/10/28/fine-grained-capabilities-for-taxonomy-terms-in-4-7/

https://make.wordpress.org/core/2016/09/08/wp_hook-next-generation-actions-and-filters/

https://make.wordpress.org/core/2016/10/26/registering-your-settings-in-wordpress-4-7/

 

But Wait, There is More!

Over 447 bugs, 165 enhancements, 8 feature requests, and 15 blessed tasks have been marked as fixed in WordPress 4.7. Some additional ones to highlight include:

  • Make media library searchable by file name (#22744)
  • Improved Custom Background Properties UI (#22058)
  • Hue-only Color Picker (#38263)
  • Fix Sections that .cannot-expand (#37980)
  • Allow Plugins to do Comprehensive Late Validation of Settings (#37638)

Please, test your code. Fixing issues now, before 4.7 is released, helps you and helps millions of WordPress sites.

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

Customizer Improvements in 4.7

WordPress 4.7 has been the most active release on record for the customize component, with four major feature projects merging and shipping with 4.7 and over 90 tickets closed as fixed. This post summarizes the highlights of the user and developer-facing changes.

4.7 Customizer Feature Projects

Create pages within live preview during site setup

Add new pages while building menus and setting a static front page; outline your site directly in the customizer.

This project began with the ability to create posts and pages direction from the available menu items panel in the customizer, as originally proposed near the end of the 4.6 cycle:

https://make.wordpress.org/core/2016/06/16/feature-proposal-content-authorship-in-menus-with-live-preview/

Subsequent changes also added the ability to create new pages when assigning the front page and posts page in the Static Front Page section. Because this is now built into the core dropdown-pages customizer control, themes and plugins can also allow users to create new pages for their options instead of relying on existing content. The homepage sections in Twenty Seventeen include this new allow_addition parameter. Here’s how to register a dropdown-pages control supporting new pages:

$wp_customize->add_control( 'featured_page', array(
	'label'          => __( 'Featured Page', 'mytextdomain' ),
	'section'        => 'theme_options',
	'type'           => 'dropdown-pages',
	'allow_addition' => true, // This allows users to add new pages from this dropdown-pages control.
) );

Additionally, a proposal for term statuses was developed as a first step toward expanding the menus functionality to work for creating and previewing taxonomy terms in a future release (see #37915).

Improvements to the Sliding Panels UI

Customizer navigation is now faster, smoother, and more accessible.

This project tackled a series of tickets focused on improving the usability of the “sliding panels” UI in the customizer controls pane. The first step was to refactor the section and panel markup so that sections and panels are not logically nested. This is the biggest internal change to the UI and has a dedicated post going into the details:

https://make.wordpress.org/core/2016/09/28/changes-to-customizer-sliding-panelssections-in-wordpress-4-7/

This primary change resolved numerous problems with sections and panels not opening and closing properly, and eliminated situations where navigation to leave a section could become hidden. The next step was making section and panel headers “sticky” so that navigation is easier to access within long sections (such as for a menu); see #34343.

Finally, hover and focus styling for navigation in the customizer has been updated to use the blue-border approach found elsewhere in core, including for the device-preview buttons in the customizer, in #29158. This completes a refresh of the customizer controls pane’s UI design that began in WordPress 4.3 with #31336. The core UI now uses the following consistent UI patterns in the customizer:

  • White background colors are used only to indicate navigation and actionable items (such as inputs)
  • The general #eee background color provides visual contrast against the white elements
  • 1px #ddd borders separate navigational elements from background margins and from each other
  • 15px of spacing is provided between elements where visual separation is desired
  • 4px borders are used on one side of a navigation element to show hover or focus, with a color of #0073aa
  • Customizer text uses color: #555d66, with #0073aa for hover and focus states on navigation elements

Plugins and themes should follow these conventions in any custom customizer UI that they introduce, and inherit core styles wherever possible.

Any custom sections and panels, as well as customizations to the core objects in plugins and themes, should be tested extensively to ensure that they continue functioning as intended with all of these changes in 4.7. It’s particularly important to ensure that things like the use of color match the core conventions so that the user experience is seamless between functionality added by plugins and core.

Customize Changesets (formerly Transactions)

Browse your site and switch themes more seamlessly within the customizer, as your changes automatically persist in the background.

This project rewrote the internals of the customizer preview mechanism to make changes persistent. Each change made to a setting in the customizer is saved to a changeset (a new customize_changeset post type), facilitating future features such as scheduled changes, revisions, or saving and sharing drafted changes. Changesets also open the door to using the customizer to preview Ajax requests, headless sites, and REST API calls for mobile apps. In 4.7, changesets enable switching themes in the customizer without needing to decide between publishing or losing your customizations, as they’re automatically persisted in the background.

For more details on changesets, check out the two dedicated posts:

https://make.wordpress.org/core/2016/10/12/customize-changesets-formerly-transactions-merge-proposal/

https://make.wordpress.org/core/2016/10/12/customize-changesets-technical-design-decisions/

Custom CSS

Fine-tune your site and take your theme customizations to the next level with custom css in the customizer.

#35395 introduced a user-oriented custom CSS option in the customizer. Now that the base functionality is in place, it will be further enhanced in #38707 in future releases. Read the feature proposal for details on the implementation and why it’s important for core:

https://make.wordpress.org/core/2016/10/11/feature-proposal-better-theme-customizations-via-custom-css-with-live-previews/

There’s also a dedicated post that walks through the process of migrating existing custom CSS options in themes and plugins to the core functionality – be sure to follow those steps if your plugin or theme does custom CSS:

https://make.wordpress.org/core/2016/11/26/extending-the-custom-css-editor/

Other Changes with Dedicated Posts

4.7 features several other features deserving special attention. Read the posts for visible edit shortcuts (which expand the functionality of customizer partials), video headers (which extend the custom header feature), and starter content for more information:

https://make.wordpress.org/core/2016/11/10/visible-edit-shortcuts-in-the-customizer-preview/

https://make.wordpress.org/core/2016/11/26/video-headers-in-4-7/

https://make.wordpress.org/core/2016/11/30/starter-content-for-themes-in-4-7/

Additional User-facing Changes

With over 90 tickets fixed in the customize component in 4.7, we can’t cover everything here. But, here are a few more highlights:

Improved Custom Background Properties UI

#22058 introduces a more comprehensive and more usable custom background properties UI when a custom background is set up. There are now presets to control all of the detailed options at once, and the individual options are presented in a more visual way. Background size and vertical position are also now available as standalone options when using a custom preset.

Theme developers should update their add_theme_support() calls for custom-background to specify the default size, vertical position, and preset to reflect their default background image CSS. Perhaps the most significant improvement here is the ability for users to easily set up fixed full-screen backgrounds – and the ability for themes to make that behavior default if desired.

And even more…

4.7 also:

  • Loads the frontend preview iframe more naturally, eliminating a lot of weirdness with JS running in an unexpected location and ensuring that JS-based routing will work (#30028)
  • Allows the search results page to be previewed, and any forms that use the GET method in general can now be submitted whereas previously they would do nothing when submitted (#20714)
  • Hides edit post links in the customizer by default. Plugins, such as Customize Posts, can restore the links if they make post editing available in the customizer (#38648), although the visible edit shortcuts should generally be used instead.
  • Shows a cursor: not-allowed for mouse users when hovering over external links in the preview, as these can’t be previewed
  • Officially removes support for the customizer in Internet Explorer 8, preventing users of this outdated browser from accessing the customizer at all (#38021)

Additional Developer-oriented Changes

Hue-only Color Picker

#38263 adds a hue-only mode to the Iris color picker, wpColorPicker, and WP_Customize_Color_Control. Built for Twenty Seventeen’s custom colors functionality, the hue-only mode allows users to select a hue and saves the hue degree as a number between 0 and 359. To add a hue-color control:

$wp_customize->add_control( new WP_Customize_Color_Control( $wp_customize, 'colorscheme_hue', array(
	'mode' => 'hue',
	'section' => 'colors',
) ) );

As demonstrated in Twenty Seventeen’s custom colors strategy, the hue-selection strategy opens up a whole new world of possibilities for custom color options in themes. Rather than introducing numerous text and background color options and requiring users to adjust them to ensure that adequate color contrast is provided, themes can consolidate their color options into one or more hue pickers. Then, the corresponding use of hsl colors in CSS allows themes to define color patterns where users customize color hues without impacting the lightness of a color option, thereby preserving the designer’s use of proper contrast between text and background colors, and any use of color lightness for visual hierarchy. Check out the implementation in Twenty Seventeen for inspiration (including instant live preview).

Fix Sections that .cannot-expand

When creating custom customizer sections that, for example, display an external link but don’t actually expand to show section contents, the cannot-expand class can be added to the section title container to prevent JS events and CSS hover/focus styles from being applied. Be sure to also remove the tabindex="0" from the container if you copy the core code since your custom section shouldn’t be focusable if it can’t expand (and any contained links or buttons would be keyboard-focusable automatically). See #37980 for details.

Allow Plugins to do Comprehensive Late Validation of Settings

To account for custom subclasses of WP_Customize_Setting that don’t apply the customize_validate_{{$setting_id}} filter, this filter now will be applied when WP_Customize_Manager::validate_setting_values() is called. This ensures that plugins can add custom validation for every setting. For more, see #37638.

Credits

Huge thanks to the 61 people (and counting) receiving props for the 120+ customize component commits in 4.7 (as of RC2): @westonruter, @celloexpressions, @afercia, @sirbrillig, @ryankienstra, @helen, @ocean90, @melchoyce, @bradyvercher, @folletto, @johnbillion, @delawski, @karmatosed, @georgestephanis, @dlh, @curdin, @valendesigns, @mattwiebe, @michaelarestad, @joemcgill, @sstoqnov, @lgedeon, @mihai2u, @coreymcollins, @stubgo, @utkarshpatel, @desrosj, @odysseygate, @johnregan3, @aaroncampbell, @mapk, @iseulde, @mrahmadawais, @vishalkakadiya, @sayedwp, @hugobaeta, @jonathanbardo, @jorbin, @tristangemus, @deltafactory, @kkoppenhaver, @seancjones, @Presskopp, @Mista-Flo, @nikeo, @adamsilverstein, @lukecavanagh, @coffee2code, @peterwilsoncc, @presskopp, @pento, @Kelderic, @sebastian.pisula, @mckernanin, @FolioVision, @MikeHansenMe, @welcher, @cdog, @grapplerulrich, @iamfriendly, @flixos90.

 

#4-7, #customize, #dev-notes

Starter content for themes in 4.7

One of the hardest things for people setting up sites with WordPress for the first time is understanding what themes are and how a given theme can work for you, especially when there’s no content there to visualize. There are also significant gaps between local theme previews, screenshots, and .org previews. Even when there are easy-to-use site customization tools, it is difficult to figure out where to start and what things are going to be like.

To help users along that path, 4.7 introduces the concept of “starter content” – theme-specific selections of content to help showcase a theme to users and serve as a starting point for further setup of new sites. Starter content works especially well in tandem with visible edit shortcuts, allowing users to not only see what content might work best where within a theme, but from there to be able to jump to building off of that base without having to initially spend time figuring out, say, which widgets areas map where.

How it works

Starter content is applied and displayed upon entering the customizer, with no changes appearing on the live site until customizer changes are explicitly saved and published. In 4.7, this initial view of a theme with starter content will only happen for “fresh sites” – new installs that have not yet had any posts, pages, widgets, or customizer settings updated. This state is indicated in the fresh_site option with a value of 1. The current limitation is in line with prioritizing initial site setup for this release, and allows for themes to begin implementing content and ensuring that there is a solid base before introducing more complicated logic and UI to “merge” starter content with existing content in a future release (#38624). That being said, if two themes in a given fresh site both have starter content, if the starter content from the first theme is applied and you make some changes to that starter content, when you switch to the second theme the starter content from that theme will override the starter content from the first theme only for the settings which have not been modified. Also remember that theme mods are always theme-specific, so starter content for theme switches will never be copied.

Core provides a set of content that themes can select from (technical details below). These include a variety of widgets, pages, and nav menu items (including references for the pages), along with the ability to provide attachments, theme mods, and options. Any included images for attachments need to be from within a theme or plugin folder and cannot be loaded from an external URL. Twenty Seventeen will ship with starter content enabled; there are no plans to add the functionality to past default themes.

How to use it

Themes define a subset of core-provided starter content using add_theme_support() – let’s look at a breakdown of how Twenty Seventeen does things. In its setup function hooked to after_setup_theme, we see an array with collections of widgets, posts (pages), attachments, options, theme mods, and nav menus registered as the starter content. The customizer looks for this starter-content at after_setup_theme priority 100, so do make this call at that point or later:

add_theme_support( 'starter-content', array( /*...*/ ) )

Widgets

Each widget area ID corresponds to one sidebar registered by the theme, with the contents of each widget area array being a list of widget “symbols” that reference core-registered widget configurations. Most default widgets are available (archives, calendar, categories, meta, recent-comments, recent-posts, and search), as well as text widgets with business hours (text_business_info) and a short prompt for an “about this site” style blurb (text_about). Themes should place widgets based on what works best in that area – for instance, business info in a footer widget of a business-centric theme, or a nicely styled calendar widget in the sidebar of a blog.

Custom widgets can also be registered at the time of starter content registration or later filtered in, which will be more likely the case for plugins, as add_theme_support() for starter content will be overridden by any later calls.

// Custom registration example
add_theme_support( 'starter-content', array(
	'widgets' => array(
		'sidebar-1' => array(
			'meta_custom' => array( 'meta', array(
				'title' => 'Pre-hydrated meta widget.',
			) ),
		),
	),
);

// Plugin widget added using filters
function myprefix_starter_content_add_widget( $content, $config ) {
	if ( isset( $content['widgets']['sidebar-1'] ) ) {
		$content['widgets']['sidebar-1']['a_custom_widget'] = array(
			'my_custom_widget', array(
				'title' => 'A Special Plugin Widget',
			),
		);
	}
	return $content;
}
add_filter( 'get_theme_starter_content', 'myprefix_starter_content_add_widget', 10, 2 );

Posts (Pages)

Like widgets, core provides posts which can be referenced by symbols; all six currently in the core set are pages, but the starter content API can support various post types (including attachments, which are defined and handled separately). The symbols for the core-provided pages as of 4.7 are home, about, contact, blog, news, and homepage-section. The pages references by blog and news are both empty in the content area and are meant to be assigned as the page for posts (detailed with options below). Imported posts can further be used as post IDs when referenced using the symbol of the item within double curly braces, e.g. {{home}} for the static front page option.

Posts, like widgets, are also easily customizable, either by overriding specific fields for a predefined item or by defining a new custom one entirely. The available fields are post_type, post_title, post_excerpt, post_name (slug), post_content, menu_order, comment_status, thumbnail (featured image ID), and template (page template name, as would be stored in post meta).

// Overriding/supplementing a predefined item plus a custom definition
add_theme_support( 'starter-content', array(
	'posts' => array(
		'about' => array(
			// Use a page template with the predefined about page
			'template' => 'sample-page-template.php',
		),
		'custom' => array(
			'post_type' => 'post',
			'post_title' => 'Custom Post',
			'thumbnail' => '{{featured-image-logo}}',
		),
	),
);

Attachments

While attachments are post objects, they have special handling due to the sideloading of specified media. Media must be loaded from within the theme or plugin directory – external URLs are currently disallowed for performance reasons. The location of the media, either as a full file path or relative to the theme root, is indicated in the file array item, and some other post fields are available, with post_content mapping to description and post_excerpt to caption. Imported attachments can further be used by using their respective array keys as symbols used within double curly braces, e.g. {{featured-image-logo}} as the featured image (thumbnail) for a post. In the example below, an attachment is specified and used as the featured image for the about page.

add_theme_support( 'starter-content', array(
	'attachments' => array(
		'featured-image-logo' => array(
			'post_title' => 'Featured Logo',
			'post_content' => 'Attachment Description',
			'post_excerpt' => 'Attachment Caption',
			'file' => 'assets/images/featured-logo.jpg',
		),
	),
	'posts' => array(
		'about' => array(
			// Use the above featured image with the predefined about page
			'thumbnail' => '{{featured-image-logo}}',
		),
	),
);

Nav Menus

Nav menus are also specially treated post objects. There are essentially two types of nav menu items – custom links, which require a title and url, and object references, which require type, object, and object_id, which can be a {{post}} symbolic reference.

Options and Theme Mods

Options and theme mods are more freeform and merely require a match for a name. Symbolic references to imported items are particularly useful here, such as for the page_on_front option and Twenty Seventeen’s multi-section homepage as stored in theme mods. Themes hosted on .org will likely be limited to theme mods and a subset of options; all other developers are encouraged to consider user experience and expectations first.

What does this mean for themes?

Core-provided content helps support a consistent preview experience across themes with high quality localized content, helping users understand how WordPress and that theme fit their needs. Theme authors are encouraged to select from core-provided content, but as is always the case with WordPress, starter content still has some flexibility, and will continue to mature as a feature over time.

While theme review guidelines need to be finalized and documented, it is anticipated that themes being submitted to WordPress.org will be expected to select from core-provided content to promote consistency and to help keep the theme review process from becoming lengthier, with exceptions being made on a case by case basis. Themes being distributed outside of WordPress.org are not subject to the same review process; however, it is recommended that consistent user experiences be the primary consideration in how starter content is chosen and implemented.

What’s next?

Testing this feature with your theme or plugin does not require a fresh install every time – you can set the fresh_site option to 1 using the tool of your choice, such as wp-cli or phpMyAdmin. Do note that content merging logic has not been tackled so you may not quite get the exact same effect as a truly fresh install; however, since all of the changes are held in a customizer changeset and are not otherwise live on the site, there is no data loss, unless you save and publish the starter content overrides of course.

In the future, all sites should be able to live preview new themes in ways that really showcase that theme’s capabilities, whether that’s with no content made yet or with a lot of existing content to work into the preview. This will take a lot of consideration around user expectations for content merging, and should be tackled as its own feature. There are also potentially interesting extensions such as UI for users to select from sets of content or selectively accept/reject staged changes.

And finally, to best align preview experiences in various places, theme previews on .org should also leverage starter content. Helping hands are needed here – please ping me (@helen) in Slack should you be interested!

#4-7, #dev-notes

Theming with Twenty Seventeen

In 4.7, WordPress gets a new default theme: Twenty Seventeen. Like all default themes, it’s easily customizable for users and developers. This post will cover developer features and a few tricks when customizing the theme.

Of note

Override enqueued styles and scripts

With the use of get_theme_file_uri, introduced in 4.7, Twenty Seventeen lets child themes override styles and scripts with ease. For example, if you want to replace the theme’s global.js file, you can do so by including the same file in your child theme in the same path.

Filters

Twenty Seventeen includes a handful of filters, all of which are documented in line in the code.

Content width

The value is filterable in the event a child theme needs to change it.

function childtheme_content_width( $content_width ) {
    if ( twentyseventeen_is_frontpage() ) {
        $content_width = 960;
    }
    return $content_width;
}
add_filter( 'twentyseventeen_content_width', 'childtheme_content_width' );

Custom header settings

Like past default themes, Twenty Seventeen filters the arguments for add_theme_support( 'custom-header' );. These can be changed in a child theme. Here, we’ll add flex-width to the current args.

function childtheme_custom_header_args( $args ) {
    $args['flex-width'] = true;
    return $args;
}
add_filter( 'twentyseventeen_custom_header_args', 'childtheme_custom_header_args' );

Header video settings

The theme changes the default provided by Core, but that can be modified by a child theme. Here, we change the text on the button in a child theme:

function childtheme_setup() {
    remove_filter( 'header_video_settings', 'twentyseventeen_video_controls' );
}
add_action( 'after_setup_theme', 'childtheme_setup' );

function childtheme_video_controls( $settings ) {
	$settings['l10n']['play'] = '__( 'Play my awesome video', 'childtheme' );
	$settings['l10n']['pause'] = '__( 'Pause my awesome video', 'childtheme' );
	return $settings;
}
add_filter( 'header_video_settings', 'childtheme_video_controls' );

Front page sections

Twenty Seventeen uses the Customizer to add sections to the front page. These are filterable with the twentyseventeen_front_page_sections filer. They can changed like so:

function childtheme_front_page_sections() {
	return 6;
}
add_filter( 'twentyseventeen_front_page_sections', 'childtheme_front_page_sections' );

With 6 being a new number there. In this way, the number of sections can be adjusted in a child theme.

SVGs

One of the theme’s most notable behind-the-scenes features, the use of SVGs means better accessibility for icons, they look great on any device and they’re easier to customize.

First, the list of social link icons is filterable, so child themes can change it.

function childtheme_social_links_icons( $social_links_icons ) {
    $social_links_icons['mysocialsite.com'] = 'mysocialsite';
    return $social_links_icons;
}
add_filter( 'twentyseventeen_social_links_icons', 'childtheme_social_links_icons' );

All of Twenty Seventeen’s icons are decorative in nature. But if a child theme wanted to include an icon that needed to be described in an accessible way, it can thanks to built-in options.

These examples are documented in the code itself. However, for example:

Using a title:

<?php echo twentyseventeen_get_svg( array( 'icon' => 'arrow-right', 'title' => __( 'This is title', 'childtheme' ) ) ); ?>

Another example with title and desc (description):

<?php echo twentyseventeen_get_svg( array( 'icon' => 'arrow-right', 'title' => __( 'This is title', 'childtheme' ), 'desc' => __( 'This is longer desc', 'textdomain' ) ) ); ?>

For more information on SVG accessibility, see Using ARIA to enhance SVG accessibility.

Custom Colors

Like other default themes, this one comes with some color options so you can make the theme your own. Twenty Seventeen uses saturation to create a custom color scheme that will look great. That saturation level can be adjusted, like so:

function childtheme_custom_colors_saturation() {
	return 25;
}
add_filter( 'twentyseventeen_custom_colors_saturation', 'childtheme_custom_colors_saturation' );

So the lower the number there, the more muted a color appears, and the higher it is, the more intense a color becomes.

You can also add new CSS to the existing CSS output for custom colors.

By adding a filter, child themes can add additional selectors onto the custom color scheme CSS. Like so:

// Add child theme selectors for color schemes.
function dynamic_seventeen_custom_colors_css( $css, $hue, $saturation ) {
	$css .= '
	.colors-custom .content-menu > article:not(.has-post-thumbnail),
	.colors-custom .content-menu > section:not(.has-post-thumbnail) {
		border-top-color: hsl( ' . $hue . ', ' . $saturation . ', 87% ); /* base: #ddd; */
	}';
	return $css;
}
add_filter( 'twentyseventeen_custom_colors_css', 'dynamic_seventeen_custom_colors_css', 10, 3 );

Enjoy customizing Twenty Seventeen and happy theming!

#4-7, #bundled-theme, #dev-notes, #twenty-seventeen