An event is a signal that something has happened. All DOM nodes generate such signals (but events are not limited to DOM).
Here’s a list of the most useful DOM events, just to take a look at:
- – when the mouse clicks on an element (touchscreen devices generate it on a tap).
- – when the mouse right-clicks on an element.
- / – when the mouse cursor comes over / leaves an element.
- / – when the mouse button is pressed / released over an element.
- – when the mouse is moved.
Form element events:
- – when the visitor submits a .
- – when the visitor focuses on an element, e.g. on an .
- and – when the visitor presses and then releases the button.
- – when the HTML is loaded and processed, DOM is fully built.
- – when a CSS-animation finishes.
There are many other events. We’ll get into more details of particular events in next chapters.
To react on events we can assign a handler – a function that runs in case of an event.
There are several ways to assign a handler. Let’s see them, starting from the simplest one.
A handler can be set in HTML with an attribute named .
For instance, to assign a handler for an , we can use , like here:
On mouse click, the code inside runs.
Please note that inside we use single quotes, because the attribute itself is in double quotes. If we forget that the code is inside the attribute and use double quotes inside, like this: , then it won’t work right.
Here a click runs the function :
As we know, HTML attribute names are not case-sensitive, so works as well as and … But usually attributes are lowercased: .
We can assign a handler using a DOM property .
For instance, :
If the handler is assigned using an HTML-attribute then the browser reads it, creates a new function from the attribute content and writes it to the DOM property.
So this way is actually the same as the previous one.
The handler is always in the DOM property: the HTML-attribute is just one of the ways to initialize it.
These two code pieces work the same:
HTML + JS:
As there’s only one property, we can’t assign more than one event handler.
By the way, we can assign an existing function as a handler directly:
To remove a handler – assign .
Accessing the element: this
The value of inside a handler is the element. The one which has the handler on it.
In the code below shows its contents using :
If you’re starting to work with event – please note some subtleties.
The function should be assigned as , not .
If we add brackets, then – will be the result of the function execution, so in the last code becomes (the function returns nothing). That won’t work.
…But in the markup we do need the brackets:
The difference is easy to explain. When the browser reads the attribute, it creates a handler function with the body from its content.
So the last example is the same as:
Use functions, not strings.
The assignment would work too. It works for compatibility reasons, but strongly not recommended.
Don’t use for handlers.
Such a call won’t work:
DOM-property case matters.
Assign a handler to , not , because DOM properties are case-sensitive.
The fundamental problem of the aforementioned ways to assign handlers – we can’t assign multiple handlers to one event.
For instance, one part of our code wants to highlight a button on click, and another one wants to show a message.
We’d like to assign two event handlers for that. But a new DOM property will overwrite the existing one:
Web-standard developers understood that long ago and suggested an alternative way of managing handlers using special methods and . They are free of such a problem.
The syntax to add a handler:
- Event name, e.g. .
- The handler function.
- An optional argument, the “phase” for the handler to work. To be covered later. Usually we don’t use it.
To remove the handler, use :
To remove a handler we should pass exactly the same function as was assigned.
That doesn’t work:
The handler won’t be removed, because gets another function – with the same code, but that doesn’t matter.
Here’s the right way:
Please note – if we don’t store the function in a variable, then we can’t remove it. There’s no way to “read back” handlers assigned by .
Multiple calls to allow to add multiple handlers, like this:
As we can see in the example above, we can set handlers both using a DOM-property and . But generally we use only one of these ways.
There exist events that can’t be assigned via a DOM-property. Must use .
For instance, the event (CSS animation finished) is like that.
Try the code below. In most browsers only the second handler works, not the first one.
To properly handle an event we’d want to know more about what’s happened. Not just a “click” or a “keypress”, but what were the pointer coordinates? Which key was pressed? And so on.
When an event happens, the browser creates an event object, puts details into it and passes it as an argument to the handler.
Here’s an example of getting mouse coordinates from the event object:
Some properties of object:
- Event type, here it’s .
- Element that handled the event. That’s exactly the same as , unless you bind to something else, and then becomes useful.
- Window-relative coordinates of the cursor, for mouse events.
There are more properties. They depend on the event type, so we’ll study them later when come to different events in details.
If we assign a handler in HTML, we can also use the object, like this:
That’s possible because when the browser reads the attribute, it creates a handler like this: . That is: its first argument is called , and the body is taken from the attribute.
Object handlers: handleEvent
We can assign an object as an event handler using . When an event occurs, its method is called with it.
In other words, when receives an object as the handler, it calls in case of an event.
We could also use a class for that:
Here the same object handles both events. Please note that we need to explicitly setup the events to listen using . The object only gets and here, not any other types of events.
The method does not have to do all the job by itself. It can call other event-specific methods instead, like this:
Now event handlers are clearly separated, that may be easier to support.
There are 3 ways to assign event handlers:
- HTML attribute: .
- DOM property: .
- Methods: to add, to remove.
DOM properties are ok to use, but we can’t assign more than one handler of the particular event. In many cases that limitation is not pressing.
The last way is the most flexible, but it is also the longest to write. There are few events that only work with it, for instance and (to be covered). Also supports objects as event handlers. In that case the method is called in case of the event.
No matter how you assign the handler – it gets an event object as the first argument. That object contains the details about what’s happened.
We’ll learn more about events in general and about different types of events in the next chapters.
An element receives a focus when the user either clicks on it or uses the key on the keyboard. There’s also an HTML attribute that puts the focus into an element by default when a page loads and other means of getting a focus.
Focusing generally means: “prepare to accept the data here”, so that’s the moment when we can run the code to initialize or load something.
The moment of losing the focus (“blur”) can be even more important. That’s when a user clicks somewhere else or presses to go to the next form field, or there are other means as well.
Losing the focus generally means: “the data has been entered”, so we can run the code to check it or even to save it to the server and so on.
There are important peculiarities when working with focus events. We’ll do the best to cover them here.
The event is called on focusing, and – when the element loses the focus.
Let’s use them for validation of an input field.
In the example below:
- The handler checks if the field the email is entered, and if not – shows an error.
- The handler hides the error message (on it will be checked again):
Methods and set/unset the focus on the element.
For instance, let’s make the visitor unable to leave the input if the value is invalid:
It works in all browsers except Firefox (bug).
If we enter something into the input and then try to use or click away from the , then returns the focus back.
Please note that we can’t “prevent losing focus” by calling in , because works after the element lost the focus.
A focus loss can occur for many reasons.
- An moves focus to itself, so it causes the focus loss at the element ( event), and when the is dismissed, the focus comes back ( event).
- If an element is removed from DOM, then it also causes the focus loss. If it is reinserted later, then the focus doesn’t return.
These features sometimes cause handlers to misbehave – to trigger when they are not needed.
The best recipe is to be careful when using these events. If we want to track user-initiated focus-loss, then we should evade causing it by ourselves.
Allow focusing on any element: tabindex
By default many elements do not support focusing.
The list varies between browsers, but one thing is always correct: support is guaranteed for elements that a visitor can interact with: , , , and so on.
From the other hand, elements that exist to format something like , , – are unfocusable by default. The method doesn’t work on them, and events are never triggered.
This can be changed using HTML-attribute .
The purpose of this attribute is to specify the order number of the element when is used to switch between them.
That is: if we have two elements, the first has , and the second has , then pressing while in the first element – moves us to the second one.
There are two special values:
- makes the element the last one.
- means that should ignore that element.
Any element supports focusing if it has .
For instance, here’s a list. Click the first item and press :
The order is like this: (zero is always the last). Normally, does not support focusing, but full enables it, along with events and styling with .
Events and do not bubble.
For instance, we can’t put on the to highlight it, like this:
The example above doesn’t work, because when user focuses on an , the event triggers on that input only. It doesn’t bubble up. So never triggers.
There are two solutions.
First, there’s a funny historical feature: do not bubble up, but propagate down on the capturing phase.
This will work:
Second, there are and events – exactly the same as , but they bubble.
Note that they must be assigned using , not .
So here’s another working variant:
Events and trigger on focusing/losing focus on the element.
Their specials are:
- They do not bubble. Can use capturing state instead or .
- Most elements do not support focus by default. Use to make anything focusable.
The current focused element is available as .