Backbone.js routing without changing url

user2398029 picture user2398029 · Jun 27, 2013 · Viewed 8.5k times · Source

I am migrating a single-page web application based on Backbone.js and jQuery to a Chrome extension. However, neither the pushState nor the hashbang-based router modes seem to play well with the environment within the extension. I've come to the conclusion that I'm better off just directly rendering views on user interactions, bypassing the window.location system altogether. However, I'm not too sure how to implement this without changing calls to Router.navigate in dozens of files.

Is there a pluggable/modular way to keep the Backbone routing system but bypass any changes to the url?

Answer

Christophe Marois picture Christophe Marois · Jun 28, 2013

I you really want to stick with using Router.navigate to benefit from the routing system that Backbone.js provides without having to deal with hashbang bugs when used in a Chrome extension (e.g. routes including a slash being overwritten), you could make Router.navigate load the url directly, skipping the whole pushState gymnastic.

This is actually pretty easy to accomplish:

Router = Backbone.Router.extend({

  navigate: function (url) {

    // Override pushstate and load url directly
    Backbone.history.loadUrl(url);

  },

  // Put routes here
  routes: { }

});

You can then call Router.navigate(url) to load a new route without changing history, or even bind the action to every link containing a data-backbone attribute (e.g. <a href="login" data-backbone>Login</a>) with an event like this:

$(function(){

  // Initialize router
  Router = new Router;
  Backbone.history.start();

  // Bind a[data-backbone] to router
  $(document).on('click', 'a[data-backbone]', function(e){
    e.preventDefault();

    Router.navigate( $(this).attr('href') );
  });

});