How to create and use custom events

Asked

Viewed 701 times

9

Researching I found Event and CustumEvent, both can be used to create events, and to control registrations, removals and emissions of the event should be used EventTarget, but I didn’t understand how they work, for example, how I could create a custom click event?

//Cria um evento de clique personalizado
const myClick = new Event('myClick');

//Alguma coisa para guardar as chamadas de "addEventListener"

//Adiciona um ouvinte do evento personalizado aos elmentos
myElement.addEventListener('myClick', event => console.log(event));
myOtherElement.addEventListener('myClick', event => console.log(event));

//Quando houver um clique na tela
window.addEventListener('click', function(event) {
    //Percorre uma lista onde ficaria armazenado os elementos que foram adicionado ouvintes do evento
    for(element of elementList) {
        //Se o elemento for igual ao elemento principal do clique na janela
        if (event.target === element) {
            //Dispara o evento customizado de clique
            element.dispatchEvent(myClick);
        }
    }
});

Am I on the right track? How to save calls from addEventListener?

The example is exactly like the click event that already exists, it’s just an example. At the moment I just want to know how it is done in modern browsers, I’m not worried about compatibility

4 answers

17

Basically, to create a custom event and listen to it, you must:

  1. Create the event by instantiating a new one Event. As in new Event('eventName');
  2. Trigger the event using the method dispatchEvent - available in the prototype of EventTarget, implemented by objects such as Element. To this end, the instance created before the dispatchEvent.
  3. Listen to the event using the method addEventListener of some Element.

The example below shows the whole process:

// Para criar o evento:
const myClickEvent = new Event('myClick');

const myDiv = document.querySelector('#my-div');

// Para ouvir o evento:
myDiv.addEventListener('myClick', function () {
  console.log('Evento customizado disparado!');
});

myDiv.addEventListener('click', function () {
  // Disparar o evento:
  myDiv.dispatchEvent(myClickEvent);
});
<div id="my-div">Minha div (clique)</div>

To find out more, I suggest reading:

  • But that way it would have to add two events every time, it wouldn’t be automatic. For example, assuming I want to add an event in three elements, I would also have to add three normal click event listeners in those same 3 elements, if so it would be better to add just one and encapsulate what would make my special event a function that would call in the first line of the listener’s callback

  • That’s what you need to do. I believe there’s no other way.

7


If the idea is to trigger the event myClick whenever there is a click, you can do the following:

const myClick = new Event('myClick');

document.addEventListener('click', event => {
    EventTarget.prototype.dispatchEvent.call(event.target, myClick);
});

Thus, whenever the event occurs click, the event will be triggered myClick for the same element.

const myClick = new Event('myClick');

document.addEventListener('click', event => {
    EventTarget.prototype.dispatchEvent.call(event.target, myClick);
});

const lis = document.querySelectorAll('li');

for (let li of lis) {
  li.addEventListener('myClick', event => console.log(event.target));
}
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li>Item 4</li>
  <li>Item 5</li>
</ul>

Realize that even if all the elements <li> have the event myClick, only the pressed element is fired.


However, as the event treated is the click in document, will only work if the element belongs to the node tree in document and the treated event propagates through it. If the element does not belong to the tree or the event is not propagating, the solution will not work. For example, below is an example of an element that is created dynamically and is not inserted in the document. The event click of virtual will not be propagated until document and therefore will not fire the myClick.

const myClick = new Event('myClick');

document.addEventListener('click', event => {
    EventTarget.prototype.dispatchEvent.call(event.target, myClick);
});

const virtual = document.createElement('span');

virtual.addEventListener('myClick', event => console.log(event.target));
virtual.click();

However, adding the element to the tree, document.body.appendChild(virtual), the event click will fire myClick normally. For non propagating events, it will not work even if the element belongs to the node tree.

  • I ended up coming back to this question now and just one question: have some specific reason to use the call (EventTarget.prototype.dispatchEvent.call) instead of simply already applying the function directly event.target.dispatchEvent, which is already an instance of EventTarget?

1

var evt = document.createEvent("Event");
evt.initEvent("myEvent",true,true);

// parametro customizado
evt.foo = "bar";

//registrar
document.addEventListener("myEvent",myEventHandler,false);

//invocar
document.dispatchEvent(evt);

This is just a simple example, more details on: http://www.kaizou.org/2010/03/generating-custom-javascript-events/

  • Her answer adds nothing to the already existing answer, moreover, as well as the other, she does not answer the question

  • What’s missing to be complete?

  • Doubt is like storing calls from addEventListener

  • Set what it is to store calls from an event. It would be to know how many times an event has been triggered?

  • When there’s a call from addEventListener, is added to a list for callback to be executed. How do I get this list? Somewhere it needs to be stored, but where?

  • See if this would help, if yes I translate and put in my answer https://www.bitovi.com/blog/a-crash-course-in-how-dom-events-work

  • Yeah, I guess that’s right

Show 2 more comments

0

I managed to do something similar, maybe not the best way, but it works:

//Cria um evento de clique personalizado
const myClick = new Event('myClick');

//Salva a função em um lugar qualquer, no caso, escolhi o protótipo de EventTarget
EventTarget.prototype._addEventListener = EventTarget.prototype.addEventListener;

//Adiciona uma propriedade ao protótipo de EventTarget (poderia ser em qualquer outro lugar)
EventTarget.prototype.customListener = {
  myClick: []
};

//Altera a função addEventListener
EventTarget.prototype.addEventListener = function(type, listener, options) {
  //Se não houver a variável, a cria
  if (!EventTarget.prototype.customListener[type]) {
    EventTarget.prototype.customListener[type] = [];
  }

  //Adiciona o listener à lista
  EventTarget.prototype.customListener[type].push({
    element: this,
    callback: listener
  });

  //Chama a função antiga
  this._addEventListener(type, listener, options);
}

//Adiciona um ouvinte do evento personalizado aos elmentos
document.querySelector('button').addEventListener('myClick', event => console.log('Clicked on button'));
document.querySelector('a').addEventListener('myClick', event => console.log('Clicked on link'));

//A lista de eventos:
console.log(EventTarget.prototype.customListener)

//Quando houver um clique na tela
window.addEventListener('click', function(event) {
    //Percorre uma lista onde ficaria armazenado os elementos que foram adicionado ouvintes do evento
    for(listener of EventTarget.prototype.customListener.myClick) {
        //Se o elemento for igual ao elemento principal do clique na janela
        if (event.target === listener.element) {
            //Dispara o evento customizado de clique
            listener.callback(event);
        }
    }
});
<button>Click here!</button>

<a href="#!">Click here too!</a>

I will implement in a project and then post a more useful example (maybe cross-browser too)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.