Introduction

Loading is a crucial topic in the world of web development. Developers are nearly always working to get their websites to load ASAP.

JavaScript with its huge inventory of events doesn't put loading aside. It provides an array of events to operate around different areas of loading and allow the developer to tailor all these areas according to the application's needs.

In this chapter, we'll take a look over four different events under the category of loading and see how can we use them to take the interactivity of our webpages to a whole new level.

The load event

For a given resource-fetching HTML element (such as <link>, <script>), the moment it loads completely, it dispatches a load event.

The load event is one of the most useful and most handled events in JavaScript. At some point in time, we all do want to run a piece of code when a script has been completelyexecuted, a stylesheet has been completely parsed, an audio file has been downloaded, and so on.

Let's consider a quick example. Say we want to make a log right after the following image is completely downloaded.

<img src="image.png">

To do so, we'll need to work with the onload handler of the <img> element.

var img = document.getElementsByTagName("img")[0];
img.onload = function() {
    console.log("Image completely loaded");
}

The moment the image is completely downloaded and parsed, its load event will occur and thereby the onload handler defined in line 2 will be invoked. This will result in a console log being made.

We're assuming that the script above comes after the <img> tag in the html as shown below:
<img src="image.png">
<script> /* code goes here */ </script>

Moving on, the most interesting aspect of the load event is that it's also available on the whole HTML document i.e the window object.

This means that we can track when the whole document gets loaded, and consequently execute any piece of code at this point.

However, when we talk about the loading of the whole document, we need to specifically define the meaning of this - does the loading take into account sub-resources such as external scripts, stylesheets, etc.

For an HTML document, its load event fires when all of its underlying resources are completely fetched, parsed and executed.

In contrast, the load event for, let's say, a stylesheet fires when the stylesheet itself loads completely - any underlying subresource like a background image isn't considered.

Consider the following HTML:

<!DOCTYPE html>
<html>
<body>
    <!-- a resource-fetching tag -->
    <img src="image.png">
</body>
</html>

All we have here is an image element and nothing else. Now using this HTML, we shall demonstrate the behaviour of the load event of window.

Suppose we have the following script right after the <img> element shown above:

window.onload = function() {
    console.log("Everything has been loaded!");
}

And with this also suppose that the image takes a decent amount of time to be loaded; somewhere around 3 seconds.

The log here will be made when the load event fires on the whole HTML document and this will happen only when all its underlying resources are processed completely. That is, it'll fire when the image element loads completely which takes approximately 3 seconds.

Live Example

The onload event works differently only for an HTML document i.e it fires only when all the underlying resources are loaded as well.

If we had a couple more resource-fetching elements here such as <link>, <script>, <audio> etc, instead of just a single <img> element, then load would've fired when all of them finished loading.

Many browsers display a loading spinner while a website is loading uptil the point the load event is dispatched. And we all know, websites that keep the spinner spinning for long give a not-so-good impression.

Therefore, it's recommended to developers that they construct websites in a way that they load as quickly as possible, and put the spinners to a halt in no time! This requires understanding a couple of topics such as asynchronous loading and lazy loading.

Things to note!

While working with the load event, one needs to remember a couple more things.

Firstly, the onload handler on window is equal to onload handler on document. In other words, handling load on window or document is interchangeable.

The following two snippets are, likewise, identical:

window.onload = function() {
    console.log("Loaded completely!")
}
document.onload = function() {
    console.log("Loaded completely!");
}

Secondly, the load event doesn't fire on every HTML element - it works only on resource-fetching tags like <link>, <script>, <img>, <iframe>, <audio>, <video> and so on.

Even logically, the following code doesn't make sense:

<p onload="console.log('Paragraph loaded!')">A paragraph</p>

Anyways, a couple of more examples with onload follow.

Here we call someFunction() when the stylesheet loads:

<link rel="stylesheet" href="styles.css" onload="someFunction()">

Here we dynamically create a stylesheet in JavaScript and wait for it to load, after which we make a log in the console:

var stylesheet = document.createElement("link");
stylesheet.onload = function() {
    console.log("Stylesheet loaded!");
}
stylesheet.rel = "stylesheet";
stylesheet.href = "styles.css";
document.head.appendChild(stylesheet); // append element to make a request for it

Before the load event

It's good to know that load takes into account all resources of an HTML document before getting fired. However, if one doesn't want to take this deal then what?

Say you want to execute some script as soon as the document itself loads completely - underlying resources may still be in the process of completion.

In these cases, what you need is the DOMContentLoaded event.

DOMContentLoaded fires when a webpage's DOM tree is fully constructed.

The DOM tree of a webpage finishes constructing when all of its markup is completely parsed and executed. This means that DOMContentLoaded fires when a webpage is itself parsed fully.

Unlike load, this event doesn't wait for underlying resources such as images, iframes, audio, video etc - as soon as the HTML is itself loaded, it fires.

Some important things to note about this event are shown as follows:

  1. Unlike nearly all JavaScript events, DOMContentLoaded does NOT have a corresponding onDOMContentLoaded event property. It can be used with the JavaScript event listener method only i.e addEventListener().
  2. Unlike all event names in JavaScript such as load, mousemove and so on, DOMContentLoaded doesn't follow lower casing (as you can see from the start of its name).
  3. It only fires on the document object. Any other object for example, window, or document.body isn't a target of this event.

Fulfilling all the conditions given above we arrive at the following code:

document.addEventListener("DOMContentLoaded", function() {
    console.log("Content loaded!");
});

Now add this code to the previous example with onload and notice that it will be logged before onload since it doesn't need to wait for the loading of any underlying resource.

Live Example

Following is a showcase of some of the illegal ways to use the event DOMContentLoaded:

// There is nothing like this
document.onDOMContentLoaded = function() {
    console.log("Content loaded!");
}

// or even this
document.DOMContentLoaded = function() {
    console.log("Content loaded!");
}

// or even this!
window.addEventListener("DOMContentLoaded", function() {
    console.log("Content loaded!");
});

onbeforeunload

onbeforeunload occurs just before the browser is closed. It can be used, for an example, to ask a confirmation from the user whether he really wants to exit the page or not.

window.onbeforeunload = function(e) {
    e.preventDefault(); // cancel default action
    e.returnValue = ""; // cancel default action and show a confirm dialog
}

Usually to cancel the default behaviour of any event we use the preventDefault() method on the event object and we can do so with onbeforeunload too. But the problem with this is that some browsers don't consider the method preventDefault() inside this event.

Hence for them we need to fallback with the returnValue property. The property prevents the default action, and shows a confirm dialog to the end user.

Unfortunately there is no way to show a custom confirm box with this property so you'll have to stay happy with what's given!

Handling errors

It's not surprising to know that when requesting for a resource, there's is a likelihood of something fishy happening on the backend or to the network connection, leading to an error in the response.

Luckily JavaScript has an event for dealing with such cases too - error.

For a given resource-fetching element, the error event fires when somehow the underlying resource can't be fetched, because the user's network is disabled, or the server returns a error response, or some other reason.

Below is an instance where this event takes place.

We have an <img> element refering to an image that just doesn't exist! Likewise the error event will take over.

<img src="nonExistentImage.png">
var img = document.getElementsByTagName("img")[0];

// Handing the error case for the img
img.onerror = function() {
    alert("An error occured!");
}

Live Example

The error event doesn't work for the HTML document. This is because if the main HTML page fails, then it means that nothing regarding the page is downloaded and likewise nothing is executed!

The browser handles document-level failures on its own. The same doesn't apply for HTML documents loaded using AJAX or otherwise, as in iframes.