diff --git a/package.json b/package.json index c9e39daf..8dc89d20 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,6 @@ "name": "szuru2", "version": "0.0.0", "dependencies": { - "pathjs": "~0.8.1", "jquery.cookie": "1.4.1", "jquery": "~2.1.1", "underscore": "1.7.0", diff --git a/public_html/index.html b/public_html/index.html index abec5f17..5035891f 100644 --- a/public_html/index.html +++ b/public_html/index.html @@ -12,7 +12,6 @@ - diff --git a/public_html/js/Bootstrap.js b/public_html/js/Bootstrap.js index f6c6720c..20bb07b9 100644 --- a/public_html/js/Bootstrap.js +++ b/public_html/js/Bootstrap.js @@ -1,6 +1,6 @@ var App = App || {}; -App.Bootstrap = function(auth, router, util, promise, presenterManager) { +App.Bootstrap = function(auth, router, promise, presenterManager) { promise.wait( auth.tryLoginFromCookie(), @@ -25,7 +25,7 @@ App.Bootstrap = function(auth, router, util, promise, presenterManager) { }; -App.DI.registerSingleton('bootstrap', ['auth', 'router', 'util', 'promise', 'presenterManager'], App.Bootstrap); +App.DI.registerSingleton('bootstrap', ['auth', 'router', 'promise', 'presenterManager'], App.Bootstrap); App.DI.registerManual('jQuery', function() { return window.$; }); App.DI.registerManual('pathJs', function() { return window.pathjs; }); App.DI.registerManual('_', function() { return window._; }); diff --git a/public_html/js/Pager.js b/public_html/js/Pager.js index 6062631e..a9803f93 100644 --- a/public_html/js/Pager.js +++ b/public_html/js/Pager.js @@ -51,7 +51,8 @@ App.Pager = function( function setSearchParams(newSearchParams) { setPage(1); - searchParams = newSearchParams; + searchParams = _.extend({}, newSearchParams); + delete searchParams.page; } function retrieve() { @@ -64,7 +65,8 @@ App.Pager = function( resolve({ entities: response.json.data, - totalRecords: totalRecords}); + totalRecords: totalRecords, + totalPages: totalPages}); }).fail(function(response) { reject(response); diff --git a/public_html/js/Presenters/GlobalCommentListPresenter.js b/public_html/js/Presenters/GlobalCommentListPresenter.js index 84b66a39..73722f9e 100644 --- a/public_html/js/Presenters/GlobalCommentListPresenter.js +++ b/public_html/js/Presenters/GlobalCommentListPresenter.js @@ -12,7 +12,7 @@ App.Presenters.GlobalCommentListPresenter = function( var $el; var templates = {}; - function init(args, loaded) { + function init(params, loaded) { $el = jQuery('#content'); topNavigationPresenter.select('comments'); @@ -38,25 +38,16 @@ App.Presenters.GlobalCommentListPresenter = function( }, }, function() { - onArgsChanged(args); + reinit(params, function() {}); }); }) .fail(function() { console.log(new Error(arguments)); }); } - function reinit(args, loaded) { + function reinit(params, loaded) { + pagerPresenter.reinit({query: params.query}); loaded(); - onArgsChanged(args); - } - - function onArgsChanged(args) { - var searchArgs = util.parseComplexRouteArgs(args.searchArgs); - pagerPresenter.reinit({ - page: searchArgs.page, - searchParams: { - query: searchArgs.query, - order: searchArgs.order}}); } function deinit() { @@ -79,6 +70,7 @@ App.Presenters.GlobalCommentListPresenter = function( var comments = data.comments; var $post = jQuery('
  • ' + templates.listItem({ + util: util, post: post, postTemplate: templates.post, }) + '
  • '); @@ -104,6 +96,7 @@ App.Presenters.GlobalCommentListPresenter = function( deinit: deinit, render: render, }; + }; App.DI.register('globalCommentListPresenter', ['_', 'jQuery', 'util', 'promise', 'pagerPresenter', 'topNavigationPresenter'], App.Presenters.GlobalCommentListPresenter); diff --git a/public_html/js/Presenters/HelpPresenter.js b/public_html/js/Presenters/HelpPresenter.js index 27620fce..ec41aac1 100644 --- a/public_html/js/Presenters/HelpPresenter.js +++ b/public_html/js/Presenters/HelpPresenter.js @@ -7,7 +7,7 @@ App.Presenters.HelpPresenter = function( var $el = jQuery('#content'); - function init(args, loaded) { + function init(params, loaded) { topNavigationPresenter.select('help'); topNavigationPresenter.changeTitle('Help'); render(); diff --git a/public_html/js/Presenters/HomePresenter.js b/public_html/js/Presenters/HomePresenter.js index aa1200c3..d321203e 100644 --- a/public_html/js/Presenters/HomePresenter.js +++ b/public_html/js/Presenters/HomePresenter.js @@ -15,7 +15,7 @@ App.Presenters.HomePresenter = function( var globals; var post; - function init(args, loaded) { + function init(params, loaded) { topNavigationPresenter.select('home'); topNavigationPresenter.changeTitle('Home'); diff --git a/public_html/js/Presenters/LoginPresenter.js b/public_html/js/Presenters/LoginPresenter.js index 990b0aca..954bf75e 100644 --- a/public_html/js/Presenters/LoginPresenter.js +++ b/public_html/js/Presenters/LoginPresenter.js @@ -13,12 +13,12 @@ App.Presenters.LoginPresenter = function( var $el = jQuery('#content'); var $messages; var templates = {}; - var previousRoute; + var previousLocation; - function init(args, loaded) { + function init(params, loaded) { topNavigationPresenter.select('login'); topNavigationPresenter.changeTitle('Login'); - previousRoute = args.previousRoute; + previousLocation = params.previousLocation; promise.wait(util.promiseTemplate('login-form')) .then(function(template) { templates.login = template; @@ -66,8 +66,8 @@ App.Presenters.LoginPresenter = function( } function finishLogin() { - if (previousRoute && !previousRoute.match(/logout|password-reset|activate|register/)) { - router.navigate(previousRoute); + if (previousLocation && !previousLocation.match(/logout|password-reset|activate|register/)) { + router.navigate(previousLocation); } else { router.navigateToMainPage(); } diff --git a/public_html/js/Presenters/LogoutPresenter.js b/public_html/js/Presenters/LogoutPresenter.js index 9f67e01b..b13102ee 100644 --- a/public_html/js/Presenters/LogoutPresenter.js +++ b/public_html/js/Presenters/LogoutPresenter.js @@ -11,7 +11,7 @@ App.Presenters.LogoutPresenter = function( var $messages = jQuery('#content'); - function init(args, loaded) { + function init(params, loaded) { topNavigationPresenter.select('logout'); topNavigationPresenter.changeTitle('Logout'); promise.wait(auth.logout()) diff --git a/public_html/js/Presenters/PagerPresenter.js b/public_html/js/Presenters/PagerPresenter.js index 8d7b920c..9c7210b6 100644 --- a/public_html/js/Presenters/PagerPresenter.js +++ b/public_html/js/Presenters/PagerPresenter.js @@ -26,17 +26,20 @@ App.Presenters.PagerPresenter = function( var baseUri; var updateCallback; - function init(args, loaded) { - baseUri = args.baseUri; - updateCallback = args.updateCallback; + function init(params, loaded) { + baseUri = params.baseUri; + updateCallback = params.updateCallback; messagePresenter.instant = true; - $target = args.$target; - targetContent = jQuery(args.$target).html(); + $target = params.$target; + targetContent = jQuery(params.$target).html(); - pager.init({url: args.backendUri}); - pager.setSearchParams(args.searchParams); + if (forceClear) { + clearContent(); + } + pager.init({url: params.backendUri}); + setQuery(params.query); promise.wait(util.promiseTemplate('pager')) .then(function(template) { @@ -46,62 +49,28 @@ App.Presenters.PagerPresenter = function( }); } - function reinit(args, loaded) { - forceClear = !_.isEqual(args.searchParams, pager.getSearchParams()) || parseInt(args.page) !== pager.getPage(); - - pager.setSearchParams(args.searchParams); - pager.setPage(args.page || 1); + function reinit(params, loaded) { + if (forceClear) { + clearContent(); + } + setQuery(params.query); promise.wait(retrieve()) .then(loaded) .fail(loaded); if (!endlessScroll) { - keyboard.keydown('a', prevPage); - keyboard.keydown('d', nextPage); + keyboard.keydown('a', function() { pager.prevPage(); syncUrl(); }); + keyboard.keydown('d', function() { pager.nextPage(); syncUrl(); }); } } - function deinit() { detachNextPageLoader(); } - function prevPage() { - pager.prevPage(); - syncUrl(); - } - - function nextPage() { - pager.nextPage(); - syncUrl(); - } - - function nextPageInplace() { - pager.nextPage(); - syncUrlInplace(); - } - - function setPage(newPage) { - pager.setPage(newPage); - syncUrl(); - } - - function setSearchParams(newSearchParams) { - if (_.isEqual(pager.getSearchParams(), newSearchParams)) { - return; - } - clearContent(); - pager.setSearchParams(newSearchParams); - syncUrl(); - } - function getUrl() { - return util.compileComplexRouteArgs( - baseUri, - _.extend( - {page: pager.getPage()}, - pager.getSearchParams())); + return util.appendComplexRouteParam(baseUri, _.extend({}, pager.getSearchParams(), {page: pager.getPage()})); } function syncUrl() { @@ -148,9 +117,11 @@ App.Presenters.PagerPresenter = function( showPageList(); } + if (pager.getPage() < response.totalPages) { + attachNextPageLoader(); + } refreshPageList(); hideSpinner(); - attachNextPageLoader(); resolve(); }).fail(function(response) { clearContent(); @@ -177,7 +148,8 @@ App.Presenters.PagerPresenter = function( var baseLine = $target.offset().top + $target.innerHeight(); var scrollY = jQuery(window).scrollTop() + jQuery(window).height(); if (scrollY > baseLine) { - nextPageInplace(); + pager.nextPage(); + syncUrlInplace(); window.clearInterval(scrollInterval); } }, 100); @@ -207,7 +179,8 @@ App.Presenters.PagerPresenter = function( var $a = jQuery(''); $a.click(function() { - setPage(page); + pager.setPage(page); + syncUrl(); }); $a.addClass('big-button'); $a.text(page); @@ -231,12 +204,32 @@ App.Presenters.PagerPresenter = function( } } + function setQuery(query) { + if (!query) { + return; + } + query.page = parseInt(query.page) || 1; + var page = query.page; + delete query.page; + forceClear = + query.query !== pager.getSearchParams().query || + query.order !== pager.getSearchParams().order || + parseInt(page) !== pager.getPage(); + pager.setSearchParams(query); + pager.setPage(page); + } + + function setQueryAndSyncUrl(query) { + setQuery(query); + syncUrl(); + } + return { init: init, reinit: reinit, deinit: deinit, - setPage: setPage, - setSearchParams: setSearchParams, + syncUrl: syncUrl, + setQuery: setQueryAndSyncUrl, }; }; diff --git a/public_html/js/Presenters/PostCommentListPresenter.js b/public_html/js/Presenters/PostCommentListPresenter.js index d002708f..5294d986 100644 --- a/public_html/js/Presenters/PostCommentListPresenter.js +++ b/public_html/js/Presenters/PostCommentListPresenter.js @@ -18,10 +18,10 @@ App.Presenters.PostCommentListPresenter = function( var post; var comments = []; - function init(args, loaded) { - $el = args.$target; - post = args.post; - comments = args.comments || []; + function init(params, loaded) { + $el = params.$target; + post = params.post; + comments = params.comments || []; privileges = { canListComments: auth.hasPrivilege(auth.privileges.listComments), @@ -49,7 +49,7 @@ App.Presenters.PostCommentListPresenter = function( loaded(); if (comments.length === 0) { - promise.wait(api.get('/comments/' + args.post.id)) + promise.wait(api.get('/comments/' + params.post.id)) .then(function(response) { comments = response.json.data; render(); @@ -222,6 +222,7 @@ App.Presenters.PostCommentListPresenter = function( init: init, render: render, }; + }; App.DI.register('postCommentListPresenter', ['_', 'jQuery', 'util', 'promise', 'api', 'auth', 'topNavigationPresenter', 'messagePresenter'], App.Presenters.PostCommentListPresenter); diff --git a/public_html/js/Presenters/PostListPresenter.js b/public_html/js/Presenters/PostListPresenter.js index de1e21a2..f454add7 100644 --- a/public_html/js/Presenters/PostListPresenter.js +++ b/public_html/js/Presenters/PostListPresenter.js @@ -17,13 +17,13 @@ App.Presenters.PostListPresenter = function( var $el = jQuery('#content'); var $searchInput; - var searchArgs; + var params; - function init(args, loaded) { + function init(_params, loaded) { topNavigationPresenter.select('posts'); topNavigationPresenter.changeTitle('Posts'); - searchArgs = util.parseComplexRouteArgs(args.searchArgs); - searchArgs.page = parseInt(searchArgs.page) || 1; + params = _params; + params.query = params.query || {}; promise.wait( util.promiseTemplate('post-list'), @@ -44,23 +44,14 @@ App.Presenters.PostListPresenter = function( }, }, function() { - onArgsChanged(args); + reinit(params, function() {}); }); }); } - function reinit(args, loaded) { + function reinit(params, loaded) { + pagerPresenter.reinit({query: params.query}); loaded(); - onArgsChanged(args); - } - - function onArgsChanged(args) { - searchArgs = util.parseComplexRouteArgs(args.searchArgs); - pagerPresenter.reinit({ - page: searchArgs.page, - searchParams: { - query: searchArgs.query, - order: searchArgs.order}}); } function deinit() { @@ -72,7 +63,7 @@ App.Presenters.PostListPresenter = function( $searchInput = $el.find('input[name=query]'); App.Controls.AutoCompleteInput($searchInput); - $searchInput.val(searchArgs.query); + $searchInput.val(params.query.query); $searchInput.keydown(searchInputKeyPressed); $el.find('form').submit(searchFormSubmitted); @@ -94,7 +85,8 @@ App.Presenters.PostListPresenter = function( _.each(posts, function(post) { var $post = jQuery('
  • ' + templates.listItem({ - searchArgs: searchArgs, + util: util, + query: params.query, post: post, }) + '
  • '); util.loadImagesNicely($post.find('img')); @@ -116,9 +108,8 @@ App.Presenters.PostListPresenter = function( function updateSearch() { $searchInput.blur(); - pagerPresenter.setSearchParams({ - query: $searchInput.val().trim(), - order: searchArgs.order}); + params.query.query = $searchInput.val().trim(); + pagerPresenter.setQuery(params.query); } return { diff --git a/public_html/js/Presenters/PostPresenter.js b/public_html/js/Presenters/PostPresenter.js index 8a3872c7..a06d33b5 100644 --- a/public_html/js/Presenters/PostPresenter.js +++ b/public_html/js/Presenters/PostPresenter.js @@ -20,9 +20,9 @@ App.Presenters.PostPresenter = function( var $messages = $el; var templates = {}; + var params; var postNameOrId; - var searchArgs; var post; var privileges = {}; @@ -34,7 +34,7 @@ App.Presenters.PostPresenter = function( var postContent; var postThumbnail; - function init(args, loaded) { + function init(params, loaded) { topNavigationPresenter.select('posts'); postsAroundCalculator.resetCache(); @@ -64,18 +64,19 @@ App.Presenters.PostPresenter = function( templates.postContent = postContentTemplate; templates.history = historyTemplate; - reinit(args, loaded); + reinit(params, loaded); }).fail(function(response) { showGenericError(response); loaded(); }); } - function reinit(args, loaded) { - postNameOrId = args.postNameOrId; + function reinit(_params, loaded) { + params = _params; + params.query = params.query || {}; + params.query.page = parseInt(params.query.page) || 1; - searchArgs = util.parseComplexRouteArgs(args.searchArgs); - searchArgs.page = parseInt(searchArgs.page) || 1; + postNameOrId = params.postNameOrId; promise.wait(refreshPost()) .then(function() { @@ -86,8 +87,7 @@ App.Presenters.PostPresenter = function( } function attachLinksToPostsAround() { - var searchParams = {query: searchArgs.query, order: searchArgs.order}; - promise.wait(postsAroundCalculator.getLinksToPostsAround(searchParams, searchArgs.page, post.id)) + promise.wait(postsAroundCalculator.getLinksToPostsAround(params.query, post.id)) .then(function(nextPostUrl, prevPostUrl) { var $prevPost = $el.find('#post-current-search .right a'); var $nextPost = $el.find('#post-current-search .left a'); @@ -175,7 +175,7 @@ App.Presenters.PostPresenter = function( function renderPostTemplate() { return templates.post({ - searchArgs: searchArgs, + query: params.query, post: post, ownScore: post.ownScore, postFavorites: post.favorites, diff --git a/public_html/js/Presenters/PostUploadPresenter.js b/public_html/js/Presenters/PostUploadPresenter.js index ebae81f4..0911daa6 100644 --- a/public_html/js/Presenters/PostUploadPresenter.js +++ b/public_html/js/Presenters/PostUploadPresenter.js @@ -23,7 +23,7 @@ App.Presenters.PostUploadPresenter = function( var fileDropper; var interactionEnabled = true; - function init(args, loaded) { + function init(params, loaded) { topNavigationPresenter.select('upload'); topNavigationPresenter.changeTitle('Upload'); diff --git a/public_html/js/Presenters/RegistrationPresenter.js b/public_html/js/Presenters/RegistrationPresenter.js index 546a9f71..9320b514 100644 --- a/public_html/js/Presenters/RegistrationPresenter.js +++ b/public_html/js/Presenters/RegistrationPresenter.js @@ -13,7 +13,7 @@ App.Presenters.RegistrationPresenter = function( var templates = {}; var $messages; - function init(args, loaded) { + function init(params, loaded) { topNavigationPresenter.select('register'); topNavigationPresenter.changeTitle('Registration'); promise.wait(util.promiseTemplate('registration-form')) diff --git a/public_html/js/Presenters/TagListPresenter.js b/public_html/js/Presenters/TagListPresenter.js index a54a0573..9eec6e99 100644 --- a/public_html/js/Presenters/TagListPresenter.js +++ b/public_html/js/Presenters/TagListPresenter.js @@ -13,7 +13,7 @@ App.Presenters.TagListPresenter = function( var $el = jQuery('#content'); var templates = {}; - function init(args, loaded) { + function init(params, loaded) { topNavigationPresenter.select('tags'); topNavigationPresenter.changeTitle('Tags'); @@ -36,28 +36,23 @@ App.Presenters.TagListPresenter = function( }, }, function() { - reinit(args, function() {}); + reinit(params, function() {}); }); }); } - function reinit(args, loaded) { - loaded(); + function reinit(params, loaded) { + params.query = params.query || {}; + params.query.order = params.query.order || 'name,asc'; + updateActiveOrder(params.query.order); - var searchArgs = util.parseComplexRouteArgs(args.searchArgs); - searchArgs.order = searchArgs.order || 'name,asc'; - searchArgs.page = parseInt(searchArgs.page) || 1; - updateActiveOrder(searchArgs.order); - - pagerPresenter.reinit({ - page: searchArgs.page, - searchParams: { - order: searchArgs.order}}); + pagerPresenter.reinit({query: params.query}); keyboard.keyup('p', function() { $el.find('table a').eq(0).focus(); }); + loaded(); } function deinit() { diff --git a/public_html/js/Presenters/TagPresenter.js b/public_html/js/Presenters/TagPresenter.js index 6733575a..6c6a2eaa 100644 --- a/public_html/js/Presenters/TagPresenter.js +++ b/public_html/js/Presenters/TagPresenter.js @@ -15,7 +15,7 @@ App.Presenters.TagPresenter = function( var tagName; - function init(args, loaded) { + function init(params, loaded) { topNavigationPresenter.select('tags'); topNavigationPresenter.changeTitle('Tags'); @@ -26,12 +26,12 @@ App.Presenters.TagPresenter = function( templates.tag = tagTemplate; templates.postListItem = postListItemTemplate; - reinit(args, loaded); + reinit(params, loaded); }); } - function reinit(args, loaded) { - tagName = args.tagName; + function reinit(params, loaded) { + tagName = params.tagName; render(); loaded(); @@ -55,8 +55,9 @@ App.Presenters.TagPresenter = function( var $target = $el.find('.post-list ul'); _.each(posts, function(post) { var $post = jQuery('
  • ' + templates.postListItem({ + util: util, post: post, - searchArgs: {query: tagName}, + query: {query: tagName}, }) + '
  • '); $target.append($post); }); @@ -72,6 +73,7 @@ App.Presenters.TagPresenter = function( init: init, reinit: reinit, }; + }; App.DI.register('tagPresenter', ['_', 'jQuery', 'util', 'promise', 'api', 'keyboard', 'topNavigationPresenter'], App.Presenters.TagPresenter); diff --git a/public_html/js/Presenters/TopNavigationPresenter.js b/public_html/js/Presenters/TopNavigationPresenter.js index 28a7c519..8d576535 100644 --- a/public_html/js/Presenters/TopNavigationPresenter.js +++ b/public_html/js/Presenters/TopNavigationPresenter.js @@ -12,7 +12,7 @@ App.Presenters.TopNavigationPresenter = function( var templates = {}; var baseTitle = document.title; - function init(args, loaded) { + function init(params, loaded) { promise.wait(util.promiseTemplate('top-navigation')) .then(function(template) { templates.topNavigation = template; diff --git a/public_html/js/Presenters/UserAccountRemovalPresenter.js b/public_html/js/Presenters/UserAccountRemovalPresenter.js index 177100dc..f20d0900 100644 --- a/public_html/js/Presenters/UserAccountRemovalPresenter.js +++ b/public_html/js/Presenters/UserAccountRemovalPresenter.js @@ -15,9 +15,9 @@ App.Presenters.UserAccountRemovalPresenter = function( var user; var privileges = {}; - function init(args, loaded) { - user = args.user; - target = args.target; + function init(params, loaded) { + user = params.user; + target = params.target; privileges.canDeleteAccount = auth.hasPrivilege(auth.privileges.deleteAllAccounts) || diff --git a/public_html/js/Presenters/UserAccountSettingsPresenter.js b/public_html/js/Presenters/UserAccountSettingsPresenter.js index 05c2e546..0facc7f5 100644 --- a/public_html/js/Presenters/UserAccountSettingsPresenter.js +++ b/public_html/js/Presenters/UserAccountSettingsPresenter.js @@ -17,9 +17,9 @@ App.Presenters.UserAccountSettingsPresenter = function( var avatarContent; var fileDropper; - function init(args, loaded) { - user = args.user; - target = args.target; + function init(params, loaded) { + user = params.user; + target = params.target; privileges = { canBan: diff --git a/public_html/js/Presenters/UserActivationPresenter.js b/public_html/js/Presenters/UserActivationPresenter.js index e055a455..350379f9 100644 --- a/public_html/js/Presenters/UserActivationPresenter.js +++ b/public_html/js/Presenters/UserActivationPresenter.js @@ -17,20 +17,20 @@ App.Presenters.UserActivationPresenter = function( var formHidden = false; var operation; - function init(args, loaded) { + function init(params, loaded) { topNavigationPresenter.select('login'); topNavigationPresenter.changeTitle('Account recovery'); - reinit(args, loaded); + reinit(params, loaded); } - function reinit(args, loaded) { - operation = args.operation; + function reinit(params, loaded) { + operation = params.operation; promise.wait(util.promiseTemplate('user-query-form')) .then(function(template) { templates.userQuery = template; - if (args.token) { + if (params.token) { hideForm(); - confirmToken(args.token); + confirmToken(params.token); } else { showForm(); } diff --git a/public_html/js/Presenters/UserBrowsingSettingsPresenter.js b/public_html/js/Presenters/UserBrowsingSettingsPresenter.js index e0f43f08..f26a69c2 100644 --- a/public_html/js/Presenters/UserBrowsingSettingsPresenter.js +++ b/public_html/js/Presenters/UserBrowsingSettingsPresenter.js @@ -14,9 +14,9 @@ App.Presenters.UserBrowsingSettingsPresenter = function( var user; var privileges = {}; - function init(args, loaded) { - user = args.user; - target = args.target; + function init(params, loaded) { + user = params.user; + target = params.target; privileges.canChangeBrowsingSettings = auth.isLoggedIn(user.name) && user.name === auth.getCurrentUser().name; diff --git a/public_html/js/Presenters/UserListPresenter.js b/public_html/js/Presenters/UserListPresenter.js index a86bbc15..cc0189d0 100644 --- a/public_html/js/Presenters/UserListPresenter.js +++ b/public_html/js/Presenters/UserListPresenter.js @@ -12,8 +12,9 @@ App.Presenters.UserListPresenter = function( var $el = jQuery('#content'); var templates = {}; + var params; - function init(args, loaded) { + function init(params, loaded) { topNavigationPresenter.select('users'); topNavigationPresenter.changeTitle('Users'); @@ -36,23 +37,19 @@ App.Presenters.UserListPresenter = function( }, }, function() { - reinit(args, function() {}); + reinit(params, function() {}); }); }); } - function reinit(args, loaded) { + function reinit(_params, loaded) { + params = _params; + params.query = params.query || {}; + params.query.order = params.query.order || 'name,asc'; + updateActiveOrder(params.query.order); + + pagerPresenter.reinit({query: params.query}); loaded(); - - var searchArgs = util.parseComplexRouteArgs(args.searchArgs); - searchArgs.order = searchArgs.order || 'name,asc'; - searchArgs.page = parseInt(searchArgs.page) || 1; - updateActiveOrder(searchArgs.order); - - pagerPresenter.reinit({ - page: searchArgs.page, - searchParams: { - order: searchArgs.order}}); } function deinit() { @@ -90,7 +87,8 @@ App.Presenters.UserListPresenter = function( e.preventDefault(); var $orderLink = jQuery(this); var activeSearchOrder = $orderLink.attr('data-order'); - pagerPresenter.setSearchParams({order: activeSearchOrder}); + params.query.order = activeSearchOrder; + pagerPresenter.setQuery(params.query); } return { diff --git a/public_html/js/Presenters/UserPresenter.js b/public_html/js/Presenters/UserPresenter.js index e4593138..af1223b0 100644 --- a/public_html/js/Presenters/UserPresenter.js +++ b/public_html/js/Presenters/UserPresenter.js @@ -22,32 +22,32 @@ App.Presenters.UserPresenter = function( var userName = null; var activeTab; - function init(args, loaded) { + function init(params, loaded) { promise.wait(util.promiseTemplate('user')) .then(function(template) { $messages = $el.find('.messages'); templates.user = template; - reinit(args, loaded); + reinit(params, loaded); }); } - function reinit(args, loaded) { - if (args.userName !== userName) { - userName = args.userName; + function reinit(params, loaded) { + if (params.userName !== userName) { + userName = params.userName; topNavigationPresenter.select(auth.isLoggedIn(userName) ? 'my-account' : 'users'); topNavigationPresenter.changeTitle(userName); promise.wait(api.get('/users/' + userName)) .then(function(response) { user = response.json; - var extendedContext = _.extend(args, {user: user}); + var extendedContext = _.extend(params, {user: user}); presenterManager.initPresenters([ [userBrowsingSettingsPresenter, _.extend({}, extendedContext, {target: '#browsing-settings-target'})], [userAccountSettingsPresenter, _.extend({}, extendedContext, {target: '#account-settings-target'})], [userAccountRemovalPresenter, _.extend({}, extendedContext, {target: '#account-removal-target'})]], function() { - initTabs(args); + initTabs(params); loaded(); }); @@ -58,13 +58,13 @@ App.Presenters.UserPresenter = function( }); } else { - initTabs(args); + initTabs(params); loaded(); } } - function initTabs(args) { - activeTab = args.tab || 'basic-info'; + function initTabs(params) { + activeTab = params.tab || 'basic-info'; render(); } diff --git a/public_html/js/Router.js b/public_html/js/Router.js index 47bbefbb..31240268 100644 --- a/public_html/js/Router.js +++ b/public_html/js/Router.js @@ -1,34 +1,16 @@ var App = App || {}; -App.Router = function(pathJs, _, jQuery, promise, util, appState, presenterManager) { +App.Router = function(_, jQuery, promise, util, appState, presenterManager) { var root = '#/'; var previousLocation = window.location.href; + var routes = []; injectRoutes(); - function navigateToMainPage() { - window.location.href = root; - } - - function navigate(url) { - window.location.href = url; - } - - function navigateInplace(url) { - if ('replaceState' in history) { - history.replaceState('', '', url); - pathJs.dispatch(document.location.hash); - } else { - navigate(url); - } - } - - function start() { - pathJs.listen(); - } - function injectRoutes() { + inject('', 'homePresenter'); + inject('#/', 'homePresenter'); inject('#/home', 'homePresenter'); inject('#/login', 'loginPresenter'); inject('#/logout', 'logoutPresenter'); @@ -36,24 +18,42 @@ App.Router = function(pathJs, _, jQuery, promise, util, appState, presenterManag inject('#/upload', 'postUploadPresenter'); inject('#/password-reset(/:token)', 'userActivationPresenter', {operation: 'passwordReset'}); inject('#/activate(/:token)', 'userActivationPresenter', {operation: 'activation'}); - inject('#/users(/:searchArgs)', 'userListPresenter'); + inject('#/users(/:!query)', 'userListPresenter'); inject('#/user/:userName(/:tab)', 'userPresenter'); - inject('#/posts(/:searchArgs)', 'postListPresenter'); - inject('#/post(/:postNameOrId)(/:searchArgs)', 'postPresenter'); - inject('#/comments(/:searchArgs)', 'globalCommentListPresenter'); - inject('#/tags(/:searchArgs)', 'tagListPresenter'); - inject('#/tag(/:tagName)', 'tagPresenter'); + inject('#/posts(/:!query)', 'postListPresenter'); + inject('#/post/:postNameOrId(/:!query)', 'postPresenter'); + inject('#/comments(/:!query)', 'globalCommentListPresenter'); + inject('#/tags(/:!query)', 'tagListPresenter'); + inject('#/tag/:tagName', 'tagPresenter'); inject('#/help', 'helpPresenter'); - setRoot('#/home'); } - function setRoot(newRoot) { - root = newRoot; - pathJs.root(newRoot); + function navigate(url) { + window.location.href = url; } - function inject(path, presenterName, additionalParams) { - pathJs.map(path).to(function() { + function navigateToMainPage() { + navigate(root); + } + + function navigateInplace(url) { + if ('replaceState' in history) { + history.replaceState('', '', url); + dispatch(); + } else { + navigate(url); + } + } + + function start() { + window.onpopstate = function() { + dispatch(); + }; + dispatch(); + } + + function inject(definition, presenterName, additionalParams) { + routes.push(new Route(definition, function(params) { if (util.isExitConfirmationEnabled()) { if (window.location.href === previousLocation) { return; @@ -67,28 +67,106 @@ App.Router = function(pathJs, _, jQuery, promise, util, appState, presenterManag } } + params = _.extend({}, params, additionalParams, {previousLocation: previousLocation}); + //abort every operation that can be executed promise.abortAll(); previousLocation = window.location.href; - var finalParams = _.extend( - this.params, - additionalParams, - {previousRoute: pathJs.routes.previous}); - var presenter = App.DI.get(presenterName); presenter.name = presenterName; - presenterManager.switchContentPresenter(presenter, finalParams); - }); + 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; + } + + 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; + } + + return { start: start, navigate: navigate, navigateInplace: navigateInplace, navigateToMainPage: navigateToMainPage, }; - }; -App.DI.registerSingleton('router', ['pathJs', '_', 'jQuery', 'promise', 'util', 'appState', 'presenterManager'], App.Router); +App.DI.registerSingleton('router', ['_', 'jQuery', 'promise', 'util', 'appState', 'presenterManager'], App.Router); diff --git a/public_html/js/Services/PostsAroundCalculator.js b/public_html/js/Services/PostsAroundCalculator.js index 80d0f1b4..f4f86ef0 100644 --- a/public_html/js/Services/PostsAroundCalculator.js +++ b/public_html/js/Services/PostsAroundCalculator.js @@ -9,10 +9,10 @@ App.Services.PostsAroundCalculator = function(_, promise, util, pager) { pager.resetCache(); } - function getLinksToPostsAround(searchParams, page, postId) { + function getLinksToPostsAround(query, postId) { return promise.make(function(resolve, reject) { - pager.setSearchParams(searchParams); - pager.setPage(page); + pager.setSearchParams(query); + pager.setPage(query.page); promise.wait(pager.retrieveCached()) .then(function(response) { var postIds = _.pluck(response.entities, 'id'); @@ -23,8 +23,8 @@ App.Services.PostsAroundCalculator = function(_, promise, util, pager) { } promise.wait( - getLinkToPostAround(postIds, position, page, -1), - getLinkToPostAround(postIds, position, page, 1)) + getLinkToPostAround(postIds, position, query.page, -1), + getLinkToPostAround(postIds, position, query.page, 1)) .then(function(nextPostUrl, prevPostUrl) { resolve(nextPostUrl, prevPostUrl); }); @@ -35,7 +35,7 @@ App.Services.PostsAroundCalculator = function(_, promise, util, pager) { function getLinkToPostAround(postIds, position, page, direction) { return promise.make(function(resolve, reject) { if (position + direction >= 0 && position + direction < postIds.length) { - var url = util.compileComplexRouteArgs( + var url = util.appendComplexRouteParam( '#/post/' + postIds[position + direction], _.extend({page: page}, pager.getSearchParams())); resolve(url); @@ -47,7 +47,7 @@ App.Services.PostsAroundCalculator = function(_, promise, util, pager) { _.last(response.entities) : _.first(response.entities); - var url = util.compileComplexRouteArgs( + var url = util.appendComplexRouteParam( '#/post/' + post.id, _.extend({page: page + direction}, pager.getSearchParams())); resolve(url); diff --git a/public_html/js/Util.js b/public_html/js/Util.js index e1c934ab..73c87386 100644 --- a/public_html/js/Util.js +++ b/public_html/js/Util.js @@ -31,31 +31,6 @@ App.Util = function(_, jQuery, marked, promise) { }); } - function parseComplexRouteArgs(args) { - var result = {}; - args = (args || '').split(/;/); - for (var i = 0; i < args.length; i ++) { - var arg = args[i]; - if (!arg) { - continue; - } - var kv = arg.split(/=/); - result[kv[0]] = kv[1]; - } - return result; - } - - function compileComplexRouteArgs(baseUri, args) { - var result = baseUri + '/'; - _.each(args, function(v, k) { - if (typeof(v) !== 'undefined') { - result += k + '=' + v + ';'; - } - }); - result = result.slice(0, -1); - return result; - } - function promiseTemplate(templateName) { return promiseTemplateFromDOM(templateName) || promiseTemplateWithAJAX(templateName); @@ -218,10 +193,18 @@ App.Util = function(_, jQuery, marked, promise) { return postDecorator(marked(preDecorator(text), options)); } + function appendComplexRouteParam(baseUri, params) { + var result = baseUri + '/'; + _.each(params, function(v, k) { + if (typeof(v) !== 'undefined') { + result += k + '=' + v + ';'; + } + }); + return result.slice(0, -1); + } + return { promiseTemplate: promiseTemplate, - parseComplexRouteArgs: parseComplexRouteArgs, - compileComplexRouteArgs: compileComplexRouteArgs, formatRelativeTime: formatRelativeTime, formatFileSize: formatFileSize, formatMarkdown: formatMarkdown, @@ -230,6 +213,7 @@ App.Util = function(_, jQuery, marked, promise) { isExitConfirmationEnabled: isExitConfirmationEnabled, transparentPixel: transparentPixel, loadImagesNicely: loadImagesNicely, + appendComplexRouteParam: appendComplexRouteParam, }; }; diff --git a/public_html/templates/global-comment-list-item.tpl b/public_html/templates/global-comment-list-item.tpl index 55f9baac..2b3f27bf 100644 --- a/public_html/templates/global-comment-list-item.tpl +++ b/public_html/templates/global-comment-list-item.tpl @@ -1,6 +1,6 @@
    - <%= postTemplate({post: post}) %> + <%= postTemplate({post: post, util: util}) %>
    diff --git a/public_html/templates/post-list-item.tpl b/public_html/templates/post-list-item.tpl index 26be73ae..a430d22c 100644 --- a/public_html/templates/post-list-item.tpl +++ b/public_html/templates/post-list-item.tpl @@ -1,10 +1,6 @@
    - href="#/post/<%= post.id %>/query=<%= searchArgs.query %>;order=<%= searchArgs.order %>;page=<%= searchArgs.page %>" - <% } else { %> - href="#/post/<%= post.id %>" - <% } %> + href="<%= util.appendComplexRouteParam('#/post/' + post.id, typeof(query) !== 'undefined' ? query : {}) %>" title="<%= _.map(post.tags, function(tag) { return '#' + tag.name; }).join(', ') %>"> <%= post.idMarkdown %> diff --git a/public_html/templates/post.tpl b/public_html/templates/post.tpl index 5b5737d7..bc4be7b3 100644 --- a/public_html/templates/post.tpl +++ b/public_html/templates/post.tpl @@ -10,8 +10,8 @@