Category Archives: Tutorial

Adding a JavaScript/CSS Library to Drupal with the Libraries API

Let’s say we found a useful bit of JS or CSS that we’d like to use within our Drupal site.  For example, this jQuery ListNav Plugin.  An ideal way to accomplish this is by adding it to Drupal’s Library API.  Here’s how to do it.

First, make sure you have the Libraries API module installed and enabled.

Next, we’re going to write a custom module that implements hook_libraries_info() to add our custom library to Drupal’s set.

The jquery_listnav.info file:

and the hook_libraries_info() implementation within jquery_listnav.module:

First, we create a new $libraries array and then define a key => value pair within $libraries for our new library.  The key is the name of our new library within Drupal’s eyes — in our case it’s “jquery-listnav”.  The value is another array of information about our new library.

We’ve defined the following bits of info about our library:

  • name
  • vendor_url
  • download_url
  • version_arguments (which is itself yet another array)
  • files (which is itself yet another set of multi-dimensional arrays)

The former three (name, vendor_url, and download_url) are pretty self-explanatory but let’s dig into the latter two.

The ‘version arguments’ key tells Drupal where it can find information about the library’s version.

The ‘file’ key points Drupal to where the file is located.  In this case, since our library is only one file, the version is contained therein.  If your library consists of many different JS and/or CSS files, you may have an .info file which contains the version data or it may be in only one of the files.

The ‘pattern’ key is a regex expression that tells Drupal how to find the version of the library (if any exists).

The ‘lines’ (optional) key tells Drupal the maximum number of lines to search for the aforementioned regex.  It defaults to 20 so if you know your version is always on line 1 (say, in a minified version of the code in question), you can save some cycles by specifying such here.

Next, the ‘files’ key is the crucial data point as it tells Drupal where to find the files that should be included in this library.

The ‘js’ key is yet another array that contains the file names of JS files to include in this library.  We’ve packaged the JS file in the same directory as our module but it could easily be in the theme itself.

The ‘css’ key is the same as the ‘js’ key but for CSS files.

There are quite a few more available keys in the $libraries array definition including declaring dependencies and utilizing external libraries.  You can read more about them on the Drupal 7 API Reference page for hook_libraries_info().

Finally, one last thing I’d like to cover is how to load a library and add it to a specific page.

I’d like this library to load on all displays of a specific view named ‘directory’.  So in my template.php file in my theme, I implement theme_views_pre_render() and create an if-block for that case.

Then I call:

to load the library we created earlier.  Now that that JS is available, I call drupal_add_js() to run the pertinent JS function.

Sometimes we’ll want a library loaded and available on all views, or all pages.  In that case, you could employ the same tactic but remove the if-block from the theme_views_pre_render() call.  You could even do it in something like hook_init().

Creating A Subtheme From Open Atrium 2.6x’s oa_basetheme

Last month, Open Atrium released one of their largest upgrades since version 2.  Included in this upgrade is a complete revamp of the theme layer.  You can read more about the changes in 2.6 here: A Fresh New Look for Atrium.

There is some documentation on creating a subtheme from oa_radix, OpenAtrium 2.5’s base theme but, unfortunately, the documentation for subtheming 2.6’s base theme, oa_basetheme, hasn’t been created by the maintainers just yet.

We’re trying to get this upgrade out to our users ASAP so, today, I spent some time fiddling with creating a new subtheme for Open Atrium 2.6x.  In this tutorial, we’ll go over what I’ve found:

The oa_basetheme comes with bootswatch and, using Drush, we are supposedly able to install an ‘instant subtheme’ by executing:

There are various options for this command, if you’d like to provide a machine name or use a different bootswatch theme.  You can find these options by running:

So, from my site’s directory (sites/default), I tried to run:

and was presented with

This issue had been reported on d.o, but that thread lead to no results.

Creating a Subtheme

