From 14325b43383d22c17ccbc5ff1ce5cd52b3a2bbaa Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Wed, 1 Oct 2014 22:18:50 +0200 Subject: [PATCH] Extracted pager from paged collection presenter --- TODO | 1 - public_html/index.html | 1 + public_html/js/Pager.js | 109 ++++++++++++ .../js/Presenters/PagedCollectionPresenter.js | 161 ++++++++---------- .../js/Presenters/UserListPresenter.js | 10 +- public_html/js/Util.js | 5 +- 6 files changed, 189 insertions(+), 98 deletions(-) create mode 100644 public_html/js/Pager.js diff --git a/TODO b/TODO index 5b7cb0cb..6a3c6ffa 100644 --- a/TODO +++ b/TODO @@ -26,7 +26,6 @@ everything related to posts: - single post view - previous and next post (difficult) - - extract Pager from PagedCollectionPresenter - rename PagedCollectionPresenter to PagerPresenter - remember last search - take care of pages diff --git a/public_html/index.html b/public_html/index.html index 08da4674..1ed69aec 100644 --- a/public_html/index.html +++ b/public_html/index.html @@ -72,6 +72,7 @@ + diff --git a/public_html/js/Pager.js b/public_html/js/Pager.js new file mode 100644 index 00000000..0a8d0c78 --- /dev/null +++ b/public_html/js/Pager.js @@ -0,0 +1,109 @@ +var App = App || {}; + +App.Pager = function( + _, + promise, + api) { + + var totalPages; + var pageNumber; + var searchParams; + var url; + + function init(args) { + url = args.url; + + setSearchParams(args.searchParams); + if (typeof(args.page) !== 'undefined') { + setPage(args.page); + } else { + setPage(1); + } + } + + function getPage() { + return pageNumber; + } + + function prevPage() { + if (pageNumber > 1) { + setPage(pageNumber - 1); + } + } + + function nextPage() { + if (pageNumber < totalPages) { + setPage(pageNumber + 1); + } + } + + function setPage(newPageNumber) { + pageNumber = parseInt(newPageNumber); + if (!pageNumber || isNaN(pageNumber)) { + throw new Error('Trying to set page to a non-number (' + newPageNumber + ')'); + } + } + + function getSearchParams() { + return searchParams; + } + + function setSearchParams(newSearchParams) { + setPage(1); + searchParams = newSearchParams; + } + + function retrieve() { + return promise.make(function(resolve, reject) { + promise.wait( + api.get(url, _.extend({}, searchParams, {page: pageNumber}))) + .then(function(response) { + var pageSize = response.json.pageSize; + var totalRecords = response.json.totalRecords; + totalPages = Math.ceil(totalRecords / pageSize); + + resolve({ + entities: response.json.data, + totalRecords: totalRecords}); + + }).fail(function(response) { + reject(response); + }); + }); + } + + function getVisiblePages() { + var pages = [1, totalPages || 1]; + var pagesAroundCurrent = 2; + for (var i = -pagesAroundCurrent; i <= pagesAroundCurrent; i ++) { + if (pageNumber + i >= 1 && pageNumber + i <= totalPages) { + pages.push(pageNumber + i); + } + } + if (pageNumber - pagesAroundCurrent - 1 === 2) { + pages.push(2); + } + if (pageNumber + pagesAroundCurrent + 1 === totalPages - 1) { + pages.push(totalPages - 1); + } + + return pages.sort(function(a, b) { return a - b; }).filter(function(item, pos) { + return !pos || item !== pages[pos - 1]; + }); + } + + return { + init: init, + getPage: getPage, + prevPage: prevPage, + nextPage: nextPage, + setPage: setPage, + getSearchParams: getSearchParams, + setSearchParams: setSearchParams, + retrieve: retrieve, + getVisiblePages: getVisiblePages, + }; + +}; + +App.DI.register('pager', ['_', 'promise', 'api'], App.Pager); diff --git a/public_html/js/Presenters/PagedCollectionPresenter.js b/public_html/js/Presenters/PagedCollectionPresenter.js index a63debd8..809ba07b 100644 --- a/public_html/js/Presenters/PagedCollectionPresenter.js +++ b/public_html/js/Presenters/PagedCollectionPresenter.js @@ -9,6 +9,7 @@ App.Presenters.PagedCollectionPresenter = function( api, keyboard, router, + pager, presenterManager, browsingSettings) { @@ -18,24 +19,22 @@ App.Presenters.PagedCollectionPresenter = function( var endlessScroll = browsingSettings.getSettings().endlessScroll; var scrollInterval; var template; - var totalPages; var forceClear = false; - var pageNumber; - var searchParams; var baseUri; - var backendUri; var updateCallback; var failCallback; function init(args, loaded) { + baseUri = args.baseUri; + updateCallback = args.updateCallback; + failCallback = args.failCallback; + $target = args.$target; targetContent = jQuery(args.$target).html(); - baseUri = args.baseUri; - backendUri = args.backendUri; - updateCallback = args.updateCallback; - failCallback = args.failCallback; + pager.init({url: args.backendUri}); + pager.setSearchParams(args.searchParams); promise.wait(util.promiseTemplate('pager')) .then(function(html) { @@ -46,12 +45,12 @@ App.Presenters.PagedCollectionPresenter = function( } function reinit(args, loaded) { - forceClear = !_.isEqual(args.searchParams, searchParams) || parseInt(args.page) !== pageNumber + 1; + forceClear = !_.isEqual(args.searchParams, pager.getSearchParams()) || parseInt(args.page) !== pager.getPage(); - searchParams = args.searchParams; - pageNumber = parseInt(args.page) || 1; + pager.setSearchParams(args.searchParams); + pager.setPage(args.page || 1); - softChangePage(pageNumber) + retrieve() .then(loaded) .fail(loaded); @@ -62,29 +61,46 @@ App.Presenters.PagedCollectionPresenter = function( } function prevPage() { - if (pageNumber > 1) { - changePage(pageNumber - 1); - } + pager.prevPage(); + syncUrl(); } function nextPage() { - if (pageNumber < totalPages) { - changePage(pageNumber + 1); - } + pager.nextPage(); + syncUrl(); } function nextPageInplace() { - if (pageNumber < totalPages) { - changePageInplace(pageNumber + 1); - } + pager.nextPage(); + syncUrlInplace(); } - function changePageInplace(newPageNumber) { - router.navigateInplace(getPageChangeLink(newPageNumber)); + function setPage(newPage) { + pager.setPage(newPage); + syncUrl(); } - function changePage(newPageNumber) { - router.navigate(getPageChangeLink(newPageNumber)); + function setSearchParams(newSearchParams) { + clearContent(); + pager.setSearchParams(newSearchParams); + syncUrl(); + } + + function getUrl() { + return util.compileComplexRouteArgs( + baseUri, + _.extend( + {}, + pager.getSearchParams(), + {page: pager.getPage()})); + } + + function syncUrl() { + router.navigate(getUrl()); + } + + function syncUrlInplace() { + router.navigateInplace(getUrl()); } function showSpinner() { @@ -103,40 +119,34 @@ App.Presenters.PagedCollectionPresenter = function( } } - function softChangePage(newPageNumber) { - pageNumber = newPageNumber; - + function retrieve() { showSpinner(); return promise.make(function(resolve, reject) { - promise.wait( - api.get(backendUri, _.extend({}, searchParams, {page: pageNumber}))) - .then(function(response) { - resolve(response); - var pageSize = response.json.pageSize; - var totalRecords = response.json.totalRecords; - totalPages = Math.ceil(totalRecords / pageSize); + pager.retrieve() + .then(function(response) { + updateCallback(response, forceClear || !endlessScroll); + forceClear = false; - updateCallback({ - entities: response.json.data, - totalRecords: totalRecords}, - forceClear || !endlessScroll); - forceClear = false; - - refreshPageList(); - hideSpinner(); - attachNextPageLoader(); - }).fail(function(response) { - reject(response); - if (typeof(failCallback) !== 'undefined') { - failCallback(response); - } else { - console.log(new Error(response.json && response.json.error || response)); - } - }); + refreshPageList(); + hideSpinner(); + attachNextPageLoader(); + resolve(); + }).fail(function(response) { + if (typeof(failCallback) !== 'undefined') { + failCallback(response); + } else { + console.log(new Error(response.json && response.json.error || response)); + } + reject(); + }); }); } + function clearContent() { + updateCallback({entities: [], totalRecords: 0}, true); + } + function attachNextPageLoader() { if (!endlessScroll) { return; @@ -154,10 +164,7 @@ App.Presenters.PagedCollectionPresenter = function( } function refreshPageList() { - if (typeof(totalPages) === 'undefined') { - return; - } - var pages = getVisiblePages(); + var pages = pager.getVisiblePages(); $pageList.empty(); var lastPage = 0; _.each(pages, function(page) { @@ -167,10 +174,13 @@ App.Presenters.PagedCollectionPresenter = function( lastPage = page; var $a = jQuery(''); + $a.click(function() { + setPage(page); + }); $a.addClass('big-button'); - $a.attr('href', getPageChangeLink(page)); + $a.attr('href', '#'); $a.text(page); - if (page === pageNumber) { + if (page === pager.getPage()) { $a.addClass('active'); } var $li = jQuery('
  • '); @@ -189,42 +199,13 @@ App.Presenters.PagedCollectionPresenter = function( } } - function getVisiblePages() { - var pages = [1, totalPages || 1]; - var pagesAroundCurrent = 2; - for (var i = -pagesAroundCurrent; i <= pagesAroundCurrent; i ++) { - if (pageNumber + i >= 1 && pageNumber + i <= totalPages) { - pages.push(pageNumber + i); - } - } - if (pageNumber - pagesAroundCurrent - 1 === 2) { - pages.push(2); - } - if (pageNumber + pagesAroundCurrent + 1 === totalPages - 1) { - pages.push(totalPages - 1); - } - - return pages.sort(function(a, b) { return a - b; }).filter(function(item, pos) { - return !pos || item !== pages[pos - 1]; - }); - } - - function getSearchChangeLink(newSearchParams) { - return util.compileComplexRouteArgs(baseUri, _.extend({}, searchParams, newSearchParams, {page: 1})); - } - - function getPageChangeLink(newPageNumber) { - return util.compileComplexRouteArgs(baseUri, _.extend({}, searchParams, {page: newPageNumber})); - } - return { init: init, reinit: reinit, - changePage: changePage, - getSearchChangeLink: getSearchChangeLink, - getPageChangeLink: getPageChangeLink + setPage: setPage, + setSearchParams: setSearchParams, }; }; -App.DI.register('pagedCollectionPresenter', ['_', 'jQuery', 'util', 'promise', 'api', 'keyboard', 'router', 'presenterManager', 'browsingSettings'], App.Presenters.PagedCollectionPresenter); +App.DI.register('pagedCollectionPresenter', ['_', 'jQuery', 'util', 'promise', 'api', 'keyboard', 'router', 'pager', 'presenterManager', 'browsingSettings'], App.Presenters.PagedCollectionPresenter); diff --git a/public_html/js/Presenters/UserListPresenter.js b/public_html/js/Presenters/UserListPresenter.js index 9993d3f6..905930c0 100644 --- a/public_html/js/Presenters/UserListPresenter.js +++ b/public_html/js/Presenters/UserListPresenter.js @@ -7,7 +7,6 @@ App.Presenters.UserListPresenter = function( util, promise, auth, - router, pagedCollectionPresenter, topNavigationPresenter, messagePresenter) { @@ -56,7 +55,10 @@ App.Presenters.UserListPresenter = function( searchArgs.order = searchArgs.order || 'name,asc'; updateActiveOrder(searchArgs.order); - pagedCollectionPresenter.reinit({page: searchArgs.page, searchParams: {order: searchArgs.order}}); + pagedCollectionPresenter.reinit({ + page: searchArgs.page, + searchParams: { + order: searchArgs.order}}); } function render() { @@ -91,7 +93,7 @@ App.Presenters.UserListPresenter = function( e.preventDefault(); var $orderLink = jQuery(this); var activeSearchOrder = $orderLink.attr('data-order'); - router.navigate(pagedCollectionPresenter.getSearchChangeLink({order: activeSearchOrder})); + pagedCollectionPresenter.setSearchParams({order: activeSearchOrder}); } return { @@ -102,4 +104,4 @@ App.Presenters.UserListPresenter = function( }; -App.DI.register('userListPresenter', ['_', 'jQuery', 'util', 'promise', 'auth', 'router', 'pagedCollectionPresenter', 'topNavigationPresenter', 'messagePresenter'], App.Presenters.UserListPresenter); +App.DI.register('userListPresenter', ['_', 'jQuery', 'util', 'promise', 'auth', 'pagedCollectionPresenter', 'topNavigationPresenter', 'messagePresenter'], App.Presenters.UserListPresenter); diff --git a/public_html/js/Util.js b/public_html/js/Util.js index 17753528..8cc02e02 100644 --- a/public_html/js/Util.js +++ b/public_html/js/Util.js @@ -42,10 +42,9 @@ App.Util = function(_, jQuery, promise) { function compileComplexRouteArgs(baseUri, args) { var result = baseUri + '/'; _.each(args, function(v, k) { - if (typeof(v) === 'undefined') { - return; + if (typeof(v) !== 'undefined') { + result += k + '=' + v + ';'; } - result += k + '=' + v + ';'; }); result = result.slice(0, -1); return result;