awesome-data-view
Version:
202 lines (167 loc) • 6.46 kB
text/typescript
import Pipelined from "../interface/Pipelined";
import PopupButton from "../helpers/PopupButton";
import SetStyle from "../helpers/SetStyle";
import PaleColor from "../helpers/PaleColor";
import hexToRGBA from "../helpers/hexToRGB";
export default class Paginate implements Pipelined {
protected _currentPageIndex: number = 1;
protected _pageSize: number = 10;
protected _totalItems: number = 0;
protected _buttonsLimit: number = 5;
protected _onChange: null | Function = null;
protected buttonsDiv: HTMLDivElement;
protected buttonStyle: {
[key: string]: any;
};
render(
totalItems: number,
buttonStyle = {
background: "transparent",
color: "#000",
border: "1px solid #323232",
}
) {
this._totalItems = totalItems;
this.buttonStyle = buttonStyle;
this.buttonsDiv = document.createElement("div");
let styles = {
display: "flex",
columnGap: "10px",
alignItems: "center",
};
SetStyle(this.buttonsDiv, styles);
this.buildButtons();
return this.buttonsDiv;
}
protected buildButton(onClick: Function) {
let button = document.createElement("button");
button.style.padding = "6px";
button.style.borderRadius = "4px";
button.addEventListener("click", (e) => onClick(e));
SetStyle(button, this.buttonStyle);
return button;
}
protected change() {
this.buildButtons();
if (this._onChange) this._onChange(this._currentPageIndex);
}
protected buildNumberOfItemsIndicator() {
let { button, toggleVisibility, placeholder, div } = PopupButton(
this.buttonStyle,
{
border: this.buttonStyle.border,
background: PaleColor(
hexToRGBA(this.buttonStyle.background, 1),
0.1
),
}
);
placeholder.innerHTML = `${this._pageSize} per page`;
let itemsPerPage = [5, 10, 20, 30, 40, 50, 100];
itemsPerPage.forEach((option, i) => {
let btn = document.createElement("button");
btn.innerText = option.toString();
btn.className = "px-8 py-3 hover:opacity-80";
btn.addEventListener("click", (e) => {
e.stopPropagation();
e.preventDefault();
toggleVisibility();
this._pageSize = option;
this._currentPageIndex = 1;
// this._buttonsLimit =
placeholder.innerHTML = `${this._pageSize} per page`;
this.buildButtons();
if (this._onChange) this._onChange(this._currentPageIndex);
});
if (i !== itemsPerPage.length - 1) {
btn.classList.add("border-b");
}
div.appendChild(btn);
});
return button;
}
protected buildButtons() {
if (this._buttonsLimit > this._totalItems / this._pageSize) {
this._buttonsLimit = Math.ceil(this._totalItems / this._pageSize);
}
let previousButton = this.buildButton(() => {
this._currentPageIndex = Math.max(1, this._currentPageIndex - 1);
this.change();
});
previousButton.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-left"><path d="m15 18-6-6 6-6"/></svg>`;
let nextButton = this.buildButton(() => {
this._currentPageIndex = Math.min(
Math.ceil(this._totalItems / this._pageSize),
this._currentPageIndex + 1
);
this.change();
});
nextButton.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-right"><path d="m9 18 6-6-6-6"/></svg>`;
this.buttonsDiv.innerHTML = "";
// Build number of items per page
this.buttonsDiv.appendChild(this.buildNumberOfItemsIndicator());
this.buttonsDiv.appendChild(previousButton);
// Build page indexes
let start = Math.max(1, this._currentPageIndex - 2); // Adjust to show 2 previous pages
const end = Math.min(
Math.ceil(this._totalItems / this._pageSize),
start + this._buttonsLimit - 1
); // Limit to totalItems
if (end - start < this._buttonsLimit) {
start = end - this._buttonsLimit + 1;
}
for (let i = start; i <= end; i++) {
let btn = this.buildButton(() => {
this._currentPageIndex = i;
btn.style.background = PaleColor(
hexToRGBA(this.buttonStyle.background, 1),
0.05
);
this.change();
});
btn.innerText = i.toString();
btn.style.paddingLeft = "16px";
btn.style.paddingRight = "16px";
if (i === this._currentPageIndex) {
btn.style.background = PaleColor(
hexToRGBA(this.buttonStyle.background, 1),
0.05
);
}
this.buttonsDiv.appendChild(btn);
}
this.buttonsDiv.appendChild(nextButton);
}
totalItems(size: number) {
this._totalItems = size;
return this;
}
pageSize(size: number) {
this._pageSize = size;
return this;
}
buttonsLimit(size: number) {
this._buttonsLimit = size;
return this;
}
onChange(fn: Function) {
this._onChange = fn;
return this;
}
update() {
this._currentPageIndex = 1;
this.buildButtons();
return this;
}
handle(data: Array<object> | object): Array<object> | object {
let start = Math.max(0, this._currentPageIndex - 1) * this._pageSize;
let end = Math.min(this._totalItems, start + this._pageSize);
if (data instanceof Array) {
return data.slice(start, end);
}
return data;
}
toQuery() {
return "";
}
}