After some finagling and trial-and-error, I was able to get the starter subtheme created by performing the following steps:

  1. Copy oa_basetheme from “docroot/profiles/openatrium/themes” to my site’s theme directory, “docroot/sites/default/themes”:
  2. Enable the theme with Drush:
  3. Browse to Appearance Config (/admin/appearance) and select Set As Default for oa_basetheme.
  4. Run the oa_basetheme bootswatch starter Drush command:

    No errors this time!  I’m honestly not sure if the resolution was the fact that I moved oa_basetheme from the Open Atrium profile to sites/default or the fact that I set oa_basetheme as the Default theme.  I’m inclined to think the fix was the latter since the error was a Bootswatch conflict with oa_radix, but, alas, I have yet to actually confirm this.

    This will put the new subtheme in “docroot/sites/all/themes”.  If you don’t need it in /sites/all, be sure to move it to /sites/default.

  5. Browse to Appearance Config (/admin/appearance) and select Set as Default for the original theme from Step 3.
  6. Remove the copy of oa_basetheme from your site’s theme directory

Now, if you have a fresh install of OpenAtrium 2.6x, you can go ahead and “Enable and Set as Default” directly from Appearance Config (/admin/appearance) and you’ll be good to go!

Upgrading from 2.5x to 2.6x?

However, if you, like me, are upgrading an existing OpenAtrium site from 2.5x to 2.6x, there are a few more steps you need to take to enable all the new features of the theme.

  1. Enable the Open Atrium Site Layout Defaults module.  This is a module that ships with OA 2.6x and contains the default panels config required for the new functionality in the new 2.6x theme.

    This will also enable dependencies: oa_site_layout and panels_everywhere
  2. Go ahead and Enable your new subtheme in Appearance Config (/admin/appearance) but do not Set As Default just yet.
  3. The OA base theme’s panel layout is defined in a Page called site_template for the Panels Everywhere module, however, out of the box, it’s configured to be used only when the current theme is either oa_theme or oa_basetheme.Since we have a new subtheme, we need to update the selection rules for the pertinent Variant within that Page to use the Variant for our new subtheme as well.  Sooo… browse to /admin/structure/pages/nojs/operation/site_template/handlers/site_template__atrium-modern/criteria” (or go to Admin > Structure > Pages > Edit site template Tab > Selection Rules)
  4. Under the Criteria Table, select “Current theme” from the drop down and click the “Add” button.

     Selection Rules config page of the Modern layout Variant
    On the Selection Rules config page of the Modern layout Variant, select “Current theme” and click the “Add” button
  5. Select your new subtheme from the dropdown menu and click the “Save” button.

    Theme selection while adding a new Selection Rule to the Modern layout Variant
    Select your new subtheme and click the “Save” button
  6. Click the “Update and Save” button at the bottom of the Variant Options for the Default site template page.

    Screenshot of adding a new selection rule to a variant
    Once your new selection rule has been added, click “Update and Save” on the Variant modal.
  7. Finally, go back to Appearance Config (/admin/appearance) and select Set as Default for your new subtheme.
  8. Clear caches and you’re all set to start working on the theme’s code itself.

One more thing… Regarding Concurrent Themes

We are currently planning to deploy our new subtheme to a subset of users: a beta group.

This requires keeping our existing theme from 2.5x enabled and using ThemeKey and ThemeKey User Profile (packaged with the ThemeKey module) to allow users to “opt-in” to the new theme.

To accomplish that, forego Step 7 of the previous list, leaving your old 2.5x theme as Default and your new subtheme simply Enabled.  Follow these steps to install and configure ThemeKey and ThemeKey User Profile.

  1. Install and enable ThemeKey and ThemeKey User Profile
  2. Browse to the UI Settings for ThemeKey (/admin/config/user-interface/themekey/settings/ui), expand the Selectable Themes table and check the checkbox for your old 2.5x theme and your new 2.6x subtheme.
  3. In the UI Settings table, select “Add theme option to user profile”.
  4. Click the “Save configuration” button.
  5. Browse to User Permissions configuration page, and ensure the permission: “Select different theme” is enabled for your required roles (in most cases, authenticated user).  Or, add the permission to the role with Drush:

