Compare commits

...

138 Commits

Author SHA1 Message Date
Francisco Hodge
342918a3be npm update 2018-11-01 13:23:42 -04:00
Francisco Hodge
c6244e29f6 Updating dev dependencies 2018-11-01 13:16:34 -04:00
Francisco Hodge
d6e815b2f8 Build update 2018-11-01 12:49:01 -04:00
Francisco Hodge
8a4ab7b570 npm update 2018-11-01 12:46:45 -04:00
Francisco Hodge
550715001d Adjusting button hold handler 2018-11-01 12:46:30 -04:00
Francisco Hodge
444806160b Docs update 2018-11-01 12:45:04 -04:00
Francisco Hodge
265f88c7d6 Adding onModulesLoaded 2018-11-01 00:16:11 -04:00
Francisco Hodge
2cd5cf4498 Build update 2018-11-01 00:15:42 -04:00
Francisco Hodge
40e50108ae Docs update 2018-11-01 00:14:02 -04:00
Francisco Hodge
b7636841f7 Build update 2018-10-31 20:46:55 -04:00
Francisco Hodge
922ce24eb7 Build update 2018-10-31 19:48:25 -04:00
Francisco Hodge
824c3578d0 Add class per plugin 2018-10-31 19:48:17 -04:00
Francisco Hodge
1ee5c7dd2d Docs update 2018-10-31 19:47:03 -04:00
Francisco Hodge
41cf4a472b Build update 2018-10-31 18:43:31 -04:00
Francisco Hodge
7c5f0528f2 Adjusting module loading 2018-10-31 18:43:23 -04:00
Francisco Hodge
04b2a730ef Docs update 2018-10-31 18:42:33 -04:00
Francisco Hodge
1f3d5ddf0d Build update 2018-10-31 17:58:54 -04:00
Francisco Hodge
843db06345 Module handling improvements 2018-10-31 17:57:33 -04:00
Francisco Hodge
6001d044f2 Tests update 2018-10-31 17:57:14 -04:00
Francisco Hodge
eafd6af044 Build update 2018-10-31 17:57:05 -04:00
Francisco Hodge
295493e976 Docs update 2018-10-31 17:56:32 -04:00
Francisco Hodge
472df83482 Tests update 2018-10-30 23:38:56 -04:00
Francisco Hodge
e7284b0e38 Docs update 2018-10-30 23:33:29 -04:00
Francisco Hodge
288fcf3507 Build update 2018-10-30 23:28:48 -04:00
Francisco Hodge
cfdf7574ca Tests update 2018-10-30 23:28:39 -04:00
Francisco Hodge
d567b3ac01 Enhancing add-on compatibility 2018-10-30 23:28:23 -04:00
Francisco Hodge
3bd4fb58b7 Build update 2018-10-29 11:48:05 -04:00
Francisco Hodge
01be532886 Docs update 2018-10-29 11:47:56 -04:00
Francisco Hodge
e23e6d4e04 npm update 2018-10-29 11:47:23 -04:00
Francisco Hodge
2571411e06 Update README.md 2018-10-29 11:13:40 -04:00
Francisco Hodge
0d9af8d1ec Update README.md 2018-10-29 11:13:01 -04:00
Francisco Hodge
37e52e0d98 Update README.md 2018-10-29 11:08:02 -04:00
Francisco Hodge
3ab80c4209 Update README.md 2018-10-29 11:06:52 -04:00
Francisco Hodge
d3e548b8f5 Update README.md 2018-10-29 11:04:16 -04:00
Francisco Hodge
6aff86df1f Update README.md 2018-10-29 11:02:21 -04:00
Francisco Hodge
bb8897ecbe Update README.md 2018-10-29 10:48:02 -04:00
Francisco Hodge
2fdf33d63e Update README.md 2018-10-29 10:47:07 -04:00
Francisco Hodge
1d99b1bc31 Update README.md 2018-10-29 10:41:08 -04:00
Francisco Hodge
3070479369 build update 2018-10-24 20:27:29 -04:00
Francisco Hodge
222629abdd Docs update 2018-10-24 20:20:28 -04:00
Francisco Hodge
b4b0a3bb38 Build update 2018-10-24 18:54:37 -04:00
Francisco Hodge
3f163ec62a Readme update 2018-10-24 18:53:33 -04:00
Francisco Hodge
648693cffe Update README.md 2018-10-24 18:49:46 -04:00
Francisco Hodge
fe0036f88e Removing uneeded logging 2018-10-24 18:43:44 -04:00
Francisco Hodge
f284eed9ef Removing unneeded logging 2018-10-24 18:39:45 -04:00
Francisco Hodge
b9ed3792ee npm update 2018-10-24 18:34:56 -04:00
Francisco Hodge
2e3ca5716b Docs update 2018-10-24 18:18:24 -04:00
Francisco Hodge
4589ab789d npm update 2018-10-24 18:18:01 -04:00
Francisco Hodge
806594d96c Build update 2018-10-24 18:17:26 -04:00
Francisco Hodge
5d09d461c9 build update 2018-10-20 14:53:40 -04:00
Francisco Hodge
ec11903020 npm update 2018-10-20 14:51:41 -04:00
Francisco Hodge
3f237c97c8 Update README.md 2018-10-20 14:47:31 -04:00
Francisco Hodge
53269c1fc6 readme update 2018-10-20 14:37:06 -04:00
Francisco Hodge
3da2bc3d57 Merge branch 'master' of https://github.com/hodgef/simple-keyboard 2018-10-20 14:30:10 -04:00
Francisco Hodge
97223c25ef Update README.md 2018-10-20 14:29:14 -04:00
Francisco Hodge
8ce55fc73e npm update 2018-10-20 14:26:55 -04:00
Francisco Hodge
bb8196aec5 Update README.md 2018-10-20 14:24:20 -04:00
Francisco Hodge
3c07aa8395 Update README.md 2018-10-20 14:22:18 -04:00
Francisco Hodge
7d94fc2302 Update README.md 2018-10-20 14:21:40 -04:00
Francisco Hodge
9accf04545 build update 2018-10-17 15:36:33 -04:00
Francisco Hodge
ce949fdae1 Readme update 2018-10-17 14:53:20 -04:00
Francisco Hodge
e31438b331 build update 2018-10-16 18:03:09 -04:00
Francisco Hodge
79f1dfe562 Adding coverage badge to readme 2018-10-16 18:00:21 -04:00
Francisco Hodge
37ba9fd85f deps cleanup 2018-10-16 17:59:50 -04:00
Francisco Hodge
d45b3329a7 travis ci config update 2018-10-16 17:52:04 -04:00
Francisco Hodge
1500ba2f2b travis ci config updated 2018-10-16 17:47:57 -04:00
Francisco Hodge
eb31f91b17 adding mocha to deps 2018-10-16 17:43:35 -04:00
Francisco Hodge
db95212243 travis ci config update 2018-10-16 17:37:28 -04:00
Francisco Hodge
0f0ee2233e Build update 2018-10-16 17:31:23 -04:00
Francisco Hodge
3c5b94abf8 2.6.0 cleanup 2018-10-16 17:31:13 -04:00
Francisco Hodge
48c4e362b3 Demo adjustments 2018-10-16 17:29:32 -04:00
Francisco Hodge
61b896ad77 Readme update 2018-10-16 17:26:30 -04:00
Francisco Hodge
befa988090 Updated CI tests 2018-10-16 17:26:21 -04:00
Francisco Hodge
b08fae64b8 updated travis ci config 2018-10-15 00:43:05 -04:00
Francisco Hodge
17ccf253b4 build update 2018-10-14 22:54:37 -04:00
Francisco Hodge
6edfc6efc2 README update 2018-10-14 22:52:00 -04:00
Francisco Hodge
025e351583 tests update 2018-10-14 22:46:10 -04:00
Francisco Hodge
cc85584154 build update 2018-10-14 22:44:51 -04:00
Francisco Hodge
5033b345f7 npm update 2018-10-14 22:44:02 -04:00
Francisco Hodge
5d5aef242c Update README.md 2018-10-14 19:02:14 -04:00
Francisco Hodge
71bab13453 Update README.md 2018-10-14 18:58:03 -04:00
Francisco Hodge
773a9b5eb3 Merge branch 'master' of https://github.com/hodgef/simple-keyboard 2018-10-12 18:16:22 -04:00
Francisco Hodge
b0d8923a80 build update 2018-10-12 18:15:45 -04:00
Francisco Hodge
8728cc6a2a npm update 2018-10-12 18:14:31 -04:00
Francisco Hodge
fec9d24a19 Fix caret positioning 2018-10-12 18:14:22 -04:00
Francisco Hodge
1a08fe74e0 Update issue templates 2018-10-12 17:56:47 -04:00
Francisco Hodge
b2f7bac585 Build update 2018-10-10 12:21:38 -04:00
Francisco Hodge
46bf8e0dc3 npm update 2018-10-10 12:20:32 -04:00
Francisco Hodge
e8216fee35 Demo update 2018-10-10 12:20:10 -04:00
Francisco Hodge
4f5af90d8d Fix curly brace output 2018-10-10 12:20:02 -04:00
Francisco Hodge
02fd2223ff Rename readme 2018-10-09 20:10:40 -04:00
Francisco Hodge
feb9e51441 Adding readme 2018-10-09 20:09:48 -04:00
Francisco Hodge
5c0d1ed63d Update issue templates 2018-10-09 19:54:47 -04:00
Francisco Hodge
d248a37c70 build update 2018-10-08 19:16:10 -04:00
Francisco Hodge
f1d4b77ffb npm update 2018-10-08 19:13:06 -04:00
Francisco Hodge
7795b98dcc Adding discord chat link to Readme 2018-10-08 19:12:51 -04:00
Francisco Hodge
e8c17a4050 Build update 2018-10-07 22:17:35 -04:00
Francisco Hodge
6e83a1f402 Adding highlighting support for control, alt, meta keys 2018-10-07 22:16:15 -04:00
Francisco Hodge
ba45bbe5ad build uodate 2018-10-06 22:49:57 -04:00
Francisco Hodge
d79fc3b2e3 npm update 2018-10-06 22:25:36 -04:00
Francisco Hodge
88b804643b Removing caret position reset 2018-10-06 22:25:29 -04:00
Francisco Hodge
7b7697841e Build update 2018-10-06 19:07:14 -04:00
Francisco Hodge
c1cfacfcae npm update 2018-10-06 19:02:53 -04:00
Francisco Hodge
0b1a25c8d9 Updating README 2018-10-06 19:00:30 -04:00
Francisco Hodge
53611310c0 Build update 2018-10-06 13:51:41 -04:00
Francisco Hodge
9e521122b5 2.5.2 Readme update 2018-10-06 13:50:56 -04:00
Francisco Hodge
ab6b54dc43 Fix mixed props 2018-10-06 13:49:31 -04:00
Francisco Hodge
0c773151c7 Avoid cursor position change when maxLength is set 2018-10-06 13:35:33 -04:00
Francisco Hodge
9633c99dad Caret bounds fix 2018-10-06 04:06:09 -04:00
Francisco Hodge
280956dba3 Build update 2018-10-06 02:34:06 -04:00
Francisco Hodge
92bae5f3fb Demo update 2018-10-06 02:31:09 -04:00
Francisco Hodge
fa94cf2ba3 PhysicalKeyboard highlighting improvement 2018-10-06 02:26:57 -04:00
Francisco Hodge
24de8bcb20 Clearing out uneeded code 2018-10-06 02:26:22 -04:00
Francisco Hodge
cbfba64447 improved buttonTheme functionality 2018-10-06 02:26:00 -04:00
Francisco Hodge
5e5c1c4abe Precise Button element identifiers 2018-10-06 02:25:04 -04:00
Francisco Hodge
c980024e71 onRender functionality 2018-10-06 02:24:04 -04:00
Francisco Hodge
a321ab9b91 onInit callback 2018-10-06 02:23:38 -04:00
Francisco Hodge
0f1936b03e Utilities adjustment 2018-10-06 02:23:17 -04:00
Francisco Hodge
625a426fef Cursor position support 2018-10-06 02:22:57 -04:00
Francisco Hodge
2ad0ba8506 Cursor position support 2018-10-06 02:22:02 -04:00
Francisco Hodge
d923c5d920 maxLength functionality 2018-10-06 02:18:55 -04:00
Francisco Hodge
282e84941a getButtonElement functionality 2018-10-06 02:17:54 -04:00
Francisco Hodge
e95ebc1b9e Adding utilities as instance 2018-10-06 02:16:12 -04:00
Francisco Hodge
0dffe921ff Removing readonly from demo 2018-10-06 02:12:50 -04:00
Francisco Hodge
26e7970b41 Build update 2018-09-24 21:26:41 -04:00
Francisco Hodge
36df4e83cc Readme update 2018-09-24 15:52:54 -04:00
Francisco Hodge
1c98cf85f6 Updated Styling 2018-09-23 23:38:47 -04:00
Francisco Hodge
a1d6bf4fe0 Merge Display feature 2018-09-23 23:38:34 -04:00
Francisco Hodge
345f22827b Button definitions update 2018-09-23 23:38:11 -04:00
Francisco Hodge
f0ef1e8e7b Physical Keyboard Highlighting support 2018-09-23 23:37:46 -04:00
Francisco Hodge
1cc5b9b0ee Multiple Instance Sync Support 2018-09-23 23:36:01 -04:00
Francisco Hodge
7d6e933a4e Update Keyboard Size 2018-09-23 23:32:53 -04:00
Francisco Hodge
3f4248737f Adding Full Keyboard Demo 2018-09-23 23:32:30 -04:00
Francisco Hodge
572498022c Adding build header 2018-09-09 22:47:01 -04:00
Francisco Hodge
8a85b92f8f Readme update 2018-09-08 10:59:47 -04:00
Francisco Hodge
36123371fb Readme update 2018-09-08 10:29:13 -04:00
Francisco Hodge
15c929316d Readme update 2018-08-29 10:47:04 -04:00
Francisco Hodge
30603e76b5 Emoji backspace fix 2018-08-24 00:40:54 -04:00
84 changed files with 309245 additions and 683 deletions

8
.esdoc.json Normal file
View File

@@ -0,0 +1,8 @@
{
"source": "./src",
"destination": "./docs",
"plugins": [
{"name": "esdoc-standard-plugin"},
{"name": "esdoc-ecmascript-proposal-plugin", "option": {"all": true}}
]
}

17
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,17 @@
---
name: Bug report
about: Create a report to help improve simple-keyboard
---
** simple-keyboard version you are using **
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.
**Create a sandbox example**
Edit [this sandbox example](https://codesandbox.io/s/krzkx19rr) and provide the new link.
**Screenshots**
If applicable, add screenshots to help explain your problem.

View File

@@ -0,0 +1,17 @@
---
name: Feature request
about: Suggest an idea you'd like to see in simple-keyboard
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

4
.github/github.md vendored Normal file
View File

@@ -0,0 +1,4 @@
# About .github
This directory handles special features to be used on simple-keyboard's Github repository.
It is not needed for simple-keyboard to run and can be safely removed.

View File

@@ -4,6 +4,9 @@
# testing
/coverage
# docs
/docs
# misc
.DS_Store
.env.local
@@ -14,6 +17,9 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
/.github
/demo
.esdoc.json
# Development folders and files
public

View File

@@ -1,5 +1,17 @@
language: node_js
node_js:
- "node"
install:
- npm install -g codecov
- npm install
script:
- npm run test
- npm run test -- --coverage
- codecov
after_success:
- wget https://raw.githubusercontent.com/DiscordHooks/travis-ci-discord-webhook/master/send.sh
- chmod +x send.sh
- ./send.sh success $WEBHOOK_URL
after_failure:
- wget https://raw.githubusercontent.com/DiscordHooks/travis-ci-discord-webhook/master/send.sh
- chmod +x send.sh
- ./send.sh failure $WEBHOOK_URL

384
README.md
View File

@@ -1,367 +1,29 @@
[![npm version](https://badge.fury.io/js/simple-keyboard.svg)](https://www.npmjs.com/package/simple-keyboard)
[![](https://data.jsdelivr.com/v1/package/npm/simple-keyboard/badge)](https://www.jsdelivr.com/package/npm/simple-keyboard)
<div align="center">
<a href="https://simple-keyboard.com/demo" title="View Demo" target="_blank"><img src="https://franciscohodge.com/project-pages/simple-keyboard/images/simplekeyboard-banner_B.png" align="center" width="100%"></a>
<a href="https://simple-keyboard.com/demo" title="View Demo" target="_blank"><img src="https://franciscohodge.com/project-pages/simple-keyboard/images/simple-keyboard-10172018.gif" align="center" width="100%"></a>
<blockquote>The easily customisable and responsive on-screen virtual keyboard for Javascript projects.</blockquote>
<p><a href="https://github.com/hodgef/simple-keyboard/blob/master/LICENSE" target="_blank"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License"></a>
<a href="https://www.npmjs.com/package/simple-keyboard" target="_blank"><img src="https://img.shields.io/npm/v/simple-keyboard.svg?style=flat" alt="npm version"></a>
<a href="https://travis-ci.org/hodgef/simple-keyboard" target="_blank"><img src="https://travis-ci.org/hodgef/simple-keyboard.svg?branch=master" alt="Build Status"></a>
<a href="https://codecov.io/gh/hodgef/simple-keyboard" target="_blank"><img src="https://img.shields.io/codecov/c/github/hodgef/simple-keyboard/master.svg?style=flat" alt="Coverage Status"></a>
<a href="https://doc.esdoc.org/github.com/hodgef/simple-keyboard" target="_blank"><img src="https://doc.esdoc.org/github.com/hodgef/simple-keyboard/badge.svg" alt="Documentation Status"></a>
</p>
</div>
<a href="https://franciscohodge.com/simple-keyboard/demo" title="View Demo"><img src="https://franciscohodge.com/project-pages/simple-keyboard/images/simple-keyboard-banner2.png" align="center" width="100%"></a>
## 📦 Installation & Usage
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.
> The easily customisable and responsive on-screen virtual keyboard for Javascript projects.
## 📖 Documentation
Check out the [simple-keyboard documentation](https://simple-keyboard.com/documentation) site.
## Installation
Feel free to browse the [Q&A / Use-cases](https://simple-keyboard.com/qa-use-cases/) page for advanced use-cases.
### npm
## 🚀 Demo
`npm install simple-keyboard --save`
[https://simple-keyboard.com/demo](https://simple-keyboard.com/demo)
### zip file (self-hosted)
[Click here to download the latest release (zip format).](https://github.com/hodgef/simple-keyboard/zipball/master)
> Want to use a CDN instead of self-host? Scroll down to the "Usage with CDN" instructions below.
## Usage with npm
### js
````js
import Keyboard from 'simple-keyboard';
import 'simple-keyboard/build/css/index.css';
let keyboard = new Keyboard({
onChange: input => onChange(input),
onKeyPress: button => onKeyPress(button)
});
function onChange(input){
document.querySelector(".input").value = input;
console.log("Input changed", input);
}
function onKeyPress(button){
console.log("Button pressed", button);
}
````
### html
````html
<input class="input" />
<div class="simple-keyboard"></div>
````
[![Edit krzkx19rr](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/krzkx19rr)
> Need a more extensive example? [Click here](https://github.com/hodgef/simple-keyboard/blob/master/src/demo/App.js).
## Usage with CDN
### html
````html
<html>
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/simple-keyboard@latest/build/css/index.css">
</head>
<body>
<input class="input" placeholder="Tap on the virtual keyboard to start" />
<div class="simple-keyboard"></div>
<script src="https://cdn.jsdelivr.net/npm/simple-keyboard@latest/build/index.min.js"></script>
<script src="src/index.js"></script>
</body>
</html>
````
### js (index.js)
````js
let Keyboard = window.SimpleKeyboard.default;
let myKeyboard = new Keyboard({
onChange: input => onChange(input),
onKeyPress: button => onKeyPress(button)
});
function onChange(input) {
document.querySelector(".input").value = input;
console.log("Input changed", input);
}
function onKeyPress(button) {
console.log("Button pressed", button);
}
````
[![Edit 6n0wzxjmjk](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/6n0wzxjmjk)
## Options
You can customize the Keyboard by passing options to it.
Here are the available options (the code examples are the defaults):
### layout
> Modify the keyboard layout
```js
layout: {
'default': [
'` 1 2 3 4 5 6 7 8 9 0 - = {bksp}',
'{tab} q w e r t y u i o p [ ] \\',
'{lock} a s d f g h j k l ; \' {enter}',
'{shift} z x c v b n m , . / {shift}',
'.com @ {space}'
],
'shift': [
'~ ! @ # $ % ^ & * ( ) _ + {bksp}',
'{tab} Q W E R T Y U I O P { } |',
'{lock} A S D F G H J K L : " {enter}',
'{shift} Z X C V B N M < > ? {shift}',
'.com @ {space}'
]
}
```
> Looking for keyboard layouts in other languages? **Check out [simple-keyboard-layouts](https://github.com/hodgef/simple-keyboard-layouts) !**
### layoutName
> Specifies which layout should be used.
```js
layoutName: "default"
```
### display
> Replaces variable buttons (such as `{bksp}`) with a human-friendly name (e.g.: "backspace").
```js
display: {
'{bksp}': 'backspace',
'{enter}': '< enter',
'{shift}': 'shift',
'{s}': 'shift',
'{tab}': 'tab',
'{lock}': 'caps',
'{accept}': 'Submit',
'{space}': ' ',
'{//}': ' '
}
```
### theme
> A prop to add your own css classes _to the keyboard wrapper_. You can add multiple classes separated by a space.
```js
theme: "hg-theme-default"
```
### buttonTheme
> A prop to add your own css classes _to one or several buttons_. You can add multiple classes separated by a space.
```js
buttonTheme: [
{
class: "myCustomClass",
buttons: "Q W E R T Y q w e r t y"
},
{
class: "anotherCustomClass",
buttons: "Q q"
},
...
]
```
[![Edit simple-keyboard customization demo - npm](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/vj8jvz2q4l?module=%2Fsrc%2Findex.js)
### debug
> Runs a console.log every time a key is pressed. Displays the buttons pressed and the current input.
```js
debug: false
```
### newLineOnEnter
> Specifies whether clicking the "ENTER" button will input a newline (`\n`) or not.
```js
newLineOnEnter: false
```
### inputName
> Allows you to use a single simple-keyboard instance for several inputs.
```js
inputName: "default"
```
### onKeyPress
> Executes the callback function on key press. Returns button layout name (i.e.: "{shift}").
```js
onKeyPress: (button) => console.log(button)
```
### onChange
> Executes the callback function on input change. Returns the current input's string.
```js
onChange: (input) => console.log(input)
```
### onChangeAll
> Executes the callback function on input change. Returns the input object with all defined inputs. This is useful if you're handling several inputs with simple-keyboard, as specified in the "*[Using several inputs](#using-several-inputs)*" guide.
```js
onChangeAll: (inputs) => console.log(inputs)
```
## Methods
simple-keyboard has a few methods you can use to further control it's behavior.
To access these functions, you need the instance the simple-keyboard component, like so:
```js
var keyboard = new Keyboard({
...
});
/>
// Then, use as follows...
keyboard.methodName(params);
```
### clearInput
> Clear the keyboard's input.
```js
// For default input (i.e. if you have only one)
keyboard.clearInput();
// For specific input
// Must have been previously set using the "inputName" prop.
keyboard.clearInput("inputName");
```
### getInput
> Get the keyboard's input (You can also get it from the _onChange_ prop).
```js
// For default input (i.e. if you have only one)
let input = keyboard.getInput();
// For specific input
// Must have been previously set using the "inputName" prop.
let input = keyboard.getInput("inputName");
```
### setInput
> Set the keyboard's input. Useful if you want to track input changes made outside simple-keyboard.
```js
// For default input (i.e. if you have only one)
keyboard.setInput("Hello World!");
// For specific input
// Must have been previously set using the "inputName" prop.
keyboard.setInput("Hello World!", "inputName");
```
### setOptions
> Set new option or modify existing ones after initialization. The changes are applied immediately.
```js
keyboard.setOptions({
theme: "my-custom-theme"
});
```
## Use-cases
### Using several inputs
Set the *[inputName](#inputname)* option for each input you want to handle with simple-keyboard.
For example:
```html
<input class="input" id="input1" value=""/>
<input class="input" id="input2" value=""/>
```
```js
// Here we'll store the input id that simple-keyboard will be using.
var selectedInput;
// Initialize simple-keyboard as usual
var keyboard = new Keyboard({
onChange: input => onChange(input)
});
// Add an event listener for the inputs to be tracked
document.querySelectorAll('.input')
.forEach(input => input.addEventListener('focus', onInputFocus));
/**
* When an input is focused, it will be marked as selected (selectedInput)
* This is so we can replace it's value on the onChange function
*
* Also, we will set the inputName option to a unique string identifying the input (id)
* simple-keyboard save the input in this key and report changes through onChange
*/
onInputFocus = event => {
// Setting input as selected
selectedInput = `#${event.target.id}`;
// Set the inputName option on the fly !
keyboard.setOptions({
inputName: event.target.id
});
}
// When the current input is changed, this is called
onChange = input => {
// If the input is not defined, grabbing the first ".input".
let currentInput = selectedInput || '.input';
// Updating the selected input's value
document.querySelector(currentInput).value = input;
}
```
> [See full example](https://github.com/hodgef/simple-keyboard/blob/master/src/demo/MultipleInputsDemo.js).
[![Edit simple-keyboard multiple inputs demo - npm](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/43nm6v4xyx?module=%2Fsrc%2Findex.js)
### Having keys in a different language configuration
There's a number of key layouts available. To apply them, check out [simple-keyboard-layouts](https://github.com/hodgef/simple-keyboard-layouts).
<a href="https://github.com/hodgef/simple-keyboard-layouts" title="simple-keyboard-layouts repository"><img src="https://franciscohodge.com/project-pages/simple-keyboard/images/simple-keyboard-banner3layouts.png" align="center"></a>
If you'd like to contribute your own layouts, please submit your pull request at the simple-keyboard-layouts repository.
## Demo
[https://franciscohodge.com/simple-keyboard/demo](https://franciscohodge.com/simple-keyboard/demo)
[![Edit krzkx19rr](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/krzkx19rr)
### To run demo on your own computer
@@ -374,7 +36,11 @@ If you'd like to contribute your own layouts, please submit your pull request at
* ReactJS - [react-simple-keyboard](https://github.com/hodgef/react-simple-keyboard)
## Contributing
### Questions?
<a href="http://franciscohodge.com/simple-keyboard/chat/join" title="Join our Discord chat" target="_blank"><img src="https://franciscohodge.com/project-pages/simple-keyboard/images/discord.png" align="center" width="200"></a>
## ✅ Contributing
PR's and issues are welcome. Feel free to submit any issues you have at:
[https://github.com/hodgef/simple-keyboard/issues](https://github.com/hodgef/simple-keyboard/issues)

View File

@@ -1,2 +1,13 @@
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;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;-ms-touch-action:manipulation;touch-action:manipulation}.simple-keyboard .hg-row{display:-ms-flexbox;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;-ms-flex-positive:1;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{-webkit-box-shadow:0 0 3px -1px rgba(0,0,0,.3);box-shadow:0 0 3px -1px rgba(0,0,0,.3);height:40px;border-radius:5px;-webkit-box-sizing:border-box;box-sizing:border-box;padding:5px;background:#fff;border-bottom:1px solid #b5b5b5}.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;-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center}
/*!
*
* simple-keyboard v2.7.7
* https://github.com/hodgef/simple-keyboard
*
* Copyright (c) Francisco Hodge (https://github.com/hodgef)
*
* 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;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;-ms-touch-action:manipulation;touch-action:manipulation}.simple-keyboard .hg-row{display:-ms-flexbox;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;-ms-flex-positive:1;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{-webkit-box-shadow:0 0 3px -1px rgba(0,0,0,.3);box-shadow:0 0 3px -1px rgba(0,0,0,.3);height:40px;border-radius:5px;-webkit-box-sizing:border-box;box-sizing:border-box;padding:5px;background:#fff;border-bottom:1px solid #b5b5b5;cursor:pointer;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack: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;-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex;-ms-flex-pack:center;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*/

View File

@@ -1 +1 @@
{"version":3,"sources":["webpack:///./src/lib/components/Keyboard.css"],"names":[],"mappings":"AAAA,UACE,SACA,SAAW,CAGb,iBACE,6GACA,WACA,yBACG,sBACC,qBACI,iBACR,8BACQ,sBACR,gBACA,8BACI,yBAA2B,CAGjC,yBACE,oBACA,YAAc,CAGhB,0CACE,iBAAmB,CAGrB,qDACE,gBAAkB,CAGpB,4BACE,qBACA,oBACI,YACJ,cAAgB,CAGlB,gBACE,eAAiB,CAMnB,kCACE,gCACA,YACA,iBAAmB,CAGrB,6CACE,+CACQ,uCACR,YACA,kBACA,8BACQ,sBACR,YACA,gBACA,+BAAiC,CAGlC,oDACC,kBAAoB,CAGtB,+DACE,YACA,YACA,sBACI,mBACJ,oBACA,aACA,qBACI,sBAAwB","file":"css/index.css","sourcesContent":["body, html {\r\n margin: 0;\r\n padding: 0;\r\n}\r\n\r\n.simple-keyboard {\r\n font-family: \"HelveticaNeue-Light\", \"Helvetica Neue Light\", \"Helvetica Neue\", Helvetica, Arial, \"Lucida Grande\", sans-serif;\r\n width: 100%;\r\n -webkit-user-select: none;\r\n -moz-user-select: none;\r\n -ms-user-select: none;\r\n user-select: none;\r\n -webkit-box-sizing: border-box;\r\n box-sizing: border-box;\r\n overflow: hidden;\r\n -ms-touch-action: manipulation;\r\n touch-action: manipulation;\r\n}\r\n\r\n.simple-keyboard .hg-row {\r\n display: -ms-flexbox;\r\n display: flex;\r\n}\r\n\r\n.simple-keyboard .hg-row:not(:last-child) {\r\n margin-bottom: 5px;\r\n}\r\n\r\n.simple-keyboard .hg-row .hg-button:not(:last-child) {\r\n margin-right: 5px;\r\n}\r\n\r\n.simple-keyboard .hg-button {\r\n display: inline-block;\r\n -ms-flex-positive: 1;\r\n flex-grow: 1;\r\n cursor: pointer;\r\n}\r\n\r\n.hg-standardBtn {\r\n max-width: 100px;\r\n}\r\n\r\n/**\r\n * hg-theme-default theme\r\n */\r\n.simple-keyboard.hg-theme-default {\r\n background-color: rgba(0,0,0,0.1);\r\n padding: 5px;\r\n border-radius: 5px;\r\n }\r\n\r\n.simple-keyboard.hg-theme-default .hg-button {\r\n -webkit-box-shadow: 0px 0px 3px -1px rgba(0,0,0,0.3);\r\n box-shadow: 0px 0px 3px -1px rgba(0,0,0,0.3);\r\n height: 40px;\r\n border-radius: 5px;\r\n -webkit-box-sizing: border-box;\r\n box-sizing: border-box;\r\n padding: 5px;\r\n background: white;\r\n border-bottom: 1px solid #b5b5b5;\r\n }\r\n\r\n .simple-keyboard.hg-theme-default .hg-button:active {\r\n background: #e4e4e4;\r\n }\r\n\r\n.simple-keyboard.hg-theme-default.hg-layout-numeric .hg-button {\r\n width: 33.3%;\r\n height: 60px;\r\n -ms-flex-align: center;\r\n align-items: center;\r\n display: -ms-flexbox;\r\n display: flex;\r\n -ms-flex-pack: center;\r\n justify-content: center;\r\n}\n\n\n// WEBPACK FOOTER //\n// ./src/lib/components/Keyboard.css"],"sourceRoot":""}
{"version":3,"sources":["webpack:///./src/lib/components/Keyboard.css"],"names":[],"mappings":";;;;;;;;;;;AAAA,UACE,SACA,SAAW,CAGb,iBACE,6GACA,WACA,yBACG,sBACC,qBACI,iBACR,8BACQ,sBACR,gBACA,8BACI,yBAA2B,CAGjC,yBACE,oBACA,YAAc,CAGhB,0CACE,iBAAmB,CAGrB,qDACE,gBAAkB,CAGpB,4BACE,qBACA,oBACI,YACJ,cAAgB,CAGlB,gBACE,eAAiB,CAMnB,kCACE,gCACA,YACA,iBAAmB,CAGrB,6CACE,+CACQ,uCACR,YACA,kBACA,8BACQ,sBACR,YACA,gBACA,gCACA,eACA,oBACA,aACA,sBACI,mBACJ,qBACI,sBAAwB,CAG7B,oDACC,kBAAoB,CAGtB,+DACE,YACA,YACA,sBACI,mBACJ,oBACA,aACA,qBACI,sBAAwB,CAO9B,oIACE,WAAa,CAGf,+DACE,WAAa,CAGf,2DACE,cAAgB,CAGlB,yEACE,cAAgB,CAGlB,+DACE,6BACA,UAAa,CAGf,+EACE,cAAgB,CAGlB,4EACE,cAAgB","file":"css/index.css","sourcesContent":["body, html {\r\n margin: 0;\r\n padding: 0;\r\n}\r\n\r\n.simple-keyboard {\r\n font-family: \"HelveticaNeue-Light\", \"Helvetica Neue Light\", \"Helvetica Neue\", Helvetica, Arial, \"Lucida Grande\", sans-serif;\r\n width: 100%;\r\n -webkit-user-select: none;\r\n -moz-user-select: none;\r\n -ms-user-select: none;\r\n user-select: none;\r\n -webkit-box-sizing: border-box;\r\n box-sizing: border-box;\r\n overflow: hidden;\r\n -ms-touch-action: manipulation;\r\n touch-action: manipulation;\r\n}\r\n\r\n.simple-keyboard .hg-row {\r\n display: -ms-flexbox;\r\n display: flex;\r\n}\r\n\r\n.simple-keyboard .hg-row:not(:last-child) {\r\n margin-bottom: 5px;\r\n}\r\n\r\n.simple-keyboard .hg-row .hg-button:not(:last-child) {\r\n margin-right: 5px;\r\n}\r\n\r\n.simple-keyboard .hg-button {\r\n display: inline-block;\r\n -ms-flex-positive: 1;\r\n flex-grow: 1;\r\n cursor: pointer;\r\n}\r\n\r\n.hg-standardBtn {\r\n max-width: 100px;\r\n}\r\n\r\n/**\r\n * hg-theme-default theme\r\n */\r\n.simple-keyboard.hg-theme-default {\r\n background-color: rgba(0,0,0,0.1);\r\n padding: 5px;\r\n border-radius: 5px;\r\n }\r\n\r\n.simple-keyboard.hg-theme-default .hg-button {\r\n -webkit-box-shadow: 0px 0px 3px -1px rgba(0,0,0,0.3);\r\n box-shadow: 0px 0px 3px -1px rgba(0,0,0,0.3);\r\n height: 40px;\r\n border-radius: 5px;\r\n -webkit-box-sizing: border-box;\r\n box-sizing: border-box;\r\n padding: 5px;\r\n background: white;\r\n border-bottom: 1px solid #b5b5b5;\r\n cursor: pointer;\r\n display: -ms-flexbox;\r\n display: flex;\r\n -ms-flex-align: center;\r\n align-items: center;\r\n -ms-flex-pack: center;\r\n justify-content: center;\r\n }\r\n\r\n .simple-keyboard.hg-theme-default .hg-button:active {\r\n background: #e4e4e4;\r\n }\r\n\r\n.simple-keyboard.hg-theme-default.hg-layout-numeric .hg-button {\r\n width: 33.3%;\r\n height: 60px;\r\n -ms-flex-align: center;\r\n align-items: center;\r\n display: -ms-flexbox;\r\n display: flex;\r\n -ms-flex-pack: center;\r\n justify-content: center;\r\n}\r\n\r\n.simple-keyboard.hg-theme-default .hg-button.hg-button-numpadadd {\r\n height: 85px;\r\n}\r\n\r\n.simple-keyboard.hg-theme-default .hg-button.hg-button-numpadenter {\r\n height: 85px;\r\n}\r\n\r\n.simple-keyboard.hg-theme-default .hg-button.hg-button-numpad0 {\r\n width: 105px;\r\n}\r\n\r\n.simple-keyboard.hg-theme-default .hg-button.hg-button-com {\r\n max-width: 85px;\r\n}\r\n\r\n.simple-keyboard.hg-theme-default .hg-button.hg-standardBtn.hg-button-at {\r\n max-width: 45px;\r\n}\r\n\r\n.simple-keyboard.hg-theme-default .hg-button.hg-selectedButton {\r\n background: rgba(5, 25, 70, 0.53);\r\n color: white;\r\n}\r\n\r\n.simple-keyboard.hg-theme-default .hg-button.hg-standardBtn[data-skbtn=\".com\"] {\r\n max-width: 82px;\r\n}\r\n\r\n.simple-keyboard.hg-theme-default .hg-button.hg-standardBtn[data-skbtn=\"@\"] {\r\n max-width: 60px;\r\n}\n\n\n// WEBPACK FOOTER //\n// ./src/lib/components/Keyboard.css"],"sourceRoot":""}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

25
config/getPackageJson.js Normal file
View File

@@ -0,0 +1,25 @@
const fs = require('fs');
const path = require('path');
/**
* A module to get package informations from package.json
* @module getPackageJson
* @param {...string} keys from package.json if no arguments passed it returns package.json content as object
* @returns {object} with given keys or content of package.json as object
*/
/**
* Returns package info
*/
const getPackageJson = function(...args) {
const packageJSON = JSON.parse(fs.readFileSync(path.join(__dirname, '../package.json')));
if (!args.length) {
return packageJSON;
}
return args.reduce((out, key) => {
out[key] = packageJSON[key];
return out;
}, {});
};
module.exports = getPackageJson;

View File

@@ -8,6 +8,7 @@ const eslintFormatter = require('react-dev-utils/eslintFormatter');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const paths = require('./paths');
const getClientEnvironment = require('./env');
const getPackageJson = require('./getPackageJson');
// Webpack uses `publicPath` to determine where the app is being served from.
// It requires a trailing slash, or the file assets will get an incorrect path.
@@ -42,6 +43,24 @@ const extractTextPluginOptions = shouldUseRelativeAssetPaths
{ publicPath: Array(cssFilename.split('/').length).join('../') }
: {};
const {
version,
name,
license,
repository,
author,
} = getPackageJson('version', 'name', 'license', 'repository', 'author');
const banner = `
${name} v${version}
${repository.url}
Copyright (c) ${author.replace(/ *\<[^)]*\> */g, " ")}
This source code is licensed under the ${license} license found in the
LICENSE file in the root directory of this source tree.
`;
// This is the production configuration.
// It compiles slowly and is focused on producing a fast and minimal bundle.
// The development configuration is different and lives in a separate file.
@@ -247,6 +266,10 @@ module.exports = {
},
sourceMap: shouldUseSourceMap,
}),
new webpack.BannerPlugin({
banner: banner,
entryOnly: true
}),
// Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`.
new ExtractTextPlugin({
filename: cssFilename,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,513 @@
{
"type": "File",
"start": 0,
"end": 70,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 6,
"column": 10
}
},
"program": {
"type": "Program",
"start": 0,
"end": 70,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 6,
"column": 10
}
},
"sourceType": "module",
"body": [
{
"type": "ImportDeclaration",
"start": 0,
"end": 24,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 24
}
},
"specifiers": [
{
"type": "ImportDefaultSpecifier",
"start": 7,
"end": 10,
"loc": {
"start": {
"line": 1,
"column": 7
},
"end": {
"line": 1,
"column": 10
}
},
"local": {
"type": "Identifier",
"start": 7,
"end": 10,
"loc": {
"start": {
"line": 1,
"column": 7
},
"end": {
"line": 1,
"column": 10
},
"identifierName": "App"
},
"name": "App"
}
}
],
"source": {
"type": "StringLiteral",
"start": 16,
"end": 23,
"loc": {
"start": {
"line": 1,
"column": 16
},
"end": {
"line": 1,
"column": 23
}
},
"extra": {
"rawValue": "./App",
"raw": "'./App'"
},
"value": "./App"
},
"trailingComments": [
{
"type": "CommentBlock",
"value": "*\r\n * Initializing demo\r\n ",
"start": 28,
"end": 58,
"loc": {
"start": {
"line": 3,
"column": 0
},
"end": {
"line": 5,
"column": 3
}
}
}
]
},
{
"type": "ExpressionStatement",
"start": 60,
"end": 70,
"loc": {
"start": {
"line": 6,
"column": 0
},
"end": {
"line": 6,
"column": 10
}
},
"expression": {
"type": "NewExpression",
"start": 60,
"end": 69,
"loc": {
"start": {
"line": 6,
"column": 0
},
"end": {
"line": 6,
"column": 9
}
},
"callee": {
"type": "Identifier",
"start": 64,
"end": 67,
"loc": {
"start": {
"line": 6,
"column": 4
},
"end": {
"line": 6,
"column": 7
},
"identifierName": "App"
},
"name": "App"
},
"arguments": [],
"leadingComments": null
},
"leadingComments": [
{
"type": "CommentBlock",
"value": "*\r\n * Initializing demo\r\n ",
"start": 28,
"end": 58,
"loc": {
"start": {
"line": 3,
"column": 0
},
"end": {
"line": 5,
"column": 3
}
}
}
]
}
],
"directives": []
},
"comments": [
{
"type": "CommentBlock",
"value": "*\r\n * Initializing demo\r\n ",
"start": 28,
"end": 58,
"loc": {
"start": {
"line": 3,
"column": 0
},
"end": {
"line": 5,
"column": 3
}
}
}
],
"tokens": [
{
"type": {
"label": "import",
"keyword": "import",
"beforeExpr": false,
"startsExpr": true,
"rightAssociative": false,
"isLoop": false,
"isAssign": false,
"prefix": false,
"postfix": false,
"binop": null,
"updateContext": null
},
"value": "import",
"start": 0,
"end": 6,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 6
}
}
},
{
"type": {
"label": "name",
"beforeExpr": false,
"startsExpr": true,
"rightAssociative": false,
"isLoop": false,
"isAssign": false,
"prefix": false,
"postfix": false,
"binop": null
},
"value": "App",
"start": 7,
"end": 10,
"loc": {
"start": {
"line": 1,
"column": 7
},
"end": {
"line": 1,
"column": 10
}
}
},
{
"type": {
"label": "name",
"beforeExpr": false,
"startsExpr": true,
"rightAssociative": false,
"isLoop": false,
"isAssign": false,
"prefix": false,
"postfix": false,
"binop": null
},
"value": "from",
"start": 11,
"end": 15,
"loc": {
"start": {
"line": 1,
"column": 11
},
"end": {
"line": 1,
"column": 15
}
}
},
{
"type": {
"label": "string",
"beforeExpr": false,
"startsExpr": true,
"rightAssociative": false,
"isLoop": false,
"isAssign": false,
"prefix": false,
"postfix": false,
"binop": null,
"updateContext": null
},
"value": "./App",
"start": 16,
"end": 23,
"loc": {
"start": {
"line": 1,
"column": 16
},
"end": {
"line": 1,
"column": 23
}
}
},
{
"type": {
"label": ";",
"beforeExpr": true,
"startsExpr": false,
"rightAssociative": false,
"isLoop": false,
"isAssign": false,
"prefix": false,
"postfix": false,
"binop": null,
"updateContext": null
},
"start": 23,
"end": 24,
"loc": {
"start": {
"line": 1,
"column": 23
},
"end": {
"line": 1,
"column": 24
}
}
},
{
"type": "CommentBlock",
"value": "*\r\n * Initializing demo\r\n ",
"start": 28,
"end": 58,
"loc": {
"start": {
"line": 3,
"column": 0
},
"end": {
"line": 5,
"column": 3
}
}
},
{
"type": {
"label": "new",
"keyword": "new",
"beforeExpr": true,
"startsExpr": true,
"rightAssociative": false,
"isLoop": false,
"isAssign": false,
"prefix": false,
"postfix": false,
"binop": null,
"updateContext": null
},
"value": "new",
"start": 60,
"end": 63,
"loc": {
"start": {
"line": 6,
"column": 0
},
"end": {
"line": 6,
"column": 3
}
}
},
{
"type": {
"label": "name",
"beforeExpr": false,
"startsExpr": true,
"rightAssociative": false,
"isLoop": false,
"isAssign": false,
"prefix": false,
"postfix": false,
"binop": null
},
"value": "App",
"start": 64,
"end": 67,
"loc": {
"start": {
"line": 6,
"column": 4
},
"end": {
"line": 6,
"column": 7
}
}
},
{
"type": {
"label": "(",
"beforeExpr": true,
"startsExpr": true,
"rightAssociative": false,
"isLoop": false,
"isAssign": false,
"prefix": false,
"postfix": false,
"binop": null
},
"start": 67,
"end": 68,
"loc": {
"start": {
"line": 6,
"column": 7
},
"end": {
"line": 6,
"column": 8
}
}
},
{
"type": {
"label": ")",
"beforeExpr": false,
"startsExpr": false,
"rightAssociative": false,
"isLoop": false,
"isAssign": false,
"prefix": false,
"postfix": false,
"binop": null
},
"start": 68,
"end": 69,
"loc": {
"start": {
"line": 6,
"column": 8
},
"end": {
"line": 6,
"column": 9
}
}
},
{
"type": {
"label": ";",
"beforeExpr": true,
"startsExpr": false,
"rightAssociative": false,
"isLoop": false,
"isAssign": false,
"prefix": false,
"postfix": false,
"binop": null,
"updateContext": null
},
"start": 69,
"end": 70,
"loc": {
"start": {
"line": 6,
"column": 9
},
"end": {
"line": 6,
"column": 10
}
}
},
{
"type": {
"label": "eof",
"beforeExpr": false,
"startsExpr": false,
"rightAssociative": false,
"isLoop": false,
"isAssign": false,
"prefix": false,
"postfix": false,
"binop": null,
"updateContext": null
},
"start": 70,
"end": 70,
"loc": {
"start": {
"line": 6,
"column": 10
},
"end": {
"line": 6,
"column": 10
}
}
}
]
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,407 @@
{
"type": "File",
"start": 0,
"end": 85,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 0
}
},
"program": {
"type": "Program",
"start": 0,
"end": 85,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"column": 0
}
},
"sourceType": "module",
"body": [
{
"type": "ImportDeclaration",
"start": 0,
"end": 51,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 51
}
},
"specifiers": [
{
"type": "ImportDefaultSpecifier",
"start": 7,
"end": 21,
"loc": {
"start": {
"line": 1,
"column": 7
},
"end": {
"line": 1,
"column": 21
}
},
"local": {
"type": "Identifier",
"start": 7,
"end": 21,
"loc": {
"start": {
"line": 1,
"column": 7
},
"end": {
"line": 1,
"column": 21
},
"identifierName": "SimpleKeyboard"
},
"name": "SimpleKeyboard"
}
}
],
"source": {
"type": "StringLiteral",
"start": 27,
"end": 50,
"loc": {
"start": {
"line": 1,
"column": 27
},
"end": {
"line": 1,
"column": 50
}
},
"extra": {
"rawValue": "./components/Keyboard",
"raw": "'./components/Keyboard'"
},
"value": "./components/Keyboard"
}
},
{
"type": "ExportDefaultDeclaration",
"start": 53,
"end": 83,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 30
}
},
"declaration": {
"type": "Identifier",
"start": 68,
"end": 82,
"loc": {
"start": {
"line": 2,
"column": 15
},
"end": {
"line": 2,
"column": 29
},
"identifierName": "SimpleKeyboard"
},
"name": "SimpleKeyboard",
"leadingComments": [],
"trailingComments": []
}
}
],
"directives": []
},
"comments": [],
"tokens": [
{
"type": {
"label": "import",
"keyword": "import",
"beforeExpr": false,
"startsExpr": true,
"rightAssociative": false,
"isLoop": false,
"isAssign": false,
"prefix": false,
"postfix": false,
"binop": null,
"updateContext": null
},
"value": "import",
"start": 0,
"end": 6,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 6
}
}
},
{
"type": {
"label": "name",
"beforeExpr": false,
"startsExpr": true,
"rightAssociative": false,
"isLoop": false,
"isAssign": false,
"prefix": false,
"postfix": false,
"binop": null
},
"value": "SimpleKeyboard",
"start": 7,
"end": 21,
"loc": {
"start": {
"line": 1,
"column": 7
},
"end": {
"line": 1,
"column": 21
}
}
},
{
"type": {
"label": "name",
"beforeExpr": false,
"startsExpr": true,
"rightAssociative": false,
"isLoop": false,
"isAssign": false,
"prefix": false,
"postfix": false,
"binop": null
},
"value": "from",
"start": 22,
"end": 26,
"loc": {
"start": {
"line": 1,
"column": 22
},
"end": {
"line": 1,
"column": 26
}
}
},
{
"type": {
"label": "string",
"beforeExpr": false,
"startsExpr": true,
"rightAssociative": false,
"isLoop": false,
"isAssign": false,
"prefix": false,
"postfix": false,
"binop": null,
"updateContext": null
},
"value": "./components/Keyboard",
"start": 27,
"end": 50,
"loc": {
"start": {
"line": 1,
"column": 27
},
"end": {
"line": 1,
"column": 50
}
}
},
{
"type": {
"label": ";",
"beforeExpr": true,
"startsExpr": false,
"rightAssociative": false,
"isLoop": false,
"isAssign": false,
"prefix": false,
"postfix": false,
"binop": null,
"updateContext": null
},
"start": 50,
"end": 51,
"loc": {
"start": {
"line": 1,
"column": 50
},
"end": {
"line": 1,
"column": 51
}
}
},
{
"type": {
"label": "export",
"keyword": "export",
"beforeExpr": false,
"startsExpr": false,
"rightAssociative": false,
"isLoop": false,
"isAssign": false,
"prefix": false,
"postfix": false,
"binop": null,
"updateContext": null
},
"value": "export",
"start": 53,
"end": 59,
"loc": {
"start": {
"line": 2,
"column": 0
},
"end": {
"line": 2,
"column": 6
}
}
},
{
"type": {
"label": "default",
"keyword": "default",
"beforeExpr": true,
"startsExpr": false,
"rightAssociative": false,
"isLoop": false,
"isAssign": false,
"prefix": false,
"postfix": false,
"binop": null,
"updateContext": null
},
"value": "default",
"start": 60,
"end": 67,
"loc": {
"start": {
"line": 2,
"column": 7
},
"end": {
"line": 2,
"column": 14
}
}
},
{
"type": {
"label": "name",
"beforeExpr": false,
"startsExpr": true,
"rightAssociative": false,
"isLoop": false,
"isAssign": false,
"prefix": false,
"postfix": false,
"binop": null
},
"value": "SimpleKeyboard",
"start": 68,
"end": 82,
"loc": {
"start": {
"line": 2,
"column": 15
},
"end": {
"line": 2,
"column": 29
}
}
},
{
"type": {
"label": ";",
"beforeExpr": true,
"startsExpr": false,
"rightAssociative": false,
"isLoop": false,
"isAssign": false,
"prefix": false,
"postfix": false,
"binop": null,
"updateContext": null
},
"start": 82,
"end": 83,
"loc": {
"start": {
"line": 2,
"column": 29
},
"end": {
"line": 2,
"column": 30
}
}
},
{
"type": {
"label": "eof",
"beforeExpr": false,
"startsExpr": false,
"rightAssociative": false,
"isLoop": false,
"isAssign": false,
"prefix": false,
"postfix": false,
"binop": null,
"updateContext": null
},
"start": 85,
"end": 85,
"loc": {
"start": {
"line": 3,
"column": 0
},
"end": {
"line": 3,
"column": 0
}
}
}
]
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

