One Javascript, Many Drupals…

If you've ever written a Javascript library for Drupal then you may know the pain of updating for each new version of Drupal, beginning with basic confusion about how Javascripts are supposed to behave in Drupal, then dealing with subtle changes in Drupal 7, and lately the stringent requirements to simply build a working Drupal 8 module. It's not a lot of fun.

As it happens I just finished my first Drupal 8 release of the FancyZoom module, so I've been dealing with these issues for a while. I finally decided to make the FancyZoom script universal as I was putting together both the Drupal 7 and 8 versions. It seemed pointless to make more than one download package, and yet also it seemed pointless to make a connector script inside the module separate from the remotely-hosted download script. In the long run, having a connector may be the better course for Javascripts that are meant to be hosted on a remote site (e.g., like jQuery is hosted at Google). FancyZoom checks whether Drupal is installed, and if not it just falls back to manual behavior.

Here's the script in the flesh:

// (1)
if (typeof Drupal !== 'undefined') {
  // (2)
  var isDrupal5 = (typeof Drupal.behaviors === 'undefined'),
    isDrupal7 = (typeof Drupal.formatString !== 'undefined'),
    isDrupal8 = (typeof drupalSettings !== 'undefined');

  // (3)
  if (isDrupal5) Drupal.behaviors = {};

  if (isDrupal7) {
    // (4)
    Drupal.behaviors.fancyzoom = {
      attach: function (d, settings) { FancyZoom.setupZoom(d, settings.fancyzoom); }
    }
  }
  else {
    // (5)
    Drupal.behaviors.fancyzoom = function (d) { fzSetupZoom(d); };
    if (isDrupal5) $(Drupal.behaviors.fancyzoom(document));
  }
}

So what's going on here?

  1. Check if we're in a Drupal environment. If so, then:
  2. Figure out which major version of Drupal is installed.
  3. If Drupal 5 is installed then we create the Drupal.behaviors object. If Drupal 7 (or 8) is installed then:
  4. create a D7/D8 behavior, taking a DOM context and a settings object. For D6 or D5:
  5. create a D6-style behavior, and for D5 set the behavior to execute when the document is ready.