import { UiElement } from '../ui/UiElement.js';
import "./Pagination.css";
export { Pagination }
/**
* A class creating a pagination with page *changed* events.
*
* Events:
* * changed
*
* @author rkoppe <roland.koppe@awi.de>
* @memberof vef.search
*/
class Pagination extends UiElement {
options = {
responsive: true,
maxPages: 10 // in responsive mode the page count is ignored
};
// used for accurately calculating sizes for responsive mode
widthMapping = [34, 40, 46, 52];
/**
* Initializes the pagination for the element defined by id and
* options.
*
* @param {string | HTMLElement} target
* @param {object} options
*/
constructor(target, options) {
super(target, { 'changed': [] });
this.setClass('vef-pagination');
this.options = Object.assign(this.options, options);
}
getWidth_(text) {
const index = text.toString().length - 1;
if (index < this.widthMapping.length) {
return this.widthMapping[index];
}
return this.widthMapping[this.widthMapping.length];
}
addButton_(text, page, currentPage) {
const element = this.getElement();
const a = document.createElement("a");
const width = this.getWidth_(text);
a.style.width = width + "px";
a.innerText = text;
a.href = "#";
if (page == currentPage) {
a.classList.add('active');
} else {
a.addEventListener("click", e => {
e.preventDefault();
this.fire('changed', page);
});
}
element.appendChild(a);
return width;
}
/**
* @private
*/
show_(page, pages, start, end) {
this.setHtml('');
this.addButton_('«', 1, page);
for (let i = start; i <= end; ++i) {
this.addButton_(i, i, page);
}
this.addButton_('»', pages, page);
}
/**
* @private
*/
responsiveShow_(page, pages) {
const parentWidth = this.getElement().offsetWidth;
// init with previous/next buttons and initial page
const currentPageWidth = this.getWidth_(page);
let width = 2 * this.widthMapping[0] + currentPageWidth;
// simulate max size to dynamically adjust start position with an estimation size based on the current page
let maxButtonCount = 0;
let maxWidth = width;
while (maxWidth < parentWidth) {
if ((maxWidth + currentPageWidth) < parentWidth) {
maxWidth += currentPageWidth;
++maxButtonCount;
} else {
break;
}
}
const offset = Math.ceil(maxButtonCount * 0.5);
let start = Math.max(1, page - offset);
if ((page + offset) > pages) start = Math.max(1, page - maxButtonCount);
let end = start;
// calculate actual width
let currentPage = start;
while (width < parentWidth) {
const itemWidth = this.getWidth_(++currentPage);
if (((width + itemWidth) < parentWidth) && (currentPage <= pages)) {
width += itemWidth;
++end;
} else {
break;
}
}
this.show_(page, pages, start, end);
}
/**
* Generates a new pagination for current page and number of pages.
*
* @param {number} page
* @param {number} pages
*/
show(page, pages) {
if (this.options.responsive) {
this.responsiveShow_(page, pages);
} else {
let start = Math.max(1, page - Math.floor(this.options.maxPages / 2));
let end = Math.min(start + this.options.maxPages - 1, pages);
this.show_(page, pages, start, end);
}
}
dispose() {
super.dispose();
}
}