17
docs/badge.svg Normal file
View File

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="104" height="20">
<script/>
<linearGradient id="a" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<rect rx="3" width="104" height="20" fill="#555"/>
<rect rx="3" x="64" width="40" height="20" fill="#4fc921"/>
<path fill="#4fc921" d="M64 0h4v20h-4z"/>
<rect rx="3" width="104" height="20" fill="url(#a)"/>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="32" y="15" fill="#010101" fill-opacity=".3">document</text>
<text x="32" y="14">document</text>
<text x="84" y="15" fill="#010101" fill-opacity=".3">100%</text>
<text x="84" y="14">100%</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 793 B

View File

@@ -0,0 +1,563 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<base data-ice="baseUrl" href="../../../">
<title data-ice="title">App | simple-keyboard</title>
<link type="text/css" rel="stylesheet" href="css/style.css">
<link type="text/css" rel="stylesheet" href="css/prettify-tomorrow.css">
<script src="script/prettify/prettify.js"></script>
<script src="script/manual.js"></script>
<meta name="description" content="On-screen Javascript Virtual Keyboard"><meta property="twitter:card" content="summary"><meta property="twitter:title" content="simple-keyboard"><meta property="twitter:description" content="On-screen Javascript Virtual Keyboard"></head>
<body class="layout-container" data-ice="rootContainer">
<header>
<a href="./">Home</a>
<a href="identifiers.html">Reference</a>
<a href="source.html">Source</a>
<div class="search-box">
<span>
<img src="./image/search.png">
<span class="search-input-edge"></span><input class="search-input"><span class="search-input-edge"></span>
</span>
<ul class="search-result"></ul>
</div>
<a style="position:relative; top:3px;" href="https://github.com/hodgef/simple-keyboard"><img width="20px" src="./image/github.png"></a></header>
<nav class="navigation" data-ice="nav"><div>
<ul>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#demo">demo</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/demo/App.js~App.html">App</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-components">lib/components</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/components/Keyboard.js~SimpleKeyboard.html">SimpleKeyboard</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-services">lib/services</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/KeyboardLayout.js~KeyboardLayout.html">KeyboardLayout</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html">PhysicalKeyboard</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/Utilities.js~Utilities.html">Utilities</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-tests">lib/tests</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/tests/TestUtility.js~TestUtility.html">TestUtility</a></span></span></li>
</ul>
</div>
</nav>
<div class="content" data-ice="content"><div class="header-notice">
<div data-ice="importPath" class="import-path"><pre class="prettyprint"><code data-ice="importPathCode">import App from &apos;<span><a href="file/src/demo/App.js.html#lineNumber7">simple-keyboard/src/demo/App.js</a></span>&apos;</code></pre></div>
<span data-ice="access">public</span>
<span data-ice="kind">class</span>
<span data-ice="source">| <span><a href="file/src/demo/App.js.html#lineNumber7">source</a></span></span>
</div>
<div class="self-detail detail">
<h1 data-ice="name">App</h1>
<div class="description" data-ice="description"><p>simple-keyboard demo</p>
</div>
</div>
<div data-ice="constructorSummary"><h2>Constructor Summary</h2><table class="summary" data-ice="summary">
<thead><tr><td data-ice="title" colspan="3">Public Constructor</td></tr></thead>
<tbody>
<tr data-ice="target">
<td>
<span class="access" data-ice="access">public</span>
<span class="override" data-ice="override"></span>
</td>
<td>
<div>
<p>
<span class="code" data-ice="name"><span><a href="class/src/demo/App.js~App.html#instance-constructor-constructor">constructor</a></span></span><span class="code" data-ice="signature">()</span>
</p>
</div>
<div>
<div data-ice="description"><p>Instantiates the demo class</p>
</div>
</div>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</div>
<div data-ice="memberSummary"><h2>Member Summary</h2><table class="summary" data-ice="summary">
<thead><tr><td data-ice="title" colspan="3">Public Members</td></tr></thead>
<tbody>
<tr data-ice="target">
<td>
<span class="access" data-ice="access">public</span>
<span class="override" data-ice="override"></span>
</td>
<td>
<div>
<p>
<span class="code" data-ice="name"><span><a href="class/src/demo/App.js~App.html#instance-member-handleShiftButton">handleShiftButton</a></span></span><span class="code" data-ice="signature">: <span>*</span></span>
</p>
</div>
<div>
<div data-ice="description"><p>Handles shift functionality</p>
</div>
</div>
</td>
<td>
</td>
</tr>
<tr data-ice="target">
<td>
<span class="access" data-ice="access">public</span>
<span class="override" data-ice="override"></span>
</td>
<td>
<div>
<p>
<span class="code" data-ice="name"><span><a href="class/src/demo/App.js~App.html#instance-member-layoutName">layoutName</a></span></span><span class="code" data-ice="signature">: <span><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">string</a></span></span>
</p>
</div>
<div>
<div data-ice="description"><p>Default input name</p>
</div>
</div>
</td>
<td>
</td>
</tr>
<tr data-ice="target">
<td>
<span class="access" data-ice="access">public</span>
<span class="override" data-ice="override"></span>
</td>
<td>
<div>
<p>
<span class="code" data-ice="name"><span><a href="class/src/demo/App.js~App.html#instance-member-onChange">onChange</a></span></span><span class="code" data-ice="signature">: <span>*</span></span>
</p>
</div>
<div>
<div data-ice="description"><p>Called when simple-keyboard input has changed</p>
</div>
</div>
</td>
<td>
</td>
</tr>
<tr data-ice="target">
<td>
<span class="access" data-ice="access">public</span>
<span class="override" data-ice="override"></span>
</td>
<td>
<div>
<p>
<span class="code" data-ice="name"><span><a href="class/src/demo/App.js~App.html#instance-member-onDOMLoaded">onDOMLoaded</a></span></span><span class="code" data-ice="signature">: <span>*</span></span>
</p>
</div>
<div>
<div data-ice="description"><p>Executed when the DOM is ready</p>
</div>
</div>
</td>
<td>
</td>
</tr>
<tr data-ice="target">
<td>
<span class="access" data-ice="access">public</span>
<span class="override" data-ice="override"></span>
</td>
<td>
<div>
<p>
<span class="code" data-ice="name"><span><a href="class/src/demo/App.js~App.html#instance-member-onKeyPress">onKeyPress</a></span></span><span class="code" data-ice="signature">: <span>*</span></span>
</p>
</div>
<div>
<div data-ice="description"><p>Called when a simple-keyboard key is pressed</p>
</div>
</div>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</div>
<div data-ice="constructorDetails"><h2 data-ice="title">Public Constructors</h2>
<div class="detail" data-ice="detail">
<h3 data-ice="anchor" id="instance-constructor-constructor">
<span class="access" data-ice="access">public</span>
<span class="code" data-ice="name">constructor</span><span class="code" data-ice="signature">()</span>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/demo/App.js.html#lineNumber11">source</a></span></span>
</span>
</h3>
<div data-ice="description"><p>Instantiates the demo class</p>
</div>
<div data-ice="properties">
</div>
</div>
</div>
<div data-ice="memberDetails"><h2 data-ice="title">Public Members</h2>
<div class="detail" data-ice="detail">
<h3 data-ice="anchor" id="instance-member-handleShiftButton">
<span class="access" data-ice="access">public</span>
<span class="code" data-ice="name">handleShiftButton</span><span class="code" data-ice="signature">: <span>*</span></span>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/demo/App.js.html#lineNumber54">source</a></span></span>
</span>
</h3>
<div data-ice="description"><p>Handles shift functionality</p>
</div>
<div data-ice="properties">
</div>
</div>
<div class="detail" data-ice="detail">
<h3 data-ice="anchor" id="instance-member-layoutName">
<span class="access" data-ice="access">public</span>
<span class="code" data-ice="name">layoutName</span><span class="code" data-ice="signature">: <span><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">string</a></span></span>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/demo/App.js.html#lineNumber18">source</a></span></span>
</span>
</h3>
<div data-ice="description"><p>Default input name</p>
</div>
<div data-ice="properties">
</div>
</div>
<div class="detail" data-ice="detail">
<h3 data-ice="anchor" id="instance-member-onChange">
<span class="access" data-ice="access">public</span>
<span class="code" data-ice="name">onChange</span><span class="code" data-ice="signature">: <span>*</span></span>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/demo/App.js.html#lineNumber66">source</a></span></span>
</span>
</h3>
<div data-ice="description"><p>Called when simple-keyboard input has changed</p>
</div>
<div data-ice="properties">
</div>
</div>
<div class="detail" data-ice="detail">
<h3 data-ice="anchor" id="instance-member-onDOMLoaded">
<span class="access" data-ice="access">public</span>
<span class="code" data-ice="name">onDOMLoaded</span><span class="code" data-ice="signature">: <span>*</span></span>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/demo/App.js.html#lineNumber24">source</a></span></span>
</span>
</h3>
<div data-ice="description"><p>Executed when the DOM is ready</p>
</div>
<div data-ice="properties">
</div>
</div>
<div class="detail" data-ice="detail">
<h3 data-ice="anchor" id="instance-member-onKeyPress">
<span class="access" data-ice="access">public</span>
<span class="code" data-ice="name">onKeyPress</span><span class="code" data-ice="signature">: <span>*</span></span>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/demo/App.js.html#lineNumber73">source</a></span></span>
</span>
</h3>
<div data-ice="description"><p>Called when a simple-keyboard key is pressed</p>
</div>
<div data-ice="properties">
</div>
</div>
</div>
</div>
<footer class="footer">
Generated by <a href="https://esdoc.org">ESDoc<span data-ice="esdocVersion">(1.1.0)</span><img src="./image/esdoc-logo-mini-black.png"></a>
</footer>
<script src="script/search_index.js"></script>
<script src="script/search.js"></script>
<script src="script/pretty-print.js"></script>
<script src="script/inherited-summary.js"></script>
<script src="script/test-summary.js"></script>
<script src="script/inner-link.js"></script>
<script src="script/patch-for-local.js"></script>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,203 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<base data-ice="baseUrl" href="../../../../">
<title data-ice="title">KeyboardLayout | simple-keyboard</title>
<link type="text/css" rel="stylesheet" href="css/style.css">
<link type="text/css" rel="stylesheet" href="css/prettify-tomorrow.css">
<script src="script/prettify/prettify.js"></script>
<script src="script/manual.js"></script>
<meta name="description" content="On-screen Javascript Virtual Keyboard"><meta property="twitter:card" content="summary"><meta property="twitter:title" content="simple-keyboard"><meta property="twitter:description" content="On-screen Javascript Virtual Keyboard"></head>
<body class="layout-container" data-ice="rootContainer">
<header>
<a href="./">Home</a>
<a href="identifiers.html">Reference</a>
<a href="source.html">Source</a>
<div class="search-box">
<span>
<img src="./image/search.png">
<span class="search-input-edge"></span><input class="search-input"><span class="search-input-edge"></span>
</span>
<ul class="search-result"></ul>
</div>
<a style="position:relative; top:3px;" href="https://github.com/hodgef/simple-keyboard"><img width="20px" src="./image/github.png"></a></header>
<nav class="navigation" data-ice="nav"><div>
<ul>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#demo">demo</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/demo/App.js~App.html">App</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-components">lib/components</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/components/Keyboard.js~SimpleKeyboard.html">SimpleKeyboard</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-services">lib/services</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/KeyboardLayout.js~KeyboardLayout.html">KeyboardLayout</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html">PhysicalKeyboard</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/Utilities.js~Utilities.html">Utilities</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-tests">lib/tests</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/tests/TestUtility.js~TestUtility.html">TestUtility</a></span></span></li>
</ul>
</div>
</nav>
<div class="content" data-ice="content"><div class="header-notice">
<div data-ice="importPath" class="import-path"><pre class="prettyprint"><code data-ice="importPathCode">import KeyboardLayout from &apos;<span><a href="file/src/lib/services/KeyboardLayout.js.html#lineNumber4">simple-keyboard/src/lib/services/KeyboardLayout.js</a></span>&apos;</code></pre></div>
<span data-ice="access">public</span>
<span data-ice="kind">class</span>
<span data-ice="source">| <span><a href="file/src/lib/services/KeyboardLayout.js.html#lineNumber4">source</a></span></span>
</div>
<div class="self-detail detail">
<h1 data-ice="name">KeyboardLayout</h1>
<div class="description" data-ice="description"><p>Keyboard Layout Service</p>
</div>
</div>
<div data-ice="staticMethodSummary"><h2>Static Method Summary</h2><table class="summary" data-ice="summary">
<thead><tr><td data-ice="title" colspan="3">Static Public Methods</td></tr></thead>
<tbody>
<tr data-ice="target">
<td>
<span class="access" data-ice="access">public</span>
<span data-ice="static">static</span>
<span class="override" data-ice="override"></span>
</td>
<td>
<div>
<p>
<span class="code" data-ice="name"><span><a href="class/src/lib/services/KeyboardLayout.js~KeyboardLayout.html#static-method-getDefaultLayout">getDefaultLayout</a></span></span><span class="code" data-ice="signature">(): <span><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object">object</a></span></span>
</p>
</div>
<div>
<div data-ice="description"><p>Get default simple-keyboard layout</p>
</div>
</div>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</div>
<div data-ice="staticMethodDetails"><h2 data-ice="title">Static Public Methods</h2>
<div class="detail" data-ice="detail">
<h3 data-ice="anchor" id="static-method-getDefaultLayout">
<span class="access" data-ice="access">public</span>
<span data-ice="static">static</span>
<span class="code" data-ice="name">getDefaultLayout</span><span class="code" data-ice="signature">(): <span><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object">object</a></span></span>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/services/KeyboardLayout.js.html#lineNumber9">source</a></span></span>
</span>
</h3>
<div data-ice="description"><p>Get default simple-keyboard layout</p>
</div>
<div data-ice="properties">
</div>
<div class="return-params" data-ice="returnParams">
<h4>Return:</h4>
<table>
<tbody>
<tr>
<td class="return-type code" data-ice="returnType"><span><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object">object</a></span></td>
<td class="return-desc" data-ice="returnDescription"><p>The default layout (US-QWERTY)</p>
</td>
</tr>
</tbody>
</table>
<div data-ice="returnProperties">
</div>
</div>
</div>
</div>
</div>
<footer class="footer">
Generated by <a href="https://esdoc.org">ESDoc<span data-ice="esdocVersion">(1.1.0)</span><img src="./image/esdoc-logo-mini-black.png"></a>
</footer>
<script src="script/search_index.js"></script>
<script src="script/search.js"></script>
<script src="script/pretty-print.js"></script>
<script src="script/inherited-summary.js"></script>
<script src="script/test-summary.js"></script>
<script src="script/inner-link.js"></script>
<script src="script/patch-for-local.js"></script>
</body>
</html>

View File

