The WordPress coreCoreCore is the set of software required to run WordPress. The Core Development Team builds WordPress. development team builds WordPress! Follow this site for general updates, status reports, and the occasional code debate. There’s lots of ways to contribute:
Found a bugbugA bug is an error or unexpected result. Performance improvements, code optimization, and are considered enhancements, not defects. After feature freeze, only bugs are dealt with, with regressions (adverse changes from the previous version) being the highest priority.?Create a ticket in the bug tracker.
Since WP_Widget was introduced in 2.8 the register_widget() and unregister_widget() functions required the class name (string) of a WP_Widget subclass to be supplied. As of 4.6 these functions also accept a class instance (object) of a WP_Widget subclass as well. See #28216.
Two key benefits for allowing objects to be instantiated are:
Widgets can now be instantiated and registered with constructor dependency injection.
New widgetWidgetA WordPress Widget is a small block that performs a specific function. You can add these widgets in sidebars also known as widget-ready areas on your web page. WordPress widgets were originally created to provide a simple and easy-to-use way of giving design and structure control of the WordPress theme to the user. types can now be added dynamically, such as adding a Recent Posts widget for each post type, per #35990.
As described in the Improving Setting Validation in the Customizer proposal post and detailed in #34893 and #36944, WordPress 4.6 includes new APIs related to validation of CustomizerCustomizerTool built into WordPress core that hooks into most modern themes. You can use it to preview and modify many of your site’s appearance settings. setting values. The Customizer has had sanitization of setting values since it was introduced. Sanitization involves coercing a value into something safe to persist to the database: common examples are converting a value into an integer or stripping tags from some text input. As such, sanitization is a lossy operation.
But what happens in sanitization if a provided value is irrecoverable, beyond the ability to sanitize? The Customizer did allow sanitizers to return null in such cases which resulted in the value being skipped entirely from previewing and saving, but there was no feedback to the user that the value was skipped. Additionally, when multiple settings were modified but some were skipped due to returning null, the result was that a save operation would only persist the non-skipped settings to database: a user would unexpectedly find that only some of their settings were applied, resulting in an inconsistent saved state. Save operations were not transactional/atomic.
These are the problems that the Customizer setting validation improvements in WordPress 4.6 are designed to address. With setting validation:
All modified settings are validated up-front before any of them are saved.
If any setting is invalidinvalidA resolution on the bug tracker (and generally common in software development, sometimes also notabug) that indicates the ticket is not a bug, is a support request, or is generally invalid., the Customizer save request is rejected: a save thus becomes transactional with all the settings left dirty to try saving again. (The Customizer transactions proposal is closely related to setting validation here.)
Validation error messages are displayed to the user, prompting them to fix their mistake and try again.
Sanitization and validation are also both part of the REST APIREST APIThe REST API is an acronym for the RESTful Application Program Interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data. It is how the front end of an application (think “phone app” or “website”) can communicate with the data store (think “database” or “file system”)
https://developer.wordpress.org/rest-api/ infrastructure via WP_REST_Request::sanitize_params() and WP_REST_Request::validate_params(), respectively. A setting’s value goes through validation before it goes through sanitization (this is contrary to the original proposal, see #36944).
Validation Behavior
As noted above, if any setting is invalid, a Customizer save request is blocked. When save request is rejected due to setting invalidity, the controls that have the invalid setting will get the error notifications added to them, and one of these controls will be focused so that the user can correct the mistake. If there is an control with an invalid setting in the current section expanded, then this is the focus that will get the focus. Otherwise, the section containing an invalid control will get expanded and the control then focused.
Validation of setting values on the server does not only occur when a save is attempted. The setting values are validated and re-validated with each full refresh and selective refresh, and the their validity states are returned from the server in the responses. This means that setting validity will be reported in conjunction with updates to the preview. This is important for a couple reasons:
When a setting is invalid, the previewed value will render using the previously-saved value or the default setting value, so the notification provides an explanation for why their changes aren’t appearing in the preview.
As soon as a value is corrected and the preview request finishes, the error notification will be removed from the control. This means the user doesn’t have to try to saving to see whether the value has been corrected or not.
This second point has a key implication for validating settings that are previewed purely via JavaScriptJavaScriptJavaScript or JS is an object-oriented computer programming language commonly used to create interactive effects within web browsers. WordPress makes extensive use of JS for a better user experience. While PHP is executed on the server, JS executes within a user’s browser.
https://www.javascript.com (the postMessage transport without selective refresh): you should perform the validation logic for these using JavaScript as well. See client-side validation below.
Adding Validation to a Setting
Validate Callback
Just as you can supply a sanitize_callback when registering a setting, you can also supply a validate_callback arg:
Just as supplying a sanitize_callback arg adds a filterFilterFilters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. for customize_sanitize_{$setting_id}, so too supplying a validate_callback arg will add a filter for customize_validate_{$setting_id}. Assuming that the WP_Customize_Setting instances apply filters on these in their validate methods, you can add this filter if you need to add validation for settings that have been previously added.
The validate_callback and any customize_validate_{$setting_id} filter callbacks take a WP_Error instance is its first argument (which initially is empty of any errors added), followed by the $value being sanitized, and lastly the WP_Customize_Setting instance that is being validated.
Validate Method
A second way to add validation to a setting is by overriding the validate method on a WP_Customize_Setting subclass. For example:
class Established_Year_Setting extends WP_Customize_Setting {
function validate( $value ) {
if ( empty( $value ) || ! is_numeric( $value ) ) {
return new WP_Error( 'required', __( 'You must supply a valid year.' ) );
}
if ( $value < 1900 ) {
return new WP_Error( 'year_too_small', __( 'Year is too old.' ) );
}
if ( $value > gmdate( 'Y' ) ) {
return new WP_Error( 'year_too_big', __( 'Year is too new.' ) );
}
return true;
}
}
Validating via Sanitization
The last way to add validation to a setting is to overload the sanitization routine to include validation as well. Setting sanitization and setting validation are closely related. Sanitization is for coercing/cleaning data. Validation is a pass/fail operation and is key to prevent data from being accepted when it is “too far gone” to be recovered from or when it is undesirable for the value to be silently and lossily cleaned. As noted above, setting’s sanitization logic can continue to return null and this will get interpreted as a setting’s value being invalid with a returned generic “Invalid value” error. You may also return a WP_Error instance from a sanitization routine which can be a handy way to consolidate the closely-related sanitization/validation logic; if you do this, make sure that you opt to return null in WP≤4.5, as otherwise this would result in a WP_Error instance being saved as a setting’s value (!!):
function sanitize_number( $value ) {
$can_validate = method_exists( 'WP_Customize_Setting', 'validate' );
if ( ! is_numeric( $value ) ) {
return $can_validate ? new WP_Error( 'nan', __( 'Not a number' ) ) : null;
}
return intval( $value );
}
Again, this useful if you want to consolidate the closely-related logic into a single routine and also when to perform late validation after a value has been sanitized.
Client-side Validation
As noted above, if you have a setting that is previewed purely via JavaScript (and the postMessage transport without selective refresh), you should also add client-side validation as well. If you don’t then any validation errors will persist until a refresh happens or a save is attempted. Client-side validation must not take the place of server-side validation, since it would be trivial for a malicious user to bypass the client-side validation to save an invalid value if corresponding server-side validation is not in place.
There is actually already a validate method available on the wp.customize.SettingJSJSJavaScript, a web scripting language typically executed in the browser. Often used for advanced user interfaces and behaviors. class (actually, the wp.customize.Value base class). It was introduced with the inception of the Customizer in WP 3.4, although I believe it has been rarely utilized. The validate method’s name is a bit misleading, as it actually behaves very similarly to the WP_Customize_Setting::sanitize()PHPPHPThe web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher method. Nevertheless, the method can be used to both sanitize and validate a value in JS. Note that this JS runs in the context of the Customizer pane not the preview, so any such JS should have customize-controls as a dependency (not customize-preview) and enqueued during the customize_controls_enqueue_scripts action. Some example JS validation:
wp.customize( 'established_year', function ( setting ) {
setting.validate = function ( value ) {
var code, notification;
var year = parseInt( value, 10 );
code = 'required';
if ( isNaN( year ) ) {
notification = new wp.customize.Notification( code, {message: myPlugin.l10n.requiredYear} );
setting.notifications.add( code, notification );
} else {
setting.notifications.remove( code );
}
if ( isNaN( year ) ) {
return value;
}
code = 'year_too_small';
if ( year < 1900 ) {
notification = new wp.customize.Notification( code, {message: myPlugin.l10n.yearTooSmall} );
setting.notifications.add( code, notification );
} else {
setting.notifications.remove( code );
}
code = 'year_too_big';
if ( year > new Date().getFullYear() ) {
notification = new wp.customize.Notification( code, {message: myPlugin.l10n.yearTooBig} );
setting.notifications.add( code, notification );
} else {
setting.notifications.remove( code );
}
return value;
};
} );
Notifications APIAPIAn API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways.
An error notification is added to a setting’s notifications collection when a setting’s validation routine returns a WP_Error instance. Each error added to a PHP WP_Error instance is represented as a wp.customize.Notification in JavaScript:
A WP_Error‘s code is available as notification.code in JS.
A WP_Error‘s message is available as notification.message in JS. Note that if there are multiple messages added to a given error code in PHP they will be concatenated into a single message in JS.
A WP_Error‘s data is available as notification.data in JS. This is useful to pass additional error context from the server to the client.
Any time that a WP_Error is returned from a validation routine on the server it will result in a wp.customize.Notification being created with a type property of “error”.
While setting non-error notifications from PHP is not currently supported (see #37281), you can also add non-error notifications with JS as follows:
wp.customize( 'blogname', function( setting ) {
setting.bind( function( value ) {
var code = 'long_title';
if ( value.length > 20 ) {
setting.notifications.add( code, new wp.customize.Notification(
code,
{
type: 'warning',
message: 'Theme prefers title with max 20 chars.'
}
) );
} else {
setting.notifications.remove( code );
}
} );
} );
You can also supply “info” as a notification’s type. The default type is “error”. Custom types may also be supplied, and the notifications can be styled with CSSCSSCascading Style Sheets. selector matching notice.notice-foo where “foo” is the type supplied. A control may also override the default behavior for how notifications are rendered by overriding the wp.customize.Control#renderNotifications method.
More Examples
A couple plugins that make use of validation:
Customize Validate Entitled Settings: Demo that forces the site title, widgetWidgetA WordPress Widget is a small block that performs a specific function. You can add these widgets in sidebars also known as widget-ready areas on your web page. WordPress widgets were originally created to provide a simple and easy-to-use way of giving design and structure control of the WordPress theme to the user. titles, and nav menu labels to be populated with title case and lacking exclamations and questions.
Customize Posts: Validation errors added when posts would fail to save due to empty content, post locking, or save conflicts (with the specific conflicted fields being returned as WP_Errordata). This pluginPluginA plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party. also features syncing back the server-sanitized setting values to upon save, something which I think should be in coreCoreCore is the set of software required to run WordPress. The Core Development Team builds WordPress. at some point.
Standalone Customizer Controls: Demonstration of a controls used outside the Customizer with notifications added via JS based on HTML5 validity state.
Summary of API Changes
PHP changes:
Introduces WP_Customize_Setting::validate(), WP_Customize_Setting::$validate_callback, and the customize_validate_{$setting_id} filter.
Introduces WP_Customize_Manager::validate_setting_values() to do validation (and sanitization) for the setting values supplied, returning a list of WP_Error instances for invalid settings.
Attempting to save settings that are invalid will result in the save being blocked entirely, with the errors being sent in the customize_save_response. Modifies WP_Customize_Manager::save() to check all settings for validity issues prior to calling their save methods.
Introduces WP_Customize_Setting::json() for parity with the other Customizer classes. This includes exporting of the type.
Modifies WP_Customize_Manager::post_value() to apply validate after sanitize, and if validation fails, to return the $default.
Introduces customize_save_validation_before action which fires right before the validation checks are made prior to saving.
JS changes:
Introduces wp.customize.Notification in JS which to represent WP_Error instances returned from the server when setting validation fails.
Introduces wp.customize.Control.prototype.notifications, which are synced with a control’s settings’ notifications.
Introduces wp.customize.Control.prototype.renderNotifications() to re-render a control’s notifications in its notification area. This is called automatically when the notifications collection changes.
Introduces wp.customize.settingConstructor, allowing custom setting types to be used in the same way that custom controls, panels, and sections can be made.
Injects a notification area into existing controls which is populated in response to the control’s notifications collection changing. A custom control can customize the placement of the notification area by overriding the new getNotificationsContainerElement method.
When a save fails due to setting invalidity, the invalidity errors will be added to the settings to then populate in the controls’ notification areas, and the first such invalid control will be focused.
In #34893 and the accompanying Customize Setting Validationfeature pluginFeature PluginA plugin that was created with the intention of eventually being proposed for inclusion in WordPress Core. See Features as Plugins I’ve suggested improvements to the CustomizerCustomizerTool built into WordPress core that hooks into most modern themes. You can use it to preview and modify many of your site’s appearance settings. setting validation model. More can be read about the proposal in that ticketticketCreated for both bug reports and feature development on the bug tracker. description and pluginPluginA plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party.readme, but the short of it is that settings in the Customizer generally undergo clean-up sanitization but lack a robust system for pass/fail validation. Here is a video demo depicting what I think validation should look like in the Customizer:
Normally the Customizer just sanitizes values by attempting to coerce them and clean them up into something that can be safely used (e.g. stripping tags). As for validation, and while I believe this is relatively unusual to encounter, you can also do strict validation of a setting by blocking it from being saved: this is done by returning null from WP_Customize_Setting::sanitize() (often via WP_Customize_Setting::$sanitize_callback). This is the behavior for setting the background_color: if the value is not a valid hex code, it will not save. The problem here is that there is no feedback to the user that the save was blocked. If user tries to enter “blue” as a color instead of a hex code, they will not get informed that this is invalidinvalidA resolution on the bug tracker (and generally common in software development, sometimes also notabug) that indicates the ticket is not a bug, is a support request, or is generally invalid.: it will be as if they never tried to save any change at all. Incidentally, this is also the case for widgets, where the WP_Widget::update() normally just sanitizes the instance arrays, though it can return false to blockBlockBlock is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. an update, with likewise no indication that the update was blocked.
Additionally, in the current validation system, if you have made 10 changes in your Customizer session (transaction), but half of them get blocked from saving due to being invalid, then you have an only partially-saved Customizer state. This is a really bad experience for sites that make heavy use of the Customizer beyond just using it to tweak some colors.
So to summarize the suggested improvements to validation in the customizer:
All modified settings should be validated up-front before any of them are saved.
If any setting is invalid, the Customizer save request should be rejected: a save thus becomes transactional with all the settings left dirty to try saving again.
Validation error messages should be displayed to the user, prompting them to fix their mistake and try again.
All of the above is implemented in the Customize Setting Validation feature plugin, and I’d love your feedback on it. One thing in particular I need feedback on is how specifically a setting should go about performing validation on the server. As noted above, the WP_Customize_Setting::sanitize() method can currently do both sanitization (returning a cleaned-up value) and validation (returning null to block saving if value is beyond repair). In the current feature plugin, I’m proposing:
Continue to use the same sanitize methods/callbacks/filters.
Introduce a new $strict param to indicate that validation is being performed.
Allow these functions to fail validation by returning WP_Error instances with information about what failed in addition to null as they can today.
Update 2016-06-26: The following examples differ from what has been committed to coreCoreCore is the set of software required to run WordPress. The Core Development Team builds WordPress. A follow-up post will detail the new APIs for validation.
How the changes would look for WP_Customize_Setting::sanitize():
/**
* Sanitize an input.
*
* @since 3.4.0
* @since 4.6.0 Added `$strict` param to indicate validation is being performed.
*
* @param string|array $value The value to sanitize.
* @param bool $strict Whether validation is being performed.
* @return string|array|null|WP_Error Null or WP_Error if an input isn't valid, otherwise the sanitized value.
*/
public function sanitize( $value, $strict = false )
And for the customize_sanitize_{$id}filterFilterFilters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output.:
/**
* Filter a Customize setting value.
*
* @since 3.4.0
* @since 4.6.0 Added `$strict` param to indicate validation is being performed.
*
* @param mixed $value Value of the setting.
* @param bool $strict Whether validation is being performed.
* @param WP_Customize_Setting $this WP_Customize_Setting instance.
*/
return apply_filters( "customize_sanitize_{$this->id}", $value, $this, $strict );
This should be nicely backwards-compatible, and allow for the sanitize/validate logic to be kept in the same function since they are very closely related. But that raises some questions:
Should there be a separate WP_Customize_Setting::validate() method as well that by default calls WP_Customize_Setting::sanitize() with the $strict param set to true?
Should validation only be applied when saving the setting while mere sanitization is required for previewing a value change?
On the second point here, my thought is that it may often be the desire for looser cleanup sanitization to be applied to a value during data entry. Consider a blob of text displayed on the page which forbids the use of markup. As I do data entry I may like to see what I am entering being displayed in the preview with the tags stripped (normal behavior today) whereas when I try saving I can be alerted that saving the value with markup is not allowed. This would provide the user with feedback as to why the markup is mysteriously not appearing in the preview. (As for providing this validation feedback while the user entering data, this should be done via JSJSJavaScript, a web scripting language typically executed in the browser. Often used for advanced user interfaces and behaviors., or the validation state be determined by performing validation in an update-transaction request for transactions.)
I’ll also note that REST APIREST APIThe REST API is an acronym for the RESTful Application Program Interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data. It is how the front end of an application (think “phone app” or “website”) can communicate with the data store (think “database” or “file system”)
https://developer.wordpress.org/rest-api/ supports both sanitization and validation for request args, but these are handled in two separate callbacks. The way it works is that any registered sanitize_callbacks are applied first, followed by setting of default values, and then the validate_callbacks are run. See WP_REST_Server::dispatch(). This works fine, but I think we could have more flexibility if the sanitization and validation logic could be in the same method. Perhaps you want to run sanitization before validation (sanitize by stripping tags and validate to ensure the value is not empty), or be more strict by running validation before sanitization (reject any text that contains markup entirely).
So, for you all who develop settings in the Customizer, what are your thoughts on how validation should behave, and how validation should relate to sanitization in the context of the Customizer? What do you think of the APIAPIAn API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. changes I’ve proposed?
Early this week, @celloexpressions led a bugbugA bug is an error or unexpected result. Performance improvements, code optimization, and are considered enhancements, not defects. After feature freeze, only bugs are dealt with, with regressions (adverse changes from the previous version) being the highest priority. scrub for the Customize component which can be read in the chat logs. We did a bug scrub for the tickets milestoned for 4.6. Some highlights:
Transactions (#30937) is a high priority due to it resolving several other tickets. I (@westonruter) will try to make headway this week. Tickets impacted by this include (among others, since this a low-level architectural change for the CustomizerCustomizerTool built into WordPress core that hooks into most modern themes. You can use it to preview and modify many of your site’s appearance settings.):
#30028: Load Customizer preview iframeiframeiFrame is an acronym for an inline frame. An iFrame is used inside a webpage to load another HTML document and render it. This HTML document may also contain JavaScript and/or CSS which is loaded at the time when iframe tag is parsed by the user’s browser. with natural URLURLA specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org
#20714: Theme customizer: Impossible to preview a search results page
#23225: Customizer is Incompatible with jQuery UIUIUser interface Tabs.
#31517: Customizer: show a notice after attempting to navigate to external links in live previews
#34142: Links with preventDefault() don’t have action prevented in Customizer
#28227: Customizer: Error message instead of blank screen
#22037: Customizer: Live preview fetches page but does not display
We discussed improvements to the Customizer setting validation model (#34893) and how they relate to transactions. I’ll be writing a separate Make CoreCoreCore is the set of software required to run WordPress. The Core Development Team builds WordPress. post to get feedback on it.
Global notification area and control-level notification areas were discussed. The global notification area (#35210) would be used for general Customizer notices/errors, such as fatal errors during save (#31582), whereas the notification are proposed for the in the setting validation model improvements (#34893) could be used for control-level notifications, like an error to uploading an image to a media control (#29932). Work is needed on the global notification area APIAPIAn API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. and UI. Ideally the same API could be used at the control level, where there could be a wp.customize.notifications collection but also a wp.customize.control(...).notifications collection, both of which would be instances of the same NotificationCollection. Help wanted.
The customize_value_{$id_base}filterFilterFilters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. now has the $setting object passed as the second param (#36452). The related ticketticketCreated for both bug reports and feature development on the bug tracker. to add more actions/filters for implementing value and preview interfaces without subclassing WP_Customize_Setting (#29316) has been punted.
A new “Edit Menu” button for the Custom Menu widgetWidgetA WordPress Widget is a small block that performs a specific function. You can add these widgets in sidebars also known as widget-ready areas on your web page. WordPress widgets were originally created to provide a simple and easy-to-use way of giving design and structure control of the WordPress theme to the user. in Customizer (#32683) will get a new patchpatchA special text file that describes changes to code, by identifying the files and lines which are added, removed, and altered. It may also be referred to as a diff. A patch can be applied to a codebase for testing. from @celloexpressions.
Simplification of the Customizer image control action buttons (#36175) needs some design/UXUXUser experience feedback, and letting the image placeholder be clickable (#34323) was also discussed and also needs feedback.
Cleaning up the Customizer media control CSSCSSCascading Style Sheets. (#30618) will get another patch from @celloexpressions this week.
We will be doing weekly meeting (office hours, triagetriageThe act of evaluating and sorting bug reports, in order to decide priority, severity, and other factors., bug scrubs) at 20:00UTC on Mondays. See upcoming meetings for the next time.
This Monday, 18 April, 20:00 UTC we’ll have a CustomizerCustomizerTool built into WordPress core that hooks into most modern themes. You can use it to preview and modify many of your site’s appearance settings. chat in #core-customize to discuss the roadmap and ideas for 4.6.
Referring to the Customizer roadmap post (and component page), at a high level, two big features I personally am interested in are:
#34923: Introduce basic content authorship in the Customizer
#28216: Allow to register pre-instantiated widgets
#33507: Allow widgetWidgetA WordPress Widget is a small block that performs a specific function. You can add these widgets in sidebars also known as widget-ready areas on your web page. WordPress widgets were originally created to provide a simple and easy-to-use way of giving design and structure control of the WordPress theme to the user. controls to be JSJSJavaScript, a web scripting language typically executed in the browser. Often used for advanced user interfaces and behaviors.-driven
#35574: Add REST APIREST APIThe REST API is an acronym for the RESTful Application Program Interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data. It is how the front end of an application (think “phone app” or “website”) can communicate with the data store (think “database” or “file system”)
https://developer.wordpress.org/rest-api/JSONJSONJSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML. schema information to WP_Widget
Please share in the comments below if there are any specific features and tickets that you want to contribute in this next release to push the Customizer forward. Otherwise, please also join us in #core-customize chat to discuss.
WordPress 4.5 includes a new CustomizerCustomizerTool built into WordPress core that hooks into most modern themes. You can use it to preview and modify many of your site’s appearance settings. framework called selective refresh. To recap, selective refresh is a hybrid preview mechanism that has the performance benefit of not having to refresh the entire preview window. This was previously available with JSJSJavaScript, a web scripting language typically executed in the browser. Often used for advanced user interfaces and behaviors.-applied postMessage previews, but selective refresh also improves the accuracy of the previewed change while reducing the amount of code you have to write; it also just makes possible to do performant previews that would previously been practically impossible. For example, themes often include some variation of the following PHPPHPThe web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher and JavaScriptJavaScriptJavaScript or JS is an object-oriented computer programming language commonly used to create interactive effects within web browsers. WordPress makes extensive use of JS for a better user experience. While PHP is executed on the server, JS executes within a user’s browser.
https://www.javascript.com to enable performant previewing of changes to the site title:
( function( $, api ) {
api( 'blogname', function( setting ) {
setting.bind( function( value ) {
$( '.site-title a' ).text( value );
} );
} );
} ( jQuery, wp.customize ) );
In 4.5, the coreCoreCore is the set of software required to run WordPress. The Core Development Team builds WordPress. themes now utilize selective refresh for previewing the site title and tagline. This allows the above code to be replaced with the following PHP:
So as you can see, not only is the amount of code more than cut in half (also eliminating the JS file altogether), it also ensures that when a site title change is previewed it will appear with all of the PHP filters applied from core and plugins: for example wptexturize will apply so that curly quotes and dashes will appear as expected. In REST APIREST APIThe REST API is an acronym for the RESTful Application Program Interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data. It is how the front end of an application (think “phone app” or “website”) can communicate with the data store (think “database” or “file system”)
https://developer.wordpress.org/rest-api/ parlance, selective refresh enables the Customizer preview to show title.rendered instead of just title.raw. (For more on this change to previewing the site title and tagline, see #33738. The previous JS-based previewing is retained for an instant low-fidelity preview while the selective refresh request returns.) Selective refresh is also the mechanism used for previewing the new custom logo feature in 4.5, ensuring that the logo image is rendered re-using the image_downsize logic in PHP without having to re-implement it in JS (keeping the code DRY).
With that recap of selective refresh out of the way, let’s turn to the focus of this post: selective refresh for widgets. When widgetWidgetA WordPress Widget is a small block that performs a specific function. You can add these widgets in sidebars also known as widget-ready areas on your web page. WordPress widgets were originally created to provide a simple and easy-to-use way of giving design and structure control of the WordPress theme to the user. management was added to the Customizer in 3.9, every change to a widget required a full page refresh to preview. This resulted in a poor user experience since a full refresh can take awhile, especially on weighty pages. So selective refresh of widgets is a key usability experience improvement for widget management in the Customizer in 4.5. However, as live postMessage updates to the site title and tagline have required supporting theme code (see above), so too will theme support be required for widgets, as noted in the Selective Refresh of Widgets section from the previous post on this topic:
Selective refresh for nav menus was enabled by default in 4.3. While some themes needed to add theme support for any dynamic aspects (such as the expanding submenus in Twenty Fifteen), generally nav menus seem to be fairly static and can be replaced in the document without needing any JS logic to be re-applied. Widgets, on the other hand, have much more variation in what they can display, since they can in fact display anything. For any widget that uses JavaScript to initialize some dynamic elements, such as a map or gallery slideshow, simply replacing the widget’s content with new content from the server will not work since the dynamic elements will not be re-initialized. Additionally, the sidebars (widget areas) in which the widgets are displayed may also have dynamic aspects associated with them, such as the Twenty Thirteen sidebarSidebarA sidebar in WordPress is referred to a widget-ready area used by WordPress themes to display information that is not a part of the main content. It is not always a vertical column on the side. It can be a horizontal rectangle below or above the content area, footer, header, or any where in the theme. which displays widgets in a grid using Masonry. For this theme, whenever a widget is changed/added/removed/reordered, the sidebar needs to be reflowed.
In order to allow themes to reflow sidebars and widgets to reinitialize their contents after a refresh, the selective refresh framework introduces widget-updated and sidebar-updated events. Additionally, since re-ordering widgets in a sidebar is instant by just re-ordering the elements in the DOM, some widgets with dynamically-generated iframes (such as a Twitter widget) may need to also be rebuilt, and for this reason there is a partial-content-moved event.
For the above reasons, I believe it will be much more common for widgets (and sidebars) to need special support for selective refresh, and so I think that at least for 4.5 the selective refresh should be opt-in for widgets (and perhaps in themes for sidebars). See theme support for Twenty Thirteen and plugin support for a few widgets in Jetpack (which won’t be part of the merge). At last week’s Core dev meeting, it was suggested that we add the opt-in for widget selective refresh at RCrelease candidateOne of the final stages in the version release cycle, this version signals the potential to be a final release to the public. Also see alpha (beta)..
So as noted, selective refresh for widgets will be opt-in as of 4.5 RC1 (see #35855).
What do themes and widgets need to do to opt-in for selective refresh support?
Selective refresh will be used for previewing a widget change when both the theme and the widget itself indicate support as follows:
Adding Theme Support
If your theme does not do anything fancy with its sidebars (such as using Masonry to lay out widgets), then all that you need to do is add the following to your theme:
On the other hand, if the theme is rendering a sidebar in a unique way, then to add a bit of logic to handle the changes properly. For example, as noted previously the footer area in Twenty Thirteen consists of a sidebar that is laid out using Masonry. When a widget is added, removed, or updated, the Masonry logic needs to be re-run to update the positioning of the widgets in the sidebar. The following highlighted code is what handles this:
Update 2016-07-17: Added the jQuery() DOM ready wrapper around this logic to ensure it runs after the DOM has been fully loaded, and thus ensuring the wp.customize.selectiveRefresh object exists if it is going to be loaded. See #37390 as this also turned out to be broken in Twenty Thirteen.
Note the if statement is there so the code will only run in the Customizer preview and if selective refresh is available (that is, if they are running 4.5 or later).
Adding Widget Support
If your widget lacks any dynamic functionality with JavaScript initialization, adding support just requires adding a customize_selective_refresh flag to the $widget_options param when constructing the WP_Widget subclass. If you are enqueueing any CSSCSSCascading Style Sheets. for styling the widget, you’ll also want to enqueue this unconditionally in the Customizer preview (if is_customize_preview()) so that a widget can be added to the preview and be styled properly without doing a full page refresh. For example, note these highlighted lines in a sample widget:
class Example_Widget extends WP_Widget {
public function __construct() {
parent::__construct(
'example',
__( 'Example', 'my-plugin' ),
array(
'description' => __( 'Selective refreshable widget.', 'my-plugin' ),
'customize_selective_refresh' => true,
)
);
// Enqueue style if widget is active (appears in a sidebar) or if in Customizer preview.
if ( is_active_widget( false, false, $this->id_base ) || is_customize_preview() ) {
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
}
}
public function enqueue_scripts() {
wp_enqueue_style( 'my-plugin-example-widget', plugins_url( 'example-widget.css', __FILE__ ), array(), '0.1' );
}
/* ... */
}
On the other hand, as with sidebars in a theme, if a widget uses JavaScript for initialization, you’ll need to add logic to make sure re-initialization happens when the widget is selectively refreshed. So in addition to the above example, you must:
Enqueue any dependent JS logic if is_customize_preview() just as noted above for enqueueing any CSS stylesheet.
Add a handler for partial-content-rendered selective refresh events to rebuild a widget’s dynamic elements when it is re-rendered.
As needed, add a handler for partial-content-moved selective refresh events to refresh partials if any dynamic elements involve iframes that have dynamically-written documents (such as the Twitter Timeline widget). (Adding this event handler should normally not be required.)
The Twitter Timeline widget in the Jetpack pluginPluginA plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party. is a good example for how to write these event handlers:
jQuery( function() {
// Short-circuit selective refresh events if not in customizer preview or pre-4.5.
if ( 'undefined' === typeof wp || ! wp.customize || ! wp.customize.selectiveRefresh ) {
return;
}
// Re-load Twitter widgets when a partial is rendered.
wp.customize.selectiveRefresh.bind( 'partial-content-rendered', function( placement ) {
if ( placement.container ) {
twttr.widgets.load( placement.container[0] );
}
} );
// Refresh a moved partial containing a Twitter timeline iframe, since it has to be re-built.
wp.customize.selectiveRefresh.bind( 'partial-content-moved', function( placement ) {
if ( placement.container && placement.container.find( 'iframe.twitter-timeline:not([src]):first' ).length ) {
placement.partial.refresh();
}
} );
} );
All core themes and core widgets will have support for selective refresh in 4.5. Now it’s up to theme and plugin authors to also add support to also start taking advantage of these drastic performance improvements for previewing widget changes.
In addition to the ~35 defects that were fixed in this release, there were also ~17 features and enhancements that were made. What follows are some highlights, starting with some smaller enhancements and then listing out full posts that document the larger features.
Sometimes controls need to be added which don’t directly have associated settings. For example, there can be controls needed which manipulate some aspect of the CustomizerCustomizerTool built into WordPress core that hooks into most modern themes. You can use it to preview and modify many of your site’s appearance settings. interface or manage the behavior of other controls and their settings: consider a control for managing repeating controls, where the button only serves to create other controls and their settings. When nav menus were added in the Customizer in 4.3, the UIUIUser interface for creating a new menu involved two controls which had custom settings associated them (create_new_menu and new_menu_name) which served no purpose other than to make sure the control wouldn’t raise an error. The settings had custom types to prevent them from getting saved to the DB.
In 4.5, controls are no longer required to have associated settings. By default registering a control without an explicit settings argument will result in the control’s own id being supplied as the associated setting id. To explicitly register a control without any associated settings, pass an empty array as the settings:
Because controls no longer require settings, controls now accept a capability argument (as seen above) whereas previously a control’s capabilitycapabilityA capability is permission to perform one or more types of task. Checking if a user has a capability is performed by the current_user_can function. Each user of a WordPress site might have some permissions but not others, depending on their role. For example, users who have the Author role usually have permission to edit their own posts (the “edit_posts” capability), but not permission to edit other users’ posts (the “edit_others_posts” capability). would depend on the capabilitiescapabilityA capability is permission to perform one or more types of task. Checking if a user has a capability is performed by the current_user_can function. Each user of a WordPress site might have some permissions but not others, depending on their role. For example, users who have the Author role usually have permission to edit their own posts (the “edit_posts” capability), but not permission to edit other users’ posts (the “edit_others_posts” capability). of its associated settings. A control will not be displayed if it has a defined capability which the user doesn’t have, or if the user doesn’t have the capability required for any of the associated settings. If you omit the capability for a setting-less control, it will be displayed to all users (who can customize).
Other Improvements
Shift-click on nav menu items in preview to open corresponding control in Customizer pane (#26005).
Shift-click on site title and tagline for CoreCoreCore is the set of software required to run WordPress. The Core Development Team builds WordPress. themes and any that implement selective refresh partials for these settings. Focus on the control for any setting in the preview by sending a focus-control-for-setting message to the pane, passing the setting ID. This is used to focus on controls when a shift-click is done on a selective refresh partial.
Site title and tagline will be updated via selective refresh in core themes. (#33738)
WP_Customize_Manager::add_*() methods now return the added instance. (#34596)
WP_Customize_Manager::add_setting() now applies the relevant dynamic setting filters. (#34597)
There is a new customize_nav_menu_searched_itemsfilterFilterFilters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. for nav menu item searches. (#34947)
The WP_Customize_Media_Control now allows its button_labels to be overridden. (#35542)
The setting models in the preview now have a id property and _dirty flag to correspond to the settings in the pane; dynamically created settings in the pane will be created in the preview. (#35616)
More config settings are exported to the preview to allow the preview to do more operations inline, including more nonces, the current theme, and the previewed URLURLA specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org. (#35617)
This proposal was merged to coreCoreCore is the set of software required to run WordPress. The Core Development Team builds WordPress.CoreCore is the set of software required to run WordPress. The Core Development Team builds WordPress. in [36586]. Download the latest nightly build and give it a try!
The CustomizerCustomizerTool built into WordPress core that hooks into most modern themes. You can use it to preview and modify many of your site’s appearance settings. is our framework for live previewing changes. However, settings edited in the Customizer get sent to the preview via the refresh transport by default, meaning that in order for a setting change to be applied, the entire preview has to reload: this refresh can be very slow and is anything but “live”. To remedy this poor user experience of a laggy preview, the Customizer allows settings to opt-in to using a postMessage transport which relies on JavaScriptJavaScriptJavaScript or JS is an object-oriented computer programming language commonly used to create interactive effects within web browsers. WordPress makes extensive use of JS for a better user experience. While PHP is executed on the server, JS executes within a user’s browser.
https://www.javascript.com to preview the change instantly without doing any server-side communication at all. This provides for a great user experience.
There is a major issue with settings using the postMessage transport, however: any logic used in PHPPHPThe web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher to render the setting in the template has to be duplicated in JavaScript. This means that the postMessage previewing logic violates the DRY (Don’t Repeat Yourself) principle, and so it is really only suitable for simple text or style changes that involve almost no logic (e.g. site title or background color). Even in this case, it is often not possible to fully re-implement the PHP logic in JSJSJavaScript, a web scripting language typically executed in the browser. Often used for advanced user interfaces and behaviors., since as in the example of #33738 there may be an unknown number of PHP filters that get applied to the setting’s value (such as the site title) when rendering the content on the server.
What the Customizer needs is a middle-ground between refreshing the entire preview to apply changes with PHP and between applying the changes exclusively with JavaScript. The selective refresh is the solution proposed in #27355, and this post is about documenting the feature, as it was approved for core merge in 4.5. Selective refresh also appears on the proposed Customizer roadmap.
Partial preview refreshing was first explored when Customizer widgetWidgetA WordPress Widget is a small block that performs a specific function. You can add these widgets in sidebars also known as widget-ready areas on your web page. WordPress widgets were originally created to provide a simple and easy-to-use way of giving design and structure control of the WordPress theme to the user. management was being developed for the 3.9 release. It was added to the Widget Customizer pluginPluginA plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party. and described in a Make Core post. But it was decided to remove the feature in favor of having a better generalized framework for partial refreshes in a future release (which is now). In 4.3, nav menus were added to the Customizer and with this the first core implementation of selective refresh, as described in Fast previewing changes to Menus in the Customizer. (For more background, see Implementing Selective Refresh in the Customizer.)
With the shipped example of selective refresh of nav menus in the Customizer, and an initial implementation of selective refresh for widgets, work progressed to generalize a selective framework that would support the complicated examples of nav menus and widgets, but also to support simpler use cases such as letting the server render the updated site title so that wptexturize and other filters can apply. The generalized framework has been implemented in the Customize Partial Refreshfeature pluginFeature PluginA plugin that was created with the intention of eventually being proposed for inclusion in WordPress Core. See Features as Plugins, which also re-implements selective refresh of nav menus and introduces selective refresh of sidebars and widgets.
To see a simple example of selective refresh, see the Site Title Smilies plugin showing wptexturize and emoji applying to site title updates in the preview:
Note in this example that the standard postMessage updating of the site title in the headerHeaderThe header of your site is typically the first thing people will experience. The masthead or header art located across the top of your page is part of the look and feel of your website. It can influence a visitor’s opinion about your content and you/ your organization’s brand. It may also look different on different screen sizes. is still in place and so the change appears immediately. It gets followed, however, by the content being rendered by the partial on the server. This allows for JS to apply a quick low-fidelity preview for a setting change until the server can respond with the high-fidelity preview.
Selective Refresh Architecture
This plugin introduces a selective refresh framework which centers around the concept of the partial. A partial is conceptually very similar to a Customizer control. Both controls and partials are associated with one or more settings. Whereas a control appears in the pane, the partial lives in the preview. The fields in a control update automatically to reflect the values of its associated settings, and a partial refreshes in the preview when one of its settings is changed. The name “partial” is derived from get_template_part(), which is a natural function to use in a partial’s render_callback.
In addition to a partial being associated with one or more settings, a partial is also registered with a jQuery selector which identifies the partial’s locations or “placements” on the page, where the rendered content appears. For example, a partial can be registered for the site title to update the header as well as the document title via:
When a setting (like blogname here) is modified, each registered partial is asked on the client whether it isRelatedSetting(). If that method for a partial returns true, then the partial’s refresh() method is invoked and a request is queued up to render the partial via the requestPartial() function. Calls to this function are debounced and multiple simultaneous partials being changed will be batched together in a single Ajax request to the server.
When the server receives a request to render partials, it will receive the list of partials as well as all of the modified settings in the Customizer. Partials need not be all registered up front: as settings support the customize_dynamic_setting_args and customize_dynamic_setting_class filters, so too partials support the customize_dynamic_partial_args and customize_dynamic_partial_class filters. These filters allow partials to be added on demand to support the partials being requested to render.
If there is no registered partial for the request, or if the partial’s render_callback returns false, then false will be returned in the response as the content for that partial, and the default fallback() behavior in the client-side Partial object is to requestFullRefresh(). On the other hand, if the request recognizes the partial and the render_callback returns content, then this content is passed along to the Partial instance in the client and its renderContent() method then follows through to update the document with the new content.
As noted previously, the location in the document where a partial renders its update is called a placement. A selector may match any number of elements, and so too a partial may update multiple placements. A partial’s placements in the document may each have different sets of context data associated with them. This context data is included in the partials request and is passed along to the render_callback so that the content can vary as needed, for example a widget appearing in two different sidebars would have different sidebar_id context data, which would then determine the before_widget and after_widget args used.
Partial placements may also be nested inside other placements. For example, a Custom Menu widget is rendered as a placement which then contains another placement for a nav menu. The nav menu placement is updated independently from the parent widget placement. This being said (and this is advanced usage), a selector does not need to be supplied when registering a partial: alternatively to a top-down selector, the placement for a partial can be declared from the bottom-up by adding a data-customize-partial-id attribute to any container element. Whenever a partial is re-rendered, any nested partials will be automatically recognized. (As noted above, each placement can have a different associated context, and this is indicated by JSON object in a data-customize-partial-placement-context HTML attribute.)
Aside: The architecture of the Infinity Scroll module in Jetpack mirrors Selective Refresh framework in several ways.
Linking Partials to Controls
Since each partial is associated with at least one setting, shift-clicking on the placement for a partial will attempt to focus on the related control in the pane. This was already implemented for widgets since 3.9 and recently for nav menu items as well, but now the functionality is available to partials generally.
Selective Refresh of Widgets
Selective refresh for nav menus was enabled by default in 4.3. While some themes needed to add theme support for any dynamic aspects (such as the expanding submenus in Twenty Fifteen), generally nav menus seem to be fairly static and can be replaced in the document without needing any JS logic to be re-applied. Widgets, on the other hand, have much more variation in what they can display, since they can in fact display anything. For any widget that uses JavaScript to initialize some dynamic elements, such as a map or gallery slideshow, simply replacing the widget’s content with new content from the server will not work since the dynamic elements will not be re-initialized. Additionally, the sidebars (widget areas) in which the widgets are displayed may also have dynamic aspects associated with them, such as the Twenty Thirteen sidebar which displays widgets in a grid using Masonry. For this theme, whenever a widget is changed/added/removed/reordered, the sidebar needs to be reflowed.
In order to allow themes to reflow sidebars and widgets to reinitialize their contents after a refresh, the selective refresh framework introduces widget-updated and sidebar-updated events. Additionally, since re-ordering widgets in a sidebar is instant by just re-ordering the elements in the DOM, some widgets with dynamically-generated iframes (such as a Twitter widget) may need to also be rebuilt, and for this reason there is a partial-content-moved event.
For the above reasons, I believe it will be much more common for widgets (and sidebars) to need special support for selective refresh, and so I think that at least for 4.5 the selective refresh should be opt-in for widgets (and perhaps in themes for sidebars). See theme support for Twenty Thirteen and plugin support for a few widgets in Jetpack (which won’t be part of the merge). At last week’s Core dev meeting, it was suggested that we add the opt-in for widget selective refresh at RC.
What follows is a list of aspects of the API that should be more commonly used. For full documentation, see the inline docs in the plugin source.
PHP
I suggest that Selective Refresh be added as a new Customizer component to be accessed via $wp_customize->selective_refresh which is where the methods for partials(), add_partial(), get_partial(), remove_partial(), and others would be accessed.
Events (triggered on wp.customize.selectiveRefresh):
render-partials-response
partial-content-rendered
partial-placement-moved
widget-updated
sidebar-updated
The Future
If we can eliminate full-page refreshes from being the norm for the Customizer, we can start to introduce controls inline with the preview. If the entire preview does not reload, then the inline controls won’t get destroyed by the refresh with each change. For example, consider a widget control floating immediately next to the widget in the sidebarSidebarA sidebar in WordPress is referred to a widget-ready area used by WordPress themes to display information that is not a part of the main content. It is not always a vertical column on the side. It can be a horizontal rectangle below or above the content area, footer, header, or any where in the theme. it is editing. With selective refresh, it will then also be possible to eliminate the Customizer altogether. The Customizer could be available to anyone who is logged in, with the controls being bootstrapped on demand when a user wants to edit a given element. There would be no need to navigate way from a page on the frontend to enter a unique Customizer state: the Customizer would come to the user. Any controls not relevant to being inline could remain in the Customizer pane, but it could slide in only as needed instead of appearing by default. That is to say, selective refresh makes the Customizer a much better framework for implementing frontend editing.
Feedback
There is just over a week until the first betaBetaA pre-release of software that is given out to a large group of users to trial under real conditions. Beta versions have gone through alpha testing in-house and are generally fairly close in look, feel and function to the final product; however, design changes often occur as part of the process. for 4.5. I’d like to get any final feedback on the feature as soon as possible before committing it to trunktrunkA directory in Subversion containing the latest development code in preparation for the next major release cycle. If you are running "trunk", then you are on the latest revision.. The plugin is on GitHub and the plugin directory. Feedback should be left on #27355. Note that the plugin depends on 4.5-alpha-35776 to run.
Now an update for the hottest most buzz-worthy JavaScriptJavaScriptJavaScript or JS is an object-oriented computer programming language commonly used to create interactive effects within web browsers. WordPress makes extensive use of JS for a better user experience. While PHP is executed on the server, JS executes within a user’s browser.
https://www.javascript.com-driven single page application (SPA) in WordPress: Calypso the CustomizerCustomizerTool built into WordPress core that hooks into most modern themes. You can use it to preview and modify many of your site’s appearance settings.. Earlier in the release cycle there was a proposed roadmap for the Customizer and I wanted to share an update for what improvements have made it into the 4.4 release. I won’t include everything, but I’ll highlight some items that you may notice or want to make note of.
Performance
As noted on the roadmap, the focus for the Customizer in 4.4 has been to improve performance, and there are some drastic improvements in this release. Note that selective refresh (#27355, neé partial refresh) did not make it in, however the feature pluginFeature PluginA plugin that was created with the intention of eventually being proposed for inclusion in WordPress Core. See Features as Plugins now has a pull request for review.
Multidimensional Customizer settings (options & theme mods) are not scalable (#32103)
In 4.3 the time to load/refresh the Customizer preview increases exponentially as the number of settings/controls grows. If you have 200 settings it can take 15 seconds for the preview to update. If you have 300 settings, it can take 36 seconds to load/refresh the Customizer preview. And the time to reload the preview continues to grow exponentially as the number increases:
With the fixes in place for 4.4, the time to refresh the preview grows linearly very slowly (basically flatlined) as opposed to exponentially. I would share a graph, but it would be a very boring flat horizontal line.
See also aggregated multidimensional settings below.
Reduce Customizer peak memory usage by JSONJSONJSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML.-encoding settings and controls separately (#33898)
In addition to the slow preview load/refresh time, when there are a lot of Customizer settings/controls registered, the process for exporting the data from PHPPHPThe web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher to JavaScript used a lot of server memory when it serializes the JSON data in 4.3. In 4.4, each setting and control now gets serialized individually in a loopLoopThe Loop is PHP code used by WordPress to display posts. Using The Loop, WordPress processes each post to be displayed on the current page, and formats it according to how it matches specified criteria within The Loop tags. Any HTML or PHP code in the Loop will be processed on each post. https://codex.wordpress.org/The_Loop to avoid the memory spike, and this helps avoid any white screen of death due to the allowed memory size being exhausted in PHP.
Defer embedding Customizer widgetWidgetA WordPress Widget is a small block that performs a specific function. You can add these widgets in sidebars also known as widget-ready areas on your web page. WordPress widgets were originally created to provide a simple and easy-to-use way of giving design and structure control of the WordPress theme to the user. controls to improve DOM performance (#33901)
The previous performance improvements were for the server and reduced the amount of time it takes to get a response (TTFB). Nevertheless, for sites that have a lot of widgets, the Customizer would still load very slowly, not due to WordPress being slow on the server, but due to the JavaScript running in the browser. In 4.3 given 100 widgets (with a lot of inputs), the Customizer could take 40 seconds to finish building the page due to all of the widget controls being embedded into the DOM. So in 4.4 we defer the embedding of widget controls until the contained widget area section is expanded, that is until the widget control is actually shown to the user. This results in the Customizer loading over 10× faster: what did take 40 seconds now takes 3 seconds in WordPress 4.4.
Widgets section in customize late to show up (#33052)
The widgets panel now will now always be shown even if there are no widget areas currently displayed in the preview. This ensures that the widgets panel doesn’t slide down after the preview finishes loading. This is another browser-based improvement that doesn’t actually improve actual performance but it does improve perceived performance, or at least the user experience.
Aggregated Multidimensional Settings
The problem with the scalability of multidimensional settings for options or theme mods (#32103) is that the number of filters added to preview changes grows exponentially (see above). The fix for this is to ensure that only one filterFilterFilters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. gets added for a multidimensional settings that share a common ID base. The entire root value for the option or theme mod gets stored in a variable, and any previewed setting’s value gets applied to that variable once, and this root value then gets returned by the filter. This construct is referred to in the source as a “aggregated multidimensional setting”. Note that this has only been implemented for options and theme mods: custom multidimensional setting types that subclass WP_Customize_Setting should also be able to make use of the functionality, although this has not been specifically tested.
Two new actions have been introduced:
customize_post_value_set
customize_post_value_set_{$setting_id}
These are triggered whenever WP_Customize_Manager::set_post_value() is called, and they allow for WP_Customize_Setting::preview() to update the value being previewed. You can now, for instance, call preview() on a setting up-front and then set the post value later, and the new value will be applied for previewing as expected. This can be called a “deferred preview” or “just in time” previewing.
Facilitate plugins to override Customizer features (#33552)
Sometimes widgets or menus are not applicable for a given site. TicketticketCreated for both bug reports and feature development on the bug tracker. #33552 introduces a new filter customize_loaded_components which allows nav menus or widgets to be skipped from initialization. For example, to prevent the nav menu functionality from being loaded the following pluginPluginA plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party. code can be used:
JSJSJavaScript, a web scripting language typically executed in the browser. Often used for advanced user interfaces and behaviors.Inline Docsinline docs(phpdoc, docblock, xref)
The Customizer is a JavaScript-heavy application, and in #33503#33639 the inline docs for JS have been improved to help developers understand how it works. See [33709][33911][33841].
When settings are registered for options that don’t already exist in the DB, an update for these settings in the Customizer would result in update_option() called with the default $autoload parameter and thus them being saved as autoloaded. In 4.4 you can now register option settings to explicitly not get added with autoloading, for example:
#32637 Customizer should default to returning to the front page, not the themes page
#32812 Customizer Menus: Escaping inconsistencies — You can now use limited markup in nav menu item titles in the Customizer.
#33319 Customizer headerHeaderThe header of your site is typically the first thing people will experience. The masthead or header art located across the top of your page is part of the look and feel of your website. It can influence a visitor’s opinion about your content and you/ your organization’s brand. It may also look different on different screen sizes. image crop uses static URLURLA specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org when refreshing UIUIUser interface after crop.
#33665 Menu Customizer: Implement indicators for invalidinvalidA resolution on the bug tracker (and generally common in software development, sometimes also notabug) that indicates the ticket is not a bug, is a support request, or is generally invalid. menu items
#34432 Customizer subclasses can be broken out and remain BC — All Customizer PHP classes now reside in a separate files.
#34607 Customizer: Wrapped labels should align to start of label, not checkbox or radio button
Planning for the future is a necessary and important part of the WordPress development process. As we consider the future of WordPress – both as a whole and individual features – we publish proposed roadmaps to encourage greater discussion and give insight into the coreCoreCore is the set of software required to run WordPress. The Core Development Team builds WordPress. team’s thought process.
The process of creating a roadmap is just as important as the vision behind it and the final roadmap itself. This process gives the entire community an opportunity to research and document history, define what specific items can be accomplished to bring us closer to the vision, and outlines how those tasks fit together within a possible timeframe.
What follows is a potential roadmap for the Customize component. If you’re interested in the future of live preview in WordPress, now is the perfect time to get involved and leave your feedback.
A couple of months ago, the WordPress lead developers met with the maintainers of the Customize component to discuss the future of live preview in WordPress. The goal of the chat was to come up with a potential roadmap for both the component and for how live preview can improve the user experience of WordPress for all users.
After a lot of discussion, the group decided to target the following goals over the next two years:
Considerably improve performance.
Continue iterating on current live preview features to ensure they are solid and as easy-to-use as possible, including theme browsing and installation, menus, and widgets.
Experiment with new and different user interfaces. If we were creating live preview today, what would it look like? In what ways can we ease the feeling that you’re looking through a “porthole”?
Removal of the ambiguous mode. Currently, the CustomizerCustomizerTool built into WordPress core that hooks into most modern themes. You can use it to preview and modify many of your site’s appearance settings. is contained in a sidebarSidebarA sidebar in WordPress is referred to a widget-ready area used by WordPress themes to display information that is not a part of the main content. It is not always a vertical column on the side. It can be a horizontal rectangle below or above the content area, footer, header, or any where in the theme. without the adminadmin(and super admin) toolbar, but ideally there is the admin and the theme, and no in-between. One direction this may go is enabling “Customize” on the front end to immediately load the Customizer controls.
Experiment with a guided new user experience (NUX). Live preview lends itself to site setup. How can we improve the live preview experience and combine it with the NUX? Consider a “setup wizard” use case and ensure the flow has no dead ends, i.e. users can customize everything in one.
Those overall goals for live preview in WordPress can be rewritten into some specific features that are in development or planned for the future of the Customize component. These include:
Transactions. This re-architecture of some of the Customizer internals improves compatibility with themes by loading the preview using a natural URLURLA specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org, and allows Ajax requests or even REST APIREST APIThe REST API is an acronym for the RESTful Application Program Interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data. It is how the front end of an application (think “phone app” or “website”) can communicate with the data store (think “database” or “file system”)
https://developer.wordpress.org/rest-api/ requests to be previewed. It also allows the preview to be viewed independently of the Customizer, so changes can be shared for others to review. See #30937.
Selective refresh. Only a piece of the page will need to be refreshed when this backend feature is implemented. (Formerly known as “Partial Refresh”.) Currently, this is available for menus in the Customizer. This eliminates duplication of display between PHPPHPThe web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher and JSJSJavaScript, a web scripting language typically executed in the browser. Often used for advanced user interfaces and behaviors., keeping it DRY. See #27355.
Concurrency. Allows for “locking” settings using the Heartbeat APIAPIAn API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways., improving the overall user experience by preventing users from overwriting each other’s changes. See #31436.
RevisionsRevisionsThe WordPress revisions system stores a record of each saved draft or published update. The revision system allows you to see what changes were made in each revision by dragging a slider (or using the Next/Previous buttons). The display indicates what has changed in each revision.. Enables pluginPluginA plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party. developers to add features like draft, roll back, and scheduled changes (e.g. “change my background on January 1”). This builds upon transactions, as the setting changes are staged in a transaction, and this facilitates settings to be revisioned and for settings to be scheduled. See #28721, #31089.
Theme installation. Iterates on and completes the theme browsing experience.
Responsive preview. Iterates on the concept of live preview by giving users a better idea of what their site will look like on other devices. See #31195.
Bootstrapped Customizer. Lazy-load the Customizer into the current frontend view without having to leave the page. With selective refresh implemented, inline controls and frontend bootstrapping would be possible since full-page refreshes would no longer be required.
Improvements for both touch and small devices.
Beyond those features, the group identified some specific changes that should be prioritized, in conjunction with the features planned:
The sliding animation between panels should feel more like “moving panels” (see: iOSiOSThe operating system used on iPhones and iPads.).
Keyboard navigation should be consistent and clear.
Identify “dead ends” in the interface and remove them, when possible. For example, prior to menus in the Customizer, it was not possible to customize that aspect of your site’s design with the Customizer.
The concepts surrounding live preview and the Customizer have been in development for a long time. Many of the concepts from Elastic Theme and the Visual CSS Editor have been incorporated over time. Over the next few years, experimentation with these concepts will likely take place in feature plugins. For example, this team may experiment with inline content editing, where it makes sense in the context of customizing a site. Another path for exploration is simple theme customization – e.g. change the headerHeaderThe header of your site is typically the first thing people will experience. The masthead or header art located across the top of your page is part of the look and feel of your website. It can influence a visitor’s opinion about your content and you/ your organization’s brand. It may also look different on different screen sizes. font, change the sidebar color, or change the width of the sidebar.
As with all components and new features, we shouldn’t be afraid to experiment and fail and should continually push for new experiments and ideas, especially in the context of feature plugins. Further, some of the above experiments may not make it into core, but are meant as a general direction that live preview should take in WordPress.
Taking these features together, below is a sequence outlining a possible roadmap for live preview and the Customize component in general, along with estimated targets. Please note that this is a proposed roadmap and is entirely dependent on contributor involvement. Additionally, many of these things will take place in a feature pluginFeature PluginA plugin that was created with the intention of eventually being proposed for inclusion in WordPress Core. See Features as Plugins prior to core inclusion.
Concurrency. Revisions. Theme Install. Beginning of NUX wizard. (Target: 4.6)
Focus on touch screen / small device improvements. (Target: 4.7)
Developer API improvements based on feedback from plugin developers. (Target: 4.8)
Improved UIUIUser interface after experiments in 2016. NUX “wizard mode.” (Target: 4.9)
Live preview is one of the most critical features in WordPress as we continually combat “save and surprise.” The Customizer in its current form provides an improved user experience to WordPress users when customizing their site’s design. Each feature mentioned above is a continuation of the live preview concept, building and improving upon the Customizer.
Everything above is just a proposal and we need your feedback to ensure it is the right direction. If you’re interested in any of the above, comment here with your feedback, or join the team in #core-customize.
You must be logged in to post a comment.