WordPress 4.3 Field Notes

WordPress 4.3 includes improvements to existing features and brand new features for developers. Over the past few weeks, the core team has been posting here on make/core with a number of the developer changes in WordPress 4.3.

WordPress 4.3 ships in just a week and a half. Prepare your themes, plugins, and apps for the changes above and comment on those posts with any questions, comments, or feedback.

#4-3, #dev-notes

List table changes in 4.3

List tables are a significant component of the WordPress admin, powering screens such as for posts, comments, and installed plugins. Its internals have not changed much since the introduction of WP_List_Table in 3.1, and visually has only significantly changed with the introduction of smaller screen responsive considerations in 3.8. In 4.3, we’ve improved list tables on both fronts, including API enhancements to support the front-end changes.

Better small screen responsive mode

In 3.8, list tables were made “responsive” by hiding columns as the viewport got narrower. While content truncation is a common responsive design approach, it is not a good one. Users who have a higher likelihood of being bandwidth limited, such as on phones, now have to load a second screen to see data that is potentially important for making what should be an initial decision as to what to do next. We also already have the data in markup going to waste, as well as an impossible-to-maintain set of CSS selectors hiding columns by name and then unhiding them in specific list tables. This strategy required developers to include custom CSS if using columns with the same names as core ones or if a custom column was more important than what core was showing by default.

Now, we show all the data under a toggle, showing only the bulk selection checkbox (when available) and a designated primary column by default. Screen option settings are honored, though setting them is not actually available on smaller screens right now. Check out the demo below, and read on for more about API changes.

4.3 List Tables Demo

4.3 List Tables Demo

Primary column and row actions

We’ve done a lot of work to provide a fallback primary column for custom list tables, as without one defined, list tables will suddenly look empty. Developers are able to specify a primary column via the list_table_primary_column filter, which receives the screen ID as context. This primary column is also where row actions are placed.

For example, if you’ve added a column for a slide image to a slide custom post type and would like for it to be the primary, it is now a matter of a simple filter. Previously, you would have needed to recreate the row actions in PHP and add custom CSS to ensure it did not disappear on smaller screens. As of 4.3, your code might look like:

function wpdocs_slide_list_table_primary_column( $column, $screen ) {
	if ( 'edit-slide' === $screen ) {
		$column = 'slide';
	}

	return $column;
}
add_filter( 'list_table_primary_column', 'wpdocs_slide_list_table_primary_column', 10, 2 );

Note that primary columns should typically be the first column after the checkbox. From a user perspective, it is best to keep the placement of the most important identifier of an item and its actions consistent. Specifying other primary columns will work, but may result in some visual breakage in the small responsive view when a row is toggled open. We are tracking how that may be handled on #33308.

Easier subclassing of WP_List_Table and other list tables

While WP_List_Table was designed for internal usage and didn’t make many considerations for custom subclasses, we recognize that developers use them and that clean up would benefit both implementations and future maintenance. The internal WP_List_Table classes now all call ->single_row_columns() in ->single_row() properly, which makes subclassing them significantly easier. Previously, ->single_row() in each WP_List_Table subclass contained a giant switch statement. In most cases, this was unnecessary. By calling ->single_row_columns() when rendering a row, the class will look for a method on the class inheritance chain called ->column_{$name}. This allows us to break up the columns into discrete methods, and removes the need to override ->single_row_columns(). Thusly, if you subclass a List Table like WP_Posts_List_Table, you can override a specific column just by overriding the column method, i.e: ->column_title().

Before: https://github.com/WordPress/WordPress/blob/4.2-branch/wp-admin/includes/class-wp-posts-list-table.php#L635
After: https://github.com/WordPress/WordPress/blob/master/wp-admin/includes/class-wp-posts-list-table.php#L997

#4-3, #dev-notes, #list-tables

Editor Enhancements in 4.3

Text Patterns

We added a small set of text patterns, or text shortcuts if you will. These will hopefully keep you focussed better on your writing and save you some time. 🙂

Typing *  or -  will automatically give you a proper HTML list right away. Same for 1.  or  1) , but then ordered. Not your intention? Pressing backspace will undo this change. You can also use the undo button, ctrl/cmd+z or esc.

Starting your paragraph with two to six number signs # will convert that paragraph to a heading. Similarly the greater-than symbol > will convert the paragraph to a blockquote.

We’re planning to add some more next release, and a way for plugins to extend this.

