¿Cómo evitar que las funciones relacionadas con el comportamiento se unan dos veces?

11

Tengo un comportamiento que se agrega ona algunas casillas de verificación.

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

Funciona muy bien, pero las casillas de verificación están en la parte cargada de AJAX. Si vuelvo a cargar esa parte del formulario, hacer clic en ellos hace que aparezca la ventana emergente de confirmación dos veces. Ahora, sé que puedo probar la función interna si se llama por primera vez en una fila, pero preferiría asegurarme de que se agregue a mi elemento solo una vez y, por lo tanto, solo se llame una vez. ¿Cómo puedo hacer eso?

Mołot
fuente

Respuestas:

20

La once()función ayudará con eso, p. Ej.

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

Una de las muchas referencias.

Clive
fuente
2
Gracias. Trabajado como un encanto. Supongo que es uno de estos momentos cuando simplemente no le pregunto a Google correctamente. Pregunté sobre prevenir dos veces y prevenir múltiples . Si solo hubiera preguntado sobre hacerlo una vez ...
Mołot
1
@ Mołot Pero gracias a que tu comentario fue indexado, lo encontré cuando busqué prevenir múltiples :-D
frazras
7

Necesita usar la función once () para lograr esto. De esta página

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

La cadena "myModule" que se pasa a la función se establece como un marcador en los elementos que coinciden con la selección jQuery, por lo que la próxima vez que se llame se ignorará. No use la misma cadena si llama a la función de una sola vez varias veces para diferentes propósitos, de lo contrario puede anular su propósito.

Alfred Armstrong
fuente
Gracias por su explicación :) Aceptó la respuesta de Clive ya que su código funcionó para mí directamente y no lo hizo, pero me gusta más su descripción.
Mołot
1

Aquí hay un ejemplo que se expande en la respuesta de 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
fuente
Esta solución funcionó para mí. No necesito vincular algún elemento con la acción. Tengo que ejecutar solo una función. Drupal.behaviors.checkOnce = { attach: function (context, settings) { if (context === document) { check(); } function check() { //code } } };En este caso, la check()función se ejecutará solo una vez, cuando el contexto será undocument
Vadim Sudarikov hace
0

también puedes hacer esto:

(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
fuente