jQuery coding standards
This documentation needs work. See "Help improve this page" in the sidebar.
Note: Changes to Drupal coding standards are proposed and discussed in issues in the Coding Standards project.
Prefix variables that point to jQuery objects with a dollar sign($)
In any part of your code it should be easy to understand which variables are jQuery objects and which are not.
Incorrect
When assigning a jQuery object to a variable:
var foo = $('.foo');
When assigning a jQuery object to a property:
var object = { bar: $('.bar') };
Correct
When assigning a jQuery object to a variable:
var $foo = $('.foo');
When assigning a jQuery object to a property:
var object = { $bar: $('.bar') };
Avoid compatibility issues
jQuery is evolving quickly but attempts to maintain backward compatibility with previous releases. Although multiple jQuery versions are not officially supported within a single Drupal major release, many sites use the jQuery update module to take advantage of performance and bug fixes offered by newer versions of jQuery. Custom modules using jQuery should keep up to date with syntax best-practices in order to avoid conflicts with updated versions.
Chaining
For chaining selector you can either use CSS method $(' a b > c') or JavaScript chaining $('a').find('b').children('c'). Second method is slightly faster(test). In both cases reduce the weight of selector(if possible). In case .children() and .find() will return the same results, use .find() method (test).
Incorrect
this.$el
.find('.contextual-links')
.prop('hidden', !isOpen);
Correct
this.$el.find('.contextual-links')
.prop('hidden', !isOpen);
Event Delegation
Every event (e.g. click, mouseover, etc.) in JavaScript “bubbles” up the DOM tree to parent elements. This is incredibly useful when you want many elements to call the same function. Instead of binding an event listener function to all of them, you can bind it once to their parent, and have it figure out which node triggered the event.
In examples of jQuery code, you may often see events simply return false;
to prevent the default behavior of that event. This type of prevention is often misused and also prevents the "bubbling" propagation of the event. This effect is not always desired. If you wish to either prevent the default behavior or stop propagation, they should be explicitly defined.
Incorrect
$('.item').click(function(event) {
...
// Calls both event.preventDefault() and event.stopPropagation().
return false;
});
Correct (Drupal 7)
$menus.delegate('.item', 'click', function(event) {
...
// Prevents the default behavior (ie: click).
event.preventDefault();
// Prevents propagation (ie: "bubbling").
event.stopPropagation();
});
Correct (Drupal 8)
$menus.on('click', '.item', function(event) {
...
// Prevents the default event behavior (ie: click).
event.preventDefault();
// Prevents the event from propagating (ie: "bubbling").
event.stopPropagation();
});
Functions
Separate your functions into individual functions and call them when needed.
Incorrect
// Can be called only on click.
$('.btn').click( function() { ... });
Correct
// Can be called anywhere.
function clickFunction() { ... };
$('div').click( function() {clickFunction() });
Context
Always try to give your selectors a context. The default context will search the entire page's DOM. If the context is a cached selection, use find().
Incorrect
// This has no context and is very slow.
var $element = $('.element');
Improved
// Search only in #sidebar.
var $element = $('.element', '#sidebar');
Correct
var $sidebar = $('#sidebar');
var $element = $sidebar.find('.element');
Using #id or .class
Finding elements by the tag ID is much faster (test) than by class name. If your target element appears on the page only once, select it by #id. In case when you have more than one, use class but descend from an #id. See the above context code examples.
jQuery.attr()
This applies only for D6 and D7 because D8 will ship with jQuery 1.9+ which instead uses .prop() for property.
Wrong use of .attr is the cause of the many compatibility problems. Use booleans to set a property, not an empty string. Also, do not assume that property values that are returned are always booleans. .attr('checked')
could return either true
or 'checked'
depending on jQuery version and markup.
Incorrect
$element.attr('disabled', '');
if ($element.attr('checked') === true) { ... }
Correct
$element.attr('disabled', false);
$element.attr('disabled', true);
if ($element.attr('checked')) { ... }
jQuery.each()
This method is indeed very powerful (and appropriate) when dealing with existing instantiated jQuery objects and the need to iterate on them.
It is often misused when needing to iterate over simple native JavaScript arrays or objects. Using native JavaScript for
loops are 300-1000 times faster than jQuery.each() (test).
Incorrect
var array = [ ... ];
$.each(array, function(i, item) { ... });
Correct
var array = [ ... ];
var i;
for (i = 0, len = array.length; i < len; i += 1) {
var element = array[i];
}
Help improve this page
You can:
- Log in, click Edit, and edit this page
- Log in, click Discuss, update the Page status value, and suggest an improvement
- Log in and create a Documentation issue with your suggestion