New Photography Site

I’m launching another new site on celloexpressions.com this summer. Cello Expressions Photography could be considered a photo blog in many ways, but its primary purpose is to serve as a collection of visually stimulating and contextually significant imagery. Bringing my academic/professional interests to Cello Expressions for the first time, this site focuses on architecture, landscape architecture, and construction. Given my current internship at the USC Village project, expect a particular construction emphasis right now. Visually interesting textures and natural landscapes are also featured.

Check it out at http://celloexpressions.com/photography.

The site is using my Lucidus WordPress theme, resulting in a major focus on images and minimal UI. The theme will be publicly available soon, likely as a premium theme but possibly for free on WordPress.org depending on time. Note that due to the heavy use of images, it may take some time for the content to load, but once it does, it’s pretty cool!

Awe & Joy Concert Artwork

2015 Boulder Cello Project/Chase the Music Collaboration Concert

This weekend I’m partnering with the Boulder Cello Project and Chase the Music to put on our 3rd annual concert for children in critical situations. This year’s concert is for a brother and sister and will feature a bold musical celebration of these two amazing kids.

My latest composition, Awe & Joy, scored for Flute, Horn, Percussion, and Cello Ensemble, will be premiered at the concert this Sunday, August 9, 2015 in Boulder, CO. The concert is free and we have plenty of room in the hall for guests. Details and RSVP here: https://www.eventbrite.com/e/concert-for-ayla-and-jayden-tickets-17769911283.

village-overview

USC Village Live Webcam

I’m working at the USC Village jobsite this summer as an intern for Hathaway Dinwiddie Construction Co. This is a huge project – 15 acre site, 6 buildings, over 1 million square feet – and USC has set up the usual webcams to monitor the construction progress. Unfortunately, theirs uses painfully outdated software that won’t even work in IE in compatibility mode unless you get really lucky. So I set up a page that pulls in the latest image from the camera and displays it full-screen, updating the image every second or as your connection allows so that you can see the progress.

View the full-sized live webcam stream here.

The Customizer is the Future for Themes and Theme Options

There has been a lot of backlash from the WordPress community recently over the theme review team’s decision to require theme options to be implemented in the Customizer. But this decision really is in everyone’s best interest.

WordPress 4.2 shipped with the ability to switch themes in the Customizer. When theme-installation is incorporated in a future release, the entire theme selection and customization process will be streamlined to a seamless workflow in which the user never enters the WordPress admin. This functionality is specifically targeted to users that leverage free WordPress.org themes, so it just makes sense for all themes hosted there to be Customizer-optimized. But the real win is the ability to live-preview changes before publishing them. With the Customizer, users know exactly what their site will look like when they publish their changes, a critical feature for anyone who cares what their site looks like when it’s publicly available.

Many people have been critical of the user-oriented nature of the Customizer. But its power is much stronger than most realize; one of my favorite use-cases for the customizer is custom CSS. This is the easiest way for users who want to go further to get into coding and offers a seamless experience that is infinitely better than the easy-to-kill-your-site-or-lose-your-changes-with code editor in the admin. In fact, I’d love to see a customizer-based custom CSS functionality in core as a replacement for the code editor, although I have a feeling that proposal may be too political to advance to an implementation. Bottom line, the customizer lowers the barrier to entry into WordPress development, contrary to many people’s thinking.

Yes, free themes requiring use of the Customizer will lead to a similar movement for client themes and premium themes. And that’s okay. In fact, by having everyone using the same underlying framework, users know where to look for options and have the confidence that live previewing provides. And WordPress will provide a more consistent visual experience for users as well.

You can really build any functionality into the Customizer. Theme-switching, widgets, and menus were all built as plugins first and continue to use the publicly available customizer API to run. So if you must, you can still create ridiculously complicated UI elements that no one will be able to figure out how to use, but you really don’t need to.

And complaints about the amount of screen real estate available and the 300px default width show a lack of creativity and resistance for the sake of resistance to change. Start by removing all of the ads, external links, unnecessary branding, unnecessary options, and general clutter. Make your options self-explanatory – if you need a paragraph to describe what it does, it probably shouldn’t be a user-facing option. Do you still have so much UI that the experience is completely unusable? Try an outside-the-box solution, like utilizing the core media modal (header images and core media controls use it), a custom modal (theme details modal in core), or a slide-out panel (widgets in core and eventually menus in core as well).

