Build a slideshow with Context and RE Context Libraries

Our reason for writing the RE Context Libraries module (see the blog post for more info) was to fully utilize the power of the Context module when creating javascript-dependent features using the Features module. Confused? It's actually quite straightforward. Note that though this post is exclusively concerned with the Drupal 6 versions of the modules concerned, everything it discusses is also possible in Drupal 7.

About features and contexts

In Drupal, a "feature" is nothing more than a module. What makes features interesting and useful—incredibly useful—is that the features module provides a convenient user interface for creating them. With the Features module installed, developers can build and configure a Drupal site using standard components such as views, cck fields and content types, and imagecache presets. This makes it possible, for example, to build a new blog module by creating a blog content type, custom blog cck fields, and views of the blog content type, then exporting the lot as a feature. This exported module can then be placed under version control, and/or re-used on other Drupal projects. Within a feature, the Context module provides very fine-grained control over the display of blocks and other such components. Using the blog example, Context makes it possible to display a view block containing blog categories only on the blog view and on pages of the blog content type.

Javascript enhancement

It's common, on Drupal (and other) websites, for us to 'enhance' content with javascript. For example, we might want to use javascript to turn certain links into videos, to launch an overlay from a link, to arrange content in tabs, a slideshow,  or an 'accordion.' One of the things that unites all of these features (especially the last three) is that they require the page to contain a list of items; in Drupal, such lists are typically created with the Views module. The problem we encountered was that, when making a feature such as a slideshow, we had to include custom code in the feature or add custom code to the website's theme. Neither of these solutions is optimal. In both cases, the custom code required to load the javascript files required by the feature only when the feature is present can quickly become very complex. Moreover, in the second case—where custom code is added to the theme—the javascript-embedding code must then be maintained separately from the feature that relies on it. What we wanted was a way to add javascript libraries using the same context(s) we used to display the views belonging to the feature. Fortunately, the Context module itself is extensible and it's possible to write plugins that extend it. Our module adds a new reaction type to the Context module, "Include libraries". To make a library available for use in Context, it's necessary to register the feature's javascript and/or css files with the RE Context Libraries module. This is accomplished by writing a very short module.

A simple slideshow

To demonstrate the use of the Context Libraries module, we've prepared a feature that relies on a context library module. To build the module and feature—which took about an hour—we went through the following steps:

Build the Context Library module

Like all Drupal modules, a context library module should have a "module_name.module" file and a "module_name.info" file. It must also have a "module_name.install" file. Besides these, a context library module must also contain one or more javascript and css files. The info and install files are extremely straightforward; the real substance of a context library module is the module file—reproduced here in a slightly abbreviated form. But even this file is very basic; it contains a single function that builds on a hook provided by the Context Libraries module (note that our blog may bork some of the code below—use the github version if you want to play with the code!):

/**
 * Implementation of hook_define_re_contextlibraries_library().
 */
function re_clslide_define_re_contextlibraries_library() {
  $path_to_module = drupal_get_path('module', 're_clslide');
  $library = array(
    're_clslide' => array(
      'name' => 'CL Slide (provided by: re_clslide)',
      'css' => array(
        $path_to_module .'/css/re_clslide.css',
      ),
      'js' => array(
        $path_to_module .'/js/jquery.tools.min.js',
        $path_to_module .'/js/re_clslide.js',
      ),
    ),
  );
  return $library;
} // re_clslide_define_re_contextlibraries_library()

Essentially, the module does nothing more than provide paths to the context libraries module. These files are then included in any context where this library is included as a reaction in the Context settings screen. There are a few important points to note about the array of files provided:

  • the key of the top-level array should be named as the module is named to prevent 'collisions' with other context library modules
  • the main array should contain a 'name' key and one or both of the 'css' and 'js' keys shown above
  • the 'js' array typically contains an unaltered library from another source—here, the jQuery Tools library—and a custom javascript file—here, 're_clslide.js—which can be used to invoke the behaviour of the library
  • if the filename of one of the items in the 'js' array is the same as the module name, it can be excluded on the context settings page (check the 'Include Libraries Only' box)
  • files in the 'css' array can be overridden in themes by adding a file with the same name to the theme's info file
  • an array added directly to the 'js' array (without a key) will be included in the Drupal.settings object in the head of the rendered page

Once the library module is complete—test it by enabling it and checking the source code for you included files and/or settings—it's time to build and export the feature.

Build the feature

Building features with Drupal is amply documented elsewhere, but the basic steps were:

  1. build the re_clslide content type, along with a custom field for the image
  2. build the re_clslide view
  3. build the re_clslide_* imagecache presets
  4. export the feature as re_clslide_feature, including dependencies to the items form 1, 2, and 3, and to the re_clslide module (and any other relevant modules such as views, cck and imagecache)

Enable the feature and module

At this point, the slideshow should be about 95% operational. In our feature we've placed the slideshow in a context that targets only the home page and where the view block is located in the header region. Obviously this may not work well if your theme has a header region of a fixed size. If this is the case, just edit the context and put the slideshow block in another region.

Create content

To get from 95% operational to 99% operational, you'll need to create some slides for the slideshow—the content type is 'RE CL Slide'. Create as many as you need, but keep in mind that the slideshow's images are all loaded when the page loads, so don't overdo it.

Customize css and imagecache presets

For the very last 1%, you'll need to customize the css and perhaps the imagecache presets. To customize the css, copy the RE CL Slide module's css file to the root directory of your theme, and add the following line to the theme's info file:

stylesheets[all][] = re_clslide.css

To edit the imagecache preset for the slideshow, first make sure the imagecache_ui module is enabled, and then edit the "re_clslide_slide_view" preset.