SLB 2.0: Beta 7

Rise of the API

By Sol in Lab

Simple Lightbox 2.0 is coming along nicely. It’s been in beta for a while, but thanks to our brave testers, it has improved by leaps and bounds in each release.

Beta 7 is a turning point for SLB in multiple ways.

Git Out

SLB has recently been migrated over to Git, which I’m very happy about. Among other things, Git facilitates a workflow that allow easy experimentation and fast iteration. Working on new features is far more controlled and manageable as a result.

SLB’s entire Git repository has also been published on GitHub. GitHub makes it easy to collaborate on projects using things like forking and pull requests. I initially published SLB’s Master branch to give users easy access to new releases. Later, I bit the bullet and also published SLB’s Development branch. It’s a little uncomfortable putting my raw code out there for you to see, but it’s ideal for anyone who wants to test the bleeding edge or wants to get involved in development.

All of this was actually possible since Beta 5; the big difference starting with Beta 7 is that I’ve optimized my workflow so that I can prepare releases far more easily. For example, Beta 7 has been released, but it’s not done. There are several new features planned for this phase, but I did not want to wait until they were all done before you had access to them. As a result, Beta 7 is being released in multiple stages. Once a new feature is done, it’s heading out into the big world for all to test it. Young features are impatient– they don’t want to wait for their brother and sister features to be ready.

What this means for you: More frequent updates. (Why didn’t you just say that? Geez.)

Content Handlers

One of the major features of SLB 2.0 is support for multiple content types. Why should images have a monopoly on lightboxes? What about videos, forms, and even tweets?

SLB 2.0 was built from the ground up to support multiple content types, and Beta 7 provides an API for developers to add support for any type of content quickly and easily.

What this means for you: Any type of content can be displayed in a lightbox. (Didn’t I just say that? Really…)

Even SLB’s default content types (e.g. images) use the new Content Handler API:

$handlers->add('image', array(
    'match'         => 'match_image',
    'client_script' => 'handler.image.js'
));

Match

The match property specifies the callback function used to determine if a link matches this content type. The callback does not have to be anything fancy; for example, here’s the callback to match image links:

/**
 * Matches image URIs
 * @param string $uri URI to match
 * @return bool TRUE if URI is image
 */
public function match_image($uri) {
    return ( $this->util->has_file_extension($uri, array('jpg', 'jpeg', 'jpe', 'jfif', 'jif', 'gif', 'png')) ) ? true : false;
}

Client Script

The client_script property specifies a JavaScript file to load in the browser for client-side functionality. This controls things such as how the content is rendered in the lightbox.

The file path provided in client_script is relative to WordPress’ plugins directory.

The client script code needs to return an object which is added to the content handler. Here’s the client script for images:

(function($) {
return {
    render: function(item) {
        var dfr = $.Deferred();
        //Create image object
        var img = new Image();
        var type = this;
        //Set load event
        var handler = function(e) {
            //Save Data
            item.set_data(this);
            //Set attributes
            var dim = {'width': this.width, 'height': this.height};
            item.set_attribute('dimensions', dim);
            //Build output
            var out = $('<img />', {'src': item.get_uri()});
            //Resolve deferred
            dfr.resolve(out);
        };

        //Attach event handler
        if ( img.addEventListener ) {
            img.addEventListener('load', handler, false);
        } else if ( img.attachEvent ) {
            img.attachEvent('onload', handler);
        } else {
            handler(img);
        }
        //Load image
        img.src = item.get_uri();
        //Return promise
        return dfr.promise();
    }
}
})(jQuery)

Register

All that’s left is to register the new content type at the appropriate time:

/**
 * Add custom content handler(s)
 * @param object $handlers Content Handlers
 */
public function my_custom_content_handler($handlers) {
    $handlers->add('handler-id', array (
        'match'         => 'match_callback',
        'client_script' => 'path-to-handler/handler.handler-id.js'
    ));
}

//Hook into content handler initialization
add_action('slb_content_handlers_init', 'my_custom_content_handler');

That’s all there is to it! When links are processed on the server, the registered content handlers are cycled through until a match is found and assigned to the link. To make things as fast as possible, only the content handlers that have been matched to a link will be loaded into the browser.

Priorities

Content handlers can also be prioritized so that a handler can be evaluated before other handlers. For example, if you wanted to create a custom handler for Flickr images, then you would want links to be matched against this handler before the standard image content handler.

Setting a content handler’s priority is easy and follows the example of WordPress’ own add_action()/add_filter() functions. That is, by default, all handlers have a priority of 10. If a handler should be evaluated earlier, use a lower number (e.g. 1-9). Conversely, if a handler should be evaluated later, use a higher number (e.g. 11+). All content handlers with the same priority will be evaluated in the order that they were registered.

