Como impedir que funções associadas ao comportamento sejam anexadas duas vezes?

11

Eu tenho um comportamento que adiciona ona algumas caixas de seleção.

(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 muito bem, mas as caixas de seleção estão na parte carregada em AJAX. Se eu recarregar essa parte do formulário, clicar nelas fará o pop-up de confirmação duas vezes. Agora, eu sei que posso testar a função interna se for a primeira vez consecutiva que é chamada, mas eu preferiria garantir que ela seja adicionada ao meu elemento apenas uma vez e, portanto, chamada apenas uma vez. Como eu posso fazer isso?

Mołot
fonte

Respostas:

20

A once()função ajudará nisso, por exemplo

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

Uma das muitas referências

Clive
fonte
2
Obrigado. Funcionou como um encanto. Acho que é um desses momentos em que simplesmente não consigo perguntar ao Google corretamente. Eu perguntei sobre prevenção duas vezes e prevenção múltipla . Se ao menos eu ter perguntado sobre a fazê-lo uma vez ...
MOLOT
11
@ MOLOT Mas graças ao seu comentário que está sendo indexado, eu achei quando eu procurei para Prevenir :-D múltiplas
frazras
7

Você precisa usar a função once () para conseguir isso. A partir desta página

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

A string "myModule" passada para a função é definida como um marcador nos elementos correspondentes à seleção do jQuery; portanto, na próxima vez que for chamada, os ignorará. Não use a mesma string se você chamar a função outrora várias vezes para propósitos diferentes; caso contrário, poderá anular seu objetivo.

Alfred Armstrong
fonte
Obrigado pela explicação :) Aceitou a resposta de Clive, pois o código dele funcionava diretamente para mim e você não, mas eu gosto mais da sua descrição.
Mołot
1

Aqui está um exemplo que se expande nas respostas às 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
fonte
Esta solução funcionou para mim. Não preciso vincular algum elemento à ação. Eu tenho que executar apenas uma função. Drupal.behaviors.checkOnce = { attach: function (context, settings) { if (context === document) { check(); } function check() { //code } } };Nesse caso, a check()função será executada apenas uma vez, quando o contexto for umdocument
Vadim Sudarikov
0

você também pode fazer isso:

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