Event Handling in JavaScript

In the previous lesson, we introduced the concept of an event, which is an input signal from the user to the DOM node. We also discussed how the event propagates through the DOM tree, and explained how to use JavaScript to catch the event, so that a proper feedback can be provided to the user.

And now, it is time to go over some of the most common events you are going to deal with in frontend development.

Mouse events

Let's start with the mouse events. When you place the mouse on top of the button and then click, this simple action fires five different events:

  • When you move the pointer onto the button, the mouseover event is fired.
  • When the pointer moves on top of the button, the mousemove event is fired.
  • When you press down, the mousedown event is fired.
  • When you release, the mouseup event is fired.
  • And after that, a click event will be fired.

If two click events happen close together, a dblclick (double click) event will be fired after the second click.

A pointer event object contains detailed information about exactly where the click happened. This information can be retrieved through the clientX and clientY properties.

javascript
1let button = document.getElementById("button");
2
3button.addEventListener("click", (event) => {
4  console.log("X: " + event.clientX);
5  console.log("Y: " + event.clientY);
6});

coordinates

Notice that different coordinates are returned when you click different points on the button.

You may also access information about which mouse button is pressed through the button property.

javascript
1button.addEventListener("click", (event) => {
2  if (event.button == 0) {
3    console.log("Left button");
4  } else if (event.button == 1) {
5    console.log("Middle button");
6  } else if (event.button == 2) {
7    console.log("Right button");
8  }
9});

Knowing this information allows us to create interactive applications. For example, you could use a drawing board that creates a star whenever you click on the page using the primary button, and clicking on the star with the secondary button will remove it.

However, actually implementing this requires you to have a deeper understanding of frontend development, and it might be too advanced as your first real project. So, let's come back to this topic later.

Lastly, we need to talk about a special case, the right click. In most cases, this action will activate the context menu, but sometimes, you might want to assign a different purpose, such as removing an existing star.

To prevent the default action for the right click, you can't just use preventDefault() inside a "click" event callback. That would be telling the browser to prevent the default action for the "click" event, which doesn't really have a fixed default action at all.

Instead, you need to be more specific, and tell the browser to stop the default action for the event that will activate the context menu, which is "contextmenu".

javascript
1svg.addEventListener("contextmenu", (event) => {
2  event.preventDefault();
3});

Key events

The keyboard events work similarly.

  • When a key is pressed down, the keydown event will be fired.
  • When a key is released, the keyup event will be fired.
  • After that, the keypress event will be fired.

The key event object contains information about which key has been pressed, which can be accessed through the key property.

javascript
1window.addEventListener("keypress", (event) => {
2  console.log("Key pressed: " + event.key);
3});

key events

For modifier keys such as Shift, Control, Alt, and Meta (the Command key on Mac), you can check if they are pressed using shiftKey, ctrlKey, altKey, and metaKey properties.

The reason that they get their own separate properties is to allow you to create key combinations. For example,

javascript
1window.addEventListener("keydown", (event) => {
2  if (event.ctrlKey && event.key === "k") {
3    console.log("Key combination Ctrl + K detected.");
4  }
5});

This example checks if the key combination Control + K is pressed.

Form events

The form is a special case that requires our extra attention. Besides the pointer and key events, there are a few events only for the form component.

  • When a form input field is in focus, a focus event will be fired.
  • When the user starts typing, an input event will be fired.
  • When the input element loses focus, a blur event will be fired.
  • When the user clicks submit, a submit event will be fired.

Remember when we discussed event propagation, we said that most events will propagate from the child to the parent node. Well, the focus and blur are the exceptions. Because it doesn't make sense for the parent of the <input> to be in focus or lose focus.

Clipboard Events

There are also three events for the clipboard.

  • copy fires when the user copies content from the element.
  • cut fires when the user cuts content from the element.
  • paste fires when the user pastes to the element.

These events are often used to restrict user actions. For example, if you want to prevent the user to be able to copy something from your web page, this is what you can do:

javascript
1p.addEventListener("copy", (event) => {
2  event.preventDefault();
3  event.clipboardData.setData("text/plain", "You cannot copy this content.");
4
5  alert("You cannot copy this content.");
6});

The setData() method will copy the string "You cannot copy this content." to the clipboard.

Loading events

The moment the HTML document finishes loading, a load event will be fired. This is useful when you need to schedule some initialization actions for your web page.

javascript
1window.addEventListener("load", () => {
2  alert("Page loaded.");
3});

The load event for the entire page is fired on the window, so you must attach the event listener to the global window object in order to catch this event.

External resources such as images, videos, and scripts will also fire a load event the moment they are done loading.

The load event do not propagate either, because an image finished loading does not mean its parent also just finished loading.

When you close a webpage, a beforeunload event will be fired before the web page is actually closed. It is often used to pop up an alert box to verify that the user wants to leave the page.

javascript
1window.addEventListener("beforeunload", (event) => {
2  event.preventDefault();
3});

confirm before close

Notice that the pop up alert is triggered by event.preventDefault(), not the alert() function, because in this case, we need to prevent the default action from happening, which is closing the webpage.

In conclusion

As a summary, here are all the events we have discussed in this lesson:

EventHTML attributeFires when
mouseoveronmouseoverThe pointer moves onto an element
mousemoveonmousemoveThe pointer moves on top of the button
mousedownonmousedownA mouse button is pressed down
mouseuponmouseupA mouse button is released
clickonclickRight after the mouse button is released
dblclickondblclickAfter two click events are fired very closely
scrollonscrollScrolling over an element
keydownonkeydownA key is pressed down
keyuponkeyupA key is released
keypressonkeypressRight after the key is released
focusonfocusA form input is in focus
bluronblurA form input loses focus
inputoninputA form input receives user input
submitonsubmitA form is being submitted
copyoncopyThe content in an element is being copied
cutoncutThe content in an element is being cut
pasteonpasteNew content is being pastes into the element
loadonloadThe page or resources finished loading
beforeunloadonbeforeunloadBefore the page is closed