'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;