JavaScript♥Drupal – Adding JavaScript to pages – Writing JavaScript



JavaScript♥Drupal – Adding JavaScript to pages – Writing JavaScript

1 1


dcmtl-javascript

"JavaScript ♥ Drupal" for DrupalCamp Montréal 2013

On Github pbuyle / dcmtl-javascript

JavaScript♥Drupal

by Pierre Buyle

Adding JavaScript to pages

  • Include a JavaScript file on every pages of the site.
    scripts[] = awesomeness.js
  • Include JavaScript on a page.
    drupal_add_js($data, $options)
  • Attach JavaScript to a renderable array.
    $element['#attached']['js'][] = array($data => $options)

scripts[] in .info files

scripts[] = awesomeness.js
  • Add the referenced files on every page
  • Files are processed (aggregated) and cached
  • Not very flexible but good enough

drupal_add_js()

Add JavaScript to the currently rendered page.

drupal_add_js('path/to/awesomeness.js', 'file')
drupal_add_js('alert("Awesome!");', 'inline');
drupal_add_js(array('myAwesomeModule' => array(
    'foo' => 'bar',
    'bar' => 'foo',
)), 'setting');
drupal_add_js('//aweso.me/ness.js', 'external');

$options

drupal_add_js('path/to/awesomeness.js', array(
  'type' => 'file',
  'scope' => 'footer',
  'group' => 'JSTHEME',
  'weigth' => '-10',
  'preprocess' => TRUE,
  'every_page' => TRUE,
  'defer' => TRUE,
  'cache' => FALSE,
));

#attached

Attach JavaScript to a renderable array.

$element['#attached']['js'][] = array($data => $options);
Invoke drupal_add_js($data, $options) when $element is rendered.
$element['#attached']['js'][] = array('path/to/awesomeness.js', 'file')
$element['#attached']['js'][] = array('alert("Awesome!");', 'inline');
$element['#attached']['js'][] = array(array('myAwesomeModule' => array(
    'foo' => 'bar',
    'bar' => 'foo',
)), 'setting');
$element['#attached']['js'][] = array('//aweso.me/ness.js', 'external');

Writing JavaScript

Things to known and use when writing JavaScript for Drupal

  • jQuery.noConflict
  • Drupal.behaviors
  • jQuery.once
  • Drupal.settings
  • Drupal.theme
  • Drupal.t

jQuery.noConflict

  • $ is not the jQuery object.
  • Code should be wrapped in an Immediately Invoked Function Expression.
    (function($) {
      // Here $ is the jQuery object
    })(jQuery);
  • Variables are kept out of the global scope.

Drupal.behaviors

Replace $(document).ready() to process elements.

Drupal.behaviors.doSomething = {
  attach: function(context, settings) {
    // do something here
Also used when element are removed, moved or serialized.
  }
  detach: function(context, settings, trigger) {
    // do something here too
  }
}
Attach and detach behavior altering the DOM
Drupal.attachBehaviors(context, [settings])
Drupal.detachBehaviors(context, [settings], [trigger])

jQuery.once

  • Behaviors could be applied multiple times on the page.
  • Avoid processing the same elements multiple time.
$('div.something', context).once('do-something');

Drupal.settings

Passing values from PHP to Javascript

drupal_add_js(
  array('myAwesomeModule' => array(
    'foo' => 'bar',
    'bar' => 'foo',
  )
), 'setting');
Drupal.settings.myAwesomeModule.foo;
Drupal.settings.myAwesomeModule.bar;
Drupal.behaviors.doSomething = {
  attach: function(context, settings) {
    settings.myAwesomeModule.foo
  }
}

Summary

(function($) {
  Drupal.behaviors.doSomething = {
    attach: function(context, settings) {
      $('div.something', context).once('do-something').doSomething({
        foo: settings.myAwesomeModule.foo,
        bar: settings.myAwesomeModule.bar
      });
    }
  }
})(jQuery);

Drupal.theme

Theme functions in JavaScript.

Dupal.theme.prototype.awesome = function(str) {
  return '<span class="awesome">' + str + '</span>';
}
var html = Drupal.theme('awesome', 'Hello World');
Dupal.theme.awesome = function(str) {
  return '<div class="awesome">' + str + '</div>';
}

Drupal.t

Translate strings to the page language or a given language.
Drupal.t(str, args, options)

And friends

  • Format a string containing a count of items.
    Drupal.formatPlural(count, singular, plural, args, options)
  • Replace placeholders with sanitized values in a string.
    Drupal.formatString(str, args)
  • Encode special characters in a plain-text string for display as HTML.
    Drupal.checkPlain(str)

JavaScript Libraries

Writing re-usable JavaScript with dependencies management.

A library defines a set of JavaScript files

/**
 * Implements hook_library().
 */
awesome_library() {
  return array(
    'awesomeness' => array(
      'title' => 'Awesome Library',
      'website' => 'http://aweso.me/',
      'version' => '1.0.0'
      'js' => array('full/path/to/awesome.js' => array()),
and/or CSS files
      'css' => array('full/path/to/awesome.css' => array()),
optionally using settings
      'js' => array(array('type' => 'setting', 'data' => $settings)),
and optionally requiring another library
      'dependencies' => array(
        array($module, $library),
      )
    ),
  )
}

Using a library

drupal_add_library($module, $library)
$element['#attached']['library'][] = array($module, $library)

Libraries bundled with Drupal core

Third party libraries

How to use and manage third party libraries.

Library API

http://drupal.org/project/libraries
  • Keep libraries out in site/<domain>/libraries.
  • The same library can be shared by more than one site.
  • Ease the process of upgrading a module that requires an external library.
  • Prevent incompatibilities due to having the same library installed more than once in different versions.
  • Dependency handling.
  • Library version detection.
  • Runtime control of library availability.

Declaring a 3rd party library

/**
 * Implements hook_libraries_info()
 */
function awesome_libraries_info() {
  return array(
  'awesome' => array(
    'name' => 'Awesome Library',
    'vendor url' => 'http://aweso.me',
    'download url' => 'https://github.com/awesome/awesomejs/zipball/latest',
    'version arguments' => array(
      'file' => 'package.json',
      'pattern' => '/"version": "(.*)"/',
    ),
    'files' => array('js' => array('awesome.min.js')),
  );
);

Libraries API and hook_library()

/**
 * Implements hook_library()
 */
function awesome_library() {
  $libraries = array();
  if (($library = libraries_detect('awesome')) && $library['installed']) {
    $libraries['awesome'] = array(
      'title' => $library['name'],
      'website' => $library['vendor url'],
      'version' => $library['version'],
      'js' => array(
        library['library path'] . '/' . $library['files']['js'][0]
      )
    );
  }
  return $libraries
}

The end

(function($) {
  Drupal.behaviors.doSomething = {
    attach: function(context, settings) {
      $('div.something', context).once('do-something').doSomething({
        foo: settings.myAwesomeModule.foo,
        bar: settings.myAwesomeModule.bar
      });
    }
  }
})(jQuery);

References

drupal_add_library()#attached and drupal_process_attached() hook_library Libraries API