JavaScript: eliminar escucha de eventos

136

Estoy tratando de eliminar un detector de eventos dentro de una definición de detector:

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

¿Cómo podría hacer eso? este = evento ... Gracias.

Thomas
fuente
8
triviales, pero para las referencias futuras if(click == 50) {deberían ser if( click === 50 )o if( click >= 50 ), no cambiarán la salida, pero por razones de cordura, estas comprobaciones tienen más sentido.
rlemon
Buena pregunta ... ¿cómo lo elimino si no tengo acceso al contenido? Quiero eliminar ventanas emergentes para hacer clic en los botones que usan greasemonkey para otros sitios, pero a menos que pueda hacer referencia a la función por nombre, no parece encontrar una manera de eliminarla.
JasonXA

Respuestas:

122

Necesita usar funciones con nombre.

Además, la clickvariable debe estar fuera del controlador 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);

EDITAR: Puede cerrar la click_countervariable de esta manera:

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

De esta manera puede incrementar el contador en varios elementos.


Si no quieres eso y quieres que cada uno tenga su propio contador, haz esto:

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

EDITAR: Me había olvidado de nombrar el controlador que se devolvió en las últimas dos versiones. Fijo.

usuario113716
fuente
14
+1: convertí esto en un violín y no funcionó. Pero eso fue porque necesitaba hacer clic cincuenta veces :) Qué idiota soy. Ejemplo simplificado aquí: jsfiddle.net/karim79/aZNqA
karim79
44
@ karim79: Ojalá pudiera decir que nunca antes había hecho algo así. : o) Gracias por el jsFiddle.
user113716
+1 La tercera opción funcionó para mí. Asignación de un evento clave a un campo de entrada para borrar la validación. Nice one thanks
Gurnard
Votación a favor, la tercera opción aquí es una parte importante de la comprensión de la vinculación / desvinculación de JS
SW4
se myClick = function(event){...}consideraría una función con nombre también?
Daniel Möller
80
   canvas.addEventListener('click', function(event) {
      click++;
      if(click == 50) {
          this.removeEventListener('click',arguments.callee,false);
      }

Deberías hacerlo.

edeverett
fuente
14
¡Esto es genial! Doc arguments.calleepara partes interesadas: developer.mozilla.org/en/JavaScript/Reference/…
Ender
Gracias, esto ayudó mucho.
John O
2
Desafortunadamente, esto no funciona con ECMAScript 5 (2009) o posterior, desde el enlace de MDN: "La quinta edición de ECMAScript (ES5) prohíbe el uso arguments.callee()en modo estricto. Evite usar arguments.callee()dando un nombre a las expresiones de función o una declaración de función donde una función debe llamarse a sí misma ". (aunque se está utilizando en callee()lugar de callee, todavía se elimina, ¡boo!)
Dai
59

Puede usar una expresión de función con nombre (en este caso, la función se llama abc), así:

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 ...
}

Ejemplo de trabajo rápido y sucio: http://jsfiddle.net/8qvdmLz5/2/ .

Más información sobre expresiones de funciones con nombre: http://kangax.github.io/nfe/ .

Tama
fuente
Inteligente. Uno de esos casos raros donde NFE son útiles. Gracias.
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;
};
};
Ventanas de vinilo
fuente
6

Si la solución de @ Cybernate no funciona, intente romper el gatillo en su propia función para que pueda hacer referencia a ella.

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

Si alguien usa jquery, puede hacerlo así:

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 pueda ayudar a alguien. Tenga en cuenta que la respuesta dada por @ user113716 funciona bien :)

youssman
fuente
2

Creo que es posible que deba definir la función del controlador con anticipación, de esta manera:

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

Esto le permitirá eliminar el controlador por nombre de sí mismo.

Ender
fuente
-4

Intenta esto, funcionó para mí.

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