Dave Green – Senior Developer at Make Do – @davetgreen



Dave Green – Senior Developer at Make Do – @davetgreen

2 2


wp-customizer-talk

My "Building Themes with the WP Customizer" talk, which I've presented at several WordCamps and local WordPress meet-ups.

On Github davetgreen / wp-customizer-talk

Dave Green

Senior Developer at Make Do

@davetgreen

Building themes with the WP Customizer API

YOU DON'T HAVE TO BE A

THEME DEVELOPER

TO USE THE CUSTOMIZER

You'll be less like this...

And more like this...

In the beginning, we had theme options...

Now, we have the Customizer API...

A brief summary of the Customizer API

  • Since WordPress 3.4 which was released in June 2012.

  • No external dependencies because it's built into core.

  • Integrates with the existing WordPress Settings API.

  • Gives users instant feedback when they make changes.

  • Can be extended to add more customisation options.

Preparing the Theme

Preparing the theme - Step #1

Create a subfolder in your theme called inc if you don’t already have one. Now create a file in that folder called customizer.php.

your-theme/

    inc/
      customizer.php
    js/
    functions.php
    index.php
    style.css

Preparing the theme - Step #2

Open functions.php and add the relevant line of code to require the file you just created. Without it, your customizer code won't execute!

// Child Theme
require get_stylesheet_directory() . '/inc/customizer.php';

// Parent Theme
require get_template_directory() . '/inc/customizer.php';

// Rest of your functions file...

The customize_register action hook

All of your Customizer code needs be contained inside one or more functions that are hooked into this action, or it won't be executed.

function dtg_customize( $wp_customize ) {
    // Define settings, panels, sections and controls
    // inside this function or multiple functions using
    // the same action hook.
}
add_action( 'customize_register', 'dtg_customize' );

The WP Customize Object

There are twelve $wp_customize methods available for you to use. You'll mostly be using the add_ methods.

Settings Panels Sections Controls add_setting add_panel add_section add_control get_setting get_panel get_section get_control remove_setting remove_panel remove_section remove_control

Adding a setting

Customizer settings are responsible for saving the user's changes and sanitizing the data, as well as facilitating the 'live preview' feature.

$wp_customize->add_setting( 'dtg_phone_number',
    array(
        'type'       => 'theme_mod', // OR 'option'
        'default'    => '07890 123 456',
        'capability' => 'manage_options',
        'transport'  => 'refresh', // or 'postMessage'
        'sanitize_callback' => 'dtg_sanitize_tel',
    )
);

Validating Setting Data

Here we use a regular expression to ensure our number setting contains only numbers and spaces: no letters or special characters.

// Add to the top/bottom of customizer.php.
function dtg_sanitize_tel( $data ) {

  $clean = preg_replace( '/[^0-9 ]+/', '', $data );

  return $clean;
}

Theme_Mod versus Option

Theme_Mod

Settings can only be used by that specific theme.

All customizer settings are stored within a serialized array in a single option in the database.

Option

Settings can be used by absolutely any theme or plugin.

Each of the customizer settings are stored as a unique option in the database.

Adding a section

A section is a container for customizer controls that can be grouped under a similar theme e.g. colour scheme, branding etc.

$wp_customize->add_section( 'dtg_section_contact',
    array(
        'title'          => 'Contact Info',
        'description'    => 'Contact info for DTG',
        'capability'     => 'manage_options',
        'theme-supports' => '',
        'priority'       => 10,
        'panel'          => 'dtg_panel',
    )
);

Adding a panel

A panel is a UI container for customizer sections, and is useful if you have multiple sections that can grouped under a similar theme.

$wp_customize->add_panel( 'dtg_panel',
    array(
        'title'          => 'DTG Panel',
        'description'    => 'Panel for DTG',
        'capability'     => 'manage_options',
        'theme-supports' => '',
        'priority'       => 10,
    )
);

Adding a control

Controls are UI elements such as a text fields, colour pickers and image uploaders which the user interacts with to update a setting.