No, the customizer isn’t perfect. But it’s time to give it the respect it deserves as a significant part of WordPress. After three years of slow adoption, the theme review team’s decision to enforce its use is a welcome sign for users and a positive decision for the WordPress community as a whole. I’m excited to see what developers do with the Customizer’s amazingly powerful API and what core contributors come up with to improve its design and usability.

twenty-fifteen-no-sidebar

Twenty Fifteen, no sidebar

Twenty Fifteen is another great default theme that can be easily customized. I recently had to put up a quick site for my new themes site on halsey.co. I only wanted one or two pages, with a super simple layout.

I decided to just remove the sidebar (remove the widgets first) and center the content area. On mobile, all we need to do is remove the header. This also removes the “proudly powered by WordPress” footer, as there’re better ways to display that in this context if you want it. Here’s the CSS:

body:before,
#sidebar,
#colophon,
.entry-footer {
	display:none;
}

.site-content {
	margin: 0 auto;
	float: none;
	width: 100%;
	max-width: 1200px;
}

If you’re not familiar with CSS, the easiest way to implement this is to install & activate the Modular Custom CSS plugin, then go to the Customizer and add the above CSS to the “Custom Theme CSS” field.

Cello Expressions Sheet Music Library 1-6-2014

New Sheet Music Library: The Story

After nearly two years of planning, false starts, and development, I finally launched a new sheet music library. In this post, I’ll discuss the development and implementation process, design decisions, and how I created this project in a way that the source code will be available for anyone to use for free.

History

I started posting my cello ensemble compositions and arrangements online in early 2012, when I first set up celloexpressions.com as the website for my high school cello quartet, Cello Expressions. When I transitioned the site to be the home for my projects in August of that year, I created a series of separate WordPress installs for my different sites, moving the original site to the music subdirectory and building a new system to display sheet music in a more structured way. Because I had spent the summer developing Euclid’s Muse, basing the code off of a horribly-written BuddyPress plugin, I thought that the best approach would be to create a custom database table, querying it directly. I didn’t have the time to build a posting or editing UI, so I decided I would just make edits directly in the database with PHPMyAdmin. That worked for a few months, and in November 2012, I redesigned the site’s theme (poorly). But I would last post a new piece in January 2013. It was clear that I needed an entirely different system, and that I would probably need to migrate all of my existing content (now 60 pieces) manually.

Cello Expressions Sheet Music Library, from January 2013 to December 2014.
Cello Expressions Sheet Music Library, from January 2013 to December 2014.

Goals

My primary goal for the sheet music library is to make free music, primarily for cello-oriented ensembles, widely available and accessible. I also want to get my works out there for people to play.

But my goals for making the sheet music library easy to use were much harder to accomplish with the old system. All pieces needed to have PDF downloads, preferably with the ability to have separate score and parts PDFs. I needed to display previews of the PDFs in a browser-agnostic way, rather than hoping that it would work to put a PDF in an iframe. Pieces needed to have a way to upload and display recordings, both via MP3s and via YouTube videos. Pieces needed to have fields for composers, difficulties, genres, and instrumentations, and values should cross-link between different pieces. And most importantly, I needed everything to be searchable, both internally and via search engines.

A Plugin

One of my first decisions was to build the sheet music library functionality in a plugin. That way I could use an existing WordPress theme and redesign much more easily. Over time, additional benefits became clear – others could use this plugin as well. The Boulder Cello Project will be using it, plus an add-on plugin, to power their internal members site, where they post sheet music for their meetups for members to practice in advance. The plugin will be released on WordPress.org once the initial implementation for the Cello Expressions Sheet Music Library is complete.

Custom Post Type & Taxonomies

It also became clear that I should create a sheet music custom post type, with custom taxonomies providing relationships between pieces. Composers, instrumentations, difficulties, and genres are each custom taxonomies for the sheet_music post type. PDFs for the score and parts and audio file uploads would be stored as attachments, with the attachment post ids stored as post meta in sheet_music posts. YouTube videos are stored by their URLs as post meta as well.

PDFs to Images

The solution to displaying PDF previews in a reusable way ended up being surprisingly simple. By converting the first page of the score PDF to an image, the front-end and admin can display an image preview of the PDF pretty easily. Converting PDFs to images is actually pretty simple in most modern server environments with WordPress’ image editor.

