A series of fortunate events (in JavaScript)

Part 1: Exploring listeners, handlers, and event objects

Introduction

Events in JavaScript are just like the events outside of JavaScript. The idea is vaguely the same. Event means an occurrence, something that is happening, happened or will happen. Most of us have used events in JS but haven't deep-dived into how they work, what exactly they are, and what is possible with them. Let's do that now!

Pre-requisites

  • Basic knowledge of HTML and JavaScript syntax

Wait a minute, who are you?

Most of us have either used or seen something inside a webpage like

counterButton.addEventListener("click"....

What does it mean though? This basically means that we are adding an event listener....but what is an event listener?

giphy.gif

Event Listeners

Event listeners are listeners that listen for a specific event that you want them to listen for. Basically, how our brain works, our brains are always listening for things like, say, our name, as soon as someone calls us or we hear our name, our attention is drawn to them and we act in a certain manner. Event listeners work in the same fashion.

listening.gif

There are many events in JavaScript. Some of the most common ones are 'click' (for detecting clicks), 'mouseover'(for detecting hover), and 'onchange'(For detecting change in the value of the element). These are pre-defined values that have a specific event associated with them.

Now, comes the question of where and how we can define them. Event listeners are also called DOM EventListeners, DOM or Document Object Model is a model that includes all the things that are on your webpage, which means all of your HTML tags and more. We can only attach these event listeners to these DOM elements such as a button element or a heading element. You access these through selectors and once you have them in your script you can attach these listeners.

Event Handlers

Generally, the terms Event handler and Event listeners are used interchangeably but there's a slight but important technical difference. We attach event listeners to listen for specific events and we pass a handler function to handle the event or to act in a specific way when that event occurs.

For example,

const alertButton= document.getElementById("alert-btn");
//Getting the alertButton from the HTML to the script using a query selector

alertButton.addEventListener("click", function(){
alert("Alert button was clicked");
});

In the example above, we passed two parameters to the addEventlistener method, first "click" which defined which event to listen to, hence the event listener, and second, a function which would be fired or run when the event occurs, hence the Event Handler.

Listeners and handlers work together and are called, by either of the terms to mean both of these collectively.

Other methods to add event listeners

Yes, there are other ways we can define listeners to DOM elements but are they really worth it? The short answer is no. The long answer is that you must know them so you don't see some code and be clueless as to what is happening and also why you shouldn't use these other ways.

These DOM elements each have a certain set of properties that correlate to the events that can be performed on them and therefore, listeners that could be attached. Yes, this means that not all DOM elements are created equal, they can have different types of events. Shocker? no? Good. for example, the 'play' event is only available on some elements, such as a video element.

To attach event listeners this way, we can access these properties on the object in the script after querying it, going back to the previous code example, we'd do something like,

alertButton.onclick= function(){
alert("You clicked on me again. Find other buttons");
}

But why don't we use this method? Because, if you do, then you can only add one event handler for a specific listener and that is it. If you try to add another handler, it will simply overwrite the property value.

alertButton.onclick= function(){alert(" Will I ever run? 🥺")};
//adding one handler
alertButton.onclick= function(){alert("I know I will run!")};
//this will overwrite the previous handler

Now, if we click on this button, it will only call the second handler that we passed.

But this isn't the case with addEventListener method call,

alertButton.addEventListener("click", function(){
alert("I will run first!");
});

alertButton.addEventListener("click", function(){
alert("I will run second!");
});

Here, both handlers will be fired when the alertButton will be clicked.

Inline Handlers (Absolutely never use these)

Suppose, I were to take away your JavaScript file and also take away your script tag, and ask you to add a listener to our over-clicked alertButton. Well in that case, and only in that case should you opt-in for inline handlers. Here's how to do it,

<button onclick="alert('You think this is a good idea? Really?');">
Alert</button>

Why the hate? Well no, I don't personally hate it or anything but it is considered a bad practice in the industry. This was essentially how we added listeners in the olden days but not anymore as they quickly become a little too much to handle and maintain.

Also, many common server configurations will disallow inline JavaScript, as a security measure.

no.gif

Our beloved addEventListener()

We've seen how to use this in the blog so far, It can take up to 3 parameters.

  1. type: a case-sensitive string that represents the type of event we want to listen to.
  2. listener: The listener callback which is fired when the event type mentioned occurs
  3. options (optional): An object that specifies the characteristics of the event listener. Options include capture, once, passive, signal
  4. useCapture (optional): A boolean value indicating whether events of this type will be dispatched to the registered listener before being dispatched to any EventTarget beneath it in the DOM tree. (covered in part 2)

Event Objects

Inside the event handler, we can access the event object, usually written as 'e' or 'event'. This is an object that is automatically passed to the event handler, and it contains other features and information regarding the event.

We can explicitly pass it as well, like,

alertButton.addEventListener('click', function(e){
console.log("Event object:",e);
};

Two of the most common properties and their use:

  • e.target: Returns the DOM element the event occurred on.
  • e.target.value: Returns the value of the DOM element the event occurred on. Extensively used in to get the value of elements and others

Some event objects have special properties that are relevant to a specific event, for example, the 'keydown' event has a specialized event object which contains a 'key' property that returns the key which was pressed on the keyboard.

Note: I've used anonymous function declarations in the blog for examples. You can also define the function beforehand (a named function) and pass is a listener or use arrow functions.

Other Resources

Moving forward

We've covered the basics terminology and methods of events that should give you a working knowledge of how to deal with them. I've covered some advanced topics in part 2, such as preventing default behavior, capturing, bubbling, and some edge cases that can make you scratch your brain if left ununderstood.

Part 2: Popping some bubbles (event bubbling in JS)

Stay tuned.