Comment empêcher les fonctions attachées au comportement d'être attachées deux fois?

11

J'ai un comportement qui s'ajoute onà certaines cases à cocher.

(function($) { 
  Drupal.behaviors.mymodule = {
    attach: function (context, settings) {

      $('.skip-line', context).on('change', function(){
        // some code
        if ( confirm(Drupal.t('Apply to all languages?')) ) {
          // applying...
        }
      });
    }
  };
})(jQuery);

Cela fonctionne très bien, mais les cases à cocher sont dans la partie chargée par AJAX. Si je recharge cette partie du formulaire, en cliquant dessus, la fenêtre de confirmation apparaît deux fois. Maintenant, je sais que je peux tester la fonction inside si c'est la première fois d'affilée qu'elle est appelée, mais je préférerais m'assurer qu'elle n'est ajoutée à mon élément qu'une seule fois, et donc appelée qu'une seule fois. Comment puis je faire ça?

Mołot
la source

Réponses:

20

La once()fonction vous y aidera, par exemple

(function($) { 
   Drupal.behaviors.mymodule = {
    attach: function (context, settings) {

      $('.skip-line', context).once('mymodule').on('change', function(){
        // some code
        if ( confirm(Drupal.t('Apply to all languages?')) ) {
          // applying...
        }
      });
    }
  };
})(jQuery);

Une des nombreuses références

Clive
la source
2
Merci. A fonctionné comme un charme. Je suppose que c'est l'un de ces moments où je ne demande tout simplement pas à Google correctement. J'ai demandé de prévenir deux fois et d' éviter plusieurs . Si seulement j'avais demandé à le faire une fois ...
Mołot
1
@ Mołot Mais grâce à l'indexation de votre commentaire, je l'ai trouvé lorsque j'ai cherché à prévenir plusieurs :-D
frazras
7

Vous devez utiliser la fonction once () pour y parvenir. De cette page

Drupal.behaviors.myModule = {
  attach: function (context, settings) {
    $('element', context).once('myModule', function () {
     // any behavior is now applied once
    });
  }
};

La chaîne "myModule" passée à la fonction est définie comme un marqueur sur les éléments correspondant à la sélection jQuery, donc la prochaine fois qu'elle est appelée, elle les ignore. N'utilisez pas la même chaîne si vous appelez la fonction once plusieurs fois à des fins différentes, sinon vous risquez de vaincre son objectif.

Alfred Armstrong
la source
Merci pour votre explication :) Accepté la réponse de Clive car son code a fonctionné directement pour moi et vous ne l'avez pas fait, mais j'aime mieux votre description.
Mołot
1

Voici un exemple qui se développe sur la réponse frazras:

var searchPagesFoundationAccordionInit = false;
Drupal.behaviors.searchPagesFoundationAccordionInit = {
  attach: function (context, settings) {
    // Attempt to resolve behavior being called multiple times per page load.
    if (context !== document) {
      return;
    }
    if (!searchPagesFoundationAccordionInit) {
      searchPagesFoundationAccordionInit = true;
    }
    else {
      return;
    }

    // Check if component exists.
    if ($('.view-style--search-page .search-section__sidebar .accordion').length > 0) {
     // Code here.
    }
  }
};
gelée masquée
la source
Cette solution a fonctionné pour moi. Je n'ai pas besoin de lier un élément à l'action. Je dois exécuter juste une fonction. Drupal.behaviors.checkOnce = { attach: function (context, settings) { if (context === document) { check(); } function check() { //code } } };Dans ce cas, la check()fonction ne fonctionnera qu'une seule fois, lorsque le contexte sera undocument
Vadim Sudarikov
0

vous pouvez aussi le faire aussi:

(function ($, Drupal, drupalSettings) {
    'use strict';
Drupal.behaviors.someThing = {
        attach: function (context) {
            if (context === document) {
               console.log('called inside'); // Once <-- 
            }
            console.log('called outside'); // can be manny manny  <-- 
         },
    };
})(jQuery, Drupal, drupalSettings);
taggartJ
la source