Options Framework + Theme Customizer

One of the great new features in WordPress 3.4 is the Theme Customizer which allows you to modify options for a theme and instantly preview them on the site.

I’d encourage you to try out the Theme Customizer, but first upgrade to the latest version of the Options Framework (1.3). Earlier versions explicitly checked for $_POST['update'] in the request before saving anything to the database, which doesn’t allow options set via the Theme Customizer to save properly.


Approach to Theme Customizer Support

When I originally started working with the Theme Customizer in the Options Framework, I thought about creating a method for all the defined options to automatically get outputted for use in the Customizer- no extra work required. I quickly discovered this was a bad idea.

A couple reasons why:

  1. You might want to order options differently in the front end customizer than you would in the options panel. For instance, options related to the site title & tagline should probably go in that section, rather than the tab defined in the Options Framework.
  2. It wouldn’t make sense to output options that don’t actually change the theme appearance
  3. Options that may work in a larger panel may not fit in the limited space of the Theme Customizer

Another idea I had was to add additional parameters to the $options array so that it could know which options to output for the Theme Customizer. For instance, a text option to be displayed in the “Navigation” setting could get written like this:

$options[] = array(
	"name" => "Text",
	"id" => "example_text",
	"std" => "Default Value",
	"type" => "text",
        "theme_customizer" => true,
        "section" = > "nav");

But that seemed to overcomplicate it. Some developers may still want to take this approach to outputting their options to the Theme Customizer (and you’re welcome to), but it doesn’t make sense to build this into the core plugin functionality.

Use Core Methods

In the end I decided the best way to support the theme customizer is to just use the Theme Customizer API as it was intended. (It actually didn’t take that long to come to this conclusion, I just want folks to understand the reasoning behind it).

The Theme Customizer API is actually really awesome. If there was something like this in the core Settings API we wouldn’t need the Options Framework.

When you define a control like “text”, “checkbox”, “radio”, “select”, “image” or “colorpicker”, all the required HTML and scripts are automatically outputted to make that option work. It’s lovely.

Getting Started

If you haven’t already read Otto’s post about leveraging the theme customizer I suggest you do that now. The rest of this post will make more sense if you understand how the Theme Customizer works.

If you have read Otto’s post, you’ll notice he mentions three different ways that theme options can be set. The Options Framework uses “Serialized Settings”, which is the method suggested by the Theme Review guidelines and the one that Otto primarily covers.

Option Name – Defined Programmatically

In some of the example themes for the Options Framework I have the default option name set like this:

function optionsframework_option_name() {

	// This gets the theme name from the stylesheet (lowercase and without spaces)
	$themename = get_option( 'stylesheet' );
	$themename = preg_replace("/\W/", "_", strtolower($themename) );

	$optionsframework_settings = get_option('optionsframework');
	$optionsframework_settings['id'] = $themename;
	update_option('optionsframework', $optionsframework_settings);

	// echo $themename;
}

If you use this method, the option name in use is the theme name (but in lowercase, and with spaces replaced by underscores). With this method child themes will have their options saved under a different option name.

If you want to continue using this method, you’ll need to use that variable throughout the theme customizer code for it to work correctly with both parent and child themes.

Option Name – Defined Manually

Another way to set theme option name, is to manually define it. This is the method I generally use in my own projects:

function optionsframework_option_name() {
	$optionsframework_settings = get_option('optionsframework');
	$optionsframework_settings['id'] = 'options_theme_customizer';
	update_option('optionsframework', $optionsframework_settings);
}

This means that the option name is set to “options_theme_customizer”, and it will use that same option name even with child themes.

For this tutorial, I’ll assume you’re using this second method.

You’ll need to know the option name when you set up the Theme Customizer code so that it can save changes to the option name. (In my code example, I use the option name “options_theme_customizer”.)

Tweaking Your Options Array

If you’ve set up your theme options array like the example in the “options-check” theme, it probably looks something like this:

$options[] = array(
	"name" => "Text",
	"id" => "example_text",
	"std" => "Default Value",
	"type" => "text" );

$options[] = array(
	"name" => "Select Box",
	"id" => "example_select",
	"std" => "First",
	"type" => "select",
	"options" => $test_array );

However, with the Theme Customizer we’ll want to reference these specific options in this array- so it’s useful to assign a key to each option in the array.

I’d suggest using the name value as the “id” parameter. Like so:

$options['example_text'] = array(
	"name" => "Text",
	"id" => "example_text",
	"std" => "Default Value",
	"type" => "text" );

$options['example_select'] = array(
	"name" => "Select Box",
	"id" => "example_select",
	"std" => "First",
	"type" => "select",
	"options" => $test_array );

Setting Up the Theme Customizer

Now you can add the code for the theme customizer.

This can be put wherever you think it’s appropriate in the theme, but I’d suggest adding it to options.php underneath the optionsframework_options function. This works perfectly when using the plugin version and also means it won’t be loaded if the Options Framework Plugin has been disabled.

