Comment contrôler l'ordre des comportements Drupal.be?

9

Je veux que le code JavaScript du module X ne s'exécute qu'après l'exécution de celui du module Y. Quelle est la meilleure façon de procéder?

cam8001
la source

Réponses:

5

Le code JavaScript utilisé par Drupal 7 est le suivant:

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 utilise un code similaire:

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

Si JavaScript garantit que les propriétés d'objet / tableau sont toujours parcourues dans le même ordre qu'elles sont ajoutées, alors les valeurs seront transmises de jQuery.each()la fonction utilisée comme second paramètre dans le même ordre qu'elles sont insérées dans le tableau passé en tant que premier paramètre.
Cela signifierait que le premier comportement inséré dans Drupal.behaviorsest exécuté en premier.
Dans ce cas, pour permettre aux comportements définis par votre module d'être exécutés en premier, vous pouvez utiliser un poids plus léger pour cela. Si vous voulez qu'ils soient exécutés avant les autres, le poids du module doit être réglé sur -50; d'autres valeurs peuvent également fonctionner. Si vous utilisez Drupal 7, drupal_add_js ()permet d'associer un poids au code JavaScript; Le code JavaScript avec un poids plus léger apparaît en premier dans la sortie HTML. Ce n'est pas possible avec Drupal 6, pensa-t-il.

JavaScript ne garantit pas que les propriétés sont parcourues dans le même ordre qu'elles sont ajoutées. Cela signifie que différentes implémentations JavaScript présenteraient les mêmes propriétés en utilisant un ordre différent; cela signifie également que le même ordre peut changer dans différentes versions du même navigateur.

kiamlaluno
la source
J'ai trouvé une fois une page répertoriant le poids utilisé par certains modules. Je ne me souviens pas de l'URL de cette page, et si la page ne comprenait que des modules particuliers, ou si elle était exhaustive. Si je trouve cette page, je signalerai ici le lien.
kiamlaluno
1
Vous pouvez toujours simplement vérifier dans la table système - essayezselect name, weight from system where type = 'module' order by weight ASC, name
cam8001
Malheureusement, j'ai besoin que le PHP (mymodule) de mon module s'exécute avant le PHP de l'autre module (vertical_tabs), mais que le JS de mon module s'exécute après le js de vertical_tab. Existe-t-il un moyen purement basé sur javascript de pondérer les comportements?
cam8001
@ cam8001: Je le sais, mais cela signifierait que vous devriez installer tous les modules, pour connaître le poids plus léger utilisé par un module. La page que j'ai trouvée répertorie les poids des modules, et cela peut être utile lorsque vous devez savoir quel poids vous devez attribuer à votre module à exécuter avant chaque module. Je sais, vous pourriez simplement utiliser un poids extrêmement léger, mais vous utiliseriez un poids plus léger que nécessaire.
kiamlaluno
@ cam8001: Dans ce cas, il n'y a aucun moyen d'accomplir ce que vous essayez de faire, si ce n'est de modifier l'ordre des objets contenus dans Drupal.behaviors; comme je l'ai signalé $.each(Drupal.behaviors)répertorie les objets dans le même ordre dans lequel ils sont insérés, sans se baser sur leur identifiant.
kiamlaluno
5

Utilisez le module Pondérations comportementales .
(Veuillez lui donner quelques tests avant de l'utiliser sur un site de production)

Le module permet d'attacher des poids aux comportements, puis il détourne / remplace drupal.attachBehaviorspar une implémentation personnalisée, qui respecte les poids.


Pourquoi ne pas moduler le poids à la place, comme suggéré dans l'autre réponse?

  • le poids du module est un outil assez lourd. Il s'applique à toutes les implémentations de hook (php) et comportements (js) du module, alors que nous ne sommes intéressés que par un seul comportement.
  • l'ordre des propriétés dans un objet js n'est pas garanti par la spécification (bien qu'il soit implémenté comme vous vous en doutez dans presque tous les navigateurs).

Voir
L'ordre des champs dans un objet javascript est-il prédictible lors de leur boucle? et
Ordre des éléments - pour (… dans…) boucle en javascript .

don Quichotte
la source
@kiam, Si j'en fais un module "comportement pondéré" ("bewgt") sur drupal.org, vous joindriez-vous en tant que co-responsable? Ce sera probablement un module assez petit, mais probablement mieux que de le laisser expédié avec autre chose. J'ai un exemple d'implémentation localement pour D6, semble fonctionner.
donquixote
viens de le faire .. vous êtes toujours invité :)
donquixote
drupal.org/node/1302126 - J'espère que ce sera dans le noyau en D8 :)
donquixote
Ce serait un module intéressant, mais je dois d'abord mettre à jour le code de certains de mes modules, pour lesquels je n'ai pas écrit de ligne de code depuis des siècles. Après cela, je pourrais être libre de co-développer un nouveau module.
kiamlaluno
Je dis simplement que les gens demandent des cas d'utilisation. drupal.org/node/1302126#comment-5911632
donquixote
0

Pour Drupal 6 -

Une solution simple, si cela n'a pas besoin d'être portable, est de placer le JS que vous souhaitez exécuter en dernier dans le fichier theme template.php. Les appels du thème drupal_add_js sont toujours appelés après les modules.

S'il a besoin d'être portable, la solution la plus "propre" de drupal 6 est d'ajouter un nouveau module qui a un poids différent de votre module avec le php. Vous pouvez même avoir les deux modules dans le même dossier, rendre le premier module dépendant du premier et ajuster les poids dans les crochets d'installation / mise à jour. Aucun n'est nécessaire, facilite simplement l'installation.

mirzu
la source