主题开发文档

自定义器 JavaScript API

💡 云策文档标注

概述

本文档介绍了 WordPress 4.1 中引入的自定义器 JavaScript API,涵盖其结构、核心模型和实用功能。API 主要位于 wp-admin/js/customize-controls.js 文件中,用于在自定义器控制面板和预览区域之间进行交互。

关键要点

  • 自定义器应用分为控制面板和预览区域,通过 postMessage API 通信。
  • JavaScript API 提供 wp.customize.Control、wp.customize.Section 和 wp.customize.Panel 等模型,以及对应的集合。
  • 支持动态操作控件、面板和部分,如移动控件、更改优先级、激活/停用状态和聚焦 UI 对象。
  • 可通过 autofocus 参数实现深层链接,直接跳转到自定义器中的特定面板、部分或控件。
  • 自定义控件、面板和部分可参考核心代码结构进行开发。

代码示例

// 更改预览 URL 示例
wp.customize(
	'page_for_posts',
	function( setting ) {
		setting.bind( function( pageId ) {
			pageId = parseInt( pageId, 10 );
			if ( pageId > 0 ) {
				api.previewer.previewUrl.set( api.settings.url.home + '?page_id=' + pageId );
			}
		});
	}
);

// 迭代控件示例
wp.customize.control.each( function ( control ) { /* ... */ } );

// 移动控件到其他部分示例
wp.customize.control( 'blogname' ).section( 'nav' );

// 激活/停用部分示例
wp.customize.section( 'nav' ).deactivate();
wp.customize.section( 'nav' ).activate({ duration: 1000 });

// 聚焦控件示例
wp.customize.control( 'page_on_front' ).focus();

// 更改优先级示例
wp.customize.panel( 'widgets' ).priority( 1 );

注意事项

  • 自定义器 JavaScript 分为控制面板(customize-controls.js)和预览(customize-preview.js)两个文件,建议遵循此命名约定。
  • 手动更改活动状态仅在预览刷新或加载新 URL 前有效,需注意其临时性。
  • 开发自定义对象时,可参考核心代码中的媒体控件示例,理解对象层次结构。

📄 原文内容

In WordPress 4.1, newly-expanded JavaScript APIs were introduced for all customizer objects. The entire JavaScript API is currently located in a single file, wp-admin/js/customize-controls.js, which contains models for all objects, core custom controls, and more.

Preview JS and Controls JS

The customizer app is currently split into two distinct areas: the customizer controls “pane” and the customize preview. The preview is currently in an iframe, meaning that all JS runs either in the controls pane or in the preview. The postMessage API is used to communicate between the preview and the controls.

Most themes only implement JavaScript in the customize preview, and use it to implement instant previewing of settings via postMessage. However, JS on the controls side can be used for many things, such as dynamically showing and hiding controls based on the values of other settings, changing the previewed URL, focusing parts of the preview, and more. Here’s an example from core of controls-side JS that interacts with the preview, in this case changing the previewed URL when the page for posts changes:

// Change the previewed URL to the selected page when changing the page_for_posts.
wp.customize(
	'page_for_posts',
	function( setting ) {
		setting.bind( function( pageId ) {
			pageId = parseInt( pageId, 10 );
			if ( pageId > 0 ) {
				api.previewer.previewUrl.set( api.settings.url.home + '?page_id=' + pageId );
			}
		});
	}
);

Similar logic can be used to activate UI objects based on the value of a setting. The Twenty Seventeen theme includes some useful examples for leveraging the customize JS API for improved user experience. Note that there is one JS file for the controls pane, named customize-controls.js and one file for the customize preview, named customize-preview.js. For clarity, all themes and plugins are recommended to follow this naming convention, even if customize JS is only provided in the controls or preview but not both.

The rest of this page is dedicated primarily to the controls-side JS API that was built-out in WordPress 4.1.

Models for Controls, Sections, and Panels

As in PHP, each Customizer object type has a corresponding object in JavaScript. There are wp.customize.Control, wp.customize.Panel, and wp.customize.Section models, as well as wp.customize.panel, wp.customize.section, and wp.customize.control collections (yes, they are singular) that store all control instances. You can iterate over panels, sections, and controls via:

wp.customize.panel.each( function ( panel ) { /* ... */ } );
wp.customize.section.each( function ( section ) { /* ... */ } );
wp.customize.control.each( function ( control ) { /* ... */ } );

Relating Controls, Sections, and Panels together

When registering a new control in PHP, you pass in the parent section ID:

<?php
$wp_customize->add_control(
	'blogname',
	array(
		'label'   => __( 'Site Title' ),
		'section' => 'title_tagline',
	)
);
?>

In the JavaScript API, a control’s section can be obtained predictably:

id = wp.customize.control( 'blogname' ).section(); // returns title_tagline by default

To get the section object from the ID, 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(); // returns widgets by default

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, Sections, and Controls

Control, 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. The primary purpose of these states is to show or hide the object without removing it entirely from the Customizer.

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 until the preview refreshes or loads another URL. The activate()/deactivate() methods are designed to follow the pattern of the new expanded state.

Focusing UI Objects

Building upon the expand()/collapse() methods for panels, sections, and controls, these models also support a focus() method which not only expands all of the necessary elements, but also scrolls the target container into view and puts the browser focus on the first focusable element in the container. For instance, to expand the “Static Front Page” section and focus on select dropdown for the “Front page”:

wp.customize.control( 'page_on_front' ).focus()

The focus functionality is used to implement autofocus: deep-linking to panels, sections, and controls inside of the customizer. Consider these URLs:

  • …/wp-admin/customize.php?autofocus[panel]=widgets
  • …/wp-admin/customize.php?autofocus[section]=colors
  • …/wp-admin/customize.php?autofocus[control]=blogname

This is used in WordPress core to add a link on the widgets admin page to link directly to the widgets panel within the customizer, as well as to connect visible edit shortcuts in the customize preview with the associated controls in the customize pane.

Priorities

When registering a panel, section, or control in PHP, you can supply a priority parameter. This value is stored in a wp.customize.Value instance for each respective Panel, Section, and Control instance. For example, you can obtain the priority for the widgets panel via:

priority = wp.customize.panel( 'widgets' ).priority(); // returns 110 by default

You can then dynamically change the priority and the Customizer UI will automatically re-arrange to reflect the new priorities:

wp.customize.panel( 'widgets' ).priority( 1 ); // move Widgets to the top

Custom Controls, Panels, and Sections

When working with custom Customizer objects in JS, it is usually easiest to examine the custom objects in WordPress core to understand the code structure. See wp-admin/js/customize-controls.js, particularly the wp.customize.Panel|Section|Control models. Note several examples in the core code, particularly in the media controls, which build on each others’ functionality though object hierarchy.