Basically, content handlers are added like so:

$handlers->add($id, $properties, [$priority]);

Here’s an example of registering a content handler with a high priority:

/**
 * Register content handler for Flickr images
 * @param object $handlers Content Handlers
 */
public function register_flickr_handler($handlers) {
    $args = array (
        'match'         => 'match_flickr',
        'client_script' => 'path-to-handler/handler.flickr.js'
    );
    $handlers->add('flickr', $args, 5);
}

//Hook into content handler initialization
add_action('slb_content_handlers_init', 'register_flickr_handler');

The Content Handler API is quite robust and new handlers can easily be added to SLB!

Template Tags

Template tags also get a shiny new API in this update. Adding your own template tags is now easier than ever.

$template_tags->add('tag-name', array(
    'client_script' => 'path-to-file/tag.tag-name.js'
));

Client Script

Like content handlers, template tags have a client_script property that specifies the JavaScript file that will be loaded in the browser to handle a template tag’s client-side functionality. This controls how a template tag is rendered in the browser.

The file path provided in client_script is relative to WordPress’ plugins directory.

The code in this file returns an object which is added to the template tag. Here’s the client script for the {{item}} template tag:

(function($) {
return {
    render: function(item, tag) {
        var dfr = $.Deferred();
        var m = 'get_' + tag.get_prop();
        var ret = ( this.util.is_method(item, m) ) ? item[m]() : item.get_attribute(tag.get_prop(), '');
        if ( this.util.is_promise(ret) ) {
            ret.done(function(output) {
                dfr.resolve(output);
            });
        } else {
            dfr.resolve(ret);
        }
        return dfr.promise();
    }
}
})(jQuery);

Register

Once the client script is ready, all that’s left is to register the new content type at the appropriate time:

/**
 * Add custom template tag(s)
 * @param obj $tags Template tags collection
 */
public function my_custom_template_tags($tags) {
    $tags->add('mytag', array(
        'client_script' => 'path-to-file/tag.mytag.js'
    ));
}

//Add hook to register custom template tags
add_action('slb_template_tags_init', 'my_custom_template_tags');

If that seemed really simple, that’s because it is! In-depth documentation on how to develop custom template tags is forthcoming, but the focus for this release was getting the API in order. Thankfully, the work done the content handler API made this pretty simple to do and much of the code is shared between these APIs.

Themes

The Theme API has also been updated to align with the other component APIs in this release.

$themes->add('theme-id', array (
    'name'          => 'Theme Name',
    'parent'        => 'parent-theme',
    'layout'        => 'path-to-file/layout.html',
    'client_script' => 'path-to-file/client.js',
    'client_style'  => 'path-to-file/style.css',
));

Name

The name property defines the theme’s display name. The name is displayed in the theme selection list.

Parent

Themes can optionally have a parent that they inherit the properties of. This makes customizing existing themes incredibly simple. For example, if you want to update the CSS of SLB’s default theme (ID: slb_default), you would simply add a new theme, but only define the client_style parameter:

$themes->add('my-child-theme', array (
    'name'          => 'My Child Theme',
    'parent'        => 'slb_default',
    'client_style'  => 'path-to-file/my-style.css',
));

Layout

The layout is a file that contains the HTML for the theme’s lightbox. The layout contains standard HTML and template tags that control how an item’s data is displayed when viewed in the lightbox.

Client Script

Like the other components, themes have a client_script property that specifies the JavaScript file that will be loaded in the browser to handle a theme’s client-side functionality. This controls a theme’s capabilities such as animations, etc.

The file path provided in client_script is relative to WordPress’ plugins directory.

Client Style

Finally, the client_style property specifies a CSS file for the theme.

Just like the client_script property (and all other file paths in these APIs), the file path provided in client_style is relative to WordPress’ plugins directory.

Register

Theme’s are registered just like other components:

/**
 * Add custom theme(s)
 * @param obj $themes Themes collection
 */
function my_custom_theme($themes) {
    $themes->add('theme-id', array (
        'name'          => 'Theme Name',
        'parent'        => 'parent-theme',
        'layout'        => 'path-to-file/layout.html',
        'client_script' => 'path-to-file/client.js',
        'client_style'  => 'path-to-file/style.css',
    ));
}

//Add hook to register custom theme
add_action('slb_themes_init', 'my_custom_theme');

Simple!

Get the Beta

Want to get access to the next generation of Simple Lightbox and be part of its progress? Get the beta now and leave feedback!

Next Steps

SLB 2.0 Beta 7 was a big update. Simple Lightbox 2.0 is now feature complete and from here we’re going to move straight into release candidates.