1

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Alpaus
  • 646
  • 1
  • 7
  • 21
  • maybe this can help https://github.com/lautr/asfar a jquery plugin i wrote a while back, might fit your situation better then BBQ – Hannes Jan 25 '12 at 08:27
  • @Hannes thanks very much, this looks very interesting, and currently suits me perfectly as I am populating the same div for all current ajax calls. I don't really understand how it works though, in that everything I have read so far tells me that you can't update the URL location/address bar with anything except # without triggering a page reload. How are you achieving this? – Alpaus Jan 25 '12 at 08:35
  • Dark magic ... and the http://www.w3.org/TR/html5/history.html which is (of course) not supported by some IE Versions, but if the browser does not support the HTML5 History Interface a Hash Fallback is applied, which works just as well – Hannes Jan 25 '12 at 09:18
  • Thanks again @Hannes. I will look at your plugin as it's a nicer solution to not see # in the address bar of the browser (if you're using a non-IE browser) but in the meantime, your solution led me to re-think my own problem and see it as a benefit, not a problem. As a valid url is always perfectly delimited by slashes i.e. /action/parameter I was able to use this to my advantage, also using Ben Alman's hashchange plugin. I will post my final solution for reference (or for anyone to tell me if there is anything I've done wrong). Thanks! – Alpaus Jan 25 '12 at 11:29

2 Answers2

0

That's pretty complicated. However, you can use the lower level jQuery the BBQ is built on top of... See the param and deparam areas of Ben Alman's site. You can use $.param.fragment(); or $.param.querystring to return and push values without the hashes. You can restructure the querystring to represent your apache rewriting before you push the querystring.

Lamariffic
  • 309
  • 1
  • 6
0

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();

});
Alpaus
  • 646
  • 1
  • 7
  • 21