Evil Nodoer
Evil Nodoer

Reputation: 1957

Backbone Router navigate and anchor href

In a backbone-enabled app, I have seen code that continues to use <a href="#foo"></a>, while the anchor click is handled by a backbone event handler.

Alternatively, the navigation to #foo can be handled by:

Router.history.navigate("foo");

I believe the latter is the superior approach because it allows easy migration to and from HTML5's pushState functionality. And if we do use pushState, Backbone would be able to gracefully degrade to #foo for browsers that do not support pushState.

As I am still new to Backbone, can someone more experienced and knowledgable confirm that this is the case?

Upvotes: 23

Views: 21145

Answers (4)

Pierre Ingmansson
Pierre Ingmansson

Reputation: 61

Chris' answer is awesome, but there's one addition to it that makes it even better. Backbone.history.navigate() actually returns true or false telling us if it could route to it internally. We can therefore skip the data-bypass attribute and do the following instead:

$(document).on("click", "a", function(evt) {
  var href = { prop: $(this).prop("href"), attr: $(this).attr("href") };
  var root = location.protocol + "//" + location.host + Backbone.history.options.root;

  if (href.prop && href.prop.slice(0, root.length) === root) {
    if (Backbone.history.navigate(href.attr, true)) {
      evt.preventDefault();
    }
  }
});

Upvotes: 3

Chris Salzberg
Chris Salzberg

Reputation: 27374

I personally have pushState enabled and use the approach taken in Tim Branyen's backbone-boilerplate of adding a click handler that sends all link clicks to navigate unless they have a data-bypass attribute:

$(document).on("click", "a:not([data-bypass])", function(evt) {
  var href = { prop: $(this).prop("href"), attr: $(this).attr("href") };
  var root = location.protocol + "//" + location.host + Backbone.history.options.root;

  if (href.prop && href.prop.slice(0, root.length) === root) {
    evt.preventDefault();
    Backbone.history.navigate(href.attr, true);
  }
});

This works pretty well and as @nickf mentions has the advantage that you don't have to use the hash/hashbang hack, even for browsers that do not support pushState.

Upvotes: 54

nickf
nickf

Reputation: 546443

You should write your links as their "proper" addresses, that is, not with the hash which is just a hack to get around some deficiencies of a particular browser. To then make it all work, attach a click handler to catch clicks on these items and pass the urls to Backbone.history, which can then use pushState or convert to a hashbang'd url if needed. For example:

$(document).on('click', 'a[href^="/"]', function (event) {
    // here, ensure that it was a left-mouse-button click. middle click should be
    // allowed to pass through
    event.preventDefault();
    Backbone.history.navigate(this.href);
});

Upvotes: 6

golf
golf

Reputation: 354

Yes I try to use as much Router.history.navigate as I can in my Backbone apps. This also has the benefit of if the user types in the URL "/foo" in their browser, Backbone routes it properly. Obviously if it is an external link or something you don't want to handle with Backbone then you should not include it.

Upvotes: 1

Related Questions