ColouRandom

Introducing ColouRandom, a child theme of Twenty Sixteen.

I came across this post by Chris Coyier the other day, Building Concentric Circles with Nice Color Palettes For Fun and Science. In it the author explained how (among other things) to use the website COLOURlovers to get random color palettes in order to create a set of colored concentric circles. This inspired me to build a similar functionality into a WordPress theme.

At first I thought to create a brand new theme from scratch. But I didn’t have a solid design in mind, just the idea that I wanted the theme to be able to have a random color palette applied. Fortunately, the latest default theme, Twenty Sixteen, has multiple color theme functionality built in. The default themes are built for learning from, for hacking apart and creating something awesome, so I felt this was a perfect starting point.

Calling the COLOURlovers API

Building the request in JavaScript to get a result from the COLOURlovers API was the easy part, as it turned out. Here is the base url, which requests one result from the most popular color palettes:

http://www.colourlovers.com/api/palettes/top?format=json&numResults=1

This alone won’t do, though, because as Chris mentions in his blog post, COLOURlovers doesn’t set CORS headers on their API responses. He went the route of using crossorigin.me to bypass this, but I decided that I didn’t want to involve two services where one would do. Since cross-domain requests wouldn’t work with JSON, I had to use JSONP. COLOURlovers supports this, if I added a jsonCallback parameter:

http://www.colourlovers.com/api/palettes/top?format=json&numResults=1&jsonCallback=_callback

The query will always result in the top pick, though, and I want this randomized. So I appended a random number (between 1 and 200, so we’re still picking from the top). I’m using jQuery’s ajax() function, since jQuery is bundled with WordPress. I have to specify the data type as “jsonp,” not “json,” and use the same value for the callback as I specified in the call to COLOURlovers’ API.

var rand = Math.floor(Math.random() * (200 - 1)) + 1;
var url = 'http://www.colourlovers.com/api/palettes/top?format=json&numResults=1&jsonCallback=_callback&resultOffset=' + rand;
jQuery.ajax({
    url: url,
    crossDomain: true,
    dataType: 'jsonp',
    jsonpCallback: '_callback',
    success: function(data, status, xhr) {
        if (data.length != undefined && data.length > 0) {
            if ( data[0].colors != undefined ) {
                var colors = data[0].colors;
                // do stuff with color palette
            }
        }
    },
    error: function(xhr, status, error) {
        alert('There was a problem getting a color palette.');
    }
});

Integrating with the WordPress theme

My Twenty Sixteen child theme only consists of four files: style.css, functions.php, customizer.php, and color-scheme-control.js.

The stylesheet only has one line, aside from the meta info allowing WP to recognize it as a child theme of Twenty Sixteen.

@import url('../twentysixteen/style.css');

The functions include isn’t much more; since child themes inherit their parent’s functions, I just need to make sure to call any new files. In my case, that’s my own Customizer settings:

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

It’s in this Customizer file where things get interesting. I need to add to the customize_register action, but I don’t need to redefine all the settings that Twenty Sixteen already has set up; I just need to add the new setting for getting the randomized color palette.

function colourandom_customize_register( $wp_customize ) {
    $wp_customize->add_setting( 'randomize_color_scheme', array(
        'transport'      => 'postMessage',
    ) );

    $wp_customize->add_control(
        'randomize_color_scheme',
        array(
            'label'    => __( 'Randomize Color Scheme', 'colourandom' ),
            'section'  => 'colors',
            'settings' => 'randomize_color_scheme',
            'type'     => 'checkbox',
            'priority' => 1,
        )
    );
}
add_action( 'customize_register', 'colourandom_customize_register', 11 );

I want to say something about the above code. You’ll notice that I’m setting up the trigger for getting a random color as a checkbox. Ideally, it would be a button, but I could not get a custom button to trigger a function via postMessage. So I opted for using a checkbox control, and I styled it using the customize_controls_print_styles action. The checkbox itself is hidden, and the label is styled to look like a WP admin button.

#customize-control-randomize_color_scheme label {
    position: relative;
    display: inline-block;
    text-decoration: none;
    font-size: 13px;
    line-height: 26px;
    height: 28px;
    margin: 0;
    padding: 0 10px 1px;
    cursor: pointer;
    border-width: 1px;
    border-style: solid;
    -webkit-appearance: none;
    -webkit-border-radius: 3px;
    border-radius: 3px;
    white-space: nowrap;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    color: #555;
    border-color: #ccc;
    background: #f7f7f7;
    -webkit-box-shadow: 0 1px 0 #ccc;
    box-shadow: 0 1px 0 #ccc;
    vertical-align: top;
}
#customize-control-randomize_color_scheme label.dashicons-before::before {
    position: absolute;
    left: 100%;
    margin-left: 10px;
    margin-top: 3px;
}
#customize-control-randomize_color_scheme input[type="checkbox"] {
    display: none;
}

The last bit was to enqueue the script to handle calling the COLOURlovers API. For this part, I did have to copy the source of color-scheme-control.js from Twenty Sixteen wholesale — the existing functionality of selecting a predefined color scheme was broken until I did. The core of that script, though — the code that applied a set of five colors to the background, page background, link color, text color, and secondary text color — was exactly what I needed to apply the retrieved color palette from the API call. (It just so happens that COLOURlovers palettes are also five colors, a happy accident indeed.) So I moved that code into a function of its own, which I call both on the dropdown list’s change event and in the success() function of my ajax call.

With the API call working and the color palette being applied to the theme, the functionality I was looking for was working fine. But depending on the connection speed and the response time of the COLOURlovers API, there was a delay between when the user clicks the “button” (checkbox :p) and the actual application of the received color palette. It needed something which would tell the user that it was waiting. A loading spinner, perhaps, like this:

Fortunately, this is something that WordPress also bundles into the admin: namely, the Dashicons icon font. So on clicking the “button,” I apply the classes dashicons-before and dashicons-loading.

The dashicons-before class is a utility class, which defines any element’s ::before pseudo-element as a usable icon. Then I just need the proper icon, and that’s the update icon.

jQuery('#customize-control-randomize_color_scheme label').addClass('dashicons-before dashicons-update');

By default, the icon displays inline to the left of the element. With a little extra CSS, though, I had it displaying just to the right outside the button.

#customize-control-randomize_color_scheme label.dashicons-before::before {
    position: absolute;
    left: 100%;
    margin-left: 10px;
    margin-top: 3px;
}

There was just one more problem. The loading icon didn’t spin. So I added a keyframe (with vendor prefixes, not shown here for simplicity’s sake) and class to use it:

@keyframes spin {
    0% {
        transform: rotate(0deg);
    }
    100% {
        transform: rotate(359deg);
    }
}
.dashicons-before.dashicons-spin::before {
    animation: spin 2s infinite linear;
}

The animation has to be applied to the ::before pseudo-element, or it will spin the whole button.

So now, adding the dashicons-spin class allows the icon to spin.

jQuery('#customize-control-randomize_color_scheme label').addClass('dashicons-before dashicons-update dashicons-spin');

Then in the ajax call’s complete() function, I remove the dashicons classes. Done and done.

In conclusion

I had a lot of fun with this little side project. It’s been my first real foray into writing client-side WP Customizer code, and I learned quite a bit writing code to extend existing theme functionality. (Supporting someone else’s code is always tricky, even code as well-documented as Twenty Sixteen.) If you feel anything I’ve written in this project can be improved, please let me know in the comments here or in the Github project.

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Related