However, options.php appears to load too late when used in the theme version. I haven’t traced down exactly why this is yet, but to get around it you can include options.php directly from your functions.php file:

require_once dirname( __FILE__ ) . '/options.php';

Front End Customizer Code

To create Theme Customizer options for the two option listed in the example array above, you would add this:


/**
 * Front End Customizer
 *
 * WordPress 3.4 Required
 */
 
add_action( 'customize_register', 'options_theme_customizer_register' );

function options_theme_customizer_register($wp_customize) {

	/**
	 * This is optional, but if you want to reuse some of the defaults
	 * or values you already have built in the options panel, you
	 * can load them into $options for easy reference
	 */
	 
	$options = optionsframework_options();
	
	/* Basic */

	$wp_customize->add_section( 'options_theme_customizer_basic', array(
		'title' => __( 'Basic', 'options_theme_customizer' ),
		'priority' => 100
	) );
	
	$wp_customize->add_setting( 'options_theme_customizer[example_text]', array(
		'default' => $options['example_text']['std'],
		'type' => 'option'
	) );

	$wp_customize->add_control( 'options_theme_customizer_example_text', array(
		'label' => $options['example_text']['name'],
		'section' => 'options_theme_customizer_basic',
		'settings' => 'options_theme_customizer[example_text]',
		'type' => $options['example_text']['type']
	) );
	
	$wp_customize->add_setting( 'options_theme_customizer[example_select]', array(
		'default' => $options['example_select']['std'],
		'type' => 'option'
	) );

	$wp_customize->add_control( 'options_theme_customizer_example_select', array(
		'label' => $options['example_select']['name'],
		'section' => 'options_theme_customizer_basic',
		'settings' => 'options_theme_customizer[example_select]',
		'type' => $options['example_select']['type'],
		'choices' => $options['example_select']['options']
	) );

You can see how the options array that was defined in optionsframework_options gets reused to output the default, label, type and choices- so they don’t need to be defined again separately.

I realize it’s a lot of extra code just too add two options to the Theme Customizer- but it’s easy enough to write (and makes you think much harder about whether an option is really needed or not).

If you did want to set up some sort of loop or function to do this instead, you’re welcome to do that as well.

What Options Are Supported

You’ll notice in Otto’s post there are example for several types of options supported by default.

The Options Framework has a couple additional option types it uses: textarea, multicheck, wp_editor, background and typography. I haven’t decided the best route to support all of these yet.

Textarea could easily be outputted as a “text” option instead. An actual textarea field might take up too much room in the Theme Customizer panel.

wp_editor won’t be supported. Doesn’t make sense.

The others are actually just groups of default options (e.g. typography is several select boxes), which could be supported in a couple ways:

  • A function could add all the individual inputs for these options in the Theme Customizer.
  • The Theme Customizer class could perhaps be extended
  • Each field could be manually added. (e.g. options_theme_customizer[example_background][color] can be set on its own).

I need to try this all out a little more before I can make a recommendation.

More Code Examples

I have demo code available as a separate theme in the Options Framework Plugin repo. Eventually I’ll merge it into the Options Check demo.

If you want to see code with all the default options listed, check out this file.

I’ve also added a demo to the theme version and plugin version of the Options Kit.

Notes on Sanitization

When your options get saved it runs through the regular sanitization filters for the Options Framework- which means the same rules apply to options set via the Theme Customizer as through the standard options panel.

However, that sanitization just occurs when the options are saved- not necessarily when someone is altering their options on the fly with the Customizer. Add sanitization where you need it.

Notes on postMessage

When you’re working in a local dev environment and update an option, the page refreshes quickly and you see the update almost immediately. However, this might not be the case for users with slow connections.

If you’re interested in using postMessage and avoiding a page refresh I’d recommend reading the rest of Otto’s tutorial and look at how Twenty Eleven does it.

Conclusions

As you can see there’s still a couple kinks and bottlenecks to work out- but I hope to have them solved soon. If you want to help you can always post a bug report to the GitHub repo and send over a pull request.

It’s also been great to see all the orders come through for the Options Kit. I’ve been spending a lot of evenings and weekends putting together examples and tracking down bugs- so everyone’s support has been much appreciated.

And big thank yous to everyone who has chipped in on some debugging of the checkbox options via twitter and e-mail- especially Otto. You folks are terrific. This is why I love building things for WordPress.

35 Responses

  1. Devin,
    Whenever I add this line to functions.php of my theme (not a child theme):
    `
    require_once dirname( __FILE__ ) . ‘/options.php';
    `
    I get this error when trying to open the customizer:
    Fatal error: Call to a member function check_capabilities() on a non-object in C:\local-path\wp-includes\class-wp-customize-control.php on line 107

    Any idea what I’m doing wrong?

    1. Your textarea is a bit overkill. I see where you got it from, but most of that isn’t needed.

      This will work:
      http://pastebin.com/FVXFu9K3

      However, you should use a different name than “WP_Customize_Textarea_Control”, because if WP adds a textarea control in the future, the names will clash. Use a prefix other than “WP”, please.

  2. Thank you for doing this great job!

    I have trouble with adding each field for background-type of option. I can’t figure it out how to divide background-type to separated options for theme customizer. Here it is.

    I’ll be appeciated for any help )

  3. I’ve been working through some things using the theme framework and ran into a snag.

    The options.php says it uses the “theme name” but the only thing I can get to display my options is the of_get_option($id,$default).

    How can I replace that? I tried hardcoding the id as noted above, but it doesn’t work.

    Thanks!

  4. Devin, thank you for spelling out how to integrate the options framework with the theme customizer.

    Did you arrive at any further conclusions regarding the best approach to adding the typography options to the theme customizer?

    When/if you get a chance, I’m particularly interested in a walk-through on either of the first 2 options you listed:

    A function could add all the individual inputs for these options in the Theme Customizer.
    The Theme Customizer class could perhaps be extended.

  5. great stuff Devin. Thx for the examples.
    I`m desperately trying to add an array of different default background images..
    Do you know how the image upload setting can be modified to add several images to choose from?

    1. Jeremy, your code works great on WordPress 3.4.2. But I just tried it with WordPress 3.5 Release Candidate 2, and it doesn’t work. Only the default option sections show up in the customizer and none specified by your code’s loop are available. I can’t find any documentation on WP 3.5’s changes to the Theme Customizer API, so I’m not sure where the incompatibility is. Any ideas?

    2. Jeremy, I figured out the problem I was having. In my functions file I registered a nav menu that I left blank in the actual menu options panel… meaning I hadn’t gotten around to defining nav items for it. Once I added nav items to the menu (or deleted the menu’s registration), everything worked fine again. It’s interesting that 3.4.2 doesn’t flake out over the blank menu, but 3.5 does.

  6. Has anyone that’s monitoring this post and its comments successfully coded their own custom control for the Theme Customizer?

    Specifically, I’m wondering if anyone has custom controls working for a couple of the options framework field types that aren’t supported by the customizer by default:

    images (use images instead of radio buttons)
    typography (a set of options to define typography)

    I’ve been trying to figure it out, but I haven’t made any progress.

  7. You said… ‘If you use this method, the option name in use is the theme name (but in lowercase, and with spaces replaced by underscores). With this method child themes will have their options saved under a different option name.’

    I like this naming, but how will I write the name here?
    $wp_customize->add_setting( 'options_theme_customizer[palette]', array(
    'default' => $options['palette']['std'],
    'type' => 'option'
    ) );

    How will I get it to use each child’s theme name? Thanks!

  8. Hi,
    thank you very much for sharing this faboulous stuff.
    Here is my question:
    when I upload an image it is also already resized in a few different sizes, is there a way to choose a different size of this uploaded image?
    I try to explain it better, I upload an image named:
    grumpycat.jpg 1024×768 px
    how can I have a link to:
    grumpycat-150×150.jpg ?

    Thank you very much for your time and patience.

  9. Dre

    What are your thoughts on what should be handled by settings and what should be handled by the theme customizer? While it seems clear the the customizer should handle anything that is *visual* in nature, isn’t there something to be said for having all theme options in one place? I’m tempted to move *all* the theme options over to the customizer, but I’m still not sure if this is a good idea.
    I’ve spent some time pondering the matter, and I have yet to come to a satisfactory conclusion. I’d be interested in your opinion on the matter.

  10. Felix

    Hi Devin,

    I’m trying to use a field for custom CSS in both theme options page and the theme customizer.

    I use this class to get support for textareas:

    https://github.com/bueltge/Wordpress-Theme-Customizer-Custom-Controls/blob/master/class-textarea_custom_control.php

    Here’s my code for the theme options page:

    $options[] = array(
    'name' => __('Style Options', 'theme'),
    'type' => 'heading' );
    $options['custom_css'] = array(
    'name' => __('Custom CSS', 'theme'),
    'desc' => __('Add some CSS to your theme.', 'theme'),
    'id' => 'custom_css',
    'type' => 'textarea');

    and for the customizer:

    $wp_customize->add_section( 'theme_style_options', array(
    'title' => __( 'Style Options', 'theme' ),
    'priority' => 210
    ) );

    $wp_customize->add_setting( 'theme[custom_css]' );

    $wp_customize->add_control( new Textarea_Custom_Control( $wp_customize, 'custom_css', array(
    'label' => $options['custom_css']['name'],
    'section' => 'theme_style_options',
    'settings' => 'theme[custom_css]'
    ) ) );

    The customizer doesn’t get the content from the field and isn’t saving anything to it. If i use a text input it is working fine, but it’s a bit too small for some CSS code.

    Does anyone have a solution?

Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>