Extracted pager from paged collection presenter
This commit is contained in:
parent
c124f89b8b
commit
14325b4338
6 changed files with 189 additions and 98 deletions
1
TODO
1
TODO
|
@ -26,7 +26,6 @@ everything related to posts:
|
||||||
|
|
||||||
- single post view
|
- single post view
|
||||||
- previous and next post (difficult)
|
- previous and next post (difficult)
|
||||||
- extract Pager from PagedCollectionPresenter
|
|
||||||
- rename PagedCollectionPresenter to PagerPresenter
|
- rename PagedCollectionPresenter to PagerPresenter
|
||||||
- remember last search
|
- remember last search
|
||||||
- take care of pages
|
- take care of pages
|
||||||
|
|
|
@ -72,6 +72,7 @@
|
||||||
<script type="text/javascript" src="/js/Auth.js"></script>
|
<script type="text/javascript" src="/js/Auth.js"></script>
|
||||||
<script type="text/javascript" src="/js/Util.js"></script>
|
<script type="text/javascript" src="/js/Util.js"></script>
|
||||||
<script type="text/javascript" src="/js/Keyboard.js"></script>
|
<script type="text/javascript" src="/js/Keyboard.js"></script>
|
||||||
|
<script type="text/javascript" src="/js/Pager.js"></script>
|
||||||
<script type="text/javascript" src="/js/BrowsingSettings.js"></script>
|
<script type="text/javascript" src="/js/BrowsingSettings.js"></script>
|
||||||
<script type="text/javascript" src="/js/Controls/FileDropper.js"></script>
|
<script type="text/javascript" src="/js/Controls/FileDropper.js"></script>
|
||||||
<script type="text/javascript" src="/js/Controls/TagInput.js"></script>
|
<script type="text/javascript" src="/js/Controls/TagInput.js"></script>
|
||||||
|
|
109
public_html/js/Pager.js
Normal file
109
public_html/js/Pager.js
Normal file
|
@ -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);
|
|
@ -9,6 +9,7 @@ App.Presenters.PagedCollectionPresenter = function(
|
||||||
api,
|
api,
|
||||||
keyboard,
|
keyboard,
|
||||||
router,
|
router,
|
||||||
|
pager,
|
||||||
presenterManager,
|
presenterManager,
|
||||||
browsingSettings) {
|
browsingSettings) {
|
||||||
|
|
||||||
|
@ -18,24 +19,22 @@ App.Presenters.PagedCollectionPresenter = function(
|
||||||
var endlessScroll = browsingSettings.getSettings().endlessScroll;
|
var endlessScroll = browsingSettings.getSettings().endlessScroll;
|
||||||
var scrollInterval;
|
var scrollInterval;
|
||||||
var template;
|
var template;
|
||||||
var totalPages;
|
|
||||||
var forceClear = false;
|
var forceClear = false;
|
||||||
|
|
||||||
var pageNumber;
|
|
||||||
var searchParams;
|
|
||||||
var baseUri;
|
var baseUri;
|
||||||
var backendUri;
|
|
||||||
var updateCallback;
|
var updateCallback;
|
||||||
var failCallback;
|
var failCallback;
|
||||||
|
|
||||||
function init(args, loaded) {
|
function init(args, loaded) {
|
||||||
|
baseUri = args.baseUri;
|
||||||
|
updateCallback = args.updateCallback;
|
||||||
|
failCallback = args.failCallback;
|
||||||
|
|
||||||
$target = args.$target;
|
$target = args.$target;
|
||||||
targetContent = jQuery(args.$target).html();
|
targetContent = jQuery(args.$target).html();
|
||||||
|
|
||||||
baseUri = args.baseUri;
|
pager.init({url: args.backendUri});
|
||||||
backendUri = args.backendUri;
|
pager.setSearchParams(args.searchParams);
|
||||||
updateCallback = args.updateCallback;
|
|
||||||
failCallback = args.failCallback;
|
|
||||||
|
|
||||||
promise.wait(util.promiseTemplate('pager'))
|
promise.wait(util.promiseTemplate('pager'))
|
||||||
.then(function(html) {
|
.then(function(html) {
|
||||||
|
@ -46,12 +45,12 @@ App.Presenters.PagedCollectionPresenter = function(
|
||||||
}
|
}
|
||||||
|
|
||||||
function reinit(args, loaded) {
|
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;
|
pager.setSearchParams(args.searchParams);
|
||||||
pageNumber = parseInt(args.page) || 1;
|
pager.setPage(args.page || 1);
|
||||||
|
|
||||||
softChangePage(pageNumber)
|
retrieve()
|
||||||
.then(loaded)
|
.then(loaded)
|
||||||
.fail(loaded);
|
.fail(loaded);
|
||||||
|
|
||||||
|
@ -62,29 +61,46 @@ App.Presenters.PagedCollectionPresenter = function(
|
||||||
}
|
}
|
||||||
|
|
||||||
function prevPage() {
|
function prevPage() {
|
||||||
if (pageNumber > 1) {
|
pager.prevPage();
|
||||||
changePage(pageNumber - 1);
|
syncUrl();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function nextPage() {
|
function nextPage() {
|
||||||
if (pageNumber < totalPages) {
|
pager.nextPage();
|
||||||
changePage(pageNumber + 1);
|
syncUrl();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function nextPageInplace() {
|
function nextPageInplace() {
|
||||||
if (pageNumber < totalPages) {
|
pager.nextPage();
|
||||||
changePageInplace(pageNumber + 1);
|
syncUrlInplace();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function changePageInplace(newPageNumber) {
|
function setPage(newPage) {
|
||||||
router.navigateInplace(getPageChangeLink(newPageNumber));
|
pager.setPage(newPage);
|
||||||
|
syncUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
function changePage(newPageNumber) {
|
function setSearchParams(newSearchParams) {
|
||||||
router.navigate(getPageChangeLink(newPageNumber));
|
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() {
|
function showSpinner() {
|
||||||
|
@ -103,40 +119,34 @@ App.Presenters.PagedCollectionPresenter = function(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function softChangePage(newPageNumber) {
|
function retrieve() {
|
||||||
pageNumber = newPageNumber;
|
|
||||||
|
|
||||||
showSpinner();
|
showSpinner();
|
||||||
|
|
||||||
return promise.make(function(resolve, reject) {
|
return promise.make(function(resolve, reject) {
|
||||||
promise.wait(
|
pager.retrieve()
|
||||||
api.get(backendUri, _.extend({}, searchParams, {page: pageNumber})))
|
|
||||||
.then(function(response) {
|
.then(function(response) {
|
||||||
resolve(response);
|
updateCallback(response, forceClear || !endlessScroll);
|
||||||
var pageSize = response.json.pageSize;
|
|
||||||
var totalRecords = response.json.totalRecords;
|
|
||||||
totalPages = Math.ceil(totalRecords / pageSize);
|
|
||||||
|
|
||||||
updateCallback({
|
|
||||||
entities: response.json.data,
|
|
||||||
totalRecords: totalRecords},
|
|
||||||
forceClear || !endlessScroll);
|
|
||||||
forceClear = false;
|
forceClear = false;
|
||||||
|
|
||||||
refreshPageList();
|
refreshPageList();
|
||||||
hideSpinner();
|
hideSpinner();
|
||||||
attachNextPageLoader();
|
attachNextPageLoader();
|
||||||
|
resolve();
|
||||||
}).fail(function(response) {
|
}).fail(function(response) {
|
||||||
reject(response);
|
|
||||||
if (typeof(failCallback) !== 'undefined') {
|
if (typeof(failCallback) !== 'undefined') {
|
||||||
failCallback(response);
|
failCallback(response);
|
||||||
} else {
|
} else {
|
||||||
console.log(new Error(response.json && response.json.error || response));
|
console.log(new Error(response.json && response.json.error || response));
|
||||||
}
|
}
|
||||||
|
reject();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clearContent() {
|
||||||
|
updateCallback({entities: [], totalRecords: 0}, true);
|
||||||
|
}
|
||||||
|
|
||||||
function attachNextPageLoader() {
|
function attachNextPageLoader() {
|
||||||
if (!endlessScroll) {
|
if (!endlessScroll) {
|
||||||
return;
|
return;
|
||||||
|
@ -154,10 +164,7 @@ App.Presenters.PagedCollectionPresenter = function(
|
||||||
}
|
}
|
||||||
|
|
||||||
function refreshPageList() {
|
function refreshPageList() {
|
||||||
if (typeof(totalPages) === 'undefined') {
|
var pages = pager.getVisiblePages();
|
||||||
return;
|
|
||||||
}
|
|
||||||
var pages = getVisiblePages();
|
|
||||||
$pageList.empty();
|
$pageList.empty();
|
||||||
var lastPage = 0;
|
var lastPage = 0;
|
||||||
_.each(pages, function(page) {
|
_.each(pages, function(page) {
|
||||||
|
@ -167,10 +174,13 @@ App.Presenters.PagedCollectionPresenter = function(
|
||||||
lastPage = page;
|
lastPage = page;
|
||||||
|
|
||||||
var $a = jQuery('<a/>');
|
var $a = jQuery('<a/>');
|
||||||
|
$a.click(function() {
|
||||||
|
setPage(page);
|
||||||
|
});
|
||||||
$a.addClass('big-button');
|
$a.addClass('big-button');
|
||||||
$a.attr('href', getPageChangeLink(page));
|
$a.attr('href', '#');
|
||||||
$a.text(page);
|
$a.text(page);
|
||||||
if (page === pageNumber) {
|
if (page === pager.getPage()) {
|
||||||
$a.addClass('active');
|
$a.addClass('active');
|
||||||
}
|
}
|
||||||
var $li = jQuery('<li/>');
|
var $li = jQuery('<li/>');
|
||||||
|
@ -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 {
|
return {
|
||||||
init: init,
|
init: init,
|
||||||
reinit: reinit,
|
reinit: reinit,
|
||||||
changePage: changePage,
|
setPage: setPage,
|
||||||
getSearchChangeLink: getSearchChangeLink,
|
setSearchParams: setSearchParams,
|
||||||
getPageChangeLink: getPageChangeLink
|
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
@ -7,7 +7,6 @@ App.Presenters.UserListPresenter = function(
|
||||||
util,
|
util,
|
||||||
promise,
|
promise,
|
||||||
auth,
|
auth,
|
||||||
router,
|
|
||||||
pagedCollectionPresenter,
|
pagedCollectionPresenter,
|
||||||
topNavigationPresenter,
|
topNavigationPresenter,
|
||||||
messagePresenter) {
|
messagePresenter) {
|
||||||
|
@ -56,7 +55,10 @@ App.Presenters.UserListPresenter = function(
|
||||||
searchArgs.order = searchArgs.order || 'name,asc';
|
searchArgs.order = searchArgs.order || 'name,asc';
|
||||||
updateActiveOrder(searchArgs.order);
|
updateActiveOrder(searchArgs.order);
|
||||||
|
|
||||||
pagedCollectionPresenter.reinit({page: searchArgs.page, searchParams: {order: searchArgs.order}});
|
pagedCollectionPresenter.reinit({
|
||||||
|
page: searchArgs.page,
|
||||||
|
searchParams: {
|
||||||
|
order: searchArgs.order}});
|
||||||
}
|
}
|
||||||
|
|
||||||
function render() {
|
function render() {
|
||||||
|
@ -91,7 +93,7 @@ App.Presenters.UserListPresenter = function(
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var $orderLink = jQuery(this);
|
var $orderLink = jQuery(this);
|
||||||
var activeSearchOrder = $orderLink.attr('data-order');
|
var activeSearchOrder = $orderLink.attr('data-order');
|
||||||
router.navigate(pagedCollectionPresenter.getSearchChangeLink({order: activeSearchOrder}));
|
pagedCollectionPresenter.setSearchParams({order: activeSearchOrder});
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
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);
|
||||||
|
|
|
@ -42,10 +42,9 @@ App.Util = function(_, jQuery, promise) {
|
||||||
function compileComplexRouteArgs(baseUri, args) {
|
function compileComplexRouteArgs(baseUri, args) {
|
||||||
var result = baseUri + '/';
|
var result = baseUri + '/';
|
||||||
_.each(args, function(v, k) {
|
_.each(args, function(v, k) {
|
||||||
if (typeof(v) === 'undefined') {
|
if (typeof(v) !== 'undefined') {
|
||||||
return;
|
|
||||||
}
|
|
||||||
result += k + '=' + v + ';';
|
result += k + '=' + v + ';';
|
||||||
|
}
|
||||||
});
|
});
|
||||||
result = result.slice(0, -1);
|
result = result.slice(0, -1);
|
||||||
return result;
|
return result;
|
||||||
|
|
Loading…
Reference in a new issue