Diving briefly into code, WP_Image_Editor’s ImageMagick implementation makes it incredibly easy to convert PDFs to Images:

/**
 * When a PDF is uploaded, generate a thumbnail image and save it in the attachment meta.
 */
add_filter( 'wp_generate_attachment_metadata', 'prefix_generate_pdf_thumbnail_metadata', 10, 2 );
function prefix_generate_pdf_thumbnail_metadata( $metadata, $attachment_id ) {
	$attachment = get_post( $attachment_id );
	if ( 'application/pdf' === get_post_mime_type( $attachment ) ) {
		// Create a png from the pdf.
		$file = get_attached_file( $attachment_id );
		$pdf = wp_get_image_editor( $file );
		if ( ! is_wp_error( $pdf ) ) { // Most likely cause for error is that ImageMagick is not available.
			$filename = $pdf->generate_filename( 'image', null, 'png' );
			$uploaded = $pdf->save( $filename, 'image/png' );
			if ( ! is_wp_error( $uploaded ) ) {
				$upload_dir = wp_upload_dir();
				update_post_meta( $attachment_id, 'pdf_thumbnail_url', $upload_dir['url'] . '/' . $uploaded['file'] );
			}
		}
	}
	return $metadata;
}

Unfortunately, not all servers have ImageMagick installed. I don’t have it installed locally, and when I went to test on the celloexpressions.com server (hosted by GoDaddy for historical reasons), it wasn’t there. I contacted support and they said I had to upgrade to a newer account, which would involve manually migrating everything (or they could do it for a fee). I’d been wanting to get off of that server for a while anyway, so I took to opportunity to move everything onto one of my existing Bluehost accounts, cleaning up some old stuff that was living on celloexpressions.com in the process. Once I switched the domain over to the new server, everything worked exactly how I had wanted.

Realizing how straightforward it is to create images from PDFs in PHP, and how much room for improvement WordPress has with regards to PDF uploads (both in terms of administration and presentation), I’m going to propose some improvements there for core once I finish this project.

Media & Embeds

In addition to digging into the intricacies of WordPress’ handling of PDFs, I spent some time working on my JavaScript skills to implement previews of uploaded audio and linked videos in the admin. Since I knew I’d be using the plugin at large scale, it was important that the admin UI was as functional and efficient as possible. Audio and video previewing was implemented based on the media wpviews in the main editor. While the result is somewhat hacky and buggy, most of the integration relies on core functions rather than extensive custom logic, and I rarely encountered the bugs in my workflows.

On the front-end, wp_audio|video_shortcode( array( ‘src’ => $url ) ); gives browser-compatible HTML5 audio and video via MediaElement.js. That also gives us a skinned player for YouTube videos that matches the audio player, can be customized with CSS, and seems to reduce the volume of ads. WordPress 4.2 will also add support for skinned Vimeo embeds, and the sheet music library plugin won’t require any changes to support Vimeo and YouTube equally.

In a future update, I plan to explore the possibilities with creating a “collection” of PDFs with the media library, similarly to galleries, audio playlists, and video playlists. If I’m successful with that, it could be used to offer separate files for each part of a piece, instead of requiring all of the parts to be in one PDF (which I manually merge the separate parts into before upload). That could also concievably provide an automated merged PDF file that’s created in PHP, if ImageMagick supports something like that.

Templates

While a custom post type with several custom fields and taxonomies would normally work best with custom theme templates, I wanted the sheet music library to be as theme-compatible as possible. So I implemented default templates for single and archive views by filtering the_content. It works pretty well on a lot of themes, and could look just fine on pretty much any theme with a little custom CSS. For more advanced implementations, custom templates and adding theme support for ‘sheet_music_library’ will do the trick. I also created a shortcode that outputs the table view that I use on the homepage.

Search, taxonomies, archives, etc. all work well with the content filtering. The sheet music post type also supports featured images, so using the theme’s templates ensures that images are still used as intended. In my case, I only use images on a few pieces, and they really stand out in search, taxonomies, and post navigation.

Themes & Design