@@ -0,0 +1,452 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<base data-ice="baseUrl" href="../../../../">
<title data-ice="title">PhysicalKeyboard | simple-keyboard</title>
<link type="text/css" rel="stylesheet" href="css/style.css">
<link type="text/css" rel="stylesheet" href="css/prettify-tomorrow.css">
<script src="script/prettify/prettify.js"></script>
<script src="script/manual.js"></script>
<meta name="description" content="On-screen Javascript Virtual Keyboard"><meta property="twitter:card" content="summary"><meta property="twitter:title" content="simple-keyboard"><meta property="twitter:description" content="On-screen Javascript Virtual Keyboard"></head>
<body class="layout-container" data-ice="rootContainer">
<header>
<a href="./">Home</a>
<a href="identifiers.html">Reference</a>
<a href="source.html">Source</a>
<div class="search-box">
<span>
<img src="./image/search.png">
<span class="search-input-edge"></span><input class="search-input"><span class="search-input-edge"></span>
</span>
<ul class="search-result"></ul>
</div>
<a style="position:relative; top:3px;" href="https://github.com/hodgef/simple-keyboard"><img width="20px" src="./image/github.png"></a></header>
<nav class="navigation" data-ice="nav"><div>
<ul>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#demo">demo</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/demo/App.js~App.html">App</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-components">lib/components</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/components/Keyboard.js~SimpleKeyboard.html">SimpleKeyboard</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-services">lib/services</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/KeyboardLayout.js~KeyboardLayout.html">KeyboardLayout</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html">PhysicalKeyboard</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/Utilities.js~Utilities.html">Utilities</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-tests">lib/tests</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/tests/TestUtility.js~TestUtility.html">TestUtility</a></span></span></li>
</ul>
</div>
</nav>
<div class="content" data-ice="content"><div class="header-notice">
<div data-ice="importPath" class="import-path"><pre class="prettyprint"><code data-ice="importPathCode">import PhysicalKeyboard from &apos;<span><a href="file/src/lib/services/PhysicalKeyboard.js.html#lineNumber4">simple-keyboard/src/lib/services/PhysicalKeyboard.js</a></span>&apos;</code></pre></div>
<span data-ice="access">public</span>
<span data-ice="kind">class</span>
<span data-ice="source">| <span><a href="file/src/lib/services/PhysicalKeyboard.js.html#lineNumber4">source</a></span></span>
</div>
<div class="self-detail detail">
<h1 data-ice="name">PhysicalKeyboard</h1>
<div class="description" data-ice="description"><p>Physical Keyboard Service</p>
</div>
</div>
<div data-ice="constructorSummary"><h2>Constructor Summary</h2><table class="summary" data-ice="summary">
<thead><tr><td data-ice="title" colspan="3">Public Constructor</td></tr></thead>
<tbody>
<tr data-ice="target">
<td>
<span class="access" data-ice="access">public</span>
<span class="override" data-ice="override"></span>
</td>
<td>
<div>
<p>
<span class="code" data-ice="name"><span><a href="class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html#instance-constructor-constructor">constructor</a></span></span><span class="code" data-ice="signature">()</span>
</p>
</div>
<div>
<div data-ice="description"><p>Creates an instance of the PhysicalKeyboard service</p>
</div>
</div>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</div>
<div data-ice="memberSummary"><h2>Member Summary</h2><table class="summary" data-ice="summary">
<thead><tr><td data-ice="title" colspan="3">Public Members</td></tr></thead>
<tbody>
<tr data-ice="target">
<td>
<span class="access" data-ice="access">public</span>
<span class="override" data-ice="override"></span>
</td>
<td>
<div>
<p>
<span class="code" data-ice="name"><span><a href="class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html#instance-member-simpleKeyboardInstance">simpleKeyboardInstance</a></span></span><span class="code" data-ice="signature">: <span><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object">object</a></span></span>
</p>
</div>
<div>
</div>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</div>
<div data-ice="methodSummary"><h2>Method Summary</h2><table class="summary" data-ice="summary">
<thead><tr><td data-ice="title" colspan="3">Public Methods</td></tr></thead>
<tbody>
<tr data-ice="target">
<td>
<span class="access" data-ice="access">public</span>
<span class="override" data-ice="override"></span>
</td>
<td>
<div>
<p>
<span class="code" data-ice="name"><span><a href="class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html#instance-method-getSimpleKeyboardLayoutKey">getSimpleKeyboardLayoutKey</a></span></span><span class="code" data-ice="signature">(event: <span><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object">object</a></span>): <span>*</span></span>
</p>
</div>
<div>
<div data-ice="description"><p>Transforms a KeyboardEvent&apos;s &quot;key.code&quot; string into a simple-keyboard layout format</p>
</div>
</div>
</td>
<td>
</td>
</tr>
<tr data-ice="target">
<td>
<span class="access" data-ice="access">public</span>
<span class="override" data-ice="override"></span>
</td>
<td>
<div>
<p>
<span class="code" data-ice="name"><span><a href="class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html#instance-method-initKeyboardListener">initKeyboardListener</a></span></span><span class="code" data-ice="signature">()</span>
</p>
</div>
<div>
<div data-ice="description"><p>Initializes key event listeners</p>
</div>
</div>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</div>
<div data-ice="constructorDetails"><h2 data-ice="title">Public Constructors</h2>
<div class="detail" data-ice="detail">
<h3 data-ice="anchor" id="instance-constructor-constructor">
<span class="access" data-ice="access">public</span>
<span class="code" data-ice="name">constructor</span><span class="code" data-ice="signature">()</span>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/services/PhysicalKeyboard.js.html#lineNumber8">source</a></span></span>
</span>
</h3>
<div data-ice="description"><p>Creates an instance of the PhysicalKeyboard service</p>
</div>
<div data-ice="properties">
</div>
</div>
</div>
<div data-ice="memberDetails"><h2 data-ice="title">Public Members</h2>
<div class="detail" data-ice="detail">
<h3 data-ice="anchor" id="instance-member-simpleKeyboardInstance">
<span class="access" data-ice="access">public</span>
<span class="code" data-ice="name">simpleKeyboardInstance</span><span class="code" data-ice="signature">: <span><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object">object</a></span></span>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/services/PhysicalKeyboard.js.html#lineNumber12">source</a></span></span>
</span>
</h3>
<div data-ice="properties">
</div>
</div>
</div>
<div data-ice="methodDetails"><h2 data-ice="title">Public Methods</h2>
<div class="detail" data-ice="detail">
<h3 data-ice="anchor" id="instance-method-getSimpleKeyboardLayoutKey">
<span class="access" data-ice="access">public</span>
<span class="code" data-ice="name">getSimpleKeyboardLayoutKey</span><span class="code" data-ice="signature">(event: <span><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object">object</a></span>): <span>*</span></span>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/services/PhysicalKeyboard.js.html#lineNumber66">source</a></span></span>
</span>
</h3>
<div data-ice="description"><p>Transforms a KeyboardEvent&apos;s &quot;key.code&quot; string into a simple-keyboard layout format</p>
</div>
<div data-ice="properties"><div data-ice="properties">
<h4 data-ice="title">Params:</h4>
<table class="params">
<thead>
<tr><td>Name</td><td>Type</td><td>Attribute</td><td>Description</td></tr>
</thead>
<tbody>
<tr data-ice="property" data-depth="0">
<td data-ice="name" class="code" data-depth="0">event</td>
<td data-ice="type" class="code"><span><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object">object</a></span></td>
<td data-ice="appendix"></td>
<td data-ice="description"><p>The KeyboardEvent</p>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="return-params" data-ice="returnParams">
<h4>Return:</h4>
<table>
<tbody>
<tr>
<td class="return-type code" data-ice="returnType"><span>*</span></td>
</tr>
</tbody>
</table>
<div data-ice="returnProperties">
</div>
</div>
</div>
<div class="detail" data-ice="detail">
<h3 data-ice="anchor" id="instance-method-initKeyboardListener">
<span class="access" data-ice="access">public</span>
<span class="code" data-ice="name">initKeyboardListener</span><span class="code" data-ice="signature">()</span>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/services/PhysicalKeyboard.js.html#lineNumber29">source</a></span></span>
</span>
</h3>
<div data-ice="description"><p>Initializes key event listeners</p>
</div>
<div data-ice="properties">
</div>
</div>
</div>
</div>
<footer class="footer">
Generated by <a href="https://esdoc.org">ESDoc<span data-ice="esdocVersion">(1.1.0)</span><img src="./image/esdoc-logo-mini-black.png"></a>
</footer>
<script src="script/search_index.js"></script>
<script src="script/search.js"></script>
<script src="script/pretty-print.js"></script>
<script src="script/inherited-summary.js"></script>
<script src="script/test-summary.js"></script>
<script src="script/inner-link.js"></script>
<script src="script/patch-for-local.js"></script>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,482 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<base data-ice="baseUrl" href="../../../../">
<title data-ice="title">TestUtility | simple-keyboard</title>
<link type="text/css" rel="stylesheet" href="css/style.css">
<link type="text/css" rel="stylesheet" href="css/prettify-tomorrow.css">
<script src="script/prettify/prettify.js"></script>
<script src="script/manual.js"></script>
<meta name="description" content="On-screen Javascript Virtual Keyboard"><meta property="twitter:card" content="summary"><meta property="twitter:title" content="simple-keyboard"><meta property="twitter:description" content="On-screen Javascript Virtual Keyboard"></head>
<body class="layout-container" data-ice="rootContainer">
<header>
<a href="./">Home</a>
<a href="identifiers.html">Reference</a>
<a href="source.html">Source</a>
<div class="search-box">
<span>
<img src="./image/search.png">
<span class="search-input-edge"></span><input class="search-input"><span class="search-input-edge"></span>
</span>
<ul class="search-result"></ul>
</div>
<a style="position:relative; top:3px;" href="https://github.com/hodgef/simple-keyboard"><img width="20px" src="./image/github.png"></a></header>
<nav class="navigation" data-ice="nav"><div>
<ul>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#demo">demo</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/demo/App.js~App.html">App</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-components">lib/components</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/components/Keyboard.js~SimpleKeyboard.html">SimpleKeyboard</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-services">lib/services</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/KeyboardLayout.js~KeyboardLayout.html">KeyboardLayout</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html">PhysicalKeyboard</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/Utilities.js~Utilities.html">Utilities</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-tests">lib/tests</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/tests/TestUtility.js~TestUtility.html">TestUtility</a></span></span></li>
</ul>
</div>
</nav>
<div class="content" data-ice="content"><div class="header-notice">
<div data-ice="importPath" class="import-path"><pre class="prettyprint"><code data-ice="importPathCode">import TestUtility from &apos;<span><a href="file/src/lib/tests/TestUtility.js.html#lineNumber4">simple-keyboard/src/lib/tests/TestUtility.js</a></span>&apos;</code></pre></div>
<span data-ice="access">public</span>
<span data-ice="kind">class</span>
<span data-ice="source">| <span><a href="file/src/lib/tests/TestUtility.js.html#lineNumber4">source</a></span></span>
</div>
<div class="self-detail detail">
<h1 data-ice="name">TestUtility</h1>
<div class="description" data-ice="description"><p>Test Utility Functions</p>
</div>
</div>
<div data-ice="memberSummary"><h2>Member Summary</h2><table class="summary" data-ice="summary">
<thead><tr><td data-ice="title" colspan="3">Public Members</td></tr></thead>
<tbody>
<tr data-ice="target">
<td>
<span class="access" data-ice="access">public</span>
<span class="override" data-ice="override"></span>
</td>
<td>
<div>
<p>
<span class="code" data-ice="name"><span><a href="class/src/lib/tests/TestUtility.js~TestUtility.html#instance-member-clear">clear</a></span></span><span class="code" data-ice="signature">: <span>*</span></span>
</p>
</div>
<div>
<div data-ice="description"><p>Clears DOM structure</p>
</div>
</div>
</td>
<td>
</td>
</tr>
<tr data-ice="target">
<td>
<span class="access" data-ice="access">public</span>
<span class="override" data-ice="override"></span>
</td>
<td>
<div>
<p>
<span class="code" data-ice="name"><span><a href="class/src/lib/tests/TestUtility.js~TestUtility.html#instance-member-iterateButtons">iterateButtons</a></span></span><span class="code" data-ice="signature">: <span>*</span></span>
</p>
</div>
<div>
<div data-ice="description"><p>Iterates on the keyboard buttons</p>
</div>
</div>
</td>
<td>
</td>
</tr>
<tr data-ice="target">
<td>
<span class="access" data-ice="access">public</span>
<span class="override" data-ice="override"></span>
</td>
<td>
<div>
<p>
<span class="code" data-ice="name"><span><a href="class/src/lib/tests/TestUtility.js~TestUtility.html#instance-member-setDOM">setDOM</a></span></span><span class="code" data-ice="signature">: <span>*</span></span>
</p>
</div>
<div>
<div data-ice="description"><p>Set&apos;s a basic DOM structure to test in</p>
</div>
</div>
</td>
<td>
</td>
</tr>
<tr data-ice="target">
<td>
<span class="access" data-ice="access">public</span>
<span class="override" data-ice="override"></span>
</td>
<td>
<div>
<p>
<span class="code" data-ice="name"><span><a href="class/src/lib/tests/TestUtility.js~TestUtility.html#instance-member-testLayoutFctButtons">testLayoutFctButtons</a></span></span><span class="code" data-ice="signature">: <span>*</span></span>
</p>
</div>
<div>
<div data-ice="description"><p>Test if function buttons are interactive (have an onclick)</p>
</div>
</div>
</td>
<td>
</td>
</tr>
<tr data-ice="target">
<td>
<span class="access" data-ice="access">public</span>
<span class="override" data-ice="override"></span>
</td>
<td>
<div>
<p>
<span class="code" data-ice="name"><span><a href="class/src/lib/tests/TestUtility.js~TestUtility.html#instance-member-testLayoutStdButtons">testLayoutStdButtons</a></span></span><span class="code" data-ice="signature">: <span>*</span></span>
</p>
</div>
<div>
<div data-ice="description"><p>Test if standard buttons respect maxLength and do input a value</p>
</div>
</div>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</div>
<div data-ice="memberDetails"><h2 data-ice="title">Public Members</h2>
<div class="detail" data-ice="detail">
<h3 data-ice="anchor" id="instance-member-clear">
<span class="access" data-ice="access">public</span>
<span class="code" data-ice="name">clear</span><span class="code" data-ice="signature">: <span>*</span></span>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/tests/TestUtility.js.html#lineNumber18">source</a></span></span>
</span>
</h3>
<div data-ice="description"><p>Clears DOM structure</p>
</div>
<div data-ice="properties">
</div>
</div>
<div class="detail" data-ice="detail">
<h3 data-ice="anchor" id="instance-member-iterateButtons">
<span class="access" data-ice="access">public</span>
<span class="code" data-ice="name">iterateButtons</span><span class="code" data-ice="signature">: <span>*</span></span>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/tests/TestUtility.js.html#lineNumber98">source</a></span></span>
</span>
</h3>
<div data-ice="description"><p>Iterates on the keyboard buttons</p>
</div>
<div data-ice="properties">
</div>
</div>
<div class="detail" data-ice="detail">
<h3 data-ice="anchor" id="instance-member-setDOM">
<span class="access" data-ice="access">public</span>
<span class="code" data-ice="name">setDOM</span><span class="code" data-ice="signature">: <span>*</span></span>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/tests/TestUtility.js.html#lineNumber8">source</a></span></span>
</span>
</h3>
<div data-ice="description"><p>Set&apos;s a basic DOM structure to test in</p>
</div>
<div data-ice="properties">
</div>
</div>
<div class="detail" data-ice="detail">
<h3 data-ice="anchor" id="instance-member-testLayoutFctButtons">
<span class="access" data-ice="access">public</span>
<span class="code" data-ice="name">testLayoutFctButtons</span><span class="code" data-ice="signature">: <span>*</span></span>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/tests/TestUtility.js.html#lineNumber74">source</a></span></span>
</span>
</h3>
<div data-ice="description"><p>Test if function buttons are interactive (have an onclick)</p>
</div>
<div data-ice="properties">
</div>
</div>
<div class="detail" data-ice="detail">
<h3 data-ice="anchor" id="instance-member-testLayoutStdButtons">
<span class="access" data-ice="access">public</span>
<span class="code" data-ice="name">testLayoutStdButtons</span><span class="code" data-ice="signature">: <span>*</span></span>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/tests/TestUtility.js.html#lineNumber25">source</a></span></span>
</span>
</h3>
<div data-ice="description"><p>Test if standard buttons respect maxLength and do input a value</p>
</div>
<div data-ice="properties">
</div>
</div>
</div>
</div>
<footer class="footer">
Generated by <a href="https://esdoc.org">ESDoc<span data-ice="esdocVersion">(1.1.0)</span><img src="./image/esdoc-logo-mini-black.png"></a>
</footer>
<script src="script/search_index.js"></script>
<script src="script/search.js"></script>
<script src="script/pretty-print.js"></script>
<script src="script/inherited-summary.js"></script>
<script src="script/test-summary.js"></script>
<script src="script/inner-link.js"></script>
<script src="script/patch-for-local.js"></script>
</body>
</html>

37
docs/coverage.json Normal file
View File

@@ -0,0 +1,37 @@
{
"coverage": "100%",
"expectCount": 77,
"actualCount": 77,
"files": {
"src/demo/App.js": {
"expectCount": 8,
"actualCount": 8,
"undocumentLines": []
},
"src/lib/components/Keyboard.js": {
"expectCount": 41,
"actualCount": 41,
"undocumentLines": []
},
"src/lib/services/KeyboardLayout.js": {
"expectCount": 2,
"actualCount": 2,
"undocumentLines": []
},
"src/lib/services/PhysicalKeyboard.js": {
"expectCount": 5,
"actualCount": 5,
"undocumentLines": []
},
"src/lib/services/Utilities.js": {
"expectCount": 15,
"actualCount": 15,
"undocumentLines": []
},
"src/lib/tests/TestUtility.js": {
"expectCount": 6,
"actualCount": 6,
"undocumentLines": []
}
}
}

83
docs/css/github.css Normal file
View File

@@ -0,0 +1,83 @@
/* github markdown */
.github-markdown {
font-size: 16px;
}
.github-markdown h1,
.github-markdown h2,
.github-markdown h3,
.github-markdown h4,
.github-markdown h5 {
margin-top: 1em;
margin-bottom: 16px;
font-weight: bold;
padding: 0;
}
.github-markdown h1:nth-of-type(1) {
margin-top: 0;
}
.github-markdown h1 {
font-size: 2em;
padding-bottom: 0.3em;
}
.github-markdown h2 {
font-size: 1.75em;
padding-bottom: 0.3em;
}
.github-markdown h3 {
font-size: 1.5em;
}
.github-markdown h4 {
font-size: 1.25em;
}
.github-markdown h5 {
font-size: 1em;
}
.github-markdown ul, .github-markdown ol {
padding-left: 2em;
}
.github-markdown pre > code {
font-size: 0.85em;
}
.github-markdown table {
margin-bottom: 1em;
border-collapse: collapse;
border-spacing: 0;
}
.github-markdown table tr {
background-color: #fff;
border-top: 1px solid #ccc;
}
.github-markdown table th,
.github-markdown table td {
padding: 6px 13px;
border: 1px solid #ddd;
}
.github-markdown table tr:nth-child(2n) {
background-color: #f8f8f8;
}
.github-markdown hr {
border-right: 0;
border-bottom: 1px solid #e5e5e5;
border-left: 0;
border-top: 0;
}
/** badge(.svg) does not have border */
.github-markdown img:not([src*=".svg"]) {
max-width: 100%;
box-shadow: 1px 1px 1px rgba(0,0,0,0.5);
}

37
docs/css/identifiers.css Normal file
View File

@@ -0,0 +1,37 @@
.identifiers-wrap {
display: flex;
align-items: flex-start;
}
.identifier-dir-tree {
background: #fff;
border: solid 1px #ddd;
border-radius: 0.25em;
top: 52px;
position: -webkit-sticky;
position: sticky;
max-height: calc(100vh - 155px);
overflow-y: scroll;
min-width: 200px;
margin-left: 1em;
}
.identifier-dir-tree-header {
padding: 0.5em;
background-color: #fafafa;
border-bottom: solid 1px #ddd;
}
.identifier-dir-tree-content {
padding: 0 0.5em 0;
}
.identifier-dir-tree-content > div {
padding-top: 0.25em;
padding-bottom: 0.25em;
}
.identifier-dir-tree-content a {
color: inherit;
}

134
docs/css/manual.css Normal file
View File

@@ -0,0 +1,134 @@
.github-markdown .manual-toc {
padding-left: 0;
}
.manual-index .manual-cards {
display: flex;
flex-wrap: wrap;
}
.manual-index .manual-card-wrap {
width: 280px;
padding: 10px 20px 10px 0;
box-sizing: border-box;
}
.manual-index .manual-card-wrap > h1 {
margin: 0;
font-size: 1em;
font-weight: 600;
padding: 0.2em 0 0.2em 0.5em;
border-radius: 0.1em 0.1em 0 0;
border: none;
}
.manual-index .manual-card-wrap > h1 span {
color: #555;
}
.manual-index .manual-card {
height: 200px;
overflow: hidden;
border: solid 1px rgba(230, 230, 230, 0.84);
border-radius: 0 0 0.1em 0.1em;
padding: 8px;
position: relative;
}
.manual-index .manual-card > div {
transform: scale(0.4);
transform-origin: 0 0;
width: 250%;
}
.manual-index .manual-card > a {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(210, 210, 210, 0.1);
}
.manual-index .manual-card > a:hover {
background: none;
}
.manual-index .manual-badge {
margin: 0;
}
.manual-index .manual-user-index {
margin-bottom: 1em;
border-bottom: solid 1px #ddd;
}
.manual-root .navigation {
padding-left: 4px;
margin-top: 4px;
}
.navigation .manual-toc-root > div {
padding-left: 0.25em;
padding-right: 0.75em;
}
.github-markdown .manual-toc-title a {
color: inherit;
}
.manual-breadcrumb-list {
font-size: 0.8em;
margin-bottom: 1em;
}
.manual-toc-title a:hover {
color: #039BE5;
}
.manual-toc li {
margin: 0.75em 0;
list-style-type: none;
}
.navigation .manual-toc [class^="indent-h"] a {
color: #666;
}
.navigation .manual-toc .indent-h1 a {
color: #555;
font-weight: 600;
display: block;
}
.manual-toc .indent-h1 {
display: block;
margin: 0.4em 0 0 0.25em;
padding: 0.2em 0 0.2em 0.5em;
border-radius: 0.1em;
}
.manual-root .navigation .manual-toc li:not(.indent-h1) {
margin-top: 0.5em;
}
.manual-toc .indent-h2 {
display: none;
margin-left: 1.5em;
}
.manual-toc .indent-h3 {
display: none;
margin-left: 2.5em;
}
.manual-toc .indent-h4 {
display: none;
margin-left: 3.5em;
}
.manual-toc .indent-h5 {
display: none;
margin-left: 4.5em;
}
.manual-nav li {
margin: 0.75em 0;
}

View File

@@ -0,0 +1,132 @@
/* Tomorrow Theme */
/* Original theme - https://github.com/chriskempson/tomorrow-theme */
/* Pretty printing styles. Used with prettify.js. */
/* SPAN elements with the classes below are added by prettyprint. */
/* plain text */
.pln {
color: #4d4d4c; }
@media screen {
/* string content */
.str {
color: #718c00; }
/* a keyword */
.kwd {
color: #8959a8; }
/* a comment */
.com {
color: #8e908c; }
/* a type name */
.typ {
color: #4271ae; }
/* a literal value */
.lit {
color: #f5871f; }
/* punctuation */
.pun {
color: #4d4d4c; }
/* lisp open bracket */
.opn {
color: #4d4d4c; }
/* lisp close bracket */
.clo {
color: #4d4d4c; }
/* a markup tag name */
.tag {
color: #c82829; }
/* a markup attribute name */
.atn {
color: #f5871f; }
/* a markup attribute value */
.atv {
color: #3e999f; }
/* a declaration */
.dec {
color: #f5871f; }
/* a variable name */
.var {
color: #c82829; }
/* a function name */
.fun {
color: #4271ae; } }
/* Use higher contrast and text-weight for printable form. */
@media print, projection {
.str {
color: #060; }
.kwd {
color: #006;
font-weight: bold; }
.com {
color: #600;
font-style: italic; }
.typ {
color: #404;
font-weight: bold; }
.lit {
color: #044; }
.pun, .opn, .clo {
color: #440; }
.tag {
color: #006;
font-weight: bold; }
.atn {
color: #404; }
.atv {
color: #060; } }
/* Style */
/*
pre.prettyprint {
background: white;
font-family: Consolas, Monaco, 'Andale Mono', monospace;
font-size: 12px;
line-height: 1.5;
border: 1px solid #ccc;
padding: 10px; }
*/
/* Specify class=linenums on a pre to get line numbering */
ol.linenums {
margin-top: 0;
margin-bottom: 0; }
/* IE indents via margin-left */
li.L0,
li.L1,
li.L2,
li.L3,
li.L4,
li.L5,
li.L6,
li.L7,
li.L8,
li.L9 {
/* */ }
/* Alternate shading for lines */
li.L1,
li.L3,
li.L5,
li.L7,
li.L9 {
/* */ }

84
docs/css/search.css Normal file
View File

@@ -0,0 +1,84 @@
/* search box */
.search-box {
position: absolute;
top: 10px;
right: 50px;
padding-right: 8px;
padding-bottom: 10px;
line-height: normal;
font-size: 12px;
}
.search-box img {
width: 20px;
vertical-align: top;
}
.search-input {
display: inline;
visibility: hidden;
width: 0;
padding: 2px;
height: 1.5em;
outline: none;
background: transparent;
border: 1px #0af;
border-style: none none solid none;
vertical-align: bottom;
}
.search-input-edge {
display: none;
width: 1px;
height: 5px;
background-color: #0af;
vertical-align: bottom;
}
.search-result {
position: absolute;
display: none;
height: 600px;
width: 100%;
padding: 0;
margin-top: 5px;
margin-left: 24px;
background: white;
box-shadow: 1px 1px 4px rgb(0,0,0);
white-space: nowrap;
overflow-y: scroll;
}
.search-result-import-path {
color: #aaa;
font-size: 12px;
}
.search-result li {
list-style: none;
padding: 2px 4px;
}
.search-result li a {
display: block;
}
.search-result li.selected {
background: #ddd;
}
.search-result li.search-separator {
background: rgb(37, 138, 175);
color: white;
}
.search-box.active .search-input {
visibility: visible;
transition: width 0.2s ease-out;
width: 300px;
}
.search-box.active .search-input-edge {
display: inline-block;
}

55
docs/css/source.css Normal file
View File

@@ -0,0 +1,55 @@
table.files-summary {
width: 100%;
margin: 10px 0;
border-spacing: 0;
border: 0;
border-collapse: collapse;
text-align: right;
}
table.files-summary tbody tr:hover {
background: #eee;
}
table.files-summary td:first-child,
table.files-summary td:nth-of-type(2) {
text-align: left;
}
table.files-summary[data-use-coverage="false"] td.coverage {
display: none;
}
table.files-summary thead {
background: #fafafa;
}
table.files-summary td {
border: solid 1px #ddd;
padding: 4px 10px;
vertical-align: top;
}
table.files-summary td.identifiers > span {
display: block;
margin-top: 4px;
}
table.files-summary td.identifiers > span:first-child {
margin-top: 0;
}
table.files-summary .coverage-count {
font-size: 12px;
color: #aaa;
display: inline-block;
min-width: 40px;
}
.total-coverage-count {
position: relative;
bottom: 2px;
font-size: 12px;
color: #666;
font-weight: 500;
padding-left: 5px;
}

608
docs/css/style.css Normal file
View File

@@ -0,0 +1,608 @@
@import url(https://fonts.googleapis.com/css?family=Roboto:400,300,700);
@import url(https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400italic,600,700);
@import url(./manual.css);
@import url(./source.css);
@import url(./test.css);
@import url(./identifiers.css);
@import url(./github.css);
@import url(./search.css);
* {
margin: 0;
padding: 0;
text-decoration: none;
}
html
{
font-family: 'Source Sans Pro', 'Roboto', sans-serif;
overflow: auto;
/*font-size: 14px;*/
/*color: #4d4e53;*/
/*color: rgba(0, 0, 0, .68);*/
color: #555;
background-color: #fff;
}
a {
/*color: #0095dd;*/
/*color:rgb(37, 138, 175);*/
color: #039BE5;
}
code a:hover {
text-decoration: underline;
}
ul, ol {
padding-left: 20px;
}
ul li {
list-style: disc;
margin: 4px 0;
}
ol li {
margin: 4px 0;
}
h1 {
margin-bottom: 10px;
font-size: 34px;
font-weight: 300;
border-bottom: solid 1px #ddd;
}
h2 {
margin-top: 24px;
margin-bottom: 10px;
font-size: 20px;
border-bottom: solid 1px #ddd;
font-weight: 300;
}
h3 {
position: relative;
font-size: 16px;
margin-bottom: 12px;
padding: 4px;
font-weight: 300;
}
details {
cursor: pointer;
}
del {
text-decoration: line-through;
}
p {
margin-bottom: 15px;
line-height: 1.5;
}
code {
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
}
pre > code {
display: block;
}
pre.prettyprint, pre > code {
padding: 4px;
margin: 1em 0;
background-color: #f5f5f5;
border-radius: 3px;
}
pre.prettyprint > code {
margin: 0;
}
p > code,
li > code {
padding: 0.2em 0.5em;
margin: 0;
font-size: 85%;
background-color: rgba(0,0,0,0.04);
border-radius: 3px;
}
.code {
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
font-size: 13px;
}
.import-path pre.prettyprint,
.import-path pre.prettyprint code {
margin: 0;
padding: 0;
border: none;
background: white;
}
.layout-container {
/*display: flex;*/
/*flex-direction: row;*/
/*justify-content: flex-start;*/
/*align-items: stretch;*/
}
.layout-container > header {
display: flex;
height: 40px;
line-height: 40px;
font-size: 16px;
padding: 0 10px;
margin: 0;
position: fixed;
width: 100%;
z-index: 1;
background-color: #fafafa;
top: 0;
border-bottom: solid 1px #ddd;
}
.layout-container > header > a{
margin: 0 5px;
color: #444;
}
.layout-container > header > a.repo-url-github {
font-size: 0;
display: inline-block;
width: 20px;
height: 38px;
background: url("../image/github.png") no-repeat center;
background-size: 20px;
vertical-align: top;
}
.navigation {
position: fixed;
top: 0;
left: 0;
box-sizing: border-box;
width: 250px;
height: 100%;
padding-top: 40px;
padding-left: 15px;
padding-bottom: 2em;
margin-top:1em;
overflow-x: scroll;
box-shadow: rgba(255, 255, 255, 1) -1px 0 0 inset;
border-right: 1px solid #ddd;
}
.navigation ul {
padding: 0;
}
.navigation li {
list-style: none;
margin: 4px 0;
white-space: nowrap;
}
.navigation li a {
color: #666;
}
.navigation .nav-dir-path {
display: block;
margin-top: 0.7em;
margin-bottom: 0.25em;
font-weight: 600;
}
.kind-class,
.kind-interface,
.kind-function,
.kind-typedef,
.kind-variable,
.kind-external {
margin-left: 0.75em;
width: 1.2em;
height: 1.2em;
display: inline-block;
text-align: center;
border-radius: 0.2em;
margin-right: 0.2em;
font-weight: bold;
line-height: 1.2em;
}
.kind-class {
color: #009800;
background-color: #bfe5bf;
}
.kind-interface {
color: #fbca04;
background-color: #fef2c0;
}
.kind-function {
color: #6b0090;
background-color: #d6bdde;
}
.kind-variable {
color: #eb6420;
background-color: #fad8c7;
}
.kind-typedef {
color: #db001e;
background-color: #edbec3;
}
.kind-external {
color: #0738c3;
background-color: #bbcbea;
}
.summary span[class^="kind-"] {
margin-left: 0;
}
h1 .version,
h1 .url a {
font-size: 14px;
color: #aaa;
}
.content {
margin-top: 40px;
margin-left: 250px;
padding: 10px 50px 10px 20px;
}
.header-notice {
font-size: 14px;
color: #aaa;
margin: 0;
}
.expression-extends .prettyprint {
margin-left: 10px;
background: white;
}
.extends-chain {
border-bottom: 1px solid#ddd;
padding-bottom: 10px;
margin-bottom: 10px;
}
.extends-chain span:nth-of-type(1) {
padding-left: 10px;
}
.extends-chain > div {
margin: 5px 0;
}
.description table {
font-size: 14px;
border-spacing: 0;
border: 0;
border-collapse: collapse;
}
.description thead {
background: #999;
color: white;
}
.description table td,
.description table th {
border: solid 1px #ddd;
padding: 4px;
font-weight: normal;
}
.flat-list ul {
padding-left: 0;
}
.flat-list li {
display: inline;
list-style: none;
}
table.summary {
width: 100%;
margin: 10px 0;
border-spacing: 0;
border: 0;
border-collapse: collapse;
}
table.summary thead {
background: #fafafa;
}
table.summary td {
border: solid 1px #ddd;
padding: 4px 10px;
}
table.summary tbody td:nth-child(1) {
text-align: right;
white-space: nowrap;
min-width: 64px;
vertical-align: top;
}
table.summary tbody td:nth-child(2) {
width: 100%;
border-right: none;
}
table.summary tbody td:nth-child(3) {
white-space: nowrap;
border-left: none;
vertical-align: top;
}
table.summary td > div:nth-of-type(2) {
padding-top: 4px;
padding-left: 15px;
}
table.summary td p {
margin-bottom: 0;
}
.inherited-summary thead td {
padding-left: 2px;
}
.inherited-summary thead a {
color: white;
}
.inherited-summary .summary tbody {
display: none;
}
.inherited-summary .summary .toggle {
padding: 0 4px;
font-size: 12px;
cursor: pointer;
}
.inherited-summary .summary .toggle.closed:before {
content: "▶";
}
.inherited-summary .summary .toggle.opened:before {
content: "▼";
}
.member, .method {
margin-bottom: 24px;
}
table.params {
width: 100%;
margin: 10px 0;
border-spacing: 0;
border: 0;
border-collapse: collapse;
}
table.params thead {
background: #eee;
color: #aaa;
}
table.params td {
padding: 4px;
border: solid 1px #ddd;
}
table.params td p {
margin: 0;
}
.content .detail > * {
margin: 15px 0;
}
.content .detail > h3 {
color: black;
background-color: #f0f0f0;
}
.content .detail > div {
margin-left: 10px;
}
.content .detail > .import-path {
margin-top: -8px;
}
.content .detail + .detail {
margin-top: 30px;
}
.content .detail .throw td:first-child {
padding-right: 10px;
}
.content .detail h4 + :not(pre) {
padding-left: 0;
margin-left: 10px;
}
.content .detail h4 + ul li {
list-style: none;
}
.return-param * {
display: inline;
}
.argument-params {
margin-bottom: 20px;
}
.return-type {
padding-right: 10px;
font-weight: normal;
}
.return-desc {
margin-left: 10px;
margin-top: 4px;
}
.return-desc p {
margin: 0;
}
.deprecated, .experimental, .instance-docs {
border-left: solid 5px orange;
padding-left: 4px;
margin: 4px 0;
}
tr.listen p,
tr.throw p,
tr.emit p{
margin-bottom: 10px;
}
.version, .since {
color: #aaa;
}
h3 .right-info {
position: absolute;
right: 4px;
font-size: 14px;
}
.version + .since:before {
content: '| ';
}
.see {
margin-top: 10px;
}
.see h4 {
margin: 4px 0;
}
.content .detail h4 + .example-doc {
margin: 6px 0;
}
.example-caption {
position: relative;
bottom: -1px;
display: inline-block;
padding: 4px;
font-style: italic;
background-color: #f5f5f5;
font-weight: bold;
border-radius: 3px;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.example-caption + pre.source-code {
margin-top: 0;
border-top-left-radius: 0;
}
footer, .file-footer {
text-align: right;
font-style: italic;
font-weight: 100;
font-size: 13px;
margin-right: 50px;
margin-left: 270px;
border-top: 1px solid #ddd;
padding-top: 30px;
margin-top: 20px;
padding-bottom: 10px;
}
footer img {
width: 24px;
vertical-align: middle;
padding-left: 4px;
position: relative;
top: -3px;
opacity: 0.6;
}
pre.source-code {
padding: 4px;
}
pre.raw-source-code > code {
padding: 0;
margin: 0;
font-size: 12px;
background: #fff;
border: solid 1px #ddd;
line-height: 1.5;
}
pre.raw-source-code > code > ol {
counter-reset:number;
list-style:none;
margin:0;
padding:0;
overflow: hidden;
}
pre.raw-source-code > code > ol li:before {
counter-increment: number;
content: counter(number);
display: inline-block;
min-width: 3em;
color: #aaa;
text-align: right;
padding-right: 1em;
}
pre.source-code.line-number {
padding: 0;
}
pre.source-code ol {
background: #eee;
padding-left: 40px;
}
pre.source-code li {
background: white;
padding-left: 4px;
list-style: decimal;
margin: 0;
}
pre.source-code.line-number li.active {
background: rgb(255, 255, 150) !important;
}
pre.source-code.line-number li.error-line {
background: #ffb8bf;
}
.inner-link-active {
/*background: rgb(255, 255, 150) !important;*/
background: #039BE5 !important;
color: #fff !important;
padding-left: 0.1em !important;
}
.inner-link-active a {
color: inherit;
}

58
docs/css/test.css Normal file
View File

@@ -0,0 +1,58 @@
table.test-summary thead {
background: #fafafa;
}
table.test-summary thead .test-description {
width: 50%;
}
table.test-summary {
width: 100%;
margin: 10px 0;
border-spacing: 0;
border: 0;
border-collapse: collapse;
}
table.test-summary thead .test-count {
width: 3em;
}
table.test-summary tbody tr:hover {
background-color: #eee;
}
table.test-summary td {
border: solid 1px #ddd;
padding: 4px 10px;
vertical-align: top;
}
table.test-summary td p {
margin: 0;
}
table.test-summary tr.test-interface .toggle {
display: inline-block;
float: left;
margin-right: 4px;
cursor: pointer;
font-size: 0.8em;
padding-top: 0.25em;
}
table.test-summary tr.test-interface .toggle.opened:before {
content: '▼';
}
table.test-summary tr.test-interface .toggle.closed:before {
content: '▶';
}
table.test-summary .test-target > span {
display: block;
margin-top: 4px;
}
table.test-summary .test-target > span:first-child {
margin-top: 0;
}

View File

@@ -0,0 +1,143 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<base data-ice="baseUrl" href="../../../">
<title data-ice="title">src/demo/App.js | simple-keyboard</title>
<link type="text/css" rel="stylesheet" href="css/style.css">
<link type="text/css" rel="stylesheet" href="css/prettify-tomorrow.css">
<script src="script/prettify/prettify.js"></script>
<script src="script/manual.js"></script>
<meta name="description" content="On-screen Javascript Virtual Keyboard"><meta property="twitter:card" content="summary"><meta property="twitter:title" content="simple-keyboard"><meta property="twitter:description" content="On-screen Javascript Virtual Keyboard"></head>
<body class="layout-container" data-ice="rootContainer">
<header>
<a href="./">Home</a>
<a href="identifiers.html">Reference</a>
<a href="source.html">Source</a>
<div class="search-box">
<span>
<img src="./image/search.png">
<span class="search-input-edge"></span><input class="search-input"><span class="search-input-edge"></span>
</span>
<ul class="search-result"></ul>
</div>
<a style="position:relative; top:3px;" href="https://github.com/hodgef/simple-keyboard"><img width="20px" src="./image/github.png"></a></header>
<nav class="navigation" data-ice="nav"><div>
<ul>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#demo">demo</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/demo/App.js~App.html">App</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-components">lib/components</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/components/Keyboard.js~SimpleKeyboard.html">SimpleKeyboard</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-services">lib/services</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/KeyboardLayout.js~KeyboardLayout.html">KeyboardLayout</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html">PhysicalKeyboard</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/Utilities.js~Utilities.html">Utilities</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-tests">lib/tests</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/tests/TestUtility.js~TestUtility.html">TestUtility</a></span></span></li>
</ul>
</div>
</nav>
<div class="content" data-ice="content"><h1 data-ice="title">src/demo/App.js</h1>
<pre class="source-code line-number raw-source-code"><code class="prettyprint linenums" data-ice="content">import Keyboard from &apos;../lib&apos;;
import &apos;./css/App.css&apos;;
/**
* simple-keyboard demo
*/
class App {
/**
* Instantiates the demo class
*/
constructor(){
document.addEventListener(&apos;DOMContentLoaded&apos;, this.onDOMLoaded);
/**
* Default input name
* @type {string}
*/
this.layoutName = &quot;default&quot;;
}
/**
* Executed when the DOM is ready
*/
onDOMLoaded = () =&gt; {
/**
* Creates a new simple-keyboard instance
*/
this.keyboard = new Keyboard({
//debug: true,
layoutName: this.layoutName,
onChange: input =&gt; this.onChange(input),
onKeyPress: button =&gt; this.onKeyPress(button),
newLineOnEnter: true,
physicalKeyboardHighlight: true,
});
/**
* Adding preview (demo only)
*/
document.querySelector(&apos;.simple-keyboard&apos;).insertAdjacentHTML(&apos;beforebegin&apos;, `
&lt;div class=&quot;simple-keyboard-preview&quot;&gt;
&lt;textarea class=&quot;input&quot;&gt;&lt;/textarea&gt;
&lt;/div&gt;
`);
document.querySelector(&apos;.input&apos;).addEventListener(&apos;change&apos;, (event) =&gt; {
this.keyboard.setInput(event.target.value);
});
}
/**
* Handles shift functionality
*/
handleShiftButton = () =&gt; {
let layoutName = this.layoutName;
let shiftToggle = this.layoutName = layoutName === &quot;default&quot; ? &quot;shift&quot; : &quot;default&quot;;
this.keyboard.setOptions({
layoutName: shiftToggle
});
}
/**
* Called when simple-keyboard input has changed
*/
onChange = input =&gt; {
document.querySelector(&apos;.input&apos;).value = input;
}
/**
* Called when a simple-keyboard key is pressed
*/
onKeyPress = button =&gt; {
console.log(&quot;Button pressed&quot;, button);
/**
* Shift functionality
*/
if(button === &quot;{lock}&quot; || button === &quot;{shift}&quot;)
this.handleShiftButton();
}
}
export default App;</code></pre>
</div>
<footer class="footer">
Generated by <a href="https://esdoc.org">ESDoc<span data-ice="esdocVersion">(1.1.0)</span><img src="./image/esdoc-logo-mini-black.png"></a>
</footer>
<script src="script/search_index.js"></script>
<script src="script/search.js"></script>
<script src="script/pretty-print.js"></script>
<script src="script/inherited-summary.js"></script>
<script src="script/test-summary.js"></script>
<script src="script/inner-link.js"></script>
<script src="script/patch-for-local.js"></script>
</body>
</html>

View File

@@ -0,0 +1,64 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<base data-ice="baseUrl" href="../../../">
<title data-ice="title">src/demo/index.js | simple-keyboard</title>
<link type="text/css" rel="stylesheet" href="css/style.css">
<link type="text/css" rel="stylesheet" href="css/prettify-tomorrow.css">
<script src="script/prettify/prettify.js"></script>
<script src="script/manual.js"></script>
<meta name="description" content="On-screen Javascript Virtual Keyboard"><meta property="twitter:card" content="summary"><meta property="twitter:title" content="simple-keyboard"><meta property="twitter:description" content="On-screen Javascript Virtual Keyboard"></head>
<body class="layout-container" data-ice="rootContainer">
<header>
<a href="./">Home</a>
<a href="identifiers.html">Reference</a>
<a href="source.html">Source</a>
<div class="search-box">
<span>
<img src="./image/search.png">
<span class="search-input-edge"></span><input class="search-input"><span class="search-input-edge"></span>
</span>
<ul class="search-result"></ul>
</div>
<a style="position:relative; top:3px;" href="https://github.com/hodgef/simple-keyboard"><img width="20px" src="./image/github.png"></a></header>
<nav class="navigation" data-ice="nav"><div>
<ul>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#demo">demo</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/demo/App.js~App.html">App</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-components">lib/components</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/components/Keyboard.js~SimpleKeyboard.html">SimpleKeyboard</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-services">lib/services</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/KeyboardLayout.js~KeyboardLayout.html">KeyboardLayout</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html">PhysicalKeyboard</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/Utilities.js~Utilities.html">Utilities</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-tests">lib/tests</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/tests/TestUtility.js~TestUtility.html">TestUtility</a></span></span></li>
</ul>
</div>
</nav>
<div class="content" data-ice="content"><h1 data-ice="title">src/demo/index.js</h1>
<pre class="source-code line-number raw-source-code"><code class="prettyprint linenums" data-ice="content">import App from &apos;./App&apos;;
/**
* Initializing demo
*/
new App();</code></pre>
</div>
<footer class="footer">
Generated by <a href="https://esdoc.org">ESDoc<span data-ice="esdocVersion">(1.1.0)</span><img src="./image/esdoc-logo-mini-black.png"></a>
</footer>
<script src="script/search_index.js"></script>
<script src="script/search.js"></script>
<script src="script/pretty-print.js"></script>
<script src="script/inherited-summary.js"></script>
<script src="script/test-summary.js"></script>
<script src="script/inner-link.js"></script>
<script src="script/patch-for-local.js"></script>
</body>
</html>

View File

@@ -0,0 +1,818 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<base data-ice="baseUrl" href="../../../../">
<title data-ice="title">src/lib/components/Keyboard.js | simple-keyboard</title>
<link type="text/css" rel="stylesheet" href="css/style.css">
<link type="text/css" rel="stylesheet" href="css/prettify-tomorrow.css">
<script src="script/prettify/prettify.js"></script>
<script src="script/manual.js"></script>
<meta name="description" content="On-screen Javascript Virtual Keyboard"><meta property="twitter:card" content="summary"><meta property="twitter:title" content="simple-keyboard"><meta property="twitter:description" content="On-screen Javascript Virtual Keyboard"></head>
<body class="layout-container" data-ice="rootContainer">
<header>
<a href="./">Home</a>
<a href="identifiers.html">Reference</a>
<a href="source.html">Source</a>
<div class="search-box">
<span>
<img src="./image/search.png">
<span class="search-input-edge"></span><input class="search-input"><span class="search-input-edge"></span>
</span>
<ul class="search-result"></ul>
</div>
<a style="position:relative; top:3px;" href="https://github.com/hodgef/simple-keyboard"><img width="20px" src="./image/github.png"></a></header>
<nav class="navigation" data-ice="nav"><div>
<ul>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#demo">demo</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/demo/App.js~App.html">App</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-components">lib/components</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/components/Keyboard.js~SimpleKeyboard.html">SimpleKeyboard</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-services">lib/services</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/KeyboardLayout.js~KeyboardLayout.html">KeyboardLayout</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html">PhysicalKeyboard</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/Utilities.js~Utilities.html">Utilities</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-tests">lib/tests</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/tests/TestUtility.js~TestUtility.html">TestUtility</a></span></span></li>
</ul>
</div>
</nav>
<div class="content" data-ice="content"><h1 data-ice="title">src/lib/components/Keyboard.js</h1>
<pre class="source-code line-number raw-source-code"><code class="prettyprint linenums" data-ice="content">import &apos;./Keyboard.css&apos;;
// Services
import PhysicalKeyboard from &apos;../services/PhysicalKeyboard&apos;;
import KeyboardLayout from &apos;../services/KeyboardLayout&apos;;
import Utilities from &apos;../services/Utilities&apos;;
/**
* Root class for simple-keyboard
* This class:
* - Parses the options
* - Renders the rows and buttons
* - Handles button functionality
*/
class 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.
*/
constructor(...params){
let keyboardDOMQuery = typeof params[0] === &quot;string&quot; ? params[0] : &apos;.simple-keyboard&apos;;
let options = typeof params[0] === &quot;object&quot; ? params[0] : params[1];
if(!options)
options = {};
/**
* Initializing Utilities
*/
this.utilities = new Utilities(this);
/**
* Processing options
*/
this.keyboardDOM = document.querySelector(keyboardDOMQuery);
/**
* @type {object}
* @property {object} layout Modify the keyboard layout.
* @property {string} layoutName Specifies which layout should be used.
* @property {object} display Replaces variable buttons (such as {bksp}) with a human-friendly name (e.g.: &#x201C;backspace&#x201D;).
* @property {boolean} mergeDisplay By default, when you set the display property, you replace the default one. This setting merges them instead.
* @property {string} theme A prop to add your own css classes to the keyboard wrapper. You can add multiple classes separated by a space.
* @property {Array} buttonTheme A prop to add your own css classes to one or several buttons.
* @property {boolean} debug Runs a console.log every time a key is pressed. Displays the buttons pressed and the current input.
* @property {boolean} newLineOnEnter Specifies whether clicking the &#x201C;ENTER&#x201D; button will input a newline (\n) or not.
* @property {boolean} tabCharOnTab Specifies whether clicking the &#x201C;TAB&#x201D; button will input a tab character (\t) or not.
* @property {string} inputName Allows you to use a single simple-keyboard instance for several inputs.
* @property {number} maxLength Restrains all of simple-keyboard inputs to a certain length. This should be used in addition to the input element&#x2019;s maxlengthattribute.
* @property {object} maxLength Restrains simple-keyboard&#x2019;s individual inputs to a certain length. This should be used in addition to the input element&#x2019;s maxlengthattribute.
* @property {boolean} syncInstanceInputs When set to true, this option synchronizes the internal input of every simple-keyboard instance.
* @property {boolean} physicalKeyboardHighlight Enable highlighting of keys pressed on physical keyboard.
* @property {string} physicalKeyboardHighlightTextColor Define the text color that the physical keyboard highlighted key should have.
* @property {string} physicalKeyboardHighlightBgColor Define the background color that the physical keyboard highlighted key should have.
* @property {function(button: string):string} onKeyPress Executes the callback function on key press. Returns button layout name (i.e.: &#x201C;{shift}&#x201D;).
* @property {function(input: string):string} onChange Executes the callback function on input change. Returns the current input&#x2019;s string.
* @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.
*/
this.options = options;
this.options.layoutName = this.options.layoutName || &quot;default&quot;;
this.options.theme = this.options.theme || &quot;hg-theme-default&quot;;
this.options.inputName = this.options.inputName || &quot;default&quot;;
/**
* @type {object} Classes identifying loaded plugins
*/
this.keyboardPluginClasses = &apos;&apos;;
/**
* Bindings
*/
this.handleButtonClicked = this.handleButtonClicked.bind(this);
this.syncInstanceInputs = this.syncInstanceInputs.bind(this);
this.clearInput = this.clearInput.bind(this);
this.getInput = this.getInput.bind(this);
this.setInput = this.setInput.bind(this);
this.replaceInput = this.replaceInput.bind(this);
this.clear = this.clear.bind(this);
this.dispatch = this.dispatch.bind(this);
this.addButtonTheme = this.addButtonTheme.bind(this);
this.removeButtonTheme = this.removeButtonTheme.bind(this);
this.getButtonElement = this.getButtonElement.bind(this);
this.handleCaret = this.handleCaret.bind(this);
this.caretEventHandler = this.caretEventHandler.bind(this);
this.onInit = this.onInit.bind(this);
this.onRender = this.onRender.bind(this);
this.render = this.render.bind(this);
this.loadModules = this.loadModules.bind(this);
this.handleButtonMouseUp = this.handleButtonMouseUp.bind(this);
this.handleButtonMouseDown = this.handleButtonMouseDown.bind(this);
this.handleButtonHold = this.handleButtonHold.bind(this);
this.onModulesLoaded = this.onModulesLoaded.bind(this);
/**
* simple-keyboard uses a non-persistent internal input to keep track of the entered string (the variable `keyboard.input`).
* This removes any dependency to input DOM elements. You can type and directly display the value in a div element, for example.
* @example
* // To get entered input
* let input = keyboard.getInput();
*
* // To clear entered input.
* keyboard.clearInput();
*
* @type {object}
* @property {object} default Default SimpleKeyboard internal input.
* @property {object} myInputName Example input that can be set through `options.inputName:&quot;myInputName&quot;`.
*/
this.input = {};
this.input[this.options.inputName] = &apos;&apos;;
/**
* @type {string} DOM class of the keyboard wrapper, normally &quot;simple-keyboard&quot; by default.
*/
this.keyboardDOMClass = keyboardDOMQuery.split(&apos;.&apos;).join(&quot;&quot;);
/**
* @type {object} Contains the DOM elements of every rendered button, the key being the button&apos;s layout name (e.g.: &quot;{enter}&quot;).
*/
this.buttonElements = {};
/**
* Rendering keyboard
*/
if(this.keyboardDOM)
this.render();
else {
console.warn(`&quot;${keyboardDOMQuery}&quot; was not found in the DOM.`);
throw new Error(&quot;KEYBOARD_DOM_ERROR&quot;);
}
/**
* Saving instance
* This enables multiple simple-keyboard support with easier management
*/
if(!window[&apos;SimpleKeyboardInstances&apos;])
window[&apos;SimpleKeyboardInstances&apos;] = {};
window[&apos;SimpleKeyboardInstances&apos;][this.utilities.camelCase(this.keyboardDOMClass)] = this;
/**
* Physical Keyboard support
*/
this.physicalKeyboardInterface = new PhysicalKeyboard(this);
/**
* Modules
*/
this.modules = {};
this.loadModules();
}
/**
* Handles clicks made to keyboard buttons
* @param {string} button The button&apos;s layout name.
*/
handleButtonClicked(button){
let debug = this.options.debug;
/**
* Ignoring placeholder buttons
*/
if(button === &apos;{//}&apos;)
return false;
/**
* Calling onKeyPress
*/
if(typeof this.options.onKeyPress === &quot;function&quot;)
this.options.onKeyPress(button);
if(!this.input[this.options.inputName])
this.input[this.options.inputName] = &apos;&apos;;
let updatedInput = this.utilities.getUpdatedInput(button, this.input[this.options.inputName], this.options, this.caretPosition);
if(this.input[this.options.inputName] !== updatedInput){
/**
* If maxLength and handleMaxLength yield true, halting
*/
if(this.options.maxLength &amp;&amp; this.utilities.handleMaxLength(this.input, this.options, updatedInput)){
return false;
}
this.input[this.options.inputName] = updatedInput;
if(debug)
console.log(&apos;Input changed:&apos;, this.input);
/**
* Enforce syncInstanceInputs, if set
*/
if(this.options.syncInstanceInputs)
this.syncInstanceInputs(this.input);
/**
* Calling onChange
*/
if(typeof this.options.onChange === &quot;function&quot;)
this.options.onChange(this.input[this.options.inputName]);
}
if(debug){
console.log(&quot;Key pressed:&quot;, button);
}
}
/**
* Handles button mousedown
*/
/* istanbul ignore next */
handleButtonMouseDown(button, e){
/**
* @type {boolean} Whether the mouse is being held onKeyPress
*/
this.isMouseHold = true;
if(this.holdInteractionTimeout)
clearTimeout(this.holdInteractionTimeout);
if(this.holdTimeout)
clearTimeout(this.holdTimeout);
/**
* @type {object} Time to wait until a key hold is detected
*/
this.holdTimeout = setTimeout(() =&gt; {
if(
this.isMouseHold &amp;&amp;
(
(!button.includes(&quot;{&quot;) &amp;&amp; !button.includes(&quot;}&quot;)) ||
button === &quot;{bksp}&quot; ||
button === &quot;{space}&quot; ||
button === &quot;{tab}&quot;
)
){
if(this.options.debug)
console.log(&quot;Button held:&quot;, button);
this.handleButtonHold(button, e);
}
clearTimeout(this.holdTimeout);
}, 500);
}
/**
* Handles button mouseup
*/
handleButtonMouseUp(){
this.isMouseHold = false;
if(this.holdInteractionTimeout)
clearTimeout(this.holdInteractionTimeout);
}
/**
* Handles button hold
*/
/* istanbul ignore next */
handleButtonHold(button){
/**
* @type {object} Timeout dictating the speed of key hold iterations
*/
this.holdInteractionTimeout = setTimeout(() =&gt; {
this.handleButtonClicked(button);
this.handleButtonHold(button);
}, 100);
}
/**
* Send a command to all simple-keyboard instances (if you have several instances).
*/
syncInstanceInputs(){
this.dispatch((instance) =&gt; {
instance.replaceInput(this.input);
});
}
/**
* Clear the keyboard&#x2019;s input.
* @param {string} [inputName] optional - the internal input to select
*/
clearInput(inputName){
inputName = inputName || this.options.inputName;
this.input[this.options.inputName] = &apos;&apos;;
/**
* Enforce syncInstanceInputs, if set
*/
if(this.options.syncInstanceInputs)
this.syncInstanceInputs(this.input);
}
/**
* Get the keyboard&#x2019;s input (You can also get it from the onChange prop).
* @param {string} [inputName] optional - the internal input to select
*/
getInput(inputName){
inputName = inputName || this.options.inputName;
/**
* Enforce syncInstanceInputs, if set
*/
if(this.options.syncInstanceInputs)
this.syncInstanceInputs(this.input);
return this.input[this.options.inputName];
}
/**
* Set the keyboard&#x2019;s input.
* @param {string} input the input value
* @param {string} inputName optional - the internal input to select
*/
setInput(input, inputName){
inputName = inputName || this.options.inputName;
this.input[inputName] = input;
/**
* Enforce syncInstanceInputs, if set
*/
if(this.options.syncInstanceInputs)
this.syncInstanceInputs(this.input);
}
/**
* Replace the input object (`keyboard.input`)
* @param {object} inputObj The input object
*/
replaceInput(inputObj){
this.input = inputObj;
}
/**
* Set new option or modify existing ones after initialization.
* @param {object} option The option to set
*/
setOptions = option =&gt; {
option = option || {};
this.options = Object.assign(this.options, option);
this.render();
}
/**
* Remove all keyboard rows and reset keyboard values.
* Used interally between re-renders.
*/
clear(){
this.keyboardDOM.innerHTML = &apos;&apos;;
this.keyboardDOM.className = this.keyboardDOMClass;
this.buttonElements = {};
}
/**
* 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){
if(!window[&apos;SimpleKeyboardInstances&apos;]){
console.warn(`SimpleKeyboardInstances is not defined. Dispatch cannot be called.`);
throw new Error(&quot;INSTANCES_VAR_ERROR&quot;);
}
return Object.keys(window[&apos;SimpleKeyboardInstances&apos;]).forEach((key) =&gt; {
callback(window[&apos;SimpleKeyboardInstances&apos;][key], key);
})
}
/**
* 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, className){
if(!className || !buttons)
return false;
buttons.split(&quot; &quot;).forEach(button =&gt; {
className.split(&quot; &quot;).forEach(classNameItem =&gt; {
if(!this.options.buttonTheme)
this.options.buttonTheme = [];
let classNameFound = false;
/**
* If class is already defined, we add button to class definition
*/
this.options.buttonTheme.map(buttonTheme =&gt; {
if(buttonTheme.class.split(&quot; &quot;).includes(classNameItem)){
classNameFound = true;
let buttonThemeArray = buttonTheme.buttons.split(&quot; &quot;);
if(!buttonThemeArray.includes(button)){
classNameFound = true;
buttonThemeArray.push(button);
buttonTheme.buttons = buttonThemeArray.join(&quot; &quot;);
}
}
return buttonTheme;
});
/**
* If class is not defined, we create a new entry
*/
if(!classNameFound){
this.options.buttonTheme.push({
class: classNameItem,
buttons: buttons
});
}
});
});
this.render();
}
/**
* 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, className){
/**
* When called with empty parameters, remove all button themes
*/
if(!buttons &amp;&amp; !className){
this.options.buttonTheme = [];
this.render();
return false;
}
/**
* If buttons are passed and buttonTheme has items
*/
if(buttons &amp;&amp; Array.isArray(this.options.buttonTheme) &amp;&amp; this.options.buttonTheme.length){
let buttonArray = buttons.split(&quot; &quot;);
buttonArray.forEach((button, key) =&gt; {
this.options.buttonTheme.map((buttonTheme, index) =&gt; {
/**
* If className is set, we affect the buttons only for that class
* Otherwise, we afect all classes
*/
if(
(className &amp;&amp; className.includes(buttonTheme.class)) ||
!className
){
let filteredButtonArray = buttonTheme.buttons.split(&quot; &quot;).filter(item =&gt; item !== button);
/**
* If buttons left, return them, otherwise, remove button Theme
*/
if(filteredButtonArray.length){
buttonTheme.buttons = filteredButtonArray.join(&quot; &quot;);
} else {
this.options.buttonTheme.splice(index, 1);
buttonTheme = null;
}
}
return buttonTheme;
});
});
this.render();
}
}
/**
* 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){
let output;
let buttonArr = this.buttonElements[button];
if(buttonArr){
if(buttonArr.length &gt; 1){
output = buttonArr;
} else {
output = buttonArr[0];
}
}
return output;
}
/**
* Retrieves the current cursor position within a input or textarea (if any)
*/
handleCaret(){
if(this.options.debug){
console.log(&quot;Caret handling started&quot;);
}
document.addEventListener(&quot;keyup&quot;, this.caretEventHandler);
document.addEventListener(&quot;mouseup&quot;, this.caretEventHandler);
document.addEventListener(&quot;touchend&quot;, this.caretEventHandler);
}
/**
* Called by {@link handleCaret} when an event that warrants a cursor position update is triggered
*/
caretEventHandler(event){
let targetTagName = event.target.tagName.toLowerCase();
if(
targetTagName === &quot;textarea&quot; ||
targetTagName === &quot;input&quot;
){
/**
* Tracks current cursor position
* As keys are pressed, text will be added/removed at that position within the input.
*/
this.caretPosition = event.target.selectionStart;
if(this.options.debug){
console.log(&apos;Caret at: &apos;, event.target.selectionStart, event.target.tagName.toLowerCase());
}
}
}
/**
* Executes the callback function once simple-keyboard is rendered for the first time (on initialization).
*/
onInit(){
if(this.options.debug){
console.log(&quot;Initialized&quot;);
}
/**
* Caret handling
*/
this.handleCaret();
if(typeof this.options.onInit === &quot;function&quot;)
this.options.onInit();
}
/**
* Executes the callback function every time simple-keyboard is rendered (e.g: when you change layouts).
*/
onRender(){
if(typeof this.options.onRender === &quot;function&quot;)
this.options.onRender();
}
/**
* Executes the callback function once all modules have been loaded
*/
onModulesLoaded(){
if(typeof this.options.onModulesLoaded === &quot;function&quot;)
this.options.onModulesLoaded();
}
/**
* Register module
*/
registerModule = (name, initCallback) =&gt; {
if(!this.modules[name])
this.modules[name] = {};
initCallback(this.modules[name]);
}
/**
* Load modules
*/
loadModules(){
if(Array.isArray(this.options.modules)){
this.options.modules.forEach(Module =&gt; {
let module = new Module();
/* istanbul ignore next */
if(module.constructor.name &amp;&amp; module.constructor.name !== &quot;Function&quot;){
let classStr = `module-${this.utilities.camelCase(module.constructor.name)}`;
this.keyboardPluginClasses = this.keyboardPluginClasses + ` ${classStr}`;
}
module.init(this);
});
this.keyboardPluginClasses = this.keyboardPluginClasses + &apos; modules-loaded&apos;;
this.render();
this.onModulesLoaded();
}
}
/**
* Get module prop
*/
getModuleProp = (name, prop) =&gt; {
if(!this.modules[name])
return false;
return this.modules[name][prop];
}
/**
* getModulesList
*/
getModulesList = () =&gt; {
return Object.keys(this.modules);
}
/**
* Renders rows and buttons as per options
*/
render(){
/**
* Clear keyboard
*/
this.clear();
let layoutClass = this.options.layout ? &quot;hg-layout-custom&quot; : `hg-layout-${this.options.layoutName}`;
let layout = this.options.layout || KeyboardLayout.getDefaultLayout();
/**
* Account for buttonTheme, if set
*/
let buttonThemesParsed = {};
if(Array.isArray(this.options.buttonTheme)){
this.options.buttonTheme.forEach(themeObj =&gt; {
if(themeObj.buttons &amp;&amp; themeObj.class){
let themeButtons;
if(typeof themeObj.buttons === &quot;string&quot;){
themeButtons = themeObj.buttons.split(&apos; &apos;);
}
if(themeButtons){
themeButtons.forEach(themeButton =&gt; {
let themeParsed = buttonThemesParsed[themeButton];
// If the button has already been added
if(themeParsed){
// Making sure we don&apos;t add duplicate classes, even when buttonTheme has duplicates
if(!this.utilities.countInArray(themeParsed.split(&quot; &quot;), themeObj.class)){
buttonThemesParsed[themeButton] = `${themeParsed} ${themeObj.class}`;
}
} else {
buttonThemesParsed[themeButton] = themeObj.class;
}
});
}
} else {
console.warn(`buttonTheme row is missing the &quot;buttons&quot; or the &quot;class&quot;. Please check the documentation.`)
}
});
}
/**
* Adding themeClass, layoutClass to keyboardDOM
*/
this.keyboardDOM.className += ` ${this.options.theme} ${layoutClass} ${this.keyboardPluginClasses}`;
/**
* Iterating through each row
*/
layout[this.options.layoutName].forEach((row, rIndex) =&gt; {
let rowArray = row.split(&apos; &apos;);
/**
* Creating empty row
*/
var rowDOM = document.createElement(&apos;div&apos;);
rowDOM.className += &quot;hg-row&quot;;
/**
* Iterating through each button in row
*/
rowArray.forEach((button, bIndex) =&gt; {
let fctBtnClass = this.utilities.getButtonClass(button);
let buttonThemeClass = buttonThemesParsed[button];
let buttonDisplayName = this.utilities.getButtonDisplayName(button, this.options.display, this.options.mergeDisplay);
/**
* Creating button
*/
var buttonDOM = document.createElement(&apos;div&apos;);
buttonDOM.className += `hg-button ${fctBtnClass}${buttonThemeClass ? &quot; &quot;+buttonThemeClass : &quot;&quot;}`;
buttonDOM.onclick = () =&gt; this.handleButtonClicked(button);
buttonDOM.onmousedown = (e) =&gt; this.handleButtonMouseDown(button, e);
/**
* Adding identifier
*/
buttonDOM.setAttribute(&quot;data-skBtn&quot;, button);
/**
* Adding unique id
* Since there&apos;s no limit on spawning same buttons, the unique id ensures you can style every button
*/
let buttonUID = `${this.options.layoutName}-r${rIndex}b${bIndex}`;
buttonDOM.setAttribute(&quot;data-skBtnUID&quot;, buttonUID);
/**
* Adding display label
*/
buttonDOM.setAttribute(&quot;data-displayLabel&quot;, buttonDisplayName);
/**
* Adding button label to button
*/
var buttonSpanDOM = document.createElement(&apos;span&apos;);
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);
});
/**
* Appending row to keyboard
*/
this.keyboardDOM.appendChild(rowDOM);
});
/**
* Calling onRender
*/
this.onRender();
if(!this.initialized){
/**
* Ensures that onInit is only called once per instantiation
*/
this.initialized = true;
/**
* Handling mouseup
*/
document.onmouseup = () =&gt; this.handleButtonMouseUp();
/**
* Calling onInit
*/
this.onInit();
}
}
}
export default SimpleKeyboard;
</code></pre>
</div>
<footer class="footer">
Generated by <a href="https://esdoc.org">ESDoc<span data-ice="esdocVersion">(1.1.0)</span><img src="./image/esdoc-logo-mini-black.png"></a>
</footer>
<script src="script/search_index.js"></script>
<script src="script/search.js"></script>
<script src="script/pretty-print.js"></script>
<script src="script/inherited-summary.js"></script>
<script src="script/test-summary.js"></script>
<script src="script/inner-link.js"></script>
<script src="script/patch-for-local.js"></script>
</body>
</html>

View File

@@ -0,0 +1,61 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<base data-ice="baseUrl" href="../../../">
<title data-ice="title">src/lib/index.js | simple-keyboard</title>
<link type="text/css" rel="stylesheet" href="css/style.css">
<link type="text/css" rel="stylesheet" href="css/prettify-tomorrow.css">
<script src="script/prettify/prettify.js"></script>
<script src="script/manual.js"></script>
<meta name="description" content="On-screen Javascript Virtual Keyboard"><meta property="twitter:card" content="summary"><meta property="twitter:title" content="simple-keyboard"><meta property="twitter:description" content="On-screen Javascript Virtual Keyboard"></head>
<body class="layout-container" data-ice="rootContainer">
<header>
<a href="./">Home</a>
<a href="identifiers.html">Reference</a>
<a href="source.html">Source</a>
<div class="search-box">
<span>
<img src="./image/search.png">
<span class="search-input-edge"></span><input class="search-input"><span class="search-input-edge"></span>
</span>
<ul class="search-result"></ul>
</div>
<a style="position:relative; top:3px;" href="https://github.com/hodgef/simple-keyboard"><img width="20px" src="./image/github.png"></a></header>
<nav class="navigation" data-ice="nav"><div>
<ul>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#demo">demo</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/demo/App.js~App.html">App</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-components">lib/components</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/components/Keyboard.js~SimpleKeyboard.html">SimpleKeyboard</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-services">lib/services</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/KeyboardLayout.js~KeyboardLayout.html">KeyboardLayout</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html">PhysicalKeyboard</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/Utilities.js~Utilities.html">Utilities</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-tests">lib/tests</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/tests/TestUtility.js~TestUtility.html">TestUtility</a></span></span></li>
</ul>
</div>
</nav>
<div class="content" data-ice="content"><h1 data-ice="title">src/lib/index.js</h1>
<pre class="source-code line-number raw-source-code"><code class="prettyprint linenums" data-ice="content">import SimpleKeyboard from &apos;./components/Keyboard&apos;;
export default SimpleKeyboard;
</code></pre>
</div>
<footer class="footer">
Generated by <a href="https://esdoc.org">ESDoc<span data-ice="esdocVersion">(1.1.0)</span><img src="./image/esdoc-logo-mini-black.png"></a>
</footer>
<script src="script/search_index.js"></script>
<script src="script/search.js"></script>
<script src="script/pretty-print.js"></script>
<script src="script/inherited-summary.js"></script>
<script src="script/test-summary.js"></script>
<script src="script/inner-link.js"></script>
<script src="script/patch-for-local.js"></script>
</body>
</html>

View File

@@ -0,0 +1,87 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<base data-ice="baseUrl" href="../../../../">
<title data-ice="title">src/lib/services/KeyboardLayout.js | simple-keyboard</title>
<link type="text/css" rel="stylesheet" href="css/style.css">
<link type="text/css" rel="stylesheet" href="css/prettify-tomorrow.css">
<script src="script/prettify/prettify.js"></script>
<script src="script/manual.js"></script>
<meta name="description" content="On-screen Javascript Virtual Keyboard"><meta property="twitter:card" content="summary"><meta property="twitter:title" content="simple-keyboard"><meta property="twitter:description" content="On-screen Javascript Virtual Keyboard"></head>
<body class="layout-container" data-ice="rootContainer">
<header>
<a href="./">Home</a>
<a href="identifiers.html">Reference</a>
<a href="source.html">Source</a>
<div class="search-box">
<span>
<img src="./image/search.png">
<span class="search-input-edge"></span><input class="search-input"><span class="search-input-edge"></span>
</span>
<ul class="search-result"></ul>
</div>
<a style="position:relative; top:3px;" href="https://github.com/hodgef/simple-keyboard"><img width="20px" src="./image/github.png"></a></header>
<nav class="navigation" data-ice="nav"><div>
<ul>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#demo">demo</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/demo/App.js~App.html">App</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-components">lib/components</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/components/Keyboard.js~SimpleKeyboard.html">SimpleKeyboard</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-services">lib/services</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/KeyboardLayout.js~KeyboardLayout.html">KeyboardLayout</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html">PhysicalKeyboard</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/Utilities.js~Utilities.html">Utilities</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-tests">lib/tests</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/tests/TestUtility.js~TestUtility.html">TestUtility</a></span></span></li>
</ul>
</div>
</nav>
<div class="content" data-ice="content"><h1 data-ice="title">src/lib/services/KeyboardLayout.js</h1>
<pre class="source-code line-number raw-source-code"><code class="prettyprint linenums" data-ice="content">/**
* Keyboard Layout Service
*/
class KeyboardLayout {
/**
* Get default simple-keyboard layout
* @return {object} The default layout (US-QWERTY)
*/
static getDefaultLayout(){
return {
&apos;default&apos;: [
&apos;` 1 2 3 4 5 6 7 8 9 0 - = {bksp}&apos;,
&apos;{tab} q w e r t y u i o p [ ] \\&apos;,
&apos;{lock} a s d f g h j k l ; \&apos; {enter}&apos;,
&apos;{shift} z x c v b n m , . / {shift}&apos;,
&apos;.com @ {space}&apos;
],
&apos;shift&apos;: [
&apos;~ ! @ # $ % ^ &amp; * ( ) _ + {bksp}&apos;,
&apos;{tab} Q W E R T Y U I O P { } |&apos;,
&apos;{lock} A S D F G H J K L : &quot; {enter}&apos;,
&apos;{shift} Z X C V B N M &lt; &gt; ? {shift}&apos;,
&apos;.com @ {space}&apos;
]
}
}
}
export default KeyboardLayout;</code></pre>
</div>
<footer class="footer">
Generated by <a href="https://esdoc.org">ESDoc<span data-ice="esdocVersion">(1.1.0)</span><img src="./image/esdoc-logo-mini-black.png"></a>
</footer>
<script src="script/search_index.js"></script>
<script src="script/search.js"></script>
<script src="script/pretty-print.js"></script>
<script src="script/inherited-summary.js"></script>
<script src="script/test-summary.js"></script>
<script src="script/inner-link.js"></script>
<script src="script/patch-for-local.js"></script>
</body>
</html>

View File

@@ -0,0 +1,155 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<base data-ice="baseUrl" href="../../../../">
<title data-ice="title">src/lib/services/PhysicalKeyboard.js | simple-keyboard</title>
<link type="text/css" rel="stylesheet" href="css/style.css">
<link type="text/css" rel="stylesheet" href="css/prettify-tomorrow.css">
<script src="script/prettify/prettify.js"></script>
<script src="script/manual.js"></script>
<meta name="description" content="On-screen Javascript Virtual Keyboard"><meta property="twitter:card" content="summary"><meta property="twitter:title" content="simple-keyboard"><meta property="twitter:description" content="On-screen Javascript Virtual Keyboard"></head>
<body class="layout-container" data-ice="rootContainer">
<header>
<a href="./">Home</a>
<a href="identifiers.html">Reference</a>
<a href="source.html">Source</a>
<div class="search-box">
<span>
<img src="./image/search.png">
<span class="search-input-edge"></span><input class="search-input"><span class="search-input-edge"></span>
</span>
<ul class="search-result"></ul>
</div>
<a style="position:relative; top:3px;" href="https://github.com/hodgef/simple-keyboard"><img width="20px" src="./image/github.png"></a></header>
<nav class="navigation" data-ice="nav"><div>
<ul>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#demo">demo</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/demo/App.js~App.html">App</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-components">lib/components</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/components/Keyboard.js~SimpleKeyboard.html">SimpleKeyboard</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-services">lib/services</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/KeyboardLayout.js~KeyboardLayout.html">KeyboardLayout</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html">PhysicalKeyboard</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/Utilities.js~Utilities.html">Utilities</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-tests">lib/tests</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/tests/TestUtility.js~TestUtility.html">TestUtility</a></span></span></li>
</ul>
</div>
</nav>
<div class="content" data-ice="content"><h1 data-ice="title">src/lib/services/PhysicalKeyboard.js</h1>
<pre class="source-code line-number raw-source-code"><code class="prettyprint linenums" data-ice="content">/**
* Physical Keyboard Service
*/
class PhysicalKeyboard {
/**
* Creates an instance of the PhysicalKeyboard service
*/
constructor(simpleKeyboardInstance){
/**
* @type {object} A simple-keyboard instance
*/
this.simpleKeyboardInstance = simpleKeyboardInstance;
/**
* Bindings
*/
this.initKeyboardListener = this.initKeyboardListener.bind(this);
this.getSimpleKeyboardLayoutKey = this.getSimpleKeyboardLayoutKey.bind(this);
/**
* Initialize key listeners
*/
this.initKeyboardListener();
}
/**
* Initializes key event listeners
*/
initKeyboardListener(){
// Adding button style on keydown
document.addEventListener(&quot;keydown&quot;, (event) =&gt; {
if(this.simpleKeyboardInstance.options.physicalKeyboardHighlight){
let buttonPressed = this.getSimpleKeyboardLayoutKey(event);
this.simpleKeyboardInstance.dispatch(instance =&gt; {
let buttonDOM = instance.getButtonElement(buttonPressed) || instance.getButtonElement(`{${buttonPressed}}`);
if(buttonDOM){
buttonDOM.style.backgroundColor = this.simpleKeyboardInstance.options.physicalKeyboardHighlightBgColor || &quot;#9ab4d0&quot;;
buttonDOM.style.color = this.simpleKeyboardInstance.options.physicalKeyboardHighlightTextColor || &quot;white&quot;;
}
});
}
});
// Removing button style on keyup
document.addEventListener(&quot;keyup&quot;, (event) =&gt; {
if(this.simpleKeyboardInstance.options.physicalKeyboardHighlight){
let buttonPressed = this.getSimpleKeyboardLayoutKey(event);
this.simpleKeyboardInstance.dispatch(instance =&gt; {
let buttonDOM = instance.getButtonElement(buttonPressed) || instance.getButtonElement(`{${buttonPressed}}`);
if(buttonDOM){
buttonDOM.removeAttribute(&quot;style&quot;);
}
});
}
});
}
/**
* Transforms a KeyboardEvent&apos;s &quot;key.code&quot; string into a simple-keyboard layout format
* @param {object} event The KeyboardEvent
*/
getSimpleKeyboardLayoutKey(event){
let output;
if(
event.code.includes(&quot;Numpad&quot;) ||
event.code.includes(&quot;Shift&quot;) ||
event.code.includes(&quot;Space&quot;) ||
event.code.includes(&quot;Backspace&quot;) ||
event.code.includes(&quot;Control&quot;) ||
event.code.includes(&quot;Alt&quot;) ||
event.code.includes(&quot;Meta&quot;)
){
output = event.code;
} else {
output = event.key;
}
/**
* If button is not uppercase, casting to lowercase
*/
if (
output !== output.toUpperCase() ||
(event.code[0] === &quot;F&quot; &amp;&amp; Number.isInteger(Number(event.code[1])) &amp;&amp; event.code.length &lt;= 3)
) {
output = output.toLowerCase();
}
return output;
}
}
export default PhysicalKeyboard;</code></pre>
</div>
<footer class="footer">
Generated by <a href="https://esdoc.org">ESDoc<span data-ice="esdocVersion">(1.1.0)</span><img src="./image/esdoc-logo-mini-black.png"></a>
</footer>
<script src="script/search_index.js"></script>
<script src="script/search.js"></script>
<script src="script/pretty-print.js"></script>
<script src="script/inherited-summary.js"></script>
<script src="script/test-summary.js"></script>
<script src="script/inner-link.js"></script>
<script src="script/patch-for-local.js"></script>
</body>
</html>

View File

@@ -0,0 +1,411 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<base data-ice="baseUrl" href="../../../../">
<title data-ice="title">src/lib/services/Utilities.js | simple-keyboard</title>
<link type="text/css" rel="stylesheet" href="css/style.css">
<link type="text/css" rel="stylesheet" href="css/prettify-tomorrow.css">
<script src="script/prettify/prettify.js"></script>
<script src="script/manual.js"></script>
<meta name="description" content="On-screen Javascript Virtual Keyboard"><meta property="twitter:card" content="summary"><meta property="twitter:title" content="simple-keyboard"><meta property="twitter:description" content="On-screen Javascript Virtual Keyboard"></head>
<body class="layout-container" data-ice="rootContainer">
<header>
<a href="./">Home</a>
<a href="identifiers.html">Reference</a>
<a href="source.html">Source</a>
<div class="search-box">
<span>
<img src="./image/search.png">
<span class="search-input-edge"></span><input class="search-input"><span class="search-input-edge"></span>
</span>
<ul class="search-result"></ul>
</div>
<a style="position:relative; top:3px;" href="https://github.com/hodgef/simple-keyboard"><img width="20px" src="./image/github.png"></a></header>
<nav class="navigation" data-ice="nav"><div>
<ul>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#demo">demo</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/demo/App.js~App.html">App</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-components">lib/components</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/components/Keyboard.js~SimpleKeyboard.html">SimpleKeyboard</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-services">lib/services</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/KeyboardLayout.js~KeyboardLayout.html">KeyboardLayout</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html">PhysicalKeyboard</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/Utilities.js~Utilities.html">Utilities</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-tests">lib/tests</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/tests/TestUtility.js~TestUtility.html">TestUtility</a></span></span></li>
</ul>
</div>
</nav>
<div class="content" data-ice="content"><h1 data-ice="title">src/lib/services/Utilities.js</h1>
<pre class="source-code line-number raw-source-code"><code class="prettyprint linenums" data-ice="content">/**
* Utility Service
*/
class Utilities {
/**
* Creates an instance of the Utility service
*/
constructor(simpleKeyboardInstance){
/**
* @type {object} A simple-keyboard instance
*/
this.simpleKeyboardInstance = simpleKeyboardInstance;
/**
* Bindings
*/
this.getButtonClass = this.getButtonClass.bind(this);
this.getButtonDisplayName = this.getButtonDisplayName.bind(this);
this.getUpdatedInput = this.getUpdatedInput.bind(this);
this.updateCaretPos = this.updateCaretPos.bind(this);
this.isMaxLengthReached = this.isMaxLengthReached.bind(this);
this.camelCase = this.camelCase.bind(this);
this.countInArray = this.countInArray.bind(this);
}
/**
* Adds default classes to a given button
*
* @param {string} button The button&apos;s layout name
* @return {string} The classes to be added to the button
*/
getButtonClass(button){
let buttonTypeClass = (button.includes(&quot;{&quot;) &amp;&amp; button.includes(&quot;}&quot;) &amp;&amp; button !== &apos;{//}&apos;) ? &quot;functionBtn&quot; : &quot;standardBtn&quot;;
let buttonWithoutBraces = button.replace(&quot;{&quot;, &quot;&quot;).replace(&quot;}&quot;, &quot;&quot;);
let buttonNormalized = &apos;&apos;;
if(buttonTypeClass !== &quot;standardBtn&quot;)
buttonNormalized = ` hg-button-${buttonWithoutBraces}`;
return `hg-${buttonTypeClass}${buttonNormalized}`;
}
/**
* Default button display labels
*/
getDefaultDiplay(){
return {
&apos;{bksp}&apos;: &apos;backspace&apos;,
&apos;{backspace}&apos;: &apos;backspace&apos;,
&apos;{enter}&apos;: &apos;&lt; enter&apos;,
&apos;{shift}&apos;: &apos;shift&apos;,
&apos;{shiftleft}&apos;: &apos;shift&apos;,
&apos;{shiftright}&apos;: &apos;shift&apos;,
&apos;{alt}&apos;: &apos;alt&apos;,
&apos;{s}&apos;: &apos;shift&apos;,
&apos;{tab}&apos;: &apos;tab&apos;,
&apos;{lock}&apos;: &apos;caps&apos;,
&apos;{capslock}&apos;: &apos;caps&apos;,
&apos;{accept}&apos;: &apos;Submit&apos;,
&apos;{space}&apos;: &apos; &apos;,
&apos;{//}&apos;: &apos; &apos;,
&quot;{esc}&quot;: &quot;esc&quot;,
&quot;{escape}&quot;: &quot;esc&quot;,
&quot;{f1}&quot;: &quot;f1&quot;,
&quot;{f2}&quot;: &quot;f2&quot;,
&quot;{f3}&quot;: &quot;f3&quot;,
&quot;{f4}&quot;: &quot;f4&quot;,
&quot;{f5}&quot;: &quot;f5&quot;,
&quot;{f6}&quot;: &quot;f6&quot;,
&quot;{f7}&quot;: &quot;f7&quot;,
&quot;{f8}&quot;: &quot;f8&quot;,
&quot;{f9}&quot;: &quot;f9&quot;,
&quot;{f10}&quot;: &quot;f10&quot;,
&quot;{f11}&quot;: &quot;f11&quot;,
&quot;{f12}&quot;: &quot;f12&quot;,
&apos;{numpaddivide}&apos;: &apos;/&apos;,
&apos;{numlock}&apos;: &apos;lock&apos;,
&quot;{arrowup}&quot;: &quot;&#x2191;&quot;,
&quot;{arrowleft}&quot;: &quot;&#x2190;&quot;,
&quot;{arrowdown}&quot;: &quot;&#x2193;&quot;,
&quot;{arrowright}&quot;: &quot;&#x2192;&quot;,
&quot;{prtscr}&quot;: &quot;print&quot;,
&quot;{scrolllock}&quot;: &quot;scroll&quot;,
&quot;{pause}&quot;: &quot;pause&quot;,
&quot;{insert}&quot;: &quot;ins&quot;,
&quot;{home}&quot;: &quot;home&quot;,
&quot;{pageup}&quot;: &quot;up&quot;,
&quot;{delete}&quot;: &quot;del&quot;,
&quot;{end}&quot;: &quot;end&quot;,
&quot;{pagedown}&quot;: &quot;down&quot;,
&quot;{numpadmultiply}&quot;: &quot;*&quot;,
&quot;{numpadsubtract}&quot;: &quot;-&quot;,
&quot;{numpadadd}&quot;: &quot;+&quot;,
&quot;{numpadenter}&quot;: &quot;enter&quot;,
&quot;{period}&quot;: &quot;.&quot;,
&quot;{numpaddecimal}&quot;: &quot;.&quot;,
&quot;{numpad0}&quot;: &quot;0&quot;,
&quot;{numpad1}&quot;: &quot;1&quot;,
&quot;{numpad2}&quot;: &quot;2&quot;,
&quot;{numpad3}&quot;: &quot;3&quot;,
&quot;{numpad4}&quot;: &quot;4&quot;,
&quot;{numpad5}&quot;: &quot;5&quot;,
&quot;{numpad6}&quot;: &quot;6&quot;,
&quot;{numpad7}&quot;: &quot;7&quot;,
&quot;{numpad8}&quot;: &quot;8&quot;,
&quot;{numpad9}&quot;: &quot;9&quot;,
};
}
/**
* Returns the display (label) name for a given button
*
* @param {string} button The button&apos;s layout name
* @param {object} display The provided display option
* @param {boolean} mergeDisplay Whether the provided param value should be merged with the default one.
*/
getButtonDisplayName(button, display, mergeDisplay){
if(mergeDisplay){
display = Object.assign({}, this.getDefaultDiplay(), display);
} else {
display = display || this.getDefaultDiplay();
}
return display[button] || button;
}
/**
* Returns the updated input resulting from clicking a given button
*
* @param {string} button The button&apos;s layout name
* @param {string} input The input string
* @param {object} options The simple-keyboard options object
* @param {number} caretPos The cursor&apos;s current position
*/
getUpdatedInput(button, input, options, caretPos){
let output = input;
if((button === &quot;{bksp}&quot; || button === &quot;{backspace}&quot;) &amp;&amp; output.length &gt; 0){
output = this.removeAt(output, caretPos);
} else if(button === &quot;{space}&quot;)
output = this.addStringAt(output, &quot; &quot;, caretPos);
else if(button === &quot;{tab}&quot; &amp;&amp; !(typeof options.tabCharOnTab === &quot;boolean&quot; &amp;&amp; options.tabCharOnTab === false)){
output = this.addStringAt(output, &quot;\t&quot;, caretPos);
} else if((button === &quot;{enter}&quot; || button === &quot;{numpadenter}&quot;) &amp;&amp; options.newLineOnEnter)
output = this.addStringAt(output, &quot;\n&quot;, caretPos);
else if(button.includes(&quot;numpad&quot;) &amp;&amp; Number.isInteger(Number(button[button.length - 2]))){
output = this.addStringAt(output, button[button.length - 2], caretPos);
}
else if(button === &quot;{numpaddivide}&quot;)
output = this.addStringAt(output, &apos;/&apos;, caretPos);
else if(button === &quot;{numpadmultiply}&quot;)
output = this.addStringAt(output, &apos;*&apos;, caretPos);
else if(button === &quot;{numpadsubtract}&quot;)
output = this.addStringAt(output, &apos;-&apos;, caretPos);
else if(button === &quot;{numpadadd}&quot;)
output = this.addStringAt(output, &apos;+&apos;, caretPos);
else if(button === &quot;{numpaddecimal}&quot;)
output = this.addStringAt(output, &apos;.&apos;, caretPos);
else if(button === &quot;{&quot; || button === &quot;}&quot;)
output = this.addStringAt(output, button, caretPos);
else if(!button.includes(&quot;{&quot;) &amp;&amp; !button.includes(&quot;}&quot;))
output = this.addStringAt(output, button, caretPos);
return output;
}
/**
* Moves the cursor position by a given amount
*
* @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.
*/
updateCaretPos(length, minus){
if(minus){
if(this.simpleKeyboardInstance.caretPosition &gt; 0)
this.simpleKeyboardInstance.caretPosition = this.simpleKeyboardInstance.caretPosition - length
} else {
this.simpleKeyboardInstance.caretPosition = this.simpleKeyboardInstance.caretPosition + length;
}
}
/**
* Adds a string to the input at a given position
*
* @param {string} source The source input
* @param {string} string The string to add
* @param {number} position The (cursor) position where the string should be added
*/
addStringAt(source, string, position){
let output;
if(this.simpleKeyboardInstance.options.debug){
console.log(&quot;Caret at:&quot;, position);
}
if(!position &amp;&amp; position !== 0){
output = source + string;
} else {
output = [source.slice(0, position), string, source.slice(position)].join(&apos;&apos;);
/**
* Avoid caret position change when maxLength is set
*/
if(!this.isMaxLengthReached()){
this.updateCaretPos(string.length);
}
}
return output;
}
/**
* Removes an amount of characters at a given position
*
* @param {string} source The source input
* @param {number} position The (cursor) position from where the characters should be removed
*/
removeAt(source, position){
if(this.simpleKeyboardInstance.caretPosition === 0){
return source;
}
let output;
let prevTwoChars;
let emojiMatched;
let 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 &amp;&amp; position &gt;= 0){
prevTwoChars = source.substring(position - 2, position)
emojiMatched = prevTwoChars.match(emojiMatchedReg);
if(emojiMatched){
output = source.substr(0, (position - 2)) + source.substr(position);
this.updateCaretPos(2, true);
} else {
output = source.substr(0, (position - 1)) + source.substr(position);
this.updateCaretPos(1, true);
}
} else {
prevTwoChars = source.slice(-2);
emojiMatched = prevTwoChars.match(emojiMatchedReg);
if(emojiMatched){
output = source.slice(0, -2);
this.updateCaretPos(2, true);
} else {
output = source.slice(0, -1);
this.updateCaretPos(1, true);
}
}
return output;
}
/**
* Determines whether the maxLength has been reached. This function is called when the maxLength option it set.
*
* @param {object} inputObj
* @param {object} options
* @param {string} updatedInput
*/
handleMaxLength(inputObj, options, updatedInput){
let maxLength = options.maxLength;
let currentInput = inputObj[options.inputName];
let condition = currentInput.length === maxLength;
if(
/**
* If pressing this button won&apos;t add more characters
* We exit out of this limiter function
*/
updatedInput.length &lt;= currentInput.length
){
return false;
}
if(Number.isInteger(maxLength)){
if(options.debug){
console.log(&quot;maxLength (num) reached:&quot;, condition);
}
if(condition){
/**
* @type {boolean} Boolean value that shows whether maxLength has been reached
*/
this.maxLengthReached = true;
return true;
} else {
this.maxLengthReached = false;
return false;
}
}
if(typeof maxLength === &quot;object&quot;){
let condition = currentInput.length === maxLength[options.inputName];
if(options.debug){
console.log(&quot;maxLength (obj) reached:&quot;, condition);
}
if(condition){
this.maxLengthReached = true;
return true;
} else {
this.maxLengthReached = false;
return false;
}
}
}
/**
* Gets the current value of maxLengthReached
*/
isMaxLengthReached(){
return Boolean(this.maxLengthReached);
}
/**
* Transforms an arbitrary string to camelCase
*
* @param {string} string The string to transform.
*/
camelCase(string){
return string.toLowerCase().trim().split(/[.\-_\s]/g).reduce((string, word) =&gt; string + word[0].toUpperCase() + word.slice(1));
};
/**
* Counts the number of duplicates in a given array
*
* @param {Array} array The haystack to search in
* @param {string} value The needle to search for
*/
countInArray(array, value){
return array.reduce((n, x) =&gt; n + (x === value), 0);
}
}
export default Utilities;</code></pre>
</div>
<footer class="footer">
Generated by <a href="https://esdoc.org">ESDoc<span data-ice="esdocVersion">(1.1.0)</span><img src="./image/esdoc-logo-mini-black.png"></a>
</footer>
<script src="script/search_index.js"></script>
<script src="script/search.js"></script>
<script src="script/pretty-print.js"></script>
<script src="script/inherited-summary.js"></script>
<script src="script/test-summary.js"></script>
<script src="script/inner-link.js"></script>
<script src="script/patch-for-local.js"></script>
</body>
</html>

View File

@@ -0,0 +1,165 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<base data-ice="baseUrl" href="../../../../">
<title data-ice="title">src/lib/tests/TestUtility.js | simple-keyboard</title>
<link type="text/css" rel="stylesheet" href="css/style.css">
<link type="text/css" rel="stylesheet" href="css/prettify-tomorrow.css">
<script src="script/prettify/prettify.js"></script>
<script src="script/manual.js"></script>
<meta name="description" content="On-screen Javascript Virtual Keyboard"><meta property="twitter:card" content="summary"><meta property="twitter:title" content="simple-keyboard"><meta property="twitter:description" content="On-screen Javascript Virtual Keyboard"></head>
<body class="layout-container" data-ice="rootContainer">
<header>
<a href="./">Home</a>
<a href="identifiers.html">Reference</a>
<a href="source.html">Source</a>
<div class="search-box">
<span>
<img src="./image/search.png">
<span class="search-input-edge"></span><input class="search-input"><span class="search-input-edge"></span>
</span>
<ul class="search-result"></ul>
</div>
<a style="position:relative; top:3px;" href="https://github.com/hodgef/simple-keyboard"><img width="20px" src="./image/github.png"></a></header>
<nav class="navigation" data-ice="nav"><div>
<ul>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#demo">demo</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/demo/App.js~App.html">App</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-components">lib/components</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/components/Keyboard.js~SimpleKeyboard.html">SimpleKeyboard</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-services">lib/services</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/KeyboardLayout.js~KeyboardLayout.html">KeyboardLayout</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html">PhysicalKeyboard</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/Utilities.js~Utilities.html">Utilities</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-tests">lib/tests</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/tests/TestUtility.js~TestUtility.html">TestUtility</a></span></span></li>
</ul>
</div>
</nav>
<div class="content" data-ice="content"><h1 data-ice="title">src/lib/tests/TestUtility.js</h1>
<pre class="source-code line-number raw-source-code"><code class="prettyprint linenums" data-ice="content">/**
* Test Utility Functions
*/
export default class TestUtility {
/**
* Set&apos;s a basic DOM structure to test in
*/
setDOM = (divClass) =&gt; {
this.clear();
const div = document.createElement(&apos;div&apos;);
div.className += divClass || &quot;simple-keyboard&quot;;
document.body.appendChild(div);
}
/**
* Clears DOM structure
*/
clear = () =&gt; {
document.body.innerHTML = &quot;&quot;;
}
/**
* Test if standard buttons respect maxLength and do input a value
*/
testLayoutStdButtons = (keyboard) =&gt; {
let stdBtnCount = 0;
let fullInput = &apos;&apos;;
this.iterateButtons((button) =&gt; {
let label = button.getAttribute(&quot;data-skbtn&quot;);
if(label.includes(&quot;{&quot;))
return false;
// Click all standard buttons, respects maxLength
button.onclick();
// Recording fullInput, bypasses maxLength
fullInput = keyboard.utilities.getUpdatedInput(label, fullInput, keyboard.options, null);
stdBtnCount += label.length;
});
/**
* Check if maxLength is respected
*/
if(
(
typeof keyboard.options.maxLength === &quot;object&quot; &amp;&amp;
keyboard.getInput().length !== keyboard.options.maxLength[keyboard.options.layoutName]
) ||
(
typeof keyboard.options.maxLength !== &quot;object&quot; &amp;&amp;
keyboard.getInput().length !== keyboard.options.maxLength
)
)
throw new Error(&quot;MAX_LENGTH_ISSUE&quot;);
else
console.log(&quot;MAX_LENGTH PASSED:&quot;, keyboard.options.layoutName, keyboard.getInput().length, keyboard.options.maxLength);
/**
* Check if all standard buttons are inputting something
* (Regardless of maxLength)
*/
if(stdBtnCount !== fullInput.length)
throw new Error(&quot;STANDARD_BUTTONS_ISSUE&quot;);
else
console.log(&quot;STANDARD_BUTTONS PASSED:&quot;, keyboard.options.layoutName, stdBtnCount, fullInput.length);
}
/**
* Test if function buttons are interactive (have an onclick)
*/
testLayoutFctButtons = (callback) =&gt; {
let fctBtnCount = 0;
let fctBtnHasOnclickCount = 0;
this.iterateButtons((button) =&gt; {
let label = button.getAttribute(&quot;data-skbtn&quot;);
if(!label.includes(&quot;{&quot;) &amp;&amp; !label.includes(&quot;}&quot;))
return false;
fctBtnCount++;
if(button.onclick){
button.onclick();
fctBtnHasOnclickCount++;
}
callback(fctBtnCount, fctBtnHasOnclickCount);
});
}
/**
* Iterates on the keyboard buttons
*/
iterateButtons = (callback, selector) =&gt; {
let rows = document.body.querySelector(selector || &apos;.simple-keyboard&apos;).children;
Array.from(rows).forEach(row =&gt; {
Array.from(row.children).forEach((button) =&gt; {
callback(button);
});
});
}
}</code></pre>
</div>
<footer class="footer">
Generated by <a href="https://esdoc.org">ESDoc<span data-ice="esdocVersion">(1.1.0)</span><img src="./image/esdoc-logo-mini-black.png"></a>
</footer>
<script src="script/search_index.js"></script>
<script src="script/search.js"></script>
<script src="script/pretty-print.js"></script>
<script src="script/inherited-summary.js"></script>
<script src="script/test-summary.js"></script>
<script src="script/inner-link.js"></script>
<script src="script/patch-for-local.js"></script>
</body>
</html>

291
docs/identifiers.html Normal file
View File

@@ -0,0 +1,291 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<base data-ice="baseUrl">
<title data-ice="title">Reference | simple-keyboard</title>
<link type="text/css" rel="stylesheet" href="css/style.css">
<link type="text/css" rel="stylesheet" href="css/prettify-tomorrow.css">
<script src="script/prettify/prettify.js"></script>
<script src="script/manual.js"></script>
<meta name="description" content="On-screen Javascript Virtual Keyboard"><meta property="twitter:card" content="summary"><meta property="twitter:title" content="simple-keyboard"><meta property="twitter:description" content="On-screen Javascript Virtual Keyboard"></head>
<body class="layout-container" data-ice="rootContainer">
<header>
<a href="./">Home</a>
<a href="identifiers.html">Reference</a>
<a href="source.html">Source</a>
<div class="search-box">
<span>
<img src="./image/search.png">
<span class="search-input-edge"></span><input class="search-input"><span class="search-input-edge"></span>
</span>
<ul class="search-result"></ul>
</div>
<a style="position:relative; top:3px;" href="https://github.com/hodgef/simple-keyboard"><img width="20px" src="./image/github.png"></a></header>
<nav class="navigation" data-ice="nav"><div>
<ul>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#demo">demo</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/demo/App.js~App.html">App</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-components">lib/components</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/components/Keyboard.js~SimpleKeyboard.html">SimpleKeyboard</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-services">lib/services</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/KeyboardLayout.js~KeyboardLayout.html">KeyboardLayout</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html">PhysicalKeyboard</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/Utilities.js~Utilities.html">Utilities</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-tests">lib/tests</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/tests/TestUtility.js~TestUtility.html">TestUtility</a></span></span></li>
</ul>
</div>
</nav>
<div class="content" data-ice="content"><h1>References</h1>
<div class="identifiers-wrap">
<div>
<div data-ice="dirSummaryWrap">
<h2 data-ice="dirPath" id="demo">demo</h2>
<div data-ice="dirSummary"><table class="summary" data-ice="summary">
<thead><tr><td data-ice="title" colspan="3">summary</td></tr></thead>
<tbody>
<tr data-ice="target">
<td>
<span class="access" data-ice="access">public</span>
<span class="override" data-ice="override"></span>
</td>
<td>
<div>
<p>
<span data-ice="kind-icon" class="kind-class">C</span>
<span class="code" data-ice="name"><span><a href="class/src/demo/App.js~App.html">App</a></span></span>
</p>
</div>
<div>
<div data-ice="description"><p>simple-keyboard demo</p>
</div>
</div>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div data-ice="dirSummaryWrap">
<h2 data-ice="dirPath" id="lib-components">lib/components</h2>
<div data-ice="dirSummary"><table class="summary" data-ice="summary">
<thead><tr><td data-ice="title" colspan="3">summary</td></tr></thead>
<tbody>
<tr data-ice="target">
<td>
<span class="access" data-ice="access">public</span>
<span class="override" data-ice="override"></span>
</td>
<td>
<div>
<p>
<span data-ice="kind-icon" class="kind-class">C</span>
<span class="code" data-ice="name"><span><a href="class/src/lib/components/Keyboard.js~SimpleKeyboard.html">SimpleKeyboard</a></span></span>
</p>
</div>
<div>
<div data-ice="description"><p>Root class for simple-keyboard
This class:</p>
<ul>
<li>Parses the options</li>
<li>Renders the rows and buttons</li>
<li>Handles button functionality</li>
</ul>
</div>
</div>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div data-ice="dirSummaryWrap">
<h2 data-ice="dirPath" id="lib-services">lib/services</h2>
<div data-ice="dirSummary"><table class="summary" data-ice="summary">
<thead><tr><td data-ice="title" colspan="3">summary</td></tr></thead>
<tbody>
<tr data-ice="target">
<td>
<span class="access" data-ice="access">public</span>
<span class="override" data-ice="override"></span>
</td>
<td>
<div>
<p>
<span data-ice="kind-icon" class="kind-class">C</span>
<span class="code" data-ice="name"><span><a href="class/src/lib/services/KeyboardLayout.js~KeyboardLayout.html">KeyboardLayout</a></span></span>
</p>
</div>
<div>
<div data-ice="description"><p>Keyboard Layout Service</p>
</div>
</div>
</td>
<td>
</td>
</tr>
<tr data-ice="target">
<td>
<span class="access" data-ice="access">public</span>
<span class="override" data-ice="override"></span>
</td>
<td>
<div>
<p>
<span data-ice="kind-icon" class="kind-class">C</span>
<span class="code" data-ice="name"><span><a href="class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html">PhysicalKeyboard</a></span></span>
</p>
</div>
<div>
<div data-ice="description"><p>Physical Keyboard Service</p>
</div>
</div>
</td>
<td>
</td>
</tr>
<tr data-ice="target">
<td>
<span class="access" data-ice="access">public</span>
<span class="override" data-ice="override"></span>
</td>
<td>
<div>
<p>
<span data-ice="kind-icon" class="kind-class">C</span>
<span class="code" data-ice="name"><span><a href="class/src/lib/services/Utilities.js~Utilities.html">Utilities</a></span></span>
</p>
</div>
<div>
<div data-ice="description"><p>Utility Service</p>
</div>
</div>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div data-ice="dirSummaryWrap">
<h2 data-ice="dirPath" id="lib-tests">lib/tests</h2>
<div data-ice="dirSummary"><table class="summary" data-ice="summary">
<thead><tr><td data-ice="title" colspan="3">summary</td></tr></thead>
<tbody>
<tr data-ice="target">
<td>
<span class="access" data-ice="access">public</span>
<span class="override" data-ice="override"></span>
</td>
<td>
<div>
<p>
<span data-ice="kind-icon" class="kind-class">C</span>
<span class="code" data-ice="name"><span><a href="class/src/lib/tests/TestUtility.js~TestUtility.html">TestUtility</a></span></span>
</p>
</div>
<div>
<div data-ice="description"><p>Test Utility Functions</p>
</div>
</div>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="identifier-dir-tree" data-ice="dirTreeWrap">
<div class="identifier-dir-tree-header">Directories</div>
<div class="identifier-dir-tree-content" data-ice="dirTree"><div style="padding-left: 0em"><a href="#demo">demo</a></div>
<div style="padding-left: 1em"><a href="#lib-components">components</a></div>
<div style="padding-left: 1em"><a href="#lib-services">services</a></div>
<div style="padding-left: 1em"><a href="#lib-tests">tests</a></div></div>
</div>
</div>
</div>
<footer class="footer">
Generated by <a href="https://esdoc.org">ESDoc<span data-ice="esdocVersion">(1.1.0)</span><img src="./image/esdoc-logo-mini-black.png"></a>
</footer>
<script src="script/search_index.js"></script>
<script src="script/search.js"></script>
<script src="script/pretty-print.js"></script>
<script src="script/inherited-summary.js"></script>
<script src="script/test-summary.js"></script>
<script src="script/inner-link.js"></script>
<script src="script/patch-for-local.js"></script>
</body>
</html>

17
docs/image/badge.svg Normal file
View File

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="104" height="20">
<script/>
<linearGradient id="a" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<rect rx="3" width="104" height="20" fill="#555"/>
<rect rx="3" x="64" width="40" height="20" fill="@color@"/>
<path fill="@color@" d="M64 0h4v20h-4z"/>
<rect rx="3" width="104" height="20" fill="url(#a)"/>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="32" y="15" fill="#010101" fill-opacity=".3">document</text>
<text x="32" y="14">document</text>
<text x="84" y="15" fill="#010101" fill-opacity=".3">@ratio@</text>
<text x="84" y="14">@ratio@</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 799 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
docs/image/github.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="102" height="20">
<script/>
<linearGradient id="a" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<rect rx="3" width="102" height="20" fill="#555"/>
<rect rx="3" x="52" width="50" height="20" fill="@color@"/>
<path fill="@color@" d="M52 0h4v20h-4z"/>
<rect rx="3" width="102" height="20" fill="url(#a)"/>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="26" y="15" fill="#010101" fill-opacity=".3">manual</text>
<text x="26" y="14">manual</text>
<text x="77" y="15" fill="#010101" fill-opacity=".3">@value@</text>
<text x="77" y="14">@value@</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 795 B

BIN
docs/image/search.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

87
docs/index.html Normal file
View File

@@ -0,0 +1,87 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<base data-ice="baseUrl">
<title data-ice="title">Home | simple-keyboard</title>
<link type="text/css" rel="stylesheet" href="css/style.css">
<link type="text/css" rel="stylesheet" href="css/prettify-tomorrow.css">
<script src="script/prettify/prettify.js"></script>
<script src="script/manual.js"></script>
<meta name="description" content="On-screen Javascript Virtual Keyboard"><meta property="twitter:card" content="summary"><meta property="twitter:title" content="simple-keyboard"><meta property="twitter:description" content="On-screen Javascript Virtual Keyboard"></head>
<body class="layout-container" data-ice="rootContainer">
<header>
<a href="./">Home</a>
<a href="identifiers.html">Reference</a>
<a href="source.html">Source</a>
<div class="search-box">
<span>
<img src="./image/search.png">
<span class="search-input-edge"></span><input class="search-input"><span class="search-input-edge"></span>
</span>
<ul class="search-result"></ul>
</div>
<a style="position:relative; top:3px;" href="https://github.com/hodgef/simple-keyboard"><img width="20px" src="./image/github.png"></a></header>
<nav class="navigation" data-ice="nav"><div>
<ul>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#demo">demo</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/demo/App.js~App.html">App</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-components">lib/components</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/components/Keyboard.js~SimpleKeyboard.html">SimpleKeyboard</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-services">lib/services</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/KeyboardLayout.js~KeyboardLayout.html">KeyboardLayout</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html">PhysicalKeyboard</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/Utilities.js~Utilities.html">Utilities</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-tests">lib/tests</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/tests/TestUtility.js~TestUtility.html">TestUtility</a></span></span></li>
</ul>
</div>
</nav>
<div class="content" data-ice="content"><div data-ice="index" class="github-markdown"><p><div>
<a href="https://simple-keyboard.com/demo" title="View Demo" target="_blank"><img src="https://franciscohodge.com/project-pages/simple-keyboard/images/simplekeyboard-banner_B.png" width="100%"></a>
<a href="https://simple-keyboard.com/demo" title="View Demo" target="_blank"><img src="https://franciscohodge.com/project-pages/simple-keyboard/images/simple-keyboard-10172018.gif" width="100%"></a>
&lt;blockquote&gt;The easily customisable and responsive on-screen virtual keyboard for Javascript projects.&lt;/blockquote&gt;
<p><a href="https://github.com/hodgef/simple-keyboard/blob/master/LICENSE" target="_blank"><img src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
<a href="https://www.npmjs.com/package/simple-keyboard" target="_blank"><img src="https://img.shields.io/npm/v/simple-keyboard.svg?style=flat"></a>
<a href="https://travis-ci.org/hodgef/simple-keyboard" target="_blank"><img src="https://travis-ci.org/hodgef/simple-keyboard.svg?branch=master"></a>
<a href="https://codecov.io/gh/hodgef/simple-keyboard" target="_blank"><img src="https://img.shields.io/codecov/c/github/hodgef/simple-keyboard/master.svg?style=flat"></a>
<a href="https://doc.esdoc.org/github.com/hodgef/simple-keyboard" target="_blank"><img src="https://doc.esdoc.org/github.com/hodgef/simple-keyboard/badge.svg"></a>
</p>
</div>
</p>
<h2 id="&#x1F4E6;-installation--amp--usage">&#x1F4E6; Installation &amp; Usage</h2><p>You can use simple-keyboard as a <code>&lt;script&gt;</code> tag from a CDN, or install it from npm.</p>
<p>Check out the <a href="https://simple-keyboard.com/getting-started">Getting Started</a> docs to begin.</p>
<h2 id="&#x1F4D6;-documentation">&#x1F4D6; Documentation</h2><p>Check out the <a href="https://simple-keyboard.com/documentation">simple-keyboard documentation</a> site.</p>
<p>Feel free to browse the <a href="https://simple-keyboard.com/qa-use-cases/">Q&amp;A / Use-cases</a> page for advanced use-cases.</p>
<h2 id="&#x1F680;-demo">&#x1F680; Demo</h2><p><a href="https://simple-keyboard.com/demo">https://simple-keyboard.com/demo</a></p>
<h3 id="to-run-demo-on-your-own-computer">To run demo on your own computer</h3><ul>
<li>Clone this repository</li>
<li><code>npm install</code></li>
<li><code>npm start</code></li>
<li>Visit <a href="http://localhost:3000/">http://localhost:3000/</a></li>
</ul>
<h3 id="other-versions">Other versions</h3><ul>
<li>ReactJS - <a href="https://github.com/hodgef/react-simple-keyboard">react-simple-keyboard</a></li>
</ul>
<h3 id="questions-">Questions?</h3><p><a href="http://franciscohodge.com/simple-keyboard/chat/join" title="Join our Discord chat" target="_blank"><img src="https://franciscohodge.com/project-pages/simple-keyboard/images/discord.png" width="200"></a></p>
<h2 id="&#x2705;-contributing">&#x2705; Contributing</h2><p>PR&apos;s and issues are welcome. Feel free to submit any issues you have at:
<a href="https://github.com/hodgef/simple-keyboard/issues">https://github.com/hodgef/simple-keyboard/issues</a></p>
</div>
</div>
<footer class="footer">
Generated by <a href="https://esdoc.org">ESDoc<span data-ice="esdocVersion">(1.1.0)</span><img src="./image/esdoc-logo-mini-black.png"></a>
</footer>
<script src="script/search_index.js"></script>
<script src="script/search.js"></script>
<script src="script/pretty-print.js"></script>
<script src="script/inherited-summary.js"></script>
<script src="script/test-summary.js"></script>
<script src="script/inner-link.js"></script>
<script src="script/patch-for-local.js"></script>
</body>
</html>

2609
docs/index.json Normal file

File diff suppressed because one or more lines are too long

1
docs/lint.json Normal file
View File

@@ -0,0 +1 @@
[]

View File

@@ -0,0 +1,28 @@
(function(){
function toggle(ev) {
var button = ev.target;
var parent = ev.target.parentElement;
while(parent) {
if (parent.tagName === 'TABLE' && parent.classList.contains('summary')) break;
parent = parent.parentElement;
}
if (!parent) return;
var tbody = parent.querySelector('tbody');
if (button.classList.contains('opened')) {
button.classList.remove('opened');
button.classList.add('closed');
tbody.style.display = 'none';
} else {
button.classList.remove('closed');
button.classList.add('opened');
tbody.style.display = 'block';
}
}
var buttons = document.querySelectorAll('.inherited-summary thead .toggle');
for (var i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', toggle);
}
})();

32
docs/script/inner-link.js Normal file
View File

@@ -0,0 +1,32 @@
// inner link(#foo) can not correctly scroll, because page has fixed header,
// so, I manually scroll.
(function(){
var matched = location.hash.match(/errorLines=([\d,]+)/);
if (matched) return;
function adjust() {
window.scrollBy(0, -55);
var el = document.querySelector('.inner-link-active');
if (el) el.classList.remove('inner-link-active');
// ``[ ] . ' " @`` are not valid in DOM id. so must escape these.
var id = location.hash.replace(/([\[\].'"@$])/g, '\\$1');
var el = document.querySelector(id);
if (el) el.classList.add('inner-link-active');
}
window.addEventListener('hashchange', adjust);
if (location.hash) {
setTimeout(adjust, 0);
}
})();
(function(){
var els = document.querySelectorAll('[href^="#"]');
var href = location.href.replace(/#.*$/, ''); // remove existed hash
for (var i = 0; i < els.length; i++) {
var el = els[i];
el.href = href + el.getAttribute('href'); // because el.href is absolute path
}
})();

12
docs/script/manual.js Normal file
View File

@@ -0,0 +1,12 @@
(function(){
var matched = location.pathname.match(/\/(manual\/.*\.html)$/);
if (!matched) return;
var currentName = matched[1];
var cssClass = '.navigation .manual-toc li[data-link="' + currentName + '"]';
var styleText = cssClass + '{ display: block; }\n';
styleText += cssClass + '.indent-h1 a { color: #039BE5 }';
var style = document.createElement('style');
style.textContent = styleText;
document.querySelector('head').appendChild(style);
})();

View File

@@ -0,0 +1,8 @@
(function(){
if (location.protocol === 'file:') {
var elms = document.querySelectorAll('a[href="./"]');
for (var i = 0; i < elms.length; i++) {
elms[i].href = './index.html';
}
}
})();

View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,46 @@
!function(){/*
Copyright (C) 2006 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
window.PR_SHOULD_USE_CONTINUATION=!0;
(function(){function T(a){function d(e){var b=e.charCodeAt(0);if(92!==b)return b;var a=e.charAt(1);return(b=w[a])?b:"0"<=a&&"7">=a?parseInt(e.substring(1),8):"u"===a||"x"===a?parseInt(e.substring(2),16):e.charCodeAt(1)}function f(e){if(32>e)return(16>e?"\\x0":"\\x")+e.toString(16);e=String.fromCharCode(e);return"\\"===e||"-"===e||"]"===e||"^"===e?"\\"+e:e}function b(e){var b=e.substring(1,e.length-1).match(/\\u[0-9A-Fa-f]{4}|\\x[0-9A-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\s\S]|-|[^-\\]/g);e=
[];var a="^"===b[0],c=["["];a&&c.push("^");for(var a=a?1:0,g=b.length;a<g;++a){var h=b[a];if(/\\[bdsw]/i.test(h))c.push(h);else{var h=d(h),k;a+2<g&&"-"===b[a+1]?(k=d(b[a+2]),a+=2):k=h;e.push([h,k]);65>k||122<h||(65>k||90<h||e.push([Math.max(65,h)|32,Math.min(k,90)|32]),97>k||122<h||e.push([Math.max(97,h)&-33,Math.min(k,122)&-33]))}}e.sort(function(e,a){return e[0]-a[0]||a[1]-e[1]});b=[];g=[];for(a=0;a<e.length;++a)h=e[a],h[0]<=g[1]+1?g[1]=Math.max(g[1],h[1]):b.push(g=h);for(a=0;a<b.length;++a)h=b[a],
c.push(f(h[0])),h[1]>h[0]&&(h[1]+1>h[0]&&c.push("-"),c.push(f(h[1])));c.push("]");return c.join("")}function v(e){for(var a=e.source.match(/(?:\[(?:[^\x5C\x5D]|\\[\s\S])*\]|\\u[A-Fa-f0-9]{4}|\\x[A-Fa-f0-9]{2}|\\[0-9]+|\\[^ux0-9]|\(\?[:!=]|[\(\)\^]|[^\x5B\x5C\(\)\^]+)/g),c=a.length,d=[],g=0,h=0;g<c;++g){var k=a[g];"("===k?++h:"\\"===k.charAt(0)&&(k=+k.substring(1))&&(k<=h?d[k]=-1:a[g]=f(k))}for(g=1;g<d.length;++g)-1===d[g]&&(d[g]=++A);for(h=g=0;g<c;++g)k=a[g],"("===k?(++h,d[h]||(a[g]="(?:")):"\\"===
k.charAt(0)&&(k=+k.substring(1))&&k<=h&&(a[g]="\\"+d[k]);for(g=0;g<c;++g)"^"===a[g]&&"^"!==a[g+1]&&(a[g]="");if(e.ignoreCase&&n)for(g=0;g<c;++g)k=a[g],e=k.charAt(0),2<=k.length&&"["===e?a[g]=b(k):"\\"!==e&&(a[g]=k.replace(/[a-zA-Z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var A=0,n=!1,l=!1,m=0,c=a.length;m<c;++m){var p=a[m];if(p.ignoreCase)l=!0;else if(/[a-z]/i.test(p.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi,""))){n=!0;
l=!1;break}}for(var w={b:8,t:9,n:10,v:11,f:12,r:13},r=[],m=0,c=a.length;m<c;++m){p=a[m];if(p.global||p.multiline)throw Error(""+p);r.push("(?:"+v(p)+")")}return new RegExp(r.join("|"),l?"gi":"g")}function U(a,d){function f(a){var c=a.nodeType;if(1==c){if(!b.test(a.className)){for(c=a.firstChild;c;c=c.nextSibling)f(c);c=a.nodeName.toLowerCase();if("br"===c||"li"===c)v[l]="\n",n[l<<1]=A++,n[l++<<1|1]=a}}else if(3==c||4==c)c=a.nodeValue,c.length&&(c=d?c.replace(/\r\n?/g,"\n"):c.replace(/[ \t\r\n]+/g,
" "),v[l]=c,n[l<<1]=A,A+=c.length,n[l++<<1|1]=a)}var b=/(?:^|\s)nocode(?:\s|$)/,v=[],A=0,n=[],l=0;f(a);return{a:v.join("").replace(/\n$/,""),c:n}}function J(a,d,f,b,v){f&&(a={h:a,l:1,j:null,m:null,a:f,c:null,i:d,g:null},b(a),v.push.apply(v,a.g))}function V(a){for(var d=void 0,f=a.firstChild;f;f=f.nextSibling)var b=f.nodeType,d=1===b?d?a:f:3===b?W.test(f.nodeValue)?a:d:d;return d===a?void 0:d}function G(a,d){function f(a){for(var l=a.i,m=a.h,c=[l,"pln"],p=0,w=a.a.match(v)||[],r={},e=0,t=w.length;e<
t;++e){var z=w[e],q=r[z],g=void 0,h;if("string"===typeof q)h=!1;else{var k=b[z.charAt(0)];if(k)g=z.match(k[1]),q=k[0];else{for(h=0;h<A;++h)if(k=d[h],g=z.match(k[1])){q=k[0];break}g||(q="pln")}!(h=5<=q.length&&"lang-"===q.substring(0,5))||g&&"string"===typeof g[1]||(h=!1,q="src");h||(r[z]=q)}k=p;p+=z.length;if(h){h=g[1];var B=z.indexOf(h),D=B+h.length;g[2]&&(D=z.length-g[2].length,B=D-h.length);q=q.substring(5);J(m,l+k,z.substring(0,B),f,c);J(m,l+k+B,h,K(q,h),c);J(m,l+k+D,z.substring(D),f,c)}else c.push(l+
k,q)}a.g=c}var b={},v;(function(){for(var f=a.concat(d),l=[],m={},c=0,p=f.length;c<p;++c){var w=f[c],r=w[3];if(r)for(var e=r.length;0<=--e;)b[r.charAt(e)]=w;w=w[1];r=""+w;m.hasOwnProperty(r)||(l.push(w),m[r]=null)}l.push(/[\0-\uffff]/);v=T(l)})();var A=d.length;return f}function y(a){var d=[],f=[];a.tripleQuotedStrings?d.push(["str",/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,
null,"'\""]):a.multiLineStrings?d.push(["str",/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"]):d.push(["str",/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"]);a.verbatimStrings&&f.push(["str",/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null]);var b=a.hashComments;b&&(a.cStyleComments?(1<b?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\r\n]*)/,
null,"#"]),f.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,null])):d.push(["com",/^#[^\r\n]*/,null,"#"]));a.cStyleComments&&(f.push(["com",/^\/\/[^\r\n]*/,null]),f.push(["com",/^\/\*[\s\S]*?(?:\*\/|$)/,null]));if(b=a.regexLiterals){var v=(b=1<b?"":"\n\r")?".":"[\\S\\s]";f.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*("+
("/(?=[^/*"+b+"])(?:[^/\\x5B\\x5C"+b+"]|\\x5C"+v+"|\\x5B(?:[^\\x5C\\x5D"+b+"]|\\x5C"+v+")*(?:\\x5D|$))+/")+")")])}(b=a.types)&&f.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&f.push(["kwd",new RegExp("^(?:"+b.replace(/[\s,]+/g,"|")+")\\b"),null]);d.push(["pln",/^\s+/,null," \r\n\t\u00a0"]);b="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(b+="(?!s*/)");f.push(["lit",/^@[a-z_$][a-z_$@0-9]*/i,null],["typ",/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],["pln",/^[a-z_$][a-z_$@0-9]*/i,
null],["lit",/^(?:0x[a-f0-9]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+\-]?\d+)?)[a-z]*/i,null,"0123456789"],["pln",/^\\[\s\S]?/,null],["pun",new RegExp(b),null]);return G(d,f)}function L(a,d,f){function b(a){var c=a.nodeType;if(1==c&&!A.test(a.className))if("br"===a.nodeName)v(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((3==c||4==c)&&f){var d=a.nodeValue,q=d.match(n);q&&(c=d.substring(0,q.index),a.nodeValue=c,(d=d.substring(q.index+q[0].length))&&
a.parentNode.insertBefore(l.createTextNode(d),a.nextSibling),v(a),c||a.parentNode.removeChild(a))}}function v(a){function b(a,c){var d=c?a.cloneNode(!1):a,k=a.parentNode;if(k){var k=b(k,1),e=a.nextSibling;k.appendChild(d);for(var f=e;f;f=e)e=f.nextSibling,k.appendChild(f)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;a=b(a.nextSibling,0);for(var d;(d=a.parentNode)&&1===d.nodeType;)a=d;c.push(a)}for(var A=/(?:^|\s)nocode(?:\s|$)/,n=/\r\n?|\n/,l=a.ownerDocument,m=l.createElement("li");a.firstChild;)m.appendChild(a.firstChild);
for(var c=[m],p=0;p<c.length;++p)b(c[p]);d===(d|0)&&c[0].setAttribute("value",d);var w=l.createElement("ol");w.className="linenums";d=Math.max(0,d-1|0)||0;for(var p=0,r=c.length;p<r;++p)m=c[p],m.className="L"+(p+d)%10,m.firstChild||m.appendChild(l.createTextNode("\u00a0")),w.appendChild(m);a.appendChild(w)}function t(a,d){for(var f=d.length;0<=--f;){var b=d[f];I.hasOwnProperty(b)?E.console&&console.warn("cannot override language handler %s",b):I[b]=a}}function K(a,d){a&&I.hasOwnProperty(a)||(a=/^\s*</.test(d)?
"default-markup":"default-code");return I[a]}function M(a){var d=a.j;try{var f=U(a.h,a.l),b=f.a;a.a=b;a.c=f.c;a.i=0;K(d,b)(a);var v=/\bMSIE\s(\d+)/.exec(navigator.userAgent),v=v&&8>=+v[1],d=/\n/g,A=a.a,n=A.length,f=0,l=a.c,m=l.length,b=0,c=a.g,p=c.length,w=0;c[p]=n;var r,e;for(e=r=0;e<p;)c[e]!==c[e+2]?(c[r++]=c[e++],c[r++]=c[e++]):e+=2;p=r;for(e=r=0;e<p;){for(var t=c[e],z=c[e+1],q=e+2;q+2<=p&&c[q+1]===z;)q+=2;c[r++]=t;c[r++]=z;e=q}c.length=r;var g=a.h;a="";g&&(a=g.style.display,g.style.display="none");
try{for(;b<m;){var h=l[b+2]||n,k=c[w+2]||n,q=Math.min(h,k),B=l[b+1],D;if(1!==B.nodeType&&(D=A.substring(f,q))){v&&(D=D.replace(d,"\r"));B.nodeValue=D;var N=B.ownerDocument,u=N.createElement("span");u.className=c[w+1];var y=B.parentNode;y.replaceChild(u,B);u.appendChild(B);f<h&&(l[b+1]=B=N.createTextNode(A.substring(q,h)),y.insertBefore(B,u.nextSibling))}f=q;f>=h&&(b+=2);f>=k&&(w+=2)}}finally{g&&(g.style.display=a)}}catch(x){E.console&&console.log(x&&x.stack||x)}}var E=window,C=["break,continue,do,else,for,if,return,while"],
F=[[C,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,restrict,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],H=[F,"alignas,alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,noexcept,noreturn,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],
O=[F,"abstract,assert,boolean,byte,extends,finally,final,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"],P=[F,"abstract,add,alias,as,ascending,async,await,base,bool,by,byte,checked,decimal,delegate,descending,dynamic,event,finally,fixed,foreach,from,get,global,group,implicit,in,interface,internal,into,is,join,let,lock,null,object,out,override,orderby,params,partial,readonly,ref,remove,sbyte,sealed,select,set,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,value,var,virtual,where,yield"],
F=[F,"abstract,async,await,constructor,debugger,enum,eval,export,function,get,implements,instanceof,interface,let,null,set,undefined,var,with,yield,Infinity,NaN"],Q=[C,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],R=[C,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],C=[C,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],
S=/^(DIR|FILE|array|vector|(de|priority_)?queue|(forward_)?list|stack|(const_)?(reverse_)?iterator|(unordered_)?(multi)?(set|map)|bitset|u?(int|float)\d*)\b/,W=/\S/,X=y({keywords:[H,P,O,F,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",Q,R,C],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),I={};t(X,["default-code"]);t(G([],[["pln",/^[^<?]+/],["dec",
/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),"default-markup htm html mxml xhtml xml xsl".split(" "));t(G([["pln",/^[\s]+/,null," \t\r\n"],["atv",/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,
"\"'"]],[["tag",/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],["pun",/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);t(G([],[["atv",/^[\s\S]+/]]),["uq.val"]);t(y({keywords:H,
hashComments:!0,cStyleComments:!0,types:S}),"c cc cpp cxx cyc m".split(" "));t(y({keywords:"null,true,false"}),["json"]);t(y({keywords:P,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:S}),["cs"]);t(y({keywords:O,cStyleComments:!0}),["java"]);t(y({keywords:C,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);t(y({keywords:Q,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);t(y({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",
hashComments:!0,multiLineStrings:!0,regexLiterals:2}),["perl","pl","pm"]);t(y({keywords:R,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);t(y({keywords:F,cStyleComments:!0,regexLiterals:!0}),["javascript","js","ts","typescript"]);t(y({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,
regexLiterals:!0}),["coffee"]);t(G([],[["str",/^[\s\S]+/]]),["regex"]);var Y=E.PR={createSimpleLexer:G,registerLangHandler:t,sourceDecorator:y,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:E.prettyPrintOne=function(a,d,f){f=f||!1;d=d||null;var b=document.createElement("div");b.innerHTML="<pre>"+a+"</pre>";
b=b.firstChild;f&&L(b,f,!0);M({j:d,m:f,h:b,l:1,a:null,i:null,c:null,g:null});return b.innerHTML},prettyPrint:E.prettyPrint=function(a,d){function f(){for(var b=E.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;p<t.length&&c.now()<b;p++){for(var d=t[p],l=g,m=d;m=m.previousSibling;){var n=m.nodeType,u=(7===n||8===n)&&m.nodeValue;if(u?!/^\??prettify\b/.test(u):3!==n||/\S/.test(m.nodeValue))break;if(u){l={};u.replace(/\b(\w+)=([\w:.%+-]+)/g,function(a,b,c){l[b]=c});break}}m=d.className;if((l!==g||r.test(m))&&
!e.test(m)){n=!1;for(u=d.parentNode;u;u=u.parentNode)if(q.test(u.tagName)&&u.className&&r.test(u.className)){n=!0;break}if(!n){d.className+=" prettyprinted";n=l.lang;if(!n){var n=m.match(w),C;!n&&(C=V(d))&&z.test(C.tagName)&&(n=C.className.match(w));n&&(n=n[1])}if(y.test(d.tagName))u=1;else var u=d.currentStyle,x=v.defaultView,u=(u=u?u.whiteSpace:x&&x.getComputedStyle?x.getComputedStyle(d,null).getPropertyValue("white-space"):0)&&"pre"===u.substring(0,3);x=l.linenums;(x="true"===x||+x)||(x=(x=m.match(/\blinenums\b(?::(\d+))?/))?
x[1]&&x[1].length?+x[1]:!0:!1);x&&L(d,x,u);M({j:n,h:d,m:x,l:u,a:null,i:null,c:null,g:null})}}}p<t.length?E.setTimeout(f,250):"function"===typeof a&&a()}for(var b=d||document.body,v=b.ownerDocument||document,b=[b.getElementsByTagName("pre"),b.getElementsByTagName("code"),b.getElementsByTagName("xmp")],t=[],n=0;n<b.length;++n)for(var l=0,m=b[n].length;l<m;++l)t.push(b[n][l]);var b=null,c=Date;c.now||(c={now:function(){return+new Date}});var p=0,w=/\blang(?:uage)?-([\w.]+)(?!\S)/,r=/\bprettyprint\b/,
e=/\bprettyprinted\b/,y=/pre|xmp/i,z=/^code$/i,q=/^(?:pre|code|xmp)$/i,g={};f()}},H=E.define;"function"===typeof H&&H.amd&&H("google-code-prettify",[],function(){return Y})})();}()

View File

@@ -0,0 +1,25 @@
(function(){
prettyPrint();
var lines = document.querySelectorAll('.prettyprint.linenums li[class^="L"]');
for (var i = 0; i < lines.length; i++) {
lines[i].id = 'lineNumber' + (i + 1);
}
var matched = location.hash.match(/errorLines=([\d,]+)/);
if (matched) {
var lines = matched[1].split(',');
for (var i = 0; i < lines.length; i++) {
var id = '#lineNumber' + lines[i];
var el = document.querySelector(id);
el.classList.add('error-line');
}
return;
}
if (location.hash) {
// ``[ ] . ' " @`` are not valid in DOM id. so must escape these.
var id = location.hash.replace(/([\[\].'"@$])/g, '\\$1');
var line = document.querySelector(id);
if (line) line.classList.add('active');
}
})();

117
docs/script/search.js Normal file
View File

@@ -0,0 +1,117 @@
(function(){
var searchIndex = window.esdocSearchIndex;
var searchBox = document.querySelector('.search-box');
var input = document.querySelector('.search-input');
var result = document.querySelector('.search-result');
var selectedIndex = -1;
var prevText;
// active search box and focus when mouse enter on search box.
searchBox.addEventListener('mouseenter', function(){
searchBox.classList.add('active');
input.focus();
});
// search with text when key is upped.
input.addEventListener('keyup', function(ev){
var text = ev.target.value.toLowerCase();
if (!text) {
result.style.display = 'none';
result.innerHTML = '';
return;
}
if (text === prevText) return;
prevText = text;
var html = {class: [], method: [], member: [], function: [], variable: [], typedef: [], external: [], file: [], test: [], testFile: []};
var len = searchIndex.length;
var kind;
for (var i = 0; i < len; i++) {
var pair = searchIndex[i];
if (pair[0].indexOf(text) !== -1) {
kind = pair[3];
html[kind].push('<li><a href="' + pair[1] + '">' + pair[2] + '</a></li>');
}
}
var innerHTML = '';
for (kind in html) {
var list = html[kind];
if (!list.length) continue;
innerHTML += '<li class="search-separator">' + kind + '</li>\n' + list.join('\n');
}
result.innerHTML = innerHTML;
if (innerHTML) result.style.display = 'block';
selectedIndex = -1;
});
// down, up and enter key are pressed, select search result.
input.addEventListener('keydown', function(ev){
if (ev.keyCode === 40) {
// arrow down
var current = result.children[selectedIndex];
var selected = result.children[selectedIndex + 1];
if (selected && selected.classList.contains('search-separator')) {
var selected = result.children[selectedIndex + 2];
selectedIndex++;
}
if (selected) {
if (current) current.classList.remove('selected');
selectedIndex++;
selected.classList.add('selected');
}
} else if (ev.keyCode === 38) {
// arrow up
var current = result.children[selectedIndex];
var selected = result.children[selectedIndex - 1];
if (selected && selected.classList.contains('search-separator')) {
var selected = result.children[selectedIndex - 2];
selectedIndex--;
}
if (selected) {
if (current) current.classList.remove('selected');
selectedIndex--;
selected.classList.add('selected');
}
} else if (ev.keyCode === 13) {
// enter
var current = result.children[selectedIndex];
if (current) {
var link = current.querySelector('a');
if (link) location.href = link.href;
}
} else {
return;
}
ev.preventDefault();
});
// select search result when search result is mouse over.
result.addEventListener('mousemove', function(ev){
var current = result.children[selectedIndex];
if (current) current.classList.remove('selected');
var li = ev.target;
while (li) {
if (li.nodeName === 'LI') break;
li = li.parentElement;
}
if (li) {
selectedIndex = Array.prototype.indexOf.call(result.children, li);
li.classList.add('selected');
}
});
// clear search result when body is clicked.
document.body.addEventListener('click', function(ev){
selectedIndex = -1;
result.style.display = 'none';
result.innerHTML = '';
});
})();

794
docs/script/search_index.js Normal file
View File

@@ -0,0 +1,794 @@
window.esdocSearchIndex = [
[
"simple-keyboard/src/demo/app.js~app",
"class/src/demo/App.js~App.html",
"<span>App</span> <span class=\"search-result-import-path\">simple-keyboard/src/demo/App.js</span>",
"class"
],
[
"simple-keyboard/src/lib/services/keyboardlayout.js~keyboardlayout",
"class/src/lib/services/KeyboardLayout.js~KeyboardLayout.html",
"<span>KeyboardLayout</span> <span class=\"search-result-import-path\">simple-keyboard/src/lib/services/KeyboardLayout.js</span>",
"class"
],
[
"simple-keyboard/src/lib/services/physicalkeyboard.js~physicalkeyboard",
"class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html",
"<span>PhysicalKeyboard</span> <span class=\"search-result-import-path\">simple-keyboard/src/lib/services/PhysicalKeyboard.js</span>",
"class"
],
[
"simple-keyboard/src/lib/components/keyboard.js~simplekeyboard",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html",
"<span>SimpleKeyboard</span> <span class=\"search-result-import-path\">simple-keyboard/src/lib/components/Keyboard.js</span>",
"class"
],
[
"simple-keyboard/src/lib/tests/testutility.js~testutility",
"class/src/lib/tests/TestUtility.js~TestUtility.html",
"<span>TestUtility</span> <span class=\"search-result-import-path\">simple-keyboard/src/lib/tests/TestUtility.js</span>",
"class"
],
[
"simple-keyboard/src/lib/services/utilities.js~utilities",
"class/src/lib/services/Utilities.js~Utilities.html",
"<span>Utilities</span> <span class=\"search-result-import-path\">simple-keyboard/src/lib/services/Utilities.js</span>",
"class"
],
[
"src/.external-ecmascript.js~array",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array",
"src/.external-ecmascript.js~Array",
"external"
],
[
"src/.external-ecmascript.js~arraybuffer",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer",
"src/.external-ecmascript.js~ArrayBuffer",
"external"
],
[
"src/.external-ecmascript.js~boolean",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean",
"src/.external-ecmascript.js~Boolean",
"external"
],
[
"src/.external-ecmascript.js~dataview",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView",
"src/.external-ecmascript.js~DataView",
"external"
],
[
"src/.external-ecmascript.js~date",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date",
"src/.external-ecmascript.js~Date",
"external"
],
[
"src/.external-ecmascript.js~error",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error",
"src/.external-ecmascript.js~Error",
"external"
],
[
"src/.external-ecmascript.js~evalerror",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/EvalError",
"src/.external-ecmascript.js~EvalError",
"external"
],
[
"src/.external-ecmascript.js~float32array",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array",
"src/.external-ecmascript.js~Float32Array",
"external"
],
[
"src/.external-ecmascript.js~float64array",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float64Array",
"src/.external-ecmascript.js~Float64Array",
"external"
],
[
"src/.external-ecmascript.js~function",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function",
"src/.external-ecmascript.js~Function",
"external"
],
[
"src/.external-ecmascript.js~generator",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator",
"src/.external-ecmascript.js~Generator",
"external"
],
[
"src/.external-ecmascript.js~generatorfunction",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/GeneratorFunction",
"src/.external-ecmascript.js~GeneratorFunction",
"external"
],
[
"src/.external-ecmascript.js~infinity",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Infinity",
"src/.external-ecmascript.js~Infinity",
"external"
],
[
"src/.external-ecmascript.js~int16array",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int16Array",
"src/.external-ecmascript.js~Int16Array",
"external"
],
[
"src/.external-ecmascript.js~int32array",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int32Array",
"src/.external-ecmascript.js~Int32Array",
"external"
],
[
"src/.external-ecmascript.js~int8array",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int8Array",
"src/.external-ecmascript.js~Int8Array",
"external"
],
[
"src/.external-ecmascript.js~internalerror",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/InternalError",
"src/.external-ecmascript.js~InternalError",
"external"
],
[
"src/.external-ecmascript.js~json",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON",
"src/.external-ecmascript.js~JSON",
"external"
],
[
"src/.external-ecmascript.js~map",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map",
"src/.external-ecmascript.js~Map",
"external"
],
[
"src/.external-ecmascript.js~nan",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN",
"src/.external-ecmascript.js~NaN",
"external"
],
[
"src/.external-ecmascript.js~number",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number",
"src/.external-ecmascript.js~Number",
"external"
],
[
"src/.external-ecmascript.js~object",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object",
"src/.external-ecmascript.js~Object",
"external"
],
[
"src/.external-ecmascript.js~promise",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise",
"src/.external-ecmascript.js~Promise",
"external"
],
[
"src/.external-ecmascript.js~proxy",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy",
"src/.external-ecmascript.js~Proxy",
"external"
],
[
"src/.external-ecmascript.js~rangeerror",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RangeError",
"src/.external-ecmascript.js~RangeError",
"external"
],
[
"src/.external-ecmascript.js~referenceerror",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ReferenceError",
"src/.external-ecmascript.js~ReferenceError",
"external"
],
[
"src/.external-ecmascript.js~reflect",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect",
"src/.external-ecmascript.js~Reflect",
"external"
],
[
"src/.external-ecmascript.js~regexp",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp",
"src/.external-ecmascript.js~RegExp",
"external"
],
[
"src/.external-ecmascript.js~set",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set",
"src/.external-ecmascript.js~Set",
"external"
],
[
"src/.external-ecmascript.js~string",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String",
"src/.external-ecmascript.js~String",
"external"
],
[
"src/.external-ecmascript.js~symbol",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol",
"src/.external-ecmascript.js~Symbol",
"external"
],
[
"src/.external-ecmascript.js~syntaxerror",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SyntaxError",
"src/.external-ecmascript.js~SyntaxError",
"external"
],
[
"src/.external-ecmascript.js~typeerror",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError",
"src/.external-ecmascript.js~TypeError",
"external"
],
[
"src/.external-ecmascript.js~urierror",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/URIError",
"src/.external-ecmascript.js~URIError",
"external"
],
[
"src/.external-ecmascript.js~uint16array",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint16Array",
"src/.external-ecmascript.js~Uint16Array",
"external"
],
[
"src/.external-ecmascript.js~uint32array",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint32Array",
"src/.external-ecmascript.js~Uint32Array",
"external"
],
[
"src/.external-ecmascript.js~uint8array",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array",
"src/.external-ecmascript.js~Uint8Array",
"external"
],
[
"src/.external-ecmascript.js~uint8clampedarray",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8ClampedArray",
"src/.external-ecmascript.js~Uint8ClampedArray",
"external"
],
[
"src/.external-ecmascript.js~weakmap",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap",
"src/.external-ecmascript.js~WeakMap",
"external"
],
[
"src/.external-ecmascript.js~weakset",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet",
"src/.external-ecmascript.js~WeakSet",
"external"
],
[
"src/.external-ecmascript.js~boolean",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean",
"src/.external-ecmascript.js~boolean",
"external"
],
[
"src/.external-ecmascript.js~function",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function",
"src/.external-ecmascript.js~function",
"external"
],
[
"src/.external-ecmascript.js~null",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null",
"src/.external-ecmascript.js~null",
"external"
],
[
"src/.external-ecmascript.js~number",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number",
"src/.external-ecmascript.js~number",
"external"
],
[
"src/.external-ecmascript.js~object",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object",
"src/.external-ecmascript.js~object",
"external"
],
[
"src/.external-ecmascript.js~string",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String",
"src/.external-ecmascript.js~string",
"external"
],
[
"src/.external-ecmascript.js~undefined",
"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined",
"src/.external-ecmascript.js~undefined",
"external"
],
[
"src/demo/app.js",
"file/src/demo/App.js.html",
"src/demo/App.js",
"file"
],
[
"src/demo/app.js~app#constructor",
"class/src/demo/App.js~App.html#instance-constructor-constructor",
"src/demo/App.js~App#constructor",
"method"
],
[
"src/demo/app.js~app#handleshiftbutton",
"class/src/demo/App.js~App.html#instance-member-handleShiftButton",
"src/demo/App.js~App#handleShiftButton",
"member"
],
[
"src/demo/app.js~app#keyboard",
"class/src/demo/App.js~App.html#instance-member-keyboard",
"src/demo/App.js~App#keyboard",
"member"
],
[
"src/demo/app.js~app#layoutname",
"class/src/demo/App.js~App.html#instance-member-layoutName",
"src/demo/App.js~App#layoutName",
"member"
],
[
"src/demo/app.js~app#onchange",
"class/src/demo/App.js~App.html#instance-member-onChange",
"src/demo/App.js~App#onChange",
"member"
],
[
"src/demo/app.js~app#ondomloaded",
"class/src/demo/App.js~App.html#instance-member-onDOMLoaded",
"src/demo/App.js~App#onDOMLoaded",
"member"
],
[
"src/demo/app.js~app#onkeypress",
"class/src/demo/App.js~App.html#instance-member-onKeyPress",
"src/demo/App.js~App#onKeyPress",
"member"
],
[
"src/demo/index.js",
"file/src/demo/index.js.html",
"src/demo/index.js",
"file"
],
[
"src/lib/components/keyboard.js",
"file/src/lib/components/Keyboard.js.html",
"src/lib/components/Keyboard.js",
"file"
],
[
"src/lib/components/keyboard.js~simplekeyboard#addbuttontheme",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-method-addButtonTheme",
"src/lib/components/Keyboard.js~SimpleKeyboard#addButtonTheme",
"method"
],
[
"src/lib/components/keyboard.js~simplekeyboard#buttonelements",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-member-buttonElements",
"src/lib/components/Keyboard.js~SimpleKeyboard#buttonElements",
"member"
],
[
"src/lib/components/keyboard.js~simplekeyboard#careteventhandler",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-method-caretEventHandler",
"src/lib/components/Keyboard.js~SimpleKeyboard#caretEventHandler",
"method"
],
[
"src/lib/components/keyboard.js~simplekeyboard#caretposition",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-member-caretPosition",
"src/lib/components/Keyboard.js~SimpleKeyboard#caretPosition",
"member"
],
[
"src/lib/components/keyboard.js~simplekeyboard#clear",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-method-clear",
"src/lib/components/Keyboard.js~SimpleKeyboard#clear",
"method"
],
[
"src/lib/components/keyboard.js~simplekeyboard#clearinput",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-method-clearInput",
"src/lib/components/Keyboard.js~SimpleKeyboard#clearInput",
"method"
],
[
"src/lib/components/keyboard.js~simplekeyboard#constructor",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-constructor-constructor",
"src/lib/components/Keyboard.js~SimpleKeyboard#constructor",
"method"
],
[
"src/lib/components/keyboard.js~simplekeyboard#dispatch",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-method-dispatch",
"src/lib/components/Keyboard.js~SimpleKeyboard#dispatch",
"method"
],
[
"src/lib/components/keyboard.js~simplekeyboard#getbuttonelement",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-method-getButtonElement",
"src/lib/components/Keyboard.js~SimpleKeyboard#getButtonElement",
"method"
],
[
"src/lib/components/keyboard.js~simplekeyboard#getinput",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-method-getInput",
"src/lib/components/Keyboard.js~SimpleKeyboard#getInput",
"method"
],
[
"src/lib/components/keyboard.js~simplekeyboard#getmoduleprop",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-member-getModuleProp",
"src/lib/components/Keyboard.js~SimpleKeyboard#getModuleProp",
"member"
],
[
"src/lib/components/keyboard.js~simplekeyboard#getmoduleslist",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-member-getModulesList",
"src/lib/components/Keyboard.js~SimpleKeyboard#getModulesList",
"member"
],
[
"src/lib/components/keyboard.js~simplekeyboard#handlebuttonclicked",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-method-handleButtonClicked",
"src/lib/components/Keyboard.js~SimpleKeyboard#handleButtonClicked",
"method"
],
[
"src/lib/components/keyboard.js~simplekeyboard#handlebuttonhold",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-method-handleButtonHold",
"src/lib/components/Keyboard.js~SimpleKeyboard#handleButtonHold",
"method"
],
[
"src/lib/components/keyboard.js~simplekeyboard#handlebuttonmousedown",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-method-handleButtonMouseDown",
"src/lib/components/Keyboard.js~SimpleKeyboard#handleButtonMouseDown",
"method"
],
[
"src/lib/components/keyboard.js~simplekeyboard#handlebuttonmouseup",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-method-handleButtonMouseUp",
"src/lib/components/Keyboard.js~SimpleKeyboard#handleButtonMouseUp",
"method"
],
[
"src/lib/components/keyboard.js~simplekeyboard#handlecaret",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-method-handleCaret",
"src/lib/components/Keyboard.js~SimpleKeyboard#handleCaret",
"method"
],
[
"src/lib/components/keyboard.js~simplekeyboard#holdinteractiontimeout",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-member-holdInteractionTimeout",
"src/lib/components/Keyboard.js~SimpleKeyboard#holdInteractionTimeout",
"member"
],
[
"src/lib/components/keyboard.js~simplekeyboard#holdtimeout",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-member-holdTimeout",
"src/lib/components/Keyboard.js~SimpleKeyboard#holdTimeout",
"member"
],
[
"src/lib/components/keyboard.js~simplekeyboard#initialized",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-member-initialized",
"src/lib/components/Keyboard.js~SimpleKeyboard#initialized",
"member"
],
[
"src/lib/components/keyboard.js~simplekeyboard#input",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-member-input",
"src/lib/components/Keyboard.js~SimpleKeyboard#input",
"member"
],
[
"src/lib/components/keyboard.js~simplekeyboard#ismousehold",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-member-isMouseHold",
"src/lib/components/Keyboard.js~SimpleKeyboard#isMouseHold",
"member"
],
[
"src/lib/components/keyboard.js~simplekeyboard#keyboarddom",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-member-keyboardDOM",
"src/lib/components/Keyboard.js~SimpleKeyboard#keyboardDOM",
"member"
],
[
"src/lib/components/keyboard.js~simplekeyboard#keyboarddomclass",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-member-keyboardDOMClass",
"src/lib/components/Keyboard.js~SimpleKeyboard#keyboardDOMClass",
"member"
],
[
"src/lib/components/keyboard.js~simplekeyboard#keyboardpluginclasses",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-member-keyboardPluginClasses",
"src/lib/components/Keyboard.js~SimpleKeyboard#keyboardPluginClasses",
"member"
],
[
"src/lib/components/keyboard.js~simplekeyboard#loadmodules",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-method-loadModules",
"src/lib/components/Keyboard.js~SimpleKeyboard#loadModules",
"method"
],
[
"src/lib/components/keyboard.js~simplekeyboard#modules",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-member-modules",
"src/lib/components/Keyboard.js~SimpleKeyboard#modules",
"member"
],
[
"src/lib/components/keyboard.js~simplekeyboard#oninit",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-method-onInit",
"src/lib/components/Keyboard.js~SimpleKeyboard#onInit",
"method"
],
[
"src/lib/components/keyboard.js~simplekeyboard#onmodulesloaded",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-method-onModulesLoaded",
"src/lib/components/Keyboard.js~SimpleKeyboard#onModulesLoaded",
"method"
],
[
"src/lib/components/keyboard.js~simplekeyboard#onrender",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-method-onRender",
"src/lib/components/Keyboard.js~SimpleKeyboard#onRender",
"method"
],
[
"src/lib/components/keyboard.js~simplekeyboard#options",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-member-options",
"src/lib/components/Keyboard.js~SimpleKeyboard#options",
"member"
],
[
"src/lib/components/keyboard.js~simplekeyboard#physicalkeyboardinterface",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-member-physicalKeyboardInterface",
"src/lib/components/Keyboard.js~SimpleKeyboard#physicalKeyboardInterface",
"member"
],
[
"src/lib/components/keyboard.js~simplekeyboard#registermodule",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-member-registerModule",
"src/lib/components/Keyboard.js~SimpleKeyboard#registerModule",
"member"
],
[
"src/lib/components/keyboard.js~simplekeyboard#removebuttontheme",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-method-removeButtonTheme",
"src/lib/components/Keyboard.js~SimpleKeyboard#removeButtonTheme",
"method"
],
[
"src/lib/components/keyboard.js~simplekeyboard#render",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-method-render",
"src/lib/components/Keyboard.js~SimpleKeyboard#render",
"method"
],
[
"src/lib/components/keyboard.js~simplekeyboard#replaceinput",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-method-replaceInput",
"src/lib/components/Keyboard.js~SimpleKeyboard#replaceInput",
"method"
],
[
"src/lib/components/keyboard.js~simplekeyboard#setinput",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-method-setInput",
"src/lib/components/Keyboard.js~SimpleKeyboard#setInput",
"method"
],
[
"src/lib/components/keyboard.js~simplekeyboard#setoptions",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-member-setOptions",
"src/lib/components/Keyboard.js~SimpleKeyboard#setOptions",
"member"
],
[
"src/lib/components/keyboard.js~simplekeyboard#syncinstanceinputs",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-method-syncInstanceInputs",
"src/lib/components/Keyboard.js~SimpleKeyboard#syncInstanceInputs",
"method"
],
[
"src/lib/components/keyboard.js~simplekeyboard#utilities",
"class/src/lib/components/Keyboard.js~SimpleKeyboard.html#instance-member-utilities",
"src/lib/components/Keyboard.js~SimpleKeyboard#utilities",
"member"
],
[
"src/lib/index.js",
"file/src/lib/index.js.html",
"src/lib/index.js",
"file"
],
[
"src/lib/services/keyboardlayout.js",
"file/src/lib/services/KeyboardLayout.js.html",
"src/lib/services/KeyboardLayout.js",
"file"
],
[
"src/lib/services/keyboardlayout.js~keyboardlayout.getdefaultlayout",
"class/src/lib/services/KeyboardLayout.js~KeyboardLayout.html#static-method-getDefaultLayout",
"src/lib/services/KeyboardLayout.js~KeyboardLayout.getDefaultLayout",
"method"
],
[
"src/lib/services/physicalkeyboard.js",
"file/src/lib/services/PhysicalKeyboard.js.html",
"src/lib/services/PhysicalKeyboard.js",
"file"
],
[
"src/lib/services/physicalkeyboard.js~physicalkeyboard#constructor",
"class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html#instance-constructor-constructor",
"src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard#constructor",
"method"
],
[
"src/lib/services/physicalkeyboard.js~physicalkeyboard#getsimplekeyboardlayoutkey",
"class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html#instance-method-getSimpleKeyboardLayoutKey",
"src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard#getSimpleKeyboardLayoutKey",
"method"
],
[
"src/lib/services/physicalkeyboard.js~physicalkeyboard#initkeyboardlistener",
"class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html#instance-method-initKeyboardListener",
"src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard#initKeyboardListener",
"method"
],
[
"src/lib/services/physicalkeyboard.js~physicalkeyboard#simplekeyboardinstance",
"class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html#instance-member-simpleKeyboardInstance",
"src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard#simpleKeyboardInstance",
"member"
],
[
"src/lib/services/utilities.js",
"file/src/lib/services/Utilities.js.html",
"src/lib/services/Utilities.js",
"file"
],
[
"src/lib/services/utilities.js~utilities#addstringat",
"class/src/lib/services/Utilities.js~Utilities.html#instance-method-addStringAt",
"src/lib/services/Utilities.js~Utilities#addStringAt",
"method"
],
[
"src/lib/services/utilities.js~utilities#camelcase",
"class/src/lib/services/Utilities.js~Utilities.html#instance-method-camelCase",
"src/lib/services/Utilities.js~Utilities#camelCase",
"method"
],
[
"src/lib/services/utilities.js~utilities#constructor",
"class/src/lib/services/Utilities.js~Utilities.html#instance-constructor-constructor",
"src/lib/services/Utilities.js~Utilities#constructor",
"method"
],
[
"src/lib/services/utilities.js~utilities#countinarray",
"class/src/lib/services/Utilities.js~Utilities.html#instance-method-countInArray",
"src/lib/services/Utilities.js~Utilities#countInArray",
"method"
],
[
"src/lib/services/utilities.js~utilities#getbuttonclass",
"class/src/lib/services/Utilities.js~Utilities.html#instance-method-getButtonClass",
"src/lib/services/Utilities.js~Utilities#getButtonClass",
"method"
],
[
"src/lib/services/utilities.js~utilities#getbuttondisplayname",
"class/src/lib/services/Utilities.js~Utilities.html#instance-method-getButtonDisplayName",
"src/lib/services/Utilities.js~Utilities#getButtonDisplayName",
"method"
],
[
"src/lib/services/utilities.js~utilities#getdefaultdiplay",
"class/src/lib/services/Utilities.js~Utilities.html#instance-method-getDefaultDiplay",
"src/lib/services/Utilities.js~Utilities#getDefaultDiplay",
"method"
],
[
"src/lib/services/utilities.js~utilities#getupdatedinput",
"class/src/lib/services/Utilities.js~Utilities.html#instance-method-getUpdatedInput",
"src/lib/services/Utilities.js~Utilities#getUpdatedInput",
"method"
],
[
"src/lib/services/utilities.js~utilities#handlemaxlength",
"class/src/lib/services/Utilities.js~Utilities.html#instance-method-handleMaxLength",
"src/lib/services/Utilities.js~Utilities#handleMaxLength",
"method"
],
[
"src/lib/services/utilities.js~utilities#ismaxlengthreached",
"class/src/lib/services/Utilities.js~Utilities.html#instance-method-isMaxLengthReached",
"src/lib/services/Utilities.js~Utilities#isMaxLengthReached",
"method"
],
[
"src/lib/services/utilities.js~utilities#maxlengthreached",
"class/src/lib/services/Utilities.js~Utilities.html#instance-member-maxLengthReached",
"src/lib/services/Utilities.js~Utilities#maxLengthReached",
"member"
],
[
"src/lib/services/utilities.js~utilities#removeat",
"class/src/lib/services/Utilities.js~Utilities.html#instance-method-removeAt",
"src/lib/services/Utilities.js~Utilities#removeAt",
"method"
],
[
"src/lib/services/utilities.js~utilities#simplekeyboardinstance",
"class/src/lib/services/Utilities.js~Utilities.html#instance-member-simpleKeyboardInstance",
"src/lib/services/Utilities.js~Utilities#simpleKeyboardInstance",
"member"
],
[
"src/lib/services/utilities.js~utilities#updatecaretpos",
"class/src/lib/services/Utilities.js~Utilities.html#instance-method-updateCaretPos",
"src/lib/services/Utilities.js~Utilities#updateCaretPos",
"method"
],
[
"src/lib/tests/testutility.js",
"file/src/lib/tests/TestUtility.js.html",
"src/lib/tests/TestUtility.js",
"file"
],
[
"src/lib/tests/testutility.js~testutility#clear",
"class/src/lib/tests/TestUtility.js~TestUtility.html#instance-member-clear",
"src/lib/tests/TestUtility.js~TestUtility#clear",
"member"
],
[
"src/lib/tests/testutility.js~testutility#iteratebuttons",
"class/src/lib/tests/TestUtility.js~TestUtility.html#instance-member-iterateButtons",
"src/lib/tests/TestUtility.js~TestUtility#iterateButtons",
"member"
],
[
"src/lib/tests/testutility.js~testutility#setdom",
"class/src/lib/tests/TestUtility.js~TestUtility.html#instance-member-setDOM",
"src/lib/tests/TestUtility.js~TestUtility#setDOM",
"member"
],
[
"src/lib/tests/testutility.js~testutility#testlayoutfctbuttons",
"class/src/lib/tests/TestUtility.js~TestUtility.html#instance-member-testLayoutFctButtons",
"src/lib/tests/TestUtility.js~TestUtility#testLayoutFctButtons",
"member"
],
[
"src/lib/tests/testutility.js~testutility#testlayoutstdbuttons",
"class/src/lib/tests/TestUtility.js~TestUtility.html#instance-member-testLayoutStdButtons",
"src/lib/tests/TestUtility.js~TestUtility#testLayoutStdButtons",
"member"
]
]

View File

@@ -0,0 +1,54 @@
(function(){
function toggle(ev) {
var button = ev.target;
var parent = ev.target.parentElement;
while(parent) {
if (parent.tagName === 'TR' && parent.classList.contains('test-interface')) break;
parent = parent.parentElement;
}
if (!parent) return;
var direction;
if (button.classList.contains('opened')) {
button.classList.remove('opened');
button.classList.add('closed');
direction = 'closed';
} else {
button.classList.remove('closed');
button.classList.add('opened');
direction = 'opened';
}
var targetDepth = parseInt(parent.dataset.testDepth, 10) + 1;
var nextElement = parent.nextElementSibling;
while (nextElement) {
var depth = parseInt(nextElement.dataset.testDepth, 10);
if (depth >= targetDepth) {
if (direction === 'opened') {
if (depth === targetDepth) nextElement.style.display = '';
} else if (direction === 'closed') {
nextElement.style.display = 'none';
var innerButton = nextElement.querySelector('.toggle');
if (innerButton && innerButton.classList.contains('opened')) {
innerButton.classList.remove('opened');
innerButton.classList.add('closed');
}
}
} else {
break;
}
nextElement = nextElement.nextElementSibling;
}
}
var buttons = document.querySelectorAll('.test-summary tr.test-interface .toggle');
for (var i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', toggle);
}
var topDescribes = document.querySelectorAll('.test-summary tr[data-test-depth="0"]');
for (var i = 0; i < topDescribes.length; i++) {
topDescribes[i].style.display = '';
}
})();

137
docs/source.html Normal file
View File

@@ -0,0 +1,137 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<base data-ice="baseUrl" href="">
<title data-ice="title">Source | simple-keyboard</title>
<link type="text/css" rel="stylesheet" href="css/style.css">
<link type="text/css" rel="stylesheet" href="css/prettify-tomorrow.css">
<script src="script/prettify/prettify.js"></script>
<script src="script/manual.js"></script>
<meta name="description" content="On-screen Javascript Virtual Keyboard"><meta property="twitter:card" content="summary"><meta property="twitter:title" content="simple-keyboard"><meta property="twitter:description" content="On-screen Javascript Virtual Keyboard"></head>
<body class="layout-container" data-ice="rootContainer">
<header>
<a href="./">Home</a>
<a href="identifiers.html">Reference</a>
<a href="source.html">Source</a>
<div class="search-box">
<span>
<img src="./image/search.png">
<span class="search-input-edge"></span><input class="search-input"><span class="search-input-edge"></span>
</span>
<ul class="search-result"></ul>
</div>
<a style="position:relative; top:3px;" href="https://github.com/hodgef/simple-keyboard"><img width="20px" src="./image/github.png"></a></header>
<nav class="navigation" data-ice="nav"><div>
<ul>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#demo">demo</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/demo/App.js~App.html">App</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-components">lib/components</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/components/Keyboard.js~SimpleKeyboard.html">SimpleKeyboard</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-services">lib/services</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/KeyboardLayout.js~KeyboardLayout.html">KeyboardLayout</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html">PhysicalKeyboard</a></span></span></li>
<li data-ice="doc"><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/services/Utilities.js~Utilities.html">Utilities</a></span></span></li>
<li data-ice="doc"><a data-ice="dirPath" class="nav-dir-path" href="identifiers.html#lib-tests">lib/tests</a><span data-ice="kind" class="kind-class">C</span><span data-ice="name"><span><a href="class/src/lib/tests/TestUtility.js~TestUtility.html">TestUtility</a></span></span></li>
</ul>
</div>
</nav>
<div class="content" data-ice="content"><h1>Source <img data-ice="coverageBadge" src="./badge.svg"><span data-ice="totalCoverageCount" class="total-coverage-count">77/77</span></h1>
<table class="files-summary" data-ice="files" data-use-coverage="true">
<thead>
<tr>
<td>File</td>
<td>Identifier</td>
<td class="coverage">Document</td>
<td style="display: none;">Size</td>
<td style="display: none;">Lines</td>
<td style="display: none;">Updated</td>
</tr>
</thead>
<tbody>
<tr data-ice="file">
<td data-ice="filePath"><span><a href="file/src/demo/App.js.html">src/demo/App.js</a></span></td>
<td data-ice="identifier" class="identifiers"><span><a href="class/src/demo/App.js~App.html">App</a></span></td>
<td class="coverage"><span data-ice="coverage">100 %</span><span data-ice="coverageCount" class="coverage-count">8/8</span></td>
<td style="display: none;" data-ice="size">1921 byte</td>
<td style="display: none;" data-ice="lines">84</td>
<td style="display: none;" data-ice="updated">2018-11-05 16:32:42 (UTC)</td>
</tr>
<tr data-ice="file">
<td data-ice="filePath"><span><a href="file/src/demo/index.js.html">src/demo/index.js</a></span></td>
<td data-ice="identifier" class="identifiers">-</td>
<td class="coverage"><span data-ice="coverage">-</span></td>
<td style="display: none;" data-ice="size">70 byte</td>
<td style="display: none;" data-ice="lines">5</td>
<td style="display: none;" data-ice="updated">2018-09-02 03:31:31 (UTC)</td>
</tr>
<tr data-ice="file">
<td data-ice="filePath"><span><a href="file/src/lib/components/Keyboard.js.html">src/lib/components/Keyboard.js</a></span></td>
<td data-ice="identifier" class="identifiers"><span><a href="class/src/lib/components/Keyboard.js~SimpleKeyboard.html">SimpleKeyboard</a></span></td>
<td class="coverage"><span data-ice="coverage">100 %</span><span data-ice="coverageCount" class="coverage-count">41/41</span></td>
<td style="display: none;" data-ice="size">24443 byte</td>
<td style="display: none;" data-ice="lines">759</td>
<td style="display: none;" data-ice="updated">2018-11-05 16:42:42 (UTC)</td>
</tr>
<tr data-ice="file">
<td data-ice="filePath"><span><a href="file/src/lib/index.js.html">src/lib/index.js</a></span></td>
<td data-ice="identifier" class="identifiers">-</td>
<td class="coverage"><span data-ice="coverage">-</span></td>
<td style="display: none;" data-ice="size">85 byte</td>
<td style="display: none;" data-ice="lines">2</td>
<td style="display: none;" data-ice="updated">2018-06-06 23:02:53 (UTC)</td>
</tr>
<tr data-ice="file">
<td data-ice="filePath"><span><a href="file/src/lib/services/KeyboardLayout.js.html">src/lib/services/KeyboardLayout.js</a></span></td>
<td data-ice="identifier" class="identifiers"><span><a href="class/src/lib/services/KeyboardLayout.js~KeyboardLayout.html">KeyboardLayout</a></span></td>
<td class="coverage"><span data-ice="coverage">100 %</span><span data-ice="coverageCount" class="coverage-count">2/2</span></td>
<td style="display: none;" data-ice="size">746 byte</td>
<td style="display: none;" data-ice="lines">28</td>
<td style="display: none;" data-ice="updated">2018-10-03 02:14:58 (UTC)</td>
</tr>
<tr data-ice="file">
<td data-ice="filePath"><span><a href="file/src/lib/services/PhysicalKeyboard.js.html">src/lib/services/PhysicalKeyboard.js</a></span></td>
<td data-ice="identifier" class="identifiers"><span><a href="class/src/lib/services/PhysicalKeyboard.js~PhysicalKeyboard.html">PhysicalKeyboard</a></span></td>
<td class="coverage"><span data-ice="coverage">100 %</span><span data-ice="coverageCount" class="coverage-count">5/5</span></td>
<td style="display: none;" data-ice="size">2879 byte</td>
<td style="display: none;" data-ice="lines">96</td>
<td style="display: none;" data-ice="updated">2018-10-03 02:15:56 (UTC)</td>
</tr>
<tr data-ice="file">
<td data-ice="filePath"><span><a href="file/src/lib/services/Utilities.js.html">src/lib/services/Utilities.js</a></span></td>
<td data-ice="identifier" class="identifiers"><span><a href="class/src/lib/services/Utilities.js~Utilities.html">Utilities</a></span></td>
<td class="coverage"><span data-ice="coverage">100 %</span><span data-ice="coverageCount" class="coverage-count">15/15</span></td>
<td style="display: none;" data-ice="size">10567 byte</td>
<td style="display: none;" data-ice="lines">352</td>
<td style="display: none;" data-ice="updated">2018-10-03 17:11:36 (UTC)</td>
</tr>
<tr data-ice="file">
<td data-ice="filePath"><span><a href="file/src/lib/tests/TestUtility.js.html">src/lib/tests/TestUtility.js</a></span></td>
<td data-ice="identifier" class="identifiers"><span><a href="class/src/lib/tests/TestUtility.js~TestUtility.html">TestUtility</a></span></td>
<td class="coverage"><span data-ice="coverage">100 %</span><span data-ice="coverageCount" class="coverage-count">6/6</span></td>
<td style="display: none;" data-ice="size">2830 byte</td>
<td style="display: none;" data-ice="lines">106</td>
<td style="display: none;" data-ice="updated">2018-10-04 22:12:09 (UTC)</td>
</tr>
</tbody>
</table>
</div>
<footer class="footer">
Generated by <a href="https://esdoc.org">ESDoc<span data-ice="esdocVersion">(1.1.0)</span><img src="./image/esdoc-logo-mini-black.png"></a>
</footer>
<script src="script/search_index.js"></script>
<script src="script/search.js"></script>
<script src="script/pretty-print.js"></script>
<script src="script/inherited-summary.js"></script>
<script src="script/test-summary.js"></script>
<script src="script/inner-link.js"></script>
<script src="script/patch-for-local.js"></script>
</body>
</html>

1372
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
{
"name": "simple-keyboard",
"version": "2.3.22",
"description": "On-screen Virtual Keyboard",
"version": "2.7.7",
"description": "On-screen Javascript Virtual Keyboard",
"main": "build/index.js",
"scripts": {
"start": "node scripts/start.js",
@@ -9,7 +9,8 @@
"demo": "node scripts/demo.js",
"test": "node scripts/test.js --env=jsdom",
"postinstall": "node bin/postinstall",
"prepublish": "npm run build"
"prepublish": "npm run build",
"docs": "esdoc"
},
"repository": {
"type": "git",
@@ -19,7 +20,7 @@
"bugs": {
"url": "https://github.com/hodgef/simple-keyboard/issues"
},
"homepage": "https://franciscohodge.com/simple-keyboard",
"homepage": "https://virtual-keyboard.js.org/",
"keywords": [
"javascript",
"es6",
@@ -27,10 +28,13 @@
"keyboard",
"onscreen",
"virtual",
"screen-keyboard",
"component",
"virtual-keyboard",
"touchscreen",
"touch-screen"
"touch-screen",
"kiosk",
"osk"
],
"license": "MIT",
"dependencies": {},
@@ -47,6 +51,9 @@
"copy-webpack-plugin": "^4.3.1",
"css-loader": "0.28.7",
"dotenv": "4.0.0",
"esdoc": "^1.1.0",
"esdoc-ecmascript-proposal-plugin": "^1.0.0",
"esdoc-standard-plugin": "^1.0.0",
"eslint": "4.10.0",
"eslint-config-react-app": "^2.0.1",
"eslint-loader": "1.9.0",
@@ -58,6 +65,9 @@
"file-loader": "1.1.5",
"fs-extra": "3.0.1",
"html-webpack-plugin": "2.29.0",
"istanbul": "^0.4.5",
"istanbul-api": "^2.0.6",
"istanbul-reports": "^2.0.1",
"jest": "20.0.4",
"object-assign": "4.1.1",
"postcss-flexbugs-fixes": "3.2.0",
@@ -66,7 +76,7 @@
"prop-types": "^15.6.1",
"raf": "3.4.0",
"react": "^16.2.0",
"react-dev-utils": "^4.2.1",
"react-dev-utils": "^4.2.2",
"react-dom": "^16.2.0",
"style-loader": "0.19.0",
"sw-precache-webpack-plugin": "0.11.4",
@@ -78,7 +88,8 @@
},
"jest": {
"collectCoverageFrom": [
"src/**/*.{js,jsx,mjs}"
"src/**/*.{js,jsx,mjs}",
"!**/tests/**"
],
"setupFiles": [
"<rootDir>/config/polyfills.js"

View File

@@ -1,36 +1,56 @@
import Keyboard from '../lib';
import './css/App.css';
/**
* simple-keyboard demo
*/
class App {
/**
* Instantiates the demo class
*/
constructor(){
document.addEventListener('DOMContentLoaded', this.onDOMLoaded);
/**
* Default input name
* @type {string}
*/
this.layoutName = "default";
}
/**
* Executed when the DOM is ready
*/
onDOMLoaded = () => {
/**
* Creates a new simple-keyboard instance
*/
this.keyboard = new Keyboard({
debug: true,
layoutName: this.layoutName,
onChange: input => this.onChange(input),
onKeyPress: button => this.onKeyPress(button),
newLineOnEnter: true
newLineOnEnter: true,
physicalKeyboardHighlight: true,
});
this.keyboard.setInput("Hello World!");
/**
* Adding preview (demo only)
*/
document.querySelector('.simple-keyboard').insertAdjacentHTML('beforebegin', `
<div class="simple-keyboard-preview">
<textarea class="input" readonly>Hello World!</textarea>
<textarea class="input"></textarea>
</div>
`);
console.log(this.keyboard);
document.querySelector('.input').addEventListener('change', (event) => {
this.keyboard.setInput(event.target.value);
});
}
/**
* Handles shift functionality
*/
handleShiftButton = () => {
let layoutName = this.layoutName;
let shiftToggle = this.layoutName = layoutName === "default" ? "shift" : "default";
@@ -40,10 +60,16 @@ class App {
});
}
/**
* Called when simple-keyboard input has changed
*/
onChange = input => {
document.querySelector('.input').value = input;
}
/**
* Called when a simple-keyboard key is pressed
*/
onKeyPress = button => {
console.log("Button pressed", button);

View File

@@ -1,77 +0,0 @@
import Keyboard from '../lib';
import './css/MultipleInputsDemo.css';
class App {
constructor(){
document.addEventListener('DOMContentLoaded', this.onDOMLoaded);
this.layoutName = "default";
}
onDOMLoaded = () => {
this.keyboard = new Keyboard({
debug: true,
layoutName: this.layoutName,
onChange: input => this.onChange(input),
onKeyPress: button => this.onKeyPress(button)
});
/**
* Adding preview (demo only)
* In production, this would be part of your HTML file
*/
document.querySelector('.simple-keyboard').insertAdjacentHTML('beforebegin', `
<div>
<label>Input 1</label>
<input class="input" id="input1" value=""/>
</div>
<div>
<label>Input 2</label>
<input class="input" id="input2" value=""/>
</div>
`);
/**
* Changing active input onFocus
*/
document.querySelectorAll('.input')
.forEach(input => input.addEventListener('focus', this.onInputFocus));
console.log(this.keyboard);
}
onInputFocus = event => {
this.selectedInput = `#${event.target.id}`;
this.keyboard.setOptions({
inputName: event.target.id
});
}
onChange = input => {
let currentInput = this.selectedInput || '.input';
document.querySelector(currentInput).value = input;
}
onKeyPress = button => {
console.log("Button pressed", button);
/**
* Shift functionality
*/
if(button === "{lock}" || button === "{shift}")
this.handleShiftButton();
}
handleShiftButton = () => {
let layoutName = this.layoutName;
let shiftToggle = this.layoutName = layoutName === "default" ? "shift" : "default";
this.keyboard.setOptions({
layoutName: shiftToggle
});
}
}
export default App;

View File

@@ -1,6 +1,6 @@
#root {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
max-width: 1000px;
max-width: 850px;
margin: 0 auto;
padding-top: 20px;
}
@@ -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: 300px;
height: 260px;
border-top-right-radius: 5px;
border-top-left-radius: 5px;
padding: 10px;

View File

@@ -1,40 +0,0 @@
#root {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
max-width: 1000px;
margin: 0 auto;
padding-top: 20px;
}
#root .screenContainer {
background: rgba(0,0,0,0.8);
border: 20px solid;
height: 300px;
border-top-right-radius: 5px;
border-top-left-radius: 5px;
padding: 10px;
box-sizing: border-box;
}
#root .inputContainer {
color: white;
background: transparent;
border: none;
outline: none;
font-family: monospace;
width: 100%;
height: 100%;
}
.simple-keyboard.hg-layout-custom {
border-top-left-radius: 0px;
border-top-right-radius: 0px;
}
input {
padding: 10px;
margin: 10px 0;
}
label {
display: block;
}

View File

@@ -0,0 +1,67 @@
import TestUtility from '../../lib/tests/TestUtility';
import Index from '../index';
import App from '../App';
let testUtil = new TestUtility();
it('Demo will load', () => {
testUtil.setDOM();
let demo = new App();
});
it('Demo onDOMLoaded will work', () => {
testUtil.setDOM();
let demo = new App();
demo.onDOMLoaded();
expect(demo.keyboard).toBeTruthy();
});
it('Demo onChange will work', () => {
testUtil.setDOM();
let demo = new App();
demo.onDOMLoaded();
demo.onChange("test");
expect(document.body.querySelector('.input').value).toBe("test");
});
it('Demo onChange will work', () => {
testUtil.setDOM();
let demo = new App();
demo.onDOMLoaded();
demo.keyboard.getButtonElement("q").onclick();
expect(document.body.querySelector('.input').value).toBe("q");
});
it('Demo input change will work', () => {
testUtil.setDOM();
let demo = new App();
demo.onDOMLoaded();
document.body.querySelector('.input').value = "test";
document.body.querySelector('.input').dispatchEvent(new Event('change'));
expect(demo.keyboard.getInput()).toBe("test");
});
it('Demo handleShiftButton will work', () => {
testUtil.setDOM();
let demo = new App();
demo.onDOMLoaded();
demo.keyboard.getButtonElement("{shift}")[0].onclick();
expect(demo.keyboard.options.layoutName).toBe("shift");
demo.keyboard.getButtonElement("{shift}")[0].onclick();
expect(demo.keyboard.options.layoutName).toBe("default");
});

View File

@@ -51,6 +51,10 @@ body, html {
padding: 5px;
background: white;
border-bottom: 1px solid #b5b5b5;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
.simple-keyboard.hg-theme-default .hg-button:active {
@@ -63,4 +67,37 @@ body, html {
align-items: center;
display: flex;
justify-content: center;
}
.simple-keyboard.hg-theme-default .hg-button.hg-button-numpadadd {
height: 85px;
}
.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, 0.53);
color: white;
}
.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;
}

View File

@@ -1,10 +1,22 @@
import './Keyboard.css';
// Services
import PhysicalKeyboard from '../services/PhysicalKeyboard';
import KeyboardLayout from '../services/KeyboardLayout';
import Utilities from '../services/Utilities';
/**
* Root class for simple-keyboard
* This class:
* - Parses the options
* - Renders the rows and buttons
* - Handles button functionality
*/
class 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.
*/
constructor(...params){
let keyboardDOMQuery = typeof params[0] === "string" ? params[0] : '.simple-keyboard';
let options = typeof params[0] === "object" ? params[0] : params[1];
@@ -12,30 +24,140 @@ class SimpleKeyboard {
if(!options)
options = {};
/**
* Initializing Utilities
*/
this.utilities = new Utilities(this);
/**
* Processing options
*/
this.keyboardDOM = document.querySelector(keyboardDOMQuery);
/**
* @type {object}
* @property {object} layout Modify the keyboard layout.
* @property {string} layoutName Specifies which layout should be used.
* @property {object} display Replaces variable buttons (such as {bksp}) with a human-friendly name (e.g.: “backspace”).
* @property {boolean} mergeDisplay By default, when you set the display property, you replace the default one. This setting merges them instead.
* @property {string} theme A prop to add your own css classes to the keyboard wrapper. You can add multiple classes separated by a space.
* @property {Array} buttonTheme A prop to add your own css classes to one or several buttons.
* @property {boolean} debug Runs a console.log every time a key is pressed. Displays the buttons pressed and the current input.
* @property {boolean} newLineOnEnter Specifies whether clicking the “ENTER” button will input a newline (\n) or not.
* @property {boolean} tabCharOnTab Specifies whether clicking the “TAB” button will input a tab character (\t) or not.
* @property {string} inputName Allows you to use a single simple-keyboard instance for several inputs.
* @property {number} maxLength Restrains all of simple-keyboard inputs to a certain length. This should be used in addition to the input elements maxlengthattribute.
* @property {object} maxLength Restrains simple-keyboards individual inputs to a certain length. This should be used in addition to the input elements maxlengthattribute.
* @property {boolean} syncInstanceInputs When set to true, this option synchronizes the internal input of every simple-keyboard instance.
* @property {boolean} physicalKeyboardHighlight Enable highlighting of keys pressed on physical keyboard.
* @property {string} physicalKeyboardHighlightTextColor Define the text color that the physical keyboard highlighted key should have.
* @property {string} physicalKeyboardHighlightBgColor Define the background color that the physical keyboard highlighted key should have.
* @property {function(button: string):string} onKeyPress Executes the callback function on key press. Returns button layout name (i.e.: “{shift}”).
* @property {function(input: string):string} onChange Executes the callback function on input change. Returns the current inputs string.
* @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.
*/
this.options = options;
this.options.layoutName = this.options.layoutName || "default";
this.options.theme = this.options.theme || "hg-theme-default";
this.options.inputName = this.options.inputName || "default";
/**
* @type {object} Classes identifying loaded plugins
*/
this.keyboardPluginClasses = '';
/**
* Bindings
*/
this.handleButtonClicked = this.handleButtonClicked.bind(this);
this.syncInstanceInputs = this.syncInstanceInputs.bind(this);
this.clearInput = this.clearInput.bind(this);
this.getInput = this.getInput.bind(this);
this.setInput = this.setInput.bind(this);
this.replaceInput = this.replaceInput.bind(this);
this.clear = this.clear.bind(this);
this.dispatch = this.dispatch.bind(this);
this.addButtonTheme = this.addButtonTheme.bind(this);
this.removeButtonTheme = this.removeButtonTheme.bind(this);
this.getButtonElement = this.getButtonElement.bind(this);
this.handleCaret = this.handleCaret.bind(this);
this.caretEventHandler = this.caretEventHandler.bind(this);
this.onInit = this.onInit.bind(this);
this.onRender = this.onRender.bind(this);
this.render = this.render.bind(this);
this.loadModules = this.loadModules.bind(this);
this.handleButtonMouseUp = this.handleButtonMouseUp.bind(this);
this.handleButtonMouseDown = this.handleButtonMouseDown.bind(this);
this.handleButtonHold = this.handleButtonHold.bind(this);
this.onModulesLoaded = this.onModulesLoaded.bind(this);
/**
* simple-keyboard uses a non-persistent internal input to keep track of the entered string (the variable `keyboard.input`).
* This removes any dependency to input DOM elements. You can type and directly display the value in a div element, for example.
* @example
* // To get entered input
* let input = keyboard.getInput();
*
* // To clear entered input.
* keyboard.clearInput();
*
* @type {object}
* @property {object} default Default SimpleKeyboard internal input.
* @property {object} myInputName Example input that can be set through `options.inputName:"myInputName"`.
*/
this.input = {};
this.input[this.options.inputName] = '';
/**
* @type {string} DOM class of the keyboard wrapper, normally "simple-keyboard" by default.
*/
this.keyboardDOMClass = keyboardDOMQuery.split('.').join("");
/**
* @type {object} Contains the DOM elements of every rendered button, the key being the button's layout name (e.g.: "{enter}").
*/
this.buttonElements = {};
/**
* Rendering keyboard
*/
if(this.keyboardDOM)
this.render();
else
console.error(`"${keyboardDOMQuery}" was not found in the DOM.`);
else {
console.warn(`"${keyboardDOMQuery}" was not found in the DOM.`);
throw new Error("KEYBOARD_DOM_ERROR");
}
/**
* Saving instance
* This enables multiple simple-keyboard support with easier management
*/
if(!window['SimpleKeyboardInstances'])
window['SimpleKeyboardInstances'] = {};
window['SimpleKeyboardInstances'][this.utilities.camelCase(this.keyboardDOMClass)] = this;
/**
* Physical Keyboard support
*/
this.physicalKeyboardInterface = new PhysicalKeyboard(this);
/**
* Modules
*/
this.modules = {};
this.loadModules();
}
handleButtonClicked = (button) => {
/**
* Handles clicks made to keyboard buttons
* @param {string} button The button's layout name.
*/
handleButtonClicked(button){
let debug = this.options.debug;
/**
* Ignoring placeholder buttons
*/
@@ -47,25 +169,32 @@ class SimpleKeyboard {
*/
if(typeof this.options.onKeyPress === "function")
this.options.onKeyPress(button);
/**
* Updating input
*/
let options = {
newLineOnEnter: (this.options.newLineOnEnter === true)
}
if(!this.input[this.options.inputName])
this.input[this.options.inputName] = '';
let updatedInput = Utilities.getUpdatedInput(button, this.input[this.options.inputName], options);
let updatedInput = this.utilities.getUpdatedInput(button, this.input[this.options.inputName], this.options, this.caretPosition);
if(this.input[this.options.inputName] !== updatedInput){
/**
* If maxLength and handleMaxLength yield true, halting
*/
if(this.options.maxLength && this.utilities.handleMaxLength(this.input, this.options, updatedInput)){
return false;
}
this.input[this.options.inputName] = updatedInput;
if(debug)
console.log('Input changed:', this.input);
/**
* Enforce syncInstanceInputs, if set
*/
if(this.options.syncInstanceInputs)
this.syncInstanceInputs(this.input);
/**
* Calling onChange
*/
@@ -78,40 +207,418 @@ class SimpleKeyboard {
}
}
clearInput = (inputName) => {
inputName = inputName || this.options.inputName;
this.input[this.options.inputName] = '';
/**
* Handles button mousedown
*/
/* istanbul ignore next */
handleButtonMouseDown(button, e){
/**
* @type {boolean} Whether the mouse is being held onKeyPress
*/
this.isMouseHold = true;
if(this.holdInteractionTimeout)
clearTimeout(this.holdInteractionTimeout);
if(this.holdTimeout)
clearTimeout(this.holdTimeout);
/**
* @type {object} Time to wait until a key hold is detected
*/
this.holdTimeout = setTimeout(() => {
if(
this.isMouseHold &&
(
(!button.includes("{") && !button.includes("}")) ||
button === "{bksp}" ||
button === "{space}" ||
button === "{tab}"
)
){
if(this.options.debug)
console.log("Button held:", button);
this.handleButtonHold(button, e);
}
clearTimeout(this.holdTimeout);
}, 500);
}
getInput = (inputName) => {
/**
* Handles button mouseup
*/
handleButtonMouseUp(){
this.isMouseHold = false;
if(this.holdInteractionTimeout)
clearTimeout(this.holdInteractionTimeout);
}
/**
* Handles button hold
*/
/* istanbul ignore next */
handleButtonHold(button){
/**
* @type {object} Timeout dictating the speed of key hold iterations
*/
this.holdInteractionTimeout = setTimeout(() => {
this.handleButtonClicked(button);
this.handleButtonHold(button);
}, 100);
}
/**
* Send a command to all simple-keyboard instances (if you have several instances).
*/
syncInstanceInputs(){
this.dispatch((instance) => {
instance.replaceInput(this.input);
});
}
/**
* Clear the keyboards input.
* @param {string} [inputName] optional - the internal input to select
*/
clearInput(inputName){
inputName = inputName || this.options.inputName;
this.input[this.options.inputName] = '';
/**
* Enforce syncInstanceInputs, if set
*/
if(this.options.syncInstanceInputs)
this.syncInstanceInputs(this.input);
}
/**
* Get the keyboards input (You can also get it from the onChange prop).
* @param {string} [inputName] optional - the internal input to select
*/
getInput(inputName){
inputName = inputName || this.options.inputName;
/**
* Enforce syncInstanceInputs, if set
*/
if(this.options.syncInstanceInputs)
this.syncInstanceInputs(this.input);
return this.input[this.options.inputName];
}
setInput = (input, inputName) => {
/**
* Set the keyboards input.
* @param {string} input the input value
* @param {string} inputName optional - the internal input to select
*/
setInput(input, inputName){
inputName = inputName || this.options.inputName;
this.input[inputName] = input;
/**
* Enforce syncInstanceInputs, if set
*/
if(this.options.syncInstanceInputs)
this.syncInstanceInputs(this.input);
}
/**
* Replace the input object (`keyboard.input`)
* @param {object} inputObj The input object
*/
replaceInput(inputObj){
this.input = inputObj;
}
/**
* Set new option or modify existing ones after initialization.
* @param {object} option The option to set
*/
setOptions = option => {
option = option || {};
this.options = Object.assign(this.options, option);
this.render();
}
clear = () => {
/**
* Remove all keyboard rows and reset keyboard values.
* Used interally between re-renders.
*/
clear(){
this.keyboardDOM.innerHTML = '';
this.keyboardDOM.className = this.keyboardDOMClass;
this.buttonElements = {};
}
render = () => {
/**
* 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){
if(!window['SimpleKeyboardInstances']){
console.warn(`SimpleKeyboardInstances is not defined. Dispatch cannot be called.`);
throw new Error("INSTANCES_VAR_ERROR");
}
return Object.keys(window['SimpleKeyboardInstances']).forEach((key) => {
callback(window['SimpleKeyboardInstances'][key], key);
})
}
/**
* 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, className){
if(!className || !buttons)
return false;
buttons.split(" ").forEach(button => {
className.split(" ").forEach(classNameItem => {
if(!this.options.buttonTheme)
this.options.buttonTheme = [];
let classNameFound = false;
/**
* If class is already defined, we add button to class definition
*/
this.options.buttonTheme.map(buttonTheme => {
if(buttonTheme.class.split(" ").includes(classNameItem)){
classNameFound = true;
let buttonThemeArray = buttonTheme.buttons.split(" ");
if(!buttonThemeArray.includes(button)){
classNameFound = true;
buttonThemeArray.push(button);
buttonTheme.buttons = buttonThemeArray.join(" ");
}
}
return buttonTheme;
});
/**
* If class is not defined, we create a new entry
*/
if(!classNameFound){
this.options.buttonTheme.push({
class: classNameItem,
buttons: buttons
});
}
});
});
this.render();
}
/**
* 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, className){
/**
* When called with empty parameters, remove all button themes
*/
if(!buttons && !className){
this.options.buttonTheme = [];
this.render();
return false;
}
/**
* If buttons are passed and buttonTheme has items
*/
if(buttons && Array.isArray(this.options.buttonTheme) && this.options.buttonTheme.length){
let buttonArray = buttons.split(" ");
buttonArray.forEach((button, key) => {
this.options.buttonTheme.map((buttonTheme, index) => {
/**
* If className is set, we affect the buttons only for that class
* Otherwise, we afect all classes
*/
if(
(className && className.includes(buttonTheme.class)) ||
!className
){
let filteredButtonArray = buttonTheme.buttons.split(" ").filter(item => item !== button);
/**
* If buttons left, return them, otherwise, remove button Theme
*/
if(filteredButtonArray.length){
buttonTheme.buttons = filteredButtonArray.join(" ");
} else {
this.options.buttonTheme.splice(index, 1);
buttonTheme = null;
}
}
return buttonTheme;
});
});
this.render();
}
}
/**
* 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){
let output;
let buttonArr = this.buttonElements[button];
if(buttonArr){
if(buttonArr.length > 1){
output = buttonArr;
} else {
output = buttonArr[0];
}
}
return output;
}
/**
* Retrieves the current cursor position within a input or textarea (if any)
*/
handleCaret(){
if(this.options.debug){
console.log("Caret handling started");
}
document.addEventListener("keyup", this.caretEventHandler);
document.addEventListener("mouseup", this.caretEventHandler);
document.addEventListener("touchend", this.caretEventHandler);
}
/**
* Called by {@link handleCaret} when an event that warrants a cursor position update is triggered
*/
caretEventHandler(event){
let targetTagName = event.target.tagName.toLowerCase();
if(
targetTagName === "textarea" ||
targetTagName === "input"
){
/**
* Tracks current cursor position
* As keys are pressed, text will be added/removed at that position within the input.
*/
this.caretPosition = event.target.selectionStart;
if(this.options.debug){
console.log('Caret at: ', event.target.selectionStart, event.target.tagName.toLowerCase());
}
}
}
/**
* Executes the callback function once simple-keyboard is rendered for the first time (on initialization).
*/
onInit(){
if(this.options.debug){
console.log("Initialized");
}
/**
* Caret handling
*/
this.handleCaret();
if(typeof this.options.onInit === "function")
this.options.onInit();
}
/**
* Executes the callback function every time simple-keyboard is rendered (e.g: when you change layouts).
*/
onRender(){
if(typeof this.options.onRender === "function")
this.options.onRender();
}
/**
* Executes the callback function once all modules have been loaded
*/
onModulesLoaded(){
if(typeof this.options.onModulesLoaded === "function")
this.options.onModulesLoaded();
}
/**
* Register module
*/
registerModule = (name, initCallback) => {
if(!this.modules[name])
this.modules[name] = {};
initCallback(this.modules[name]);
}
/**
* Load modules
*/
loadModules(){
if(Array.isArray(this.options.modules)){
this.options.modules.forEach(Module => {
let module = new Module();
/* istanbul ignore next */
if(module.constructor.name && module.constructor.name !== "Function"){
let classStr = `module-${this.utilities.camelCase(module.constructor.name)}`;
this.keyboardPluginClasses = this.keyboardPluginClasses + ` ${classStr}`;
}
module.init(this);
});
this.keyboardPluginClasses = this.keyboardPluginClasses + ' modules-loaded';
this.render();
this.onModulesLoaded();
}
}
/**
* Get module prop
*/
getModuleProp = (name, prop) => {
if(!this.modules[name])
return false;
return this.modules[name][prop];
}
/**
* getModulesList
*/
getModulesList = () => {
return Object.keys(this.modules);
}
/**
* Renders rows and buttons as per options
*/
render(){
/**
* Clear keyboard
*/
this.clear();
let layoutClass = this.options.layout ? "hg-layout-custom" : `hg-layout-${this.options.layoutName}`;
let layout = this.options.layout || KeyboardLayout.getLayout(this.options.layoutName);
let layout = this.options.layout || KeyboardLayout.getDefaultLayout();
/**
* Account for buttonTheme, if set
@@ -120,17 +627,25 @@ class SimpleKeyboard {
if(Array.isArray(this.options.buttonTheme)){
this.options.buttonTheme.forEach(themeObj => {
if(themeObj.buttons && themeObj.class){
let themeButtons = themeObj.buttons.split(' ');
let themeButtons;
if(Array.isArray(themeButtons)){
if(typeof themeObj.buttons === "string"){
themeButtons = themeObj.buttons.split(' ');
}
if(themeButtons){
themeButtons.forEach(themeButton => {
let themeParsed = buttonThemesParsed[themeButton];
// If the button has already been added
if(themeParsed)
buttonThemesParsed[themeButton] = `${themeParsed} ${themeObj.class}`;
else
if(themeParsed){
// Making sure we don't add duplicate classes, even when buttonTheme has duplicates
if(!this.utilities.countInArray(themeParsed.split(" "), themeObj.class)){
buttonThemesParsed[themeButton] = `${themeParsed} ${themeObj.class}`;
}
} else {
buttonThemesParsed[themeButton] = themeObj.class;
}
});
}
} else {
@@ -142,12 +657,12 @@ class SimpleKeyboard {
/**
* Adding themeClass, layoutClass to keyboardDOM
*/
this.keyboardDOM.className += ` ${this.options.theme} ${layoutClass}`;
this.keyboardDOM.className += ` ${this.options.theme} ${layoutClass} ${this.keyboardPluginClasses}`;
/**
* Iterating through each row
*/
layout[this.options.layoutName].forEach((row) => {
layout[this.options.layoutName].forEach((row, rIndex) => {
let rowArray = row.split(' ');
/**
@@ -159,10 +674,10 @@ class SimpleKeyboard {
/**
* Iterating through each button in row
*/
rowArray.forEach((button) => {
let fctBtnClass = Utilities.getButtonClass(button);
rowArray.forEach((button, bIndex) => {
let fctBtnClass = this.utilities.getButtonClass(button);
let buttonThemeClass = buttonThemesParsed[button];
let buttonDisplayName = Utilities.getButtonDisplayName(button, this.options.display);
let buttonDisplayName = this.utilities.getButtonDisplayName(button, this.options.display, this.options.mergeDisplay);
/**
* Creating button
@@ -170,6 +685,24 @@ class SimpleKeyboard {
var buttonDOM = document.createElement('div');
buttonDOM.className += `hg-button ${fctBtnClass}${buttonThemeClass ? " "+buttonThemeClass : ""}`;
buttonDOM.onclick = () => this.handleButtonClicked(button);
buttonDOM.onmousedown = (e) => this.handleButtonMouseDown(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
*/
let buttonUID = `${this.options.layoutName}-r${rIndex}b${bIndex}`;
buttonDOM.setAttribute("data-skBtnUID", buttonUID);
/**
* Adding display label
*/
buttonDOM.setAttribute("data-displayLabel", buttonDisplayName);
/**
* Adding button label to button
@@ -178,17 +711,19 @@ class SimpleKeyboard {
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);
/**
* Calling onInit
*/
if(typeof this.options.onInit === "function")
this.options.onInit();
});
/**
@@ -196,6 +731,28 @@ class SimpleKeyboard {
*/
this.keyboardDOM.appendChild(rowDOM);
});
/**
* Calling onRender
*/
this.onRender();
if(!this.initialized){
/**
* Ensures that onInit is only called once per instantiation
*/
this.initialized = true;
/**
* Handling mouseup
*/
document.onmouseup = () => this.handleButtonMouseUp();
/**
* Calling onInit
*/
this.onInit();
}
}
}

View File

@@ -1,8 +0,0 @@
import React from 'react';
import ReactDOM from 'react-dom';
import Keyboard from './Keyboard';
it('Keyboard renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<Keyboard />, div);
});

View File

@@ -0,0 +1,864 @@
import Keyboard from '../Keyboard';
import TestUtility from '../../tests/TestUtility';
let testUtil = new TestUtility();
it('Keyboard will not render without target element', () => {
try {
new Keyboard();
expect(true).toBe(false);
} catch (e) {
expect(e.message).toBe("KEYBOARD_DOM_ERROR");
}
});
it('Keyboard will run without options', () => {
// Prepare target DOM element
testUtil.setDOM();
// No options
new Keyboard();
});
it('Keyboard will run with empty options', () => {
// Prepare target DOM element
testUtil.setDOM();
// No options
new Keyboard({});
});
it('Keyboard will run with custom DOM target', () => {
testUtil.setDOM("myTestDiv");
new Keyboard(".myTestDiv");
expect(document.body.querySelector(".myTestDiv")).toBeDefined();
});
it('Keyboard will run with debug option set', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
debug: true
});
expect(keyboard.options.debug).toBeTruthy();
});
it('Keyboard standard buttons will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
maxLength: {
"default": 10
}
});
testUtil.testLayoutStdButtons(keyboard);
});
it('Keyboard shift buttons will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
keyboard.setOptions({
layoutName: "shift",
maxLength: 42
});
testUtil.testLayoutStdButtons(keyboard);
});
it('Keyboard setOptions will work without a param', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
keyboard.setOptions();
});
it('Keyboard empty buttons wont do anything as expected', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
layout: {
default: [
"{//} {button} d",
"a b c d e f g h i j",
]
}
});
keyboard.getButtonElement("{//}").onclick();
});
it('Keyboard onKeyPress will work', () => {
testUtil.setDOM();
let pressed = false;
let keyboard = new Keyboard({
onKeyPress: () => {
pressed = true;
},
debug: true
});
keyboard.getButtonElement("q").onclick();
expect(pressed).toBeTruthy();
});
it('Keyboard standard function buttons will not change input', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
testUtil.iterateButtons((button) => {
if(button.getAttribute("data-skbtn") === "{shift}"){
button.onclick();
}
});
expect(keyboard.getInput()).toBeFalsy();
});
it('Keyboard syncInstanceInputs will work', () => {
testUtil.clear();
document.body.innerHTML = `
<div class="keyboard1"></div>
<div class="keyboard2"></div>
`;
let sharedOptions = {
syncInstanceInputs: true
};
let keyboard1 = new Keyboard(".keyboard1", sharedOptions);
let keyboard2 = new Keyboard(".keyboard2", sharedOptions);
keyboard1.getButtonElement("q").onclick();
expect(keyboard2.getInput()).toBe("q");
});
it('Keyboard onChange will work', () => {
testUtil.setDOM();
let output = false;
let keyboard = new Keyboard({
onChange: (input) => {
output = input;
}
});
keyboard.getButtonElement("q").onclick();
expect(output).toBe("q");
});
it('Keyboard clearInput will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
keyboard.input = {
"default": "hello"
};
keyboard.clearInput();
expect(keyboard.getInput()).toBeFalsy();
});
it('Keyboard clearInput will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
/**
* Avoid setInput for this test
*/
keyboard.input = {
"default": "hello"
};
keyboard.clearInput();
expect(keyboard.getInput()).toBeFalsy();
});
it('Keyboard clearInput will work with syncInstanceInputs', () => {
testUtil.clear();
document.body.innerHTML = `
<div class="keyboard1"></div>
<div class="keyboard2"></div>
`;
let sharedOptions = {
syncInstanceInputs: true
};
let keyboard1 = new Keyboard(".keyboard1", sharedOptions);
let keyboard2 = new Keyboard(".keyboard2", sharedOptions);
/**
* Avoid setInput for this test
*/
keyboard1.input = {
"default": "hello"
};
keyboard2.clearInput();
expect(keyboard1.getInput()).toBeFalsy();
});
it('Keyboard setInput will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
keyboard.setInput("hello");
expect(keyboard.getInput()).toBe("hello");
});
it('Keyboard setInput will work with syncInstanceInputs', () => {
testUtil.clear();
document.body.innerHTML = `
<div class="keyboard1"></div>
<div class="keyboard2"></div>
`;
let sharedOptions = {
syncInstanceInputs: true
};
let keyboard1 = new Keyboard(".keyboard1", sharedOptions);
let keyboard2 = new Keyboard(".keyboard2", sharedOptions);
keyboard1.setInput("hello");
expect(keyboard2.getInput()).toBe("hello");
});
it('Keyboard dispatch will work', () => {
testUtil.setDOM();
document.body.innerHTML = `
<div class="keyboard1"></div>
<div class="keyboard2"></div>
`;
let keyboard1 = new Keyboard(".keyboard1");
let keyboard2 = new Keyboard(".keyboard2");
keyboard1.dispatch(instance => {
instance.setOptions({
buttonTheme: [
{
class: "myCustomClass",
buttons: "Q"
}
]
})
});
expect(keyboard2.options.buttonTheme[0].class).toBe("myCustomClass");
});
it('Keyboard dispatch will not work without SimpleKeyboardInstances', () => {
testUtil.setDOM();
document.body.innerHTML = `
<div class="keyboard1"></div>
<div class="keyboard2"></div>
`;
let keyboard1 = new Keyboard(".keyboard1");
let keyboard2 = new Keyboard(".keyboard2");
window['SimpleKeyboardInstances'] = null;
try {
keyboard1.dispatch(instance => {
instance.setOptions({
buttonTheme: [
{
class: "myCustomClass",
buttons: "Q"
}
]
})
});
expect(true).toBe(false);
} catch (e) {
expect(e.message).toBe("INSTANCES_VAR_ERROR");
}
});
it('Keyboard addButtonTheme will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
let returnVal = keyboard.addButtonTheme("q", "test");
expect(keyboard.options.buttonTheme[0].class).toBe("test");
});
it('Keyboard addButtonTheme will not work without params', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
let returnVal = keyboard.addButtonTheme();
expect(returnVal).toBeFalsy();
});
it('Keyboard addButtonTheme will amend a buttonTheme', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
buttonTheme: [
{
class: "test",
buttons: "s"
}
]
});
keyboard.addButtonTheme("q", "test");
expect(keyboard.options.buttonTheme[0].class).toBe("test");
});
it('Keyboard addButtonTheme will create a buttonTheme', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
buttonTheme: [
{
class: "blurb",
buttons: "s"
}
]
});
keyboard.addButtonTheme("q", "test");
expect(keyboard.options.buttonTheme[1].class).toBe("test");
});
it('Keyboard addButtonTheme will ignore a repeated buttonTheme', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
buttonTheme: [
{
class: "test",
buttons: "s a"
}
]
});
keyboard.addButtonTheme("a", "test");
expect(keyboard.options.buttonTheme[0].buttons).toBe("s a");
});
it('Keyboard addButtonTheme will amend a buttonTheme', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
buttonTheme: [
{
class: "test",
buttons: "s"
}
]
});
keyboard.addButtonTheme("q", "test");
expect(keyboard.options.buttonTheme[0].buttons).toBe("s q");
});
it('Keyboard removeButtonTheme without params will remove all button themes', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
buttonTheme: [
{
class: "test",
buttons: "s"
}
]
});
keyboard.removeButtonTheme();
expect(keyboard.options.buttonTheme.length).toBe(0);
});
it('Keyboard removeButtonTheme will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
buttonTheme: [
{
class: "test",
buttons: "s"
}
]
});
keyboard.removeButtonTheme("s", "test");
expect(keyboard.options.buttonTheme.length).toBe(0);
});
it('Keyboard removeButtonTheme will work wihtout a class', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
buttonTheme: [
{
class: "test",
buttons: "s"
}
]
});
keyboard.removeButtonTheme("s");
expect(keyboard.options.buttonTheme.length).toBe(0);
});
it('Keyboard removeButtonTheme will do nothing without a button param', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
buttonTheme: [
{
class: "test",
buttons: "s"
}
]
});
keyboard.removeButtonTheme(null, "test");
expect(keyboard.options.buttonTheme.length).toBe(1);
});
it('Keyboard removeButtonTheme does nothing if req button doesnt have a buttonTheme', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
buttonTheme: [
{
class: "test",
buttons: "a"
}
]
});
keyboard.removeButtonTheme("s", "test");
expect(keyboard.options.buttonTheme.length).toBe(1);
});
it('Keyboard removeButtonTheme does nothing if buttonTheme class does not exist', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
buttonTheme: [
{
class: "testy",
buttons: "a"
}
]
});
keyboard.removeButtonTheme("a", "test");
expect(keyboard.options.buttonTheme.length).toBe(1);
});
it('Keyboard removeButtonTheme does nothing if buttonTheme doesnt have the requested buttons', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
buttonTheme: [
{
class: "test",
buttons: "a b c d e f"
}
]
});
keyboard.removeButtonTheme("g", "test");
expect(keyboard.options.buttonTheme[0].buttons).toBe("a b c d e f");
});
it('Keyboard getButtonElement will not return anything if empty match', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
layout: {
default: [
"{//} {button} d",
"a b c d e f g h i j",
]
}
});
expect(keyboard.getButtonElement("{waldo}")).toBeFalsy();
});
it('Keyboard getButtonElement will return multiple matched buttons', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
expect(keyboard.getButtonElement("{shift}").length).toBe(2);
});
it('Keyboard will receive physical keyboard events', () => {
testUtil.setDOM();
new Keyboard({
debug: true,
physicalKeyboardHighlight: true
});
document.dispatchEvent(new KeyboardEvent('keyup', {
charCode: 0,
code: "KeyF",
key: "f",
which: 70,
target: {
tagName: "input"
}
}));
});
it('Keyboard caretEventHandler will detect input, textarea focus', () => {
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);
});
it('Keyboard caretEventHandler ignore positioning if input, textarea is blur', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
keyboard.caretEventHandler({
charCode: 0,
code: "KeyF",
key: "f",
which: 70,
target: {
tagName: "div",
selectionStart: 4
}
});
expect(keyboard.caretPosition).toBeFalsy();
});
it('Keyboard caretEventHandler will work with debug', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
debug: true
});
keyboard.caretEventHandler({
charCode: 0,
code: "KeyF",
key: "f",
which: 70,
target: {
tagName: "input",
selectionStart: 3
}
});
expect(keyboard.caretPosition).toBe(3);
});
it('Keyboard onInit will work', () => {
testUtil.setDOM();
let passed = false;
let keyboard = new Keyboard({
onInit: () => {
passed = true
}
});
expect(passed).toBeTruthy();
});
it('Keyboard onRender will work', () => {
testUtil.setDOM();
let passed = false;
let keyboard = new Keyboard({
onRender: () => {
passed = true
}
});
expect(passed).toBeTruthy();
});
it('Keyboard buttonTheme that is invalid will be ignored and not throw', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
buttonTheme: [
{
class: null,
buttons: null
}
]
});
});
it('Keyboard buttonTheme buttons that are invalid will be ignored and not throw', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
buttonTheme: [
{
class: null,
buttons: undefined
}
]
});
});
it('Keyboard buttonTheme will be ignored if buttons param not a string', () => {
testUtil.setDOM();
new Keyboard({
buttonTheme: [
{
class: "test",
buttons: {
wrong: true
}
}
]
});
});
it('Keyboard buttonTheme will be ignored if already added', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
buttonTheme: [
{
class: "test",
buttons: "a b c"
},
{
class: "test",
buttons: "c"
},
{
class: "anotherclass",
buttons: "c"
},
{
class: "yetAnotherclass",
buttons: "c"
},
{
class: "anotherclass",
buttons: "c"
},
]
});
});
it('Keyboard can set a module', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
keyboard.registerModule(
"test",
(module) => {
module.foo = "bar";
}
);
expect(keyboard.getModuleProp("test", "foo")).toBe("bar");
});
it('Keyboard registerModule will return current module tree', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
keyboard.modules.test = {
testy: "test"
};
keyboard.registerModule(
"test",
(module) => {
module.foo = "bar";
}
);
expect(keyboard.getModuleProp("test", "testy")).toBe("test");
expect(keyboard.getModuleProp("test", "foo")).toBe("bar");
});
it('Keyboard can set a module by amending the modules tree', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
keyboard.modules = {
testman: {
foo: "baz"
}
};
keyboard.registerModule(
"test",
(module) => {
module.foo = "bar";
}
);
expect(keyboard.getModuleProp("test", "foo")).toBe("bar");
});
it('Keyboard will not retrieve an option for an inexistent module', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
expect(keyboard.getModuleProp("test", "foo")).toBeFalsy();
});
it('Keyboard will get a list of modules', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
keyboard.registerModule(
"test",
(module) => {
module.foo = "bar";
}
);
expect(keyboard.getModulesList()[0]).toBe("test");
});
it('Keyboard loadModules will load a simple module', () => {
testUtil.setDOM();
class myClass {
init = (module) => {
module.foo = "bar";
};
}
let keyboard = new Keyboard({
modules: [
myClass
]
});
});
it('Keyboard handleButtonMouseUp will set isMouseHold to false', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
keyboard.isMouseHold = true;
document.onmouseup();
expect(keyboard.isMouseHold).toBeFalsy();
});
it('Keyboard handleButtonMouseUp clear holdInteractionTimeout', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
keyboard.isMouseHold = true;
keyboard.holdInteractionTimeout = setTimeout(() => {}, 10000);
document.onmouseup();
});
it('Keyboard handleButtonMouseDown will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
keyboard.handleButtonMouseDown("q", {
target: keyboard.getButtonElement("q")
});
keyboard.getButtonElement("q").onmousedown();
document.onmouseup();
});
it('Keyboard onModulesLoaded will work', () => {
testUtil.setDOM();
class myClass {
init = (module) => {
module.foo = "bar";
};
}
let foo;
let keyboard = new Keyboard({
modules: [
myClass
],
onModulesLoaded: () => {
foo = "bar";
}
});
expect(foo).toBe("bar");
});

