ultimate-pagination
Version:
Universal pagination model generation algorithm that can be used to build a UI component
129 lines (104 loc) • 5.41 kB
text/typescript
import {createRange} from './ultimate-pagination-utils';
import {
createPageFunctionFactory,
createFirstEllipsis,
createSecondEllipsis,
createFirstPageLink,
createPreviousPageLink,
createNextPageLink,
createLastPageLink,
PaginationModelItem
} from './ultimate-pagination-item-factories';
export interface PaginationModelOptions {
currentPage: number;
totalPages: number;
boundaryPagesRange?: number;
siblingPagesRange?: number;
hideEllipsis?: boolean;
hidePreviousAndNextPageLinks?: boolean;
hideFirstAndLastPageLinks?: boolean;
}
export {PaginationModelItem};
export type PaginationModel = PaginationModelItem[];
export function getPaginationModel(options: PaginationModelOptions): PaginationModel {
if (options == null) { throw new Error('getPaginationModel(): options object should be a passed'); }
const totalPages = Number(options.totalPages);
if (isNaN(totalPages)) { throw new Error('getPaginationModel(): totalPages should be a number'); }
if (totalPages < 0) { throw new Error('getPaginationModel(): totalPages shouldn\'t be a negative number'); }
const currentPage = Number(options.currentPage);
if (isNaN(currentPage)) { throw new Error('getPaginationModel(): currentPage should be a number'); }
if (currentPage < 0) { throw new Error('getPaginationModel(): currentPage shouldn\'t be a negative number'); }
if (currentPage > totalPages) { throw new Error('getPaginationModel(): currentPage shouldn\'t be greater than totalPages'); }
const boundaryPagesRange = (options.boundaryPagesRange == null ? 1 : Number(options.boundaryPagesRange));
if (isNaN(boundaryPagesRange)) { throw new Error('getPaginationModel(): boundaryPagesRange should be a number'); }
if (boundaryPagesRange < 0) { throw new Error('getPaginationModel(): boundaryPagesRange shouldn\'t be a negative number'); }
const siblingPagesRange = (options.siblingPagesRange == null ? 1 : Number(options.siblingPagesRange));
if (isNaN(siblingPagesRange)) { throw new Error('getPaginationModel(): siblingPagesRange should be a number'); }
if (siblingPagesRange < 0) { throw new Error('getPaginationModel(): siblingPagesRange shouldn\'t be a negative number'); }
const hidePreviousAndNextPageLinks = Boolean(options.hidePreviousAndNextPageLinks);
const hideFirstAndLastPageLinks = Boolean(options.hideFirstAndLastPageLinks);
const hideEllipsis = Boolean(options.hideEllipsis);
const ellipsisSize = (hideEllipsis ? 0 : 1);
const paginationModel: PaginationModelItem[] = [];
const createPage = createPageFunctionFactory(options);
if (!hideFirstAndLastPageLinks) {
paginationModel.push(createFirstPageLink(options));
}
if (!hidePreviousAndNextPageLinks) {
paginationModel.push(createPreviousPageLink(options));
}
// Simplify generation of pages if number of available items is equal or greater than total pages to show
if (1 + 2 * ellipsisSize + 2 * siblingPagesRange + 2 * boundaryPagesRange >= totalPages) {
const allPages = createRange(1, totalPages).map(createPage);
paginationModel.push(...allPages);
} else {
// Calculate group of first pages
const firstPagesStart = 1;
const firstPagesEnd = boundaryPagesRange;
const firstPages = createRange(firstPagesStart, firstPagesEnd).map(createPage);
// Calculate group of last pages
const lastPagesStart = totalPages + 1 - boundaryPagesRange;
const lastPagesEnd = totalPages;
const lastPages = createRange(lastPagesStart, lastPagesEnd).map(createPage);
// Calculate group of main pages
const mainPagesStart = Math.min(
Math.max(
currentPage - siblingPagesRange,
firstPagesEnd + ellipsisSize + 1
),
lastPagesStart - ellipsisSize - 2 * siblingPagesRange - 1
);
const mainPagesEnd = mainPagesStart + 2 * siblingPagesRange;
const mainPages = createRange(mainPagesStart, mainPagesEnd).map(createPage);
// Add group of first pages
paginationModel.push(...firstPages);
if (!hideEllipsis) {
// Calculate and add ellipsis before group of main pages
const firstEllipsisPageNumber = mainPagesStart - 1;
const showPageInsteadOfFirstEllipsis = (firstEllipsisPageNumber === firstPagesEnd + 1);
const createFirstEllipsisOrPage = showPageInsteadOfFirstEllipsis ? createPage : createFirstEllipsis;
const firstEllipsis = createFirstEllipsisOrPage(firstEllipsisPageNumber);
paginationModel.push(firstEllipsis);
}
// Add group of main pages
paginationModel.push(...mainPages);
if (!hideEllipsis) {
// Calculate and add ellipsis after group of main pages
const secondEllipsisPageNumber = mainPagesEnd + 1;
const showPageInsteadOfSecondEllipsis = (secondEllipsisPageNumber === lastPagesStart - 1);
const createSecondEllipsisOrPage = showPageInsteadOfSecondEllipsis ? createPage : createSecondEllipsis;
const secondEllipsis = createSecondEllipsisOrPage(secondEllipsisPageNumber);
paginationModel.push(secondEllipsis);
}
// Add group of last pages
paginationModel.push(...lastPages);
}
if (!hidePreviousAndNextPageLinks) {
paginationModel.push(createNextPageLink(options));
}
if (!hideFirstAndLastPageLinks) {
paginationModel.push(createLastPageLink(options));
}
return paginationModel;
}
export {ITEM_TYPES, ITEM_KEYS, PaginationItemType} from './ultimate-pagination-constants';