$wp_customize->add_control( new WP_Customize_Control(
        $wp_customize,
        'dtg_phone_number',
        array(
            'label'    => 'Phone Number',
            'section'  => 'dtg_section_contact',
            'settings' => 'dtg_phone_number',
            'type'     => 'text',
            'priority' => 10,
            'active_callback' => 'is_front_page', // NEW!
        )
) );

Notes about controls

Panels and/or sections won't appear in the customizer unless you have added a control to a particular section.

Equally, controls won't appear unless they have been added to a section.

Adding a control to an existing section

$wp_customize->add_control( new WP_Customize__Control(
        $wp_customize,
        'dtg_intro_text',
        array(
            'label'    => 'Introductory Text',
            'section'  => 'title_tagline', // BINGO!
            'settings' => 'dtg_intro_text',
            'priority' => 10,
        )
) );

Additional Control Types

In addition to the WP_Customize_Control class used for standard HTML form elements, there are classes for several other control types..

  • WP_Customize_Color_Control

  • WP_Customize_Upload_Control

  • WP_Customize_Image_Control

  • WP_Customize_Background_Image_Control

  • WP_Customize_Header_Image_Control

  • WP_Customize_Cropped_Image_Control

  • WP_Customize_Media_Control

Getting a setting value

The function get_theme_mod() is used to retrieve your customizer settings from the database for use in your theme.

// You should escape the string before you use it.
echo esc_html( get_theme_mod( 'dtg_welcome' ) );

// You can add a fall back value which will override
// the setting's default value if it exists.
$text = esc_html( get_theme_mod( 'dtg_welcome', 'Hello!' ) );

If you've elected to register the setting as an option, you'll need to retrieve it by using the get_option function instead.

Adding a colour picker

Let's add a colour picker to change the colour of the site title.

function dtg_add_colour_picker( $wp_customize ) {
    $wp_customize->add_setting(
    'dtg_title_colour',
        array(
            'default'    => '#000',
            'capability' => 'manage_options',
            'transport'  => 'postMessage',
            'priority'   => 10,
        )
    );
$wp_customize->add_section(
    'dtg_section_colour',
    array(
        'title'          => 'Colour Options',
        'description'    => 'Colour options for DTG',
        'capability'     => 'manage_options',
        'priority'       => 10,
        'panel'          => 'dtg_panel',
    )
);
$wp_customize->add_control(
    new WP_Customize_Color_Control(
        $wp_customize,
        'dtg_title_colour',
        array(
            'label'    => 'Title Colour',
            'section'  => 'dtg_section_colour',
            'settings' => 'dtg_title_colour',
        )
    )
);
}
add_action( 'customize_register', 'dtg_add_colour_picker' );

Generating the new CSS

Now that we've chosen a new colour for the target elements, we need to ensure that we're generating the new CSS on the front-end.

In order to do this, we need to hook into the wp_head action using a function added to our customizer.php file.

Generating the new CSS

function dtg_customize_css() {
  ?>

  <style type="text/css">
    .site-title a {
      color: <?php echo get_theme_mod('dtg_title_colour'); ?>;
    }
    /** Repeat for every selector you're targeting. **/
  </style>

  <?php
}
add_action( 'wp_head', 'dtg_customize_css' );

Enabling Live Preview

Changing the the transport argument from refresh to postMessage updates the live preview using JS instead of refreshing the iFrame.

$wp_customize->add_setting( 'dtg_phone_number',
    array(
        'default'    => '07890 123 456',
        'capability' => 'manage_options',
        'transport'  => 'postMessage', // BINGO!
        'sanitize_callback' => 'dtg_validate',
    )
);

Adding customizer JS

If one doesn't exist in your theme, create a file called customizer.js in your theme's Javascript directory containing the following:

( function( $ ) {

    // Customizer JS goes here.

} )( jQuery );

Now you need to add a Javascript handler for every customizer setting that needs to use the live preview feature.

Adding a JS handler

Let's add a handler to enable live preview for our phone number setting.

