Skip to content

Latest commit

 

History

History
141 lines (115 loc) · 4.78 KB

1.2-javascript-jquery.md

File metadata and controls

141 lines (115 loc) · 4.78 KB

Javascript/jQuery

Javascript is a very large subject matter, and the presumption is that you understand at least the bare essentials to take the certification exam, and there are plenty of places to learn Javascript online. As such the notes for this section will just cover Drupal-related Javascript topics.

One change from Drupal 7 to Drupal 8, is that jQuery is no longer automatically loaded. This means jQuery must be manually pulled in as a dependency. There are examples of that below.

Adding Javascript Libraries

Theme and module Javascript should be loaded in using asset libraries (i.e. *.libraries.yml files where * is the name of the theme or module).

Local Javascript Libraries

Suppose you have a theme named mytheme, which needs to include the following Javascript files:

fancy-ui-tabs.js
fancy-ui-accordion.js
fancy-ui-tables.js (dependent on underscore and jQuery)

It would follow that you would create mytheme.libraries.yml with the following contents:

fancy-ui:
  version: 1.x
  js:
    js/fancy-tabs.js: {}
    js/fancy-accordion.js: {}
fancy-ui-tables:
  version: 1.x
  js:
    js/fancy-tables.js: {}
  dependencies:
    - core/underscore
    - core/jquery

External Javascript Libraries

Though it can be problematic for performance and security reasons, there are times when you will need to load external Javascript into your site.

For example loading AngularJS via a CDN, from Adding stylesheets (CSS) and JavaScript (JS) to a Drupal 8 theme:

angular.angularjs:
  remote: https://github.com/angular
  version: 1.4.4
  license:
    name: MIT
    url: https://github.com/angular/angular.js/blob/master/LICENSE
    gpl-compatible: true
  js:
    https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js: { type: external, minified: true }

Attaching Javascript

Once libraries have been defined, they need to be attached where they are needed.

Attaching to All Pages

To attach Javascript to all pages:

Under the libraries: section of mytheme.info.yml:

libraries:
  - 'mytheme/global-styling'
  - 'mytheme/bootstrap-scripts'
  - 'mytheme/fancy-ui'

Attaching to a Subset of Pages

You can use hooks to add conditionally.

For example, to only load on nodes (skipping other entities), add the following function to your mytheme.theme file.

function mytheme_preprocess_node(&$variables) {
  $variables['#attached']['library'][] = 'mytheme/fancy-tables';
}

Or if you only want to load on the maintenance page:

function mytheme_preprocess_maintenance_page(&$variables) {
  $variables['#attached']['library'][] = 'mytheme/fancy-tables';
}

Drupal.behaviors

Instead of using $(document).ready(function() {}), as is common in jQuery development, it is better to make use of Drupal.behaviors as it will ensure code runs on normal page loads, ajax calls and inside BigPipe.

Example from Javascript API Overview:

Drupal.behaviors.myBehavior = {
  attach: function (context, settings) {
    // Using once() to apply the myCustomBehaviour effect when you want to do just run one function.
    $(context).find('input.myCustomBehavior').once('myCustomBehavior').addClass('processed');

    // Using once() with more complexity.
    $(context).find('input.myCustom').once('mySecondBehavior').each(function () {
      if ($(this).visible()) {
          $(this).css('background', 'green');
      }
      else {
        $(this).css('background', 'yellow').show();
      }
    });
  }
};

attach() is called once the DOM has loaded for all Drupal.behaviors properties, both on the initial page load, and any subsequent ajax calls.

Closures

Since Drupal's implementation of jQuery uses jQuery.noConflict(), it is also considered good practice to wrap your custom Drupal javascript inside of a closure like this:

(function ($, Drupal) {
  Drupal.behaviors.myModuleBehavior = {
    ...
  };
})(jQuery, Drupal);

Additional Resources