szurubooru/client/js/views/manual_page_view.js
2020-06-04 19:02:33 -04:00

165 lines
4.9 KiB
JavaScript

'use strict';
const router = require('../router.js');
const keyboard = require('../util/keyboard.js');
const views = require('../util/views.js');
const holderTemplate = views.getTemplate('manual-pager');
const navTemplate = views.getTemplate('manual-pager-nav');
function _removeConsecutiveDuplicates(a) {
return a.filter((item, pos, ary) => {
return !pos || item !== ary[pos - 1];
});
}
function _getVisiblePageNumbers(currentPage, totalPages) {
const threshold = 2;
let pagesVisible = [];
for (let i = 1; i <= threshold; i++) {
pagesVisible.push(i);
}
for (let i = totalPages - threshold; i <= totalPages; i++) {
pagesVisible.push(i);
}
for (let i = currentPage - threshold;
i <= currentPage + threshold;
i++) {
pagesVisible.push(i);
}
pagesVisible = pagesVisible.filter((item, pos, ary) => {
return item >= 1 && item <= totalPages;
});
pagesVisible = pagesVisible.sort((a, b) => {
return a - b;
});
pagesVisible = _removeConsecutiveDuplicates(pagesVisible);
return pagesVisible;
}
function _getPages(
currentPage, pageNumbers, limit, defaultLimit, removedItems) {
const pages = new Map();
let prevPage = 0;
for (let page of pageNumbers) {
if (page !== prevPage + 1) {
pages.set(page - 1, {ellipsis: true});
}
pages.set(page, {
number: page,
offset:
((page - 1) * limit) -
(page > currentPage ? removedItems : 0),
limit: limit === defaultLimit ? null : limit,
active: currentPage === page,
});
prevPage = page;
}
return pages;
}
class ManualPageView {
constructor(ctx) {
this._hostNode = document.getElementById('content-holder');
views.replaceContent(this._hostNode, holderTemplate());
}
run(ctx) {
const offset = parseInt(ctx.parameters.offset || 0);
const limit = parseInt(ctx.parameters.limit || ctx.defaultLimit);
this.clearMessages();
views.emptyContent(this._pageNavNode);
ctx.requestPage(offset, limit).then(response => {
ctx.pageRenderer({
parameters: ctx.parameters,
response: response,
hostNode: this._pageContentHolderNode,
});
keyboard.bind(['a', 'left'], () => {
this._navigateToPrevNextPage('prev');
});
keyboard.bind(['d', 'right'], () => {
this._navigateToPrevNextPage('next');
});
let removedItems = 0;
if (response.total) {
this._refreshNav(
offset, limit, response.total, removedItems, ctx);
}
if (!response.results.length) {
this.showInfo('No data to show');
}
response.results.addEventListener('remove', e => {
removedItems++;
this._refreshNav(
offset, limit, response.total, removedItems, ctx);
});
views.syncScrollPosition();
}, response => {
this.showError(response.message);
});
}
get pageHeaderHolderNode() {
return this._hostNode.querySelector('.page-header-holder');
}
get _pageContentHolderNode() {
return this._hostNode.querySelector('.page-content-holder');
}
get _pageNavNode() {
return this._hostNode.querySelector('.page-nav');
}
clearMessages() {
views.clearMessages(this._hostNode);
}
showSuccess(message) {
views.showSuccess(this._hostNode, message);
}
showError(message) {
views.showError(this._hostNode, message);
}
showInfo(message) {
views.showInfo(this._hostNode, message);
}
_navigateToPrevNextPage(className) {
const linkNode = this._hostNode.querySelector('a.' + className);
if (linkNode.classList.contains('disabled')) {
return;
}
router.show(linkNode.getAttribute('href'));
}
_refreshNav(offset, limit, total, removedItems, ctx) {
const currentPage = Math.floor((offset + limit - 1) / limit) + 1;
const totalPages = Math.ceil((total - removedItems) / limit);
const pageNumbers = _getVisiblePageNumbers(currentPage, totalPages);
const pages = _getPages(
currentPage, pageNumbers, limit, ctx.defaultLimit, removedItems);
views.replaceContent(
this._pageNavNode,
navTemplate({
getClientUrlForPage: ctx.getClientUrlForPage,
prevPage: Math.min(totalPages, Math.max(1, currentPage - 1)),
nextPage: Math.min(totalPages, Math.max(1, currentPage + 1)),
currentPage: currentPage,
totalPages: totalPages,
pages: pages,
}));
}
}
module.exports = ManualPageView;