JavaScript: remover ouvinte de evento

136

Estou tentando remover um ouvinte de evento dentro de uma definição de ouvinte:

canvas.addEventListener('click', function(event) {
    click++;
    if(click == 50) {
        // remove this event listener here!
    }
// More code here ...

Como eu pude fazer isso? this = event ... Obrigado.

Thomas
fonte
8
trivial, mas para o futuro as referências if(click == 50) {devem ser if( click === 50 )ou if( click >= 50 )- elas não mudarão a saída, mas por razões de sanidade essas verificações fazem mais sentido.
Rlemon 14/03
Boa pergunta ... como removê-lo se não tenho acesso ao conteúdo? Desejo remover pop-ups por botões onclick usando greasemonkey para outros sites, mas, a menos que eu consiga referenciar a função pelo nome, não encontro uma maneira de removê-la.
JasonXA

Respostas:

122

Você precisa usar funções nomeadas.

Além disso, a clickvariável precisa estar fora do manipulador para incrementar.

var click_count = 0;

function myClick(event) {
    click_count++;
    if(click_count == 50) {
       // to remove
       canvas.removeEventListener('click', myClick);
    }
}

// to add
canvas.addEventListener('click', myClick);

EDIT: Você pode fechar em torno da click_countervariável assim:

var myClick = (function( click_count ) {
    var handler = function(event) {
        click_count++;
        if(click_count == 50) {
           // to remove
           canvas.removeEventListener('click', handler);
        }
    };
    return handler;
})( 0 );

// to add
canvas.addEventListener('click', myClick);

Dessa forma, você pode incrementar o contador em vários elementos.


Se você não quer isso e deseja que cada um tenha seu próprio contador, faça o seguinte:

var myClick = function( click_count ) {
    var handler = function(event) {
        click_count++;
        if(click_count == 50) {
           // to remove
           canvas.removeEventListener('click', handler);
        }
    };
    return handler;
};

// to add
canvas.addEventListener('click', myClick( 0 ));

Edição: Eu tinha esquecido de nomear o manipulador sendo retornado nas duas últimas versões. Fixo.

user113716
fonte
14
+1 - Transformei isso em um violino e não funcionou. Mas isso foi porque eu precisava clicar cinquenta vezes :) Que idiota eu sou. Exemplo simplificado aqui: jsfiddle.net/karim79/aZNqA
karim79
4
@ karim79: Eu gostaria de poder dizer que nunca fiz nada assim antes. : o) Obrigado pelo jsFiddle.
usar o seguinte comando
+1 A terceira opção funcionou para mim. Atribuindo um evento-chave a um campo de entrada para limpar a validação. Agradável um #
Gurnard
Upvote, terceira opção aqui é parte importante da JS compreensão de ligação / desligamento
SW4
seria myClick = function(event){...}considerada uma função nomeada também?
Daniel Möller
80
   canvas.addEventListener('click', function(event) {
      click++;
      if(click == 50) {
          this.removeEventListener('click',arguments.callee,false);
      }

Deveria fazê-lo.

Edeverett
fonte
14
Isso é legal! Documento arguments.calleepara as partes interessadas: developer.mozilla.org/en/JavaScript/Reference/…
Ender
Obrigado, isso ajudou muito.
John O
2
Infelizmente, isso não funciona com o ECMAScript 5 (2009) ou posterior, no link MDN: "A 5ª edição do ECMAScript (ES5) proíbe o uso arguments.callee()no modo estrito. Evite usar arguments.callee()dando um nome às expressões de função ou usando uma declaração de função onde uma função deve se chamar ". (embora esteja usando em callee()vez de callee, ainda é removido, boo!)
Dai
59

Você pode usar uma expressão de função nomeada (nesse caso, a função é nomeada abc), assim:

let click = 0;
canvas.addEventListener('click', function abc(event) {
    click++;
    if (click >= 50) {
        // remove event listener function `abc`
        canvas.removeEventListener('click', abc);
    }
    // More code here ...
}

Exemplo de trabalho rápido e sujo: http://jsfiddle.net/8qvdmLz5/2/ .

Mais informações sobre expressões de funções nomeadas: http://kangax.github.io/nfe/ .

Tama
fonte
Inteligente. Um daqueles casos raros em que a ENF é útil. Obrigado.
21419 DanMan
7
element.querySelector('.addDoor').onEvent('click', function (e) { });
element.querySelector('.addDoor').removeListeners();


HTMLElement.prototype.onEvent = function (eventType, callBack, useCapture) {
this.addEventListener(eventType, callBack, useCapture);
if (!this.myListeners) {
    this.myListeners = [];
};
this.myListeners.push({ eType: eventType, callBack: callBack });
return this;
};


HTMLElement.prototype.removeListeners = function () {
if (this.myListeners) {
    for (var i = 0; i < this.myListeners.length; i++) {
        this.removeEventListener(this.myListeners[i].eType, this.myListeners[i].callBack);
    };
   delete this.myListeners;
};
};
Janelas de vinil
fonte
6

Se a solução do @ Cybernate não funcionar, tente ativar o gatilho para sua própria função, para que você possa fazer referência a ele.

clickHandler = function(event){
  if (click++ == 49)
    canvas.removeEventListener('click',clickHandler);
}
canvas.addEventListener('click',clickHandler);
Brad Christie
fonte
4

Se alguém usa jquery, ele pode fazer assim:

var click_count = 0;
$( "canvas" ).bind( "click", function( event ) {
    //do whatever you want
    click_count++;
    if ( click_count == 50 ) {
        //remove the event
        $( this ).unbind( event );
    }
});

Espero que possa ajudar alguém. Observe que a resposta dada por @ user113716 funciona muito bem :)

youssman
fonte
2

Eu acho que você pode precisar definir a função de manipulador com antecedência, assim:

var myHandler = function(event) {
    click++; 
    if(click == 50) { 
        this.removeEventListener('click', myHandler);
    } 
}
canvas.addEventListener('click', myHandler);

Isso permitirá que você remova o manipulador por nome de dentro dele.

Ender
fonte
-4

Tente isso, funcionou para mim.

<button id="btn">Click</button>
<script>
 console.log(btn)
 let f;
 btn.addEventListener('click', f=function(event) {
 console.log('Click')
 console.log(f)
 this.removeEventListener('click',f)
 console.log('Event removed')
})  
</script>
user3870075
fonte