Now when a user browses to their Edit Profile page, they’ll be presented with a field to select the theme to use.

Screenshot of Edit Profile page including ThemeKey User Profile selection table
A user can select which theme to use on their Edit Profile page

How to Add a Custom Shortcode to Drupal 7

We recently received a request to embed some JavaScript for a live chat client into multiple pages within our site.  The live chat service provided the JS code snippet to our team along with the ID key we would need to use within the snippet to link the client on our pages with the live-chatters on the other side.  There were also a few settings that could be changed within the snippet — things like background color, offset width, and location on the page.

Since we do not allow JavaScript tags within our WYSIWYG editor, we couldn’t just ask our Content Managers (CMs) to copy/paste the snippet right into the Body (or other) field.  We also didn’t want to be called upon everytime the script needed to be embedded on a different page or when the ID key changed due to a new marketing campaign (or any other reason).  We decided to use Shortcodes.

Shortcodes are little bits of code that, when parsed in a field that allows them, expand to a pre-defined output, replacing any pre-defined variables in the expansion.

For a quick example, a shortcode for embedding a link to Google may be:

When that string is parsed in a shortcode-enabled field, it might render as:

This is useful because, if the link to Google were to ever change, any number of instances of the shortcode can be updated all at once by one modification to the Shortcode code.

As I mentioned, Shortcodes can also take variables.  For example:

might expand to

This tutorial requires the contrib module Shortcode.  We’ll write a custom module to extend its functionality and add a new shortcode. Here’s how to do it.

First, let’s create a module.  I’ll call mine “tmbridge_custom_shortcodes” and, thus, create a directory, tmbridge_custom_shortcodes, in my custom modules directory and two files, tmbridge_custom_shortcodes.module and tmbridge_custom_shortcodes.info, in that directory.

I won’t speak to writing the info file in this post, but you can refer to this page on d.o for more information.

The first thing we need to do in this new module is name and describe our new shortcode and indicate the callback functions it will use:

We need to define the variables (or attributes) for our new shortcode.  We do this by implementing hook_theme():

Next, let’s define our callback function for the new shortcode.  This callback function takes the variables as defined by the user in the shortcode’s use in the WYSIWYG editor and applies any business logic, formatting, or modification (like setting a default, if empty):

Now, we need to define the theme function that our process callback function calls.  In this case, it’s simply ‘shortcode_friendly_alert’.  This theme function returns the output of the shortcode with the variables replaced.  Here’s where the magic of this module happens.  You can put literally any markup you wish into this function’s output and populate as many variables within it with user-defined data (this means you could get data from any Drupal object that’s in scope, as well).  It could be JavaScript (including AJAX functionality), CSS, output from other theme functions (blocks, views, etc.), Or… just run of the mill HTML markup.

In this tutorial, we’re just using some (really) basic JS and HTML to make the point, but I really want to drive home the wide breadth of functionality one could implement herein.

Finally, let’s define our tip callback.  This function outputs text below the WYSIWYG editor that tells the user what the shortcode is used for and shows the user what parameters are available.

And that’s it for the code!  Simply enable the module and be sure to remember to enable the new shortcode in all the Text Formats you’d like it available within (/admin/config/content/formats).  The available shortcodes are listed in the vertical tab “Shortcodes” under “Filter Settings:

Enabling Shortcode in Text Format Settings
Be sure to enable your new Shortcode in the Text Format settings

You will then see your new shortcode available in all fields that use those Text Formats.

Your new shortcode is now available in all WYSIWYG fields that use those Text Formats.
Your new shortcode is now available in all WYSIWYG fields that use those Text Formats.