The 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. is the first true JS-driven feature in core. That’s awesome, especially coming out of WCSF where 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/. has been highlighted so prominently between Backbone.js, the WP REST API, Node.js, and socket.io. The Customizer has a great architecture with models for settings, controls, watchable-values, collections, events, and asynchronous callbacks. Nevertheless, the JavaScript 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. in the Customizer is incomplete.
Existing Challenges
When widgets were added to the Customizer in 3.9, adding 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. controls to 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. sections required direct DOM manipulation. For controls there is at least a Control model to manage state For sections and panels, however, there are no JS JavaScript, a web scripting language typically executed in the browser. Often used for advanced user interfaces and behaviors. models at all, and so adding them dynamically is even more of a challenge. And this is the exact challenge that Nick Halsey’s Menu Customizer 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 currently has to struggle through.
When Customizer panels were added in 4.0 to group all widget area sections into a “Widgets” panel, a bug was introduced whereby shift-clicking a widget in the preview no longer revealed the widget control in the Customizer pane because the sections were inside of the collapsed Widgets panel: there were no models to represent the state for whether or not a panel or section were currently expanded. Without models, a fix of this would require more messy DOM traversal to check if parent accordion sections were expanded or not. Storing data in the DOM is bad.
In 4.0 the concept of contextual controls were added to the Customizer. This allowed controls to be registered with an active_callback
, such as is_front_page
, which the preview would execute and pass back up to the Customizer pane to then show/hide the control based on which URL A specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org was being previewed. This worked well, except when all controls in a section were inactive: then the result was a Customizer section without any visible controls. Instead, the expected behavior would be for the section to automatically collapse as well when all controls inside become inactive. Again, this problem stems from the fact that there is no JS model to represent a section and to list out the controls associated with it.
For the past three weeks I’ve been focused on fleshing out the Customizer API to address these challenges, and to facilitate doing new dynamic things in the Customizer. The parent ticket Created for both bug reports and feature development on the bug tracker. for this is #28709: Improve/introduce Customizer JS models for Controls, Sections, and Panels.
Models for Panels and Sections
As noted above, there is a wp.customize.Control
model, and then there is a wp.customize.control
collection (yes, it is singular) to store all control instances. So to follow the pattern established by controls, in the patch there is a wp.customize.Panel
and wp.customize.Section
, along with wp.customize.panel
and wp.customize.section
collections (both singular again). So just as with controls, you can iterate over panels and sections via:
wp.customize.panel.each( function ( panel ) { /* ... */ } );
wp.customize.section.each( function ( section ) { /* ... */ } );
Relating Controls, Sections, and Panels together
When registering a new control in PHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 5.6.20 or higher, you pass in the parent section ID:
$wp_customize->add_control( 'blogname', array(
'label' => __( 'Site Title' ),
'section' => 'title_tagline',
) );
In the proposed JavaScript API, a control’s section can be obtained predictably:
id = wp.customize.control( 'blogname' ).section(); // => title_tagline
To get the section object from the ID, you just look up the section by the ID as normal: wp.customize.section( id )
.
You can move a control to another section using this section
state as well, here moving it to the Navigation section:
wp.customize.control( 'blogname' ).section( 'nav' );
Likewise, you can get a section’s panel ID in the same way:
id = wp.customize.section( 'sidebar-widgets-sidebar-1' ).panel(); // => widgets
You can go the other way as well, to get the children of panels and sections:
sections = wp.customize.panel( 'widgets' ).sections();
controls = wp.customize.section( 'title_tagline' ).controls();
You can use these to move all controls from one section to another:
_.each( wp.customize.section( 'title_tagline' ).controls(), function ( control ) {
control.section( 'nav' );
});
Contextual Panels and Sections
Also just as with controls, when you invoke $wp_customize->add_section()
you can pass an active_callback
param to indicate whether the section is relevant to the currently-previewed URL; the same goes for panels. A good example of a contextual section is only showing the “Static Front Page A WordPress website can have a dynamic blog-like front page, or a “static front page” which is used to show customized content. Typically this is the first page you see when you visit a site url, like wordpress.org for example.” section if the preview is currently on the front-page:
function contextual_static_front_page_section( $wp_customize ) {
$wp_customize->get_section( 'static_front_page' )->active_callback = 'is_front_page';
}
add_action( 'customize_register', 'contextual_static_front_page_section', 11 );
Nevertheless, this will not usually be needed because a section inherits its active state from its control children (and a panel inherits from its section children), via the new isContextuallyActive()
method. If all controls within a section become inactive, then the section will automatically become inactive.
As with controls, Panel
and Section
instances have an active
state (a wp.customize.Value
instance). When the active
state changes, the panel, section, and control instances invoke their respective onChangeActive
method, which by default slides the container element up and down, if false
and true
respectively. There are also activate()
and deactivate()
methods now for manipulating this active
state, for panels, sections, and controls:
wp.customize.section( 'nav' ).deactivate(); // slide up
wp.customize.section( 'nav' ).activate({ duration: 1000 }); // slide down slowly
wp.customize.section( 'colors' ).deactivate({ duration: 0 }); // hide immediately
wp.customize.section( 'nav' ).deactivate({ completeCallback: function () {
wp.customize.section( 'colors' ).activate(); // show after nav hides completely
} });
Note that manually changing the active
state would only stick unti