2013-02-26 14:54:43 -05:00
|
|
|
/**
|
|
|
|
URL related functions.
|
|
|
|
|
|
|
|
@class URL
|
|
|
|
@namespace Discourse
|
|
|
|
@module Discourse
|
|
|
|
**/
|
2013-06-20 17:20:08 -04:00
|
|
|
Discourse.URL = Em.Object.createWithMixins({
|
2013-02-26 14:54:43 -05:00
|
|
|
|
2013-02-26 15:17:52 -05:00
|
|
|
// Used for matching a topic
|
|
|
|
TOPIC_REGEXP: /\/t\/([^\/]+)\/(\d+)\/?(\d+)?/,
|
|
|
|
|
|
|
|
// Used for matching a /more URL
|
|
|
|
MORE_REGEXP: /\/more$/,
|
|
|
|
|
2013-02-26 14:54:43 -05:00
|
|
|
/**
|
|
|
|
Browser aware replaceState. Will only be invoked if the browser supports it.
|
|
|
|
|
|
|
|
@method replaceState
|
|
|
|
@param {String} path The path we are replacing our history state with.
|
|
|
|
**/
|
|
|
|
replaceState: function(path) {
|
2013-02-26 17:25:56 -05:00
|
|
|
|
2013-02-26 14:54:43 -05:00
|
|
|
if (window.history &&
|
|
|
|
window.history.pushState &&
|
|
|
|
window.history.replaceState &&
|
|
|
|
!navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]|WebApps\/.+CFNetwork)/) &&
|
|
|
|
(window.location.pathname !== path)) {
|
2013-02-26 17:25:56 -05:00
|
|
|
|
|
|
|
// Always use replaceState in the next runloop to prevent weird routes changing
|
|
|
|
// while URLs are loading. For example, while a topic loads it sets `currentPost`
|
|
|
|
// which triggers a replaceState even though the topic hasn't fully loaded yet!
|
|
|
|
Em.run.next(function() {
|
2013-06-20 17:20:08 -04:00
|
|
|
var location = Discourse.URL.get('router.location');
|
|
|
|
if (location.replaceURL) { location.replaceURL(path); }
|
2013-02-26 17:25:56 -05:00
|
|
|
});
|
2013-02-26 14:54:43 -05:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
Our custom routeTo method is used to intelligently overwrite default routing
|
|
|
|
behavior.
|
|
|
|
|
|
|
|
It contains the logic necessary to route within a topic using replaceState to
|
|
|
|
keep the history intact.
|
|
|
|
|
|
|
|
@method routeTo
|
|
|
|
@param {String} path The path we are routing to.
|
|
|
|
**/
|
|
|
|
routeTo: function(path) {
|
2013-07-18 15:40:06 -04:00
|
|
|
|
2013-02-26 15:17:52 -05:00
|
|
|
var oldPath = window.location.pathname;
|
2013-02-26 14:54:43 -05:00
|
|
|
path = path.replace(/https?\:\/\/[^\/]+/, '');
|
2013-07-03 14:06:34 -04:00
|
|
|
|
|
|
|
// If the URL is absolute, remove rootURL
|
2013-03-14 08:01:52 -04:00
|
|
|
if (path.match(/^\//)) {
|
2013-04-03 18:26:47 -04:00
|
|
|
var rootURL = (Discourse.BaseUri === undefined ? "/" : Discourse.BaseUri);
|
|
|
|
rootURL = rootURL.replace(/\/$/, '');
|
2013-03-14 08:01:52 -04:00
|
|
|
path = path.replace(rootURL, '');
|
|
|
|
}
|
2013-02-26 14:54:43 -05:00
|
|
|
|
2013-07-04 17:31:06 -04:00
|
|
|
// TODO: Extract into rules we can inject into the URL handler
|
|
|
|
if (this.navigatedToHome(oldPath, path)) { return; }
|
|
|
|
if (this.navigatedToListMore(oldPath, path)) { return; }
|
|
|
|
if (this.navigatedToHome(oldPath, path)) { return; }
|
|
|
|
|
|
|
|
// Be wary of looking up the router. In this case, we have links in our
|
|
|
|
// HTML, say form compiled markdown posts, that need to be routed.
|
|
|
|
var router = this.get('router');
|
|
|
|
router.router.updateURL(path);
|
|
|
|
return router.handleURL(path);
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
Replaces the query parameters in the URL. Use no parameters to clear them.
|
|
|
|
|
|
|
|
@method replaceQueryParams
|
|
|
|
**/
|
|
|
|
queryParams: Em.computed.alias('router.location.queryParams'),
|
|
|
|
|
|
|
|
/**
|
|
|
|
Redirect to a URL.
|
|
|
|
This has been extracted so it can be tested.
|
|
|
|
|
|
|
|
@method redirectTo
|
|
|
|
**/
|
|
|
|
redirectTo: function(url) {
|
|
|
|
window.location = Discourse.getURL(url);
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
@private
|
|
|
|
|
|
|
|
If we're viewing more topics, scroll to where we were previously.
|
|
|
|
|
|
|
|
@method navigatedToListMore
|
|
|
|
@param {String} oldPath the previous path we were on
|
|
|
|
@param {String} path the path we're navigating to
|
|
|
|
**/
|
|
|
|
navigatedToListMore: function(oldPath, path) {
|
|
|
|
// If we transition from a /more path, scroll to the top
|
|
|
|
if (this.MORE_REGEXP.exec(oldPath) && (oldPath.indexOf(path) === 0)) {
|
|
|
|
window.scrollTo(0, 0);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
@private
|
|
|
|
|
|
|
|
If the URL is in the topic form, /t/something/:topic_id/:post_number
|
|
|
|
then we want to apply some special logic. If the post_number changes within the
|
|
|
|
same topic, use replaceState and instruct our controller to load more posts.
|
|
|
|
|
|
|
|
@method navigatedToPost
|
|
|
|
@param {String} oldPath the previous path we were on
|
|
|
|
@param {String} path the path we're navigating to
|
|
|
|
**/
|
|
|
|
navigatedToPost: function(oldPath, path) {
|
|
|
|
|
2013-07-03 14:06:34 -04:00
|
|
|
var newMatches = this.TOPIC_REGEXP.exec(path),
|
|
|
|
newTopicId = newMatches ? newMatches[2] : null;
|
|
|
|
|
2013-02-26 14:54:43 -05:00
|
|
|
if (newTopicId) {
|
2013-07-03 14:06:34 -04:00
|
|
|
var oldMatches = this.TOPIC_REGEXP.exec(oldPath),
|
|
|
|
oldTopicId = oldMatches ? oldMatches[2] : null;
|
2013-02-26 15:17:52 -05:00
|
|
|
|
|
|
|
// If the topic_id is the same
|
|
|
|
if (oldTopicId === newTopicId) {
|
2013-02-26 14:54:43 -05:00
|
|
|
Discourse.URL.replaceState(path);
|
2013-06-20 17:20:08 -04:00
|
|
|
|
2013-07-03 14:06:34 -04:00
|
|
|
var topicController = Discourse.__container__.lookup('controller:topic'),
|
|
|
|
opts = {};
|
|
|
|
|
|
|
|
if (newMatches[3]) opts.nearPost = newMatches[3];
|
2013-06-20 17:20:08 -04:00
|
|
|
var postStream = topicController.get('postStream');
|
|
|
|
postStream.refresh(opts).then(function() {
|
|
|
|
topicController.setProperties({
|
|
|
|
currentPost: opts.nearPost || 1,
|
|
|
|
progressPosition: opts.nearPost || 1
|
|
|
|
});
|
|
|
|
});
|
2013-02-26 15:17:52 -05:00
|
|
|
|
|
|
|
// Abort routing, we have replaced our state.
|
2013-07-04 17:31:06 -04:00
|
|
|
return true;
|
2013-02-26 14:54:43 -05:00
|
|
|
}
|
|
|
|
}
|
2013-02-26 15:17:52 -05:00
|
|
|
|
2013-07-04 17:31:06 -04:00
|
|
|
return false;
|
2013-04-22 14:21:29 -04:00
|
|
|
},
|
|
|
|
|
2013-06-20 17:20:08 -04:00
|
|
|
/**
|
2013-07-04 17:31:06 -04:00
|
|
|
@private
|
2013-06-20 17:20:08 -04:00
|
|
|
|
2013-07-04 17:31:06 -04:00
|
|
|
Handle the custom case of routing to the root path from itself.
|
|
|
|
|
|
|
|
@param {String} oldPath the previous path we were on
|
|
|
|
@param {String} path the path we're navigating to
|
2013-06-20 17:20:08 -04:00
|
|
|
**/
|
2013-07-04 17:31:06 -04:00
|
|
|
navigatedToHome: function(oldPath, path) {
|
|
|
|
|
|
|
|
var defaultFilter = "/" + Discourse.ListController.filters[0];
|
|
|
|
|
|
|
|
if (path === "/" && (oldPath === "/" || oldPath === defaultFilter)) {
|
|
|
|
// Refresh our list
|
|
|
|
this.controllerFor('list').refresh();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
},
|
2013-06-20 17:20:08 -04:00
|
|
|
|
2013-04-22 14:21:29 -04:00
|
|
|
/**
|
|
|
|
@private
|
|
|
|
|
|
|
|
Get the origin of the current location.
|
|
|
|
This has been extracted so it can be tested.
|
|
|
|
|
|
|
|
@method origin
|
|
|
|
**/
|
|
|
|
origin: function() {
|
|
|
|
return window.location.origin;
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
@private
|
|
|
|
|
2013-07-04 17:31:06 -04:00
|
|
|
Get a handle on the application's router. Note that currently it uses `__container__` which is not
|
|
|
|
advised but there is no other way to access the router.
|
2013-04-22 14:21:29 -04:00
|
|
|
|
2013-07-04 17:31:06 -04:00
|
|
|
@property router
|
2013-04-22 14:21:29 -04:00
|
|
|
**/
|
2013-07-04 17:31:06 -04:00
|
|
|
router: function() {
|
|
|
|
return Discourse.__container__.lookup('router:main');
|
|
|
|
}.property(),
|
|
|
|
|
|
|
|
/**
|
|
|
|
@private
|
|
|
|
|
|
|
|
Get a controller. Note that currently it uses `__container__` which is not
|
|
|
|
advised but there is no other way to access the router.
|
|
|
|
|
|
|
|
@method controllerFor
|
|
|
|
@param {String} name the name of the controller
|
|
|
|
**/
|
|
|
|
controllerFor: function(name) {
|
|
|
|
return Discourse.__container__.lookup('controller:' + name);
|
2013-02-26 14:54:43 -05:00
|
|
|
}
|
|
|
|
|
2013-07-04 17:31:06 -04:00
|
|
|
|
2013-06-20 17:20:08 -04:00
|
|
|
});
|