Course: JavaScript

Progress (0%)

  1. Foundation

  2. Numbers

  3. Strings

  4. Conditions

  5. Loops

  6. Arrays

  7. Functions

  8. Objects

  9. Exceptions

  10. HTML DOM

  11. CSSOM

  12. Events

  13. Drag and Drop

  14. opt Touch Events

  15. Misc

  16. Project: Analog Clock

JavaScript Hash Change Event

Chapter 66 7 mins

Learning outcomes:

  1. When does hashchange fire
  2. The hash/anchor in a URL
  3. Handling hashchange
  4. Things to note while working with hashchange

Introduction

These days, single-page applications (SPAs) are pretty common on the web. They rely on heavy amounts of careful AJAX programming, sometimes also coupled with hash-based URL navigation.

The latter here requires us to know about the hashchange event in JavaScript — when does it fire and how to use it to power features alongside navigation.

Let's dive right into exploring the event...

Understanding hashchange

The hashchange event fires every time the hash/anchor of the URL changes in the browser's address bar. The event's target is the window object.

Apart from window, hashchange doesn't fire on any other element.

Let's first understand what and where is the hash in a given URL. Shown below is a simple URL pointing to some dummy location.

The part of the URL after the hash symbol (#), including the symbol, is called the hash, or the anchor.

Originally, the hash was meant to allow navigating to any element with a given id (since ids are unique).

For instance, if we have an element with id='section1' on the webpage www.example.com/home, then going to www.example.com/home#section1 would scroll the document to that very element.

However, these days, anchors in a URL don't always have corresponding elements — rather they're used for JavaScript-driven navigation. This is because of two reasons:

  1. Anchor changes are reflected in the browser's history.
  2. Anchor changes don't cause a page reload.

Anyways, coming back to our event, whenever the hash/anchor of the current page's URL changes, JavaScript fires the hashchange event.

Handling the event

Let's try to create a simple program that logs a static message each time the URL's hash changes.

First, we need to set up the handler for hashchange. For now, we'll go with the onhashchange property on window, but you could also use addEventListener() for the job.

window.onhashchange = function() {
    // code goes here
}

Then, inside the handler function, we put the log statement.

window.onhashchange = function() {
    console.log('Hash changed!');
}

Now it would be very tedious to go on to the address bar and manually change the hash. Won't it be better to create some links that change the hash itself? Sounds convincing.

Below we create 3 HTML <a> links with href pointing to '#sect1', '#sect2' and '#sect3', respectively.

<a href="#sect1">Go to #sect1</a>
<a href="#sect2">Go to #sect2</a>
<a href="#sect3">Go to #sect3</a>

As soon as we click one of these, the URL's hash in the address bar changes.

Since, in this case there are no elements on the page with id equal to 'sect1', 'sect2' or 'sect3', visiting the links above won't cause a scroll change in the document. However, if we put such elements in the document, then pressing a link would change the URL and scroll the document to the exact location where the corresponding element lies.

With all this in place, let's try our example.

Live Example

Another example

One example is good. But two are better?

Let's consider one more example of handling the hashchange event.

As before, we have to log a message to the console each time the hash changes, but this time instead of showing a static message, we ought to display the new and the previous URL.

Doesn't sound difficult, does it?

To start with, we save the current URL of the document in a variable currentURL and then create another variable prevURL to hold the previous URL. Initially, since there is no previous URL, prevURL remains undefined.

var prevURL;
var currentURL = window.location.href;

Next, we set up the handler for hashchange. When the handler fires, it means that the URL's hash has changed, likewise we assign currentURL to prevURL, and then update the currentURL to window.location.

var prevURL;
var currentURL = window.location.href;

window.onhashchange = function() {
    prevURL = currentURL;
    currentURL = window.location.href;
}

With both the desired URLs in hand, our last step would be to log them:

var prevURL;
var currentURL = window.location.href;

window.onhashchange = function() {
    prevURL = currentURL;
    currentURL = window.location.href;

    console.log('Previous URL:', prevURL);
    console.log('Current URL:', currentURL);
}

Let's try a live example:

Live Example

Things to note

While working with the hashchange event, there are certain things to take note of.

First of them is as follows:

The hashchange event fires only when there is a change in the hash part of the URL. This means that when a page is loaded with a given hash to start with, the hashchange event doesn't fire.

Why?

Simply because in this case, no change has occurred in the hash. The page was requested for with a certain hash already in the URL — that hash doesn't constitute a change in the URL.

Alright, but why is knowing this important?

To make sure that if we have a feature in our application that takes place when the hash becomes equal to some value, it takes place even when the underlying document is loaded along with the hash in the URL (i.e. there is no hash change).

To do so, we put the code for the feature additionally outside the handler for hashchange as well, in order to put it into action if the document's URL initially had the hash.

Secondly, as mentioned above, the hashchange event has only one possible target — window.

Apart from window, the event doesn't fire on any other element/object.

This means that the following bunch of statements are useless to handle any hash changes in the URL:

document.onhashchange = handlerFunction; // useless document.documentElement.onhashchange = handlerFunction; // useless

The event never fires on the given element nodes document and document.documentElement, and any other node; likewise the given handlers won't ever get called!

The one and only way is the use window:

window.onhashchange = handlerFunction;

In conclusion

The hashchange event is quite useful in today's complex era of web technologies. Numerous applications out there utilise it, coupled with AJAX to power navigation, without needing to reload the whole page.

As you learn more and more concepts in JavaScript, you'll be able to work with hashchange and appreciate its significance even more.