The plan all along was to go with a WordPress.org theme for the initial roll-out, then come back and do a custom theme specifically for use with the sheet music library plugin. But after exploring tons of potential theme options (while testing the theme compatibility of the plugin), I ended up going with Twenty Fifteen. And I’m liking it so much that I may not even do a child theme (I currently have some custom CSS, but that’s it). While I’m not happy with every component of the theme, the biggest things that made it my choice are its strong, scalable typography and its sticky sidebar functionality. CelloExpressions.com has a global header that’s displayed on all sites in the network, and by having no header and a minimal sidebar for the theme, I was able to keep things simple while still providing means for navigating throughout the site. In fact, I ended up with no menu for the music library, leaving navigation and discovery to search and a widget for each custom taxonomy.

My biggest problems with Twenty Fifteen were lack of color contrast, and excessive whitespace/inefficient use of space in places. For a while I had planned to use Twenty Fourteen, since it provides so much space for navigation and is very space-efficient. But upon further investigation, the only part of the sheet music library requiring more horizontal space is the table view on the homepage, so I just dropped some margins there. The contrast issues were a quick fix with Twenty Fifteen’s custom color options, combined with the dark “global” Cello Expressions header.

I also designed a new logo for myself and Cello Expressions as part of this process. I started out on paper, from doodles that had been done while trying to stay awake during class. As I learn more about graphic design, I’m pleased with my final result, and it works great in vector format. Currently, I’m using it in the header and as the site icon. I’ll use it elsewhere as opportunities arise.

Cello Expressions Logo

Migration & New Content

Once the new plugin was finally complete and I’d settled on using Twenty Fifteen at least initially, I was ready to migrate the 60+ pieces from the old site to the new site and add all of the music from the past two years that never made it into the old system.

Because the old implementation was so bad, and most of the old fields wouldn’t translate cleanly to the new taxonomies for composers, instruments, difficulties, and genres, I had to manually migrate all of the content. This also gave me the opportunity to remove some pieces that weren’t up to my current standards.

I started by moving the entire contents of my old server to the new Bluehost server, renaming the /music/ directory to /music-archive/. Then, once I moved the nameservers, I created a new site in the celloexpressions.com multisite network, at /music/. After putting some text in the homepage and setting up my plugins, I started migrating content.

In the end it took nearly two weeks and countless hours, but I now have 104 pieces in my new sheet music library. About half were migrated from the old library, and the other half are newly-published. At a rough estimate, two-thirds have an audio or video recording, or both. They all have scores, terms in four taxonomies, and publication dates back-dated to when they were created. While it required a colossal effort that’s still not quite complete, this project was very much worth it. And the best part is that all of the work, from the software powering it to the music it contains, is free for anyone to use, in the spirit of open source.

New Plugins: Chromeless Widgets Page and Basic Funding Tracker

I just published two plugins I developed for projects this semester on WordPress.org.

Chromeless Widgets Page plugin iconChromeless Widgets Page offers a quick way to build and iterate on a custom page that’s external to the web portion of a site. I developed it for the USC Annenberg Digital Lounge (where I’m the WordPress Specialist), where we used it to build an events page that’s displayed on large TV screens in our physical space.

Basic Funding Tracker plugin iconBasic Funding Tracker is a widget that displays progress toward a fundraising goal both visually and numerically. It was developed for USC ASCE‘s internal P2, where we’re using it to track sponsorship for our annual conference in April.

Both plugins were cases where the projects required minimal extra effort to write in a way that they could be used more widely. It’s well worth contributing basic plugins with minimal options and niche use-cases back to the community, even if it requires extra time to build the plugin.

Proposed WordPress Customizer Theme-Switching UX

This is a proposal for how theme-switching and theme-installation could be incorporated into WordPress’ Customizer. This will eventually be attempted in some form as a feature-plugin to later be merged into WordPress core. The goal is to soften the distinction between themes and theme options and to make theme switching a fast, streamlined experience built-in with other Customization options in a unified interface.

Themes is a panel, but with backwards-sliding, coming in from the left instead of the right. This implies a new layer of hierarchy above the top-level controls. Switching contexts to the theme-browser is just like switching contexts to a panel, but to exit the themes context, you select a theme. The currently active/currently previewed theme is selected and has an arrow back to the right, to slide back to the top-level controls. All of this sliding can also be triggered by swiping on touch devices.

