223 votes

Comment vérifier si l'auditeur d'événements attaché dynamiquement existe ou non ?

Voici mon problème : est-il possible de vérifier l'existence d'un récepteur d'événement attaché dynamiquement ? Ou comment puis-je vérifier l'état de la propriété "onclick" ( ?) dans le DOM ? J'ai cherché une solution sur Internet, comme sur Stack Overflow, mais sans succès. Voici mon code html :

<a id="link1" onclick="linkclick(event)"> link 1 </a>
<a id="link2"> link 2 </a> <!-- without inline onclick handler -->

Ensuite, en Javascript, j'attache un récepteur d'événements créé dynamiquement au deuxième lien :

document.getElementById('link2').addEventListener('click', linkclick, false);

Le code s'exécute correctement, mais toutes mes tentatives de détection de l'auditeur attaché échouent :

// test for #link2 - dynamically created eventlistener
alert(elem.onclick); // null
alert(elem.hasAttribute('onclick')); // false
alert(elem.click); // function click(){[native code]} // btw, what's this?

jsFiddle est ici . Si vous cliquez sur "Add onclick for 2" puis sur "[link 2]", l'événement se déclenche bien, mais l'événement "Test link 2" est toujours faux. Quelqu'un peut-il m'aider ?

125voto

Karol Grabowski Points 1061

J'ai fait quelque chose comme ça :

const element = document.getElementById('div');

if (element.getAttribute('listener') !== 'true') {
     element.addEventListener('click', function (e) {
         const elementClicked = e.target;
         elementClicked.setAttribute('listener', 'true');
         console.log('event has been attached');
    });
}

Création d'un attribut spécial pour un élément lorsque l'écouteur est attaché et vérification de son existence.

77voto

Ivan Points 2695

Il n'existe aucun moyen de vérifier si des récepteurs d'événements attachés dynamiquement existent ou non.

La seule façon de savoir si un écouteur d'événement est attaché est d'attacher des écouteurs d'événement comme ceci :

elem.onclick = function () { console.log (1) }

Vous pouvez alors tester si un écouteur d'événements a été attaché à onclick en renvoyant !!elem.onclick (ou quelque chose de similaire).

33voto

Cesar Points 332

Ce que je ferais, c'est créer un booléen à l'extérieur de votre fonction qui commence par FALSE et qui devient VRAI lorsque vous attachez l'événement. Cela servirait en quelque sorte d'indicateur avant que vous n'attachiez à nouveau l'événement. Voici un exemple de cette idée.

// initial load
var attached = false;

// this will only execute code once
doSomething = function()
{
 if (!attached)
 {
  attached = true;
  //code
 }
} 

//attach your function with change event
window.onload = function()
{
 var txtbox = document.getElementById('textboxID');

 if (window.addEventListener)
 {
  txtbox.addEventListener('change', doSomething, false);
 }
 else if(window.attachEvent)
 {
  txtbox.attachEvent('onchange', doSomething);
 }
}

15voto

arufian Points 568

Duplicata possible : Vérifie si un élément est doté d'un récepteur d'événements. Pas de jQuery Vous y trouverez ma réponse.

Voici l'astuce pour le navigateur Chromium (Chrome) :

getEventListeners(document.querySelector('your-element-selector'));

8voto

Angel Politis Points 7101

tl;dr : Non, vous ne pouvez pas le faire de manière native.


Le seul moyen que je connaisse pour y parvenir serait de créer un objet de stockage personnalisé dans lequel vous conserveriez un enregistrement des auditeurs ajoutés. Quelque chose comme ça :

/* Create a storage object. */
var CustomEventStorage = [];

Étape 1 : Tout d'abord, vous aurez besoin d'une fonction capable de parcourir l'objet de stockage et de renvoyer l'enregistrement d'un élément donné (ou faux).

