uma - w3schools javascript reference html dom events




Como fazer a função onclick executar apenas uma vez? (5)

Manipuladores e ouvintes de eventos

Existem três maneiras * de registrar um evento em um elemento. Os exemplos a seguir mostram como registrar o evento click em um link com a classe .once **, que chama a função test() quando acionada.

  1. Ouvinte de evento (recomendado)
    • document.querySelector('.once') .addEventListener ('clique', teste); `
  2. Atributo no evento ( não recomendado)
    • <a href='#/' class='once' 'onclick='test()'> >Click</a>
  3. Propriedade no evento
    • document.querySelector('.once') .onclick = test; `

* Consulte manipuladores de eventos do DOM para obter detalhes
** .once classe .once não é relevante para o # 2

Problemas

O OP ( O riginal P ost) tem um ouvinte de evento (veja o número 1 acima) registrando um evento de clique na tag <body> e um atributo no evento (veja o item 2 acima) registrando o evento de clique em um <div> . Cada um chama uma função (também conhecida como função de retorno de chamada) chamada klikaj() que é redundante. Clicar no corpo (que normalmente está em qualquer lugar) não é útil quando você pretende que o usuário clique em uma div. Se o usuário clicar em qualquer lugar, exceto o div , klikaj() será chamado. Se o usuário clicar na div, klikaj() será chamado duas vezes. Sugiro que você remova os dois manipuladores de eventos e os substitua por:

UMA.

document.getElementById('thumb0').addEventListener("click", klikaj);

Observe que o klikaj não tem parênteses () porque o navegador interpreta () como executar a função agora, e não quando o usuário aciona o evento registrado (consulte os itens 1 e 3 acima). Se um manipulador de eventos tiver instruções adicionais e / ou funções de retorno de chamada, uma função anônima deve ser envolvida e a sintaxe normal se aplica:

B.

document.getElementById('thumb0').addEventListener("click", function(event) { 
  klikaj();
  console.log('clicked');
});

Uma alternativa mais limpa é adicionar linhas extras na definição da função de retorno de chamada e registrar eventos como #A.

Solução

Basta adicionar a seguinte instrução como a última linha de klikaj() :

this.style.pointerEvents = "none";

Isso tornará a tag clicada não clicável. Aplicado ao código OP, deve ser assim:

<div id="thumb0" class="thumbs">Thumb 0</div>
<script>
  function klikaj(event) {
    gtag('event', 'first-4', {
      'event_category' : 'cat-4',
      'event_label' : 'site'
    });
    this.style.pointerEvents = "none";   
  }

  document.getElementById('thumb0').addEventListener("click", klikaj);
</script>

Demo

A seguinte demonstração tem dois links:

  1. .default - um link normal registrado para o evento click que, quando acionado, chama test()

  2. .once - um link registrado para o evento click que, quando acionado, chama test() e torna o link impossível de clicar.

function test() {
  console.log('test');
}

document.querySelector('.default').onclick = function(e) {
  test();
}

document.querySelector('.once').onclick = function(e) {
  test();
  this.style.pointerEvents = 'none';
}
<a href='#/' class='default'>Default</a><br>
<a href='#/' class='once'>Once</a>

Eu tenho esse código para o Google analytics em um botão. Eu preciso que ele seja executado apenas uma vez, para que o usuário não possa alterar as estatísticas pressionando o botão várias vezes. Tentei soluções de tópicos semelhantes, mas eles não funcionam. Por favor ajude. Este é o meu código.

<script>
    function klikaj(i) {
        gtag('event', 'first-4', {
            'event_category' : 'cat-4',
            'event_label' : 'site'
        });
    }

    document.body.addEventListener("click", klikaj(i), {once:true})
</script>


<div id="thumb0" class="thumbs" onclick="klikaj('rad1')">My button</div>

Basta usar uma variável flag e configurá-la na primeira execução:

var handlerExecuted = false;
function clickHandler() {
  if (!handlerExecuted) {
    console.log("call gtag() here");
    handlerExecuted = true;
  } else {
    console.log("not calling gtag() function");
  }
}
document
  .getElementById("thumb0")
  .addEventListener("click", clickHandler);
<div id="thumb0" class="thumbs">My button</div>

Uma variação avançada que usa fechamentos e pode ser usada em vários botões:

function clickHandlerFactory() {
  var handlerExecuted = false;
  return function() {
    if (!handlerExecuted) {
      console.log("call gtag() here");
      handlerExecuted = true;
    } else {
      console.log("not calling gtag() function");
    }
  }
}
[...document.querySelectorAll(".thumbs")].forEach(function(el) {
  el.addEventListener("click", clickHandlerFactory());
});
<div id="thumb0" class="thumbs">Button 1</div>
<div id="thumb1" class="thumbs">Button 2</div>


Há um problema com a maneira como você está tentando anexar sua função de manipulador. A função klikaj(i) retorna undefined portanto você está anexando indefinida ao botão. Se você deseja executar o klikaj(i) quando o botão é clicado, coloque-o dentro de um fechamento como este:

const button = document.querySelector('button')
const i = 10
function klikaj(i) {console.log('clicked once')}

button.addEventListener('click', () => { klikaj(i) }, {once: true})
<button>Hello world</button>

Se o navegador não suportar o {once: true} você poderá simulá-lo usando:

const button = document.querySelector('button')
const i = 10
function klikaj(i) {console.log("clicked once")}

function clickOnceHandler(event) {
  klikaj(i)
  event.currentTarget.removeEventListener('click', clickOnceHandler)
}

button.addEventListener('click', clickOnceHandler)
<button>Hello world</button>


Remova o atributo onclick no seu botão e registre o ouvinte via JavaScript, como você tentou:

<div id="thumb0" class="thumbs"
  style="border: 1px solid; cursor: pointer; float: left">
    My button
</div>
<script>
    function klikaj(i) {
        console.log(i);
    }
    document.getElementById('thumb0')
        .addEventListener("click", function(event) {
            klikaj('rad1');
        }, {once: true});
</script>

Se o seu navegador não suportar a opção { once: true } , você poderá remover o ouvinte de eventos manualmente:

<div id="thumb0" class="thumbs"
  style="border: 1px solid;cursor: pointer;float:left">
    My button
</div>

<script>
    function klikaj(i) {
        console.log(i);
    }
    function onClick(event) {
      klikaj('rad1');
      document
        .getElementById('thumb0')
        .removeEventListener("click", onClick);
    }
    
    document
      .getElementById('thumb0')
      .addEventListener("click", onClick);
</script>


você pode usar removeAttribute() assim: document.getElementById('thumb0').removeAttribute("onclick");

ou você pode deixar a função retornar falsa assim: document.getElementById('thumb0').onclick = ()=> false





dom-events