web-dev-qa-db-fra.com

Javascript/DOM: Comment supprimer tous les événements d'un objet DOM?

Juste question: est-il possible de supprimer complètement tous les événements d'un objet, par exemple. une div?

EDIT: J'ajoute par div.addEventListener('click',eventReturner(),false); un événement.

function eventReturner() {
    return function() {
        dosomething();
    };
}

EDIT2: J'ai trouvé un moyen, qui fonctionne, mais pas possible d'utiliser pour mon cas:

var returnedFunction;
function addit() {
    var div = document.getElementById('div');
    returnedFunction = eventReturner();
    div.addEventListener('click',returnedFunction,false); //You HAVE to take here a var and not the direct call to eventReturner(), because the function address must be the same, and it would change, if the function was called again.
}
function removeit() {
    var div = document.getElementById('div');
    div.removeEventListener('click',returnedFunction,false);
}
58
Florian Müller

Je ne suis pas sûr de ce que vous entendez par remove all events. Supprimer tous les gestionnaires pour un type d'événement spécifique ou tous les gestionnaires d'événement pour un type?

Supprimer tous les gestionnaires d'événements

Si vous souhaitez supprimer tous les gestionnaires d'événements (de tout type), vous pouvez clone l'élément et le remplacer par son clone:

var clone = element.cloneNode(true);

Remarque: Ceci préservera les attributs et les enfants, mais ne conservera aucune modification apportée aux propriétés du DOM.


Supprimer les gestionnaires d'événements "anonymes" d'un type spécifique

L’autre méthode consiste à utiliser removeEventListener() mais je suppose que vous avez déjà essayé cela et que cela n’a pas fonctionné. voici la capture :

L'appel de addEventListener à une fonction anonyme crée un nouvel écouteur à chaque fois. L'appel de removeEventListener à une fonction anonyme n'a aucun effet . Une fonction anonyme crée un objet unique à chaque appel. Il ne s'agit pas d'une référence à un objet existant, bien qu'elle puisse en appeler un. Lorsque vous ajoutez un écouteur d'événements de cette manière, veillez à ce qu'il ne soit ajouté qu'une seule fois. Il est permanent (ne peut pas être supprimé) jusqu'à ce que l'objet auquel il a été ajouté soit détruit.

Vous passez essentiellement une fonction anonyme à addEventListener car eventReturner renvoie une fonction.

Vous avez deux possibilités pour résoudre ceci:

  1. N'utilisez pas une fonction qui retourne une fonction. Utilisez la fonction directement:

    function handler() {
        dosomething();
    }
    
    div.addEventListener('click',handler,false);
    
  2. Créez un wrapper pour addEventListener qui stocke une référence à la fonction renvoyée et créez une fonction bizarre removeAllEvents:

    var _eventHandlers = {}; // somewhere global
    
    function addListener(node, event, handler, capture) {
        if(!(node in _eventHandlers)) {
            // _eventHandlers stores references to nodes
            _eventHandlers[node] = {};
        }
        if(!(event in _eventHandlers[node])) {
            // each entry contains another entry for each event type
            _eventHandlers[node][event] = [];
        }
        // capture reference
        _eventHandlers[node][event].Push([handler, capture]);
        node.addEventListener(event, handler, capture);
     }
    
    function removeAllListeners(node, event) {
        if(node in _eventHandlers) {
            var handlers = _eventHandlers[node];
            if(event in handlers) {
                var eventHandlers = handlers[event];
                for(var i = eventHandlers.length; i--;) {
                    var handler = eventHandlers[i];
                    node.removeEventListener(event, handler[0], handler[1]);
                }
            }
        }
    }
    

    Et puis vous pourriez l'utiliser avec:

    addListener(div, 'click', eventReturner(), false)
    // and later
    removeListeners(div, 'click')
    

DÉMO

Remarque: Si votre code est exécuté longtemps et que vous créez et supprimez de nombreux éléments, vous devez vous assurer de supprimer les éléments contenus. dans _eventHandlers lorsque vous les détruisez.

81
Felix Kling

Utilisez la fonction remove() du programme d'écoute d'événement. Par exemple:

getEventListeners().click.forEach((e)=>{e.remove()})
25
JuanGG

Cela supprimera tous les écouteurs des enfants, mais sera lent pour les grandes pages. Brutalement simple à écrire.

element.outerHTML = element.outerHTML;
13
pabombs

Comme le dit corwin.amber, il existe des différences entre Webkit et les autres.