/* The function that finds a record in the storage by a given element. */
function findRecordByElement (element) {
    /* Iterate over every entry in the storage object. */
    for (var index = 0, length = CustomEventStorage.length; index < length; index++) {
        /* Cache the record. */
        var record = CustomEventStorage[index];

        /* Check whether the given element exists. */
        if (element == record.element) {
            /* Return the record. */
            return record;
        }
    }

    /* Return false by default. */
    return false;
}

Étape 2 : Ensuite, vous aurez besoin d'une fonction capable d'ajouter un écouteur d'événement mais aussi d'insérer l'écouteur dans l'objet de stockage.

/* The function that adds an event listener, while storing it in the storage object. */
function insertListener (element, event, listener, options) {
    /* Use the element given to retrieve the record. */
    var record = findRecordByElement(element);

    /* Check whether any record was found. */
    if (record) {
        /* Normalise the event of the listeners object, in case it doesn't exist. */
        record.listeners[event] = record.listeners[event] || [];
    }
    else {
        /* Create an object to insert into the storage object. */
        record = {
            element: element,
            listeners: {}
        };

        /* Create an array for event in the record. */
        record.listeners[event] = [];

        /* Insert the record in the storage. */
        CustomEventStorage.push(record);
    }

    /* Insert the listener to the event array. */
    record.listeners[event].push(listener);

    /* Add the event listener to the element. */
    element.addEventListener(event, listener, options);
}

Étape 3 : En ce qui concerne votre question, vous aurez besoin de la fonction suivante pour vérifier si un élément a été ajouté en tant qu'écouteur d'événement pour un événement spécifié.

/* The function that checks whether an event listener is set for a given event. */
function listenerExists (element, event, listener) {
    /* Use the element given to retrieve the record. */
    var record = findRecordByElement(element);

    /* Check whether a record was found & if an event array exists for the given event. */
    if (record && event in record.listeners) {
        /* Return whether the given listener exists. */
        return !!~record.listeners[event].indexOf(listener);
    }

    /* Return false by default. */
    return false;
}

Étape 4 : Enfin, vous aurez besoin d'une fonction capable de supprimer un auditeur de l'objet de stockage.

/* The function that removes a listener from a given element & its storage record. */
function removeListener (element, event, listener, options) {
    /* Use the element given to retrieve the record. */
    var record = findRecordByElement(element);

    /* Check whether any record was found and, if found, whether the event exists. */
    if (record && event in record.listeners) {
        /* Cache the index of the listener inside the event array. */
        var index = record.listeners[event].indexOf(listener);

        /* Check whether listener is not -1. */
        if (~index) {
            /* Delete the listener from the event array. */
            record.listeners[event].splice(index, 1);
        }

        /* Check whether the event array is empty or not. */
        if (!record.listeners[event].length) {
            /* Delete the event array. */
            delete record.listeners[event];
        }
    }

    /* Add the event listener to the element. */
    element.removeEventListener(event, listener, options);
}

Extrait :

window.onload = function () {
  var
    /* Cache the test element. */
    element = document.getElementById("test"),

    /* Create an event listener. */
    listener = function (e) {
      console.log(e.type + "triggered!");
    };

  /* Insert the listener to the element. */
  insertListener(element, "mouseover", listener);

  /* Log whether the listener exists. */
  console.log(listenerExists(element, "mouseover", listener));

  /* Remove the listener from the element. */
  removeListener(element, "mouseover", listener);

  /* Log whether the listener exists. */
  console.log(listenerExists(element, "mouseover", listener));
};

<!-- Include the Custom Event Storage file -->
<script src = "https://cdn.rawgit.com/angelpolitis/custom-event-storage/master/main.js"></script>

<!-- A Test HTML element -->
<div id = "test" style = "background:#000; height:50px; width: 50px"></div>

Bien que plus de 5 ans se soient écoulés depuis que le PO a posé la question, je pense que les personnes qui tomberont sur cette question à l'avenir bénéficieront de cette réponse, alors n'hésitez pas à y apporter des suggestions ou des améliorations.

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