jqueryfriendly-urljquery-bbq

jQuery BBQ plugin with PHP pretty URLs


I'm having trouble working out how to get started on jQuery's BBQ plugin to enable support for forward/back and bookmarking in my Ajax site, with pretty URLs.

I have pretty URLs for my PHP pages via Apache mod_rewrite rules so that http://example.org/store.php?cat_id=5 is accessible via http://example.org/store/5

These URLs are obviously only relevant when accessing a PHP page directly via the browser, as once the user has landed on the first page they visited and clicks any of the internal links, they are intercepted by my JavaScript code and the content is updated via Ajax (i.e. instead of reloading the page).

So, this means my back/forward and bookmark functionality doesn't work which is where I come to BBQ to try to implement that.

Looking at quite a few examples, I can't figure out how to make this work with pretty URLs, as my href tags don't already contain #. My href tags look like this:

<a class='cat_link' href='/store/5' data-cat-id='5'>

Clicking on that link results in the following jquery ajax request running:

$('#container').delegate(".cat_link", "click", function(){
    $.get('/views/tileview.php',{ cat_id: $(this).data('cat-id') }, function(result){
        $("#viewport").hide().html(result).fadeIn(750);
    });
});

which loads Ajax content from /views/tileview.php with GET parameter cat_id = 5 and loads the resulting HTML into the #viewport div.

Now, my question is, am I able to use the BBQ plugin to support the back/forward and bookmarking without altering my hrefs to include hashes in them (i.e. with current URLs)? Also, regardless of whether I need to change my URLs how do I handle the fact that the URLs are pretty and don't have 'parameters' in them in the '?=' sense?

My current implementation degrades without JavaScript code so that the links just take the visitor to the correct URL and they essentially see the same content (albeit with a full PHP page load instead of just an Ajax call and updated div). This is something I want to maintain whilst getting the back/forward and bookmarking support.


Solution

  • As per my comment above to @Hannes excellent response, I was able to use my pretty url formation to my advantage in the end by re-writing my event handlers to just trigger a hash change and then use the onhashchange event to make the ajax calls. I also included Ben Alman's hashchange plugin to ensure compatibility with IE and other browsers that don't have the hashchange functionality.

    $(document).ready(function(){
      //pre-load spinner image to ensure it's already cached before it's used
      var image = $('<img />').attr('src', '/js/spinner/ajax-loader.gif');
      var opts = {
                img: '/js/spinner/ajax-loader.gif',
                height: 42,
                width: 42,
                position: 'center',
                hide: true
            };
      var current_hash = '';
          //if this is a straight URL, cache the contents to use later in case 
          //  of back button being used to come back here
      if (window.location.hash == '') {
          var cache_viewport = $('#viewport').html();
      }
    
    $('#container').delegate(".cat_link", "click", function(){
        var href = $(this).attr('href');
        window.location.hash = "#" + href;
        return false;
       });
    
    $('#container').delegate(".product_tile_a", "click", function(){
        var href = $(this).attr('href');
        window.location.hash = "#" + href;
        return false;
       });
    
    
     $(window).hashchange(function(){
      var hash = window.location.hash;
          //if the new hash is a straight URL, reload the straight URL's html content
      if (hash == '') {
          $("#viewport").html(cache_viewport);
      }
      else if (hash != current_hash) {
        var strings = hash.split("/");
        var action = strings[1];
        var param = strings[2];
        current_hash = hash;
        callAjax(action, param);
    }
     });
    
     function callAjax(action, param) {
      switch(action) {
          case 'store':
            $("#viewport").spinner(opts);
            $.get('/views/tileview.php',{ cat_id: param }, function(result){   
                $("#viewport").spinner('remove'); 
                $("#viewport").hide().html(result).fadeIn(500);
                });
                break;
          case 'products':
            $("#viewport").spinner(opts);
            $.get('/views/productview.php',{ product_id: param },function(result){   
                $("#viewport").spinner('remove'); 
                $("#viewport").hide().html(result).fadeIn(500);
                });
                break;
          default:
            null;
        }
    }
    
     //ensures hashchange is called on initial load in case of a bookmarked hash
     $(window).hashchange();
    
    });