View File

@@ -1,37 +1,29 @@
/**
* Keyboard Layout Service
*/
class KeyboardLayout {
static getLayout = layout => {
if(layout === "qwerty"){
return {
'default': [
'` 1 2 3 4 5 6 7 8 9 0 - = {bksp}',
'{tab} q w e r t y u i o p [ ] \\',
'{lock} a s d f g h j k l ; \' {enter}',
'{shift} z x c v b n m , . / {shift}',
'.com @ {space}'
],
'shift': [
'~ ! @ # $ % ^ & * ( ) _ + {bksp}',
'{tab} Q W E R T Y U I O P { } |',
'{lock} A S D F G H J K L : " {enter}',
'{shift} Z X C V B N M < > ? {shift}',
'.com @ {space}'
]
};
} else if(layout === "numeric"){
return {
'default': [
'1 2 3',
'4 5 6',
'7 8 9',
'{//} 0 {bksp}'
]
};
} else {
return KeyboardLayout.getLayout("qwerty");
}
/**
* Get default simple-keyboard layout
* @return {object} The default layout (US-QWERTY)
*/
static getDefaultLayout(){
return {
'default': [
'` 1 2 3 4 5 6 7 8 9 0 - = {bksp}',
'{tab} q w e r t y u i o p [ ] \\',
'{lock} a s d f g h j k l ; \' {enter}',
'{shift} z x c v b n m , . / {shift}',
'.com @ {space}'
],
'shift': [
'~ ! @ # $ % ^ & * ( ) _ + {bksp}',
'{tab} Q W E R T Y U I O P { } |',
'{lock} A S D F G H J K L : " {enter}',
'{shift} Z X C V B N M < > ? {shift}',
'.com @ {space}'
]
}
}
}
export default KeyboardLayout;

View File

@@ -0,0 +1,97 @@
/**
* Physical Keyboard Service
*/
class PhysicalKeyboard {
/**
* Creates an instance of the PhysicalKeyboard service
*/
constructor(simpleKeyboardInstance){
/**
* @type {object} A simple-keyboard instance
*/
this.simpleKeyboardInstance = simpleKeyboardInstance;
/**
* Bindings
*/
this.initKeyboardListener = this.initKeyboardListener.bind(this);
this.getSimpleKeyboardLayoutKey = this.getSimpleKeyboardLayoutKey.bind(this);
/**
* Initialize key listeners
*/
this.initKeyboardListener();
}
/**
* Initializes key event listeners
*/
initKeyboardListener(){
// Adding button style on keydown
document.addEventListener("keydown", (event) => {
if(this.simpleKeyboardInstance.options.physicalKeyboardHighlight){
let buttonPressed = this.getSimpleKeyboardLayoutKey(event);
this.simpleKeyboardInstance.dispatch(instance => {
let buttonDOM = instance.getButtonElement(buttonPressed) || instance.getButtonElement(`{${buttonPressed}}`);
if(buttonDOM){
buttonDOM.style.backgroundColor = this.simpleKeyboardInstance.options.physicalKeyboardHighlightBgColor || "#9ab4d0";
buttonDOM.style.color = this.simpleKeyboardInstance.options.physicalKeyboardHighlightTextColor || "white";
}
});
}
});
// Removing button style on keyup
document.addEventListener("keyup", (event) => {
if(this.simpleKeyboardInstance.options.physicalKeyboardHighlight){
let buttonPressed = this.getSimpleKeyboardLayoutKey(event);
this.simpleKeyboardInstance.dispatch(instance => {
let buttonDOM = instance.getButtonElement(buttonPressed) || instance.getButtonElement(`{${buttonPressed}}`);
if(buttonDOM){
buttonDOM.removeAttribute("style");
}
});
}
});
}
/**
* Transforms a KeyboardEvent's "key.code" string into a simple-keyboard layout format
* @param {object} event The KeyboardEvent
*/
getSimpleKeyboardLayoutKey(event){
let output;
if(
event.code.includes("Numpad") ||
event.code.includes("Shift") ||
event.code.includes("Space") ||
event.code.includes("Backspace") ||
event.code.includes("Control") ||
event.code.includes("Alt") ||
event.code.includes("Meta")
){
output = event.code;
} else {
output = event.key;
}
/**
* If button is not uppercase, casting to lowercase
*/
if (
output !== output.toUpperCase() ||
(event.code[0] === "F" && Number.isInteger(Number(event.code[1])) && event.code.length <= 3)
) {
output = output.toLowerCase();
}
return output;
}
}
export default PhysicalKeyboard;

View File

@@ -1,92 +1,353 @@
/**
* Utility Service
*/
class Utilities {
static normalizeString(string){
let output;
/**
* Creates an instance of the Utility service
*/
constructor(simpleKeyboardInstance){
/**
* @type {object} A simple-keyboard instance
*/
this.simpleKeyboardInstance = simpleKeyboardInstance;
if(string === "@")
output = 'at';
else if(string === ",")
output = 'comma';
else if(string === ".")
output = 'dot';
else if(string === "\\")
output = 'backslash';
else if(string === "/")
output = 'fordardslash';
else if(string === "*")
output = 'asterisk';
else if(string === "&")
output = 'ampersand';
else if(string === "$")
output = 'dollarsign';
else if(string === "=")
output = 'equals';
else if(string === "+")
output = 'plus';
else if(string === "-")
output = 'minus';
else if(string === "'")
output = 'apostrophe';
else if(string === ";")
output = 'colon';
else if(string === "[")
output = 'openbracket';
else if(string === "]")
output = 'closebracket';
else if(string === "//")
output = 'emptybutton';
else
output = '';
return output ? ` hg-button-${output}` : '';
/**
* Bindings
*/
this.getButtonClass = this.getButtonClass.bind(this);
this.getButtonDisplayName = this.getButtonDisplayName.bind(this);
this.getUpdatedInput = this.getUpdatedInput.bind(this);
this.updateCaretPos = this.updateCaretPos.bind(this);
this.isMaxLengthReached = this.isMaxLengthReached.bind(this);
this.camelCase = this.camelCase.bind(this);
this.countInArray = this.countInArray.bind(this);
}
static getButtonClass = button => {
let buttonTypeClass = (button.includes("{") && button !== '{//}') ? "functionBtn" : "standardBtn";
/**
* Adds default classes to a given button
*
* @param {string} button The button's layout name
* @return {string} The classes to be added to the button
*/
getButtonClass(button){
let buttonTypeClass = (button.includes("{") && button.includes("}") && button !== '{//}') ? "functionBtn" : "standardBtn";
let buttonWithoutBraces = button.replace("{", "").replace("}", "");
let buttonNormalized = '';
let buttonNormalized =
buttonTypeClass === "standardBtn" ?
Utilities.normalizeString(buttonWithoutBraces) : ` hg-button-${buttonWithoutBraces}`;
if(buttonTypeClass !== "standardBtn")
buttonNormalized = ` hg-button-${buttonWithoutBraces}`;
return `hg-${buttonTypeClass}${buttonNormalized}`;
}
static getDefaultDiplay(){
/**
* Default button display labels
*/
getDefaultDiplay(){
return {
'{bksp}': 'backspace',
'{backspace}': 'backspace',
'{enter}': '< enter',
'{shift}': 'shift',
'{shiftleft}': 'shift',
'{shiftright}': 'shift',
'{alt}': 'alt',
'{s}': 'shift',
'{tab}': 'tab',
'{lock}': 'caps',
'{capslock}': 'caps',
'{accept}': 'Submit',
'{space}': ' ',
'{//}': ' '
'{//}': ' ',
"{esc}": "esc",
"{escape}": "esc",
"{f1}": "f1",
"{f2}": "f2",
"{f3}": "f3",
"{f4}": "f4",
"{f5}": "f5",
"{f6}": "f6",
"{f7}": "f7",
"{f8}": "f8",
"{f9}": "f9",
"{f10}": "f10",
"{f11}": "f11",
"{f12}": "f12",
'{numpaddivide}': '/',
'{numlock}': 'lock',
"{arrowup}": "↑",
"{arrowleft}": "←",
"{arrowdown}": "↓",
"{arrowright}": "→",
"{prtscr}": "print",
"{scrolllock}": "scroll",
"{pause}": "pause",
"{insert}": "ins",
"{home}": "home",
"{pageup}": "up",
"{delete}": "del",
"{end}": "end",
"{pagedown}": "down",
"{numpadmultiply}": "*",
"{numpadsubtract}": "-",
"{numpadadd}": "+",
"{numpadenter}": "enter",
"{period}": ".",
"{numpaddecimal}": ".",
"{numpad0}": "0",
"{numpad1}": "1",
"{numpad2}": "2",
"{numpad3}": "3",
"{numpad4}": "4",
"{numpad5}": "5",
"{numpad6}": "6",
"{numpad7}": "7",
"{numpad8}": "8",
"{numpad9}": "9",
};
}
/**
* Returns the display (label) name for a given button
*
* @param {string} button The button's layout name
* @param {object} display The provided display option
* @param {boolean} mergeDisplay Whether the provided param value should be merged with the default one.
*/
getButtonDisplayName(button, display, mergeDisplay){
if(mergeDisplay){
display = Object.assign({}, this.getDefaultDiplay(), display);
} else {
display = display || this.getDefaultDiplay();
}
static getButtonDisplayName = (button, display) => {
display = display || Utilities.getDefaultDiplay();
return display[button] || button;
}
static getUpdatedInput = (button, input, options) => {
/**
* Returns the updated input resulting from clicking a given button
*
* @param {string} button The button's layout name
* @param {string} input The input string
* @param {object} options The simple-keyboard options object
* @param {number} caretPos The cursor's current position
*/
getUpdatedInput(button, input, options, caretPos){
let output = input;
let newLineOnEnter = options.newLineOnEnter;
if(button === "{bksp}" && output.length > 0)
output = output.slice(0, -1);
else if(button === "{space}")
output = output + ' ';
else if(button === "{tab}")
output = output + "\t";
else if(button === "{enter}" && newLineOnEnter)
output = output + "\n";
if((button === "{bksp}" || button === "{backspace}") && output.length > 0){
output = this.removeAt(output, caretPos);
} else if(button === "{space}")
output = this.addStringAt(output, " ", caretPos);
else if(button === "{tab}" && !(typeof options.tabCharOnTab === "boolean" && options.tabCharOnTab === false)){
output = this.addStringAt(output, "\t", caretPos);
} else if((button === "{enter}" || button === "{numpadenter}") && options.newLineOnEnter)
output = this.addStringAt(output, "\n", caretPos);
else if(button.includes("numpad") && Number.isInteger(Number(button[button.length - 2]))){
output = this.addStringAt(output, button[button.length - 2], caretPos);
}
else if(button === "{numpaddivide}")
output = this.addStringAt(output, '/', caretPos);
else if(button === "{numpadmultiply}")
output = this.addStringAt(output, '*', caretPos);
else if(button === "{numpadsubtract}")
output = this.addStringAt(output, '-', caretPos);
else if(button === "{numpadadd}")
output = this.addStringAt(output, '+', caretPos);
else if(button === "{numpaddecimal}")
output = this.addStringAt(output, '.', caretPos);
else if(button === "{" || button === "}")
output = this.addStringAt(output, button, caretPos);
else if(!button.includes("{") && !button.includes("}"))
output = output + button;
output = this.addStringAt(output, button, caretPos);
return output;
}
/**
* Moves the cursor position by a given amount
*
* @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.
*/
updateCaretPos(length, minus){
if(minus){
if(this.simpleKeyboardInstance.caretPosition > 0)
this.simpleKeyboardInstance.caretPosition = this.simpleKeyboardInstance.caretPosition - length
} else {
this.simpleKeyboardInstance.caretPosition = this.simpleKeyboardInstance.caretPosition + length;
}
}
/**
* Adds a string to the input at a given position
*
* @param {string} source The source input
* @param {string} string The string to add
* @param {number} position The (cursor) position where the string should be added
*/
addStringAt(source, string, position){
let output;
if(this.simpleKeyboardInstance.options.debug){
console.log("Caret at:", position);
}
if(!position && position !== 0){
output = source + string;
} else {
output = [source.slice(0, position), string, source.slice(position)].join('');
/**
* Avoid caret position change when maxLength is set
*/
if(!this.isMaxLengthReached()){
this.updateCaretPos(string.length);
}
}
return output;
}
/**
* Removes an amount of characters at a given position
*
* @param {string} source The source input
* @param {number} position The (cursor) position from where the characters should be removed
*/
removeAt(source, position){
if(this.simpleKeyboardInstance.caretPosition === 0){
return source;
}
let output;
let prevTwoChars;
let emojiMatched;
let 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){
prevTwoChars = source.substring(position - 2, position)
emojiMatched = prevTwoChars.match(emojiMatchedReg);
if(emojiMatched){
output = source.substr(0, (position - 2)) + source.substr(position);
this.updateCaretPos(2, true);
} else {
output = source.substr(0, (position - 1)) + source.substr(position);
this.updateCaretPos(1, true);
}
} else {
prevTwoChars = source.slice(-2);
emojiMatched = prevTwoChars.match(emojiMatchedReg);
if(emojiMatched){
output = source.slice(0, -2);
this.updateCaretPos(2, true);
} else {
output = source.slice(0, -1);
this.updateCaretPos(1, true);
}
}
return output;
}
/**
* Determines whether the maxLength has been reached. This function is called when the maxLength option it set.
*
* @param {object} inputObj
* @param {object} options
* @param {string} updatedInput
*/
handleMaxLength(inputObj, options, updatedInput){
let maxLength = options.maxLength;
let currentInput = inputObj[options.inputName];
let condition = currentInput.length === maxLength;
if(
/**
* If pressing this button won't add more characters
* We exit out of this limiter function
*/
updatedInput.length <= currentInput.length
){
return false;
}
if(Number.isInteger(maxLength)){
if(options.debug){
console.log("maxLength (num) reached:", condition);
}
if(condition){
/**
* @type {boolean} Boolean value that shows whether maxLength has been reached
*/
this.maxLengthReached = true;
return true;
} else {
this.maxLengthReached = false;
return false;
}
}
if(typeof maxLength === "object"){
let condition = currentInput.length === maxLength[options.inputName];
if(options.debug){
console.log("maxLength (obj) reached:", condition);
}
if(condition){
this.maxLengthReached = true;
return true;
} else {
this.maxLengthReached = false;
return false;
}
}
}
/**
* Gets the current value of maxLengthReached
*/
isMaxLengthReached(){
return Boolean(this.maxLengthReached);
}
/**
* Transforms an arbitrary string to camelCase
*
* @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));
};
/**
* Counts the number of duplicates in a given array
*
* @param {Array} array The haystack to search in
* @param {string} value The needle to search for
*/
countInArray(array, value){
return array.reduce((n, x) => n + (x === value), 0);
}
}
export default Utilities;

View File

@@ -0,0 +1,118 @@
import Keyboard from '../../components/Keyboard';
import TestUtility from '../../tests/TestUtility';
let testUtil = new TestUtility();
it('PhysicalKeyboard keydown will be handled with physicalKeyboardHighlight', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
physicalKeyboardHighlight: true
});
document.dispatchEvent(new KeyboardEvent('keydown', {
code: "KeyF",
key: "f",
target: {
tagName: "input"
}
}));
});
it('PhysicalKeyboard keydown will be handled without physicalKeyboardHighlight', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
physicalKeyboardHighlight: false
});
document.dispatchEvent(new KeyboardEvent('keydown', {
code: "KeyF",
key: "f",
target: {
tagName: "input"
}
}));
});
it('PhysicalKeyboard keydown will not style non-existent buttons', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
physicalKeyboardHighlight: true
});
document.dispatchEvent(new KeyboardEvent('keydown', {
code: "WRONG",
key: "WRONG",
target: {
tagName: "input"
}
}));
});
it('PhysicalKeyboard keyup will be handled with physicalKeyboardHighlight', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
physicalKeyboardHighlight: true
});
document.dispatchEvent(new KeyboardEvent('keyup', {
code: "KeyF",
key: "f",
target: {
tagName: "input"
}
}));
});
it('PhysicalKeyboard keyup will be handle special buttons', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
physicalKeyboardHighlight: true
});
document.dispatchEvent(new KeyboardEvent('keyup', {
code: "Shift",
key: "Shift",
target: {
tagName: "input"
}
}));
});
it('PhysicalKeyboard keyup will not style non-existent buttons', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
physicalKeyboardHighlight: true,
debug: true
});
document.dispatchEvent(new KeyboardEvent('keyup', {
code: "WRONG",
key: "WRONG",
target: {
tagName: "input"
}
}));
});
it('PhysicalKeyboard will work with F1-F12 keys', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
physicalKeyboardHighlight: true,
debug: true
});
document.dispatchEvent(new KeyboardEvent('keyup', {
code: "F12",
key: "F12",
target: {
tagName: "input"
}
}));
});