When a different theme is selected from the theme browser, it instantly slides back to the main panel of top-level controls, but now reflects the controls available in the new theme. This is accomplished by rendering the controls specific to the new theme via ajax and the new customizer sections/panels JS API, and then deleting the controls that were specific to the old theme. This should be doable in a back-compatible way by working some trickery with the existing customizer APIs, caching stuff, and/or leveraging WP-API.

The preview would instantly need to switch to a loading indicator until the front-end re-rendered with the new theme, but that shouldn’t take too long and is unavoidable regardless of the implementation here.

In the theme browser, the add-new-theme functionality would be present via a + new theme tile matching the one in the current interface, and bring up a modal containing the 3.9 pieces of THX. From there, the theme-installer previewer (also containing the theme details) would need to either remain in the (almost-full-screen) modal or open in a new tab that closed on install/close-button-click (or, do a full-screen iframe on top of the customizer and modal with the theme-install-preview, although that might get a bit crazy).

We would need a solution for unsaved changes in previewed themes that are not activated, as theme-specific controls are hidden/removed when previewing another theme.

Prerequisites:

  • JS API for adding and deleting panels, sections, settings, and controls, to complement the existing controls API.
  • Distinction/ability to save changes without publishing and/or the ability to save without activating a new theme. Although, not distinguishing between saving and saving and activating would probably make more sense here.

Three Etudes for Cello Choir

Since the Boulder Cello Project is facing a shortage of accessible, mixed-difficulty-level sheet music, and I’ve been wanting to do more short compositions, I’ve decided to write a series of etudes for cello choir. Each one has a hard one-page limit to keep things well-scoped, and to force my ideas into succinct presentations that could be expanded into full pieces at some point.

Being for cello choir, they’re designed to work best for large groups of cellists (I’d generally consider at least 3 per part to be a good threshold between “ensemble” and “choir”). Being mixed-difficulty-level, they’re most appropriate for groups of cellists with widely differing abilities and musical backgrounds (Boulder Cello Project has adult beginners, professionals, and everywhere in between).

To keep things interesting, I’m attempting to do one etude per day. And to also record each one (multi-tracking so that I can cover every part). So far, it’s going pretty well, other than the every day part. Here’s what I’ve got so far:

Of course, I’ll post them all to my sheet music library once I finally rebuild it to actually take advantage of WordPress.

WordPress 4.0 Customizer API Improvements

I cross-posted much of this post to Make WordPress Core before WordPress 4.0 Beta 1. I’ll be updating this version with more examples throughout the beta period.

WordPress 4.0 features several new additions to the Customizer API (see also Theme Customization API). In this post, I’ll discuss the improvements in detail.

Customizer Panels

The Customizer now includes a new way to group options together: panels. Just like a section is a container for controls, a panel is a container for sections. This was implemented in #27406. In WordPress Core, widget management in the customizer has been consolidated into the “Widgets” panel. Instead of having as many sections as there are widget areas making a mess out of the customization experience, only one widgets section appears alongside the other customizer sections. But when you select it, rather then sliding down like regular sections, it slides over to reveal a new context for the entire customizer controls area. My Menu Customizer project also relies on this new panels functionality, as all menus can be consolidated into one panel. But themes and/or plugins with extensive options may also wish to create their own panels to better organize their controls, so we built an API for customizer panels. The Panels API is easy-to-use and works almost identically to the existing customizer section API. Add a panel with the following, within the customize_register action:

$wp_customize->add_panel( 'panel_id', array(
	'priority' => 10,
	'capability' => 'edit_theme_options',
	'theme_supports' => '',
	'title' => '',
	'description' => '',
) );

As always, only use the arguments where you aren’t using the default values. Note that the panel will not be displayed unless sections are assigned to it. To add a section to a panel, just use the panel id for the new panel argument:

$wp_customize->add_section( 'section_id', array(
	'priority' => 10,
	'capability' => 'edit_theme_options',
	'theme_supports' => '',
	'title' => '',
	'description' => '',
	'panel' => 'panel_id',
) );

You may notice that $wp_customize->add_panel and $wp_customize->add_section have the same arguments (other than panel, of course). This is because panels are a special type of section; technically speaking, WP_Customize_Panel extends WP_Customize_Section. Your sections are backwards-compatible: you can add the panel argument to existing sections without issues. However, you do need to check for the existence of WP_Customize_Manager->add_panel() if you’re maintaining pre-4.0 compatibility. As with Customizer Sections, you can access and modify Panels via:

  • $wp_customize->get_panel( $id );
  • $wp_customize->remove_panel( $id );

