There are many user-facing Customizer Tool 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. improvements in 4.9, including: drafting/scheduling of changesets, autosave revisions The 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., changeset post locking, frontend public previews, a new experience for browsing and installing themes, updated nav menu creation UX User experience, and the code editing improvements for the Custom HTML HyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers. widget A 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. and Additional CSS Cascading Style Sheets.. But in addition to all of these, there are also many improvements for developers which will make extending the Customizer much more pleasant.
Something important to remember about the Customizer is that it is a single page application that is powered by JavaScript JavaScript 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/.. Many developers may only interact with the PHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher API An 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. for registering controls, settings, sections, panels, and partials. But controls, sections, and panels do not need to be registered in PHP at all. The PHP API for registration is essentially a wrapper for the underlying JS JavaScript, a web scripting language typically executed in the browser. Often used for advanced user interfaces and behaviors. API. When you load the Customizer all of the params for the PHP-registered constructs are exported to the client for the JavaScript API to instantiate and initially add to the UI User interface, but this JS API can dynamically instantiate additional constructs at any time thereafter in a Customizer session. This is how new widgets, nav menus, and nav menu items are added without requiring the entire Customizer to reload. You can also avoid statically registering settings and partials in PHP by instead adding filters to dynamically recognize settings and partials, allowing them to be registered on demand. All of this allows the Customizer application to scale out to be able to customize and preview an unlimited number of things on a site (e.g. any post or page with their postmeta in the Customize Posts feature plugin A plugin that was created with the intention of eventually being proposed for inclusion in WordPress Core. See Features as Plugins.). The point here is that in order for the Customizer to scale, the JavaScript API must be used directly. So this is why the Customizer JS API improvements in 4.9 are important as they fix many longstanding annoyances and shortcomings with the JS API.
This dev note Each important change in WordPress Core is documented in a developers note, (usually called dev note). Good dev notes generally include a description of the change, the decision that led to this change, and a description of how developers are supposed to work with that change. Dev notes are published on Make/Core blog during the beta phase of WordPress release cycle. Publishing dev notes is particularly important when plugin/theme authors and WordPress developers need to be aware of those changes.In general, all dev notes are compiled into a Field Guide at the beginning of the release candidate phase. contains the following sections:
Elimination of Repeated ID when Adding Constructs
Previously in the Customizer when you wanted to add a new construct dynamically you would need to pass the ID into the constructor itself and then pass the ID in when adding it to a collection as well. This was unfortunate as it required keeping multiple references to the same ID in sync, for example:
/* Before WordPress 4.9 */
wp.customize.control.add(
'foo',
new wp.customize.Control( 'foo', { /* … */ } )
);
Or to store the identifier in a variable to re-use, as the two should never differ:
/* Before WordPress 4.9 */
var code = 'too_short';
wp.customize.control( 'blogname' ).notifications.add(
code,
new wp.customize.Notification( code, {
message: 'Site title too short.'
} )
);
In 4.9 this is no longer required, as the ID will be automatically read from the object being passed to the add
method. So now you can simply do:
/* Since WordPress 4.9 */
wp.customize.control.add(
new wp.customize.Control( 'foo', { /* … */ } )
);
And:
/* Since WordPress 4.9 */
wp.customize.control( 'blogname' ).notifications.add(
new wp.customize.Notification( 'too_short', {
message: 'Site title too short.'
} )
);
Naturally the change here to the add
method is backwards-compatible, and existing code that passes an ID as the first argument will still continue to work.
Flattened Constructor Parameters
When creating a setting in JavaScript, the supplied options argument is simply a 1-level deep object:
var setting = new wp.customize.Setting( 'foo', value, {
transport: 'postMessage',
/* ... */
} );
However, when constructing something else—controls, sections, panels, or partials—the supplied options object required the properties to be wrapped in an intermediary params
property like this:
/* Before WordPress 4.9 */
var control = new wp.customize.Control( 'bar', {
params: {
section: 'title_tagline'
/* ... */
}
} );
This was annoying and the params
property has been unwrapped to allow you to pass the props in the root options
object:
/* Since WordPress 4.9 */
var control = new wp.customize.Control( 'bar', {
section: 'title_tagline'
/* ... */
} );
Backwards compatibility is maintained, so existing code that passes props via options.params
will continue to be read from first, and then fall back to the new unwrapped options
for props. The options.params
property is soft-deprecated in 4.9 (using it will raise no warning) but it may be hard-deprecated in the future.
Default Parameters
Another longstanding annoyance with adding constructs in the Customizer is that there was a lack of parameter defaults. When creating a Color control, for example, the following is the minimum required prior to 4.9:
/* Before WordPress 4.9 */
var control = new wp.customize.ColorControl( 'favorite_color', {
params: {
type: 'color',
content: '<li class="customize-control customize-control-color"></li>',
priority: 10,
active: true,
section: 'colors',
label: 'Favorite Color',
settings: { 'default': 'favorite_color' },
}
} );
wp.customize.control.add( 'favorite_color', control );
This is a lot of code, considering that in PHP all that a user would have to do is:
$control = new WP_Customize_Color_Control( $wp_customize, 'favorite_color', array(
'section' => 'colors',
'label' =>'Favorite Color',
'settings' => array( 'default' => 'favorite_color' ),
) );
$wp_customize->add_control( $control );
The type
, content
, priority
, and active
properties have defaults in PHP and so too they should have defaults in JS. And now they do. Creating a Color control in JS, combined with the flattening of params
above, is now just:
/* Since WordPress 4.9 */
var control = new wp.customize.ColorControl( 'favorite_color', {
section: 'colors',
label: 'Favorite Color',
settings: { 'default': 'favorite_color' },
} );
wp.customize.control.add( control );
So creating controls in JS is now pretty much identical to creating them in PHP, aside from the differences in syntax.
Beyond controls, defaults are also available for settings, sections, panels, and partials. For settings, defaults are provided for transport
(refresh) and previewer
(which should never vary):
/* Before WordPress 4.9 */
var setting = new wp.customize.Setting( 'favorite_color', '#000000', {
transport: 'refresh',
previewer: wp.customize.previewer
} );
wp.customize.add( 'favorite_color', setting );
/* Since WordPress 4.9 */
var setting = new wp.customize.Setting( 'favorite_color', '#000000' );
wp.customize.add( setting );
On all constructs (controls, settings, panels, sections, partials) there is a defaults
property on their function prototypes which contains the default params. This can be leveraged to add new defaults to subclasses, in addition to any extended methods. For example:
var ColorSetting = wp.customize.Setting.extend({
defaults: _.extend(
{},
wp.customize.Setting.prototype.defaults,
{
transport: 'postMessage'
}
),
validate: function( value ) {
var setting = this, validatedValue;
validatedValue = wp.customize.Setting.prototype.validate.call( setting, value );
if ( null === validatedValue ) {
return validatedValue;
}
if ( /^#\d{6}$/.test( validatedValue ) ) {
setting.notifications.remove( 'invalid_color' );
} else {
setting.notifications.add( new wp.customize.Notification( 'invalid_color', {
message: 'Bad color format'
} ) );
}
return validatedValue;
}
});
When this ColorSetting
is instantiated, the transport
of postMessage
will not need to be explicitly provided each time.
Passing Settings when Instantiating Controls
When instantiating controls in JS prior to 4.9, you had to pass settings
as an object mapping a setting key to the setting ID. For example, to add a control for manipulating the site title, you would do:
var blognameControl = new wp.customize.Control( 'blogname2', {
/* ... */
settings: {
'default': 'blogname'
}
} );
If a control is manipulating multiple settings, then the keys for the settings
object will get additional values:
var bgPositionControl = new wp.customize.BackgroundPositionControl( 'mobile_bg_position', {
/* ... */
settings: {
x: 'mobile_background_position_x',
y: 'mobile_background_position_y'
}
} );
The settings
object here is really just indicating which settings the control depends on, so that it can defer initialization until all of the settings are created. Prior to 4.9, the keys served no purpose other than to give a symbolic reference to a given setting. When a default
setting is used, then it also can be accessed directly via a setting
shortcut. For example:
var xValue = bgPositionControl.settings.x.get();
var title = blognameControl.settings['default'].get();
var title2 = blognameControl.setting.get();
In 4.9, the way settings
are passed to controls is getting revamped. Additionally, the symbolic keys supplied for the settings are now more useful in that they can be used to create input element links.
First of all, if you have a control that just takes one setting, you can now just pass a single setting
:
var control = new wp.customize.Control( 'blogname2', {
/* ... */
setting: 'blogname'
} );
Additionally, just as with partials you can pass settings
as an array (#36167), where the first item then becomes the default
.
Furthermore, instead of passing a setting’s string ID you can now pass an existing Setting
object, promoting better encapsulation (#37964):
var control = new wp.customize.Control( 'blogname2', {
/* ... */
setting: wp.customize( 'blogname' )
} );
Where this gets particularly important is that you can also pass Value
instances as settings instead of registering a Setting
, which would then attempt to get saved in the changeset (and fail as being unrecognized, without static of dynamic server-side registration). In other words, a control (view) can be supplied a model which is either a Setting
or a Value
(and the former is a subclass of the latter). This is how the controls for the changeset status and date are constructed. For example, to create a control which manages the sidebar A 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. width, one could do (which also shows how to add a control to the new Publish Settings section):
wp.customize.control.add( new wp.customize.Control( 'pane_width', {
type: 'number',
section: 'publish_settings',
setting: new wp.customize.Value( 300 ),
label: 'Pane Width',
priority: 110,
input_attrs: {
min: 150,
max: 1000
}
} ) );
A plugin A 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 could then listen for changes to that control’s setting
model to then perhaps store the value in localStorage
to persist the user preference for how wide they want their sidebar to be. Being able to construct controls with Value
models is a next iteration beyond setting-less controls introduced in 4.5.
Prior to 4.9, in spite of having these symbolic references to a control’s settings the control’s content would require the actual setting ID to be used in any input element links (the bidirectional data binding between a control’s setting and input). For example, the site title control has a default
setting pointing to blogname
, but in spite of this, the content for the control would contain:
<input type="text" data-customize-setting-link="blogname">
The fact that data-customize-setting-link
required an actual setting ID to be used as its value made it difficult to create reusable control templates. This now has been improved in 4.9 by allowing the setting keys to be used in data-customize-setting-key-link
attributes:
<input type="text" data-customize-setting-key-link="default">
The WP_Customize_Control::get_link()
PHP method has been updated to output a data-customize-setting-key-link
attribute with the supplied setting key as its value when the associated setting does not exist. Otherwise, it maintains its prior behavior of using the setting ID as the value for a data-customize-setting-link
attribute. The JS logic responsible for linking inputs with settings via elements is now contained in a new linkElements
method on Control
.
Control Templates
Refer back to the “Pane Width” example above where a type of number
was supplied when constructing a base wp.customize.Control
class. This would not work prior to 4.9 because there were no content templates defined for base control types. This is no longer the case with the resolution of #30738. If you construct a control and supply a type
param that corresponds to an HTML5 input type, then the default control template will be used to render the control. Note that for color inputs, one should use the dedicated ColorControl
.
A control’s template is normally derived by its type
; for instance, a Background Position control has a type of background_position
and then has a wp.template
ID of customize-control-background_position-content
. The template is normally output by a control’s WP_Customize_Control::content_template()
template after the control has been registered via WP_Customize_Manager::register_control_type()
. In 4.9 however, this can all be bypassed as controls now understand a templateId
param.
An example of supplying an ad hoc templateId
when constructing a control can be seen in the changeset status control, where it overrides the template used for this one radio control instance:
var statusControl = new api.Control( 'changeset_status', {
priority: 10,
type: 'radio',
section: 'publish_settings',
setting: api.state( 'selectedChangesetStatus' ),
templateId: 'customize-selected-changeset-status-control',
label: api.l10n.action,
choices: api.settings.changeset.statusChoices
} );
api.control.add( statusControl );
Alternatively, if you have a custom control that you always want to have a specific template (as when calling WP_Customize_Manager::register_control_type()
in PHP), you can now do this entirely in JS by adding templateId
to the control subclass’s defaults
, as can be seen in the PreviewLinkControl
:
var PreviewLinkControl = api.Control.extend({
defaults: _.extend(
{},
api.Control.prototype.defaults,
{
templateId: 'customize-preview-link-control'
}
)
/* ... */
});
For some more examples, see answer on the WordPress Development Stack Exchange.
Speaking of WP_Customize_Manager::register_control_type()
, the types for panels, sections, and controls now are all registered before the customize_register
action is triggered. This means that if you have a plugin that unregisters all customize_register
actions in order to create a “blank slate” plugin-specific Customizer, you no longer have to re-register these types to be able to use them.
Date/Time Control
In support of the 4.9 feature for scheduling changesets for publishing (#28721), there is a new control for representing a date/time. The control shows fields for editing the date with optional fields also for editing the time. The control syncs to a setting a date in the Y-m-d H:i:s
format. The time in the control can either be presented in 12-hour format or 24-hour format. Additionally, the control can specify that it requires a future date. The PHP class is WP_Customize_Date_Time_Control
and the JS class is wp.customize.DateTimeControl
. Here is how to create a few of the controls in JS with screenshots for how they appear:
wp.customize.control.add( new wp.customize.DateTimeControl( 'birthdate', {
label: 'Birthdate',
description: "Someone was born on this day.",
section: sectionId,
includeTime: false,
setting: new wp.customize.Value( '2000-01-02' )
} ) );