Interactive systems, such as websites in a browser or even the terminal, are arranged according to the same principle. They load, then go into a waiting mode, and wait for the user to perform an action. Such actions include clicks, typing, mouse movements, keyboard shortcuts, and so on.
From the code's perspective, there are events representing all actions. Let's observe some popular events:
click
submit
keyup
keydown
focus
contextmenu
mouseover
mousedown
mouseup
The events are highly detailed. Even typing a letter is split into two events: pressing the key and releasing the key. In addition, we can distinguish hotkeys from regular input with the help of the keypress
event.
Any event will be associated with a specific element in the DOM. Imagine you need to add a new behavior. You should find any element and add a callback to the addEventListener()
method. The program will call it when an event occurs:
<button id="myButton"></button>
const button = document.getElementById('myButton');
// Adding the handler, called when we click a button element
button.addEventListener('click', () => alert('Boom 1!'));
// Adding the second handler
button.addEventListener('click', () => alert('Boom 2!'));
Each event handler is a function that gets called when an event occurs. These handlers run one by one, following the order they were defined.
If necessary, you can delete the handler, although this is rare in practice:
const button = document.getElementById('myButton');
const handler = () => alert('Boom 1!');
button.addEventListener('click', handler);
// It's important to pass the same function here by reference
button.removeEventListener('click', handler);
We can call events programmatically. For example, this is relevant for focus.
Imagine that you open a chat hoping to write a message there, but no text appears. You need to focus on the input field to type.
By default, this doesn't happen, and this is where we come in:
const input = document.getElementById('textInput');
// The cursor appears in the input field
// Try changing channels in Slack
// You will see that the input field is focused automatically
input.focus();
How to test
You should use events in the browser regularly to understand how they work. The easiest way to do this is as follows:
- Open the console on any site. See where you can find the kind of elements you want to work with, such as buttons or forms
- Choose any element you want to practice. For simplicity's sake, you can take
body
- Add a handler to it
- Call an event, and you'll see a reaction
const element = document.body;
element.addEventListener('click', () => console.log('wow!'));
// Now you can click on any part of the site
wow!
// If you need a form element
// Select the first input it encounters
const element2 = document.querySelector('input');
// We hang the handler and display everything we need
element2.addEventListener('keyup', () => console.log('pressed!'));
It is how you can test any event on any site.
Event object
Each event that occurs has information associated with it, which depends on the type of event. For example, the click
event involves the click and its coordinates — the point on the screen. This information is available through an event object passed to the event handler. Event objects are passed to any handler always as a single parameter:
<div id="myElement">Boom!</div>
const button = document.getElementById('myElement');
button.addEventListener('click', (event) => {
// Regular object
console.log(event);
// Coordinates of the point where the click occurred
console.log(event.clientX);
console.log(event.clientY);
});
Each click on the button will cause a new event
object with its values corresponding to the current event. The event
is an ordinary object filled with many properties which are easiest to learn directly in the browser. Different events have both common properties and specific ones.
For example, a click has coordinates, and a keystroke has its value. For more information about the properties, see the documentation.
General properties:
event.target
is the DOM element where the event occurred. It's the easiest way to get the data needed after the eventevent. type
is the event's name, for example,click
,keyup
, and so on
As an example, let's look at the task of validating the entered password. We'll highlight the input field with a red frame if the password is too short:
See the Pen js_dom_events by Hexlet (@hexlet) on CodePen.
Default action
For some elements, the browser performs a default action when certain events are triggered. For example, if we put a handler for clicking on a link, it will suddenly take us to another page, the one specified in the href
attribute.
Here we can see an example of the default action itself, which isn't affected by the presence of handlers. If you cancel this action, you should call the event.preventDefault()
method inside the handler:
<a href="#" id="myElement">Boom!</a>
const button = document.getElementById('myElement');
button.addEventListener('click', (e) => {
// If you do not do this, the browser will load a new page
e.preventDefault();
alert(e.target.textContent);
});
The following elements have default actions:
- Clicking on a link takes you to the page specified in the
href
attribute - Clicking a Submit button starts sending the form to the server
- Rotating the mouse wheel in
textarea
moves the text if it doesn't fit - Right-click context menu call
Competition between events
While we execute handlers, new events may occur both from user actions and automated actions from the handlers themselves. Some events always happen as a whole block — for example, mouseup and click. But this doesn't mean that the execution of the code will automatically drop everything and switch over to processing these events. Instead, events are queued and executed sequentially.
But some events are still taken into processing immediately. It applies to events that are generated programmatically, for example, focus.
You may wonder what happens to the page while we execute the handler. And there are a few possible options here.
If the handler executes some code synchronously, such as making calculations, everything else stops, and the page freezes. If this behavior lasts too long, some browsers will freeze, and others will suggest closing the tab. Here we can conclude that handlers should perform their task as soon as possible.
But what if we have a synchronous tab, such as a request being made to the server? In this case, everything works OK, since HTTP requests do not block code execution.
This lesson may make it clear why JavaScript is the way it is. The event system is possible only in asynchronous code. Essentially, when a page loads, the handlers are initialized and installed, and then, as a rule, no code is executed; the entire page waits for actions from the user.
Common mistakes
Quite often, beginners get confused about functions. Instead of the function itself, they pass the result of the function call to the handler:
const button = document.getElementById('myElement');
const handler = () => {
alert('Click!');
};
button.addEventListener('click', handler());
The handler()
function is executed when the handler is hovered over the event, instead of the function itself the result of the handler()
call will be passed.
Are there any more questions? Ask them in the Discussion section.
The Hexlet support team or other students will answer you.
For full access to the course you need a professional subscription.
A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.