szurubooru/public_html/js/Router.js

175 lines
4.6 KiB
JavaScript
Raw Normal View History

2014-08-31 23:22:56 +02:00
var App = App || {};
App.Router = function(_, jQuery, promise, util, appState, presenterManager) {
2014-08-31 23:22:56 +02:00
var root = '#/';
2014-09-16 17:29:11 +02:00
var previousLocation = window.location.href;
var routes = [];
2014-08-31 23:22:56 +02:00
injectRoutes();
function injectRoutes() {
inject('', 'homePresenter');
inject('#/', 'homePresenter');
inject('#/home', 'homePresenter');
inject('#/login', 'loginPresenter');
inject('#/logout', 'logoutPresenter');
inject('#/register', 'registrationPresenter');
inject('#/upload', 'postUploadPresenter');
inject('#/password-reset(/:token)', 'userActivationPresenter', {operation: 'passwordReset'});
inject('#/activate(/:token)', 'userActivationPresenter', {operation: 'activation'});
inject('#/users(/:!query)', 'userListPresenter');
inject('#/user/:userName(/:tab)', 'userPresenter');
inject('#/posts(/:!query)', 'postListPresenter');
inject('#/post/:postNameOrId(/:!query)', 'postPresenter');
inject('#/comments(/:!query)', 'globalCommentListPresenter');
inject('#/tags(/:!query)', 'tagListPresenter');
inject('#/tag/:tagName', 'tagPresenter');
inject('#/help', 'helpPresenter');
2014-09-08 22:02:28 +02:00
}
2014-08-31 23:22:56 +02:00
function navigate(url) {
window.location.href = url;
2014-09-08 22:02:28 +02:00
}
2014-08-31 23:22:56 +02:00
function navigateToMainPage() {
navigate(root);
}
function navigateInplace(url) {
if ('replaceState' in history) {
history.replaceState('', '', url);
dispatch();
} else {
navigate(url);
}
}
2014-08-31 23:22:56 +02:00
function start() {
2014-10-10 23:40:15 +02:00
if ('onhashchange' in window) {
window.onhashchange = dispatch;
} else {
window.onpopstate = dispatch;
}
dispatch();
2014-09-08 22:02:28 +02:00
}
2014-08-31 23:22:56 +02:00
function inject(definition, presenterName, additionalParams) {
routes.push(new Route(definition, function(params) {
2014-09-25 19:22:31 +02:00
if (util.isExitConfirmationEnabled()) {
if (window.location.href === previousLocation) {
return;
} else {
if (window.confirm('Are you sure you want to leave this page? Data will be lost.')) {
util.disableExitConfirmation();
} else {
window.location.href = previousLocation;
return;
}
}
}
2014-10-02 00:30:25 +02:00
params = _.extend({}, params, additionalParams, {previousLocation: previousLocation});
2014-10-02 00:30:25 +02:00
//abort every operation that can be executed
promise.abortAll();
2014-09-25 19:22:31 +02:00
previousLocation = window.location.href;
2014-09-17 22:37:49 +02:00
var presenter = App.DI.get(presenterName);
presenter.name = presenterName;
presenterManager.switchContentPresenter(presenter, params);
}));
}
function dispatch() {
var url = document.location.hash;
for (var i = 0; i < routes.length; i ++) {
var route = routes[i];
if (route.match(url)) {
route.callback(route.params);
return true;
}
}
//todo: 404
console.log(new Error('Unhandled route: ' + url));
return false;
2014-09-08 22:02:28 +02:00
}
2014-08-31 23:22:56 +02:00
function parseComplexParamValue(value) {
var result = {};
var params = (value || '').split(/;/);
for (var i = 0; i < params.length; i ++) {
var param = params[i];
if (!param) {
continue;
}
var kv = param.split(/=/);
result[kv[0]] = kv[1];
}
return result;
}
function Route(definition, callback) {
var possibleRoutes = getPossibleRoutes(definition);
function getPossibleRoutes(routeDefinition) {
var parts = [];
var re = new RegExp('\\(([^}]+?)\\)', 'g');
while (true) {
var text = re.exec(routeDefinition);
if (!text) {
break;
}
parts.push(text[1]);
}
var possibleRoutes = [routeDefinition.split('(')[0]];
for (var i = 0; i < parts.length; i ++) {
possibleRoutes.push(possibleRoutes[possibleRoutes.length - 1] + parts[i]);
}
return possibleRoutes;
}
function match(url) {
var params = {};
for (var i = 0; i < possibleRoutes.length; i ++) {
var possibleRoute = possibleRoutes[i];
var compare = url;
var possibleRouteParts = possibleRoute.split('/');
var compareParts = compare.split('/');
if (possibleRoute.search(':') > 0) {
for (var j = 0; j < possibleRouteParts.length; j ++) {
if ((j < compareParts.length) && (possibleRouteParts[j].charAt(0) === ':')) {
var key = possibleRouteParts[j].substring(1);
var value = compareParts[j];
if (key.charAt(0) === '!') {
key = key.substring(1);
value = parseComplexParamValue(value);
}
params[key] = value;
compare = compare.replace(compareParts[j], possibleRouteParts[j]);
}
}
}
if (possibleRoute === compare) {
this.params = params;
return true;
}
}
return false;
}
this.match = match;
this.callback = callback;
}
2014-08-31 23:22:56 +02:00
return {
start: start,
navigate: navigate,
navigateInplace: navigateInplace,
2014-08-31 23:22:56 +02:00
navigateToMainPage: navigateToMainPage,
};
};
App.DI.registerSingleton('router', ['_', 'jQuery', 'promise', 'util', 'appState', 'presenterManager'], App.Router);