aboutsummaryrefslogtreecommitdiff
path: root/client/js
diff options
context:
space:
mode:
authorrr-2016-07-07 21:18:35 +0200
committerrr-2016-07-08 00:54:24 +0200
commit5ac5eb550380e9c9a5c4fdbbbf08fadbe01ff4a9 (patch)
tree7aedc28b8fef9e62d8624fdd85a095ae90efa8e6 /client/js
parentcd1f4709f0c636c6cbcf62c90c7df0eb593c6c3c (diff)
client/general: refactor URL parameter handling
Diffstat (limited to 'client/js')
-rw-r--r--client/js/controllers/comments_controller.js12
-rw-r--r--client/js/controllers/help_controller.js4
-rw-r--r--client/js/controllers/page_controller.js2
-rw-r--r--client/js/controllers/password_reset_controller.js2
-rw-r--r--client/js/controllers/post_controller.js18
-rw-r--r--client/js/controllers/post_list_controller.js16
-rw-r--r--client/js/controllers/tag_categories_controller.js1
-rw-r--r--client/js/controllers/tag_controller.js4
-rw-r--r--client/js/controllers/tag_list_controller.js14
-rw-r--r--client/js/controllers/user_controller.js4
-rw-r--r--client/js/controllers/user_list_controller.js14
-rw-r--r--client/js/router.js11
-rw-r--r--client/js/util/misc.js27
-rw-r--r--client/js/util/views.js18
-rw-r--r--client/js/views/endless_page_view.js2
-rw-r--r--client/js/views/home_view.js4
-rw-r--r--client/js/views/manual_page_view.js2
-rw-r--r--client/js/views/posts_header_view.js16
-rw-r--r--client/js/views/tags_header_view.js4
-rw-r--r--client/js/views/users_header_view.js4
20 files changed, 102 insertions, 77 deletions
diff --git a/client/js/controllers/comments_controller.js b/client/js/controllers/comments_controller.js
index 0f2684f..7fa490e 100644
--- a/client/js/controllers/comments_controller.js
+++ b/client/js/controllers/comments_controller.js
@@ -14,11 +14,11 @@ class CommentsController {
topNavigation.activate('comments');
this._pageController = new PageController({
- searchQuery: ctx.searchQuery,
+ parameters: ctx.parameters,
getClientUrlForPage: page => {
- const searchQuery = Object.assign(
- {}, ctx.searchQuery, {page: page});
- return '/comments/' + misc.formatSearchQuery(searchQuery);
+ const parameters = Object.assign(
+ {}, ctx.parameters, {page: page});
+ return '/comments/' + misc.formatUrlParameters(parameters);
},
requestPage: page => {
return PostList.search(
@@ -63,7 +63,7 @@ class CommentsController {
};
module.exports = router => {
- router.enter('/comments/:query?',
- (ctx, next) => { misc.parseSearchQueryRoute(ctx, next); },
+ router.enter('/comments/:parameters?',
+ (ctx, next) => { misc.parseUrlParametersRoute(ctx, next); },
(ctx, next) => { new CommentsController(ctx); });
};
diff --git a/client/js/controllers/help_controller.js b/client/js/controllers/help_controller.js
index f7dcafa..4c42d0b 100644
--- a/client/js/controllers/help_controller.js
+++ b/client/js/controllers/help_controller.js
@@ -15,9 +15,9 @@ module.exports = router => {
new HelpController();
});
router.enter('/help/:section', (ctx, next) => {
- new HelpController(ctx.params.section);
+ new HelpController(ctx.parameters.section);
});
router.enter('/help/:section/:subsection', (ctx, next) => {
- new HelpController(ctx.params.section, ctx.params.subsection);
+ new HelpController(ctx.parameters.section, ctx.parameters.subsection);
});
};
diff --git a/client/js/controllers/page_controller.js b/client/js/controllers/page_controller.js
index a7154ee..6a490ee 100644
--- a/client/js/controllers/page_controller.js
+++ b/client/js/controllers/page_controller.js
@@ -8,7 +8,7 @@ class PageController {
constructor(ctx) {
const extendedContext = {
getClientUrlForPage: ctx.getClientUrlForPage,
- searchQuery: ctx.searchQuery,
+ parameters: ctx.parameters,
};
ctx.headerContext = Object.assign({}, extendedContext);
diff --git a/client/js/controllers/password_reset_controller.js b/client/js/controllers/password_reset_controller.js
index 00a288c..f291bd4 100644
--- a/client/js/controllers/password_reset_controller.js
+++ b/client/js/controllers/password_reset_controller.js
@@ -58,6 +58,6 @@ module.exports = router => {
});
router.enter(/\/password-reset\/([^:]+):([^:]+)$/, (ctx, next) => {
ctx.controller = new PasswordResetFinishController(
- ctx.params[0], ctx.params[1]);
+ ctx.parameters[0], ctx.parameters[1]);
});
};
diff --git a/client/js/controllers/post_controller.js b/client/js/controllers/post_controller.js
index c00e87b..a9c6dd2 100644
--- a/client/js/controllers/post_controller.js
+++ b/client/js/controllers/post_controller.js
@@ -11,14 +11,14 @@ const PostView = require('../views/post_view.js');
const EmptyView = require('../views/empty_view.js');
class PostController {
- constructor(id, editMode, searchQuery) {
+ constructor(id, editMode, parameters) {
topNavigation.activate('posts');
Promise.all([
Post.get(id),
PostList.getAround(
id, this._decorateSearchQuery(
- searchQuery ? searchQuery.text : '')),
+ parameters ? parameters.query : '')),
]).then(responses => {
const [post, aroundResponse] = responses;
this._post = post;
@@ -30,7 +30,7 @@ class PostController {
canEditPosts: api.hasPrivilege('posts:edit'),
canListComments: api.hasPrivilege('comments:list'),
canCreateComments: api.hasPrivilege('comments:create'),
- searchQuery: searchQuery,
+ parameters: parameters,
});
if (this._view.sidebarControl) {
this._view.sidebarControl.addEventListener(
@@ -149,17 +149,17 @@ class PostController {
}
module.exports = router => {
- router.enter('/post/:id/edit/:query?',
- (ctx, next) => { misc.parseSearchQueryRoute(ctx, next); },
+ router.enter('/post/:id/edit/:parameters?',
+ (ctx, next) => { misc.parseUrlParametersRoute(ctx, next); },
(ctx, next) => {
ctx.controller = new PostController(
- ctx.params.id, true, ctx.searchQuery);
+ ctx.parameters.id, true, ctx.parameters);
});
router.enter(
- '/post/:id/:query?',
- (ctx, next) => { misc.parseSearchQueryRoute(ctx, next); },
+ '/post/:id/:parameters?',
+ (ctx, next) => { misc.parseUrlParametersRoute(ctx, next); },
(ctx, next) => {
ctx.controller = new PostController(
- ctx.params.id, false, ctx.searchQuery);
+ ctx.parameters.id, false, ctx.parameters);
});
};
diff --git a/client/js/controllers/post_list_controller.js b/client/js/controllers/post_list_controller.js
index 16f3765..8219520 100644
--- a/client/js/controllers/post_list_controller.js
+++ b/client/js/controllers/post_list_controller.js
@@ -19,15 +19,15 @@ class PostListController {
this._ctx = ctx;
this._pageController = new PageController({
- searchQuery: ctx.searchQuery,
+ parameters: ctx.parameters,
getClientUrlForPage: page => {
- const searchQuery = Object.assign(
- {}, ctx.searchQuery, {page: page});
- return '/posts/' + misc.formatSearchQuery(searchQuery);
+ const parameters = Object.assign(
+ {}, ctx.parameters, {page: page});
+ return '/posts/' + misc.formatUrlParameters(parameters);
},
requestPage: page => {
return PostList.search(
- this._decorateSearchQuery(ctx.searchQuery.text),
+ this._decorateSearchQuery(ctx.parameters.query),
page, 40, fields);
},
headerRenderer: headerCtx => {
@@ -51,7 +51,7 @@ class PostListController {
}
get _massTagTags() {
- return (this._ctx.searchQuery.tag || '').split(/\s+/).filter(s => s);
+ return (this._ctx.parameters.tag || '').split(/\s+/).filter(s => s);
}
_evtTag(e) {
@@ -91,7 +91,7 @@ class PostListController {
module.exports = router => {
router.enter(
- '/posts/:query?',
- (ctx, next) => { misc.parseSearchQueryRoute(ctx, next); },
+ '/posts/:parameters?',
+ (ctx, next) => { misc.parseUrlParametersRoute(ctx, next); },
(ctx, next) => { ctx.controller = new PostListController(ctx); });
};
diff --git a/client/js/controllers/tag_categories_controller.js b/client/js/controllers/tag_categories_controller.js
index f33438d..f676eb4 100644
--- a/client/js/controllers/tag_categories_controller.js
+++ b/client/js/controllers/tag_categories_controller.js
@@ -2,7 +2,6 @@
const api = require('../api.js');
const tags = require('../tags.js');
-const misc = require('../util/misc.js');
const TagCategoryList = require('../models/tag_category_list.js');
const topNavigation = require('../models/top_navigation.js');
const TagCategoriesView = require('../views/tag_categories_view.js');
diff --git a/client/js/controllers/tag_controller.js b/client/js/controllers/tag_controller.js
index 08a3c09..9d46744 100644
--- a/client/js/controllers/tag_controller.js
+++ b/client/js/controllers/tag_controller.js
@@ -10,10 +10,10 @@ const EmptyView = require('../views/empty_view.js');
class TagController {
constructor(ctx, section) {
- Tag.get(ctx.params.name).then(tag => {
+ Tag.get(ctx.parameters.name).then(tag => {
topNavigation.activate('tags');
- this._name = ctx.params.name;
+ this._name = ctx.parameters.name;
tag.addEventListener('change', e => this._evtSaved(e));
const categories = {};
diff --git a/client/js/controllers/tag_list_controller.js b/client/js/controllers/tag_list_controller.js
index 7492398..f059771 100644
--- a/client/js/controllers/tag_list_controller.js
+++ b/client/js/controllers/tag_list_controller.js
@@ -16,14 +16,14 @@ class TagListController {
topNavigation.activate('tags');
this._pageController = new PageController({
- searchQuery: ctx.searchQuery,
+ parameters: ctx.parameters,
getClientUrlForPage: page => {
- const searchQuery = Object.assign(
- {}, ctx.searchQuery, {page: page});
- return '/tags/' + misc.formatSearchQuery(searchQuery);
+ const parameters = Object.assign(
+ {}, ctx.parameters, {page: page});
+ return '/tags/' + misc.formatUrlParameters(parameters);
},
requestPage: page => {
- return TagList.search(ctx.searchQuery.text, page, 50, fields);
+ return TagList.search(ctx.parameters.query, page, 50, fields);
},
headerRenderer: headerCtx => {
Object.assign(headerCtx, {
@@ -49,7 +49,7 @@ class TagListController {
module.exports = router => {
router.enter(
- '/tags/:query?',
- (ctx, next) => { misc.parseSearchQueryRoute(ctx, next); },
+ '/tags/:parameters?',
+ (ctx, next) => { misc.parseUrlParametersRoute(ctx, next); },
(ctx, next) => { ctx.controller = new TagListController(ctx); });
};
diff --git a/client/js/controllers/user_controller.js b/client/js/controllers/user_controller.js
index 31a562b..e068bfd 100644
--- a/client/js/controllers/user_controller.js
+++ b/client/js/controllers/user_controller.js
@@ -11,11 +11,11 @@ const EmptyView = require('../views/empty_view.js');
class UserController {
constructor(ctx, section) {
- User.get(ctx.params.name).then(user => {
+ User.get(ctx.parameters.name).then(user => {
const isLoggedIn = api.isLoggedIn(user);
const infix = isLoggedIn ? 'self' : 'any';
- this._name = ctx.params.name;
+ this._name = ctx.parameters.name;
user.addEventListener('change', e => this._evtSaved(e));
const myRankIndex = api.user ?
diff --git a/client/js/controllers/user_list_controller.js b/client/js/controllers/user_list_controller.js
index e9f0894..31d0e72 100644
--- a/client/js/controllers/user_list_controller.js
+++ b/client/js/controllers/user_list_controller.js
@@ -13,14 +13,14 @@ class UserListController {
topNavigation.activate('users');
this._pageController = new PageController({
- searchQuery: ctx.searchQuery,
+ parameters: ctx.parameters,
getClientUrlForPage: page => {
- const searchQuery = Object.assign(
- {}, ctx.searchQuery, {page: page});
- return '/users/' + misc.formatSearchQuery(searchQuery);
+ const parameters = Object.assign(
+ {}, ctx.parameters, {page: page});
+ return '/users/' + misc.formatUrlParameters(parameters);
},
requestPage: page => {
- return UserList.search(ctx.searchQuery.text, page);
+ return UserList.search(ctx.parameters.query, page);
},
headerRenderer: headerCtx => {
return new UsersHeaderView(headerCtx);
@@ -41,7 +41,7 @@ class UserListController {
module.exports = router => {
router.enter(
- '/users/:query?',
- (ctx, next) => { misc.parseSearchQueryRoute(ctx, next); },
+ '/users/:parameters?',
+ (ctx, next) => { misc.parseUrlParametersRoute(ctx, next); },
(ctx, next) => { ctx.controller = new UserListController(ctx); });
};
diff --git a/client/js/router.js b/client/js/router.js
index 426d6d4..490b804 100644
--- a/client/js/router.js
+++ b/client/js/router.js
@@ -39,7 +39,7 @@ class Context {
this.title = document.title;
this.state = state || {};
this.state.path = path;
- this.params = {};
+ this.parameters = {};
}
pushState() {
@@ -61,14 +61,14 @@ class Route {
middleware(fn) {
return (ctx, next) => {
- if (this.match(ctx.path, ctx.params)) {
+ if (this.match(ctx.path, ctx.parameters)) {
return fn(ctx, next);
}
next();
};
}
- match(path, params) {
+ match(path, parameters) {
const keys = this.keys;
const qsIndex = path.indexOf('?');
const pathname = ~qsIndex ? path.slice(0, qsIndex) : path;
@@ -81,8 +81,9 @@ class Route {
for (let i = 1, len = m.length; i < len; ++i) {
const key = keys[i - 1];
const val = _decodeURLEncodedURIComponent(m[i]);
- if (val !== undefined || !(hasOwnProperty.call(params, key.name))) {
- params[key.name] = val;
+ if (val !== undefined ||
+ !(hasOwnProperty.call(parameters, key.name))) {
+ parameters[key.name] = val;
}
}
diff --git a/client/js/util/misc.js b/client/js/util/misc.js
index 5e2297a..a3efede 100644
--- a/client/js/util/misc.js
+++ b/client/js/util/misc.js
@@ -113,7 +113,7 @@ function formatMarkdown(text) {
'$1[$2]($2)');
text = text.replace(/\]\(@(\d+)\)/g, '](/post/$1)');
text = text.replace(/\]\(\+([a-zA-Z0-9_-]+)\)/g, '](/user/$1)');
- text = text.replace(/\]\(#([a-zA-Z0-9_-]+)\)/g, '](/posts/text=$1)');
+ text = text.replace(/\]\(#([a-zA-Z0-9_-]+)\)/g, '](/posts/query=$1)');
return text;
};
@@ -131,7 +131,7 @@ function formatMarkdown(text) {
//search permalinks
text = text.replace(
/\[search\]((?:[^\[]|\[(?!\/?search\]))+)\[\/search\]/ig,
- '<a href="/posts/text=$1"><code>$1</code></a>');
+ '<a href="/posts/query=$1"><code>$1</code></a>');
//spoilers
text = text.replace(
/\[spoiler\]((?:[^\[]|\[(?!\/?spoiler\]))+)\[\/spoiler\]/ig,
@@ -149,10 +149,13 @@ function formatMarkdown(text) {
return postDecorator(marked(preDecorator(text), options));
}
-function formatSearchQuery(dict) {
+function formatUrlParameters(dict) {
let result = [];
for (let key of Object.keys(dict)) {
const value = dict[key];
+ if (key === 'parameters') {
+ continue;
+ }
if (value) {
result.push(`${key}=${value}`);
}
@@ -160,19 +163,23 @@ function formatSearchQuery(dict) {
return result.join(';');
}
-function parseSearchQuery(query) {
+function parseUrlParameters(query) {
let result = {};
for (let word of (query || '').split(/;/)) {
const [key, value] = word.split(/=/, 2);
result[key] = value;
}
- result.text = result.text || '';
+ result.query = result.query || '';
result.page = parseInt(result.page || '1');
return result;
}
-function parseSearchQueryRoute(ctx, next) {
- ctx.searchQuery = parseSearchQuery(ctx.params.query || '');
+function parseUrlParametersRoute(ctx, next) {
+ // ctx.parameters = {"user":...,"action":...} from /users/:user/:action
+ // ctx.parameters.parameters = value of :parameters as per /url/:parameters
+ Object.assign(
+ ctx.parameters,
+ parseUrlParameters(ctx.parameters.parameters));
next();
}
@@ -235,9 +242,9 @@ function escapeHtml(unsafe) {
module.exports = {
range: range,
- formatSearchQuery: formatSearchQuery,
- parseSearchQuery: parseSearchQuery,
- parseSearchQueryRoute: parseSearchQueryRoute,
+ formatUrlParameters: formatUrlParameters,
+ parseUrlParameters: parseUrlParameters,
+ parseUrlParametersRoute: parseUrlParametersRoute,
formatRelativeTime: formatRelativeTime,
formatFileSize: formatFileSize,
formatMarkdown: formatMarkdown,
diff --git a/client/js/util/views.js b/client/js/util/views.js
index a8af438..9561a27 100644
--- a/client/js/util/views.js
+++ b/client/js/util/views.js
@@ -146,6 +146,22 @@ function makeColorInput(options) {
'label', {class: 'color'}, colorInput + textInput);
}
+function getPostUrl(id, parameters) {
+ let url = '/post/' + encodeURIComponent(id);
+ if (parameters && parameters.query) {
+ url += '/query=' + encodeURIComponent(parameters.query);
+ }
+ return url;
+}
+
+function getPostEditUrl(id, parameters) {
+ let url = '/post/' + encodeURIComponent(id) + '/edit';
+ if (parameters && parameters.query) {
+ url += '/query=' + encodeURIComponent(parameters.query);
+ }
+ return url;
+}
+
function makePostLink(id) {
const text = '@' + id;
return api.hasPrivilege('posts:view') ?
@@ -303,6 +319,8 @@ function getTemplate(templatePath) {
ctx = {};
}
Object.assign(ctx, {
+ getPostUrl: getPostUrl,
+ getPostEditUrl: getPostEditUrl,
makeRelativeTime: makeRelativeTime,
makeFileSize: makeFileSize,
makeMarkdown: makeMarkdown,
diff --git a/client/js/views/endless_page_view.js b/client/js/views/endless_page_view.js
index 5965642..142a6dc 100644
--- a/client/js/views/endless_page_view.js
+++ b/client/js/views/endless_page_view.js
@@ -30,7 +30,7 @@ class EndlessPageView {
ctx.headerRenderer(ctx.headerContext);
}
- this._loadPage(ctx, ctx.searchQuery.page, true);
+ this._loadPage(ctx, ctx.parameters.page, true);
this._probePageLoad(ctx);
}
diff --git a/client/js/views/home_view.js b/client/js/views/home_view.js
index a8d151b..3278972 100644
--- a/client/js/views/home_view.js
+++ b/client/js/views/home_view.js
@@ -87,8 +87,8 @@ class HomeView {
_evtFormSubmit(e) {
e.preventDefault();
this._searchInputNode.blur();
- router.show('/posts/' + misc.formatSearchQuery({
- text: this._searchInputNode.value}));
+ router.show('/posts/' + misc.formatUrlParameters({
+ query: this._searchInputNode.value}));
}
}
diff --git a/client/js/views/manual_page_view.js b/client/js/views/manual_page_view.js
index 4d896e9..1ceac67 100644
--- a/client/js/views/manual_page_view.js
+++ b/client/js/views/manual_page_view.js
@@ -63,7 +63,7 @@ class ManualPageView {
const pageHeaderHolderNode
= sourceNode.querySelector('.page-header-holder');
const pageNavNode = sourceNode.querySelector('.page-nav');
- const currentPage = ctx.searchQuery.page;
+ const currentPage = ctx.parameters.page;
ctx.headerContext.hostNode = pageHeaderHolderNode;
if (ctx.headerRenderer) {
diff --git a/client/js/views/posts_header_view.js b/client/js/views/posts_header_view.js
index 5958e2a..6824b87 100644
--- a/client/js/views/posts_header_view.js
+++ b/client/js/views/posts_header_view.js
@@ -53,7 +53,7 @@ class PostsHeaderView {
'click', e => this._evtStopTaggingClick(e));
this._massTagFormNode.addEventListener(
'submit', e => this._evtMassTagFormSubmit(e));
- this._toggleMassTagVisibility(!!ctx.searchQuery.tag);
+ this._toggleMassTagVisibility(!!ctx.parameters.tag);
}
}
@@ -96,9 +96,9 @@ class PostsHeaderView {
_evtStopTaggingClick(e) {
e.preventDefault();
- router.show('/posts/' + misc.formatSearchQuery({
- text: this._ctx.searchQuery.text,
- page: this._ctx.searchQuery.page,
+ router.show('/posts/' + misc.formatUrlParameters({
+ query: this._ctx.parameters.query,
+ page: this._ctx.parameters.page,
}));
}
@@ -117,7 +117,7 @@ class PostsHeaderView {
e.preventDefault();
const text = this._queryInputNode.value;
this._queryInputNode.blur();
- router.show('/posts/' + misc.formatSearchQuery({text: text}));
+ router.show('/posts/' + misc.formatUrlParameters({query: text}));
}
_evtMassTagFormSubmit(e) {
@@ -125,10 +125,10 @@ class PostsHeaderView {
const text = this._queryInputNode.value;
const tag = this._massTagInputNode.value;
this._massTagInputNode.blur();
- router.show('/posts/' + misc.formatSearchQuery({
- text: text,
+ router.show('/posts/' + misc.formatUrlParameters({
+ query: text,
tag: tag,
- page: this._ctx.searchQuery.page,
+ page: this._ctx.parameters.page,
}));
}
}
diff --git a/client/js/views/tags_header_view.js b/client/js/views/tags_header_view.js
index 61ea8d2..a9babc2 100644
--- a/client/js/views/tags_header_view.js
+++ b/client/js/views/tags_header_view.js
@@ -37,8 +37,8 @@ class TagsHeaderView {
e.preventDefault();
this._queryInputNode.blur();
router.show(
- '/tags/' + misc.formatSearchQuery({
- text: this._queryInputNode.value,
+ '/tags/' + misc.formatUrlParameters({
+ query: this._queryInputNode.value,
}));
}
}
diff --git a/client/js/views/users_header_view.js b/client/js/views/users_header_view.js
index 2284ba7..8678025 100644
--- a/client/js/views/users_header_view.js
+++ b/client/js/views/users_header_view.js
@@ -31,8 +31,8 @@ class UsersHeaderView {
e.preventDefault();
this._queryInputNode.blur();
router.show(
- '/users/' + misc.formatSearchQuery({
- text: this._queryInputNode.value,
+ '/users/' + misc.formatUrlParameters({
+ query: this._queryInputNode.value,
}));
}
}

© 2015 - 2026 Jakob L. Kreuze