Compare commits

...

38 Commits

Author SHA1 Message Date
Francisco Hodge
effee00b87 Added new inputPattern option 2019-01-24 23:04:59 -05:00
Francisco Hodge
90b408eff6 Tests update 2019-01-24 23:03:48 -05:00
Francisco Hodge
21fa732b1f Types update 2019-01-24 23:03:23 -05:00
Francisco Hodge
80f4307c36 Build update 2019-01-24 23:03:14 -05:00
Francisco Hodge
681bb3d0ee npm update 2019-01-24 23:02:59 -05:00
Francisco Hodge
e1fa685c6c Merge branch 'master' of https://github.com/hodgef/simple-keyboard 2019-01-17 18:37:07 -05:00
Francisco Hodge
2de7154128 npm update 2019-01-17 18:36:48 -05:00
Francisco Hodge
c9afe43f5b Build update 2019-01-17 18:36:36 -05:00
Francisco Hodge
c59f819db9 Tests update 2019-01-17 18:36:19 -05:00
Francisco Hodge
1f9efb0c66 Ensure caretPosition is unset on disableCaretPositioning 2019-01-17 18:36:09 -05:00
Francisco Hodge
32cbce8c8a Update issue templates 2019-01-17 09:20:47 -05:00
Francisco Hodge
6c2236f762 Adding types for disableCaretPositioning option 2019-01-16 19:38:42 -05:00
Francisco Hodge
23a50e6f44 Updated devDependencies 2019-01-06 15:44:07 -05:00
Francisco Hodge
c316d493c7 Tests update 2018-12-27 13:46:15 -05:00
Francisco Hodge
70e7635f25 npm update 2018-12-27 13:38:38 -05:00
Francisco Hodge
f5b73b09e7 Merge pull request #45 from mkusher/patch-1
fixed camelCase function
2018-12-27 13:33:09 -05:00
Aleh Kashnikau
7432e01740 fixed camelCase function
Added check for empty word
2018-12-27 21:29:05 +03:00
Francisco Hodge
459ab71c45 npm update 2018-12-24 13:31:13 -05:00
Francisco Hodge
a5c177e41c Specifying layout class on keyboard element 2018-12-24 13:30:52 -05:00
Francisco Hodge
d382945de7 Updated devDependencies 2018-12-23 17:42:02 -05:00
Francisco Hodge
4335f477a1 Adding new option: useButtonTag 2018-12-14 00:28:18 -05:00
Francisco Hodge
d03f00c0d1 Updated devDependencies 2018-12-08 15:49:33 -05:00
Francisco Hodge
9cea07dd41 Merge pull request #41 from armno/fix-incorrect-return-type-definition
[Angular] Fix return type of getButtonElement()
2018-12-04 20:11:10 -05:00
Francisco Hodge
efe18e7240 Build update 2018-12-04 20:06:52 -05:00
Francisco Hodge
82e242a806 Modified getInput return type 2018-12-04 20:06:32 -05:00
Armno
4a9d485d5b add return type for getButtonElement in type definition file 2018-12-04 10:42:05 +07:00
Francisco Hodge
6ffd2e77ad Improved Angular types support 2018-12-02 14:48:46 -05:00
Francisco Hodge
7753bc5ba3 Build update 2018-11-28 09:04:10 -05:00
Francisco Hodge
9c4fa00363 Merge pull request #40 from armno/master
Add type definition file for TypeScript
2018-11-28 08:58:36 -05:00
Francisco Hodge
251af057d8 npm update 2018-11-28 08:53:06 -05:00
Francisco Hodge
e60574d56d Build update 2018-11-28 08:52:58 -05:00
Francisco Hodge
b3b482e864 Copy index.d.ts to build folder on build 2018-11-28 08:52:27 -05:00
Armno
ff037ad5b7 remove exporting KeyboardOptions interface 2018-11-28 12:43:13 +07:00
Armno
ede2ce04b1 add overloaded constructor type definition 2018-11-28 11:56:00 +07:00
Armno
10380099e6 add more types 2018-11-28 11:20:32 +07:00
Armno
058b6774da Merge remote-tracking branch 'upstream/master' 2018-11-28 09:17:25 +07:00
Armno
b5cbfa780b add public methods type definitions 2018-11-27 23:43:20 +07:00
Armno
5c40dd3109 WIP: create type definition file 2018-11-27 19:57:08 +07:00
19 changed files with 1831 additions and 1231 deletions

View File