New Built-in Customizer Controls

WordPress core now provides support for a much wider array of Customizer controls. Implemented in #28477, these changes eliminate the need to create custom controls for most common use cases. The textarea type is now supported in core. For any type of input that uses an input element, you can simply specify the type attribute using the type parameter of $wp_customize->add_control(). Here’s an example:

$wp_customize->add_control( 'setting_id', array(
	'type' => 'url',
	'priority' => 10,
	'section' => 'title_tagline',
	'label' => 'URL Field',
) );

Which results in the following markup in the Customizer:

<li id="customize-control-setting_id" class="customize-control customize-control-url">
<label>
<span class="customize-control-title">URL Field</span>
<input type="url" value="" data-customize-setting-link="setting_id">
</label>
</li>

This is pretty powerful, as you can now use the built-in WP_Customize_Control for most common use-cases rather than creating a custom control. But what about input types like number and range that require additional attributes like min, max, and step?

New Built-in Customizer Control Parameters

First of all, all of the built-in Customizer controls (including the custom controls such as WP_Customizer_Color_Control) now support descriptions, just like Customizer sections have descriptions (see #27981). This was much-needed and allows for inline help text at the control level. More interestingly, to complement the new support for arbitrary input types, a new input_attrs parameter allows you to add attributes to the input element (also implemented in #28477). This extends beyond just using min, max, and step for number and range, to the ability to add custom classes, placeholders, the pattern attribute, and anything else you need to the input element. Here’s an example:

$wp_customize->add_control( 'setting_id', array(
	'type' => 'range',
	'priority' => 10,
	'section' => 'title_tagline',
	'label' => 'Range',
	'description' => 'This is the range control description.',
	'input_attrs' => array(
		'min' => 0,
		'max' => 10,
		'step' => 2,
		'class' => 'test-class test',
		'style' => 'color: #0a0',
	),
) );

Which results in the following markup in the Customizer:

<li id="customize-control-setting_id" class="customize-control customize-control-range">
	 <label>
		 <span class="customize-control-title">Range</span>
		 <span class="description customize-control-description">This is the range control description.</span>
 <input type="range" min="0" max="10" step="2" class="test-class test" style="color: #0a0;" value="" data-customize-setting-link="setting_id">
	 </label>
 </li>

Which displays as follows (in Chrome 35): customizer-4.0-range-control

The ability to add classes is particularly useful if you need to target specific controls with CSS or JS, but it doesn’t need to have any special markup. I’m using this in the Menu Customizer for the Menu Name field, which is just an ordinary text control with a special setting type.

Contextual Controls

Customizer controls can now be displayed or hidden based on the Customizer’s preview context. For example, options that are only relevant to the front page can be shown only when the user is previewing their front page in the Customizer (see #27993). This is already implemented in core for Widgets; Widgets have always been contextually faded and shown/hidden based on their visibility in the preview, but this functionality is now built off of the core active_callback API in both PHP and JS. There are three different ways to specify whether a given control should only be displayed in a certain context. The first, and most straightforward, is to use the active_callback argument in $wp_customize->add_control().

$wp_customize->add_control( 'front_page_greeting', array(
	'label'      => __( 'Greeting' ),
	'type' => 'textarea',
	'section' =>
	'title_tagline',
	'active_callback' => 'is_front_page',
) );

Note that you may use either built-in conditional functions or a custom function. If you have a custom control (via a subclass of WP_Customize_Control) and a custom callback function, you can skip the active_callback argument and override the active_callback function instead:

class WP_Greeting_Control extends WP_Customize_Control {
	// ...

	function active_callback() {
		return is_front_page();
	}
}

Finally, the customize_control_active filter will override all of the other active callback options and may be a better solution in certain cases (note that this particular example will be avoidable with future work on expanding the Customizer’s JS API, and does not hide the title_tagline section, only the controls in it):

function titletagline_customize_control_active_filter( $active, $control ) {
	if ( 'title_tagline' === $control->section ) {
		$active = is_front_page();
	}
	return $active;
}
add_filter( 'customize_control_active', 'titletagline_customize_control_active_filter', 10, 2 );

In addition to the PHP API for contextual controls, you can override the control-visibility-toggle function on the JS side. By default, controls will slideUp and slideDown as they become visible or hidden when the Customizer preview is navigated. If you’re familiar with the Customizer control JS API (see wp-admin/js/customize-controls.js, and wp.customize.Control), the Widgets implementation of a custom toggle function is a good example:

api.Widgets.WidgetControl = api.Control.extend({
// ...
   /**
    * Update widget control to indicate whether it is currently rendered.
    *
    * Overrides api.Control.toggle()
    *
    * <a href='http://profiles.wordpress.org/param' class='mention'>@param</a> {Boolean} active
    */
    toggle: function ( active ) {
        this.container.toggleClass( 'widget-rendered', active );
    },
// ...
) };

/**
 * Extends wp.customize.controlConstructor with control constructor for widget_form.
 */
$.extend( api.controlConstructor, {
    widget_form: api.Widgets.WidgetControl,
} );

Changes to the customize_update_ and customize_preview_ Actions

You probably already know that the Customizer supports both option and theme_mod types for settings. But did you know that you can register arbitrary types? Since this is generally undocumented, I’ll show how it works (this has been in place since 3.4):

$wp_customize->add_setting( 'setting_id', array(
	'type' => 'custom_type',
	'capability' => 'edit_theme_options',
	'theme_supports' => '',
	'default' => '',
	'transport' => 'refresh',
	'sanitize_callback' => '',
	'sanitize_js_callback' => '',
) );

There are a few actions that you can use to handle saving and previewing of custom types (option and theme_mod are handled automatically). Namely, customize_update_$type and customize_preview_$type are useful here. Previously, the value of the setting was passed to these actions, but there was no context. In 4.0, via #27979, the WP_Customize_Setting instance is passed to these actions, allowing more advanced saving and previewing operations. Here’s an example from my Menu Customizer project:

function menu_customizer_update_menu_name( $value, $setting ) {
...
	// Update the menu name with the new $value.
	wp_update_nav_menu_object( $setting->menu_id, array( 'menu-name' => trim( esc_html( $value ) ) ) );
}
add_action( 'customize_update_menu_name', 'menu_customizer_update_menu_name' );

This part of the Customizer API is a bit too complex to fully explain here, as most of it already existed, but suffice to say that the addition of the setting instance to these actions greatly expands the possibilities of working with custom setting types in the Customizer.

New “customize” Capability

Note: this API component is coming in 4.0 beta 2.

The Customizer has been decoupled from edit_theme_options in favor of a customize meta capability, which is mapped to edit_theme_options by default. This allows for wider use of the Customizer’s extensive capability-access options, which are built into panels, sections, and settings. Additionally, this makes it possible to allow non-administrators to use the customizer for, for example, customizing posts. This change is an important step to expanding the scope of the Customizer beyond themes. See #28605. To allow users with lower capabilities to access the Customizer, use something like the following:

function allow_users_who_can_edit_posts_to_customize( $caps, $cap, $user_id ) {
        $required_cap = 'edit_posts';
        if ( 'customize' === $cap && user_can( $user_id, $required_cap ) ) {
                $caps = array( $required_cap );
        }
        return $caps;
}
add_filter( 'map_meta_cap', 'allow_users_who_can_edit_posts_to_customize', 10, 3 );

Customizer Conditional Function

The new is_customize_preview() conditional function can be used to check whether the front-end is being displayed in the Customizer. The naming derives from the fact that the term “preview” applies to both theme previews and previewing changes before saving them. See #23509 for some sample use-cases from WordPress.com.

Examples

Look at the Widget Customizer and Menu Customizer code for more examples of many of these features. Please feel free to ask in the comments if you have you questions with any of these implementations; I spent a good amount of time preparing and reviewing the associated patches and soliciting feedback in the process of adding these changes to core.

Use This API for Good, not Evil

These new additions to the Customizer API greatly expand the ability to create intricate options for users. But please don’t forget about WordPress’ core philosophies. So, before you go adding entire panels full of new options, remember to strive for simplicity and design for the majority, even in themes and plugins. These additions make the Customizer better for developers; now, let’s make it as good as it can be for our end-users.