View File

@@ -0,0 +1,456 @@
import Keyboard from '../../components/Keyboard';
import TestUtility from '../../tests/TestUtility';
let testUtil = new TestUtility();
it('Keyboard mergeDisplay will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
mergeDisplay: true,
display: {
"q": "qreplaced"
}
});
expect(keyboard.getButtonElement("q").getAttribute("data-displaylabel")).toBe("qreplaced");
});
it('Keyboard function buttons will work', () => {
testUtil.setDOM();
new Keyboard();
testUtil.testLayoutFctButtons((fctBtnCount, fctBtnHasOnclickCount) => {
expect(fctBtnCount).toBe(fctBtnHasOnclickCount);
});
});
it('Keyboard {bksp} button will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
let output = keyboard.utilities.getUpdatedInput("{bksp}", "test", keyboard.options);
expect(output).toBe("tes");
});
it('Keyboard {space} button will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
let output = keyboard.utilities.getUpdatedInput("{space}", "test", keyboard.options);
expect(output).toBe("test ");
});
it('Keyboard {tab} button will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
let output = keyboard.utilities.getUpdatedInput("{tab}", "test", keyboard.options);
expect(output).toBe("test\t");
});
it('Keyboard {tab} button will work with tabCharOnTab:false', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
tabCharOnTab: false
});
let output = keyboard.utilities.getUpdatedInput("{tab}", "test", keyboard.options);
expect(output).toBe("test");
});
it('Keyboard {enter} button will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
let output = keyboard.utilities.getUpdatedInput("{enter}", "test", keyboard.options);
expect(output).toBe("test");
});
it('Keyboard {enter} button will work with newLineOnEnter:true', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
newLineOnEnter: true
});
let output = keyboard.utilities.getUpdatedInput("{enter}", "test", keyboard.options);
expect(output).toBe("test\n");
});
it('Keyboard {numpadX} buttons will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
for(let i = 0;i<=9;i++){
let output = keyboard.utilities.getUpdatedInput(`{numpad${i}}`, "test", keyboard.options);
expect(output).toBe(`test${i}`);
}
});
it('Keyboard {numpaddivide} button will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
let output = keyboard.utilities.getUpdatedInput("{numpaddivide}", "test", keyboard.options);
expect(output).toBe("test/");
});
it('Keyboard {numpadmultiply} button will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
let output = keyboard.utilities.getUpdatedInput("{numpadmultiply}", "test", keyboard.options);
expect(output).toBe("test*");
});
it('Keyboard {numpadsubtract} button will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
let output = keyboard.utilities.getUpdatedInput("{numpadsubtract}", "test", keyboard.options);
expect(output).toBe("test-");
});
it('Keyboard {numpadadd} button will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
let output = keyboard.utilities.getUpdatedInput("{numpadadd}", "test", keyboard.options);
expect(output).toBe("test+");
});
it('Keyboard {numpadadd} button will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
let output = keyboard.utilities.getUpdatedInput("{numpadadd}", "test", keyboard.options);
expect(output).toBe("test+");
});
it('Keyboard {numpaddecimal} button will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
let output = keyboard.utilities.getUpdatedInput("{numpaddecimal}", "test", keyboard.options);
expect(output).toBe("test.");
});
it('Keyboard custom function buttons will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
layout: {
default: [
"{randombuttontest}"
]
}
});
let output = keyboard.utilities.getUpdatedInput("{randombuttontest}", "test", keyboard.options);
expect(output).toBe("test");
expect(keyboard.getButtonElement("{randombuttontest}").onclick).toBeTruthy();
});
it('Keyboard "{" button will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
let output = keyboard.utilities.getUpdatedInput("{", "test", keyboard.options);
expect(output).toBe("test{");
});
it('Keyboard "}" button will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
let output = keyboard.utilities.getUpdatedInput("}", "test", keyboard.options);
expect(output).toBe("test}");
});
it('Keyboard standard button will affect input', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
for (let i = 65; i <= 90; i++) {
let char = String.fromCharCode(i);
let output = keyboard.utilities.getUpdatedInput(char, "test", keyboard.options);
expect(output).toBe(`test${char}`);
}
});
it('Keyboard updateCaretPos will work with minus', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
keyboard.caretPosition = 5;
keyboard.utilities.updateCaretPos(2, true);
expect(keyboard.caretPosition).toBe(3);
});
it('Keyboard updateCaretPos will work with plus', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
keyboard.caretPosition = 5;
keyboard.utilities.updateCaretPos(2);
expect(keyboard.caretPosition).toBe(7);
});
it('Keyboard addStringAt will work with debug', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
debug: true
});
keyboard.getButtonElement("q").onclick();
expect(keyboard.getInput()).toBe("q");
});
it('Keyboard addStringAt will work with position', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
debug: true
});
keyboard.setInput("test");
keyboard.caretPosition = 4;
keyboard.getButtonElement("q").onclick();
expect(keyboard.getInput()).toBe("testq");
});
it('Keyboard addStringAt will respect maxLength', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
debug: true,
maxLength: 4
});
keyboard.setInput("test");
keyboard.caretPosition = 4;
keyboard.utilities.handleMaxLength(keyboard.input, keyboard.options, "testq")
keyboard.utilities.addStringAt("test", "q", 4);
expect(keyboard.caretPosition).toBe(4);
});
it('Keyboard handleMaxLength will exit out on same updatedInput', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
debug: true
});
keyboard.setInput("test");
let output = keyboard.utilities.handleMaxLength(keyboard.input, keyboard.options, "test")
expect(output).toBeFalsy();
});
it('Keyboard handleMaxLength will work with object maxLength', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
maxLength: {
default: 4
}
});
keyboard.setInput("test");
let output = keyboard.utilities.handleMaxLength(keyboard.input, keyboard.options, "testq");
expect(output).toBeTruthy();
});
it('Keyboard handleMaxLength will work with object maxLength and debug', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
maxLength: {
default: 4
},
debug: true
});
keyboard.setInput("test");
let output = keyboard.utilities.handleMaxLength(keyboard.input, keyboard.options, "testq");
expect(output).toBeTruthy();
});
it('Keyboard handleMaxLength will return false if obj maxLength not reached', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
maxLength: {
default: 7
}
});
keyboard.setInput("test");
let output = keyboard.utilities.handleMaxLength(keyboard.input, keyboard.options, "testq");
expect(output).toBeFalsy();
});
it('Keyboard handleMaxLength will work without debug', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
maxLength: 4
});
keyboard.setInput("test");
let output = keyboard.utilities.handleMaxLength(keyboard.input, keyboard.options, "testq");
expect(output).toBeTruthy();
});
it('Keyboard handleMaxLength will work with numeric maxLength', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
maxLength: 3
});
keyboard.setInput("test");
let output = keyboard.utilities.handleMaxLength(keyboard.input, keyboard.options, "testq");
expect(output).toBeFalsy();
});
it('Keyboard handleMaxLength wont work with non numeric or object maxLength', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
maxLength: "wrong"
});
keyboard.setInput("test");
let output = keyboard.utilities.handleMaxLength(keyboard.input, keyboard.options, "testq");
expect(output).toBeFalsy();
});
it('Keyboard handleMaxLength wont work with non numeric or object maxLength (with debug)', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
maxLength: "wrong",
debug: true
});
keyboard.setInput("test");
let output = keyboard.utilities.handleMaxLength(keyboard.input, keyboard.options, "testq");
expect(output).toBeFalsy();
});
it('Keyboard isMaxLengthReached will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
maxLength: 5
});
let output = keyboard.utilities.isMaxLengthReached();
expect(output).toBeFalsy();
});
it('Keyboard removeAt will exit out on caretPosition:0', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
keyboard.setInput("test");
keyboard.caretPosition = 0;
keyboard.utilities.removeAt(keyboard.getInput(), 0);
expect(keyboard.getInput()).toBe("test");
});
it('Keyboard removeAt will remove multi-byte unicodes with caretPos>0', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
keyboard.caretPosition = 6;
let output = keyboard.utilities.removeAt("test\uD83D\uDE00", 6);
expect(output).toBe("test");
});
it('Keyboard removeAt will not remove multi-byte unicodes with caretPos:0', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
let output = keyboard.utilities.removeAt("\uD83D\uDE00");
expect(output).toBeFalsy();
});
it('Keyboard removeAt will remove regular strings', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
keyboard.caretPosition = 6;
let output = keyboard.utilities.removeAt("testie", 6);
expect(output).toBe("testi");
});

