We have a backbone.js app that displays a number of forms to the user. What we want is very simple: if the user goes to another page without saving the filled-in form, we want t
I would also hack Backbone.history.loadUrl
, that's where loading the route callbacks happen.
// ALLOW PREVENTING HASH NAVIGATION
var originalFn = Backbone.history.loadUrl;
Backbone.history.loadUrl = function() {
// I introduced an application state variable, but it can be solved in multiple ways
if (app && app.states.isNavigationBlocked) {
var previousFragment = Backbone.history.fragment;
window.location.hash = '#' + previousFragment;
return false;
}
else {
return originalFn.apply(this, arguments);
}
};
Backbone listens to the hashchange
event and sets Backbone.history.checkUrl
as a callback:
https://github.com/jashkenas/backbone/blob/1.1.2/backbone.js#L1414
Backbone.$(window).on('hashchange', this.checkUrl);
Backbone.history.checkUrl checks if the hash has changed and calls Backbone.history.loadUrl
checkUrl: function(e) {
var current = this.getFragment();
if (current === this.fragment && this.iframe) {
current = this.getFragment(this.getHash(this.iframe));
}
if (current === this.fragment) return false;
if (this.iframe) this.navigate(current);
this.loadUrl();
},
Backbone.history.loadUrl finds the first matching route and calls its callback:
loadUrl: function(fragment) {
fragment = this.fragment = this.getFragment(fragment);
return _.any(this.handlers, function(handler) {
if (handler.route.test(fragment)) {
handler.callback(fragment);
return true;
}
});
},
Useful note:
Backbone.history.fragment
stores the current hash, it's set in Backbone.history.loadUrl
, so we can access it AFTER the hashchange
event but BEFORE the router callbacks do their job.