@@ -1,6 +1,9 @@
---
name: Bug report
about: Create a report to help improve simple-keyboard
title: ''
labels: ''
assignees: hodgef
---
@@ -8,7 +11,7 @@ about: Create a report to help improve simple-keyboard
As some bugs have been addressed in later versions, please ensure you are running the latest.
**Describe the bug**
A clear and concise description of what the bug is.
A clear and concise description of what the bug is. Providing a [sandbox example](https://codesandbox.io/s/vanilla) or code depicting the issue is important, as this will help us reproduce the issue.
**Screenshots**
If applicable, add screenshots to help explain your problem.

View File

@@ -1,6 +1,9 @@
---
name: Feature request
about: Suggest an idea you'd like to see in simple-keyboard
title: ''
labels: ''
assignees: ''
---

View File

@@ -1,6 +1,6 @@
/*!
*
* simple-keyboard v2.11.5
* simple-keyboard v2.14.0
* https://github.com/hodgef/simple-keyboard
*
* Copyright (c) Francisco Hodge (https://github.com/hodgef)
@@ -8,5 +8,5 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/body,html{margin:0;padding:0}.simple-keyboard{font-family:HelveticaNeue-Light,Helvetica Neue Light,Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif;width:100%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;box-sizing:border-box;overflow:hidden;touch-action:manipulation}.simple-keyboard .hg-row{display:flex}.simple-keyboard .hg-row:not(:last-child){margin-bottom:5px}.simple-keyboard .hg-row .hg-button:not(:last-child){margin-right:5px}.simple-keyboard .hg-button{display:inline-block;flex-grow:1;cursor:pointer}.hg-standardBtn{max-width:100px}.simple-keyboard.hg-theme-default{background-color:rgba(0,0,0,.1);padding:5px;border-radius:5px}.simple-keyboard.hg-theme-default .hg-button{box-shadow:0 0 3px -1px rgba(0,0,0,.3);height:40px;border-radius:5px;box-sizing:border-box;padding:5px;background:#fff;border-bottom:1px solid #b5b5b5;cursor:pointer;display:flex;align-items:center;justify-content:center}.simple-keyboard.hg-theme-default .hg-button:active{background:#e4e4e4}.simple-keyboard.hg-theme-default.hg-layout-numeric .hg-button{width:33.3%;height:60px;align-items:center;display:flex;justify-content:center}.simple-keyboard.hg-theme-default .hg-button.hg-button-numpadadd,.simple-keyboard.hg-theme-default .hg-button.hg-button-numpadenter{height:85px}.simple-keyboard.hg-theme-default .hg-button.hg-button-numpad0{width:105px}.simple-keyboard.hg-theme-default .hg-button.hg-button-com{max-width:85px}.simple-keyboard.hg-theme-default .hg-button.hg-standardBtn.hg-button-at{max-width:45px}.simple-keyboard.hg-theme-default .hg-button.hg-selectedButton{background:rgba(5,25,70,.53);color:#fff}.simple-keyboard.hg-theme-default .hg-button.hg-standardBtn[data-skbtn=".com"]{max-width:82px}.simple-keyboard.hg-theme-default .hg-button.hg-standardBtn[data-skbtn="@"]{max-width:60px}
*/body,html{margin:0;padding:0}.simple-keyboard{font-family:HelveticaNeue-Light,Helvetica Neue Light,Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif;width:100%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;box-sizing:border-box;overflow:hidden;touch-action:manipulation}.simple-keyboard .hg-row{display:flex}.simple-keyboard .hg-row:not(:last-child){margin-bottom:5px}.simple-keyboard .hg-row .hg-button:not(:last-child){margin-right:5px}.simple-keyboard .hg-button{display:inline-block;flex-grow:1;cursor:pointer}.hg-standardBtn{max-width:100px}.simple-keyboard.hg-theme-default{background-color:rgba(0,0,0,.1);padding:5px;border-radius:5px}.simple-keyboard.hg-theme-default .hg-button{box-shadow:0 0 3px -1px rgba(0,0,0,.3);height:40px;border-radius:5px;box-sizing:border-box;padding:5px;background:#fff;border-bottom:1px solid #b5b5b5;cursor:pointer;display:flex;align-items:center;justify-content:center}.simple-keyboard button.hg-button{border-width:0;outline:0;font-size:inherit}.simple-keyboard.hg-theme-default .hg-button:active{background:#e4e4e4}.simple-keyboard.hg-theme-default.hg-layout-numeric .hg-button{width:33.3%;height:60px;align-items:center;display:flex;justify-content:center}.simple-keyboard.hg-theme-default .hg-button.hg-button-numpadadd,.simple-keyboard.hg-theme-default .hg-button.hg-button-numpadenter{height:85px}.simple-keyboard.hg-theme-default .hg-button.hg-button-numpad0{width:105px}.simple-keyboard.hg-theme-default .hg-button.hg-button-com{max-width:85px}.simple-keyboard.hg-theme-default .hg-button.hg-standardBtn.hg-button-at{max-width:45px}.simple-keyboard.hg-theme-default .hg-button.hg-selectedButton{background:rgba(5,25,70,.53);color:#fff}.simple-keyboard.hg-theme-default .hg-button.hg-standardBtn[data-skbtn=".com"]{max-width:82px}.simple-keyboard.hg-theme-default .hg-button.hg-standardBtn[data-skbtn="@"]{max-width:60px}
/*# sourceMappingURL=index.css.map */

File diff suppressed because one or more lines are too long

199
build/index.d.ts vendored Normal file
View File

@@ -0,0 +1,199 @@
declare module 'simple-keyboard' {
interface KeyboardLayoutObject {
default: string[];
shift?: string[];
}
interface KeyboardButtonTheme {
class: string;
buttons: string;
}
interface KeyboardOptions {
/**
* Modify the keyboard layout.
*/
layout?: KeyboardLayoutObject;
/**
* Specifies which layout should be used.
*/
layoutName?: string;
/**
* Replaces variable buttons (such as `{bksp}`) with a human-friendly name (e.g.: `backspace`).
*/
display?: { [button: string]: string };
/**
* By default, when you set the display property, you replace the default one. This setting merges them instead.
*/
mergeDisplay?: boolean;
/**
* A prop to add your own css classes to the keyboard wrapper. You can add multiple classes separated by a space.
*/
theme?: string;
/**
* A prop to add your own css classes to one or several buttons.
*/
buttonTheme?: KeyboardButtonTheme[];
/**
* Runs a `console.log` every time a key is pressed. Displays the buttons pressed and the current input.
*/
debug?: boolean;
/**
* Specifies whether clicking the "ENTER" button will input a newline (`\n`) or not.
*/
newLineOnEnter?: boolean;
/**
* Specifies whether clicking the "TAB" button will input a tab character (`\t`) or not.
*/
tabCharOnTab?: boolean;
/**
* Allows you to use a single simple-keyboard instance for several inputs.
*/
inputName?: string;
/**
* `number`: Restrains all of simple-keyboard inputs to a certain length. This should be used in addition to the input elements maxlengthattribute.
*
* `{ [inputName: string]: number }`: Restrains simple-keyboards individual inputs to a certain length. This should be used in addition to the input elements maxlengthattribute.
*/
maxLength?:
| number
| {
[inputName: string]: number;
};
/**
* When set to true, this option synchronizes the internal input of every simple-keyboard instance.
*/
syncInstanceInputs?: boolean;
/**
* Enable highlighting of keys pressed on physical keyboard.
*/
physicalKeyboardHighlight?: boolean;
/**
* Calling preventDefault for the mousedown events keeps the focus on the input.
*/
preventMouseDownDefault?: boolean;
/**
* Define the text color that the physical keyboard highlighted key should have.
*/
physicalKeyboardHighlightTextColor?: string;
/**
* Define the background color that the physical keyboard highlighted key should have.
*/
physicalKeyboardHighlightBgColor?: string;
/**
* Render buttons as a button element instead of a div element.
*/
useButtonTag?: boolean;
/**
* A prop to ensure characters are always be added/removed at the end of the string.
*/
disableCaretPositioning?: boolean;
/**
* Restrains input(s) change to the defined regular expression pattern.
*/
inputPattern?: any;
/**
* Executes the callback function on key press. Returns button layout name (i.e.: "{shift}").
*/
onKeyPress?: (button: string) => any;
/**
* Executes the callback function on input change. Returns the current input's string.
*/
onChange?: (input: string) => any;
/**
* Executes the callback function every time simple-keyboard is rendered (e.g: when you change layouts).
*/
onRender?: () => void;
/**
* Executes the callback function once simple-keyboard is rendered for the first time (on initialization).
*/
onInit?: () => void;
/**
* Executes the callback function on input change. Returns the input object with all defined inputs.
*/
onChangeAll?: (inputs: any) => any;
}
class Keyboard {
constructor(selector: string, options: KeyboardOptions);
constructor(options: KeyboardOptions);
options: KeyboardOptions;
/**
* Adds/Modifies an entry to the `buttonTheme`. Basically a way to add a class to a button.
* @param {string} buttons List of buttons to select (separated by a space).
* @param {string} className Classes to give to the selected buttons (separated by space).
*/
addButtonTheme(buttons: string, className: string): void;
/**
* Removes/Amends an entry to the `buttonTheme`. Basically a way to remove a class previously added to a button through buttonTheme or addButtonTheme.
* @param {string} buttons List of buttons to select (separated by a space).
* @param {string} className Classes to give to the selected buttons (separated by space).
*/
removeButtonTheme(buttons: string, className: string): void;
/**
* Clear the keyboard's input.
*
* @param {string} [inputName] optional - the internal input to select
*/
clearInput(inputName?: string): void;
/**
* Get the keyboards input (You can also get it from the onChange prop).
* @param {string} [inputName] optional - the internal input to select
*/
getInput(inputName?: string): string;
/**
* Set the keyboards input.
* @param {string} input the input value
* @param {string} inputName optional - the internal input to select
*/
setInput(input: string, inputName?: string): void;
/**
* Set new option or modify existing ones after initialization.
* @param {KeyboardOptions} option The option to set
*/
setOptions(options: KeyboardOptions): void;
/**
* Send a command to all simple-keyboard instances at once (if you have multiple instances).
* @param {function(instance: object, key: string)} callback Function to run on every instance
*/
dispatch(callback: (instance: any, key: string) => void): void;
/**
* 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
*/
getButtonElement(button: string): HTMLElement | HTMLElement[];
}
export default Keyboard;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -79,6 +79,7 @@ module.exports = {
appPackageJson: resolveApp('package.json'),
appSrc: resolveApp('src'),
appSrcLib: resolveApp('src/lib'),
appSrcLibTypes: resolveApp('src/lib/@types'),
appSrcDemo: resolveApp('src/demo'),
appTsConfig: resolveApp('tsconfig.json'),
yarnLockFile: resolveApp('yarn.lock'),

View File

@@ -21,6 +21,7 @@ const getClientEnvironment = require('./env');
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin-alt');
const typescriptFormatter = require('react-dev-utils/typescriptFormatter');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const getPackageJson = require('./getPackageJson');
@@ -510,6 +511,12 @@ module.exports = {
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
// You can remove this if you don't use Moment.js:
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
new CopyWebpackPlugin([
{
from: `${paths.appSrcLibTypes}`,
to: paths.appLayoutsBuild
}
]),
// Generate a service worker script that will precache, and keep up to date,
// the HTML & assets that are part of the Webpack build.
/*new WorkboxWebpackPlugin.GenerateSW({

2353
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,9 @@
{
"name": "simple-keyboard",
"version": "2.11.5",
"version": "2.14.0",
"description": "On-screen Javascript Virtual Keyboard",
"main": "build/index.js",
"types": "build/index.d.ts",
"scripts": {
"start": "node scripts/start.js",
"build": "node scripts/build.js",
@@ -34,72 +35,79 @@
"touchscreen",
"touch-screen",
"kiosk",
"osk"
"osk",
"js"
],
"license": "MIT",
"devDependencies": {
"@babel/core": "7.1.6",
"@babel/plugin-proposal-class-properties": "^7.1.0",
"@babel/preset-env": "^7.1.6",
"@babel/core": "7.2.2",
"@babel/plugin-proposal-class-properties": "^7.2.3",
"@babel/preset-env": "^7.2.3",
"@babel/preset-react": "^7.0.0",
"@svgr/webpack": "4.1.0",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "9.0.0",
"babel-eslint": "10.0.1",
"babel-jest": "23.6.0",
"babel-loader": "8.0.4",
"babel-plugin-named-asset-import": "^0.2.3",
"babel-preset-react-app": "^6.1.0",
"babel-loader": "8.0.5",
"babel-plugin-named-asset-import": "^0.3.0",
"babel-preset-react-app": "^7.0.0",
"bfj": "6.1.1",
"case-sensitive-paths-webpack-plugin": "2.1.2",
"chalk": "2.4.1",
"css-loader": "1.0.1",
"dotenv": "6.1.0",
"chalk": "2.4.2",
"copy-webpack-plugin": "^4.6.0",
"css-loader": "2.1.0",
"dotenv": "6.2.0",
"dotenv-expand": "4.2.0",
"esdoc": "^1.1.0",
"esdoc-ecmascript-proposal-plugin": "^1.0.0",
"esdoc-standard-plugin": "^1.0.0",
"eslint": "5.9.0",
"eslint-config-react-app": "^3.0.5",
"eslint": "5.12.0",
"eslint-config-react-app": "^3.0.6",
"eslint-loader": "2.1.1",
"eslint-plugin-flowtype": "2.50.3",
"eslint-plugin-flowtype": "3.2.0",
"eslint-plugin-import": "2.14.0",
"eslint-plugin-jsx-a11y": "6.1.2",
"eslint-plugin-react": "7.11.1",
"file-loader": "2.0.0",
"eslint-plugin-react": "7.12.3",
"file-loader": "3.0.1",
"fork-ts-checker-webpack-plugin-alt": "0.4.14",
"fs-extra": "7.0.1",
"html-webpack-plugin": "4.0.0-beta.4",
"html-webpack-plugin": "4.0.0-beta.5",
"identity-obj-proxy": "3.0.0",
"jest": "23.6.0",
"jest-pnp-resolver": "1.0.2",
"jest-resolve": "23.6.0",
"mini-css-extract-plugin": "0.4.4",
"mini-css-extract-plugin": "0.5.0",
"optimize-css-assets-webpack-plugin": "5.0.1",
"pnp-webpack-plugin": "1.2.0",
"pnp-webpack-plugin": "1.2.1",
"postcss-flexbugs-fixes": "4.1.0",
"postcss-loader": "3.0.0",
"postcss-preset-env": "6.4.0",
"postcss-preset-env": "6.5.0",
"postcss-safe-parser": "4.0.1",
"react": "^16.6.3",
"react-app-polyfill": "^0.1.3",
"react-dev-utils": "^6.1.1",
"react-dom": "^16.6.1",
"resolve": "1.8.1",
"react": "^16.7.0",
"react-app-polyfill": "^0.2.0",
"react-dev-utils": "^7.0.1",
"react-dom": "^16.7.0",
"resolve": "1.9.0",
"sass-loader": "7.1.0",
"style-loader": "0.23.1",
"terser-webpack-plugin": "1.1.0",
"terser-webpack-plugin": "1.2.1",
"url-loader": "1.1.2",
"webpack": "4.26.1",
"webpack-dev-server": "3.1.10",
"webpack": "4.28.3",
"webpack-dev-server": "3.1.14",
"webpack-manifest-plugin": "2.0.4",
"workbox-webpack-plugin": "3.6.3"
},
"eslintConfig": {
"extends": "react-app"
"extends": "react-app",
"settings": {
"react": {
"pragma": "React",
"version": "detect"
}
}
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
],

View File

@@ -31,7 +31,7 @@ class App {
onChange: input => this.onChange(input),
onKeyPress: button => this.onKeyPress(button),
newLineOnEnter: true,
physicalKeyboardHighlight: true,
physicalKeyboardHighlight: true
});
/**

View File

@@ -8,7 +8,7 @@
#root .simple-keyboard-preview {
background: rgba(0,0,0,0.8);
border: 20px solid rgba(0,0,0,0.1);
height: 260px;
height: 200px;
border-top-right-radius: 5px;
border-top-left-radius: 5px;
padding: 10px;

199
src/lib/@types/index.d.ts vendored Normal file
View File

@@ -0,0 +1,199 @@
declare module 'simple-keyboard' {
interface KeyboardLayoutObject {
default: string[];
shift?: string[];
}
interface KeyboardButtonTheme {
class: string;
buttons: string;
}
interface KeyboardOptions {
/**
* Modify the keyboard layout.
*/
layout?: KeyboardLayoutObject;
/**
* Specifies which layout should be used.
*/
layoutName?: string;
/**
* Replaces variable buttons (such as `{bksp}`) with a human-friendly name (e.g.: `backspace`).
*/
display?: { [button: string]: string };
/**
* By default, when you set the display property, you replace the default one. This setting merges them instead.
*/
mergeDisplay?: boolean;
/**
* A prop to add your own css classes to the keyboard wrapper. You can add multiple classes separated by a space.
*/
theme?: string;
/**
* A prop to add your own css classes to one or several buttons.
*/
buttonTheme?: KeyboardButtonTheme[];
/**
* Runs a `console.log` every time a key is pressed. Displays the buttons pressed and the current input.
*/
debug?: boolean;
/**
* Specifies whether clicking the "ENTER" button will input a newline (`\n`) or not.
*/
newLineOnEnter?: boolean;
/**
* Specifies whether clicking the "TAB" button will input a tab character (`\t`) or not.
*/
tabCharOnTab?: boolean;
/**
* Allows you to use a single simple-keyboard instance for several inputs.
*/
inputName?: string;
/**
* `number`: Restrains all of simple-keyboard inputs to a certain length. This should be used in addition to the input elements maxlengthattribute.
*
* `{ [inputName: string]: number }`: Restrains simple-keyboards individual inputs to a certain length. This should be used in addition to the input elements maxlengthattribute.
*/
maxLength?:
| number
| {
[inputName: string]: number;
};
/**
* When set to true, this option synchronizes the internal input of every simple-keyboard instance.
*/
syncInstanceInputs?: boolean;
/**
* Enable highlighting of keys pressed on physical keyboard.
*/
physicalKeyboardHighlight?: boolean;
/**
* Calling preventDefault for the mousedown events keeps the focus on the input.
*/
preventMouseDownDefault?: boolean;
/**
* Define the text color that the physical keyboard highlighted key should have.
*/
physicalKeyboardHighlightTextColor?: string;
/**
* Define the background color that the physical keyboard highlighted key should have.
*/
physicalKeyboardHighlightBgColor?: string;
/**
* Render buttons as a button element instead of a div element.
*/
useButtonTag?: boolean;
/**
* A prop to ensure characters are always be added/removed at the end of the string.
*/
disableCaretPositioning?: boolean;
/**
* Restrains input(s) change to the defined regular expression pattern.
*/
inputPattern?: any;
/**
* Executes the callback function on key press. Returns button layout name (i.e.: "{shift}").
*/
onKeyPress?: (button: string) => any;
/**
* Executes the callback function on input change. Returns the current input's string.
*/
onChange?: (input: string) => any;
/**
* Executes the callback function every time simple-keyboard is rendered (e.g: when you change layouts).
*/
onRender?: () => void;
/**
* Executes the callback function once simple-keyboard is rendered for the first time (on initialization).
*/
onInit?: () => void;
/**
* Executes the callback function on input change. Returns the input object with all defined inputs.
*/
onChangeAll?: (inputs: any) => any;
}
class Keyboard {
constructor(selector: string, options: KeyboardOptions);
constructor(options: KeyboardOptions);
options: KeyboardOptions;
/**
* Adds/Modifies an entry to the `buttonTheme`. Basically a way to add a class to a button.
* @param {string} buttons List of buttons to select (separated by a space).
* @param {string} className Classes to give to the selected buttons (separated by space).
*/
addButtonTheme(buttons: string, className: string): void;
/**
* Removes/Amends an entry to the `buttonTheme`. Basically a way to remove a class previously added to a button through buttonTheme or addButtonTheme.
* @param {string} buttons List of buttons to select (separated by a space).
* @param {string} className Classes to give to the selected buttons (separated by space).
*/
removeButtonTheme(buttons: string, className: string): void;
/**
* Clear the keyboard's input.
*
* @param {string} [inputName] optional - the internal input to select
*/
clearInput(inputName?: string): void;
/**
* Get the keyboards input (You can also get it from the onChange prop).
* @param {string} [inputName] optional - the internal input to select
*/
getInput(inputName?: string): string;
/**
* Set the keyboards input.
* @param {string} input the input value
* @param {string} inputName optional - the internal input to select
*/
setInput(input: string, inputName?: string): void;
/**
* Set new option or modify existing ones after initialization.
* @param {KeyboardOptions} option The option to set
*/
setOptions(options: KeyboardOptions): void;
/**
* Send a command to all simple-keyboard instances at once (if you have multiple instances).
* @param {function(instance: object, key: string)} callback Function to run on every instance
*/
dispatch(callback: (instance: any, key: string) => void): void;
/**
* 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
*/
getButtonElement(button: string): HTMLElement | HTMLElement[];
}
export default Keyboard;
}

View File

@@ -57,6 +57,13 @@ body, html {
justify-content: center;
}
/* When using option "useButtonTag" */
.simple-keyboard button.hg-button {
border-width: 0;
outline: 0;
font-size: inherit;
}
.simple-keyboard.hg-theme-default .hg-button:active {
background: #e4e4e4;
}

View File

@@ -18,7 +18,7 @@ class 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.
*/
constructor(...params){
let keyboardDOMQuery = typeof params[0] === "string" ? params[0] : '.simple-keyboard';
let keyboardDOMQuery = typeof params[0] === "string" ? params[0] : ".simple-keyboard";
let options = typeof params[0] === "object" ? params[0] : params[1];
if(!options)
@@ -58,6 +58,9 @@ class SimpleKeyboard {
* @property {function} onRender Executes the callback function every time simple-keyboard is rendered (e.g: when you change layouts).
* @property {function} onInit Executes the callback function once simple-keyboard is rendered for the first time (on initialization).
* @property {function(inputs: object):object} onChangeAll Executes the callback function on input change. Returns the input object with all defined inputs.
* @property {boolean} useButtonTag Render buttons as a button element instead of a div element.
* @property {boolean} disableCaretPositioning A prop to ensure characters are always be added/removed at the end of the string.
* @property {object} inputPattern Restrains input(s) change to the defined regular expression pattern.
*/
this.options = options;
this.options.layoutName = this.options.layoutName || "default";
@@ -94,6 +97,7 @@ class SimpleKeyboard {
this.handleButtonMouseDown = this.handleButtonMouseDown.bind(this);
this.handleButtonHold = this.handleButtonHold.bind(this);
this.onModulesLoaded = this.onModulesLoaded.bind(this);
this.inputPatternIsValid = this.inputPatternIsValid.bind(this);
/**
* simple-keyboard uses a non-persistent internal input to keep track of the entered string (the variable `keyboard.input`).
@@ -179,7 +183,17 @@ class SimpleKeyboard {
button, this.input[this.options.inputName], this.options, this.caretPosition
);
if(this.input[this.options.inputName] !== updatedInput){
if(
// If input will change as a result of this button press
this.input[this.options.inputName] !== updatedInput &&
// This pertains to the "inputPattern" option:
(
// If inputPattern isn't set
!this.options.inputPattern ||
// Or, if it is set and if the pattern is valid - we proceed.
(this.options.inputPattern && this.inputPatternIsValid(updatedInput))
)
){
/**
* If maxLength and handleMaxLength yield true, halting
@@ -502,6 +516,39 @@ class SimpleKeyboard {
return output;
}
/**
* This handles the "inputPattern" option
* by checking if the provided inputPattern passes
*/
inputPatternIsValid(inputVal){
let inputPatternRaw = this.options.inputPattern;
let inputPattern;
/**
* Check if input pattern is global or targeted to individual inputs
*/
if(inputPatternRaw instanceof RegExp){
inputPattern = inputPatternRaw;
} else {
inputPattern = inputPatternRaw[this.options.inputName];
}
if(inputPattern && inputVal){
let didInputMatch = inputPattern.test(inputVal);
if(this.options.debug){
console.log(`inputPattern ("${inputPattern}"): ${didInputMatch ? "passed" : "did not pass!"}`);
}
return didInputMatch;
} else {
/**
* inputPattern doesn't seem to be set for the current input, or input is empty. Pass.
*/
return true;
}
}
/**
* Retrieves the current cursor position within a input or textarea (if any)
*/
@@ -540,24 +587,29 @@ class SimpleKeyboard {
this.dispatch(instance => {
if(instance.isMouseHold){
instance.isMouseHold = false;
}
instance.isMouseHold = false;
}
if(
(targetTagName === "textarea" ||
targetTagName === "input") &&
!instance.options.disableCaretPositioning
){
/**
* Tracks current cursor position
* As keys are pressed, text will be added/removed at that position within the input.
*/
instance.caretPosition = event.target.selectionStart;
if(
(targetTagName === "textarea" ||
targetTagName === "input") &&
!instance.options.disableCaretPositioning
){
/**
* Tracks current cursor position
* As keys are pressed, text will be added/removed at that position within the input.
*/
instance.caretPosition = event.target.selectionStart;
if(instance.options.debug){
console.log('Caret at: ', event.target.selectionStart, event.target.tagName.toLowerCase(), `(${instance.keyboardDOMClass})`);
}
}
if(instance.options.debug){
console.log("Caret at: ", event.target.selectionStart, event.target.tagName.toLowerCase(), `(${instance.keyboardDOMClass})`);
}
} else if(instance.options.disableCaretPositioning){
/**
* If we toggled off disableCaretPositioning, we must ensure caretPosition doesn't persist once reactivated.
*/
instance.caretPosition = null;
}
});
}
@@ -621,7 +673,7 @@ class SimpleKeyboard {
module.init(this);
});
this.keyboardPluginClasses = this.keyboardPluginClasses + ' modules-loaded';
this.keyboardPluginClasses = this.keyboardPluginClasses + " modules-loaded";
this.render();
this.onModulesLoaded();
@@ -654,7 +706,7 @@ class SimpleKeyboard {
*/
this.clear();
let layoutClass = this.options.layout ? "hg-layout-custom" : `hg-layout-${this.options.layoutName}`;
let layoutClass = `hg-layout-${this.options.layoutName}`;
let layout = this.options.layout || KeyboardLayout.getDefaultLayout();
let useTouchEvents = this.options.useTouchEvents || false
@@ -668,7 +720,7 @@ class SimpleKeyboard {
let themeButtons;
if(typeof themeObj.buttons === "string"){
themeButtons = themeObj.buttons.split(' ');
themeButtons = themeObj.buttons.split(" ");
}
if(themeButtons){
@@ -701,12 +753,12 @@ class SimpleKeyboard {
* Iterating through each row
*/
layout[this.options.layoutName].forEach((row, rIndex) => {
let rowArray = row.split(' ');
let rowArray = row.split(" ");
/**
* Creating empty row
*/
var rowDOM = document.createElement('div');
let rowDOM = document.createElement("div");
rowDOM.className += "hg-row";
/**
@@ -720,7 +772,8 @@ class SimpleKeyboard {
/**
* Creating button
*/
var buttonDOM = document.createElement('div');
let buttonType = this.options.useButtonTag ? "button" : "div";
let buttonDOM = document.createElement(buttonType);
buttonDOM.className += `hg-button ${fctBtnClass}${buttonThemeClass ? " "+buttonThemeClass : ""}`;
if (useTouchEvents) {
@@ -761,7 +814,7 @@ class SimpleKeyboard {
/**
* Adding button label to button
*/
var buttonSpanDOM = document.createElement('span');
let buttonSpanDOM = document.createElement('span');
buttonSpanDOM.innerHTML = buttonDisplayName;
buttonDOM.appendChild(buttonSpanDOM);

View File

@@ -137,7 +137,9 @@ it('Keyboard onKeyPress will work', () => {
it('Keyboard standard function buttons will not change input', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
let keyboard = new Keyboard({
useButtonTag: true
});
testUtil.iterateButtons((button) => {
if(button.getAttribute("data-skbtn") === "{shift}"){
@@ -596,6 +598,42 @@ it('Keyboard caretEventHandler will detect input, textarea focus', () => {
expect(keyboard.caretPosition).toBe(3);
});
it('Keyboard caretEventHandler will not set caretPosition on disableCaretPositioning', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
keyboard.caretEventHandler({
charCode: 0,
code: "KeyF",
key: "f",
which: 70,
target: {
tagName: "input",
selectionStart: 3
}
});
expect(keyboard.caretPosition).toBe(3);
keyboard.setOptions({
disableCaretPositioning: true
});
keyboard.caretEventHandler({
charCode: 0,
code: "KeyF",
key: "f",
which: 70,
target: {
tagName: "input",
selectionStart: 3
}
});
expect(keyboard.caretPosition).toBeFalsy();
});
it('Keyboard caretEventHandler ignore positioning if input, textarea is blur', () => {
testUtil.setDOM();
@@ -909,4 +947,46 @@ it('Keyboard onModulesLoaded will work', () => {
});
expect(foo).toBe("bar");
});
it('Keyboard inputPattern will work globally', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
inputPattern: /^\d+$/
});
keyboard.getButtonElement("q").onclick();
expect(keyboard.getInput()).toBeFalsy();
keyboard.getButtonElement("1").onclick();
expect(keyboard.getInput()).toBe("1");
});
it('Keyboard inputPattern will work by input name', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
debug: true,
inputName: "test1",
inputPattern: {
test1: /^\d+$/
}
});
keyboard.getButtonElement("q").onclick();
keyboard.getButtonElement("1").onclick();
expect(keyboard.getInput()).toBe("1");
keyboard.setOptions({
inputName: "default"
});
keyboard.getButtonElement("q").onclick();
keyboard.getButtonElement("1").onclick();
expect(keyboard.getInput()).toBe("q1");
});

View File

@@ -359,7 +359,14 @@ class Utilities {
* @param {string} string The string to transform.
*/
camelCase(string){
return string.toLowerCase().trim().split(/[.\-_\s]/g).reduce((string, word) => string + word[0].toUpperCase() + word.slice(1));
return string
.toLowerCase()
.trim()
.split(/[.\-_\s]/g)
.reduce(
(string, word) =>
word.length ? string + word[0].toUpperCase() + word.slice(1) : string
);
};
/**
@@ -373,4 +380,4 @@ class Utilities {
}
}
export default Utilities;
export default Utilities;

View File

@@ -477,4 +477,10 @@ it('Keyboard removeAt will remove regular strings', () => {
keyboard.caretPosition = 6;
output = keyboard.utilities.removeAt("testie", 6, true);
expect(keyboard.caretPosition).toBe(5);
});
it('Keyboard will work with custom (and weird) class', () => {
testUtil.setDOM("my--weird--class");
let keyboard = new Keyboard(".my--weird--class");
expect(keyboard.keyboardDOMClass).toBe("my--weird--class");
});