diff --git a/core/misc/drupal.js b/core/misc/drupal.js index b1b4125..cbb8870 100644 --- a/core/misc/drupal.js +++ b/core/misc/drupal.js @@ -18,6 +18,21 @@ if (window.jQuery) { "use strict"; /** + * Build the list of behaviors to run. + * + * @param {String} event + * A string with two possible values: 'attach' or 'detach'. + * @param {String} [trigger] + * For a 'detach' event the trigger value detachBehavior was called with. + * + * @return {Array} + * An ordered array of behavior names. + */ + Drupal.behaviorList = function (event, trigger) { + return Object.keys(Drupal.behaviors); + }; + + /** * Custom error type thrown after attach/detach if one or more behaviors failed. * * @param list @@ -71,29 +86,33 @@ if (window.jQuery) { * enables the reprocessing of given elements, which may be needed on occasion * despite the ability to limit behavior attachment to a particular element.) * - * @param context + * @param {DOMElement} context * An element to attach behaviors to. If none is given, the document element * is used. - * @param settings + * @param {Object} settings * An object containing settings for the current context. If none is given, * the global drupalSettings object is used. + * @param {Array} behaviorList + * An list of behavior names to run on the current context. */ - Drupal.attachBehaviors = function (context, settings) { + Drupal.attachBehaviors = function (context, settings, behaviorList) { context = context || document; settings = settings || drupalSettings; - var i, errors = [], behaviors = Drupal.behaviors; + behaviorList = behaviorList || Drupal.behaviorList('attach'); + var errors = []; + var behaviors = Drupal.behaviors; // Execute all of them. - for (i in behaviors) { - if (behaviors.hasOwnProperty(i) && typeof behaviors[i].attach === 'function') { + behaviorList.forEach(function (behaviorName) { + if (behaviors.hasOwnProperty(behaviorName) && typeof behaviors[behaviorName].attach === 'function') { // Don't stop the execution of behaviors in case of an error. try { - behaviors[i].attach(context, settings); + behaviors[behaviorName].attach(context, settings); } catch (e) { - errors.push({behavior: i, error: e}); + errors.push({behavior: behaviorName, error: e}); } } - } + }); // Once all behaviors have been processed, inform the user about errors. if (errors.length) { throw new DrupalBehaviorError(errors, 'attach'); @@ -116,13 +135,13 @@ if (window.jQuery) { * implementation, i.e. .removeOnce('behaviorName'), to ensure the behavior is * detached only from previously processed elements. * - * @param context + * @param {DOMElement} context * An element to detach behaviors from. If none is given, the document element * is used. - * @param settings + * @param {Object} settings * An object containing settings for the current context. If none given, the * global drupalSettings object is used. - * @param trigger + * @param {String} trigger * A string containing what's causing the behaviors to be detached. The * possible triggers are: * - unload: (default) The context element is being removed from the DOM. @@ -140,26 +159,30 @@ if (window.jQuery) { * in them before the form is serialized. The canonical use-case is so * that WYSIWYG editors can update the hidden textarea to which they are * bound. + * @param {Array} behaviorList + * An list of behavior names to run on the current context. * * @see Drupal.attachBehaviors */ - Drupal.detachBehaviors = function (context, settings, trigger) { + Drupal.detachBehaviors = function (context, settings, trigger, behaviorList) { context = context || document; settings = settings || drupalSettings; trigger = trigger || 'unload'; - var i, errors = [], behaviors = Drupal.behaviors; + behaviorList = behaviorList || Drupal.behaviorList('detach', trigger); + var errors = []; + var behaviors = Drupal.behaviors; // Execute all of them. - for (i in behaviors) { - if (behaviors.hasOwnProperty(i) && typeof behaviors[i].detach === 'function') { + behaviorList.forEach(function (behaviorName) { + if (behaviors.hasOwnProperty(behaviorName) && typeof behaviors[behaviorName].detach === 'function') { // Don't stop the execution of behaviors in case of an error. try { - behaviors[i].detach(context, settings, trigger); + behaviors[behaviorName].detach(context, settings, trigger); } catch (e) { - errors.push({behavior: i, error: e}); + errors.push({behavior: behaviorName, error: e}); } } - } + }); // Once all behaviors have been processed, inform the user about errors. if (errors.length) { throw new DrupalBehaviorError(errors, 'detach:' + trigger);