View File

@@ -0,0 +1,107 @@
/**
* Test Utility Functions
*/
export default class TestUtility {
/**
* Set's a basic DOM structure to test in
*/
setDOM = (divClass) => {
this.clear();
const div = document.createElement('div');
div.className += divClass || "simple-keyboard";
document.body.appendChild(div);
}
/**
* Clears DOM structure
*/
clear = () => {
document.body.innerHTML = "";
}
/**
* Test if standard buttons respect maxLength and do input a value
*/
testLayoutStdButtons = (keyboard) => {
let stdBtnCount = 0;
let fullInput = '';
this.iterateButtons((button) => {
let label = button.getAttribute("data-skbtn");
if(label.includes("{"))
return false;
// Click all standard buttons, respects maxLength
button.onclick();
// Recording fullInput, bypasses maxLength
fullInput = keyboard.utilities.getUpdatedInput(label, fullInput, keyboard.options, null);
stdBtnCount += label.length;
});
/**
* Check if maxLength is respected
*/
if(
(
typeof keyboard.options.maxLength === "object" &&
keyboard.getInput().length !== keyboard.options.maxLength[keyboard.options.layoutName]
) ||
(
typeof keyboard.options.maxLength !== "object" &&
keyboard.getInput().length !== keyboard.options.maxLength
)
)
throw new Error("MAX_LENGTH_ISSUE");
else
console.log("MAX_LENGTH PASSED:", keyboard.options.layoutName, keyboard.getInput().length, keyboard.options.maxLength);
/**
* Check if all standard buttons are inputting something
* (Regardless of maxLength)
*/
if(stdBtnCount !== fullInput.length)
throw new Error("STANDARD_BUTTONS_ISSUE");
else
console.log("STANDARD_BUTTONS PASSED:", keyboard.options.layoutName, stdBtnCount, fullInput.length);
}
/**
* Test if function buttons are interactive (have an onclick)
*/
testLayoutFctButtons = (callback) => {
let fctBtnCount = 0;
let fctBtnHasOnclickCount = 0;
this.iterateButtons((button) => {
let label = button.getAttribute("data-skbtn");
if(!label.includes("{") && !label.includes("}"))
return false;
fctBtnCount++;
if(button.onclick){
button.onclick();
fctBtnHasOnclickCount++;
}
callback(fctBtnCount, fctBtnHasOnclickCount);
});
}
/**
* Iterates on the keyboard buttons
*/
iterateButtons = (callback, selector) => {
let rows = document.body.querySelector(selector || '.simple-keyboard').children;
Array.from(rows).forEach(row => {
Array.from(row.children).forEach((button) => {
callback(button);
});
});
}
}