37

If I enable pushState in the backbone router, do I need to use return false on all links or does backbone handle this automatically? Is there any samples out there, both the html part and the script part.

marcus
  • 9,616
  • 9
  • 58
  • 108

4 Answers4

66

This is the pattern Tim Branyen uses in his boilerplate:

initializeRouter: function () {
  Backbone.history.start({ pushState: true });
  $(document).on('click', 'a:not([data-bypass])', function (evt) {

    var href = $(this).attr('href');
    var protocol = this.protocol + '//';

    if (href.slice(protocol.length) !== protocol) {
      evt.preventDefault();
      app.router.navigate(href, true);
    }
  });
}

Using that, rather than individually doing preventDefault on links, you let the router handle them by default and make exceptions by having a data-bypass attribute. In my experience it works well as a pattern. I don't know of any great examples around, but trying it out yourself should not be too hard. Backbone's beauty lies in its simplicity ;)

ggozad
  • 13,105
  • 3
  • 40
  • 49
  • 4
    Just a heads up - I noticed that IE7 returned the absolute URL in some cases where I was expecting the relative URL. To handle this case, you'll want to normalize the value of `href` to be a relative path before calling navigate. – mshafrir Apr 28 '12 at 08:06
  • 1
    Just curious, what is (href.slice(protocol.length) !== protocol) doing? – dezman Jan 28 '14 at 22:45
  • This [gist](https://gist.github.com/tbranyen/1142129) might help, it says _"Ensure the protocol is not part of URL, meaning its relative."_ With that said, it seems like there'd be easier (and less obtuse) means to do such. – ken Feb 21 '14 at 20:15
  • this.protocol? this is not actually set anywhere. must be from the backbone boiler plate project. my answer works fine without this unecessary logic – mynameistechno Feb 27 '14 at 23:48
  • 2
    I could not find the snippet above about anchor handling anywhere in the boilerplate project. Has the project been emptied? – Federico Bellucci Mar 10 '14 at 10:22
  • 4
    Shouldn't `href.slice(protocol.length)` actually be `href.slice(0, protocol.length)`? – Matt Huggins Aug 04 '14 at 17:55
  • How would I do this with multiple routers? – Jay Aug 19 '16 at 20:36
9
 $(document.body).on('click', 'a', function(e){
   e.preventDefault();
   Backbone.history.navigate(e.currentTarget.pathname, {trigger: true});
 });
mynameistechno
  • 3,526
  • 1
  • 37
  • 32
1

match() or startsWith() (ES 6) also can be used for checking protocol. If you want to support absolute urls by pathname property, check the base urls by location.origin.

function(evt) {
  var target = evt.currentTarget;
  var href = target.getAttribute('href');

  if (!href.match(/^https?:\/\//)) {
    Backbone.history.navigate(href, true);
    evt.preventDefault();
  }
  // or

  var protocol = target.protocol;

  if (!href.startsWith(protocol)) {
    // ...
  }
  // or

  // http://stackoverflow.com/a/25495161/531320
  if (!window.location.origin) {
    window.location.origin = window.location.protocol 
     + "//" + window.location.hostname
     + (window.location.port ? ':' + window.location.port: '');
  }

  var absolute_url = target.href;
  var base_url = location.origin;
  var pathname = target.pathname;

  if (absolute_url.startsWith(base_url)) {
    Backbone.history.navigate(pathname, true);
    evt.preventDefault();
  }
}
masakielastic
  • 4,540
  • 1
  • 39
  • 42
0

You can prevent the default behavior of click on <a> tags in html. Just add the below code inside <script /> tag.

<script>
$(document).on("click", "a", function(e)
{
    e.preventDefault();
    var href = $(e.currentTarget).attr('href');
    router.navigate(href, true);router
});
</script>
Mr Lister
  • 45,515
  • 15
  • 108
  • 150
Sunil Kumar
  • 535
  • 6
  • 13