FIX: Double load on back button

This commit is contained in:
Robin Ward 2013-07-18 15:40:06 -04:00
parent 147a239b28
commit 419cbc7701
3 changed files with 56 additions and 48 deletions

View File

@ -48,6 +48,7 @@ Discourse.URL = Em.Object.createWithMixins({
@param {String} path The path we are routing to. @param {String} path The path we are routing to.
**/ **/
routeTo: function(path) { routeTo: function(path) {
var oldPath = window.location.pathname; var oldPath = window.location.pathname;
path = path.replace(/https?\:\/\/[^\/]+/, ''); path = path.replace(/https?\:\/\/[^\/]+/, '');

View File

@ -3,7 +3,8 @@
*/ */
var get = Ember.get, set = Ember.set; var get = Ember.get, set = Ember.set;
var popstateReady = false; var popstateFired = false;
var supportsHistoryState = window.history && 'state' in window.history;
// Thanks: https://gist.github.com/kares/956897 // Thanks: https://gist.github.com/kares/956897
var re = /([^&=]+)=?([^&]*)/g; var re = /([^&=]+)=?([^&]*)/g;
@ -46,9 +47,6 @@ Ember.DiscourseLocation = Ember.Object.extend({
init: function() { init: function() {
set(this, 'location', get(this, 'location') || window.location); set(this, 'location', get(this, 'location') || window.location);
if ( $.inArray('state', $.event.props) < 0 ) {
jQuery.event.props.push('state');
}
this.initState(); this.initState();
}, },
@ -66,10 +64,18 @@ Ember.DiscourseLocation = Ember.Object.extend({
this.set('queryParams', $.parseParams(location.search)); this.set('queryParams', $.parseParams(location.search));
} }
set(this, 'history', get(this, 'history') || window.history);
this.replaceState(this.formatURL(this.getURL())); this.replaceState(this.formatURL(this.getURL()));
set(this, 'history', window.history);
}, },
/**
Will be pre-pended to path upon state change
@property rootURL
@default '/'
*/
rootURL: '/',
/** /**
@private @private
@ -96,9 +102,10 @@ Ember.DiscourseLocation = Ember.Object.extend({
@param path {String} @param path {String}
*/ */
setURL: function(path) { setURL: function(path) {
var state = this.getState();
path = this.formatURL(path); path = this.formatURL(path);
if (this.getState() && this.getState().path !== path) {
popstateReady = true; if (state && state.path !== path) {
this.pushState(path); this.pushState(path);
} }
}, },
@ -113,10 +120,10 @@ Ember.DiscourseLocation = Ember.Object.extend({
@param path {String} @param path {String}
*/ */
replaceURL: function(path) { replaceURL: function(path) {
var state = this.getState();
path = this.formatURL(path); path = this.formatURL(path);
if (this.getState() && this.getState().path !== path) { if (state && state.path !== path) {
popstateReady = true;
this.replaceState(path); this.replaceState(path);
} }
}, },
@ -125,14 +132,13 @@ Ember.DiscourseLocation = Ember.Object.extend({
@private @private
Get the current `history.state` Get the current `history.state`
Polyfill checks for native browser support and falls back to retrieving
from a private _historyState variable
@method getState @method getState
*/ */
getState: function() { getState: function() {
var historyState = get(this, 'history').state; return supportsHistoryState ? get(this, 'history').state : this._historyState;
if (historyState) return historyState;
return {path: window.location.pathname};
}, },
/** /**
@ -144,9 +150,17 @@ Ember.DiscourseLocation = Ember.Object.extend({
@param path {String} @param path {String}
*/ */
pushState: function(path) { pushState: function(path) {
if (!window.history.pushState) return; var state = { path: path };
this.set('currentState', { path: path } );
window.history.pushState({ path: path }, null, path); get(this, 'history').pushState(state, null, path);
// store state if browser doesn't support `history.state`
if (!supportsHistoryState) {
this._historyState = state;
}
// used for webkit workaround
this._previousURL = this.getURL();
}, },
/** /**
@ -158,9 +172,17 @@ Ember.DiscourseLocation = Ember.Object.extend({
@param path {String} @param path {String}
*/ */
replaceState: function(path) { replaceState: function(path) {
if (!window.history.replaceState) return; var state = { path: path };
this.set('currentState', { path: path } );
window.history.replaceState({ path: path }, null, path); get(this, 'history').replaceState(state, null, path);
// store state if browser doesn't support `history.state`
if (!supportsHistoryState) {
this._historyState = state;
}
// used for webkit workaround
this._previousURL = this.getURL();
}, },
@ -175,7 +197,10 @@ Ember.DiscourseLocation = Ember.Object.extend({
// When our query params change, update the URL // When our query params change, update the URL
queryParamsStringChanged: function() { queryParamsStringChanged: function() {
this.replaceState(this.formatURL(this.getURL())); var loc = this;
Em.run.next(function () {
loc.replaceState(loc.formatURL(loc.getURL()));
});
}.observes('queryParamsString'), }.observes('queryParamsString'),
/** /**
@ -191,21 +216,13 @@ Ember.DiscourseLocation = Ember.Object.extend({
var guid = Ember.guidFor(this), var guid = Ember.guidFor(this),
self = this; self = this;
$(window).bind('popstate.ember-location-'+guid, function(e) { Ember.$(window).on('popstate.ember-location-'+guid, function(e) {
if (e.state) { // Ignore initial page load popstate event in Chrome
var currentState = self.get('currentState'); if (!popstateFired) {
if (currentState) { popstateFired = true;
var url = e.state.path, if (self.getURL() === self._previousURL) { return; }
rootURL = (Discourse.BaseUri === undefined ? "/" : Discourse.BaseUri);
rootURL = rootURL.replace(/\/$/, '');
url = url.replace(rootURL, '');
callback(url);
} else {
this.set('currentState', e.state);
}
} }
callback(self.getURL());
}); });
}, },
@ -218,27 +235,21 @@ Ember.DiscourseLocation = Ember.Object.extend({
@param url {String} @param url {String}
*/ */
formatURL: function(url) { formatURL: function(url) {
var rootURL = (Discourse.BaseUri === undefined ? "/" : Discourse.BaseUri); var rootURL = get(this, 'rootURL');
if (url !== '') { if (url !== '') {
rootURL = rootURL.replace(/\/$/, ''); rootURL = rootURL.replace(/\/$/, '');
} }
// remove prefix from URL if it is already in url - i.e. /discourse/t/... -> /t/if rootURL is /discourse
// this sometimes happens when navigating to already visited location
if ((rootURL.length > 1) && (url.substring(0, rootURL.length + 1) === (rootURL + "/")))
{
url = url.substring(rootURL.length);
}
return rootURL + url + this.get('queryParamsString'); return rootURL + url + this.get('queryParamsString');
}, },
willDestroy: function() { willDestroy: function() {
var guid = Ember.guidFor(this); var guid = Ember.guidFor(this);
Ember.$(window).unbind('popstate.ember-location-'+guid); Ember.$(window).off('popstate.ember-location-'+guid);
} }
}); });
Ember.Location.registerImplementation('discourse_location', Ember.DiscourseLocation); Ember.Location.registerImplementation('discourse_location', Ember.DiscourseLocation);

View File

@ -9,6 +9,7 @@
Discourse.TopicFromParamsRoute = Discourse.Route.extend({ Discourse.TopicFromParamsRoute = Discourse.Route.extend({
setupController: function(controller, params) { setupController: function(controller, params) {
params = params || {}; params = params || {};
params.track_visit = true; params.track_visit = true;
@ -34,7 +35,6 @@ Discourse.TopicFromParamsRoute = Discourse.Route.extend({
composerController = this.controllerFor('composer'); composerController = this.controllerFor('composer');
postStream.refresh(params).then(function () { postStream.refresh(params).then(function () {
// The post we requested might not exist. Let's find the closest post // The post we requested might not exist. Let's find the closest post
var closest = postStream.closestPostNumberFor(params.nearPost) || 1; var closest = postStream.closestPostNumberFor(params.nearPost) || 1;
@ -53,11 +53,7 @@ Discourse.TopicFromParamsRoute = Discourse.Route.extend({
ignoreIfChanged: true ignoreIfChanged: true
}); });
} }
}); });
} }
}); });