Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
JavaScript in Drupal
/**
* @file
* Always start with a brief, one-line description of the script.
*
* If more than one line is needed to describe the script, provide more detailed
* comment text following a blank comment line.
*/
// Use an IIFE (immediately invoked function expression) to encapsulate your
// script from other scripts loaded on the page and to prevent pollution of the
// global namespace.
//
// Always begin the IIFE with a semicolon to prevent unintended consequences
// with script aggregation and compression. Always include the 'undefined'
// parameter for undefined comparisons.
;(function (window, document, $, undefined) {
// Declare all variables used in a function at the top of the function body.
// Variables are scoped to their containing function (or object), not to block
// where they were first declared. There shouldn't be many variables here
// besides the following module variable.
// Implement the Revealing Module pattern. You can call the module whatever
// you'd like to call it. The module should always be referred to throughout
// the entire script by the name you declare here.
//
// The Revealing Module pattern can be seen as "fragile" because the module's
// public methods can't be overridden without breaking the internal function
// references. In theory, this is a bad thing. In practice, the fact that all
// of this is going on within an IIFE means that you'll almost never extend
// your modules in that way because they aren't available outside of the IIFE.
//
// Providing the name of the module for what could be an anonymous function
// seems redundant, but this helps with debugging because any errors will
// reference the module by name.
var myModule = (function myModule() {
// Because of the nature of closures, variables declared at the function
// scope will be private by default, but they may be publicly exposed later.
// Never initialize values here; only declare them.
var privateVariable,
publicVariable;
// Declare all functions as proper functions. These functions have access
// to all module variables and functions. This syntax is simpler and cleaner
// than the equivalent "var privateFunction = function () {}" syntax and is
// functionally identical. It also makes it clear that these functions are
// meant to be called within the module just like normal functions are. In
// the scope of the module, there's nothing at all special about them.
function privateFunction(content) {
// Instead of building HTML structures in the middle of code, use the
// Drupal.theme function or other templating system (e.g. Twig, Mustache).
return Drupal.theme('ExampleThemeFunction', content);
}
// If you need to process DOM nodes as they're added to the document, send
// the context as a parameter.
function publicFunction(context) {
// ...
}
// The init function is the entry point into the module.
function init() {
// Set up everything necessary for this module.
privateVariable = true;
publicVariable = 'some value';
// Actual functionality should be handled in functions.
console.log(privateFunction(publicVariable));
}
// Return an object. All object members will be publicly accessible. Nothing
// new should be defined here. The job of this object is to expose specific
// variable and function members, not to create new functionality. Public
// member names do not need to match their private counterparts, but it's a
// good idea to limit aliasing to avoid confusion.
//
// External name on the left, internal name on the right.
return {
exposedVariable: publicVariable,
process: publicFunction,
init: init
};
}());
// One behavior per script file. Each script should be responsible for doing
// just one thing, and in the simplest way possible. Rely on libraries where
// possible for broader functionality.
Drupal.behaviors.myBehaviorName = {
attach: function (context, settings) {
// The 'once' function is only necessary if you need code to execute code
// when Drupal fires attach functions.
$('body').once('my-behavior-name', function () {
// Initialize the module.
myModule.init();
});
// Anything outside the jQuery.once callback will be called during each
// attach cycle. You should submit the context for each time this code is
// run so the module is aware of what's happening on the page.
myModule.process(context);
}
}
// Put all theme functions at the end of the IIFE in alphabetical order.
Drupal.theme.prototype.ExampleThemeFunction = function (content) {
return '<div class="example">' + content + '</div>';
};
// Always put the invoking parentheses inside the wrapping parentheses. They can
// go inside or outside the wrapping parentheses, but for the sake of a single,
// consistent convention, put them on the inside.
}(this, this.document, jQuery));
// Further Reading:
//
// Immediately-Invoked Function Expression (IIFE):
// http://benalman.com/news/2010/11/immediately-invoked-function-expression/
// Again With the Module Pattern – Reveal Something to the World:
// http://christianheilmann.com/2007/08/22/again-with-the-module-pattern-reveal-something-to-the-world/
// JavaScript Programming Patterns:
// http://www.klauskomenda.com/code/javascript-programming-patterns/
// Learning JavaScript Design Patterns:
// http://www.addyosmani.com/resources/essentialjsdesignpatterns/book/
//
// P.S. Always leave a newline at the end of the file.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.