mirror of
https://github.com/hodgef/simple-keyboard.git
synced 2025-02-15 12:43:09 +08:00
163 lines
4.6 KiB
TypeScript
163 lines
4.6 KiB
TypeScript
import "./css/CandidateBox.css";
|
|
|
|
import Utilities from "../services/Utilities";
|
|
import {
|
|
CandidateBoxParams,
|
|
CandidateBoxRenderParams,
|
|
CandidateBoxShowParams,
|
|
KeyboardOptions,
|
|
} from "./../interfaces";
|
|
|
|
class CandidateBox {
|
|
utilities: Utilities;
|
|
options: KeyboardOptions;
|
|
candidateBoxElement!: HTMLDivElement;
|
|
pageIndex = 0;
|
|
pageSize: number;
|
|
|
|
constructor({ utilities, options }: CandidateBoxParams) {
|
|
this.utilities = utilities;
|
|
this.options = options;
|
|
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, e: MouseEvent) => {
|
|
onSelect(selectedCandidate, e);
|
|
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");
|
|
const getMouseEvent = () => {
|
|
const mouseEvent = new (this.options.useTouchEvents ? TouchEvent : MouseEvent)("click");
|
|
Object.defineProperty(mouseEvent, "target", {
|
|
value: candidateListLIElement,
|
|
});
|
|
return mouseEvent;
|
|
};
|
|
|
|
candidateListLIElement.className = "hg-candidate-box-list-item";
|
|
candidateListLIElement.innerHTML = this.options.display?.[candidateListItem] || candidateListItem;
|
|
|
|
if(this.options.useTouchEvents) {
|
|
candidateListLIElement.ontouchstart = (e: any) =>
|
|
onItemSelected(candidateListItem, e || getMouseEvent());
|
|
} else {
|
|
candidateListLIElement.onclick = (e = getMouseEvent() as MouseEvent) =>
|
|
onItemSelected(candidateListItem, e);
|
|
}
|
|
|
|
// 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");
|
|
|
|
const prevBtnElementClickAction = () => {
|
|
if (!isPrevBtnElementActive) return;
|
|
this.renderPage({
|
|
candidateListPages,
|
|
targetElement,
|
|
pageIndex: pageIndex - 1,
|
|
nbPages,
|
|
onItemSelected,
|
|
});
|
|
};
|
|
|
|
if(this.options.useTouchEvents) {
|
|
prevBtnElement.ontouchstart = prevBtnElementClickAction;
|
|
} else {
|
|
prevBtnElement.onclick = prevBtnElementClickAction;
|
|
}
|
|
|
|
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");
|
|
|
|
const nextBtnElementClickAction = () => {
|
|
if (!isNextBtnElementActive) return;
|
|
this.renderPage({
|
|
candidateListPages,
|
|
targetElement,
|
|
pageIndex: pageIndex + 1,
|
|
nbPages,
|
|
onItemSelected,
|
|
});
|
|
};
|
|
|
|
if(this.options.useTouchEvents) {
|
|
nextBtnElement.ontouchstart = nextBtnElementClickAction;
|
|
} else {
|
|
nextBtnElement.onclick = nextBtnElementClickAction;
|
|
}
|
|
|
|
this.candidateBoxElement.appendChild(nextBtnElement);
|
|
|
|
// Append candidate box to target element
|
|
targetElement.prepend(this.candidateBoxElement);
|
|
}
|
|
}
|
|
|
|
export default CandidateBox;
|