Sous Chrome:

getEventListeners(document);

Ce qui vous donne un objet avec tous les écouteurs d'événement existants:

Object 
 click: Array[1]
 closePopups: Array[1]
 keyup: Array[1]
 mouseout: Array[1]
 mouseover: Array[1]
 ...

De là, vous pouvez atteindre l'auditeur que vous souhaitez supprimer:

getEventListeners(document).copy[0].remove();

Donc, tous les auditeurs de l'événement:

for(var eventType in getEventListeners(document)) {
   getEventListeners(document)[eventType].forEach(
      function(o) { o.remove(); }
   ) 
}

Dans Firefox

C'est un peu différent car il utilise un wrapper d'écoute qui ne contient aucune fonction remove. Vous devez obtenir l'auditeur que vous souhaitez supprimer:

document.removeEventListener("copy", getEventListeners(document).copy[0].listener)

Tous les auditeurs de l'événement:

for(var eventType in getEventListeners(document)) {
  getEventListeners(document)[eventType].forEach(
    function(o) { document.removeEventListener(eventType, o.listener) }
  ) 
}

Je suis tombé par hasard sur cet article en essayant de désactiver la protection contre la copie agaçante d'un site Web d'actualités.

Prendre plaisir!

7
Jmakuc

Peut-être que le navigateur le fera pour vous si vous faites quelque chose comme:

Copiez la div et ses attributs et insérez-la avant l'ancienne, puis déplacez le contenu de l'ancien vers le nouveau et supprimez l'ancien?

0
Mic

Pour compléter les réponses, voici des exemples concrets de suppression d'événements lorsque vous visitez des sites Web et que vous n'avez pas le contrôle sur le code HTML et JavaScript généré.

Certains sites Web gênants vous empêchent de copier-coller les noms d'utilisateur sur les formulaires de connexion, ce qui pourrait facilement être contourné si l'événement onpaste était ajouté avec l'attribut HTML onpaste="return false". Dans ce cas, il suffit de cliquer avec le bouton droit sur le champ de saisie, de sélectionner "Inspecter l'élément" dans un navigateur tel que Firefox et de supprimer l'attribut HTML.

Toutefois, si l'événement a été ajouté via JavaScript, procédez comme suit:

document.getElementById("lyca_login_mobile_no").onpaste = function(){return false};

Nous devrons également supprimer l'événement via JavaScript:

document.getElementById("lyca_login_mobile_no").onpaste = null;

Dans mon exemple, j'ai utilisé l'ID "lyca_login_mobile_no" puisqu'il s'agissait de l'ID de saisie de texte utilisé par le site Web que je visitais.

Un autre moyen de supprimer l'événement (qui supprimera également tous les événements) consiste à supprimer le nœud et à en créer un nouveau, comme nous devons le faire si addEventListener était utilisé pour ajouter des événements à l'aide d'une fonction anonyme que nous ne pouvons pas supprimer. avec removeEventListener. Cela peut également être effectué via la console du navigateur en inspectant un élément, en copiant le code HTML, en supprimant le code HTML, puis en le collant au même endroit.

Cela peut aussi être fait plus rapidement et automatisé avec JavaScript:

var oldNode = document.getElementById("lyca_login_mobile_no");
var newNode = oldNode.cloneNode(true);
oldNode.parentNode.insertBefore(newNode, oldNode);
oldNode.parentNode.removeChild(oldNode);

Mise à jour: si l'application Web est créée à l'aide d'un cadre JavaScript tel que Angular, les solutions précédentes ne fonctionnent pas ou ne fonctionnent pas correctement. Une autre solution de contournement pour permettre le collage serait de définir la valeur via JavaScript:

document.getElementById("lyca_login_mobile_no").value = "username";

Pour le moment, je ne sais pas s'il existe un moyen de supprimer tous les événements de validation et de restriction de formulaire sans détruire une application entièrement écrite en JavaScript, telle qu'Angle.

0
baptx

Chrome uniquement

Alors que j'essaie de supprimer un EventListener dans un test de Protractor et que je n'ai pas accès à l'écouteur .__ dans le test, la procédure suivante permet de supprimer tous les écouteurs d'événement d'un seul type:

function(eventType){
    getEventListeners(window).[eventType].forEach(
        function(e){
            window.removeEventListener(eventType, e.listener)
        }
    );
}

J'espère que cela aide quelqu'un comme réponse précédente utilisait la méthode "remove" qui depuis ne fonctionne plus.

0
Filipe Melo