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