// WordPress makes a `wp` Javascript object available to us.
wp.customize( 'dtg_phone_number', function( value ) {

    // Update the phone number HTML when the value changes.
    value.bind( function( newval ) {
      $( '.phone-number' ).text( newval );
    } );

} );

Adding a JS handler

And another handler for the site title colour setting.

wp.customize( 'dtg_title_colour', function( value ) {

    // Change the colour of the title elment.
    value.bind( function( newval ) {
      $( '.site-title a' ).css( 'color' , newval );
    } );

} );

Enqueue the customizer JS

Now we must enqueue the customizer.js file, the WordPress way.

function dtg_customizer_js() {

    wp_enqueue_script(
        'dtg-customizer-js',
        get_stylesheet_directory_uri() . '/js/customizer.js',
        array( 'jquery','customize-preview' ),
        false,
        true // In the footer!
    );
}
add_action('customize_preview_init', 'dtg_customizer_js');

Let's have a look...

Here's one I made earlier

Making Modifications

Use the get_ methods to modify the properties of a given customizer setting, panel, section or control.

$wp_customize->get_setting( 'dtg_phone_number' )->default =
'999';

$wp_customize->get_panel( 'dtg_panel' )->description =
'Stop! Panel Time!';

$wp_customize->get_section( 'dtg_section' )->title =
'WordPress ROCKS!';

$wp_customize->get_control( 'dtg_phone_number' )->label =
'Telephone';

Removing items from the Customizer object

Anything that exists in the customizer - including default options - can be removed using the remove_ methods.

$wp_customize->remove_panel( 'dtg_panel' );

$wp_customize->remove_section( 'header_image' );
$wp_customize->remove_section( 'background_image' );

$wp_customize->remove_control( 'background_color' );
$wp_customize->remove_control( 'header_background_color' );
$wp_customize->remove_control( 'sidebar_textcolor' );

Custom Setting Types

Save certain settings to a different database table and handle the live previews your own way by first defining a custom setting type.

$wp_customize->add_setting( 'dtg_custom_setting',
    array(
        'type'    => 'custom_type',
        'default' => 'value,
    )
);

Saving the Data

function dtg_update( $val, $setting ) {
    // Save the $val for the $setting.
}
add_action( 'customize_update_custom_type', 'dtg_update' );

Handling the Live Preview

function dtg_preview( $setting ) {
    // Update the live preview for the $setting
}
add_action( 'customize_update_custom_type', 'dtg_preview' );

Creating Custom Controls

// Extend the base class if it exists.
if ( class_exists( 'WP_Customize_Control' ) ) {
    class Fancy_Custom_Control extends WP_Customize_Control {

        public function render_content() { ?>
            <label><?php echo esc_html( $this->label ); ?>
            <?php $s = array( 'textarea_name' => $this->id );

            wp_editor( $this->value(), $this->id, $s ); ?>
            </label>
        <?php
    }
}

Adding a custom control

// Use our new shiny class!
$wp_customize->add_control(
    new Fancy_Editor_Custom_Control(
        $wp_customize,
        'dtg_wysiwyg_field',
        array(
            'label'    => 'Example WYSIWYG Field',
            'section'  => 'dtg_example_section',
            'settings' => 'dtg_wysiwyg_field',
            'priority' => 10,
        )
    )
);

Live Preview on Multisite

If you find that the customizer live preview panel is failing to load, uncheck option #4 in your Network Settings to overcome this issue.

In The Future

  • Customizer as a top level link in the dashboard.

  • Better user experience for touch & mobile devices

  • Javascript overhaul for improved performance.

  • Responsive preview for mobile/tablet devices.

  • More robust admin with revisions and locking.

Sign of things to come?

Just one more thing...

Wordpress.org Themes

In April 2015, the WordPress Theme Review Team decided to enforce the use of the Customizer for theme options in all newly submitted themes.

YOU SHOULD TAKE A LOOK AT...

THANK YOU!

@davetgreen

Slides available at

davetgreen.me/customizer-talk

github.com/davetgreen/wp-customizer-talk

QUESTIONS?

@davetgreen

1
Dave Green Senior Developer at Make Do @davetgreen