mirror of
https://github.com/hodgef/simple-keyboard.git
synced 2026-07-14 00:00:06 +08:00
Compare commits
@@ -17,8 +17,6 @@ jobs:
|
|||||||
- name: npm install, build, and test
|
- name: npm install, build, and test
|
||||||
run: |
|
run: |
|
||||||
npm install
|
npm install
|
||||||
npm run start -- --testMode
|
|
||||||
npm run demo
|
|
||||||
npm run coverage
|
npm run coverage
|
||||||
env:
|
env:
|
||||||
CI: true
|
CI: true
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<p>
|
<p>
|
||||||
<a href="https://simple-keyboard.com/demo">
|
<a href="https://simple-keyboard.com/demo">
|
||||||
<img alt="simple-keyboard: Javascript Virtual Keyboard" src="https://i.imgur.com/Po6659n.gif">
|
<img alt="simple-keyboard: Javascript Virtual Keyboard" src="https://i.imgur.com/PrpbdIu.png">
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="https://www.npmjs.com/package/simple-keyboard">
|
<a href="https://www.npmjs.com/package/simple-keyboard">
|
||||||
@@ -14,10 +14,6 @@
|
|||||||
<a href="https://github.com/hodgef/simple-keyboard/actions">
|
<a href="https://github.com/hodgef/simple-keyboard/actions">
|
||||||
<img alt="Publish Status" src="https://github.com/hodgef/simple-keyboard/workflows/Publish/badge.svg?color=green" />
|
<img alt="Publish Status" src="https://github.com/hodgef/simple-keyboard/workflows/Publish/badge.svg?color=green" />
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="https://bundlephobia.com/result?p=simple-keyboard">
|
|
||||||
<img src="https://badgen.net/bundlephobia/minzip/simple-keyboard/?color=green" alt="install size">
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="https://david-dm.org/hodgef/simple-keyboard">
|
<a href="https://david-dm.org/hodgef/simple-keyboard">
|
||||||
<img src="https://badgen.net/david/dep/hodgef/simple-keyboard" alt="coverage">
|
<img src="https://badgen.net/david/dep/hodgef/simple-keyboard" alt="coverage">
|
||||||
@@ -30,17 +26,17 @@
|
|||||||
|
|
||||||
<blockquote>Virtual Keyboard for Javascript. Compatible with your JS, React, Angular or Vue projects.</blockquote>
|
<blockquote>Virtual Keyboard for Javascript. Compatible with your JS, React, Angular or Vue projects.</blockquote>
|
||||||
|
|
||||||
## Demo 🚀
|
## 🚀 Demo
|
||||||
|
|
||||||
[Demo Showcase (Vanilla, Angular, React, Vue)](https://simple-keyboard.com/demo)
|
[Demo Showcase (Vanilla, Angular, React, Vue)](https://simple-keyboard.com/demo)
|
||||||
|
|
||||||
## Installation & Usage 📦
|
## 📦 Installation & Usage
|
||||||
|
|
||||||
You can use simple-keyboard as a `<script>` tag from a CDN, or install it from npm.
|
You can use simple-keyboard as a `<script>` tag from a CDN, or install it from npm.
|
||||||
|
|
||||||
Check out the [Getting Started](https://simple-keyboard.com/getting-started) docs to begin.
|
Check out the [Getting Started](https://simple-keyboard.com/getting-started) docs to begin.
|
||||||
|
|
||||||
## Documentation 📖
|
## 📖 Documentation
|
||||||
|
|
||||||
Check out the [simple-keyboard documentation](https://simple-keyboard.com/documentation) site.
|
Check out the [simple-keyboard documentation](https://simple-keyboard.com/documentation) site.
|
||||||
|
|
||||||
@@ -63,7 +59,7 @@ Feel free to browse the [Questions & Answers (FAQ)](https://simple-keyboard.com/
|
|||||||
|
|
||||||
<a href="https://discordapp.com/invite/SJexsCG" title="Join our Discord chat" target="_blank"><img src="https://discordapp.com/api/guilds/498978399801573396/widget.png?style=banner2" align="center"></a>
|
<a href="https://discordapp.com/invite/SJexsCG" title="Join our Discord chat" target="_blank"><img src="https://discordapp.com/api/guilds/498978399801573396/widget.png?style=banner2" align="center"></a>
|
||||||
|
|
||||||
## Modules ✳️
|
## ✳️ Modules
|
||||||
|
|
||||||
You can extend simple-keyboard's functionality with [modules](https://hodgef.com/simple-keyboard/modules/). Such as:
|
You can extend simple-keyboard's functionality with [modules](https://hodgef.com/simple-keyboard/modules/). Such as:
|
||||||
|
|
||||||
@@ -74,7 +70,7 @@ You can extend simple-keyboard's functionality with [modules](https://hodgef.com
|
|||||||
|
|
||||||
Want to create your own module? Check out the [Modules page](https://hodgef.com/simple-keyboard/modules/) for instructions.
|
Want to create your own module? Check out the [Modules page](https://hodgef.com/simple-keyboard/modules/) for instructions.
|
||||||
|
|
||||||
## Compatibility 🎯
|
## 🎯 Compatibility
|
||||||
|
|
||||||
- Internet Explorer 11
|
- Internet Explorer 11
|
||||||
- Edge (Spartan) 16+
|
- Edge (Spartan) 16+
|
||||||
@@ -84,7 +80,7 @@ Want to create your own module? Check out the [Modules page](https://hodgef.com/
|
|||||||
- Firefox 57+
|
- Firefox 57+
|
||||||
- iOS 9+
|
- iOS 9+
|
||||||
|
|
||||||
## Contributing ✅
|
## ✅ Contributing
|
||||||
|
|
||||||
PRs and issues are always welcome. Feel free to submit any issues you have at:
|
PRs and issues are always welcome. Feel free to submit any issues you have at:
|
||||||
[https://github.com/hodgef/simple-keyboard/issues](https://github.com/hodgef/simple-keyboard/issues)
|
[https://github.com/hodgef/simple-keyboard/issues](https://github.com/hodgef/simple-keyboard/issues)
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
/*!
|
/*!
|
||||||
*
|
*
|
||||||
* simple-keyboard v3.0.0
|
* simple-keyboard v3.1.0
|
||||||
* https://github.com/hodgef/simple-keyboard
|
* https://github.com/hodgef/simple-keyboard
|
||||||
*
|
*
|
||||||
* Copyright (c) Francisco Hodge (https://github.com/hodgef) and project contributors.
|
* Copyright (c) Francisco Hodge (https://github.com/hodgef) and project contributors.
|
||||||
|
|||||||
+2
-2
File diff suppressed because one or more lines are too long
Vendored
+10
-9
@@ -13,8 +13,8 @@ declare class SimpleKeyboard {
|
|||||||
input: KeyboardInput;
|
input: KeyboardInput;
|
||||||
options: KeyboardOptions;
|
options: KeyboardOptions;
|
||||||
utilities: any;
|
utilities: any;
|
||||||
caretPosition: number;
|
caretPosition: number | null;
|
||||||
caretPositionEnd: number;
|
caretPositionEnd: number | null;
|
||||||
keyboardDOM: KeyboardElement;
|
keyboardDOM: KeyboardElement;
|
||||||
keyboardPluginClasses: string;
|
keyboardPluginClasses: string;
|
||||||
keyboardDOMClass: string;
|
keyboardDOMClass: string;
|
||||||
@@ -34,8 +34,9 @@ declare class SimpleKeyboard {
|
|||||||
holdTimeout: number;
|
holdTimeout: number;
|
||||||
isMouseHold: boolean;
|
isMouseHold: boolean;
|
||||||
initialized: boolean;
|
initialized: boolean;
|
||||||
candidateBox: CandidateBox;
|
candidateBox: CandidateBox | null;
|
||||||
keyboardRowsDOM: KeyboardElement;
|
keyboardRowsDOM: KeyboardElement;
|
||||||
|
defaultName: string;
|
||||||
/**
|
/**
|
||||||
* Creates an instance of SimpleKeyboard
|
* Creates an instance of SimpleKeyboard
|
||||||
* @param {Array} params If first parameter is a string, it is considered the container class. The second parameter is then considered the options object. If first parameter is an object, it is considered the options object.
|
* @param {Array} params If first parameter is a string, it is considered the container class. The second parameter is then considered the options object. If first parameter is an object, it is considered the options object.
|
||||||
@@ -47,20 +48,20 @@ declare class SimpleKeyboard {
|
|||||||
handleParams: (params: KeyboardParams) => {
|
handleParams: (params: KeyboardParams) => {
|
||||||
keyboardDOMClass: string;
|
keyboardDOMClass: string;
|
||||||
keyboardDOM: KeyboardElement;
|
keyboardDOM: KeyboardElement;
|
||||||
options: Partial<KeyboardOptions>;
|
options: Partial<KeyboardOptions | undefined>;
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* Getters
|
* Getters
|
||||||
*/
|
*/
|
||||||
getOptions: () => KeyboardOptions;
|
getOptions: () => KeyboardOptions;
|
||||||
getCaretPosition: () => number;
|
getCaretPosition: () => number | null;
|
||||||
getCaretPositionEnd: () => number;
|
getCaretPositionEnd: () => number | null;
|
||||||
/**
|
/**
|
||||||
* Changes the internal caret position
|
* Changes the internal caret position
|
||||||
* @param {number} position The caret's start position
|
* @param {number} position The caret's start position
|
||||||
* @param {number} positionEnd The caret's end position
|
* @param {number} positionEnd The caret's end position
|
||||||
*/
|
*/
|
||||||
setCaretPosition(position: number, endPosition?: number): void;
|
setCaretPosition(position: number | null, endPosition?: number | null): void;
|
||||||
/**
|
/**
|
||||||
* Retrieve the candidates for a given input
|
* Retrieve the candidates for a given input
|
||||||
* @param input The input string to check
|
* @param input The input string to check
|
||||||
@@ -104,7 +105,7 @@ declare class SimpleKeyboard {
|
|||||||
* Clear the keyboard’s input.
|
* Clear the keyboard’s input.
|
||||||
* @param {string} [inputName] optional - the internal input to select
|
* @param {string} [inputName] optional - the internal input to select
|
||||||
*/
|
*/
|
||||||
clearInput(inputName: string): void;
|
clearInput(inputName?: string): void;
|
||||||
/**
|
/**
|
||||||
* Get the keyboard’s input (You can also get it from the onChange prop).
|
* Get the keyboard’s 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
|
||||||
@@ -166,7 +167,7 @@ declare class SimpleKeyboard {
|
|||||||
* Get the DOM Element of a button. If there are several buttons with the same name, an array of the DOM Elements is returned.
|
* Get the DOM Element of a button. If there are several buttons with the same name, an array of the DOM Elements is returned.
|
||||||
* @param {string} button The button layout name to select
|
* @param {string} button The button layout name to select
|
||||||
*/
|
*/
|
||||||
getButtonElement(button: string): KeyboardElement | KeyboardElement[];
|
getButtonElement(button: string): KeyboardElement | KeyboardElement[] | undefined;
|
||||||
/**
|
/**
|
||||||
* This handles the "inputPattern" option
|
* This handles the "inputPattern" option
|
||||||
* by checking if the provided inputPattern passes
|
* by checking if the provided inputPattern passes
|
||||||
|
|||||||
Vendored
+9
-7
@@ -3,10 +3,10 @@ import Utilities from "./services/Utilities";
|
|||||||
export interface KeyboardLayoutObject {
|
export interface KeyboardLayoutObject {
|
||||||
[key: string]: string[];
|
[key: string]: string[];
|
||||||
}
|
}
|
||||||
export interface KeyboardButtonTheme {
|
export declare type KeyboardButtonTheme = {
|
||||||
class: string;
|
class: string;
|
||||||
buttons: string;
|
buttons: string;
|
||||||
}
|
} | null;
|
||||||
export interface KeyboardButtonAttributes {
|
export interface KeyboardButtonAttributes {
|
||||||
attribute: string;
|
attribute: string;
|
||||||
value: string;
|
value: string;
|
||||||
@@ -32,16 +32,18 @@ export declare type CandidateBoxRenderParams = {
|
|||||||
onItemSelected: (selectedCandidate: string) => void;
|
onItemSelected: (selectedCandidate: string) => void;
|
||||||
};
|
};
|
||||||
export declare type KeyboardElement = HTMLDivElement | HTMLButtonElement;
|
export declare type KeyboardElement = HTMLDivElement | HTMLButtonElement;
|
||||||
export declare type KeyboardHandlerEvent = PointerEvent & TouchEvent & KeyboardEvent & {
|
export declare type KeyboardHandlerEvent = any;
|
||||||
target: HTMLDivElement & HTMLInputElement;
|
|
||||||
};
|
|
||||||
export interface KeyboardButtonElements {
|
export interface KeyboardButtonElements {
|
||||||
[key: string]: KeyboardElement[];
|
[key: string]: KeyboardElement[];
|
||||||
}
|
}
|
||||||
export interface UtilitiesParams {
|
export interface UtilitiesParams {
|
||||||
getOptions: () => KeyboardOptions;
|
getOptions: () => KeyboardOptions;
|
||||||
getCaretPosition: () => number;
|
getCaretPosition: () => number | null;
|
||||||
getCaretPositionEnd: () => number;
|
getCaretPositionEnd: () => number | null;
|
||||||
|
dispatch: any;
|
||||||
|
}
|
||||||
|
export interface PhysicalKeyboardParams {
|
||||||
|
getOptions: () => KeyboardOptions;
|
||||||
dispatch: any;
|
dispatch: any;
|
||||||
}
|
}
|
||||||
export interface KeyboardOptions {
|
export interface KeyboardOptions {
|
||||||
|
|||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
import { KeyboardOptions, UtilitiesParams } from "../interfaces";
|
import { KeyboardOptions, PhysicalKeyboardParams } from "../interfaces";
|
||||||
/**
|
/**
|
||||||
* Physical Keyboard Service
|
* Physical Keyboard Service
|
||||||
*/
|
*/
|
||||||
@@ -8,7 +8,7 @@ declare class PhysicalKeyboard {
|
|||||||
/**
|
/**
|
||||||
* Creates an instance of the PhysicalKeyboard service
|
* Creates an instance of the PhysicalKeyboard service
|
||||||
*/
|
*/
|
||||||
constructor({ dispatch, getOptions }: Partial<UtilitiesParams>);
|
constructor({ dispatch, getOptions }: PhysicalKeyboardParams);
|
||||||
handleHighlightKeyDown(event: KeyboardEvent): void;
|
handleHighlightKeyDown(event: KeyboardEvent): void;
|
||||||
handleHighlightKeyUp(event: KeyboardEvent): void;
|
handleHighlightKeyUp(event: KeyboardEvent): void;
|
||||||
/**
|
/**
|
||||||
|
|||||||
Vendored
+13
-5
@@ -5,8 +5,8 @@ import { KeyboardOptions, UtilitiesParams } from "../interfaces";
|
|||||||
*/
|
*/
|
||||||
declare class Utilities {
|
declare class Utilities {
|
||||||
getOptions: () => KeyboardOptions;
|
getOptions: () => KeyboardOptions;
|
||||||
getCaretPosition: () => number;
|
getCaretPosition: () => number | null;
|
||||||
getCaretPositionEnd: () => number;
|
getCaretPositionEnd: () => number | null;
|
||||||
dispatch: any;
|
dispatch: any;
|
||||||
maxLengthReached: boolean;
|
maxLengthReached: boolean;
|
||||||
/**
|
/**
|
||||||
@@ -72,6 +72,7 @@ declare class Utilities {
|
|||||||
"{home}": string;
|
"{home}": string;
|
||||||
"{pageup}": string;
|
"{pageup}": string;
|
||||||
"{delete}": string;
|
"{delete}": string;
|
||||||
|
"{forwarddelete}": string;
|
||||||
"{end}": string;
|
"{end}": string;
|
||||||
"{pagedown}": string;
|
"{pagedown}": string;
|
||||||
"{numpadmultiply}": string;
|
"{numpadmultiply}": string;
|
||||||
@@ -122,7 +123,7 @@ declare class Utilities {
|
|||||||
* @param {number} length Represents by how many characters the input should be moved
|
* @param {number} length Represents by how many characters the input should be moved
|
||||||
* @param {boolean} minus Whether the cursor should be moved to the left or not.
|
* @param {boolean} minus Whether the cursor should be moved to the left or not.
|
||||||
*/
|
*/
|
||||||
updateCaretPosAction(length: number, minus?: boolean): number;
|
updateCaretPosAction(length: number, minus?: boolean): number | null;
|
||||||
/**
|
/**
|
||||||
* Adds a string to the input at a given position
|
* Adds a string to the input at a given position
|
||||||
*
|
*
|
||||||
@@ -133,20 +134,27 @@ declare class Utilities {
|
|||||||
*/
|
*/
|
||||||
addStringAt(source: string, str: string, position?: number, positionEnd?: number, moveCaret?: boolean): string;
|
addStringAt(source: string, str: string, position?: number, positionEnd?: number, moveCaret?: boolean): string;
|
||||||
/**
|
/**
|
||||||
* Removes an amount of characters at a given position
|
* Removes an amount of characters before a given position
|
||||||
*
|
*
|
||||||
* @param {string} source The source input
|
* @param {string} source The source input
|
||||||
* @param {number} position The (cursor) position from where the characters should be removed
|
* @param {number} position The (cursor) position from where the characters should be removed
|
||||||
* @param {boolean} moveCaret Whether to update simple-keyboard's cursor
|
* @param {boolean} moveCaret Whether to update simple-keyboard's cursor
|
||||||
*/
|
*/
|
||||||
removeAt(source: string, position?: number, positionEnd?: number, moveCaret?: boolean): string;
|
removeAt(source: string, position?: number, positionEnd?: number, moveCaret?: boolean): string;
|
||||||
|
/**
|
||||||
|
* Removes an amount of characters after a given position
|
||||||
|
*
|
||||||
|
* @param {string} source The source input
|
||||||
|
* @param {number} position The (cursor) position from where the characters should be removed
|
||||||
|
*/
|
||||||
|
removeForwardsAt(source: string, position?: number, positionEnd?: number, moveCaret?: boolean): string;
|
||||||
/**
|
/**
|
||||||
* Determines whether the maxLength has been reached. This function is called when the maxLength option it set.
|
* Determines whether the maxLength has been reached. This function is called when the maxLength option it set.
|
||||||
*
|
*
|
||||||
* @param {object} inputObj
|
* @param {object} inputObj
|
||||||
* @param {string} updatedInput
|
* @param {string} updatedInput
|
||||||
*/
|
*/
|
||||||
handleMaxLength(inputObj: KeyboardInput, updatedInput: string): boolean;
|
handleMaxLength(inputObj: KeyboardInput, updatedInput: string): boolean | undefined;
|
||||||
/**
|
/**
|
||||||
* Gets the current value of maxLengthReached
|
* Gets the current value of maxLengthReached
|
||||||
*/
|
*/
|
||||||
|
|||||||
Generated
+1151
-570
File diff suppressed because it is too large
Load Diff
+19
-19
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "simple-keyboard",
|
"name": "simple-keyboard",
|
||||||
"version": "3.0.0",
|
"version": "3.1.0",
|
||||||
"description": "On-screen Javascript Virtual Keyboard",
|
"description": "On-screen Javascript Virtual Keyboard",
|
||||||
"main": "build/index.js",
|
"main": "build/index.js",
|
||||||
"types": "build/types/index.d.ts",
|
"types": "build/types/index.d.ts",
|
||||||
@@ -39,38 +39,38 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.13.0",
|
"@babel/cli": "^7.13.16",
|
||||||
"@babel/core": "^7.13.8",
|
"@babel/core": "^7.14.2",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.13.0",
|
"@babel/plugin-proposal-class-properties": "^7.13.0",
|
||||||
"@babel/plugin-transform-typescript": "^7.13.0",
|
"@babel/plugin-transform-typescript": "^7.13.0",
|
||||||
"@babel/polyfill": "^7.12.1",
|
"@babel/polyfill": "^7.12.1",
|
||||||
"@babel/preset-env": "^7.13.9",
|
"@babel/preset-env": "^7.14.2",
|
||||||
"@types/jest": "^26.0.20",
|
"@types/jest": "^26.0.23",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.16.1",
|
"@typescript-eslint/eslint-plugin": "^4.23.0",
|
||||||
"@typescript-eslint/parser": "^4.16.1",
|
"@typescript-eslint/parser": "^4.23.0",
|
||||||
"autoprefixer": "^10.2.5",
|
"autoprefixer": "^10.2.5",
|
||||||
"babel-eslint": "^10.1.0",
|
"babel-eslint": "^10.1.0",
|
||||||
"babel-loader": "^8.2.2",
|
"babel-loader": "^8.2.2",
|
||||||
"babel-preset-minify": "^0.5.0",
|
"babel-preset-minify": "^0.5.0",
|
||||||
"core-js": "^3.9.1",
|
"core-js": "^3.12.1",
|
||||||
"css-loader": "^5.1.1",
|
"css-loader": "^5.2.4",
|
||||||
"eslint": "^7.21.0",
|
"eslint": "^7.26.0",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
"html-webpack-plugin": "^5.3.0",
|
"html-webpack-plugin": "^5.3.1",
|
||||||
"jest": "^26.6.3",
|
"jest": "^26.6.3",
|
||||||
"mini-css-extract-plugin": "^1.3.9",
|
"mini-css-extract-plugin": "^1.6.0",
|
||||||
"optimize-css-assets-webpack-plugin": "^5.0.4",
|
"optimize-css-assets-webpack-plugin": "^5.0.4",
|
||||||
"postcss": "^8.2.8",
|
"postcss": "^8.2.15",
|
||||||
"postcss-loader": "^5.2.0",
|
"postcss-loader": "^5.2.0",
|
||||||
"prettier": "^2.2.1",
|
"prettier": "^2.3.0",
|
||||||
"prettier-webpack-plugin": "^1.2.0",
|
"prettier-webpack-plugin": "^1.2.0",
|
||||||
"style-loader": "^2.0.0",
|
"style-loader": "^2.0.0",
|
||||||
"terser-webpack-plugin": "^5.1.1",
|
"terser-webpack-plugin": "^5.1.2",
|
||||||
"typescript": "^4.2.3",
|
"typescript": "^4.2.4",
|
||||||
"url-loader": "^4.1.1",
|
"url-loader": "^4.1.1",
|
||||||
"webpack": "^5.24.3",
|
"webpack": "^5.37.0",
|
||||||
"webpack-cli": "^4.5.0",
|
"webpack-cli": "^4.7.0",
|
||||||
"webpack-dev-server": "4.0.0-beta.0"
|
"webpack-dev-server": "4.0.0-beta.3"
|
||||||
},
|
},
|
||||||
"jest": {
|
"jest": {
|
||||||
"roots": [
|
"roots": [
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
|
|
||||||
class CandidateBox {
|
class CandidateBox {
|
||||||
utilities: Utilities;
|
utilities: Utilities;
|
||||||
candidateBoxElement: HTMLDivElement;
|
candidateBoxElement!: HTMLDivElement;
|
||||||
pageIndex = 0;
|
pageIndex = 0;
|
||||||
pageSize;
|
pageSize;
|
||||||
|
|
||||||
|
|||||||
+273
-261
@@ -22,28 +22,29 @@ import CandidateBox from "./CandidateBox";
|
|||||||
* - Handles button functionality
|
* - Handles button functionality
|
||||||
*/
|
*/
|
||||||
class SimpleKeyboard {
|
class SimpleKeyboard {
|
||||||
input: KeyboardInput;
|
input!: KeyboardInput;
|
||||||
options: KeyboardOptions;
|
options!: KeyboardOptions;
|
||||||
utilities: any;
|
utilities: any;
|
||||||
caretPosition: number;
|
caretPosition!: number | null;
|
||||||
caretPositionEnd: number;
|
caretPositionEnd!: number | null;
|
||||||
keyboardDOM: KeyboardElement;
|
keyboardDOM!: KeyboardElement;
|
||||||
keyboardPluginClasses: string;
|
keyboardPluginClasses!: string;
|
||||||
keyboardDOMClass: string;
|
keyboardDOMClass!: string;
|
||||||
buttonElements: KeyboardButtonElements;
|
buttonElements!: KeyboardButtonElements;
|
||||||
currentInstanceName: string;
|
currentInstanceName!: string;
|
||||||
allKeyboardInstances: { [key: string]: SimpleKeyboard };
|
allKeyboardInstances!: { [key: string]: SimpleKeyboard };
|
||||||
keyboardInstanceNames: string[];
|
keyboardInstanceNames!: string[];
|
||||||
isFirstKeyboardInstance: boolean;
|
isFirstKeyboardInstance!: boolean;
|
||||||
physicalKeyboard: PhysicalKeyboard;
|
physicalKeyboard!: PhysicalKeyboard;
|
||||||
modules: { [key: string]: any };
|
modules!: { [key: string]: any };
|
||||||
activeButtonClass: string;
|
activeButtonClass!: string;
|
||||||
holdInteractionTimeout: number;
|
holdInteractionTimeout!: number;
|
||||||
holdTimeout: number;
|
holdTimeout!: number;
|
||||||
isMouseHold: boolean;
|
isMouseHold!: boolean;
|
||||||
initialized: boolean;
|
initialized!: boolean;
|
||||||
candidateBox: CandidateBox;
|
candidateBox!: CandidateBox | null;
|
||||||
keyboardRowsDOM: KeyboardElement;
|
keyboardRowsDOM!: KeyboardElement;
|
||||||
|
defaultName = "default";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an instance of SimpleKeyboard
|
* Creates an instance of SimpleKeyboard
|
||||||
@@ -159,8 +160,9 @@ class SimpleKeyboard {
|
|||||||
* @property {object} default Default SimpleKeyboard internal input.
|
* @property {object} default Default SimpleKeyboard internal input.
|
||||||
* @property {object} myInputName Example input that can be set through `options.inputName:"myInputName"`.
|
* @property {object} myInputName Example input that can be set through `options.inputName:"myInputName"`.
|
||||||
*/
|
*/
|
||||||
|
const { inputName = this.defaultName } = this.options;
|
||||||
this.input = {};
|
this.input = {};
|
||||||
this.input[this.options.inputName] = "";
|
this.input[inputName] = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {string} DOM class of the keyboard wrapper, normally "simple-keyboard" by default.
|
* @type {string} DOM class of the keyboard wrapper, normally "simple-keyboard" by default.
|
||||||
@@ -231,7 +233,7 @@ class SimpleKeyboard {
|
|||||||
): {
|
): {
|
||||||
keyboardDOMClass: string;
|
keyboardDOMClass: string;
|
||||||
keyboardDOM: KeyboardElement;
|
keyboardDOM: KeyboardElement;
|
||||||
options: Partial<KeyboardOptions>;
|
options: Partial<KeyboardOptions | undefined>;
|
||||||
} => {
|
} => {
|
||||||
let keyboardDOMClass;
|
let keyboardDOMClass;
|
||||||
let keyboardDOM;
|
let keyboardDOM;
|
||||||
@@ -287,15 +289,15 @@ class SimpleKeyboard {
|
|||||||
* Getters
|
* Getters
|
||||||
*/
|
*/
|
||||||
getOptions = (): KeyboardOptions => this.options;
|
getOptions = (): KeyboardOptions => this.options;
|
||||||
getCaretPosition = (): number => this.caretPosition;
|
getCaretPosition = (): number | null => this.caretPosition;
|
||||||
getCaretPositionEnd = (): number => this.caretPositionEnd;
|
getCaretPositionEnd = (): number | null => this.caretPositionEnd;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes the internal caret position
|
* Changes the internal caret position
|
||||||
* @param {number} position The caret's start position
|
* @param {number} position The caret's start position
|
||||||
* @param {number} positionEnd The caret's end position
|
* @param {number} positionEnd The caret's end position
|
||||||
*/
|
*/
|
||||||
setCaretPosition(position: number, endPosition = position): void {
|
setCaretPosition(position: number | null, endPosition = position): void {
|
||||||
this.caretPosition = position;
|
this.caretPosition = position;
|
||||||
this.caretPositionEnd = endPosition;
|
this.caretPositionEnd = endPosition;
|
||||||
}
|
}
|
||||||
@@ -379,8 +381,7 @@ class SimpleKeyboard {
|
|||||||
* @param {string} button The button's layout name.
|
* @param {string} button The button's layout name.
|
||||||
*/
|
*/
|
||||||
handleButtonClicked(button: string, e?: KeyboardHandlerEvent): void {
|
handleButtonClicked(button: string, e?: KeyboardHandlerEvent): void {
|
||||||
const debug = this.options.debug;
|
const { inputName = this.defaultName, debug } = this.options;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ignoring placeholder buttons
|
* Ignoring placeholder buttons
|
||||||
*/
|
*/
|
||||||
@@ -389,15 +390,14 @@ class SimpleKeyboard {
|
|||||||
/**
|
/**
|
||||||
* Creating inputName if it doesn't exist
|
* Creating inputName if it doesn't exist
|
||||||
*/
|
*/
|
||||||
if (!this.input[this.options.inputName])
|
if (!this.input[inputName]) this.input[inputName] = "";
|
||||||
this.input[this.options.inputName] = "";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculating new input
|
* Calculating new input
|
||||||
*/
|
*/
|
||||||
const updatedInput = this.utilities.getUpdatedInput(
|
const updatedInput = this.utilities.getUpdatedInput(
|
||||||
button,
|
button,
|
||||||
this.input[this.options.inputName],
|
this.input[inputName],
|
||||||
this.caretPosition,
|
this.caretPosition,
|
||||||
this.caretPositionEnd
|
this.caretPositionEnd
|
||||||
);
|
);
|
||||||
@@ -410,7 +410,7 @@ class SimpleKeyboard {
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
// If input will change as a result of this button press
|
// If input will change as a result of this button press
|
||||||
this.input[this.options.inputName] !== updatedInput &&
|
this.input[inputName] !== updatedInput &&
|
||||||
// This pertains to the "inputPattern" option:
|
// This pertains to the "inputPattern" option:
|
||||||
// If inputPattern isn't set
|
// If inputPattern isn't set
|
||||||
(!this.options.inputPattern ||
|
(!this.options.inputPattern ||
|
||||||
@@ -432,7 +432,7 @@ class SimpleKeyboard {
|
|||||||
*/
|
*/
|
||||||
const newInputValue = this.utilities.getUpdatedInput(
|
const newInputValue = this.utilities.getUpdatedInput(
|
||||||
button,
|
button,
|
||||||
this.input[this.options.inputName],
|
this.input[inputName],
|
||||||
this.caretPosition,
|
this.caretPosition,
|
||||||
this.caretPositionEnd,
|
this.caretPositionEnd,
|
||||||
true
|
true
|
||||||
@@ -483,7 +483,7 @@ class SimpleKeyboard {
|
|||||||
this.keyboardDOM
|
this.keyboardDOM
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.candidateBox.destroy();
|
this.candidateBox?.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -639,8 +639,9 @@ class SimpleKeyboard {
|
|||||||
* Clear the keyboard’s input.
|
* Clear the keyboard’s input.
|
||||||
* @param {string} [inputName] optional - the internal input to select
|
* @param {string} [inputName] optional - the internal input to select
|
||||||
*/
|
*/
|
||||||
clearInput(inputName: string): void {
|
clearInput(
|
||||||
inputName = inputName || this.options.inputName;
|
inputName: string = this.options.inputName || this.defaultName
|
||||||
|
): void {
|
||||||
this.input[inputName] = "";
|
this.input[inputName] = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -658,7 +659,10 @@ class SimpleKeyboard {
|
|||||||
* Get the keyboard’s input (You can also get it from the onChange prop).
|
* Get the keyboard’s 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 = this.options.inputName, skipSync = false): string {
|
getInput(
|
||||||
|
inputName: string = this.options.inputName || this.defaultName,
|
||||||
|
skipSync = false
|
||||||
|
): string {
|
||||||
/**
|
/**
|
||||||
* Enforce syncInstanceInputs, if set
|
* Enforce syncInstanceInputs, if set
|
||||||
*/
|
*/
|
||||||
@@ -697,7 +701,7 @@ class SimpleKeyboard {
|
|||||||
*/
|
*/
|
||||||
setInput(
|
setInput(
|
||||||
input: string,
|
input: string,
|
||||||
inputName = this.options.inputName,
|
inputName: string = this.options.inputName || this.defaultName,
|
||||||
skipSync?: boolean
|
skipSync?: boolean
|
||||||
): void {
|
): void {
|
||||||
this.input[inputName] = input;
|
this.input[inputName] = input;
|
||||||
@@ -758,19 +762,6 @@ class SimpleKeyboard {
|
|||||||
* @param {object} options The options to set
|
* @param {object} options The options to set
|
||||||
*/
|
*/
|
||||||
onSetOptions(changedOptions: string[] = []): void {
|
onSetOptions(changedOptions: string[] = []): void {
|
||||||
/**
|
|
||||||
* Changed: inputName
|
|
||||||
*/
|
|
||||||
if (changedOptions.includes("inputName")) {
|
|
||||||
/**
|
|
||||||
* inputName changed. This requires a caretPosition reset
|
|
||||||
*/
|
|
||||||
if (this.options.debug) {
|
|
||||||
console.log("inputName changed. caretPosition reset.");
|
|
||||||
}
|
|
||||||
this.setCaretPosition(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changed: layoutName
|
* Changed: layoutName
|
||||||
*/
|
*/
|
||||||
@@ -851,7 +842,7 @@ class SimpleKeyboard {
|
|||||||
* If class is already defined, we add button to class definition
|
* If class is already defined, we add button to class definition
|
||||||
*/
|
*/
|
||||||
this.options.buttonTheme.map((buttonTheme) => {
|
this.options.buttonTheme.map((buttonTheme) => {
|
||||||
if (buttonTheme.class.split(" ").includes(classNameItem)) {
|
if (buttonTheme?.class.split(" ").includes(classNameItem)) {
|
||||||
classNameFound = true;
|
classNameFound = true;
|
||||||
|
|
||||||
const buttonThemeArray = buttonTheme.buttons.split(" ");
|
const buttonThemeArray = buttonTheme.buttons.split(" ");
|
||||||
@@ -904,26 +895,28 @@ class SimpleKeyboard {
|
|||||||
) {
|
) {
|
||||||
const buttonArray = buttons.split(" ");
|
const buttonArray = buttons.split(" ");
|
||||||
buttonArray.forEach((button) => {
|
buttonArray.forEach((button) => {
|
||||||
this.options.buttonTheme.map((buttonTheme, index) => {
|
this.options?.buttonTheme?.map((buttonTheme, index) => {
|
||||||
/**
|
/**
|
||||||
* If className is set, we affect the buttons only for that class
|
* If className is set, we affect the buttons only for that class
|
||||||
* Otherwise, we afect all classes
|
* Otherwise, we afect all classes
|
||||||
*/
|
*/
|
||||||
if (
|
if (
|
||||||
(className && className.includes(buttonTheme.class)) ||
|
(buttonTheme &&
|
||||||
|
className &&
|
||||||
|
className.includes(buttonTheme.class)) ||
|
||||||
!className
|
!className
|
||||||
) {
|
) {
|
||||||
const filteredButtonArray = buttonTheme.buttons
|
const filteredButtonArray = buttonTheme?.buttons
|
||||||
.split(" ")
|
.split(" ")
|
||||||
.filter((item) => item !== button);
|
.filter((item) => item !== button);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If buttons left, return them, otherwise, remove button Theme
|
* If buttons left, return them, otherwise, remove button Theme
|
||||||
*/
|
*/
|
||||||
if (filteredButtonArray.length) {
|
if (buttonTheme && filteredButtonArray?.length) {
|
||||||
buttonTheme.buttons = filteredButtonArray.join(" ");
|
buttonTheme.buttons = filteredButtonArray.join(" ");
|
||||||
} else {
|
} else {
|
||||||
this.options.buttonTheme.splice(index, 1);
|
this.options.buttonTheme?.splice(index, 1);
|
||||||
buttonTheme = null;
|
buttonTheme = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -940,7 +933,9 @@ class SimpleKeyboard {
|
|||||||
* Get the DOM Element of a button. If there are several buttons with the same name, an array of the DOM Elements is returned.
|
* Get the DOM Element of a button. If there are several buttons with the same name, an array of the DOM Elements is returned.
|
||||||
* @param {string} button The button layout name to select
|
* @param {string} button The button layout name to select
|
||||||
*/
|
*/
|
||||||
getButtonElement(button: string): KeyboardElement | KeyboardElement[] {
|
getButtonElement(
|
||||||
|
button: string
|
||||||
|
): KeyboardElement | KeyboardElement[] | undefined {
|
||||||
let output;
|
let output;
|
||||||
|
|
||||||
const buttonArr = this.buttonElements[button];
|
const buttonArr = this.buttonElements[button];
|
||||||
@@ -969,7 +964,8 @@ class SimpleKeyboard {
|
|||||||
if (inputPatternRaw instanceof RegExp) {
|
if (inputPatternRaw instanceof RegExp) {
|
||||||
inputPattern = inputPatternRaw;
|
inputPattern = inputPatternRaw;
|
||||||
} else {
|
} else {
|
||||||
inputPattern = inputPatternRaw[this.options.inputName];
|
inputPattern =
|
||||||
|
inputPatternRaw[this.options.inputName || this.defaultName];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inputPattern && inputVal) {
|
if (inputPattern && inputVal) {
|
||||||
@@ -1077,10 +1073,11 @@ class SimpleKeyboard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(targetTagName === "textarea" || targetTagName === "input") &&
|
(targetTagName === "textarea" ||
|
||||||
["text", "search", "url", "tel", "password"].includes(
|
(targetTagName === "input" &&
|
||||||
event.target.type
|
["text", "search", "url", "tel", "password"].includes(
|
||||||
) &&
|
event.target.type
|
||||||
|
))) &&
|
||||||
!instance.options.disableCaretPositioning
|
!instance.options.disableCaretPositioning
|
||||||
) {
|
) {
|
||||||
/**
|
/**
|
||||||
@@ -1106,6 +1103,13 @@ class SimpleKeyboard {
|
|||||||
* If we toggled off disableCaretPositioning, we must ensure caretPosition doesn't persist once reactivated.
|
* If we toggled off disableCaretPositioning, we must ensure caretPosition doesn't persist once reactivated.
|
||||||
*/
|
*/
|
||||||
instance.setCaretPosition(null);
|
instance.setCaretPosition(null);
|
||||||
|
|
||||||
|
if (instance.options.debug) {
|
||||||
|
console.log(
|
||||||
|
`Caret position reset due to "${event?.type}" event`,
|
||||||
|
event
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1146,26 +1150,25 @@ class SimpleKeyboard {
|
|||||||
/**
|
/**
|
||||||
* Remove buttons
|
* Remove buttons
|
||||||
*/
|
*/
|
||||||
let deleteButton = (buttonElement: KeyboardElement) => {
|
const deleteButton = (buttonElement: KeyboardElement | null) => {
|
||||||
buttonElement.onpointerdown = null;
|
if (buttonElement) {
|
||||||
buttonElement.onpointerup = null;
|
buttonElement.onpointerdown = null;
|
||||||
buttonElement.onpointercancel = null;
|
buttonElement.onpointerup = null;
|
||||||
buttonElement.ontouchstart = null;
|
buttonElement.onpointercancel = null;
|
||||||
buttonElement.ontouchend = null;
|
buttonElement.ontouchstart = null;
|
||||||
buttonElement.ontouchcancel = null;
|
buttonElement.ontouchend = null;
|
||||||
buttonElement.onclick = null;
|
buttonElement.ontouchcancel = null;
|
||||||
buttonElement.onmousedown = null;
|
buttonElement.onclick = null;
|
||||||
buttonElement.onmouseup = null;
|
buttonElement.onmousedown = null;
|
||||||
|
buttonElement.onmouseup = null;
|
||||||
|
|
||||||
buttonElement.remove();
|
buttonElement.remove();
|
||||||
buttonElement = null;
|
buttonElement = null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.recurseButtons(deleteButton);
|
this.recurseButtons(deleteButton);
|
||||||
|
|
||||||
this.recurseButtons = null;
|
|
||||||
deleteButton = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove wrapper events
|
* Remove wrapper events
|
||||||
*/
|
*/
|
||||||
@@ -1213,6 +1216,7 @@ class SimpleKeyboard {
|
|||||||
if (Array.isArray(buttonTheme)) {
|
if (Array.isArray(buttonTheme)) {
|
||||||
buttonTheme.forEach((themeObj) => {
|
buttonTheme.forEach((themeObj) => {
|
||||||
if (
|
if (
|
||||||
|
themeObj &&
|
||||||
themeObj.class &&
|
themeObj.class &&
|
||||||
typeof themeObj.class === "string" &&
|
typeof themeObj.class === "string" &&
|
||||||
themeObj.buttons &&
|
themeObj.buttons &&
|
||||||
@@ -1336,7 +1340,7 @@ class SimpleKeyboard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeof this.options.beforeFirstRender === "function")
|
if (typeof this.options.beforeFirstRender === "function")
|
||||||
this.options.beforeFirstRender();
|
this.options.beforeFirstRender(this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify about PointerEvents usage
|
* Notify about PointerEvents usage
|
||||||
@@ -1369,7 +1373,7 @@ class SimpleKeyboard {
|
|||||||
*/
|
*/
|
||||||
beforeRender() {
|
beforeRender() {
|
||||||
if (typeof this.options.beforeRender === "function")
|
if (typeof this.options.beforeRender === "function")
|
||||||
this.options.beforeRender();
|
this.options.beforeRender(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1574,211 +1578,219 @@ class SimpleKeyboard {
|
|||||||
/**
|
/**
|
||||||
* Iterating through each row
|
* Iterating through each row
|
||||||
*/
|
*/
|
||||||
layout[this.options.layoutName].forEach((row, rIndex) => {
|
layout[this.options.layoutName || this.defaultName].forEach(
|
||||||
let rowArray = row.split(" ");
|
(row, rIndex) => {
|
||||||
|
let rowArray = row.split(" ");
|
||||||
/**
|
|
||||||
* Enforce excludeFromLayout
|
|
||||||
*/
|
|
||||||
if (this.options.excludeFromLayout[this.options.layoutName]) {
|
|
||||||
rowArray = rowArray.filter(
|
|
||||||
(buttonName) =>
|
|
||||||
!this.options.excludeFromLayout[this.options.layoutName].includes(
|
|
||||||
buttonName
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creating empty row
|
|
||||||
*/
|
|
||||||
let rowDOM = document.createElement("div");
|
|
||||||
rowDOM.className += "hg-row";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tracking container indicators in rows
|
|
||||||
*/
|
|
||||||
const containerStartIndexes: number[] = [];
|
|
||||||
const containerEndIndexes: number[] = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Iterating through each button in row
|
|
||||||
*/
|
|
||||||
rowArray.forEach((button, bIndex) => {
|
|
||||||
/**
|
|
||||||
* Check if button has a container indicator
|
|
||||||
*/
|
|
||||||
const buttonHasContainerStart =
|
|
||||||
!disableRowButtonContainers &&
|
|
||||||
typeof button === "string" &&
|
|
||||||
button.length > 1 &&
|
|
||||||
button.indexOf("[") === 0;
|
|
||||||
|
|
||||||
const buttonHasContainerEnd =
|
|
||||||
!disableRowButtonContainers &&
|
|
||||||
typeof button === "string" &&
|
|
||||||
button.length > 1 &&
|
|
||||||
button.indexOf("]") === button.length - 1;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save container start index, if applicable
|
* Enforce excludeFromLayout
|
||||||
*/
|
*/
|
||||||
if (buttonHasContainerStart) {
|
|
||||||
containerStartIndexes.push(bIndex);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removing indicator
|
|
||||||
*/
|
|
||||||
button = button.replace(/\[/g, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buttonHasContainerEnd) {
|
|
||||||
containerEndIndexes.push(bIndex);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removing indicator
|
|
||||||
*/
|
|
||||||
button = button.replace(/\]/g, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processing button options
|
|
||||||
*/
|
|
||||||
const fctBtnClass = this.utilities.getButtonClass(button);
|
|
||||||
const buttonDisplayName = this.utilities.getButtonDisplayName(
|
|
||||||
button,
|
|
||||||
this.options.display,
|
|
||||||
this.options.mergeDisplay
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creating button
|
|
||||||
*/
|
|
||||||
const buttonType = this.options.useButtonTag ? "button" : "div";
|
|
||||||
const buttonDOM = document.createElement(buttonType);
|
|
||||||
buttonDOM.className += `hg-button ${fctBtnClass}`;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adding buttonTheme
|
|
||||||
*/
|
|
||||||
buttonDOM.classList.add(...this.getButtonThemeClasses(button));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adding buttonAttributes
|
|
||||||
*/
|
|
||||||
this.setDOMButtonAttributes(
|
|
||||||
button,
|
|
||||||
(attribute: string, value: string) => {
|
|
||||||
buttonDOM.setAttribute(attribute, value);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
this.activeButtonClass = "hg-activeButton";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle button click event
|
|
||||||
*/
|
|
||||||
/* istanbul ignore next */
|
|
||||||
if (
|
if (
|
||||||
this.utilities.pointerEventsSupported() &&
|
this.options.excludeFromLayout &&
|
||||||
!useTouchEvents &&
|
this.options.excludeFromLayout[
|
||||||
!useMouseEvents
|
this.options.layoutName || this.defaultName
|
||||||
|
]
|
||||||
) {
|
) {
|
||||||
|
rowArray = rowArray.filter(
|
||||||
|
(buttonName) =>
|
||||||
|
this.options.excludeFromLayout &&
|
||||||
|
!this.options.excludeFromLayout[
|
||||||
|
this.options.layoutName || this.defaultName
|
||||||
|
].includes(buttonName)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creating empty row
|
||||||
|
*/
|
||||||
|
let rowDOM = document.createElement("div");
|
||||||
|
rowDOM.className += "hg-row";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracking container indicators in rows
|
||||||
|
*/
|
||||||
|
const containerStartIndexes: number[] = [];
|
||||||
|
const containerEndIndexes: number[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterating through each button in row
|
||||||
|
*/
|
||||||
|
rowArray.forEach((button, bIndex) => {
|
||||||
/**
|
/**
|
||||||
* Handle PointerEvents
|
* Check if button has a container indicator
|
||||||
*/
|
*/
|
||||||
buttonDOM.onpointerdown = (e: KeyboardHandlerEvent) => {
|
const buttonHasContainerStart =
|
||||||
this.handleButtonClicked(button, e);
|
!disableRowButtonContainers &&
|
||||||
this.handleButtonMouseDown(button, e);
|
typeof button === "string" &&
|
||||||
};
|
button.length > 1 &&
|
||||||
buttonDOM.onpointerup = (e: KeyboardHandlerEvent) => {
|
button.indexOf("[") === 0;
|
||||||
this.handleButtonMouseUp(button, e);
|
|
||||||
};
|
const buttonHasContainerEnd =
|
||||||
buttonDOM.onpointercancel = (e: KeyboardHandlerEvent) => {
|
!disableRowButtonContainers &&
|
||||||
this.handleButtonMouseUp(button, e);
|
typeof button === "string" &&
|
||||||
};
|
button.length > 1 &&
|
||||||
} else {
|
button.indexOf("]") === button.length - 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fallback for browsers not supporting PointerEvents
|
* Save container start index, if applicable
|
||||||
*/
|
*/
|
||||||
if (useTouchEvents) {
|
if (buttonHasContainerStart) {
|
||||||
|
containerStartIndexes.push(bIndex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle touch events
|
* Removing indicator
|
||||||
*/
|
*/
|
||||||
buttonDOM.ontouchstart = (e: KeyboardHandlerEvent) => {
|
button = button.replace(/\[/g, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buttonHasContainerEnd) {
|
||||||
|
containerEndIndexes.push(bIndex);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removing indicator
|
||||||
|
*/
|
||||||
|
button = button.replace(/\]/g, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processing button options
|
||||||
|
*/
|
||||||
|
const fctBtnClass = this.utilities.getButtonClass(button);
|
||||||
|
const buttonDisplayName = this.utilities.getButtonDisplayName(
|
||||||
|
button,
|
||||||
|
this.options.display,
|
||||||
|
this.options.mergeDisplay
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creating button
|
||||||
|
*/
|
||||||
|
const buttonType = this.options.useButtonTag ? "button" : "div";
|
||||||
|
const buttonDOM = document.createElement(buttonType);
|
||||||
|
buttonDOM.className += `hg-button ${fctBtnClass}`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adding buttonTheme
|
||||||
|
*/
|
||||||
|
buttonDOM.classList.add(...this.getButtonThemeClasses(button));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adding buttonAttributes
|
||||||
|
*/
|
||||||
|
this.setDOMButtonAttributes(
|
||||||
|
button,
|
||||||
|
(attribute: string, value: string) => {
|
||||||
|
buttonDOM.setAttribute(attribute, value);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
this.activeButtonClass = "hg-activeButton";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle button click event
|
||||||
|
*/
|
||||||
|
/* istanbul ignore next */
|
||||||
|
if (
|
||||||
|
this.utilities.pointerEventsSupported() &&
|
||||||
|
!useTouchEvents &&
|
||||||
|
!useMouseEvents
|
||||||
|
) {
|
||||||
|
/**
|
||||||
|
* Handle PointerEvents
|
||||||
|
*/
|
||||||
|
buttonDOM.onpointerdown = (e: KeyboardHandlerEvent) => {
|
||||||
this.handleButtonClicked(button, e);
|
this.handleButtonClicked(button, e);
|
||||||
this.handleButtonMouseDown(button, e);
|
this.handleButtonMouseDown(button, e);
|
||||||
};
|
};
|
||||||
buttonDOM.ontouchend = (e: KeyboardHandlerEvent) => {
|
buttonDOM.onpointerup = (e: KeyboardHandlerEvent) => {
|
||||||
this.handleButtonMouseUp(button, e);
|
this.handleButtonMouseUp(button, e);
|
||||||
};
|
};
|
||||||
buttonDOM.ontouchcancel = (e: KeyboardHandlerEvent) => {
|
buttonDOM.onpointercancel = (e: KeyboardHandlerEvent) => {
|
||||||
this.handleButtonMouseUp(button, e);
|
this.handleButtonMouseUp(button, e);
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
/**
|
/**
|
||||||
* Handle mouse events
|
* Fallback for browsers not supporting PointerEvents
|
||||||
*/
|
*/
|
||||||
buttonDOM.onclick = (e: KeyboardHandlerEvent) => {
|
if (useTouchEvents) {
|
||||||
this.isMouseHold = false;
|
/**
|
||||||
this.handleButtonClicked(button, e);
|
* Handle touch events
|
||||||
};
|
*/
|
||||||
buttonDOM.onmousedown = (e: KeyboardHandlerEvent) => {
|
buttonDOM.ontouchstart = (e: KeyboardHandlerEvent) => {
|
||||||
this.handleButtonMouseDown(button, e);
|
this.handleButtonClicked(button, e);
|
||||||
};
|
this.handleButtonMouseDown(button, e);
|
||||||
buttonDOM.onmouseup = (e: KeyboardHandlerEvent) => {
|
};
|
||||||
this.handleButtonMouseUp(button, e);
|
buttonDOM.ontouchend = (e: KeyboardHandlerEvent) => {
|
||||||
};
|
this.handleButtonMouseUp(button, e);
|
||||||
|
};
|
||||||
|
buttonDOM.ontouchcancel = (e: KeyboardHandlerEvent) => {
|
||||||
|
this.handleButtonMouseUp(button, e);
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
/**
|
||||||
|
* Handle mouse events
|
||||||
|
*/
|
||||||
|
buttonDOM.onclick = (e: KeyboardHandlerEvent) => {
|
||||||
|
this.isMouseHold = false;
|
||||||
|
this.handleButtonClicked(button, e);
|
||||||
|
};
|
||||||
|
buttonDOM.onmousedown = (e: KeyboardHandlerEvent) => {
|
||||||
|
this.handleButtonMouseDown(button, e);
|
||||||
|
};
|
||||||
|
buttonDOM.onmouseup = (e: KeyboardHandlerEvent) => {
|
||||||
|
this.handleButtonMouseUp(button, e);
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* Adding identifier
|
||||||
|
*/
|
||||||
|
buttonDOM.setAttribute("data-skBtn", button);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adding unique id
|
||||||
|
* Since there's no limit on spawning same buttons, the unique id ensures you can style every button
|
||||||
|
*/
|
||||||
|
const buttonUID = `${this.options.layoutName}-r${rIndex}b${bIndex}`;
|
||||||
|
buttonDOM.setAttribute("data-skBtnUID", buttonUID);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adding button label to button
|
||||||
|
*/
|
||||||
|
const buttonSpanDOM = document.createElement("span");
|
||||||
|
buttonSpanDOM.innerHTML = buttonDisplayName;
|
||||||
|
buttonDOM.appendChild(buttonSpanDOM);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adding to buttonElements
|
||||||
|
*/
|
||||||
|
if (!this.buttonElements[button]) this.buttonElements[button] = [];
|
||||||
|
|
||||||
|
this.buttonElements[button].push(buttonDOM);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appending button to row
|
||||||
|
*/
|
||||||
|
rowDOM.appendChild(buttonDOM);
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adding identifier
|
* Parse containers in row
|
||||||
*/
|
*/
|
||||||
buttonDOM.setAttribute("data-skBtn", button);
|
rowDOM = this.parseRowDOMContainers(
|
||||||
|
rowDOM,
|
||||||
|
rIndex,
|
||||||
|
containerStartIndexes,
|
||||||
|
containerEndIndexes
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adding unique id
|
* Appending row to hg-rows
|
||||||
* Since there's no limit on spawning same buttons, the unique id ensures you can style every button
|
|
||||||
*/
|
*/
|
||||||
const buttonUID = `${this.options.layoutName}-r${rIndex}b${bIndex}`;
|
this.keyboardRowsDOM.appendChild(rowDOM);
|
||||||
buttonDOM.setAttribute("data-skBtnUID", buttonUID);
|
}
|
||||||
|
);
|
||||||
/**
|
|
||||||
* Adding button label to button
|
|
||||||
*/
|
|
||||||
const buttonSpanDOM = document.createElement("span");
|
|
||||||
buttonSpanDOM.innerHTML = buttonDisplayName;
|
|
||||||
buttonDOM.appendChild(buttonSpanDOM);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adding to buttonElements
|
|
||||||
*/
|
|
||||||
if (!this.buttonElements[button]) this.buttonElements[button] = [];
|
|
||||||
|
|
||||||
this.buttonElements[button].push(buttonDOM);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Appending button to row
|
|
||||||
*/
|
|
||||||
rowDOM.appendChild(buttonDOM);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse containers in row
|
|
||||||
*/
|
|
||||||
rowDOM = this.parseRowDOMContainers(
|
|
||||||
rowDOM,
|
|
||||||
rIndex,
|
|
||||||
containerStartIndexes,
|
|
||||||
containerEndIndexes
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Appending row to hg-rows
|
|
||||||
*/
|
|
||||||
this.keyboardRowsDOM.appendChild(rowDOM);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Appending row to keyboard
|
* Appending row to keyboard
|
||||||
@@ -1806,7 +1818,7 @@ class SimpleKeyboard {
|
|||||||
!useMouseEvents
|
!useMouseEvents
|
||||||
) {
|
) {
|
||||||
document.onpointerup = (e: KeyboardHandlerEvent) =>
|
document.onpointerup = (e: KeyboardHandlerEvent) =>
|
||||||
this.handleButtonMouseUp(null, e);
|
this.handleButtonMouseUp(undefined, e);
|
||||||
this.keyboardDOM.onpointerdown = (e: KeyboardHandlerEvent) =>
|
this.keyboardDOM.onpointerdown = (e: KeyboardHandlerEvent) =>
|
||||||
this.handleKeyboardContainerMouseDown(e);
|
this.handleKeyboardContainerMouseDown(e);
|
||||||
} else if (useTouchEvents) {
|
} else if (useTouchEvents) {
|
||||||
@@ -1814,9 +1826,9 @@ class SimpleKeyboard {
|
|||||||
* Handling ontouchend, ontouchcancel
|
* Handling ontouchend, ontouchcancel
|
||||||
*/
|
*/
|
||||||
document.ontouchend = (e: KeyboardHandlerEvent) =>
|
document.ontouchend = (e: KeyboardHandlerEvent) =>
|
||||||
this.handleButtonMouseUp(null, e);
|
this.handleButtonMouseUp(undefined, e);
|
||||||
document.ontouchcancel = (e: KeyboardHandlerEvent) =>
|
document.ontouchcancel = (e: KeyboardHandlerEvent) =>
|
||||||
this.handleButtonMouseUp(null, e);
|
this.handleButtonMouseUp(undefined, e);
|
||||||
|
|
||||||
this.keyboardDOM.ontouchstart = (e: KeyboardHandlerEvent) =>
|
this.keyboardDOM.ontouchstart = (e: KeyboardHandlerEvent) =>
|
||||||
this.handleKeyboardContainerMouseDown(e);
|
this.handleKeyboardContainerMouseDown(e);
|
||||||
@@ -1825,7 +1837,7 @@ class SimpleKeyboard {
|
|||||||
* Handling mouseup
|
* Handling mouseup
|
||||||
*/
|
*/
|
||||||
document.onmouseup = (e: KeyboardHandlerEvent) =>
|
document.onmouseup = (e: KeyboardHandlerEvent) =>
|
||||||
this.handleButtonMouseUp(null, e);
|
this.handleButtonMouseUp(undefined, e);
|
||||||
this.keyboardDOM.onmousedown = (e: KeyboardHandlerEvent) =>
|
this.keyboardDOM.onmousedown = (e: KeyboardHandlerEvent) =>
|
||||||
this.handleKeyboardContainerMouseDown(e);
|
this.handleKeyboardContainerMouseDown(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1138,27 +1138,6 @@ it('Keyboard disableRowButtonContainers will bypass parseRowDOMContainers', () =
|
|||||||
expect(containers.length).toBe(0);
|
expect(containers.length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Keyboard inputName change will trigget caretPosition reset', () => {
|
|
||||||
const keyboard = new Keyboard();
|
|
||||||
|
|
||||||
keyboard.setCaretPosition(0);
|
|
||||||
|
|
||||||
keyboard.getButtonElement("q").onpointerdown();
|
|
||||||
keyboard.getButtonElement("1").onpointerdown();
|
|
||||||
|
|
||||||
expect(keyboard.getCaretPosition()).toBe(2);
|
|
||||||
|
|
||||||
keyboard.setOptions({
|
|
||||||
inputName: "myInput"
|
|
||||||
});
|
|
||||||
|
|
||||||
keyboard.getButtonElement("q").onpointerdown();
|
|
||||||
keyboard.getButtonElement("1").onpointerdown();
|
|
||||||
keyboard.getButtonElement("b").onpointerdown();
|
|
||||||
|
|
||||||
expect(keyboard.getCaretPosition()).toBe(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Keyboard destroy will work', () => {
|
it('Keyboard destroy will work', () => {
|
||||||
const keyboard = new Keyboard();
|
const keyboard = new Keyboard();
|
||||||
keyboard.destroy();
|
keyboard.destroy();
|
||||||
|
|||||||
+10
-5
@@ -6,10 +6,10 @@ export interface KeyboardLayoutObject {
|
|||||||
[key: string]: string[];
|
[key: string]: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface KeyboardButtonTheme {
|
export type KeyboardButtonTheme = {
|
||||||
class: string;
|
class: string;
|
||||||
buttons: string;
|
buttons: string;
|
||||||
}
|
} | null;
|
||||||
|
|
||||||
export interface KeyboardButtonAttributes {
|
export interface KeyboardButtonAttributes {
|
||||||
attribute: string;
|
attribute: string;
|
||||||
@@ -44,7 +44,7 @@ export type CandidateBoxRenderParams = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type KeyboardElement = HTMLDivElement | HTMLButtonElement;
|
export type KeyboardElement = HTMLDivElement | HTMLButtonElement;
|
||||||
export type KeyboardHandlerEvent = PointerEvent & TouchEvent & KeyboardEvent & { target: HTMLDivElement & HTMLInputElement };
|
export type KeyboardHandlerEvent = any;
|
||||||
|
|
||||||
export interface KeyboardButtonElements {
|
export interface KeyboardButtonElements {
|
||||||
[key: string]: KeyboardElement[]
|
[key: string]: KeyboardElement[]
|
||||||
@@ -52,8 +52,13 @@ export interface KeyboardButtonElements {
|
|||||||
|
|
||||||
export interface UtilitiesParams {
|
export interface UtilitiesParams {
|
||||||
getOptions: () => KeyboardOptions;
|
getOptions: () => KeyboardOptions;
|
||||||
getCaretPosition: () => number;
|
getCaretPosition: () => number | null;
|
||||||
getCaretPositionEnd: () => number;
|
getCaretPositionEnd: () => number | null;
|
||||||
|
dispatch: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PhysicalKeyboardParams {
|
||||||
|
getOptions: () => KeyboardOptions;
|
||||||
dispatch: any;
|
dispatch: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { KeyboardOptions, UtilitiesParams } from "../interfaces";
|
import { KeyboardOptions, PhysicalKeyboardParams } from "../interfaces";
|
||||||
import Utilities from "../services/Utilities";
|
import Utilities from "../services/Utilities";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11,7 +11,7 @@ class PhysicalKeyboard {
|
|||||||
/**
|
/**
|
||||||
* Creates an instance of the PhysicalKeyboard service
|
* Creates an instance of the PhysicalKeyboard service
|
||||||
*/
|
*/
|
||||||
constructor({ dispatch, getOptions }: Partial<UtilitiesParams>) {
|
constructor({ dispatch, getOptions }: PhysicalKeyboardParams) {
|
||||||
/**
|
/**
|
||||||
* @type {object} A simple-keyboard instance
|
* @type {object} A simple-keyboard instance
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ import { KeyboardOptions, UtilitiesParams } from "../interfaces";
|
|||||||
*/
|
*/
|
||||||
class Utilities {
|
class Utilities {
|
||||||
getOptions: () => KeyboardOptions;
|
getOptions: () => KeyboardOptions;
|
||||||
getCaretPosition: () => number;
|
getCaretPosition: () => number | null;
|
||||||
getCaretPositionEnd: () => number;
|
getCaretPositionEnd: () => number | null;
|
||||||
dispatch: any;
|
dispatch: any;
|
||||||
maxLengthReached: boolean;
|
maxLengthReached!: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an instance of the Utility service
|
* Creates an instance of the Utility service
|
||||||
@@ -106,6 +106,7 @@ class Utilities {
|
|||||||
"{home}": "home",
|
"{home}": "home",
|
||||||
"{pageup}": "up",
|
"{pageup}": "up",
|
||||||
"{delete}": "del",
|
"{delete}": "del",
|
||||||
|
"{forwarddelete}": "del",
|
||||||
"{end}": "end",
|
"{end}": "end",
|
||||||
"{pagedown}": "down",
|
"{pagedown}": "down",
|
||||||
"{numpadmultiply}": "*",
|
"{numpadmultiply}": "*",
|
||||||
@@ -177,6 +178,11 @@ class Utilities {
|
|||||||
output.length > 0
|
output.length > 0
|
||||||
) {
|
) {
|
||||||
output = this.removeAt(output, ...commonParams);
|
output = this.removeAt(output, ...commonParams);
|
||||||
|
} else if (
|
||||||
|
(button === "{delete}" || button === "{forwarddelete}") &&
|
||||||
|
output.length > 0
|
||||||
|
) {
|
||||||
|
output = this.removeForwardsAt(output, ...commonParams);
|
||||||
} else if (button === "{space}")
|
} else if (button === "{space}")
|
||||||
output = this.addStringAt(output, " ", ...commonParams);
|
output = this.addStringAt(output, " ", ...commonParams);
|
||||||
else if (
|
else if (
|
||||||
@@ -243,10 +249,12 @@ class Utilities {
|
|||||||
const options = this.getOptions();
|
const options = this.getOptions();
|
||||||
let caretPosition = this.getCaretPosition();
|
let caretPosition = this.getCaretPosition();
|
||||||
|
|
||||||
if (minus) {
|
if (caretPosition != null) {
|
||||||
if (caretPosition > 0) caretPosition = caretPosition - length;
|
if (minus) {
|
||||||
} else {
|
if (caretPosition > 0) caretPosition = caretPosition - length;
|
||||||
caretPosition = caretPosition + length;
|
} else {
|
||||||
|
caretPosition = caretPosition + length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.debug) {
|
if (options.debug) {
|
||||||
@@ -292,7 +300,7 @@ class Utilities {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes an amount of characters at a given position
|
* Removes an amount of characters before a given position
|
||||||
*
|
*
|
||||||
* @param {string} source The source input
|
* @param {string} source The source input
|
||||||
* @param {number} position The (cursor) position from where the characters should be removed
|
* @param {number} position The (cursor) position from where the characters should be removed
|
||||||
@@ -353,6 +361,65 @@ class Utilities {
|
|||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes an amount of characters after a given position
|
||||||
|
*
|
||||||
|
* @param {string} source The source input
|
||||||
|
* @param {number} position The (cursor) position from where the characters should be removed
|
||||||
|
*/
|
||||||
|
removeForwardsAt(
|
||||||
|
source: string,
|
||||||
|
position = source.length,
|
||||||
|
positionEnd = source.length,
|
||||||
|
moveCaret = false
|
||||||
|
) {
|
||||||
|
if (position === 0 && positionEnd === 0) {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
let output;
|
||||||
|
|
||||||
|
if (position === positionEnd) {
|
||||||
|
let nextTwoChars;
|
||||||
|
let emojiMatched;
|
||||||
|
const emojiMatchedReg = /([\uD800-\uDBFF][\uDC00-\uDFFF])/g;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emojis are made out of two characters, so we must take a custom approach to trim them.
|
||||||
|
* For more info: https://mathiasbynens.be/notes/javascript-unicode
|
||||||
|
*/
|
||||||
|
if (position && position >= 0) {
|
||||||
|
nextTwoChars = source.substring(position, position + 2);
|
||||||
|
emojiMatched = nextTwoChars.match(emojiMatchedReg);
|
||||||
|
|
||||||
|
if (emojiMatched) {
|
||||||
|
output = source.substr(0, position) + source.substr(position + 2);
|
||||||
|
} else {
|
||||||
|
output = source.substr(0, position) + source.substr(position + 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nextTwoChars = source.slice(2);
|
||||||
|
emojiMatched = nextTwoChars.match(emojiMatchedReg);
|
||||||
|
|
||||||
|
if (emojiMatched) {
|
||||||
|
output = source.slice(0, 2);
|
||||||
|
} else {
|
||||||
|
output = source.slice(0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
output = source.slice(0, position) + source.slice(positionEnd);
|
||||||
|
if (moveCaret) {
|
||||||
|
this.dispatch((instance: any) => {
|
||||||
|
instance.setCaretPosition(position);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether the maxLength has been reached. This function is called when the maxLength option it set.
|
* Determines whether the maxLength has been reached. This function is called when the maxLength option it set.
|
||||||
*
|
*
|
||||||
@@ -362,7 +429,7 @@ class Utilities {
|
|||||||
handleMaxLength(inputObj: KeyboardInput, updatedInput: string) {
|
handleMaxLength(inputObj: KeyboardInput, updatedInput: string) {
|
||||||
const options = this.getOptions();
|
const options = this.getOptions();
|
||||||
const maxLength = options.maxLength;
|
const maxLength = options.maxLength;
|
||||||
const currentInput = inputObj[options.inputName];
|
const currentInput = inputObj[options.inputName || "default"];
|
||||||
const condition = updatedInput.length - 1 >= maxLength;
|
const condition = updatedInput.length - 1 >= maxLength;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -393,7 +460,8 @@ class Utilities {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeof maxLength === "object") {
|
if (typeof maxLength === "object") {
|
||||||
const condition = updatedInput.length - 1 >= maxLength[options.inputName];
|
const condition =
|
||||||
|
updatedInput.length - 1 >= maxLength[options.inputName || "default"];
|
||||||
|
|
||||||
if (options.debug) {
|
if (options.debug) {
|
||||||
console.log("maxLength (obj) reached:", condition);
|
console.log("maxLength (obj) reached:", condition);
|
||||||
@@ -451,7 +519,7 @@ class Utilities {
|
|||||||
* @param {string} str The string to transform.
|
* @param {string} str The string to transform.
|
||||||
*/
|
*/
|
||||||
camelCase(str: string): string {
|
camelCase(str: string): string {
|
||||||
if (!str) return;
|
if (!str) return "";
|
||||||
|
|
||||||
return str
|
return str
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
|
|||||||
@@ -34,6 +34,16 @@ it('Keyboard {bksp} button will work', () => {
|
|||||||
expect(output).toBe("tes");
|
expect(output).toBe("tes");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Keyboard {delete} button will work', () => {
|
||||||
|
setDOM();
|
||||||
|
|
||||||
|
const keyboard = new Keyboard();
|
||||||
|
|
||||||
|
const output = keyboard.utilities.getUpdatedInput("{delete}", "test", 1);
|
||||||
|
|
||||||
|
expect(output).toBe("tst");
|
||||||
|
});
|
||||||
|
|
||||||
it('Keyboard {space} button will work', () => {
|
it('Keyboard {space} button will work', () => {
|
||||||
setDOM();
|
setDOM();
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -11,7 +11,8 @@
|
|||||||
"suppressImplicitAnyIndexErrors": true,
|
"suppressImplicitAnyIndexErrors": true,
|
||||||
"lib": ["es2020", "dom"],
|
"lib": ["es2020", "dom"],
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"downlevelIteration": true
|
"downlevelIteration": true,
|
||||||
|
"strict": true
|
||||||
},
|
},
|
||||||
"include": ["src/lib"],
|
"include": ["src/lib"],
|
||||||
"exclude": ["src/lib/**/tests"],
|
"exclude": ["src/lib/**/tests"],
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ const banner = `
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
mode: "production",
|
mode: "production",
|
||||||
entry: './src/lib/index.ts',
|
entry: './src/lib/index.ts',
|
||||||
|
target: 'es5',
|
||||||
output: {
|
output: {
|
||||||
filename: 'index.js',
|
filename: 'index.js',
|
||||||
path: path.resolve(__dirname, 'build'),
|
path: path.resolve(__dirname, 'build'),
|
||||||
|
|||||||
Reference in New Issue
Block a user