Events and the event-loop - a JavaScript guide

We're going to learn about what the event-loop is and how we can use events in JavaScript.

If you're new to JavaScript you may want to start with my learn JavaScript tutorial.

Our first event

Let's see what happens when we run this simple script:

Press the button below to run the script again.

Notice how it says end? before it says Hi? The program is executed one line at a time, but line 2 doesn't log the word 'Hi' - instead it adds an event to the event loop that will get executed 1s in the future. As long as there are events in the event loop, the program is still running. On web pages, this means you can do things other than just on page load.

As well as adding one-off future jobs, we can set a job to run on a loop of a given time, for example to update the contents of an element on the page:

Adding a click handler

As well as setting timouts and intervals, we often want to add interactivity to our web pages. One of the simplest interactions is clicking an element. We can set an element up so that when it is clicked our function gets run. This function is called an event handler or callback function.

Click 'Button 1' below to see what happens.

Our functions can be created in the 'normal' way if we'd like - we don't have to use anonymous arrow functions. And the same function can be bound to multiple events.

Our event handler receives a single argument, which is the details of the event. It's common to call this parameter e or event (we'll be using e).

Sometimes you'll see event handlers added this way instead:

... while there is a slight difference between the 2 when it comes to binding multiple event handlers, we'll use the slightly shorter 1st version here.

Some other mouse events

A click is just one kind of event which we can listen for. When you're using a website, you're triggering loads of events as you move your mouse around and hit keys on the keyboard. Let's have a go at binding to a few more of them.

The mouseover event fires whenever our mouse enters the area of the element. There's also a mouseout event that fires when we leave the area, and mousemove whenever we move within it:

As you can see, the mousemove callback handler gets called a lot!

Pointer events

But what if the user is on a mobile device without a mouse? Rather than just listening for mouse events, these days it's more sensible to listen for pointer events instead (which includes mouse events). If we don't, we may have an awesome web page on desktop which is totally useless with touchscreens.

But fingers on a screen do work a bit different from a mouse. For one thing, most devices don't detect that a finger is hovering near the screen, they only track a finger when it's touching the screen. That's an issue we'll deal with later, but for now we'll just make sure to use pointer events rather than mouse events.

Drawing our pointer

We get lots of details of an event as an argument to our event listener, the parameter we're naming e. On pointermove this includes the x and y position of the pointer. In addition, we don't just have to listen for events on buttons - we can bind event handlers to any element.

Here we're listening for events on a <canvas> element, which we can easily draw to.

And maybe we could hook up our 'Button 1' so it clears the canvas when clicked.

Responding to the keyboard

Another way we may want to interact with the page is in response to the user pressing keys on the keyboard.

IMPORTANT: for these demos to work, you'll first have to click on the demo. If you're creating a stand-alone web page (as opposed to these demos which live in <iframes>) then this wouldn't be necessary.

Notice that here we're binding to window.onkeydown rather than an element's keydown. This is because we want to respond to keyboard presses regardless of which element on the page has focus.

Like mouse and pointer events, there are several key events too. Here we're binding to both keydown and keyup events.

Drawing with the keyboard

By default when we press keys on the keyboard the browser might do something with them. For example, when we press the arrow up/down keys, the page might scroll up and down. We can prevent those default actions with e.preventDefault().

Here, we have a very simple drawing app that responds to arrow keys rather than mouse or pointer movement.

Notice how you can't draw diagonally unless you keep alternating between one key and another? That's a bit annoying. Also, the keydown event gets fired when we press down on a key, then repeats after a bit of a delay. What if we want it smoother?

There's quite a bit more code now. We keep track of which keys are down in the keys {} object, then every 16ms (~60fps) we move in the direction of any active key and draw our current location. We'll be learning a lot more of this concept of changing the state then drawing the current state on a loop in the next guide on game loops.

Other events

There are a whole host of other events you can attach your own event listener functions to. You can find a list of events you can attach to elements or events you can attach to the window, both on MDN.

What next?

Try out some of the events you've learnt about here, or explore some of the others on MDN with the links above.

If you liked this guide, you may want to try the next guide in this series, on game loops. Alternatively, there's an an interactive introduction to JavaScript and an advanced guide on rigid-body collisions