251 votes

Supprimer tous les écouteurs d'événements d'un type spécifique

Je veux supprimer tous les écouteurs d'événements d'un type spécifique qui ont été ajoutés en utilisant addEventListener(). Toutes les ressources que je consulte disent que vous devez faire ceci :

elem.addEventListener('mousedown', specific_function);
elem.removeEventListener('mousedown', specific_function);

Mais je veux être en mesure de le supprimer sans savoir ce que c'est actuellement, comme ceci :

elem.addEventListener('mousedown', specific_function);
elem.removeEventListener('mousedown');

285voto

plalx Points 14938

Cela n'est pas possible sans intercepter les appels à addEventListener et suivre les écouteurs ou utiliser une bibliothèque qui permet de telles fonctionnalités malheureusement. Cela aurait été possible si la collection des écouteurs était accessible mais la fonctionnalité n'a pas été implémentée.

La chose la plus proche que vous pouvez faire est de supprimer tous les écouteurs en clonant l'élément, ce qui ne clonera pas la collection des écouteurs.

Remarque : Cela supprimera également les écouteurs sur les enfants de l'élément.

var el = document.getElementById('el-id'),
    elClone = el.cloneNode(true);

el.parentNode.replaceChild(elClone, el);

116voto

AmadeusDrZaius Points 768

Si votre seul objectif en supprimant les auditeurs est de les empêcher de s'exécuter, vous pouvez ajouter un écouteur d'événements à la fenêtre capturant et annulant tous les événements du type donné :

window.addEventListener(type, function(event) {
    event.stopImmediatePropagation();
}, true);

En passant true pour le troisième paramètre, l'événement sera capturé lors de sa descente. Arrêter la propagation signifie que l'événement n'atteindra jamais les auditeurs qui l'écoutent.

Cependant, gardez à l'esprit que cela a une utilisation très limitée car vous ne pouvez pas ajouter de nouveaux auditeurs pour le type spécifié (ils seront tous bloqués). Il existe des moyens de contourner cela quelque peu, par exemple, en déclenchant un nouveau type d'événement que seuls vos auditeurs sauraient écouter. Voici comment vous pouvez faire cela :

window.addEventListener('click', function (event) {
    // (note: not cross-browser)
    var event2 = new CustomEvent('click2', {detail: {original: event}});
    event.target.dispatchEvent(event2);
    event.stopPropagation();
}, true);

element.addEventListener('click2', function(event) {
    if (event.detail && event.detail.original) {
        event = event.detail.original
    }
    // Faites quelque chose avec l'événement
});

Cependant, notez que cela peut ne pas fonctionner aussi bien pour des événements rapides comme mousemove, étant donné que la redistribution de l'événement introduit un retard.

Il serait préférable de simplement suivre les auditeurs ajoutés en premier lieu, comme le décrit la réponse de Martin Wantke, si vous avez besoin de le faire.

À titre de référence : https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener indique que le 3ème paramètre est soit un objet de configuration, soit un booléen, le booléen étant un raccourci pour la configuration "capture". Capture signifie que l'événement sera passé à ce rappel "avant" tout autre gestionnaire enregistré.

29voto

Martin Wantke Points 26

Vous devez remplacer EventTarget.prototype.addEventListener pour construire une fonction trap pour enregistrer tous les appels 'ajouter un écouteur'. Quelque chose comme cela :

var _listeners = [];

EventTarget.prototype.addEventListenerBase = EventTarget.prototype.addEventListener;
EventTarget.prototype.addEventListener = function(type, listener)
{
    _listeners.push({target: this, type: type, listener: listener});
    this.addEventListenerBase(type, listener);
};

Ensuite, vous pouvez construire un EventTarget.prototype.removeEventListeners:

EventTarget.prototype.removeEventListeners = function(targetType)
{
    for(var index = 0; index != _listeners.length; index++)
    {
        var item = _listeners[index];

        var target = item.target;
        var type = item.type;
        var listener = item.listener;

        if(target == this && type == targetType)
        {
            this.removeEventListener(type, listener);
        }
    }
}

En ES6, vous pouvez utiliser un symbole pour masquer la fonction originale et la liste de tous les écouteurs ajoutés directement dans l'objet instancié lui-même.

(function()
{
    let target = EventTarget.prototype;
    let functionName = 'addEventListener';
    let func = target[functionName];

    let symbolHidden = Symbol('hidden');

    function hidden(instance)
    {
        if(instance[symbolHidden] === undefined)
        {
            let area = {};
            instance[symbolHidden] = area;
            return area;
        }

        return instance[symbolHidden];
    }

    function listenersFrom(instance)
    {
        let area = hidden(instance);
        if(!area.listeners) { area.listeners = []; }
        return area.listeners;
    }

    target[functionName] = function(type, listener)
    {
        let listeners = listenersFrom(this);

        listeners.push({ type, listener });

        func.apply(this, [type, listener]);
    };

    target['removeEventListeners'] = function(targetType)
    {
        let self = this;

        let listeners = listenersFrom(this);
        let removed = [];

        listeners.forEach(item =>
        {
            let type = item.type;
            let listener = item.listener;

            if(type == targetType)
            {
                self.removeEventListener(type, listener);
            }
        });
    };
})();

Vous pouvez tester ce code avec ce petit extrait :

document.addEventListener("DOMContentLoaded", event => { console.log('événement 1'); });
document.addEventListener("DOMContentLoaded", event => { console.log('événement 2'); });
document.addEventListener("click", event => { console.log('événement de clic'); });

document.dispatchEvent(new Event('DOMContentLoaded'));
document.removeEventListeners('DOMContentLoaded');
document.dispatchEvent(new Event('DOMContentLoaded'));
// l'événement de clic fonctionne toujours, il suffit de cliquer dans le navigateur

16voto

Chris Hayes Points 1575

Supprimer tous les écouteurs sur un événement global

element.onmousedown = null;

maintenant vous pouvez à nouveau ajouter des écouteurs d'événements via

element.addEventListener('mousedown', handler, ...);

Cette solution ne fonctionne que sur les événements "globaux". Les événements personnalisés ne fonctionneront pas. Voici une liste de tous les événements globaux : https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers

14voto

Une manière moderne de supprimer des écouteurs d'événements sans faire référence à la fonction d'origine est d'utiliser AbortController. Un inconvénient étant que vous ne pouvez arrêter que les écouteurs que vous avez ajoutés vous-même.

const buttonOne = document.querySelector('#button-one');
const buttonTwo = document.querySelector('#button-two');
const abortController = new AbortController();

// Ajouter plusieurs écouteurs d'événements de clic au bouton un
buttonOne.addEventListener(
  'click',
  () => alert('Premier'),
  { signal: abortController.signal }
);

buttonOne.addEventListener(
  'click',
  () => alert('Deuxième'),
  { signal: abortController.signal }
);

// Ajouter un écouteur pour supprimer les écouteurs du premier bouton
buttonTwo.addEventListener(
  'click',
  () => abortController.abort()
);

Le premier bouton déclenchera deux boîtes de dialogue d'alerte lorsqu'il est cliqué. Cliquez sur le deuxième bouton pour supprimer ces écouteurs du premier bouton.

Cliquer pour les alertes
Supprimer les écouteurs

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X