Sunday, June 3, 2012

Detecting Back Button/Hash Change in URL


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.


Source: Tips4all

10 comments:

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

    ReplyDelete
  2. 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).

    ReplyDelete
  3. 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/balupton/History.js

    ReplyDelete
  4. 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 appropriatly 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!

    ReplyDelete
  5. I've never attempted to do this, but it seems like this has been discussed on the internet.

    Here looks to be a good place to start:
    http://www.hunlock.com/blogs/Mastering_The_Back_Button_With_Javascript

    ReplyDelete
  6. 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();

    ReplyDelete
  7. Sounds like SammyJS is what you needed.

    http://sammyjs.org/

    ReplyDelete
  8. I used a jquery plugin and wrote a YUI History like interface on top of it.

    http://jstalkies.blogspot.com/2009/10/history-utility.html

    Check it out once. If you need help I can help

    ReplyDelete
  9. Take a look to this tutorial of Single Page Interface web sites

    ReplyDelete
  10. Try simple & lightweight PathJS lib.

    Simple example:

    Path.map("#/page").to(function(){
    alert('page!');
    });

    ReplyDelete