Been a while since I wrote something. Let’s talk about some of the new stuff available in the Customizer.
Forget about some of part two
First, back in part two, I had a bit about Surfacing the Customizer. That bit is outdated now, WordPress does this for you in later versions. So, yeah, skip that.
Shiny new thing: Panels
Okay, so Panels aren’t that new. They were added in WordPress 4.0. Basically, they’re sliding containers for sections. Having trouble fitting all your settings on the screen? Group the various sections up into Panels. Panels show up as an item in the main list, and when you click the arrow next to them, the whole list glides off screen to show only those sections.
So, now we have four things: Panels, Sections, Controls, and Settings.
Panels group Sections together
Sections contain Controls
Controls are what the user changes
Settings define what the Controls change
Creating a panel is easy:
$wp_customize->add_panel( 'some_panel', array(
'title' => 'Panel 1',
'description' => 'This is a description of this panel',
'priority' => 10,
) );
All that’s new is a panel setting to tell the section to go into that panel. Simple.
Active Callbacks
One of the problems with the Customizer was that it displayed settings and showed them changing on the site to your right, but the site being displayed is the actual site. Meaning that you can navigate on it. Sometimes, the controls being shown don’t necessarily apply to the actual site that you’re seeing.
Example: If you have a control to change the color of something in the sidebar, but then are looking at a page which has no sidebar, then you have no visual feedback to tell you what the change looks like.
To fix this, “active callbacks” are used.
The active_callback is simply a new parameter that you can pass into Panels, Sections, or Controls. It can contain the name of a function, and that function will be called when the page changes. The function should return true or false (or equivalent) to indicate whether or not the element of the customizer should be shown for that page.
So, if you have a whole Panel that only make sense when the user is looking at Front Page of the site (and not an individual post), then you can do this:
$wp_customize->add_panel( 'front_page_panel', array(
'title' => 'Front Page Stuff',
'description' => 'Stuff that you can change about the Front Page',
'priority' => 10,
'active_callback' => 'is_front_page',
) );
And voila, when the user is not looking at the front page, the panel simply disappears.
You can use any of the normal WordPress Template Tags for this, or write your own function if you want to be more specific about it.
Edit: As pointed out in the comments, this will not work with ALL of the Template Tags. In particular, is_single won’t work because of the optional parameter it can take. You can define a wrapper for these methods instead, to get the same effect. Example:
function callback_single() { return is_single(); }
...
'active_callback'=>'callback_single'
...
Fun with Active Callbacks
If you do need to write your own callback function, note that the function receives the object in question when it’s called. So, if you attach an active_callback to a Panel, your function will get a argument of the WP_Customize_Panel object in question passed to it. Sections get WP_Customize_Section and such. You can use the information in these to decide whether the panel (or whatever) should be shown for that page.
So, how do we use that object? Well, you can use this to make whether certain controls show or not dependent on the values of other settings. All the various items you can use this on have a link back to the main WP_Customize_Manager. That class has a get_setting function, which you can use to determine what to do.
So, let’s make a control that causes other controls to appear, dependent on a setting.
First, let’s make a simple radio selection control:
Now, note that the callbacks are very similar. Seems like repeated code, doesn’t it? Well, it is, but remember that the $control here is the whole WP_Customize_Control object. We can use the same callback and simply check which control is calling it here instead.
So, instead of using two different callbacks, we just point our controls to this callback, which figures out what should show up for which setting. I’m sure you can simplify this further, depending on your particular needs.
One more thing: Customizing the Customizer
Not everybody likes the style of the Customizer. Maybe it clashes with your theme. Maybe you just want to tweak it a bit. Maybe you dislike that gray background color, and a more soothing blue would go better for your theme.
You can enqueue whole extra CSS files instead, if you like. Or, if you have special needs for javascript in some of your controls, and there’s libraries necessary to implement them, then you can enqueue those libraries here as well.
Okay, a quick one today. Let’s make a custom control for the customizer.
Back in the first tutorial, I talked about the various controls available in the customizer. Specifically I mentioned image handling, color wheels, text boxes, radios, dropdowns, and checkboxes.
Let’s try a new one? How about a textarea? It’s not in the core code, but it’s easy enough to add one.
Create a Class
So first, we have to create our class. Now, where we create this class is important. Specifically, we have to create it in the function called by the customize_register action. You remember that, right? It started like this:
add_action( 'customize_register', 'themename_customize_register' );
function themename_customize_register($wp_customize) {
// ... do stuff ...
The reason we have to create our class in here is because we need to make our new class extend the built in WP_Customize_Control class, and that class only gets loaded and defined when we’re actually using the customizer. An alternate means of doing this would be to wrap the class definition in an “if (class_exists(‘WP_Customize_Control’))” statement, if you prefer to not have your classes defined inside a function. Personal preference, I don’t think it makes a difference either way.
So, here’s our textarea control. All we’re doing is to override the render_content() function and make it display a textarea.
class Example_Customize_Textarea_Control extends WP_Customize_Control {
public $type = 'textarea';
public function render_content() {
?>
<label>
<span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
<textarea rows="5" style="width:100%;" <?php $this->link(); ?>><?php echo esc_textarea( $this->value() ); ?></textarea>
</label>
<?php
}
}
You can see how simple it is to do, really. We just output a span with the value from $this->label for the name displayed above the textarea, then output the textarea itself.
Note that the textarea has no “name” parameter. It doesn’t need one. The $this->link() function outputs the information for the customizer script. Specifically, it will create a “data-customizer-setting-link” attribute, to link the textarea to the proper setting it’s controlling.
Now, we just have to use the new control.
Add a setting and control
Let’s go back to the theme demo I used in the second customizer tutorial post, and add a new setting and control to demonstrate this:
$wp_customize->add_setting( 'textarea_setting', array(
'default' => 'Some default text for the textarea',
) );
$wp_customize->add_control( new Example_Customize_Textarea_Control( $wp_customize, 'textarea_setting', array(
'label' => 'Textarea Setting',
'section' => 'themedemo_demo_settings',
'settings' => 'textarea_setting',
) ) );
Nothing complicated there. We create the setting, then we create our control, using the new class we made for this purpose earlier.
Use the setting in the theme
Now let’s add to that index.php file I made in the theme demo to show the results of our work.
And that’s pretty much that. We now have a textarea control, and changing/saving results in the setting changing as well.
You can extend this further to use postMessage for real-time changing of settings, if you like.
Custom controls using complex javascript and such can be done as well. Examine the core WP_Customize_Color_Control, which uses the farbtastic Javascript for the color wheel. That one has special JS in the customize-controls.dex.js file to handle receiving the input and passing it along to the customizer JS. Look for “api.ColorControl” and how it gets the setting from the HTML and sets it. I’m not a JS guru, that sort of thing is slightly outside my own scope. 🙂
Any ideas for other controls that themes might need? Leave a comment, maybe somebody has a solution.
Last time I wrote about using the Theme Customizer to supplant/add to your existing options. But what if you’re writing a new theme entirely?
Do you even need an options page?
How many options does your theme have, anyway? Would it not make more sense to eschew those complex options pages in favor of just allowing the user to do it all “live”? With the Theme Customizer, this becomes entirely possible. As an added bonus, it also gives us a really handy use for the theme_mod system.
Step 1: Surfacing the Customizer
One thing I don’t like about the theme customizer is how hidden it is. It’s in the Themes selection space, under the strangely worded “Live Preview” option. Let’s bring that to the forefront and make it more visible for our example theme. In our functions.php file:
add_action ('admin_menu', 'themedemo_admin');
function themedemo_admin() {
// add the Customize link to the admin menu
add_theme_page( 'Customize', 'Customize', 'edit_theme_options', 'customize.php' );
}
There we go. Now we have a “Customize” link in the Appearance menu that loads up the customizer. Nice.
(Note, using the “customize.php” link works with the currently active theme only. Adding ?theme=themedemo to it would allow links to customize non-active themes, but this makes no real sense in the theme functions.php file of a theme. But if you were doing a plugin that needed to load the customizer, that might be good to know.)
Don’t do this anymore, kids. WordPress brought the Customize link to the surface in a later version.
Step 2: Adding some options
Let’s add some simple options to the theme customizer. How about a text field and, say, a color picker. Why not?
We now have “some_setting” and “some_other_setting”. You can tell that I’m being very creative with my naming scheme here. 😉
Note that I didn’t define the “type” for these settings. This means they’ll be the default type, which is “theme_mod”, and that’s perfect for this case. Since we’re providing no other way than the customizer to change these settings, then it’s nice and easy to use them.
The header and footer are pretty standard. Nothing special. You can find them in the download. What we’re really concerned with here is how the theme uses the settings themselves.
Notice the use of get_theme_mod. It’s pretty darned easy to use, really. It just gets the settings and uses them however the theme needs to. For this demo, I’m just outputting their contents for demonstration purposes. I also added in a non-existent setting to show that it works and outputs the default value when nothing is set for the theme in the theme_mod system.
The nice thing about theme_mod is that it automatically stores the information in a nice packed way, unique to the theme itself. If you have multiple copies of the same theme on the site, but with different names, each will have its own settings. Easy and handy.
Step 4: There is no step 4.
Seriously, that’s it. You can go further and make the settings work “live” using the postMessage methods I explained in the previous post, but for the most part, there’s nothing more to do. This is a simple and easy way of making settings, using them, and not worrying about complex options pages, settings in the database, where they’re stored… Why do all that extra code if you don’t have to?
Here’s a link to a working theme using the above concepts. For fun, it also supports custom background colors. 🙂
Note: Everything I’m talking about here, including the code, is in beta mode. It will be subject to change. I’ll update this post after release to fix any code changes that may occur between now and then. I’m releasing this post now so that theme authors can start looking at their themes and thinking about how they might want to change the way they do options pages.
So, WordPress 3.4 has this nifty new feature you can find on the main Theme selection page. It’s a link next to each theme labeled “Customize”. This is the new Theme Customizer, and it’s way cool.
In fact, you can’t see what it does with a simple picture, so here’s a video. It’s available in HD if you want to go full screen. 🙂
So, now you know what it does, and if you’re a theme author, you’ve probably just gotten some great ideas. Here’s how you can implement those ideas in your theme.
First, note that if you already support the built in Custom Header and Custom Background functionality the WordPress core provides, then those will magically show up and work in the theme customizer. No extra code needed on your part.
Existing Options
Now, the first thing you’ll probably want to do is to take note of how your existing settings in the theme work. You have three main options for theme settings, realistically. I’ll go over them briefly.
1. “Theme mod”. This uses the set_theme_mod and get_theme_mod functions. It’s rare that themes actually use these since I wrote about the Settings API, but it is there and if you use these normally then it is supported by the Theme Customizer (in fact it’s the default).
2. Individual Settings. If you store your theme’s settings in the options table as individual rows, one per setting, then that works fine with the customizer. This is not the preferred way of doing things in themes, however, and not the most common. Still, some themes do this, so if you’re one of them, it’s supported as well.
3. Serialized Settings. This is the way I explained in my Settings API Tutorial and the method recommended by the Theme Review guidelines, as well as the way Chip described in his own tutorial for theme settings. Essentially, you store your settings in an array, then store that array using set_option or get_option, as one row in the database. This method is supported and it’s the way I’ll primarily cover in this article. I’ll briefly mention the other two methods when appropriate.
Once you know how your settings are stored, then you’ll know what to fill in at certain spots in the code. More on this when we get to it.
Object Orientation
Now, the Theme Customizer is very object oriented, and while you don’t necessarily need to understand this to implement the basics of it, you might need to understand it if you’re going to make something completely custom. Just a warning.
First, we’ll look at the left hand side of the customizer screen. Notice that the left hand side is divided into sections. Actually, that’s their name: WP_Customize_Section. In each of these sections is one or more controls; or rather, WP_Customize_Control. Finally, each of these controls one of more settings on the page: aka WP_Customize_Setting.
The Sections organize the controls. The Controls get input and pass it to the settings. The Settings interface with your existing options in the theme.
To make new stuff here for your own custom options, you need to know where to add it. That place is the customize_register action hook.
add_action( 'customize_register', 'themename_customize_register' );
function themename_customize_register($wp_customize) {
// ... do stuff ...
The function gets a parameter of the main $wp_customize object. This is the interface point where you will do everything like adding sections and controls and such.
Sections
So, first thing to do is to add a section. Here’s one way to do it:
The first parameter is a unique ID for the section that you’ll need later (when you’re putting controls into it). The second parameter is an array of options for the section. Sections don’t have a lot of options, really. You can give them a title, you can give them a “description” if you need some explanatory text in them. The priority setting determines their order in the list.
You can also give sections a “capability” if you have a special case. Generally speaking, most sites require the “edit_theme_options” capability to have users edit this sort of thing, and this is the default capability that the sections use. However, if you have options that anybody can edit, or which should only be managed by administrators, changing this capability will prevent the section from appearing to users who can’t change those settings anyway.
One final thing you can add to a section is a “theme_supports” option. This will make the menu not appear unless the theme supports something. If you’re putting this code in a theme itself, then you already know what the theme supports, so it doesn’t make much sense. The core uses this to not show the header and background options if the theme doesn’t support them.
Settings
Next, let’s configure some settings. Yes, the settings, not the controls. See, the controls need to know what settings they’re changing, so we have to attach the settings up first.
In this case, I’ve declared that the setting I’m interested in is in an option, the option is named “themename_theme_options” in the database, and it’s serialized, and the actual array key in there is “color_scheme”. Remember that talk we had before about the Settings API and how you store your settings? This was method 3.
This setting basically tells the theme customizer where the option is stored, and how to change it’s value so that your theme displays with the changed option.
Here’s the good bit about this: You’re telling the theme customizer where the option is. You don’t have to change the way the existing option works at all.
You already have a theme options page, right? So somehow, you’re saving those options. And in the theme, it’s reading those options using get_theme_mod or get_option, right? The way the theme customizer works is that it intercepts that call using a filter, changes the option for the previewer case only, and then passes the new option along to the theme. So the theme has no idea that the value it’s getting isn’t in the database, but one the user just selected. That’s the magic trick and why themes don’t have to dramatically change to support this sort of thing. All they have to do to make custom sections is to tell the theme customizer code what options they’re using and how, and it changes those options directly for the previewer.
(Note of clarification here: The “default” setting above should be a default value, not the current value. The difference is a subtle one, but the point is that you don’t actually need to get the current value of the option from the DB and put it in here. The WP_Customize_Setting takes care of all that jazz for you. The “default” is what should be used if the value doesn’t exist in the DB at all.)
There’s one more bit to the add_setting call that we’ll come back to later when I get around to explaining postMessage.
Controls
Finally, we come to the controls. Controls can look one of a lot of ways, obviously. The simplest controls are just checkboxes, or text fields. However, colors are something that change a lot, so there’s color wheel controls too. In fact, WordPress defines a number of possible controls. Let’s go over a few:
Pretty simple. It’s referencing the section it’s in, the setting that it’s going to change, and then it has the radio type and the list of choices along with their associated values.
How about a checkbox instead? This one comes straight from core:
The default type of control is actually type = ‘text’, and it creates a text box control. One more type of control is the “dropdown-pages” type, which creates a dropdown list of the WordPress Pages.
But that’s not all. There’s actually several more, but because they’re so custom, they’re declared differently. Here’s where we get all object oriented on ya…
Whoa, what’s with the new class? The WP_Customize_Color_Control is a class that is extending the built in WP_Customize_Control class. It adds the color wheel jazz to places where color selection is needed. Note that the class is being created here with new, and so it has to get the $wp_customize passed to it directly, so it knows where to hook in. (Note: This may change before final 3.4 release.)
Other controls of note:
WP_Customize_Upload_Control – This gives you an upload box, for allowing file uploads. However, you probably won’t use this directly, you’ll extend it for other things… like:
WP_Customize_Image_Control – This gives the image picker and the uploader box. It extends the upload controller. You can see it in action on the custom background piece, where a user can upload a new file to be the background image.
WP_Customize_Header_Image_Control – Because of the resizing action of the header piece, it needs a bit of special handling and display, so the WP_Customize_Header_Image_Control extends the WP_Customize_Image_Control to add that functionality. You can see it in action on the custom header piece, where a user can upload a new file to be the header image.
So, the way to create a custom controller to do whatever you want is to make a new class of your own which extends WP_Customize_Control and adds the bits you want. How to do that is a bit complex, so I’ll save that for another tutorial. For now, you’ve got image handling, color wheels, text boxes, radios, dropdowns, and checkboxes. I think that should be enough to get started with.
End of tutorial?
Not quite. Everything I went over above is enough to add new sections to the customizer, put controls in them, and then to have the preview show your changes after a slight delay when the page refreshes. All you have to do is to call those functions with the proper parameters, in the proper place, and it’ll work.
However, note that I said “when the page refreshes”… C’mon… this is the year 2012. We don’t have flying cars, and we still have to wait a whole second or two?
Nope.
Enter postMessage
Back when I mentioned the $wp_customize->add_setting function call, I mentioned “one more bit”. That one more bit is the option called “transport”.
Transport defines how your setting change gets from the place where you changed it into the preview pane. The default setting for this is “refresh”. An alternative setting is named “postMessage”.
The postMessage transport makes it such that the setting is instantly sent into the other frame, where javascript can adjust the page on-the-fly using this new information.
An example:
Let’s say we have a setting to change the colors of the titles. All the titles on the page are in some tag that has a class of posttitle, perhaps. The option normally just saves the HTML color chosen, then outputs some inline CSS in the header.php to basically do this:
.posttitle {
color: #abcdef;
}
Or whatever the option actually is for that color.
We have hooked our setting to that option, and hooked our WP_Customize_Color_Control up to it, and now when we change it, it works and we can see the color change. Note that this is easiest to do with already working customizer options, so the best way to do it is to get it working normally first, then add on this next bit.
Now, we have the working option in the customizer, so to take away that refresh delay, we’ll add this new option to the add_setting call:
'transport' => 'postMessage',
This tells the customizer that the setting will be sent directly to the frame via javascript. However, for that setting to work, we need javascript in the frame itself to receive it.
So, back in our main function… remember that? It started like this:
add_action( 'customize_register', 'themename_customize_register' );
function themename_customize_register($wp_customize) {
// ... do stuff ...
Right at the end of that function, we’re going to add this code:
This is going to add a new function call to our preview frame’s footer. It only gets added with the preview frame, so the live site and others won’t see it, because they don’t need to see it. This is where we’re going to output our javascript to make things happen in real-time.
Here’s our function:
function themename_customize_preview() {
?>
<script type="text/javascript">
( function( $ ){
wp.customize('setting_name',function( value ) {
value.bind(function(to) {
$('.posttitle').css('color', to ? to : '' );
});
});
} )( jQuery )
</script>
<?php
}
As you can see, it just outputs a bit of javascript. This code won’t change much, ever, so let’s go over just two pieces of importance:
‘setting_name’ is the name of the setting, as added by the $wp_customize->add_setting call.
The entire line starting with jQuery(‘.posttitle’) is our custom bit of code. It gets the “to” variable, which will be the color chosen by the user, and it sets the posttitles on the page to have that color, using the css modifying functionality of jquery.
Those are the only two bits you need to change, really. The rest is pretty copy-pasta. For each real-time setting, you can dupe this bit of code in the script.
Here’s another thing: You can change pre-existing refresh settings to be postMessage ones. Take the Site Title and Tagline elements in the Header section, for example. These are refresh settings, and the reason they are is because each theme implements them differently. There’s no way for the core to know the javascript code needed for any particular theme.
But if you’re a theme author, then you’re not writing for a generic theme. You’re writing for your particular theme. You know how the site title and tagline are displayed. There’s no reason you can’t make those update in real time. And while you’re at it, the header_textcolor setting can be real time too, since you know the theme code.
In your main function again, add these three lines of code:
That changes the transport on those core settings to be postMessage. Now you need to add the javascript code to actually do the refreshing in your theme. Here’s an example of TwentyEleven doing this (with the patch I wrote for it):
function twentyeleven_customize_preview() {
?>
<script type="text/javascript">
( function( $ ){
wp.customize('blogname',function( value ) {
value.bind(function(to) {
$('#site-title a').html(to);
});
});
wp.customize('blogdescription',function( value ) {
value.bind(function(to) {
$('#site-description').html(to);
});
});
wp.customize( 'header_textcolor', function( value ) {
value.bind( function( to ) {
$('#site-title a, #site-description').css('color', to ? to : '' );
});
});
} )( jQuery )
</script>
<?php
}
For the blogname, it changes the HTML inside the “#site-title a” link. For the description, it changes the tag with #sitedescription. For the color of those, it simply targets both of them and alters their CSS.
Core has to try to be generic across all themes. But themes have more knowledge of how they work and can change things to target themselves in better ways. A theme adding controls knows what those controls change, so if it’s something simple like CSS or even something more complex like HTML, if you can write javascript code to make that modification in real time, then you can use postMessage and eliminate that refresh delay.
Hopefully this explains some of the theme customizer. Was it as clear as mud? Take a look at my patch to Twenty Eleven to add some of the theme options from its existing options screen into the customizer. You can find it on this ticket: http://core.trac.wordpress.org/ticket/20448.