From 7b024b8fbfc059cddf12c06865b5a406690ccc91 Mon Sep 17 00:00:00 2001 From: Matt Bryson Date: Wed, 23 Jul 2014 15:21:43 +0100 Subject: [PATCH 1/3] Added the ability to resetAttributes for specific attrs, rather than the whole lot. Also trigger a set event when this occures to trigger any binding updates --- backbone.trackit.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/backbone.trackit.js b/backbone.trackit.js index 2dc6f4d..e7c2ec8 100644 --- a/backbone.trackit.js +++ b/backbone.trackit.js @@ -103,11 +103,23 @@ // Restores this model's attributes to // their original values since tracking // started, the last save, or last restart. - resetAttributes: function() { + resetAttributes: function(attrs) { + if (!this._trackingChanges) return; - this.attributes = this._originalAttrs; + + if(!attrs) { + this.set(this._originalAttrs); + } else { + for (var i in attrs) { + var key=attrs[i]; + delete this._unsavedChanges[key]; + this.set(key, this._originalAttrs[key]); + } + } + this._resetTracking(); this._triggerUnsavedChanges(); + return this; }, From abd4dba616a29ee01a3d4e13dfed67c49c66a78c Mon Sep 17 00:00:00 2001 From: Matt Bryson Date: Fri, 3 Oct 2014 15:48:27 +0100 Subject: [PATCH 2/3] Added support for back button detection when html5 pushState navigation is in use --- backbone.trackit.js | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/backbone.trackit.js b/backbone.trackit.js index e7c2ec8..9d59fb2 100644 --- a/backbone.trackit.js +++ b/backbone.trackit.js @@ -41,6 +41,10 @@ // Wrap Backbone.History.navigate so that in-app routing // (`router.navigate('/path')`) can be intercepted with a // confirmation if there are any unsaved models. + + //Keep the un wrapped method so we can call it directly in the checkUrl method + var originalNavigate = Backbone.History.prototype.navigate; + Backbone.History.prototype.navigate = _.wrap(Backbone.History.prototype.navigate, function(oldNav, fragment, options) { var prompt = getPrompt('unloadRouterPrompt', fragment, options); if (prompt) { @@ -52,12 +56,47 @@ } }); + + //To detect back button press with pushState navigation (not page loads) + //We need to intercept the Backbone.history internal popstate events + + //First remove binding to the handler so we can update it (it doesn't update otherwise) + Backbone.$(window).off('popstate', Backbone.history.checkUrl).off('hashchange', Backbone.history.checkUrl); + + //Now wrap the handler with out check + Backbone.history.checkUrl = _.wrap(Backbone.history.checkUrl, function(oldUrl, e) { + //at this point history.fragment is the fragment we are leaving, and history.getFragment is the fragment we are going to. + var currentFragment = Backbone.history.fragment; + + var prompt = getPrompt('unloadRouterPrompt', currentFragment); + if (prompt) { + if (confirm(prompt + ' \n\nAre you sure you want to leave this page?')) { + oldUrl.call(Backbone.history, e); + } else { + //As the fragment is the one we are leaving, calling the original navigate will do nothing, as the fragments match + //So we need to change the history fragment to the one in the URL, and then we can swap it back again + Backbone.history.fragment = Backbone.history.getFragment(); + originalNavigate.call(Backbone.history, currentFragment, {trigger:false}); + } + } else { + oldUrl.call(Backbone.history, e); + } + }); + + //Now Re bind to the wrapped event + Backbone.$(window).on('popstate', Backbone.history.checkUrl).on('hashchange', Backbone.history.checkUrl); + + + + // Create a browser unload handler which is triggered // on the refresh, back, or forward button. window.onbeforeunload = function(e) { return getPrompt('unloadWindowPrompt', e); }; + + // Backbone.Model API // ------------------ From 3a1f65d47dca1c27562d5ea5c5ae99d5a4aac9ed Mon Sep 17 00:00:00 2001 From: Matt Bryson Date: Tue, 21 Feb 2017 12:26:38 +0000 Subject: [PATCH 3/3] Added return on history.navigate override to support the return state. --- backbone.trackit.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/backbone.trackit.js b/backbone.trackit.js index 9d59fb2..b630c53 100644 --- a/backbone.trackit.js +++ b/backbone.trackit.js @@ -49,10 +49,10 @@ var prompt = getPrompt('unloadRouterPrompt', fragment, options); if (prompt) { if (confirm(prompt + ' \n\nAre you sure you want to leave this page?')) { - oldNav.call(this, fragment, options); + return oldNav.call(this, fragment, options); } } else { - oldNav.call(this, fragment, options); + return oldNav.call(this, fragment, options); } }); @@ -71,15 +71,15 @@ var prompt = getPrompt('unloadRouterPrompt', currentFragment); if (prompt) { if (confirm(prompt + ' \n\nAre you sure you want to leave this page?')) { - oldUrl.call(Backbone.history, e); + return oldUrl.call(Backbone.history, e); } else { //As the fragment is the one we are leaving, calling the original navigate will do nothing, as the fragments match //So we need to change the history fragment to the one in the URL, and then we can swap it back again Backbone.history.fragment = Backbone.history.getFragment(); - originalNavigate.call(Backbone.history, currentFragment, {trigger:false}); + return originalNavigate.call(Backbone.history, currentFragment, {trigger:false}); } } else { - oldUrl.call(Backbone.history, e); + return oldUrl.call(Backbone.history, e); } }); @@ -240,4 +240,4 @@ return oldSync(method, model, options); }); -})(); \ No newline at end of file +})();