October 14, 2022

Dispatching custom events

We can not only assign handlers, but also generate events from JavaScript.

Custom events can be used to create “graphical components”. For instance, a root element of our own JS-based menu may trigger events telling what happens with the menu: open (menu open), select (an item is selected) and so on. Another code may listen for the events and observe what’s happening with the menu.

We can generate not only completely new events, that we invent for our own purposes, but also built-in ones, such as click, mousedown etc. That may be helpful for automated testing.

Event constructor

Built-in event classes form a hierarchy, similar to DOM element classes. The root is the built-in Event class.

We can create Event objects like this:

let event = new Event(type[, options]);

Arguments:

  • type – event type, a string like "click" or our own like "my-event".

  • options – the object with two optional properties:

    • bubbles: true/false – if true, then the event bubbles.
    • cancelable: true/false – if true, then the “default action” may be prevented. Later we’ll see what it means for custom events.

    By default both are false: {bubbles: false, cancelable: false}.

dispatchEvent

After an event object is created, we should “run” it on an element using the call elem.dispatchEvent(event).

Then handlers react on it as if it were a regular browser event. If the event was created with the bubbles flag, then it bubbles.

In the example below the click event is initiated in JavaScript. The handler works same way as if the button was clicked:

<button id="elem" onclick="alert('Click!');">Autoclick</button>

<script>
  let event = new Event("click");
  elem.dispatchEvent(event);
</script>
event.isTrusted

There is a way to tell a “real” user event from a script-generated one.

The property event.isTrusted is true for events that come from real user actions and false for script-generated events.

Bubbling example

We can create a bubbling event with the name "hello" and catch it on document.

All we need is to set bubbles to true:

<h1 id="elem">Hello from the script!</h1>

<script>
  // catch on document...
  document.addEventListener("hello", function(event) { // (1)
    alert("Hello from " + event.target.tagName); // Hello from H1
  });

  // ...dispatch on elem!
  let event = new Event("hello", {bubbles: true}); // (2)
  elem.dispatchEvent(event);

  // the handler on document will activate and display the message.

</script>

Notes:

  1. We should use addEventListener for our custom events, because on<event> only exists for built-in events, document.onhello doesn’t work.
  2. Must set bubbles:true, otherwise the event won’t bubble up.

The bubbling mechanics is the same for built-in (click) and custom (hello) events. There are also capturing and bubbling stages.

MouseEvent, KeyboardEvent and others

Here’s a short list of classes for UI Events from the UI Event specification