Here’s a demo video @boren made.

Inline Link Toolbar

This toolbar will show up when you put your cursor in a link. You’ll now be able to see a short version of the URL without having to open the link modal all the time. Clicking it will open the page that it links to in a new browser tab. If you wanted to do this before, you had to open the link modal and copy paste the URL in a new browser tab yourself.

It also comes with an edit and remove button. We hope to move the editing experience inline next release as well.

Inline link toolbar

#4-3, #dev-notes, #editor

Headings in Admin screens change in WordPress 4.3

Are you a theme, plugin or framework developer for WordPress? Take note: the heading structure in the Admin screens will change in WordPress 4.3.

From H2 to H1

Currently, in WordPress 4.2 and before, the main heading in admin screens is an <h2>. However, if you want to have a correct, semantic heading structure, a page should an <h1>, but only one, which describes what the page is about.

People using assistive technology use the <h1> to identify a page and quickly know where they are. Further, proper HTML5 dictates that an <h1> should be the initial heading.

Therefore, in WordPress 4.3 the headings of all admin screens have been changed from <h2> to <h1> (see #31650).

Related CSS changes

If your theme or plugin still uses <h2> for admin screens, don’t worry; styles for <h2> are still supported in the admin CSS so that, visually, nothing changes during the update to 4.3. However, a new class was introduced to properly style <h1>s, page-title-action. Here’s an example of the new class in use:

<h1>Posts <a href="[..]/wp-admin/post-new.php" class="page-title-action">Add New</a></h1>

The old class .wrap .add-new-h2 is still supported but has been labeled deprecated. It has been replaced by: .wrap .page-title-action.

More changes ahead

After the release of WordPress 4.3, the accessibility team will continue making changes to heading so that they are semantically correct. Current <h3>s will become <h2>s, <h4>s will become <h3>s, and so on.

Check your code

Does your plugin, theme, or framework have admin screens? Check the heading structure. Change the main heading from an <h2> into an <h1>. If you’re feeling generous, check the rest of your heading structure to ensure it’s semantic.

Making these semantic changes will ensure your plugin or theme is in sync with WordPress and that people using a screen reader can understand your admin screens better.

If you have any questions, ask them in the comment section below, or contact the WordPress accessibility team in the #accessibility channel in WordPress Slack.

#4-3, #dev-notes

get_transient() is now more strict in 4.3

WordPress 4.3 includes a change to get_transient(). As reported in #23881 and #30380, get_transient() had a check for get_option( $transient_timeout ) < time().

Because get_option() can return false and false is always < time() 😖, get_transient() could delete transient timeout options in an unexpected way or cause two more unnecessary queries.

WordPress 4.3 now checks the return value first before comparing with the current time. This means that WordPress will no longer delete broken transients via get_transient() if you have only deleted the timeout option. See [33110].

If you have to delete a transient manually, please make sure that you’re deleting _transient_timeout_$transient and '_transient_' . $transient. (Hint: Transients can be stored in an external object cache too.)

See also: the Transients API Codex page.

#4-3, #dev-notes, #options-meta

Legacy Theme Preview Removed in 4.3

This release we removed the old code for the Legacy Theme Preview, which hasn’t been maintained since the introduction of the customizer in WordPress 3.5. Recently, we noticed that the theme preview no longer works when using a static front page. We kept the old theme preview for no-JS and some browsers that were less capable. But since browsers are doing a better job today we don’t need to continue fixing/shipping this legacy code. It’s removed in [33492].

#4-3, #dev-notes, #themes

Fast previewing changes to Menus in the Customizer

The foundation of the Customizer is built on the concept of the “setting”, an abstract representation of anything in WordPress: options, theme mods, posts, terms, and so on. Settings are linked to controls which are responsible for manipulating them. When a setting is changed it gets pushed into the preview window so that the modification can be reviewed before being published live.

There are two ways (transports) for how a setting can be pushed into the preview: refresh and postMessage. The refresh transport does a full page refresh with the modified settings applied, and so it relies on PHP to apply the setting changes. The refresh transport is designed to be compatible with all themes, but for heavy sites refresh can be excruciating slow and taxing on the server. For this reason, the postMessage transport was introduced for previewing changes. This transport uses JavaScript to apply the changes instantly in the preview without any Ajax requests or PHP calls. This is great, but themes have to opt-in to postMessage transport for settings because they must also include JavaScript code which duplicates the logic which is already being executed on the server by PHP. The postMessage transport violates the DRY principle.

With that background out of the way…

Partial Refresh of Menus

In WordPress 4.3 menu management is being added to the Customizer, extending the types of objects that the Customizer can manipulate to include nav_menu taxonomy terms and nav_menu_item posts. We wanted this menu management experience to be fast so it had to avoid the slow full-page refresh transport. Nevertheless, the postMessage transport wasn’t possible to use either since we wouldn’t be able to duplicate all of the PHP menu walker logic and theme/plugin extensions for rendering menus purely in JavaScript. We also wanted to enable fast previewing of menu changes by default. So we implemented a postMessage/refresh hybrid approach which uses postMessage to sync the menus settings to the preview, and then the preview does an Ajax request to render just the contents of the menu container, and this Ajax response is then inserted into the DOM to replace the previous menu container. The technical name for this approach we have been calling “partial refresh”, but you can call it “fast preview”.

When the Customizer determines it can’t do a partial refresh, it falls back to performing a full page refresh. Conditions for why a menu change will get a full page refresh include:

  • if the menu was just assigned to a location for the first time or removed from being assigned to a location, since the theme may have some changes to the layout that it may need to perform;
  • or if wp_nav_menu() is called with with echo being false, since the theme may be doing some string replacement in this case which we can’t replicate in the partial-refresh Ajax request;
  • or if wp_nav_menu() is called with with a non-JSON serializable fallback_cb, such as a closure or a object method—this arg has to be empty or a string;
  • or if wp_nav_menu() is called with with a walker object instance, as opposed to a class name string;
  • or if wp_nav_menu() is called without a theme_location arg and the menu arg is not an term ID or a menu object;
  • or if the menu selected in a Custom Menu widget is changed, since partial refresh for widgets is not yet supported (however, see feature plugin)—subsequent changes to the menu will result in fast partial refreshes if the above conditions

When a menu is being updated via partial refresh, the menu container will receive a classname customize-partial-refreshing, which by default changes the opacity to 25%.

Theme Support

The fast preview for menu changes is being enabled by default so that theme authors don’t have to opt-in to the functionality like they do for instant preview (postMessage transport). In general this should be fine. However, if the theme includes some JavaScript which dynamically manipulates the rendered menu container, such as adding event handlers for expanding/collapsing submenus, then the theme would need to include some JS to re-apply the modifications once the menu is partial-refreshed, as the old DOM for the menu container gets replaced.

The Twenty Fifteen theme actually uses JS to expand/collapse submenu items, so it needed a patch in 4.3 to re-setup a partial-refreshed main nav menu. In addition to firing the menu container DOM setup logic once at jQuery.ready(), it now invokes the functionality whenever the menu is partial-refreshed. See the initMainNavigation() JS function.

So in general, if your theme needs to dynamically initialize menus with JavaScript, the pattern for the initialization code should be:

jQuery(function($) {
	function initMainNavigation( container ) {
		/* set up container... */
	}
	initMainNavigation( $( '.main-navigation' ) );

	$( document ).on( 'customize-preview-menu-refreshed', function( e, params ) {
		if ( 'primary' === params.wpNavMenuArgs.theme_location ) {
			initMainNavigation( params.newContainer );
			/* optionally sync a previous menu state from params.oldContainer... */
		}
	});
});

The params being passed to the event handler consists of the following properties:

  • newContainer: jQuery object containing the new menu container element retrieved from Ajax; this is what you would manipulate to initialize.
  • oldContainer: the previous jQuery object holding the element for the replaced menu container; this is useful if there is any state in the old menu that should persist in the new menu, such as which submenus are expanded (as in Twenty Fifteen).
  • wpNavMenuArgs: The array of arguments passed to wp_nav_menu() in the template, such as template_location.
  • instanceNumber: The index for which wp_nav_menu() call being updated.

The Future

Partial refresh is an “experimental transport” introduced here specifically for menus. In 4.4 we hope to generalize the framework so that any setting can be setup for fast preview, starting with widgets (see #27355). There is a Customize Partial Refresh feature plugin that implements widget partial refresh in a beta state. This partial refresh functionality I’ve also identified as being critical for Customizer Transactions.

#4-3, #customize, #dev-notes, #feature-plugins, #feature-selective-refresh, #kickoff, #menu-customizer, #menus, #partial-refresh, #proposal

Old Distraction Free Writing Code Removed in 4.3

This release we removed all old DFW code, which hasn’t been used in core since 4.1. We left it in core for two releases so plugin authors had the time to update. If it is essential to your plugin, the files in 4.2 can still be reused and improved. See [32677].

#4-3, #dev-notes, #editor

Passwords in 4.3: Strong by Default

One of the development efforts in the WordPress 4.3 cycle was improving the way that passwords are chosen and changed. Before, people had to start from scratch when choosing a password. They were presented with an empty box, and had to use a really terrible tool for generating secure passwords: the human brain.

Here’s how things look now, as we approach 4.3’s release candidate…

Screen Shot

And when you click that button…

Screen Shot

You start out with a strong password. And if you like, you can just accept that. Most modern browsers will offer to remember it for you (as well as password managers like 1Password and LastPass). Or, you could go old school and write it on a sticky note. Hey: anything is better than choosing “letmein”!

You can, of course, click into the field and edit it. But now the password strength meter is better integrated with the field. Things start to look dire as you go your own way.

Screen Shot

That red seems to signal danger. And hey, look, below. This password is SO BAD that WordPress wants to make extra sure you know you’re doing something monstrously foolhardy.

If you’re in a public location, you can hide your password, to prevent people from peeking over your shoulder.

Screen Shot

This new interface is also integrated into the Add New User screen. By default, we won’t even reveal the password. We’ll just send the user a reset link.

Screen Shot

But if you’re in a non-email environment or would like to pass this password to the user in a secure method such as iMessage, Signal, or TextSecure, you can reveal it…

Screen Shot

The new interface can also be found on the password reset screen and the WordPress install screen. They all start you out with a long, random, unguessable password. Although WordPress isn’t stopping you from choosing terrible passwords, the default in 4.3 is that you get secure passwords, and making them less secure takes a bit of work.

In addition to this new UI, we have also stopped e-mailing passwords, so valid passwords aren’t going to sit in your e-mail inbox, waiting for some future e-mail hacker to gain access. Password reset links now expire in 24 hours by default. And when your password or e-mail changes, we send you an e-mail (in the case of e-mail, to your old address), so if someone hijacks your browser session and changes those critical items, at least you’ll be aware that it happened, and you can take action. You can disable these e-mails via the send_password_change_email and send_email_change_email filters (just have them return false).

Huge thanks to everyone who contributed code, testing, UI, and thoughtful feedback on this feature!

#4-3, #dev-notes, #passwords

Site Icon

WordPress 4.3 adds the ability for site owners to manage their site’s favicon on desktop and mobile. Site Icons work out of the box, are theme independent, and don’t require theme support. There are four sizes that WordPress supports by default:

  • 32x32px favicon.
  • 180x180px app icon for iOS up to the iPhone 6+.
  • 192x192px Android/Chrome app icon.
  • 270x270px medium-sized tile for Windows.

The public API is very simple:

  • wp_site_icon() displays all available favicons and app icons.
  • get_site_icon_url() returns the url to the current site’s icon, or the default passed to it.
  • site_icon_url() displays an escaped version of the url to the current site’s icon.
  • has_site_icon() returns whether the current site has an icon set up or not.

At this point we discourage theme authors from using site icons as logos in the front-end. It’s unexpected behavior for users since it doesn’t fit the API’s purpose.

Custom Site Icons

Plugin authors can add custom sizes to the site icon feature. To do this, filter the array of available sizes on the admin side and the array of meta tags on the front-end, like so:

<?php

function prefix_custom_site_icon_size( $sizes ) {
   $sizes[] = 64;

   return $sizes;
}
add_filter( 'site_icon_image_sizes', 'prefix_custom_site_icon_size' );

function prefix_custom_site_icon_tag( $meta_tags ) {
   $meta_tags[] = sprintf( '<link rel="icon" href="%s" sizes="64x64" />', esc_url( get_site_icon_url( null, 64 ) ) );

   return $meta_tags;
}
add_filter( 'site_icon_meta_tags', 'prefix_custom_site_icon_tag' );

Customizer Controls

Nick Halsey published an article about the new Customizer controls that were introduced for Site Icon. The new controls make it trivial for any theme or plugin author to add custom features that require cropped images. For example, a logo manager. 😉

#4-3, #customize, #dev-notes, #site-icons