/ blog

Handling Hash

12 February 2008 · Estimated reading time: 4 minutes

No, I’m not talking about drug smuggling. I’m talking about the inconsistencies in how The Big 3 web browsers deal with window.location.hash.

I know, I know, you can’t believe what you’re reading. But it’s true! Firefox, Internet Explorer and Safari all behave differently in how they treat the JavaScript value window.location.hash. A stunning revelation, this.

As the web gets more AJAXy, the need for preserving state in URLs has grown. A way to meet this requirement that has been noticed to be in use on both Google and Yahoo properties is to add parameters to the URL, not with the traditional query string delimiter (?), but with the hash (#) sign instead.

This has the advantage of being something you can manipulate via JavaScript without forcing a page reload. Add a history entry at the same time and, violá, you just un-broke the back button!

At work, we had a similar requirement for a client site where, after registering, the user would round trip back to a Google Map with a particular info balloon open.

See it in action.

In implementing this functionality, I noticed that Firefox, IE and Safari handle the various cases (no hash, hash only, and hash + content) differently.

Essentially, the value of window.location.hash in all cases was either an empty string or a hash (optionally followed by content). The differences came in when you got which values. Here’s the breakdown:

Browser No Hash (test) Hash Only (test) Hash + Content (test)
Firefox 2 & 3 empty string empty string #content
Internet Explorer 6 & 7 empty string # #content
Safari 3 empty string empty string #content
Safari 2 empty string # #content

All browsers return an empty string when no hash mark is present. Great. All browsers return the hash mark plus whatever comes after it if both of those pieces are present. Super.

They differ in how they handle just the hash mark by itself. Firefox returns an empty string in this case. Internet Explorer returns the hash mark. Oh well.

What I find interesting is that Safari 2 behaves like IE, but Safari 3 behaves like Firefox. I wonder why the change?

In any case, in my code, the following is how I test for a valid hash value:

if ('' !== window.location.hash && '#' !== window.location.hash) {