Jak zapobiec dwukrotnemu dołączaniu funkcji związanych z zachowaniem?

11

Mam zachowanie, które dodaje się ondo niektórych pól wyboru.

(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);

Działa bardzo dobrze, ale pola wyboru znajdują się w części załadowanej do AJAX. Jeśli ponownie załaduję tę część formularza, kliknięcie ich spowoduje dwukrotne wyświetlenie potwierdzenia. Teraz wiem, że mogę przetestować funkcję wewnętrzną, jeśli jest wywoływana po raz pierwszy, ale wolałbym upewnić się, że jest dodana do mojego elementu tylko raz, a zatem wywoływana tylko raz. Jak mogę to zrobić?

Mołot
źródło

Odpowiedzi:

20

once()Funkcja pomoże z tym, na przykład

(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);

Jedna z wielu referencji

Clive
źródło
2
Dzięki. Działa jak urok. Myślę, że to jeden z tych momentów, kiedy po prostu nie pytam właściwie Google. Zapytałem o zapobieganie dwa razy i zapobieganie wielokrotności . Gdybym tylko zapytał o zrobienie tego raz ...
Mołot
1
@ Mołot Ale dzięki zaindeksowaniu Twojego komentarza znalazłem go, gdy szukałem opcji zapobiegania wielokrotności :-D
frazras
7

Aby to osiągnąć, musisz użyć funkcji once (). Z tej strony

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

Ciąg „myModule” przekazany do funkcji jest ustawiany jako znacznik na elementach pasujących do wyboru jQuery, więc przy następnym wywołaniu ignoruje je. Nie używaj tego samego ciągu, jeśli wywołujesz funkcję raz wiele razy w różnych celach, w przeciwnym razie możesz pokonać jej cel.

Alfred Armstrong
źródło
Dziękuję za wyjaśnienie :) Zaakceptowałem odpowiedź Clive'a, ponieważ jego kod działał bezpośrednio dla mnie, a ty nie, ale bardziej podoba mi się twój opis.
Mołot
2

Oto przykład, który rozwija się w odpowiedzi na 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.
    }
  }
};
maskedjellybean
źródło
To rozwiązanie działało dla mnie. Nie muszę łączyć jakiegoś elementu z akcją. Muszę uruchomić tylko funkcję. Drupal.behaviors.checkOnce = { attach: function (context, settings) { if (context === document) { check(); } function check() { //code } } };W takim przypadku check()funkcja będzie działać tylko raz, gdy kontekstem będziedocument
Vadim Sudarikov
1

możesz też to zrobić:

(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
źródło
Świetnie, to działa dla mnie
Mahtab Alam