Allow CandidateBox caret positioning, passing event though onChange. Per https://github.com/hodgef/react-simple-keyboard/issues/1298

This commit is contained in:
Francisco Hodge
2021-06-28 23:26:43 -07:00
parent c6f12f0f92
commit 3032bef324
13 changed files with 201 additions and 25 deletions
+12 -3
View File
@@ -45,8 +45,8 @@ class CandidateBox {
targetElement,
pageIndex: this.pageIndex,
nbPages: candidateListPages.length,
onItemSelected: (selectedCandidate: string) => {
onSelect(selectedCandidate);
onItemSelected: (selectedCandidate: string, e: MouseEvent) => {
onSelect(selectedCandidate, e);
this.destroy();
},
});
@@ -73,9 +73,18 @@ class CandidateBox {
// Create Candidate box list items
candidateListPages[pageIndex].forEach((candidateListItem) => {
const candidateListLIElement = document.createElement("li");
const getMouseEvent = () => {
const mouseEvent = new MouseEvent("click");
Object.defineProperty(mouseEvent, "target", {
value: candidateListLIElement,
});
return mouseEvent;
};
candidateListLIElement.className = "hg-candidate-box-list-item";
candidateListLIElement.textContent = candidateListItem;
candidateListLIElement.onclick = () => onItemSelected(candidateListItem);
candidateListLIElement.onclick = (e = getMouseEvent()) =>
onItemSelected(candidateListItem, e);
// Append list item to ul
candidateListULElement.appendChild(candidateListLIElement);
+26 -8
View File
@@ -320,8 +320,10 @@ class SimpleKeyboard {
const layoutCandidates = Object.keys(layoutCandidatesObj).filter(
(layoutCandidate: string) => {
const inputSubstr =
input.substring(0, this.getCaretPositionEnd() || 0) || input;
const regexp = new RegExp(`${layoutCandidate}$`, "g");
const matches = [...input.matchAll(regexp)];
const matches = [...inputSubstr.matchAll(regexp)];
return !!matches.length;
}
);
@@ -359,21 +361,37 @@ class SimpleKeyboard {
this.candidateBox.show({
candidateValue,
targetElement,
onSelect: (selectedCandidate: string) => {
onSelect: (selectedCandidate: string, e: MouseEvent) => {
const currentInput = this.getInput(this.options.inputName, true);
const initialCaretPosition = this.getCaretPositionEnd() || 0;
const inputSubstr =
currentInput.substring(0, initialCaretPosition || 0) ||
currentInput;
const regexp = new RegExp(`${candidateKey}$`, "g");
const newInput = currentInput.replace(regexp, selectedCandidate);
const newInputSubstr = inputSubstr.replace(regexp, selectedCandidate);
const newInput = currentInput.replace(inputSubstr, newInputSubstr);
const caretPositionDiff = newInputSubstr.length - inputSubstr.length;
let newCaretPosition =
(initialCaretPosition || currentInput.length) + caretPositionDiff;
if (newCaretPosition < 0) newCaretPosition = 0;
this.setInput(newInput, this.options.inputName, true);
this.setCaretPosition(newCaretPosition);
if (typeof this.options.onChange === "function")
this.options.onChange(this.getInput(this.options.inputName, true));
this.options.onChange(
this.getInput(this.options.inputName, true),
e
);
/**
* Calling onChangeAll
*/
if (typeof this.options.onChangeAll === "function")
this.options.onChangeAll(this.getAllInputs());
this.options.onChangeAll(this.getAllInputs(), e);
},
});
}
@@ -429,7 +447,7 @@ class SimpleKeyboard {
* Calling onKeyPress
*/
if (typeof this.options.onKeyPress === "function")
this.options.onKeyPress(button);
this.options.onKeyPress(button, e);
if (
// If input will change as a result of this button press
@@ -483,13 +501,13 @@ class SimpleKeyboard {
* Calling onChange
*/
if (typeof this.options.onChange === "function")
this.options.onChange(this.getInput(this.options.inputName, true));
this.options.onChange(this.getInput(this.options.inputName, true), e);
/**
* Calling onChangeAll
*/
if (typeof this.options.onChangeAll === "function")
this.options.onChangeAll(this.getAllInputs());
this.options.onChangeAll(this.getAllInputs(), e);
/**
* Check if this new input has candidates (suggested words)
@@ -216,7 +216,7 @@ it('CandidateBox select candidate will work', () => {
keyboard.getButtonElement("a").click();
keyboard.candidateBox.candidateBoxElement.querySelector("li").click();
expect(onSelect).toBeCalledWith("1");
expect(onSelect).toBeCalledWith("1", expect.anything());
keyboard.destroy();
});
@@ -353,6 +353,7 @@ it('CandidateBox selection should trigger onChange', () => {
});
const candidateBoxRenderFn = keyboard.candidateBox.renderPage;
jest.spyOn(keyboard.candidateBox, "renderPage").mockImplementation((params) => {
candidateBoxOnItemSelected = params.onItemSelected;
params.onItemSelected = onSelect;
@@ -362,10 +363,10 @@ it('CandidateBox selection should trigger onChange', () => {
keyboard.getButtonElement("a").click();
keyboard.candidateBox.candidateBoxElement.querySelector("li").click();
expect(keyboard.options.onChange).toBeCalledWith("a");
expect(keyboard.options.onChangeAll).toBeCalledWith({"default": "a"});
expect(keyboard.options.onChange.mock.calls[0][0]).toBe("a");
expect(keyboard.options.onChangeAll.mock.calls[0][0]).toMatchObject({"default": "a"});
expect(keyboard.options.onChange).toBeCalledWith("1");
expect(keyboard.options.onChangeAll).toBeCalledWith({"default": "1"});
expect(keyboard.options.onChange.mock.calls[1][0]).toBe("1");
expect(keyboard.options.onChangeAll.mock.calls[1][0]).toMatchObject({"default": "1"});
keyboard.destroy();
});
+12 -2
View File
@@ -31,7 +31,7 @@ export type CandidateBoxShowParams = {
candidateValue: string,
targetElement: KeyboardElement,
// eslint-disable-next-line no-unused-vars
onSelect: (selectedCandidate: string) => void
onSelect: (selectedCandidate: string, e: MouseEvent) => void
}
export type CandidateBoxRenderParams = {
@@ -40,7 +40,7 @@ export type CandidateBoxRenderParams = {
pageIndex: number;
nbPages: number;
// eslint-disable-next-line no-unused-vars
onItemSelected: (selectedCandidate: string) => void
onItemSelected: (selectedCandidate: string, e: MouseEvent) => void
}
export type KeyboardElement = HTMLDivElement | HTMLButtonElement;
@@ -240,6 +240,16 @@ export interface KeyboardOptions {
*/
onInit?: (instance?: SimpleKeyboard) => void;
/**
* Retrieves the current input
*/
onChange?: (input: string, e?: MouseEvent) => any;
/**
* Retrieves all inputs
*/
onChangeAll?: (inputObj: KeyboardInput, e?: MouseEvent) => any;
/**
* Module options can have any format
*/