Added rtl option. Fixes #712

This commit is contained in:
Francisco Hodge 2020-10-16 00:09:09 -04:00
parent 11593c33b0
commit 58fad19e21
14 changed files with 222 additions and 15 deletions

View File

@ -1,6 +1,6 @@
/*! /*!
* *
* simple-keyboard v2.30.50 * simple-keyboard v2.31.0
* https://github.com/hodgef/simple-keyboard * https://github.com/hodgef/simple-keyboard
* *
* Copyright (c) Francisco Hodge (https://github.com/hodgef) * Copyright (c) Francisco Hodge (https://github.com/hodgef)

File diff suppressed because one or more lines are too long

5
build/index.d.ts vendored
View File

@ -152,6 +152,11 @@ declare module 'simple-keyboard' {
*/ */
disableButtonHold?: boolean; disableButtonHold?: boolean;
/**
* Adds unicode right-to-left control characters to input return values.
*/
rtl?: boolean;
/** /**
* Executes the callback function on key press. Returns button layout name (i.e.: "{shift}"). * Executes the callback function on key press. Returns button layout name (i.e.: "{shift}").
*/ */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

14
package-lock.json generated
View File

@ -1,6 +1,6 @@
{ {
"name": "simple-keyboard", "name": "simple-keyboard",
"version": "2.30.50", "version": "2.31.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@ -11203,7 +11203,11 @@
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
"dev": true, "dev": true,
"optional": true "optional": true,
"requires": {
"bindings": "^1.5.0",
"nan": "^2.12.1"
}
}, },
"html-encoding-sniffer": { "html-encoding-sniffer": {
"version": "1.0.2", "version": "1.0.2",
@ -20962,7 +20966,11 @@
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
"dev": true, "dev": true,
"optional": true "optional": true,
"requires": {
"bindings": "^1.5.0",
"nan": "^2.12.1"
}
}, },
"import-local": { "import-local": {
"version": "2.0.0", "version": "2.0.0",

View File

@ -1,6 +1,6 @@
{ {
"name": "simple-keyboard", "name": "simple-keyboard",
"version": "2.30.50", "version": "2.31.0",
"description": "On-screen Javascript Virtual Keyboard", "description": "On-screen Javascript Virtual Keyboard",
"main": "build/index.js", "main": "build/index.js",
"types": "build/index.d.ts", "types": "build/index.d.ts",

72
src/demo/RTLDemo.js Normal file
View File

@ -0,0 +1,72 @@
import Keyboard from "../lib";
import "./css/RTLDemo.css";
const setDOM = () => {
document.querySelector("#root").innerHTML = `
<input class="input" placeholder="Tap on the virtual keyboard to start" />
<div class="simple-keyboard"></div>
`;
};
class Demo {
constructor() {
setDOM();
/**
* Demo Start
*/
this.keyboard = new Keyboard({
onChange: input => this.onChange(input),
onKeyPress: button => this.onKeyPress(button),
rtl: true,
layout: {
default: [
"\u05e5 1 2 3 4 5 6 7 8 9 0 - = {bksp}",
"{tab} \u05e3 \u05df \u05e7 \u05e8 \u05d0 \u05d8 \u05d5 \u05ea \u05dd \u05e4 ] [ \\",
"{lock} \u05e9 \u05d3 \u05d2 \u05db \u05e2 \u05d9 \u05d7 \u05dc \u05da : ' {enter}",
"{shift} \u05d6 \u05e1 \u05d1 \u05d4 \u05e0 \u05de \u05e6 , . / {shift}",
".com @ {space}"
],
shift: [
"~ ! @ # $ % ^ & * ( ) _ + {bksp}",
"{tab} Q W E R T Y U I O P { } |",
'{lock} A S D F G H J K L : " {enter}',
"{shift} Z X C V B N M < > ? {shift}",
".com @ {space}"
]
}
});
/**
* Update simple-keyboard when input is changed directly
*/
document.querySelector(".input").addEventListener("input", event => {
this.keyboard.setInput(event.target.value);
});
}
onChange(input) {
document.querySelector(".input").value = input;
console.log("Input changed", input, input.split(""));
}
onKeyPress(button) {
console.log("Button pressed", button);
/**
* If you want to handle the shift and caps lock buttons
*/
if (button === "{shift}" || button === "{lock}") this.handleShift();
}
handleShift() {
const currentLayout = this.keyboard.options.layoutName;
const shiftToggle = currentLayout === "default" ? "shift" : "default";
this.keyboard.setOptions({
layoutName: shiftToggle
});
}
}
export default Demo;

13
src/demo/css/RTLDemo.css Normal file
View File

@ -0,0 +1,13 @@
input {
width: 100%;
height: 100px;
padding: 20px;
font-size: 20px;
border: none;
box-sizing: border-box;
direction: rtl;
}
.simple-keyboard {
max-width: 850px;
}

View File

@ -4,6 +4,7 @@ import "./css/index.css";
* Demos * Demos
*/ */
import BasicDemo from "./BasicDemo"; import BasicDemo from "./BasicDemo";
//import RTLDemo from "./RTLDemo";
//import ButtonThemeDemo from "./ButtonThemeDemo"; //import ButtonThemeDemo from "./ButtonThemeDemo";
//import DOMElementDemo from "./DOMElementDemo"; //import DOMElementDemo from "./DOMElementDemo";
//import FullKeyboardDemo from "./FullKeyboardDemo"; //import FullKeyboardDemo from "./FullKeyboardDemo";

View File

@ -0,0 +1,72 @@
import { setDOM, removeRTLControls } from '../../utils/TestUtility';
import RTLDemo from '../RTLDemo';
it('Demo will load', () => {
setDOM();
new RTLDemo();
});
it('Demo onDOMLoaded will work', () => {
setDOM();
const demo = new RTLDemo();
expect(demo.keyboard).toBeTruthy();
});
it('Demo onChange will work', () => {
setDOM();
const demo = new RTLDemo();
demo.onChange("test");
expect(removeRTLControls(document.body.querySelector('.input').value)).toBe("test");
});
it('Demo onChange will work', () => {
setDOM();
const demo = new RTLDemo();
demo.keyboard.getButtonElement(".").onclick();
expect(removeRTLControls(document.body.querySelector('.input').value)).toBe(".");
});
it('Demo input change will work', () => {
setDOM();
const demo = new RTLDemo();
document.body.querySelector('.input').value = "test";
document.body.querySelector('.input').dispatchEvent(new Event('input'));
expect(removeRTLControls(demo.keyboard.getInput())).toBe("test");
});
it('Demo handleShiftButton will work', () => {
setDOM();
const demo = new RTLDemo();
demo.keyboard.getButtonElement("{shift}")[0].onclick();
expect(demo.keyboard.options.layoutName).toBe("shift");
demo.keyboard.getButtonElement("{shift}")[0].onclick();
expect(demo.keyboard.options.layoutName).toBe("default");
});
it('RTL control caracters will be added to ', () => {
setDOM();
const demo = new RTLDemo();
demo.keyboard.getButtonElement("פ").onclick();
demo.keyboard.getButtonElement("ם").onclick();
demo.keyboard.getButtonElement("[").onclick();
expect(demo.keyboard.getInput()).toBe("‫פם[");
expect(demo.keyboard.input[demo.keyboard.options.inputName]).toBe("פם[");
});

View File

@ -152,6 +152,11 @@ declare module 'simple-keyboard' {
*/ */
disableButtonHold?: boolean; disableButtonHold?: boolean;
/**
* Adds unicode right-to-left control characters to input return values.
*/
rtl?: boolean;
/** /**
* Executes the callback function on key press. Returns button layout name (i.e.: "{shift}"). * Executes the callback function on key press. Returns button layout name (i.e.: "{shift}").
*/ */

View File

@ -83,6 +83,7 @@ class SimpleKeyboard {
* @property {boolean} useMouseEvents Opt out of PointerEvents handling, falling back to the prior mouse event logic. * @property {boolean} useMouseEvents Opt out of PointerEvents handling, falling back to the prior mouse event logic.
* @property {function} destroy Clears keyboard listeners and DOM elements. * @property {function} destroy Clears keyboard listeners and DOM elements.
* @property {boolean} disableButtonHold Disable button hold action. * @property {boolean} disableButtonHold Disable button hold action.
* @property {boolean} rtl Adds unicode right-to-left control characters to input return values.
* @property {function} onKeyReleased Executes the callback function on key release. * @property {function} onKeyReleased Executes the callback function on key release.
* @property {array} modules Module classes to be loaded by simple-keyboard. * @property {array} modules Module classes to be loaded by simple-keyboard.
*/ */
@ -292,7 +293,7 @@ class SimpleKeyboard {
true true
); );
if (debug) console.log("Input changed:", this.input); if (debug) console.log("Input changed:", this.getAllInputs());
if (this.options.debug) { if (this.options.debug) {
console.log( console.log(
@ -312,13 +313,13 @@ class SimpleKeyboard {
* Calling onChange * Calling onChange
*/ */
if (typeof this.options.onChange === "function") if (typeof this.options.onChange === "function")
this.options.onChange(this.input[this.options.inputName]); this.options.onChange(this.getInput(this.options.inputName, true));
/** /**
* Calling onChangeAll * Calling onChangeAll
*/ */
if (typeof this.options.onChangeAll === "function") if (typeof this.options.onChangeAll === "function")
this.options.onChangeAll(this.input); this.options.onChangeAll(this.getAllInputs());
} }
if (debug) { if (debug) {
@ -470,15 +471,38 @@ class SimpleKeyboard {
* Get the keyboards input (You can also get it from the onChange prop). * Get the keyboards input (You can also get it from the onChange prop).
* @param {string} [inputName] optional - the internal input to select * @param {string} [inputName] optional - the internal input to select
*/ */
getInput(inputName) { getInput(inputName, skipSync = false) {
inputName = inputName || this.options.inputName; inputName = inputName || this.options.inputName;
/** /**
* Enforce syncInstanceInputs, if set * Enforce syncInstanceInputs, if set
*/ */
if (this.options.syncInstanceInputs) this.syncInstanceInputs(); if (this.options.syncInstanceInputs && !skipSync) this.syncInstanceInputs();
return this.input[inputName]; if (this.options.rtl) {
// Remove existing control chars
const inputWithoutRTLControl = this.input[inputName]
.replace("\u202B", "")
.replace("\u202C", "");
return "\u202B" + inputWithoutRTLControl + "\u202C";
} else {
return this.input[inputName];
}
}
/**
* Get all simple-keyboard inputs
*/
getAllInputs() {
const output = {};
const inputNames = Object.keys(this.input);
inputNames.forEach(inputName => {
output[inputName] = this.getInput(inputName, true);
});
return output;
} }
/** /**

View File

@ -122,3 +122,10 @@
}); });
}); });
} }
/**
* Remove RTL control chars
*/
export const removeRTLControls = (input) => {
return input.replace("\u202B", "").replace("\u202C", "");
}