From 402508d80f7f0cac8ec57ae727ed8bb0428728a2 Mon Sep 17 00:00:00 2001 From: Jake Harding Date: Mon, 6 Feb 2012 20:29:26 -0800 Subject: [PATCH] Getting the hash value from location.href rather than location.hash as a workaround to the Firefox bug where location.hash is decoded. --- backbone.js | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/backbone.js b/backbone.js index b5f1fea5..0c5624d2 100644 --- a/backbone.js +++ b/backbone.js @@ -834,6 +834,15 @@ // twenty times a second. interval: 50, + // Gets the true hash value. Cannot use location.hash directly due to bug + // in Firefox where location.hash will always be decoded. + getHash: function(windowOverride) { + var loc = windowOverride ? windowOverride.location : window.location; + var hash = loc.href.split('#')[1] || ''; + + return hash; + }, + // Get the cross-browser normalized URL fragment, either from the URL, // the hash, or the override. getFragment: function(fragment, forcePushState) { @@ -843,10 +852,9 @@ var search = window.location.search; if (search) fragment += search; } else { - fragment = window.location.hash; + fragment = this.getHash(); } } - fragment = decodeURIComponent(fragment); if (!fragment.indexOf(this.options.root)) fragment = fragment.substr(this.options.root.length); return fragment.replace(routeStripper, ''); }, @@ -898,7 +906,7 @@ // Or if we've started out with a hash-based route, but we're currently // in a browser where it could be `pushState`-based instead... } else if (this._wantsPushState && this._hasPushState && atRoot && loc.hash) { - this.fragment = loc.hash.replace(routeStripper, ''); + this.fragment = this.getHash().replace(routeStripper, ''); window.history.replaceState({}, document.title, loc.protocol + '//' + loc.host + this.options.root + this.fragment); } @@ -925,10 +933,10 @@ // calls `loadUrl`, normalizing across the hidden iframe. checkUrl: function(e) { var current = this.getFragment(); - if (current == this.fragment && this.iframe) current = this.getFragment(this.iframe.location.hash); - if (current == this.fragment || current == decodeURIComponent(this.fragment)) return false; + 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() || this.loadUrl(window.location.hash); + this.loadUrl() || this.loadUrl(this.getHash()); }, // Attempt to load the current URL fragment. If a route succeeds with a @@ -956,7 +964,7 @@ if (!historyStarted) return false; if (!options || options === true) options = {trigger: options}; var frag = (fragment || '').replace(routeStripper, ''); - if (this.fragment == frag || this.fragment == decodeURIComponent(frag)) return; + if (this.fragment == frag) return; // If pushState is available, we use it to set the fragment as a real URL. if (this._hasPushState) { @@ -969,7 +977,7 @@ } else if (this._wantsHashChange) { this.fragment = frag; this._updateHash(window.location, frag, options.replace); - if (this.iframe && (frag != this.getFragment(this.iframe.location.hash))) { + if (this.iframe && (frag != this.getFragment(this.getHash(this.iframe)))) { // Opening and closing the iframe tricks IE7 and earlier to push a history entry on hash-tag change. // When replace is true, we don't want this. if(!options.replace) this.iframe.document.open().close();