WordPress Widgets and Customizer JavaScript API

Summary: Learning about the WordPress custom Widgets and Customizer JavaScript API for better user experience.

Widgets

WordPress widgets allow users to add content and features to sidebars and other widget-ready areas on their website. By default, WordPress includes several built-in widgets such as Recent Posts, Categories, Search, etc. We can create custom widgets to enhance our site with unique functionalities tailored to our specific needs.

  • __construct(): Initialize the widget like naming the widget and setting description.
  • widget(): Outputs the front-end display of the widget.
  • form(): Outputs the form for the widget settings in the WordPress admin.
  • update(): Processes and saves the widget options when a user updates them.
class My_Custom_Widget extends WP_Widget {
    
    // Step 1: Constructor
    function __construct() {
        parent::__construct(
            'my_custom_widget', 
            __('My Custom Widget', 'text_domain'), 
            array('description' => __('A Custom Widget', 'text_domain')) 
        );
    }

    // Step 2: Front-End Display
    public function widget($args, $instance) {
        echo $args['before_widget'];
        if (!empty($instance['title'])) {
            echo $args['before_title'] . apply_filters('widget_title', $instance['title']) . $args['after_title'];
        }
        echo __('Hello, World!', 'text_domain');
        echo $args['after_widget'];
    }

    // Step 3: Back-End Form (for admin panel)
    public function form($instance) {
        $title = !empty($instance['title']) ? $instance['title'] : __('New title', 'text_domain');
        ?>
        <p>
            <label for="<?php echo esc_attr($this->get_field_id('title')); ?>"><?php _e('Title:'); ?></label>
            <input class="widefat" id="<?php echo esc_attr($this->get_field_id('title')); ?>" name="<?php echo esc_attr($this->get_field_name('title')); ?>" type="text" value="<?php echo esc_attr($title); ?>">
        </p>
        <?php
    }

    // Step 4: Save Widget Settings
    public function update($new_instance, $old_instance) {
        $instance = array();
        $instance['title'] = (!empty($new_instance['title'])) ? strip_tags($new_instance['title']) : '';
        return $instance;
    }
}

// Step 5: Register the Widget
function register_my_custom_widget() {
    register_widget('My_Custom_Widget');
}
add_action('widgets_init', 'register_my_custom_widget');

Customizer JavaScript API

Relating Controls, Sections, and Panels together

<?php
$wp_customize->add_control(
	'blogname',
	array(
		'label'   => __( 'Site Title' ),
		'section' => 'title_tagline',
	)
);
?>
id = wp.customize.control( 'blogname' ).section(); // returns title_tagline by default

wp.customize.control( 'blogname' ).section( 'nav' );
wp.customize.control( 'blogname' ).section( 'nav' );

sections = wp.customize.panel( 'widgets' ).sections();controls = wp.customize.section( 'title_tagline' ).controls();

// 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
} } );

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()

Priorities

When registering a panel, section, or control in PHP, we can supply a priority parameter. This value is stored in a wp.customize.Value instance for each respective PanelSection, and Control instance

priority = wp.customize.panel( 'widgets' ).priority(); // returns 110 by default
wp.customize.panel( 'widgets' ).priority( 1 ); // move Widgets to the top

Selective Refresh

Selective Refresh updates in the Customizer “preview” only refresh areas whose associate settings are changed. By only updating the elements that have changed, it’s much faster and less disruptive than a full-iframe refresh. 

The logic in pure-JavaScript postMessage updates is duplicated. The JavaScript in the Customizer must mirror the PHP that produces the markup, or take shortcuts to approximate it. But Selective Refresh is DRY as there’s no duplication of JavaScript and PHP. An Ajax request retrieves the new markup for the preview.

Registering Partials

Setting previews need to opt-in to use Selective Refresh by registering the necessary partials. Selective Refresh is added for the blogdescription setting by adding a partial with the same name.

function foo_theme_customize_register( WP_Customize_Manager $wp_customize ) {
    $wp_customize->selective_refresh->add_partial( 'blogdescription', array(
        'selector' => '.site-description',
        'container_inclusive' => false,
        'render_callback' => function() {
            bloginfo( 'description' );
        },
    ) );
}
add_action( 'customize_register', 'foo_theme_customize_register' );

Selective Refresh JavaScript Events

  • partial-content-rendered: When the placement is rendered. JavaScript-driven widgets can re-build on this event.
  • render-partials-response: When data is returned, after a request for partial rendering. The server filters this data with ‘customize_render_partials_response’.
  • partial-content-moved: When a widget has moved in its sidebar. As shown above, JavaScript-driven widgets can refresh on this event.
  • widget-updated: When the WidgetPartial is refreshed with its renderContent method.
  • sidebar-updated: When a sidebar has a widget that’s refreshed or updated. Or when a sidebar’s widgets are sorted, using reflowWidgets().

Support for selective refresh in widget

add_theme_support( 'customize-selective-refresh-widgets' );

class Foo_Widget extends WP_Widget {

    public function __construct() {
        parent::__construct(
            ‘foo’,
            __( 'Example', 'bar-plugin' ),
            array(
                'description' => __( ‘An example widget’, ‘bar-plugin’ ),
                'customize_selective_refresh' => true,
            )
        );

        if ( is_active_widget( false, false, $this->id_base ) || is_customize_preview() ) {
            add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
        }
    }
}

«
»

Leave a Reply

Your email address will not be published. Required fields are marked *