UNPKG

mp-common

Version:

This is XPO MarketPlace common libary

167 lines (141 loc) 5.4 kB
import { ChangeDetectorRef, Directive, EventEmitter, Input, Output } from '@angular/core'; import { Subscription } from 'rxjs/Subscription'; import { PaginationService } from './pagination.service'; import { PaginationInstance } from './pagination-instance'; export interface Page { label: string; value: any; } @Directive({ selector: 'pagination-template,[pagination-template]', exportAs: 'paginationApi' }) export class PaginationControlsDirective { @Input() id: string; @Input() maxSize: number = 7; @Output() pageChange: EventEmitter<number> = new EventEmitter<number>(); pages: Page[] = []; private changeSub: Subscription; constructor(private service: PaginationService, private changeDetectorRef: ChangeDetectorRef) { this.changeSub = this.service.change .subscribe(id => { if (this.id === id) { this.updatePageLinks(); this.changeDetectorRef.markForCheck(); this.changeDetectorRef.detectChanges(); } }); } ngOnInit() { if (this.id === undefined) { this.id = this.service.defaultId(); } this.updatePageLinks(); } ngOnChanges(changes: any) { this.updatePageLinks(); } ngOnDestroy() { this.changeSub.unsubscribe(); } previous() { this.checkValidId(); this.setCurrent(this.getCurrent() - 1); } next() { this.checkValidId(); this.setCurrent(this.getCurrent() + 1); } isFirstPage(): boolean { return this.getCurrent() === 1; } isLastPage(): boolean { return this.getLastPage() === this.getCurrent(); } setCurrent(page: number) { this.pageChange.emit(page); } getCurrent(): number { return this.service.getCurrentPage(this.id); } getLastPage(): number { let inst = this.service.getInstance(this.id); if (inst.totalItems < 1) { return 1; } return Math.ceil(inst.totalItems / inst.itemsPerPage); } private checkValidId() { if (!this.service.getInstance(this.id).id) { console.warn(`PaginationControlsDirective: the specified id "${this.id}" does not match any registered PaginationInstance`); } } private updatePageLinks() { let inst = this.service.getInstance(this.id); const correctedCurrentPage = this.outOfBoundCorrection(inst); if (correctedCurrentPage !== inst.currentPage) { setTimeout(() => { this.setCurrent(correctedCurrentPage); this.pages = this.createPageArray(inst.currentPage, inst.itemsPerPage, inst.totalItems, this.maxSize); }); } else { this.pages = this.createPageArray(inst.currentPage, inst.itemsPerPage, inst.totalItems, this.maxSize); } } private outOfBoundCorrection(instance: PaginationInstance): number { const totalPages = Math.ceil(instance.totalItems / instance.itemsPerPage); if (totalPages < instance.currentPage && 0 < totalPages) { return totalPages; } else if (instance.currentPage < 1) { return 1; } return instance.currentPage; } private createPageArray(currentPage: number, itemsPerPage: number, totalItems: number, paginationRange: number): Page[] { paginationRange = +paginationRange; let pages = []; const totalPages = Math.ceil(totalItems / itemsPerPage); const halfWay = Math.ceil(paginationRange / 2); const isStart = currentPage <= halfWay; const isEnd = totalPages - halfWay < currentPage; const isMiddle = !isStart && !isEnd; let ellipsesNeeded = paginationRange < totalPages; let i = 1; while (i <= totalPages && i <= paginationRange) { let label; let pageNumber = this.calculatePageNumber(i, currentPage, paginationRange, totalPages); let openingEllipsesNeeded = (i === 2 && (isMiddle || isEnd)); let closingEllipsesNeeded = (i === paginationRange - 1 && (isMiddle || isStart)); if (ellipsesNeeded && (openingEllipsesNeeded || closingEllipsesNeeded)) { label = '...'; } else { label = pageNumber; } pages.push({ label: label, value: pageNumber }); i++; } return pages; } private calculatePageNumber(i: number, currentPage: number, paginationRange: number, totalPages: number) { let halfWay = Math.ceil(paginationRange / 2); if (i === paginationRange) { return totalPages; } else if (i === 1) { return i; } else if (paginationRange < totalPages) { if (totalPages - halfWay < currentPage) { return totalPages - paginationRange + i; } else if (halfWay < currentPage) { return currentPage - halfWay + i; } else { return i; } } else { return i; } } }