Detecting Back Button/Hash Change in URL
Asked Answered
S

7

63

I just set up my new homepage at http://ritter.vg. I'm using jQuery, but very minimally.
It loads all the pages using AJAX - I have it set up to allow bookmarking by detecting the hash in the URL.

 //general functions
 function getUrl(u) {
      return u + '.html';
 }
 function loadURL(u)    {
      $.get(getUrl(u), function(r){
                $('#main').html(r);
           }
      );
 }
 //allows bookmarking
 var hash = new String(document.location).indexOf("#");
 if(hash > 0)
 {
      page = new String(document.location).substring(hash + 1);
      if(page.length > 1)
        loadURL(page);
      else
        loadURL('news');
 }
 else
      loadURL('news');

But I can't get the back and forward buttons to work.

Is there a way to detect when the back button has been pressed (or detect when the hash changes) without using a setInterval loop? When I tried those with .2 and 1 second timeouts, it pegged my CPU.

Sleight answered 6/10, 2008 at 1:18 Comment(1)
Rather than aiming for the HTML4 hashchange event; there is now the HTML5 History API which super-seeds it. Here is a good reference.Attraction
P
31

Use the jQuery hashchange event plugin instead. Regarding your full ajax navigation, try to have SEO friendly ajax. Otherwise your pages shown nothing in browsers with JavaScript limitations.

Pastor answered 6/10, 2008 at 2:46 Comment(1)
Nowadays you can use the HTML5 API for this.Servais
S
51

The answers here are all quite old.

In the HTML5 world, you should the use onpopstate event.

window.onpopstate = function(event)
{
    alert("location: " + document.location + ", state: " + JSON.stringify(event.state));
};

Or:

window.addEventListener('popstate', function(event)
{
    alert("location: " + document.location + ", state: " + JSON.stringify(event.state));
});

The latter snippet allows multiple event handlers to exist, whereas the former will replace any existing handler which may cause hard-to-find bugs.

Servais answered 6/12, 2012 at 15:49 Comment(0)
P
31

Use the jQuery hashchange event plugin instead. Regarding your full ajax navigation, try to have SEO friendly ajax. Otherwise your pages shown nothing in browsers with JavaScript limitations.

Pastor answered 6/10, 2008 at 2:46 Comment(1)
Nowadays you can use the HTML5 API for this.Servais
P
12

jQuery BBQ (Back Button & Query Library)

A high quality hash-based browser history plugin and very much up-to-date (Jan 26, 2010) as of this writing (jQuery 1.4.1).

Priestly answered 3/2, 2010 at 16:42 Comment(0)
A
11

HTML5 has included a much better solution than using hashchange which is the HTML5 State Management APIs - https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history - they allow you to change the url of the page, without needing to use hashes!

Though the HTML5 State Functionality is only available to HTML5 Browsers. So you probably want to use something like History.js which provides a backwards compatible experience to HTML4 Browsers (via hashes, but still supports data and titles as well as the replaceState functionality).

You can read more about it here: https://github.com/browserstate/History.js

Attraction answered 30/1, 2011 at 14:2 Comment(0)
A
2

Another great implementation is balupton's jQuery History which will use the native onhashchange event if it is supported by the browser, if not it will use an iframe or interval appropriately for the browser to ensure all the expected functionality is successfully emulated. It also provides a nice interface to bind to certain states.

Another project worth noting as well is jQuery Ajaxy which is pretty much an extension for jQuery History to add ajax to the mix. As when you start using ajax with hashes it get's quite complicated!

Attraction answered 28/8, 2010 at 17:47 Comment(0)
P
1

I do the following, if you want to use it then paste it in some where and set your handler code in locationHashChanged(qs) where commented, and then call changeHashValue(hashQuery) every time you load an ajax request. Its not a quick-fix answer and there are none, so you will need to think about it and pass sensible hashQuery args (ie a=1&b=2) to changeHashValue(hashQuery) and then cater for each combination of said args in your locationHashChanged(qs) callback ...

// Add code below ...
function locationHashChanged(qs)
{
  var q = parseQs(qs);
  // ADD SOME CODE HERE TO LOAD YOUR PAGE ELEMS AS PER q !!
  // YOU SHOULD CATER FOR EACH hashQuery ATTRS COMBINATION
  //  THAT IS PASSED TO changeHashValue(hashQuery)
}

// CALL THIS FROM YOUR AJAX LOAD CODE EACH LOAD ...
function changeHashValue(hashQuery)
{
  stopHashListener();
  hashValue     = hashQuery;
  location.hash = hashQuery;
  startHashListener();
}

// AND DONT WORRY ABOUT ANYTHING BELOW ...
function checkIfHashChanged()
{
  var hashQuery = getHashQuery();
  if (hashQuery == hashValue)
    return;
  hashValue = hashQuery;
  locationHashChanged(hashQuery);
}

function parseQs(qs)
{
  var q = {};
  var pairs = qs.split('&');
  for (var idx in pairs) {
    var arg = pairs[idx].split('=');
    q[arg[0]] = arg[1];
  }
  return q;
}

function startHashListener()
{
  hashListener = setInterval(checkIfHashChanged, 1000);
}

function stopHashListener()
{
  if (hashListener != null)
    clearInterval(hashListener);
  hashListener = null;
}

function getHashQuery()
{
  return location.hash.replace(/^#/, '');
}

var hashListener = null;
var hashValue    = '';//getHashQuery();
startHashListener();
Pervasive answered 18/4, 2011 at 19:53 Comment(1)
Used this just to change the active link when using anchors to navigate my page.Epitomize
R
1

Try simple & lightweight PathJS lib.

Simple example:

Path.map("#/page").to(function(){
    alert('page!');
});
Ration answered 19/4, 2012 at 18:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.