simple-keyboard/src/lib/components/CandidateBox.ts

130 lines
3.6 KiB
TypeScript
Raw Normal View History

2021-03-16 12:41:42 +08:00
import "./css/CandidateBox.css";
import Utilities from "../services/Utilities";
import {
CandidateBoxParams,
CandidateBoxRenderParams,
CandidateBoxShowParams,
} from "./../interfaces";
class CandidateBox {
utilities: Utilities;
candidateBoxElement: HTMLDivElement;
pageIndex = 0;
pageSize;
constructor({ utilities }: CandidateBoxParams) {
this.utilities = utilities;
Utilities.bindMethods(CandidateBox, this);
this.pageSize = this.utilities.getOptions().layoutCandidatesPageSize || 5;
}
destroy() {
if (this.candidateBoxElement) {
this.candidateBoxElement.remove();
this.pageIndex = 0;
}
}
show({
candidateValue,
targetElement,
onSelect,
}: CandidateBoxShowParams): void {
if (!candidateValue || !candidateValue.length) {
return;
}
const candidateListPages = this.utilities.chunkArray(
candidateValue.split(" "),
this.pageSize
);
this.renderPage({
candidateListPages,
targetElement,
pageIndex: this.pageIndex,
nbPages: candidateListPages.length,
onItemSelected: (selectedCandidate: string) => {
onSelect(selectedCandidate);
this.destroy();
},
});
}
renderPage({
candidateListPages,
targetElement,
pageIndex,
nbPages,
onItemSelected,
}: CandidateBoxRenderParams) {
// Remove current candidate box, if any
this.candidateBoxElement?.remove();
// Create candidate box element
this.candidateBoxElement = document.createElement("div");
this.candidateBoxElement.className = "hg-candidate-box";
// Candidate box list
const candidateListULElement = document.createElement("ul");
candidateListULElement.className = "hg-candidate-box-list";
// Create Candidate box list items
candidateListPages[pageIndex].forEach((candidateListItem) => {
const candidateListLIElement = document.createElement("li");
candidateListLIElement.className = "hg-candidate-box-list-item";
candidateListLIElement.textContent = candidateListItem;
candidateListLIElement.onclick = () => onItemSelected(candidateListItem);
// Append list item to ul
candidateListULElement.appendChild(candidateListLIElement);
});
// Add previous button
const isPrevBtnElementActive = pageIndex > 0;
const prevBtnElement = document.createElement("div");
prevBtnElement.classList.add("hg-candidate-box-prev");
isPrevBtnElementActive &&
prevBtnElement.classList.add("hg-candidate-box-btn-active");
prevBtnElement.onclick = () => {
if (!isPrevBtnElementActive) return;
this.renderPage({
candidateListPages,
targetElement,
pageIndex: pageIndex - 1,
nbPages,
onItemSelected,
});
};
this.candidateBoxElement.appendChild(prevBtnElement);
// Add elements to container
this.candidateBoxElement.appendChild(candidateListULElement);
// Add next button
const isNextBtnElementActive = pageIndex < nbPages - 1;
const nextBtnElement = document.createElement("div");
nextBtnElement.classList.add("hg-candidate-box-next");
isNextBtnElementActive &&
nextBtnElement.classList.add("hg-candidate-box-btn-active");
nextBtnElement.onclick = () => {
if (!isNextBtnElementActive) return;
this.renderPage({
candidateListPages,
targetElement,
pageIndex: pageIndex + 1,
nbPages,
onItemSelected,
});
};
this.candidateBoxElement.appendChild(nextBtnElement);
// Append candidate box to target element
targetElement.prepend(this.candidateBoxElement);
}
}
export default CandidateBox;