Drupal - How can I control the order of Drupal.behaviors?

The JavaScript code used by Drupal 7 is the following:

Drupal.attachBehaviors = function (context, settings) {
  context = context || document;
  settings = settings || Drupal.settings;
  // Execute all of them.
  $.each(Drupal.behaviors, function () {
    if ($.isFunction(this.attach)) {
      this.attach(context, settings);
    }
  });
};

Drupal 6 uses similar code:

Drupal.attachBehaviors = function(context) {
  context = context || document;
  if (Drupal.jsEnabled) {
    // Execute all of them.
    jQuery.each(Drupal.behaviors, function() {
      this(context);
    });
  }
};

If JavaScript would guarantee that object/array properties are always traversed in the same order they are added, then the values would be passed from jQuery.each() to the function used as its second parameter in the same order they are inserted in the array passed as first parameter.
This would mean that the first behavior inserted in Drupal.behaviorsis executed first.
In this case, to allow the behaviors defined by your module to be executed first you could use a lighter weight for it. If you want they are executed before the other ones, the module weight should be set to -50; other values can work too. If you are using Drupal 7, drupal_add_js() allows to associate a weight to the JavaScript code; JavaScript code with a lighter weight appears first in the HTML output. This is not possible with Drupal 6, thought.

JavaScript doesn't guarantee that properties are traversed in the same order they are added. This means that different JavaScript implementations would present the same properties using a different order; it also means that the same order could change in different versions of the same browser.


Use the Behavior Weights module.
(Please give it some testing before you use it on a production site)

The module allows to attach weights to behaviors, and then it hijacks/replaces drupal.attachBehaviors with a custom implementation, that does respect the weights.


Why not module weight instead, as suggested in the other answer?

  • module weight is quite a heavy tool. It applies to all hook implementations (php) and behaviors (js) of the module, while we are only interested in one single behavior.
  • the order of properties in a js object is not guaranteed by the spec (although it is implemented as-you-would-expect in almost all browsers).

See
Is the order of fields in a javascript object predicatble when looping through them? and
Elements order - for (… in …) loop in javascript.

Tags:

Javascript