Compare commits
275 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
effee00b87 | ||
|
|
90b408eff6 | ||
|
|
21fa732b1f | ||
|
|
80f4307c36 | ||
|
|
681bb3d0ee | ||
|
|
e1fa685c6c | ||
|
|
2de7154128 | ||
|
|
c9afe43f5b | ||
|
|
c59f819db9 | ||
|
|
1f9efb0c66 | ||
|
|
32cbce8c8a | ||
|
|
6c2236f762 | ||
|
|
23a50e6f44 | ||
|
|
c316d493c7 | ||
|
|
70e7635f25 | ||
|
|
f5b73b09e7 | ||
|
|
7432e01740 | ||
|
|
459ab71c45 | ||
|
|
a5c177e41c | ||
|
|
d382945de7 | ||
|
|
4335f477a1 | ||
|
|
d03f00c0d1 | ||
|
|
9cea07dd41 | ||
|
|
efe18e7240 | ||
|
|
82e242a806 | ||
|
|
4a9d485d5b | ||
|
|
6ffd2e77ad | ||
|
|
7753bc5ba3 | ||
|
|
9c4fa00363 | ||
|
|
251af057d8 | ||
|
|
e60574d56d | ||
|
|
b3b482e864 | ||
|
|
ff037ad5b7 | ||
|
|
ede2ce04b1 | ||
|
|
10380099e6 | ||
|
|
058b6774da | ||
|
|
3b12b278f7 | ||
|
|
3523df1ef5 | ||
|
|
178c63cf98 | ||
|
|
ec452963fb | ||
|
|
b5cbfa780b | ||
|
|
5c40dd3109 | ||
|
|
7ab6baa0f4 | ||
|
|
0512e2c624 | ||
|
|
2693030203 | ||
|
|
3cbdf604fe | ||
|
|
d87cb82238 | ||
|
|
125f6b6504 | ||
|
|
97b475a2b7 | ||
|
|
682660d638 | ||
|
|
d8c1327eff | ||
|
|
b8fc9425ba | ||
|
|
5c42ae3fbb | ||
|
|
a8e826679f | ||
|
|
f78bfc0d02 | ||
|
|
9c12f410ed | ||
|
|
f83884af5c | ||
|
|
be25e26c46 | ||
|
|
3b93f37cb2 | ||
|
|
822e7a97b7 | ||
|
|
bc420bb60c | ||
|
|
1aedf9c487 | ||
|
|
0052efa582 | ||
|
|
316319a311 | ||
|
|
02bc34e3b7 | ||
|
|
d38433be1c | ||
|
|
366f4cd98e | ||
|
|
ee3d6a18f2 | ||
|
|
e6d6c78389 | ||
|
|
ba09ac7952 | ||
|
|
3ee9873d77 | ||
|
|
347480735c | ||
|
|
3086a45295 | ||
|
|
d33d557f08 | ||
|
|
f8fb18e244 | ||
|
|
2d8799367a | ||
|
|
7698e29373 | ||
|
|
9f96f58663 | ||
|
|
226faaa7ec | ||
|
|
e0d8bf8824 | ||
|
|
26c6c88cae | ||
|
|
effb564455 | ||
|
|
924a30cca8 | ||
|
|
a3c1451c2e | ||
|
|
2efc9b5469 | ||
|
|
3b13360fc1 | ||
|
|
a18836f95d | ||
|
|
9a9a234761 | ||
|
|
577553299b | ||
|
|
f62dc0f87a | ||
|
|
f6b16099af | ||
|
|
b03a90b7aa | ||
|
|
eebdd570e1 | ||
|
|
32457f8471 | ||
|
|
2177211841 | ||
|
|
251260a555 | ||
|
|
00286710b2 | ||
|
|
95f71d31b1 | ||
|
|
66479fdfaa | ||
|
|
4e3a06fd78 | ||
|
|
b89f09ea13 | ||
|
|
d1100cef92 | ||
|
|
6475dcacf2 | ||
|
|
4e5d36173d | ||
|
|
931bb2a7c9 | ||
|
|
99c213e41b | ||
|
|
221c41933b | ||
|
|
3a4cf5faaa | ||
|
|
708b97d64e | ||
|
|
b41c489803 | ||
|
|
2c78c56f5e | ||
|
|
5fe8a198f1 | ||
|
|
e9c3b280ac | ||
|
|
3a97f43b5d | ||
|
|
84ab70cdb2 | ||
|
|
ba93b6f648 | ||
|
|
9abb36172d | ||
|
|
701db33ab1 | ||
|
|
2eb88579ca | ||
|
|
a309fd6cb4 | ||
|
|
342918a3be | ||
|
|
c6244e29f6 | ||
|
|
d6e815b2f8 | ||
|
|
8a4ab7b570 | ||
|
|
550715001d | ||
|
|
444806160b | ||
|
|
265f88c7d6 | ||
|
|
2cd5cf4498 | ||
|
|
40e50108ae | ||
|
|
b7636841f7 | ||
|
|
922ce24eb7 | ||
|
|
824c3578d0 | ||
|
|
1ee5c7dd2d | ||
|
|
41cf4a472b | ||
|
|
7c5f0528f2 | ||
|
|
04b2a730ef | ||
|
|
1f3d5ddf0d | ||
|
|
843db06345 | ||
|
|
6001d044f2 | ||
|
|
eafd6af044 | ||
|
|
295493e976 | ||
|
|
472df83482 | ||
|
|
e7284b0e38 | ||
|
|
288fcf3507 | ||
|
|
cfdf7574ca | ||
|
|
d567b3ac01 | ||
|
|
3bd4fb58b7 | ||
|
|
01be532886 | ||
|
|
e23e6d4e04 | ||
|
|
2571411e06 | ||
|
|
0d9af8d1ec | ||
|
|
37e52e0d98 | ||
|
|
3ab80c4209 | ||
|
|
d3e548b8f5 | ||
|
|
6aff86df1f | ||
|
|
bb8897ecbe | ||
|
|
2fdf33d63e | ||
|
|
1d99b1bc31 | ||
|
|
3070479369 | ||
|
|
222629abdd | ||
|
|
b4b0a3bb38 | ||
|
|
3f163ec62a | ||
|
|
648693cffe | ||
|
|
fe0036f88e | ||
|
|
f284eed9ef | ||
|
|
b9ed3792ee | ||
|
|
2e3ca5716b | ||
|
|
4589ab789d | ||
|
|
806594d96c | ||
|
|
5d09d461c9 | ||
|
|
ec11903020 | ||
|
|
3f237c97c8 | ||
|
|
53269c1fc6 | ||
|
|
3da2bc3d57 | ||
|
|
97223c25ef | ||
|
|
8ce55fc73e | ||
|
|
bb8196aec5 | ||
|
|
3c07aa8395 | ||
|
|
7d94fc2302 | ||
|
|
9accf04545 | ||
|
|
ce949fdae1 | ||
|
|
e31438b331 | ||
|
|
79f1dfe562 | ||
|
|
37ba9fd85f | ||
|
|
d45b3329a7 | ||
|
|
1500ba2f2b | ||
|
|
eb31f91b17 | ||
|
|
db95212243 | ||
|
|
0f0ee2233e | ||
|
|
3c5b94abf8 | ||
|
|
48c4e362b3 | ||
|
|
61b896ad77 | ||
|
|
befa988090 | ||
|
|
b08fae64b8 | ||
|
|
17ccf253b4 | ||
|
|
6edfc6efc2 | ||
|
|
025e351583 | ||
|
|
cc85584154 | ||
|
|
5033b345f7 | ||
|
|
5d5aef242c | ||
|
|
71bab13453 | ||
|
|
773a9b5eb3 | ||
|
|
b0d8923a80 | ||
|
|
8728cc6a2a | ||
|
|
fec9d24a19 | ||
|
|
1a08fe74e0 | ||
|
|
b2f7bac585 | ||
|
|
46bf8e0dc3 | ||
|
|
e8216fee35 | ||
|
|
4f5af90d8d | ||
|
|
02fd2223ff | ||
|
|
feb9e51441 | ||
|
|
5c0d1ed63d | ||
|
|
d248a37c70 | ||
|
|
f1d4b77ffb | ||
|
|
7795b98dcc | ||
|
|
e8c17a4050 | ||
|
|
6e83a1f402 | ||
|
|
ba45bbe5ad | ||
|
|
d79fc3b2e3 | ||
|
|
88b804643b | ||
|
|
7b7697841e | ||
|
|
c1cfacfcae | ||
|
|
0b1a25c8d9 | ||
|
|
53611310c0 | ||
|
|
9e521122b5 | ||
|
|
ab6b54dc43 | ||
|
|
0c773151c7 | ||
|
|
9633c99dad | ||
|
|
280956dba3 | ||
|
|
92bae5f3fb | ||
|
|
fa94cf2ba3 | ||
|
|
24de8bcb20 | ||
|
|
cbfba64447 | ||
|
|
5e5c1c4abe | ||
|
|
c980024e71 | ||
|
|
a321ab9b91 | ||
|
|
0f1936b03e | ||
|
|
625a426fef | ||
|
|
2ad0ba8506 | ||
|
|
d923c5d920 | ||
|
|
282e84941a | ||
|
|
e95ebc1b9e | ||
|
|
0dffe921ff | ||
|
|
26e7970b41 | ||
|
|
36df4e83cc | ||
|
|
1c98cf85f6 | ||
|
|
a1d6bf4fe0 | ||
|
|
345f22827b | ||
|
|
f0ef1e8e7b | ||
|
|
1cc5b9b0ee | ||
|
|
7d6e933a4e | ||
|
|
3f4248737f | ||
|
|
572498022c | ||
|
|
8a85b92f8f | ||
|
|
36123371fb | ||
|
|
15c929316d | ||
|
|
30603e76b5 | ||
|
|
ad17363173 | ||
|
|
1fe93ba6dd | ||
|
|
7e968e07b8 | ||
|
|
6c5026da34 | ||
|
|
38f178cc18 | ||
|
|
8e3b0e18c0 | ||
|
|
c32a8a9568 | ||
|
|
705b5acf53 | ||
|
|
d4886c1f6f | ||
|
|
6ba68a21e6 | ||
|
|
958019199a | ||
|
|
65bf9362bd | ||
|
|
f4a5d946d6 | ||
|
|
12fcae865e | ||
|
|
5b84982812 | ||
|
|
be6d1b0f93 | ||
|
|
0f5dad0527 |
8
.esdoc.json
Normal 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
@@ -0,0 +1,17 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help improve simple-keyboard
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: hodgef
|
||||
|
||||
---
|
||||
|
||||
**Simple-keyboard version**
|
||||
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. Providing a [sandbox example](https://codesandbox.io/s/vanilla) or code depicting the issue is important, as this will help us reproduce the issue.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea you'd like to see in simple-keyboard
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**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
@@ -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.
|
||||
8
.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
## Description
|
||||
|
||||
A few sentences describing the overall goals of the pull request's commits.
|
||||
|
||||
## Checks
|
||||
|
||||
- [ ] Tests ( `npm run test -- --coverage` ) Coverage at `./coverage/lcov-report/index.html` should be 100%
|
||||
- [ ] Documentation ( `npm run docs` ) Coverage at `./docs/source.html` should be 100%
|
||||
4
.gitignore
vendored
@@ -1,7 +1,9 @@
|
||||
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# production
|
||||
/demo
|
||||
|
||||
@@ -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
|
||||
|
||||
15
.travis.yml
@@ -1,5 +1,18 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "node"
|
||||
install:
|
||||
- npm install -g codecov
|
||||
- npm install
|
||||
script:
|
||||
- npm run test
|
||||
- npm run test -- --coverage
|
||||
- npm run demo
|
||||
- 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
|
||||
382
README.md
@@ -1,360 +1,30 @@
|
||||
# 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/skdemo-4x2.gif" align="center" width="100%"></a>
|
||||
<blockquote>The easily customisable and responsive on-screen virtual keyboard for Javascript projects.</blockquote>
|
||||
<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>
|
||||
<img src="https://img.shields.io/david/dev/hodgef/simple-keyboard.svg" alt="Dev dependencies">
|
||||
<a href="https://www.codacy.com/app/hodgef/simple-keyboard?utm_source=github.com&utm_medium=referral&utm_content=hodgef/simple-keyboard&utm_campaign=Badge_Grade" target="_blank"><img src="https://api.codacy.com/project/badge/Grade/5778fccc6a894701853d9a1f2fb44a76" alt="Codacy Badge"></a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
[](https://www.npmjs.com/package/simple-keyboard)
|
||||
## 📦 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.
|
||||
|
||||
<a href="https://franciscohodge.com/projects/simple-keyboard/"><img src="https://franciscohodge.com/project-pages/simple-keyboard/images/simple-keyboard.png" align="center"></a>
|
||||
> 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.
|
||||
|
||||
<a href="https://franciscohodge.com/simple-keyboard/demo" title="View Demo"><img src="https://franciscohodge.com/project-pages/simple-keyboard/images/k2.png" align="center" width="100%"></a>
|
||||
Feel free to browse the [Q&A / Use-cases](https://simple-keyboard.com/qa-use-cases/) page for advanced use-cases.
|
||||
|
||||
## 🚀 Demo
|
||||
|
||||
## Installation
|
||||
[https://simple-keyboard.com/demo](https://simple-keyboard.com/demo)
|
||||
|
||||
### npm
|
||||
|
||||
`npm install simple-keyboard --save`
|
||||
|
||||
### 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 => this.onChange(input),
|
||||
onKeyPress: button => this.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>
|
||||
````
|
||||
|
||||
[](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.rawgit.com/hodgef/simple-keyboard/0581247fbeda4b2fb670ceaf3facebd3258fa04f/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.rawgit.com/hodgef/simple-keyboard/d88912cd23d224a22a38da34cac7b645c6a8560c/build/index.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);
|
||||
}
|
||||
````
|
||||
|
||||
[](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}'
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### layoutName
|
||||
|
||||
> Specifies which layout should be used.
|
||||
|
||||
```js
|
||||
layoutName: "default"
|
||||
```
|
||||
|
||||
### display
|
||||
|
||||
> Replaces variable buttons (such as `{bksp}`) with a human-friendly name (e.g.: "delete").
|
||||
|
||||
```js
|
||||
display: {
|
||||
'{bksp}': 'delete',
|
||||
'{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"
|
||||
},
|
||||
...
|
||||
]
|
||||
```
|
||||
|
||||
[](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).
|
||||
|
||||
[](https://codesandbox.io/s/43nm6v4xyx?module=%2Fsrc%2Findex.js)
|
||||
|
||||
## Demo
|
||||
|
||||
[https://franciscohodge.com/simple-keyboard/demo](https://franciscohodge.com/simple-keyboard/demo)
|
||||
|
||||
[](https://codesandbox.io/s/krzkx19rr)
|
||||
|
||||
### To run demo on your own computer
|
||||
|
||||
@@ -365,9 +35,15 @@ For example:
|
||||
|
||||
### Other versions
|
||||
|
||||
* ReactJS - [react-simple-keyboard](https://github.com/hodgef/react-simple-keyboard)
|
||||
* [React.js](https://github.com/hodgef/react-simple-keyboard)
|
||||
* [Angular](https://simple-keyboard.com/demo)
|
||||
* [Vue.js](https://simple-keyboard.com/demo)
|
||||
|
||||
## 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)
|
||||
|
||||
10
bin/postinstall
Normal file
@@ -0,0 +1,10 @@
|
||||
console.log('\x1b[36m%s\x1b[0m', `
|
||||
______________________________________\n`);
|
||||
|
||||
console.log('\x1b[33m%s\x1b[0m', `Thank you for installing simple-keyboard !`);
|
||||
|
||||
console.log('\x1b[36m%s\x1b[0m', `
|
||||
Please consider starring the repository so others can also find it.
|
||||
https://github.com/hodgef/simple-keyboard/stargazers
|
||||
______________________________________
|
||||
`);
|
||||
@@ -1,2 +1,12 @@
|
||||
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}.simple-keyboard.hg-layout-default .hg-button.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}
|
||||
/*# sourceMappingURL=index.css.map*/
|
||||
/*!
|
||||
*
|
||||
* simple-keyboard v2.14.0
|
||||
* 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;box-sizing:border-box;overflow:hidden;touch-action:manipulation}.simple-keyboard .hg-row{display:flex}.simple-keyboard .hg-row:not(:last-child){margin-bottom:5px}.simple-keyboard .hg-row .hg-button:not(:last-child){margin-right:5px}.simple-keyboard .hg-button{display:inline-block;flex-grow:1;cursor:pointer}.hg-standardBtn{max-width:100px}.simple-keyboard.hg-theme-default{background-color:rgba(0,0,0,.1);padding:5px;border-radius:5px}.simple-keyboard.hg-theme-default .hg-button{box-shadow:0 0 3px -1px rgba(0,0,0,.3);height:40px;border-radius:5px;box-sizing:border-box;padding:5px;background:#fff;border-bottom:1px solid #b5b5b5;cursor:pointer;display:flex;align-items:center;justify-content:center}.simple-keyboard button.hg-button{border-width:0;outline:0;font-size:inherit}.simple-keyboard.hg-theme-default .hg-button:active{background:#e4e4e4}.simple-keyboard.hg-theme-default.hg-layout-numeric .hg-button{width:33.3%;height:60px;align-items:center;display:flex;justify-content:center}.simple-keyboard.hg-theme-default .hg-button.hg-button-numpadadd,.simple-keyboard.hg-theme-default .hg-button.hg-button-numpadenter{height:85px}.simple-keyboard.hg-theme-default .hg-button.hg-button-numpad0{width:105px}.simple-keyboard.hg-theme-default .hg-button.hg-button-com{max-width:85px}.simple-keyboard.hg-theme-default .hg-button.hg-standardBtn.hg-button-at{max-width:45px}.simple-keyboard.hg-theme-default .hg-button.hg-selectedButton{background:rgba(5,25,70,.53);color:#fff}.simple-keyboard.hg-theme-default .hg-button.hg-standardBtn[data-skbtn=".com"]{max-width:82px}.simple-keyboard.hg-theme-default .hg-button.hg-standardBtn[data-skbtn="@"]{max-width:60px}
|
||||
/*# sourceMappingURL=index.css.map */
|
||||
199
build/index.d.ts
vendored
Normal file
@@ -0,0 +1,199 @@
|
||||
declare module 'simple-keyboard' {
|
||||
interface KeyboardLayoutObject {
|
||||
default: string[];
|
||||
shift?: string[];
|
||||
}
|
||||
|
||||
interface KeyboardButtonTheme {
|
||||
class: string;
|
||||
buttons: string;
|
||||
}
|
||||
|
||||
interface KeyboardOptions {
|
||||
/**
|
||||
* Modify the keyboard layout.
|
||||
*/
|
||||
layout?: KeyboardLayoutObject;
|
||||
|
||||
/**
|
||||
* Specifies which layout should be used.
|
||||
*/
|
||||
layoutName?: string;
|
||||
|
||||
/**
|
||||
* Replaces variable buttons (such as `{bksp}`) with a human-friendly name (e.g.: `backspace`).
|
||||
*/
|
||||
display?: { [button: string]: string };
|
||||
|
||||
/**
|
||||
* By default, when you set the display property, you replace the default one. This setting merges them instead.
|
||||
*/
|
||||
mergeDisplay?: boolean;
|
||||
|
||||
/**
|
||||
* A prop to add your own css classes to the keyboard wrapper. You can add multiple classes separated by a space.
|
||||
*/
|
||||
theme?: string;
|
||||
|
||||
/**
|
||||
* A prop to add your own css classes to one or several buttons.
|
||||
*/
|
||||
buttonTheme?: KeyboardButtonTheme[];
|
||||
|
||||
/**
|
||||
* Runs a `console.log` every time a key is pressed. Displays the buttons pressed and the current input.
|
||||
*/
|
||||
debug?: boolean;
|
||||
|
||||
/**
|
||||
* Specifies whether clicking the "ENTER" button will input a newline (`\n`) or not.
|
||||
*/
|
||||
newLineOnEnter?: boolean;
|
||||
|
||||
/**
|
||||
* Specifies whether clicking the "TAB" button will input a tab character (`\t`) or not.
|
||||
*/
|
||||
tabCharOnTab?: boolean;
|
||||
|
||||
/**
|
||||
* Allows you to use a single simple-keyboard instance for several inputs.
|
||||
*/
|
||||
inputName?: string;
|
||||
|
||||
/**
|
||||
* `number`: Restrains all of simple-keyboard inputs to a certain length. This should be used in addition to the input element’s maxlengthattribute.
|
||||
*
|
||||
* `{ [inputName: string]: number }`: Restrains simple-keyboard’s individual inputs to a certain length. This should be used in addition to the input element’s maxlengthattribute.
|
||||
*/
|
||||
maxLength?:
|
||||
| number
|
||||
| {
|
||||
[inputName: string]: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* When set to true, this option synchronizes the internal input of every simple-keyboard instance.
|
||||
*/
|
||||
syncInstanceInputs?: boolean;
|
||||
|
||||
/**
|
||||
* Enable highlighting of keys pressed on physical keyboard.
|
||||
*/
|
||||
physicalKeyboardHighlight?: boolean;
|
||||
|
||||
/**
|
||||
* Calling preventDefault for the mousedown events keeps the focus on the input.
|
||||
*/
|
||||
preventMouseDownDefault?: boolean;
|
||||
|
||||
/**
|
||||
* Define the text color that the physical keyboard highlighted key should have.
|
||||
*/
|
||||
physicalKeyboardHighlightTextColor?: string;
|
||||
|
||||
/**
|
||||
* Define the background color that the physical keyboard highlighted key should have.
|
||||
*/
|
||||
physicalKeyboardHighlightBgColor?: string;
|
||||
|
||||
/**
|
||||
* Render buttons as a button element instead of a div element.
|
||||
*/
|
||||
useButtonTag?: boolean;
|
||||
|
||||
/**
|
||||
* A prop to ensure characters are always be added/removed at the end of the string.
|
||||
*/
|
||||
disableCaretPositioning?: boolean;
|
||||
|
||||
/**
|
||||
* Restrains input(s) change to the defined regular expression pattern.
|
||||
*/
|
||||
inputPattern?: any;
|
||||
|
||||
/**
|
||||
* Executes the callback function on key press. Returns button layout name (i.e.: "{shift}").
|
||||
*/
|
||||
onKeyPress?: (button: string) => any;
|
||||
|
||||
/**
|
||||
* Executes the callback function on input change. Returns the current input's string.
|
||||
*/
|
||||
onChange?: (input: string) => any;
|
||||
|
||||
/**
|
||||
* Executes the callback function every time simple-keyboard is rendered (e.g: when you change layouts).
|
||||
*/
|
||||
onRender?: () => void;
|
||||
|
||||
/**
|
||||
* Executes the callback function once simple-keyboard is rendered for the first time (on initialization).
|
||||
*/
|
||||
onInit?: () => void;
|
||||
|
||||
/**
|
||||
* Executes the callback function on input change. Returns the input object with all defined inputs.
|
||||
*/
|
||||
onChangeAll?: (inputs: any) => any;
|
||||
}
|
||||
|
||||
class Keyboard {
|
||||
constructor(selector: string, options: KeyboardOptions);
|
||||
constructor(options: KeyboardOptions);
|
||||
options: KeyboardOptions;
|
||||
|
||||
/**
|
||||
* Adds/Modifies an entry to the `buttonTheme`. Basically a way to add a class to a button.
|
||||
* @param {string} buttons List of buttons to select (separated by a space).
|
||||
* @param {string} className Classes to give to the selected buttons (separated by space).
|
||||
*/
|
||||
addButtonTheme(buttons: string, className: string): void;
|
||||
|
||||
/**
|
||||
* Removes/Amends an entry to the `buttonTheme`. Basically a way to remove a class previously added to a button through buttonTheme or addButtonTheme.
|
||||
* @param {string} buttons List of buttons to select (separated by a space).
|
||||
* @param {string} className Classes to give to the selected buttons (separated by space).
|
||||
*/
|
||||
removeButtonTheme(buttons: string, className: string): void;
|
||||
|
||||
/**
|
||||
* Clear the keyboard's input.
|
||||
*
|
||||
* @param {string} [inputName] optional - the internal input to select
|
||||
*/
|
||||
clearInput(inputName?: string): void;
|
||||
|
||||
/**
|
||||
* Get the keyboard’s input (You can also get it from the onChange prop).
|
||||
* @param {string} [inputName] optional - the internal input to select
|
||||
*/
|
||||
getInput(inputName?: string): string;
|
||||
|
||||
/**
|
||||
* Set the keyboard’s input.
|
||||
* @param {string} input the input value
|
||||
* @param {string} inputName optional - the internal input to select
|
||||
*/
|
||||
setInput(input: string, inputName?: string): void;
|
||||
|
||||
/**
|
||||
* Set new option or modify existing ones after initialization.
|
||||
* @param {KeyboardOptions} option The option to set
|
||||
*/
|
||||
setOptions(options: KeyboardOptions): void;
|
||||
|
||||
/**
|
||||
* Send a command to all simple-keyboard instances at once (if you have multiple instances).
|
||||
* @param {function(instance: object, key: string)} callback Function to run on every instance
|
||||
*/
|
||||
dispatch(callback: (instance: any, key: string) => void): void;
|
||||
|
||||
/**
|
||||
* Get the DOM Element of a button. If there are several buttons with the same name, an array of the DOM Elements is returned.
|
||||
* @param {string} button The button layout name to select
|
||||
*/
|
||||
getButtonElement(button: string): HTMLElement | HTMLElement[];
|
||||
}
|
||||
|
||||
export default Keyboard;
|
||||
}
|
||||
@@ -27,24 +27,27 @@ var dotenvFiles = [
|
||||
|
||||
// Load environment variables from .env* files. Suppress warnings using silent
|
||||
// if this file is missing. dotenv will never modify any environment variables
|
||||
// that have already been set.
|
||||
// that have already been set. Variable expansion is supported in .env files.
|
||||
// https://github.com/motdotla/dotenv
|
||||
// https://github.com/motdotla/dotenv-expand
|
||||
dotenvFiles.forEach(dotenvFile => {
|
||||
if (fs.existsSync(dotenvFile)) {
|
||||
require('dotenv').config({
|
||||
path: dotenvFile,
|
||||
});
|
||||
require('dotenv-expand')(
|
||||
require('dotenv').config({
|
||||
path: dotenvFile,
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// We support resolving modules according to `NODE_PATH`.
|
||||
// This lets you use absolute paths in imports inside large monorepos:
|
||||
// https://github.com/facebookincubator/create-react-app/issues/253.
|
||||
// https://github.com/facebook/create-react-app/issues/253.
|
||||
// It works similar to `NODE_PATH` in Node itself:
|
||||
// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders
|
||||
// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored.
|
||||
// Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims.
|
||||
// https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421
|
||||
// https://github.com/facebook/create-react-app/issues/1023#issuecomment-265344421
|
||||
// We also resolve them to make sure all tools using them work consistently.
|
||||
const appDirectory = fs.realpathSync(process.cwd());
|
||||
process.env.NODE_PATH = (process.env.NODE_PATH || '')
|
||||
|
||||
25
config/getPackageJson.js
Normal 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;
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
// This is a custom Jest transformer turning style imports into empty objects.
|
||||
// http://facebook.github.io/jest/docs/tutorial-webpack.html
|
||||
// http://facebook.github.io/jest/docs/en/webpack.html
|
||||
|
||||
module.exports = {
|
||||
process() {
|
||||
|
||||
@@ -3,10 +3,28 @@
|
||||
const path = require('path');
|
||||
|
||||
// This is a custom Jest transformer turning file imports into filenames.
|
||||
// http://facebook.github.io/jest/docs/tutorial-webpack.html
|
||||
// http://facebook.github.io/jest/docs/en/webpack.html
|
||||
|
||||
module.exports = {
|
||||
process(src, filename) {
|
||||
return `module.exports = ${JSON.stringify(path.basename(filename))};`;
|
||||
const assetFilename = JSON.stringify(path.basename(filename));
|
||||
|
||||
if (filename.match(/\.svg$/)) {
|
||||
return `module.exports = {
|
||||
__esModule: true,
|
||||
default: ${assetFilename},
|
||||
ReactComponent: (props) => ({
|
||||
$$typeof: Symbol.for('react.element'),
|
||||
type: 'svg',
|
||||
ref: null,
|
||||
key: null,
|
||||
props: Object.assign({}, props, {
|
||||
children: ${assetFilename}
|
||||
})
|
||||
}),
|
||||
};`;
|
||||
}
|
||||
|
||||
return `module.exports = ${assetFilename};`;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -5,20 +5,20 @@ const fs = require('fs');
|
||||
const url = require('url');
|
||||
|
||||
// Make sure any symlinks in the project folder are resolved:
|
||||
// https://github.com/facebookincubator/create-react-app/issues/637
|
||||
// https://github.com/facebook/create-react-app/issues/637
|
||||
const appDirectory = fs.realpathSync(process.cwd());
|
||||
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
|
||||
|
||||
const envPublicUrl = process.env.PUBLIC_URL;
|
||||
|
||||
function ensureSlash(path, needsSlash) {
|
||||
const hasSlash = path.endsWith('/');
|
||||
function ensureSlash(inputPath, needsSlash) {
|
||||
const hasSlash = inputPath.endsWith('/');
|
||||
if (hasSlash && !needsSlash) {
|
||||
return path.substr(path, path.length - 1);
|
||||
return inputPath.substr(0, inputPath.length - 1);
|
||||
} else if (!hasSlash && needsSlash) {
|
||||
return `${path}/`;
|
||||
return `${inputPath}/`;
|
||||
} else {
|
||||
return path;
|
||||
return inputPath;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,27 +38,57 @@ function getServedPath(appPackageJson) {
|
||||
return ensureSlash(servedUrl, true);
|
||||
}
|
||||
|
||||
const moduleFileExtensions = [
|
||||
'web.mjs',
|
||||
'mjs',
|
||||
'web.js',
|
||||
'js',
|
||||
'web.ts',
|
||||
'ts',
|
||||
'web.tsx',
|
||||
'tsx',
|
||||
'json',
|
||||
'web.jsx',
|
||||
'jsx',
|
||||
];
|
||||
|
||||
// Resolve file paths in the same order as webpack
|
||||
const resolveModule = (resolveFn, filePath) => {
|
||||
const extension = moduleFileExtensions.find(extension =>
|
||||
fs.existsSync(resolveFn(`${filePath}.${extension}`))
|
||||
);
|
||||
|
||||
if (extension) {
|
||||
return resolveFn(`${filePath}.${extension}`);
|
||||
}
|
||||
|
||||
return resolveFn(`${filePath}.js`);
|
||||
};
|
||||
|
||||
// config after eject: we're in ./config/
|
||||
module.exports = {
|
||||
dotenv: resolveApp('.env'),
|
||||
appPath: resolveApp('.'),
|
||||
appBuild: resolveApp('build'),
|
||||
appDemoBuild: resolveApp('demo'),
|
||||
appDemo: resolveApp('demo'),
|
||||
appPublic: resolveApp('public'),
|
||||
appHtml: resolveApp('public/index.html'),
|
||||
appIndexJs: resolveApp('src/demo/index.js'), // CRL: Updated for demo purposes
|
||||
appIndexJs: resolveModule(resolveApp, 'src/demo/index'),
|
||||
appLibIndexJs: resolveModule(resolveApp, 'src/lib/index'),
|
||||
appDemoIndexJs: resolveModule(resolveApp, 'src/demo/index'),
|
||||
appPackageJson: resolveApp('package.json'),
|
||||
appSrc: resolveApp('src'),
|
||||
appSrcLib: resolveApp('src/lib'),
|
||||
appSrcLibTypes: resolveApp('src/lib/@types'),
|
||||
appSrcDemo: resolveApp('src/demo'),
|
||||
appTsConfig: resolveApp('tsconfig.json'),
|
||||
yarnLockFile: resolveApp('yarn.lock'),
|
||||
testsSetup: resolveApp('src/setupTests.js'),
|
||||
testsSetup: resolveModule(resolveApp, 'src/setupTests'),
|
||||
proxySetup: resolveApp('src/setupProxy.js'),
|
||||
appNodeModules: resolveApp('node_modules'),
|
||||
publicUrl: getPublicUrl(resolveApp('package.json')),
|
||||
servedPath: getServedPath(resolveApp('package.json')),
|
||||
|
||||
// CRL: New paths for demo build
|
||||
appDemoIndexJs: resolveApp('src/demo/index.js'),
|
||||
appDemoSrc: resolveApp('src/demo'),
|
||||
|
||||
// CRL: New paths for library
|
||||
appLibIndexJs: resolveApp('src/lib/index.js'),
|
||||
appLibSrc: resolveApp('src/lib'),
|
||||
//servedPath: getServedPath(resolveApp('package.json')),
|
||||
servedPath: ''
|
||||
};
|
||||
|
||||
module.exports.moduleFileExtensions = moduleFileExtensions;
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
if (typeof Promise === 'undefined') {
|
||||
// Rejection tracking prevents a common issue where React gets into an
|
||||
// inconsistent state due to an error, but it gets swallowed by a Promise,
|
||||
// and the user has no idea what causes React's erratic future behavior.
|
||||
require('promise/lib/rejection-tracking').enable();
|
||||
window.Promise = require('promise/lib/es6-extensions.js');
|
||||
}
|
||||
|
||||
// fetch() polyfill for making API calls.
|
||||
require('whatwg-fetch');
|
||||
|
||||
// Object.assign() is commonly used with React.
|
||||
// It will use the native implementation if it's present and isn't buggy.
|
||||
Object.assign = require('object-assign');
|
||||
|
||||
// In tests, polyfill requestAnimationFrame since jsdom doesn't provide it yet.
|
||||
// We don't polyfill it in the browser--this is user's responsibility.
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
require('raf').polyfill(global);
|
||||
}
|
||||
@@ -1,16 +1,27 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
const autoprefixer = require('autoprefixer');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const resolve = require('resolve');
|
||||
const PnpWebpackPlugin = require('pnp-webpack-plugin');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
||||
const safePostCssParser = require('postcss-safe-parser');
|
||||
const ManifestPlugin = require('webpack-manifest-plugin');
|
||||
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
const eslintFormatter = require('react-dev-utils/eslintFormatter');
|
||||
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
|
||||
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
|
||||
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
|
||||
const paths = require('./paths');
|
||||
const getClientEnvironment = require('./env');
|
||||
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
|
||||
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin-alt');
|
||||
const typescriptFormatter = require('react-dev-utils/typescriptFormatter');
|
||||
|
||||
|
||||
// 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.
|
||||
@@ -20,10 +31,13 @@ const publicPath = paths.servedPath;
|
||||
const shouldUseRelativeAssetPaths = publicPath === './';
|
||||
// Source maps are resource heavy and can cause out of memory issue for large source files.
|
||||
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
|
||||
// Some apps do not need the benefits of saving a web request, so not inlining the chunk
|
||||
// makes for a smoother build process.
|
||||
const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false';
|
||||
// `publicUrl` is just like `publicPath`, but we will provide it to our app
|
||||
// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
|
||||
// Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz.
|
||||
const publicUrl = '.';
|
||||
const publicUrl = publicPath.slice(0, -1);
|
||||
// Get environment variables to inject into our app.
|
||||
const env = getClientEnvironment(publicUrl);
|
||||
|
||||
@@ -33,88 +47,228 @@ if (env.stringified['process.env'].NODE_ENV !== '"production"') {
|
||||
throw new Error('Production builds must have NODE_ENV=production.');
|
||||
}
|
||||
|
||||
// Note: defined here because it will be used more than once.
|
||||
const cssFilename = 'css/index.css';
|
||||
// Check if TypeScript is setup
|
||||
const useTypeScript = fs.existsSync(paths.appTsConfig);
|
||||
|
||||
// ExtractTextPlugin expects the build output to be flat.
|
||||
// (See https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/27)
|
||||
// However, our output is structured with css, js and media folders.
|
||||
// To have this structure working with relative paths, we have to use custom options.
|
||||
const extractTextPluginOptions = shouldUseRelativeAssetPaths
|
||||
? // Making sure that the publicPath goes back to to build folder.
|
||||
{ publicPath: Array(cssFilename.split('/').length).join('../') }
|
||||
: {};
|
||||
// style files regexes
|
||||
const cssRegex = /\.css$/;
|
||||
const cssModuleRegex = /\.module\.css$/;
|
||||
const sassRegex = /\.(scss|sass)$/;
|
||||
const sassModuleRegex = /\.module\.(scss|sass)$/;
|
||||
|
||||
// common function to get style loaders
|
||||
const getStyleLoaders = (cssOptions, preProcessor) => {
|
||||
const loaders = [
|
||||
{
|
||||
loader: MiniCssExtractPlugin.loader,
|
||||
options: Object.assign(
|
||||
{},
|
||||
shouldUseRelativeAssetPaths ? { publicPath: '../../' } : undefined
|
||||
),
|
||||
},
|
||||
{
|
||||
loader: require.resolve('css-loader'),
|
||||
options: cssOptions,
|
||||
},
|
||||
{
|
||||
// Options for PostCSS as we reference these options twice
|
||||
// Adds vendor prefixing based on your specified browser support in
|
||||
// package.json
|
||||
loader: require.resolve('postcss-loader'),
|
||||
options: {
|
||||
// Necessary for external CSS imports to work
|
||||
// https://github.com/facebook/create-react-app/issues/2677
|
||||
ident: 'postcss',
|
||||
plugins: () => [
|
||||
require('postcss-flexbugs-fixes'),
|
||||
require('postcss-preset-env')({
|
||||
autoprefixer: {
|
||||
flexbox: 'no-2009',
|
||||
},
|
||||
stage: 3,
|
||||
}),
|
||||
],
|
||||
sourceMap: shouldUseSourceMap,
|
||||
},
|
||||
},
|
||||
];
|
||||
if (preProcessor) {
|
||||
loaders.push({
|
||||
loader: require.resolve(preProcessor),
|
||||
options: {
|
||||
sourceMap: shouldUseSourceMap,
|
||||
},
|
||||
});
|
||||
}
|
||||
return loaders;
|
||||
};
|
||||
|
||||
// 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.
|
||||
module.exports = {
|
||||
mode: 'production',
|
||||
// Don't attempt to continue if there are any errors.
|
||||
bail: true,
|
||||
// We generate sourcemaps in production. This is slow but gives good results.
|
||||
// You can exclude the *.map files from the build during deployment.
|
||||
devtool: shouldUseSourceMap ? 'source-map' : false,
|
||||
// In production, we only want to load the app code.
|
||||
entry: [paths.appDemoIndexJs], // CRL: library index file instead of app index
|
||||
entry: [paths.appDemoIndexJs],
|
||||
output: {
|
||||
// CRL: Updated whole block with library specific info
|
||||
path: paths.appDemoBuild,
|
||||
// The build folder.
|
||||
path: paths.appDemo,
|
||||
// Generated JS file names (with nested folders).
|
||||
// There will be one main bundle, and one file per asynchronous chunk.
|
||||
// We don't currently advertise code splitting but Webpack supports it.
|
||||
filename: 'index.js',
|
||||
libraryTarget: 'umd',
|
||||
library: 'SimpleKeyboard'
|
||||
chunkFilename: 'index.[chunkhash:8].chunk.js',
|
||||
// We inferred the "public path" (such as / or /my-project) from homepage.
|
||||
publicPath: publicPath,
|
||||
// Point sourcemap entries to original disk location (format as URL on Windows)
|
||||
devtoolModuleFilenameTemplate: info =>
|
||||
path
|
||||
.relative(paths.appSrcDemo, info.absoluteResourcePath)
|
||||
.replace(/\\/g, '/'),
|
||||
},
|
||||
optimization: {
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
terserOptions: {
|
||||
parse: {
|
||||
// we want terser to parse ecma 8 code. However, we don't want it
|
||||
// to apply any minfication steps that turns valid ecma 5 code
|
||||
// into invalid ecma 5 code. This is why the 'compress' and 'output'
|
||||
// sections only apply transformations that are ecma 5 safe
|
||||
// https://github.com/facebook/create-react-app/pull/4234
|
||||
ecma: 8,
|
||||
},
|
||||
compress: {
|
||||
ecma: 5,
|
||||
warnings: false,
|
||||
// Disabled because of an issue with Uglify breaking seemingly valid code:
|
||||
// https://github.com/facebook/create-react-app/issues/2376
|
||||
// Pending further investigation:
|
||||
// https://github.com/mishoo/UglifyJS2/issues/2011
|
||||
comparisons: false,
|
||||
// Disabled because of an issue with Terser breaking valid code:
|
||||
// https://github.com/facebook/create-react-app/issues/5250
|
||||
// Pending futher investigation:
|
||||
// https://github.com/terser-js/terser/issues/120
|
||||
inline: 2,
|
||||
},
|
||||
mangle: {
|
||||
safari10: true,
|
||||
},
|
||||
output: {
|
||||
ecma: 5,
|
||||
comments: false,
|
||||
// Turned on because emoji and regex is not minified properly using default
|
||||
// https://github.com/facebook/create-react-app/issues/2488
|
||||
ascii_only: true,
|
||||
},
|
||||
},
|
||||
// Use multi-process parallel running to improve the build speed
|
||||
// Default number of concurrent runs: os.cpus().length - 1
|
||||
parallel: true,
|
||||
// Enable file caching
|
||||
cache: true,
|
||||
sourceMap: shouldUseSourceMap,
|
||||
}),
|
||||
new OptimizeCSSAssetsPlugin({
|
||||
cssProcessorOptions: {
|
||||
parser: safePostCssParser,
|
||||
map: shouldUseSourceMap
|
||||
? {
|
||||
// `inline: false` forces the sourcemap to be output into a
|
||||
// separate file
|
||||
inline: false,
|
||||
// `annotation: true` appends the sourceMappingURL to the end of
|
||||
// the css file, helping the browser find the sourcemap
|
||||
annotation: true,
|
||||
}
|
||||
: false,
|
||||
},
|
||||
}),
|
||||
],
|
||||
// Automatically split vendor and commons
|
||||
// https://twitter.com/wSokra/status/969633336732905474
|
||||
// https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366
|
||||
splitChunks: {
|
||||
/*chunks: 'all',
|
||||
name: false,*/
|
||||
cacheGroups: {
|
||||
default: false,
|
||||
}
|
||||
},
|
||||
// Keep the runtime chunk seperated to enable long term caching
|
||||
// https://twitter.com/wSokra/status/969679223278505985
|
||||
runtimeChunk: false,
|
||||
},
|
||||
resolve: {
|
||||
// This allows you to set a fallback for where Webpack should look for modules.
|
||||
// We placed these paths second because we want `node_modules` to "win"
|
||||
// if there are any conflicts. This matches Node resolution mechanism.
|
||||
// https://github.com/facebookincubator/create-react-app/issues/253
|
||||
modules: ['node_modules', paths.appNodeModules].concat(
|
||||
// https://github.com/facebook/create-react-app/issues/253
|
||||
modules: ['node_modules'].concat(
|
||||
// It is guaranteed to exist because we tweak it in `env.js`
|
||||
process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
|
||||
),
|
||||
// These are the reasonable defaults supported by the Node ecosystem.
|
||||
// We also include JSX as a common component filename extension to support
|
||||
// some tools, although we do not recommend using it, see:
|
||||
// https://github.com/facebookincubator/create-react-app/issues/290
|
||||
// https://github.com/facebook/create-react-app/issues/290
|
||||
// `web` extension prefixes have been added for better support
|
||||
// for React Native Web.
|
||||
extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx'],
|
||||
extensions: paths.moduleFileExtensions
|
||||
.map(ext => `.${ext}`)
|
||||
.filter(ext => useTypeScript || !ext.includes('ts')),
|
||||
alias: {
|
||||
// Support React Native Web
|
||||
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
|
||||
'react-native': 'react-native-web'
|
||||
'react-native': 'react-native-web',
|
||||
},
|
||||
plugins: [
|
||||
// Adds support for installing with Plug'n'Play, leading to faster installs and adding
|
||||
// guards against forgotten dependencies and such.
|
||||
PnpWebpackPlugin,
|
||||
// Prevents users from importing files from outside of src/ (or node_modules/).
|
||||
// This often causes confusion because we only process files within src/ with babel.
|
||||
// To fix this, we prevent you from importing files out of src/ -- if you'd like to,
|
||||
// please link the files into your node_modules/ and let module-resolution kick in.
|
||||
// Make sure your source files are compiled, as they will not be processed in any way.
|
||||
new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson])
|
||||
]
|
||||
new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
|
||||
],
|
||||
},
|
||||
resolveLoader: {
|
||||
plugins: [
|
||||
// Also related to Plug'n'Play, but this time it tells Webpack to load its loaders
|
||||
// from the current package.
|
||||
PnpWebpackPlugin.moduleLoader(module),
|
||||
],
|
||||
},
|
||||
module: {
|
||||
strictExportPresence: true,
|
||||
rules: [
|
||||
// TODO: Disable require.ensure as it's not a standard language feature.
|
||||
// We are waiting for https://github.com/facebookincubator/create-react-app/issues/2176.
|
||||
// { parser: { requireEnsure: false } },
|
||||
// Disable require.ensure as it's not a standard language feature.
|
||||
{ parser: { requireEnsure: false } },
|
||||
|
||||
// First, run the linter.
|
||||
// It's important to do this before Babel processes the JS.
|
||||
{
|
||||
test: /\.(js|jsx|mjs)$/,
|
||||
test: /\.(js|mjs|jsx)$/,
|
||||
enforce: 'pre',
|
||||
use: [
|
||||
{
|
||||
options: {
|
||||
formatter: eslintFormatter,
|
||||
eslintPath: require.resolve('eslint')
|
||||
formatter: require.resolve('react-dev-utils/eslintFormatter'),
|
||||
eslintPath: require.resolve('eslint'),
|
||||
|
||||
},
|
||||
loader: require.resolve('eslint-loader')
|
||||
}
|
||||
loader: require.resolve('eslint-loader'),
|
||||
},
|
||||
],
|
||||
include: paths.appDemoSrc // CRL: updated with library src folder
|
||||
include: paths.appSrcDemo,
|
||||
},
|
||||
{
|
||||
// "oneOf" will traverse all following loaders until one will
|
||||
@@ -128,76 +282,132 @@ module.exports = {
|
||||
loader: require.resolve('url-loader'),
|
||||
options: {
|
||||
limit: 10000,
|
||||
name: 'media/[name].[ext]'
|
||||
}
|
||||
name: 'static/media/[name].[hash:8].[ext]',
|
||||
},
|
||||
},
|
||||
// Process JS with Babel.
|
||||
// Process application JS with Babel.
|
||||
// The preset includes JSX, Flow, TypeScript and some ESnext features.
|
||||
{
|
||||
test: /\.(js|jsx|mjs)$/,
|
||||
include: [paths.appLibSrc, paths.appDemoSrc], // CRL: updated with library src folder
|
||||
test: /\.(js|mjs|jsx|ts|tsx)$/,
|
||||
include: paths.appSrcDemo,
|
||||
|
||||
loader: require.resolve('babel-loader'),
|
||||
options: {
|
||||
compact: true
|
||||
}
|
||||
customize: require.resolve(
|
||||
'babel-preset-react-app/webpack-overrides'
|
||||
),
|
||||
|
||||
plugins: [
|
||||
[
|
||||
require.resolve('babel-plugin-named-asset-import'),
|
||||
{
|
||||
loaderMap: {
|
||||
svg: {
|
||||
ReactComponent: '@svgr/webpack?-prettier,-svgo![path]',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
cacheDirectory: true,
|
||||
// Save disk space when time isn't as important
|
||||
cacheCompression: true,
|
||||
compact: true,
|
||||
},
|
||||
},
|
||||
// Process any JS outside of the app with Babel.
|
||||
// Unlike the application JS, we only compile the standard ES features.
|
||||
{
|
||||
test: /\.(js|mjs)$/,
|
||||
exclude: /@babel(?:\/|\\{1,2})runtime/,
|
||||
loader: require.resolve('babel-loader'),
|
||||
options: {
|
||||
babelrc: false,
|
||||
configFile: false,
|
||||
compact: false,
|
||||
presets: [
|
||||
"@babel/preset-env",
|
||||
"@babel/preset-react"
|
||||
],
|
||||
plugins: [
|
||||
[
|
||||
"@babel/plugin-proposal-class-properties"
|
||||
]
|
||||
],
|
||||
cacheDirectory: true,
|
||||
// Save disk space when time isn't as important
|
||||
cacheCompression: true,
|
||||
|
||||
// If an error happens in a package, it's possible to be
|
||||
// because it was compiled. Thus, we don't want the browser
|
||||
// debugger to show the original code. Instead, the code
|
||||
// being evaluated would be much more helpful.
|
||||
sourceMaps: false,
|
||||
},
|
||||
},
|
||||
// The notation here is somewhat confusing.
|
||||
// "postcss" loader applies autoprefixer to our CSS.
|
||||
// "css" loader resolves paths in CSS and adds assets as dependencies.
|
||||
// "style" loader normally turns CSS into JS modules injecting <style>,
|
||||
// but unlike in development configuration, we do something different.
|
||||
// `ExtractTextPlugin` first applies the "postcss" and "css" loaders
|
||||
// (second argument), then grabs the result CSS and puts it into a
|
||||
// separate file in our build process. This way we actually ship
|
||||
// a single CSS file in production instead of JS code injecting <style>
|
||||
// tags. If you use code splitting, however, any async bundles will still
|
||||
// use the "style" loader inside the async code so CSS from them won't be
|
||||
// in the main CSS file.
|
||||
// `MiniCSSExtractPlugin` extracts styles into CSS
|
||||
// files. If you use code splitting, async bundles will have their own separate CSS chunk file.
|
||||
// By default we support CSS Modules with the extension .module.css
|
||||
{
|
||||
test: /\.css$/,
|
||||
loader: ExtractTextPlugin.extract(
|
||||
Object.assign(
|
||||
{
|
||||
fallback: {
|
||||
loader: require.resolve('style-loader'),
|
||||
options: {
|
||||
hmr: false
|
||||
}
|
||||
},
|
||||
use: [
|
||||
{
|
||||
loader: require.resolve('css-loader'),
|
||||
options: {
|
||||
importLoaders: 1,
|
||||
minimize: true,
|
||||
sourceMap: shouldUseSourceMap
|
||||
}
|
||||
},
|
||||
{
|
||||
loader: require.resolve('postcss-loader'),
|
||||
options: {
|
||||
// Necessary for external CSS imports to work
|
||||
// https://github.com/facebookincubator/create-react-app/issues/2677
|
||||
ident: 'postcss',
|
||||
plugins: () => [
|
||||
require('postcss-flexbugs-fixes'),
|
||||
autoprefixer({
|
||||
browsers: [
|
||||
'>1%',
|
||||
'last 4 versions',
|
||||
'Firefox ESR',
|
||||
'not ie < 9' // React doesn't support IE8 anyway
|
||||
],
|
||||
flexbox: 'no-2009'
|
||||
})
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
extractTextPluginOptions
|
||||
)
|
||||
)
|
||||
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
|
||||
test: cssRegex,
|
||||
exclude: cssModuleRegex,
|
||||
loader: getStyleLoaders({
|
||||
importLoaders: 1,
|
||||
sourceMap: shouldUseSourceMap,
|
||||
}),
|
||||
// Don't consider CSS imports dead code even if the
|
||||
// containing package claims to have no side effects.
|
||||
// Remove this when webpack adds a warning or an error for this.
|
||||
// See https://github.com/webpack/webpack/issues/6571
|
||||
sideEffects: true,
|
||||
},
|
||||
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
|
||||
// using the extension .module.css
|
||||
{
|
||||
test: cssModuleRegex,
|
||||
loader: getStyleLoaders({
|
||||
importLoaders: 1,
|
||||
sourceMap: shouldUseSourceMap,
|
||||
modules: true,
|
||||
getLocalIdent: getCSSModuleLocalIdent,
|
||||
}),
|
||||
},
|
||||
// Opt-in support for SASS. The logic here is somewhat similar
|
||||
// as in the CSS routine, except that "sass-loader" runs first
|
||||
// to compile SASS files into CSS.
|
||||
// By default we support SASS Modules with the
|
||||
// extensions .module.scss or .module.sass
|
||||
{
|
||||
test: sassRegex,
|
||||
exclude: sassModuleRegex,
|
||||
loader: getStyleLoaders(
|
||||
{
|
||||
importLoaders: 2,
|
||||
sourceMap: shouldUseSourceMap,
|
||||
},
|
||||
'sass-loader'
|
||||
),
|
||||
// Don't consider CSS imports dead code even if the
|
||||
// containing package claims to have no side effects.
|
||||
// Remove this when webpack adds a warning or an error for this.
|
||||
// See https://github.com/webpack/webpack/issues/6571
|
||||
sideEffects: true,
|
||||
},
|
||||
// Adds support for CSS Modules, but using SASS
|
||||
// using the extension .module.scss or .module.sass
|
||||
{
|
||||
test: sassModuleRegex,
|
||||
loader: getStyleLoaders(
|
||||
{
|
||||
importLoaders: 2,
|
||||
sourceMap: shouldUseSourceMap,
|
||||
modules: true,
|
||||
getLocalIdent: getCSSModuleLocalIdent,
|
||||
},
|
||||
'sass-loader'
|
||||
),
|
||||
},
|
||||
// "file" loader makes sure assets end up in the `build` folder.
|
||||
// When you `import` an asset, you get its filename.
|
||||
@@ -206,68 +416,120 @@ module.exports = {
|
||||
{
|
||||
loader: require.resolve('file-loader'),
|
||||
// Exclude `js` files to keep "css" loader working as it injects
|
||||
// it's runtime that would otherwise processed through "file" loader.
|
||||
// it's runtime that would otherwise be processed through "file" loader.
|
||||
// Also exclude `html` and `json` extensions so they get processed
|
||||
// by webpacks internal loaders.
|
||||
exclude: [/\.js$/, /\.html$/, /\.json$/],
|
||||
exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
|
||||
options: {
|
||||
name: 'media/[name].[ext]'
|
||||
}
|
||||
}
|
||||
name: 'static/media/[name].[hash:8].[ext]',
|
||||
},
|
||||
},
|
||||
// ** STOP ** Are you adding a new loader?
|
||||
// Make sure to add the new loader(s) before the "file" loader.
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
// Generates an `index.html` file with the <script> injected.
|
||||
new HtmlWebpackPlugin({
|
||||
inject: true,
|
||||
template: paths.appHtml,
|
||||
minify: {
|
||||
removeComments: true,
|
||||
collapseWhitespace: true,
|
||||
removeRedundantAttributes: true,
|
||||
useShortDoctype: true,
|
||||
removeEmptyAttributes: true,
|
||||
removeStyleLinkTypeAttributes: true,
|
||||
keepClosingSlash: true,
|
||||
minifyJS: true,
|
||||
minifyCSS: true,
|
||||
minifyURLs: true,
|
||||
},
|
||||
}),
|
||||
// Inlines the webpack runtime script. This script is too small to warrant
|
||||
// a network request.
|
||||
shouldInlineRuntimeChunk &&
|
||||
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime~.+[.]js/]),
|
||||
// Makes some environment variables available in index.html.
|
||||
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
|
||||
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
// In production, it will be an empty string unless you specify "homepage"
|
||||
// in `package.json`, in which case it will be the pathname of that URL.
|
||||
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
|
||||
// This gives some necessary context to module not found errors, such as
|
||||
// the requesting resource.
|
||||
new ModuleNotFoundPlugin(paths.appPath),
|
||||
// Makes some environment variables available to the JS code, for example:
|
||||
// if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`.
|
||||
// It is absolutely essential that NODE_ENV was set to production here.
|
||||
// Otherwise React will be compiled in the very slow development mode.
|
||||
new InterpolateHtmlPlugin(env.raw),
|
||||
// Generates an `index.html` file with the <script> injected.
|
||||
new HtmlWebpackPlugin({
|
||||
inject: true,
|
||||
template: paths.appHtml
|
||||
}),
|
||||
// Add module names to factory functions so they appear in browser profiler.
|
||||
new webpack.NamedModulesPlugin(),
|
||||
new webpack.DefinePlugin(env.stringified),
|
||||
// Minify the code.
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
compress: false,
|
||||
mangle: {
|
||||
safari10: true
|
||||
},
|
||||
output: {
|
||||
comments: false,
|
||||
// Turned on because emoji and regex is not minified properly using default
|
||||
// https://github.com/facebookincubator/create-react-app/issues/2488
|
||||
ascii_only: true
|
||||
},
|
||||
sourceMap: shouldUseSourceMap
|
||||
}),
|
||||
// Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`.
|
||||
new ExtractTextPlugin({
|
||||
filename: cssFilename
|
||||
new MiniCssExtractPlugin({
|
||||
// Options similar to the same options in webpackOptions.output
|
||||
// both options are optional
|
||||
filename: 'index.css',
|
||||
chunkFilename: 'index.[contenthash:8].chunk.css',
|
||||
}),
|
||||
// Generate a manifest file which contains a mapping of all asset filenames
|
||||
// to their corresponding output file so that tools can pick it up without
|
||||
// having to parse `index.html`.
|
||||
/*new ManifestPlugin({
|
||||
fileName: 'asset-manifest.json',
|
||||
publicPath: publicPath,
|
||||
}),*/
|
||||
// Moment.js is an extremely popular library that bundles large locale files
|
||||
// by default due to how Webpack interprets its code. This is a practical
|
||||
// solution that requires the user to opt into importing specific locales.
|
||||
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
|
||||
// You can remove this if you don't use Moment.js:
|
||||
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
|
||||
new CopyWebpackPlugin([
|
||||
{ from: `${paths.appPublic}/favicon.ico`, to: paths.appDemoBuild },
|
||||
{ from: `${paths.appPublic}/manifest.json`, to: paths.appDemoBuild }
|
||||
])
|
||||
],
|
||||
// CRL: added externals block for library
|
||||
// externals: {
|
||||
// 'react': 'react',
|
||||
// 'react-dom': 'react-dom'
|
||||
// },
|
||||
// Generate a service worker script that will precache, and keep up to date,
|
||||
// the HTML & assets that are part of the Webpack build.
|
||||
/*new WorkboxWebpackPlugin.GenerateSW({
|
||||
clientsClaim: true,
|
||||
exclude: [/\.map$/, /asset-manifest\.json$/],
|
||||
importWorkboxFrom: 'cdn',
|
||||
navigateFallback: publicUrl + '/index.html',
|
||||
navigateFallbackBlacklist: [
|
||||
// Exclude URLs starting with /_, as they're likely an API call
|
||||
new RegExp('^/_'),
|
||||
// Exclude URLs containing a dot, as they're likely a resource in
|
||||
// public/ and not a SPA route
|
||||
new RegExp('/[^/]+\\.[^/]+$'),
|
||||
],
|
||||
}),*/
|
||||
// TypeScript type checking
|
||||
fs.existsSync(paths.appTsConfig) &&
|
||||
new ForkTsCheckerWebpackPlugin({
|
||||
typescript: resolve.sync('typescript', {
|
||||
basedir: paths.appNodeModules,
|
||||
}),
|
||||
async: false,
|
||||
checkSyntacticErrors: true,
|
||||
tsconfig: paths.appTsConfig,
|
||||
compilerOptions: {
|
||||
module: 'esnext',
|
||||
moduleResolution: 'node',
|
||||
resolveJsonModule: true,
|
||||
isolatedModules: true,
|
||||
noEmit: true,
|
||||
jsx: 'preserve',
|
||||
},
|
||||
reportFiles: [
|
||||
'**',
|
||||
'!**/*.json',
|
||||
'!**/__tests__/**',
|
||||
'!**/?(*.)(spec|test).*',
|
||||
'!src/setupProxy.js',
|
||||
'!src/setupTests.*',
|
||||
],
|
||||
watch: paths.appSrcDemo,
|
||||
silent: true,
|
||||
formatter: typescriptFormatter,
|
||||
}),
|
||||
].filter(Boolean),
|
||||
// Some libraries import Node modules but don't use them in the browser.
|
||||
// Tell Webpack to provide empty mocks for them so importing them works.
|
||||
node: {
|
||||
@@ -275,6 +537,9 @@ module.exports = {
|
||||
fs: 'empty',
|
||||
net: 'empty',
|
||||
tls: 'empty',
|
||||
child_process: 'empty'
|
||||
}
|
||||
child_process: 'empty',
|
||||
},
|
||||
// Turn off performance processing because we utilize
|
||||
// our own hints via the FileSizeReporter
|
||||
performance: false,
|
||||
};
|
||||
|
||||
@@ -1,16 +1,23 @@
|
||||
'use strict';
|
||||
|
||||
const autoprefixer = require('autoprefixer');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const resolve = require('resolve');
|
||||
const webpack = require('webpack');
|
||||
const PnpWebpackPlugin = require('pnp-webpack-plugin');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
|
||||
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
|
||||
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
|
||||
const eslintFormatter = require('react-dev-utils/eslintFormatter');
|
||||
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
|
||||
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
|
||||
const getClientEnvironment = require('./env');
|
||||
const paths = require('./paths');
|
||||
const ManifestPlugin = require('webpack-manifest-plugin');
|
||||
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
|
||||
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin-alt');
|
||||
const typescriptFormatter = require('react-dev-utils/typescriptFormatter');
|
||||
|
||||
|
||||
// Webpack uses `publicPath` to determine where the app is being served from.
|
||||
// In development, we always serve from the root. This makes config easier.
|
||||
@@ -22,16 +29,60 @@ const publicUrl = '';
|
||||
// Get environment variables to inject into our app.
|
||||
const env = getClientEnvironment(publicUrl);
|
||||
|
||||
// Check if TypeScript is setup
|
||||
const useTypeScript = fs.existsSync(paths.appTsConfig);
|
||||
|
||||
// style files regexes
|
||||
const cssRegex = /\.css$/;
|
||||
const cssModuleRegex = /\.module\.css$/;
|
||||
const sassRegex = /\.(scss|sass)$/;
|
||||
const sassModuleRegex = /\.module\.(scss|sass)$/;
|
||||
|
||||
// common function to get style loaders
|
||||
const getStyleLoaders = (cssOptions, preProcessor) => {
|
||||
const loaders = [
|
||||
require.resolve('style-loader'),
|
||||
{
|
||||
loader: require.resolve('css-loader'),
|
||||
options: cssOptions,
|
||||
},
|
||||
{
|
||||
// Options for PostCSS as we reference these options twice
|
||||
// Adds vendor prefixing based on your specified browser support in
|
||||
// package.json
|
||||
loader: require.resolve('postcss-loader'),
|
||||
options: {
|
||||
// Necessary for external CSS imports to work
|
||||
// https://github.com/facebook/create-react-app/issues/2677
|
||||
ident: 'postcss',
|
||||
plugins: () => [
|
||||
require('postcss-flexbugs-fixes'),
|
||||
require('postcss-preset-env')({
|
||||
autoprefixer: {
|
||||
flexbox: 'no-2009',
|
||||
},
|
||||
stage: 3,
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
if (preProcessor) {
|
||||
loaders.push(require.resolve(preProcessor));
|
||||
}
|
||||
return loaders;
|
||||
};
|
||||
|
||||
// This is the development configuration.
|
||||
// It is focused on developer experience and fast rebuilds.
|
||||
// The production configuration is different and lives in a separate file.
|
||||
module.exports = {
|
||||
mode: 'development',
|
||||
// You may want 'eval' instead if you prefer to see the compiled output in DevTools.
|
||||
// See the discussion in https://github.com/facebookincubator/create-react-app/issues/343.
|
||||
// See the discussion in https://github.com/facebook/create-react-app/issues/343
|
||||
devtool: 'cheap-module-source-map',
|
||||
// These are the "entry points" to our application.
|
||||
// This means they will be the "root" imports that are included in JS bundle.
|
||||
// The first two entry points enable "hot" CSS and auto-refreshes for JS.
|
||||
entry: [
|
||||
// Include an alternative client for WebpackDevServer. A client's job is to
|
||||
// connect to WebpackDevServer by a socket and get notified about changes.
|
||||
@@ -65,29 +116,46 @@ module.exports = {
|
||||
devtoolModuleFilenameTemplate: info =>
|
||||
path.resolve(info.absoluteResourcePath).replace(/\\/g, '/'),
|
||||
},
|
||||
optimization: {
|
||||
// Automatically split vendor and commons
|
||||
// https://twitter.com/wSokra/status/969633336732905474
|
||||
// https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366
|
||||
splitChunks: {
|
||||
cacheGroups: {
|
||||
default: false,
|
||||
}
|
||||
},
|
||||
// Keep the runtime chunk seperated to enable long term caching
|
||||
// https://twitter.com/wSokra/status/969679223278505985
|
||||
runtimeChunk: false,
|
||||
},
|
||||
resolve: {
|
||||
// This allows you to set a fallback for where Webpack should look for modules.
|
||||
// We placed these paths second because we want `node_modules` to "win"
|
||||
// if there are any conflicts. This matches Node resolution mechanism.
|
||||
// https://github.com/facebookincubator/create-react-app/issues/253
|
||||
modules: ['node_modules', paths.appNodeModules].concat(
|
||||
// https://github.com/facebook/create-react-app/issues/253
|
||||
modules: ['node_modules'].concat(
|
||||
// It is guaranteed to exist because we tweak it in `env.js`
|
||||
process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
|
||||
),
|
||||
// These are the reasonable defaults supported by the Node ecosystem.
|
||||
// We also include JSX as a common component filename extension to support
|
||||
// some tools, although we do not recommend using it, see:
|
||||
// https://github.com/facebookincubator/create-react-app/issues/290
|
||||
// https://github.com/facebook/create-react-app/issues/290
|
||||
// `web` extension prefixes have been added for better support
|
||||
// for React Native Web.
|
||||
extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx'],
|
||||
extensions: paths.moduleFileExtensions
|
||||
.map(ext => `.${ext}`)
|
||||
.filter(ext => useTypeScript || !ext.includes('ts')),
|
||||
alias: {
|
||||
|
||||
// Support React Native Web
|
||||
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
|
||||
'react-native': 'react-native-web',
|
||||
},
|
||||
plugins: [
|
||||
// Adds support for installing with Plug'n'Play, leading to faster installs and adding
|
||||
// guards against forgotten dependencies and such.
|
||||
PnpWebpackPlugin,
|
||||
// Prevents users from importing files from outside of src/ (or node_modules/).
|
||||
// This often causes confusion because we only process files within src/ with babel.
|
||||
// To fix this, we prevent you from importing files out of src/ -- if you'd like to,
|
||||
@@ -96,24 +164,30 @@ module.exports = {
|
||||
new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
|
||||
],
|
||||
},
|
||||
resolveLoader: {
|
||||
plugins: [
|
||||
// Also related to Plug'n'Play, but this time it tells Webpack to load its loaders
|
||||
// from the current package.
|
||||
PnpWebpackPlugin.moduleLoader(module),
|
||||
],
|
||||
},
|
||||
module: {
|
||||
strictExportPresence: true,
|
||||
rules: [
|
||||
// TODO: Disable require.ensure as it's not a standard language feature.
|
||||
// We are waiting for https://github.com/facebookincubator/create-react-app/issues/2176.
|
||||
// { parser: { requireEnsure: false } },
|
||||
// Disable require.ensure as it's not a standard language feature.
|
||||
{ parser: { requireEnsure: false } },
|
||||
|
||||
// First, run the linter.
|
||||
// It's important to do this before Babel processes the JS.
|
||||
{
|
||||
test: /\.(js|jsx|mjs)$/,
|
||||
test: /\.(js|mjs|jsx)$/,
|
||||
enforce: 'pre',
|
||||
use: [
|
||||
{
|
||||
options: {
|
||||
formatter: eslintFormatter,
|
||||
formatter: require.resolve('react-dev-utils/eslintFormatter'),
|
||||
eslintPath: require.resolve('eslint'),
|
||||
|
||||
|
||||
},
|
||||
loader: require.resolve('eslint-loader'),
|
||||
},
|
||||
@@ -136,16 +210,62 @@ module.exports = {
|
||||
name: 'static/media/[name].[hash:8].[ext]',
|
||||
},
|
||||
},
|
||||
// Process JS with Babel.
|
||||
// Process application JS with Babel.
|
||||
// The preset includes JSX, Flow, and some ESnext features.
|
||||
{
|
||||
test: /\.(js|jsx|mjs)$/,
|
||||
test: /\.(js|mjs|jsx|ts|tsx)$/,
|
||||
include: paths.appSrc,
|
||||
loader: require.resolve('babel-loader'),
|
||||
options: {
|
||||
customize: require.resolve(
|
||||
'babel-preset-react-app/webpack-overrides'
|
||||
),
|
||||
|
||||
plugins: [
|
||||
[
|
||||
require.resolve('babel-plugin-named-asset-import'),
|
||||
{
|
||||
loaderMap: {
|
||||
svg: {
|
||||
ReactComponent: '@svgr/webpack?-prettier,-svgo![path]',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
// This is a feature of `babel-loader` for webpack (not Babel itself).
|
||||
// It enables caching results in ./node_modules/.cache/babel-loader/
|
||||
// directory for faster rebuilds.
|
||||
cacheDirectory: true,
|
||||
// Don't waste time on Gzipping the cache
|
||||
cacheCompression: false,
|
||||
},
|
||||
},
|
||||
// Process any JS outside of the app with Babel.
|
||||
// Unlike the application JS, we only compile the standard ES features.
|
||||
{
|
||||
test: /\.(js|mjs)$/,
|
||||
exclude: /@babel(?:\/|\\{1,2})runtime/,
|
||||
loader: require.resolve('babel-loader'),
|
||||
options: {
|
||||
babelrc: false,
|
||||
configFile: false,
|
||||
compact: false,
|
||||
presets: [
|
||||
[
|
||||
require.resolve('babel-preset-react-app/dependencies'),
|
||||
{ helpers: true },
|
||||
],
|
||||
],
|
||||
cacheDirectory: true,
|
||||
// Don't waste time on Gzipping the cache
|
||||
cacheCompression: false,
|
||||
|
||||
// If an error happens in a package, it's possible to be
|
||||
// because it was compiled. Thus, we don't want the browser
|
||||
// debugger to show the original code. Instead, the code
|
||||
// being evaluated would be much more helpful.
|
||||
sourceMaps: false,
|
||||
},
|
||||
},
|
||||
// "postcss" loader applies autoprefixer to our CSS.
|
||||
@@ -153,37 +273,46 @@ module.exports = {
|
||||
// "style" loader turns CSS into JS modules that inject <style> tags.
|
||||
// In production, we use a plugin to extract that CSS to a file, but
|
||||
// in development "style" loader enables hot editing of CSS.
|
||||
// By default we support CSS Modules with the extension .module.css
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
require.resolve('style-loader'),
|
||||
test: cssRegex,
|
||||
exclude: cssModuleRegex,
|
||||
use: getStyleLoaders({
|
||||
importLoaders: 1,
|
||||
}),
|
||||
},
|
||||
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
|
||||
// using the extension .module.css
|
||||
{
|
||||
test: cssModuleRegex,
|
||||
use: getStyleLoaders({
|
||||
importLoaders: 1,
|
||||
modules: true,
|
||||
getLocalIdent: getCSSModuleLocalIdent,
|
||||
}),
|
||||
},
|
||||
// Opt-in support for SASS (using .scss or .sass extensions).
|
||||
// Chains the sass-loader with the css-loader and the style-loader
|
||||
// to immediately apply all styles to the DOM.
|
||||
// By default we support SASS Modules with the
|
||||
// extensions .module.scss or .module.sass
|
||||
{
|
||||
test: sassRegex,
|
||||
exclude: sassModuleRegex,
|
||||
use: getStyleLoaders({ importLoaders: 2 }, 'sass-loader'),
|
||||
},
|
||||
// Adds support for CSS Modules, but using SASS
|
||||
// using the extension .module.scss or .module.sass
|
||||
{
|
||||
test: sassModuleRegex,
|
||||
use: getStyleLoaders(
|
||||
{
|
||||
loader: require.resolve('css-loader'),
|
||||
options: {
|
||||
importLoaders: 1,
|
||||
},
|
||||
importLoaders: 2,
|
||||
modules: true,
|
||||
getLocalIdent: getCSSModuleLocalIdent,
|
||||
},
|
||||
{
|
||||
loader: require.resolve('postcss-loader'),
|
||||
options: {
|
||||
// Necessary for external CSS imports to work
|
||||
// https://github.com/facebookincubator/create-react-app/issues/2677
|
||||
ident: 'postcss',
|
||||
plugins: () => [
|
||||
require('postcss-flexbugs-fixes'),
|
||||
autoprefixer({
|
||||
browsers: [
|
||||
'>1%',
|
||||
'last 4 versions',
|
||||
'Firefox ESR',
|
||||
'not ie < 9', // React doesn't support IE8 anyway
|
||||
],
|
||||
flexbox: 'no-2009',
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
'sass-loader'
|
||||
),
|
||||
},
|
||||
// "file" loader makes sure those assets get served by WebpackDevServer.
|
||||
// When you `import` an asset, you get its (virtual) filename.
|
||||
@@ -192,10 +321,10 @@ module.exports = {
|
||||
// that fall through the other loaders.
|
||||
{
|
||||
// Exclude `js` files to keep "css" loader working as it injects
|
||||
// it's runtime that would otherwise processed through "file" loader.
|
||||
// its runtime that would otherwise be processed through "file" loader.
|
||||
// Also exclude `html` and `json` extensions so they get processed
|
||||
// by webpacks internal loaders.
|
||||
exclude: [/\.js$/, /\.html$/, /\.json$/],
|
||||
exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
|
||||
loader: require.resolve('file-loader'),
|
||||
options: {
|
||||
name: 'static/media/[name].[hash:8].[ext]',
|
||||
@@ -208,18 +337,19 @@ module.exports = {
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
// Makes some environment variables available in index.html.
|
||||
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
|
||||
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
// In development, this will be an empty string.
|
||||
new InterpolateHtmlPlugin(env.raw),
|
||||
// Generates an `index.html` file with the <script> injected.
|
||||
new HtmlWebpackPlugin({
|
||||
inject: true,
|
||||
template: paths.appHtml,
|
||||
}),
|
||||
// Add module names to factory functions so they appear in browser profiler.
|
||||
new webpack.NamedModulesPlugin(),
|
||||
// Makes some environment variables available in index.html.
|
||||
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
|
||||
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
// In development, this will be an empty string.
|
||||
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
|
||||
// This gives some necessary context to module not found errors, such as
|
||||
// the requesting resource.
|
||||
new ModuleNotFoundPlugin(paths.appPath),
|
||||
// Makes some environment variables available to the JS code, for example:
|
||||
// if (process.env.NODE_ENV === 'development') { ... }. See `./env.js`.
|
||||
new webpack.DefinePlugin(env.stringified),
|
||||
@@ -227,12 +357,12 @@ module.exports = {
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
// Watcher doesn't work well if you mistype casing in a path so we use
|
||||
// a plugin that prints an error when you attempt to do this.
|
||||
// See https://github.com/facebookincubator/create-react-app/issues/240
|
||||
// See https://github.com/facebook/create-react-app/issues/240
|
||||
new CaseSensitivePathsPlugin(),
|
||||
// If you require a missing module and then `npm install` it, you still have
|
||||
// to restart the development server for Webpack to discover it. This plugin
|
||||
// makes the discovery automatic so you don't have to restart.
|
||||
// See https://github.com/facebookincubator/create-react-app/issues/186
|
||||
// See https://github.com/facebook/create-react-app/issues/186
|
||||
new WatchMissingNodeModulesPlugin(paths.appNodeModules),
|
||||
// Moment.js is an extremely popular library that bundles large locale files
|
||||
// by default due to how Webpack interprets its code. This is a practical
|
||||
@@ -240,7 +370,44 @@ module.exports = {
|
||||
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
|
||||
// You can remove this if you don't use Moment.js:
|
||||
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
|
||||
],
|
||||
// Generate a manifest file which contains a mapping of all asset filenames
|
||||
// to their corresponding output file so that tools can pick it up without
|
||||
// having to parse `index.html`.
|
||||
new ManifestPlugin({
|
||||
fileName: 'asset-manifest.json',
|
||||
publicPath: publicPath,
|
||||
}),
|
||||
// TypeScript type checking
|
||||
useTypeScript &&
|
||||
new ForkTsCheckerWebpackPlugin({
|
||||
typescript: resolve.sync('typescript', {
|
||||
basedir: paths.appNodeModules,
|
||||
}),
|
||||
async: false,
|
||||
checkSyntacticErrors: true,
|
||||
tsconfig: paths.appTsConfig,
|
||||
compilerOptions: {
|
||||
module: 'esnext',
|
||||
moduleResolution: 'node',
|
||||
resolveJsonModule: true,
|
||||
isolatedModules: true,
|
||||
noEmit: true,
|
||||
jsx: 'preserve',
|
||||
},
|
||||
reportFiles: [
|
||||
'**',
|
||||
'!**/*.json',
|
||||
'!**/__tests__/**',
|
||||
'!**/?(*.)(spec|test).*',
|
||||
'!src/setupProxy.js',
|
||||
'!src/setupTests.*',
|
||||
],
|
||||
watch: paths.appSrc,
|
||||
silent: true,
|
||||
formatter: typescriptFormatter,
|
||||
}),
|
||||
].filter(Boolean),
|
||||
|
||||
// Some libraries import Node modules but don't use them in the browser.
|
||||
// Tell Webpack to provide empty mocks for them so importing them works.
|
||||
node: {
|
||||
@@ -250,10 +417,7 @@ module.exports = {
|
||||
tls: 'empty',
|
||||
child_process: 'empty',
|
||||
},
|
||||
// Turn off performance hints during development because we don't do any
|
||||
// splitting or minification in interest of speed. These warnings become
|
||||
// cumbersome.
|
||||
performance: {
|
||||
hints: false,
|
||||
},
|
||||
// Turn off performance processing because we utilize
|
||||
// our own hints via the FileSizeReporter
|
||||
performance: false,
|
||||
};
|
||||
|
||||
@@ -1,13 +1,29 @@
|
||||
'use strict';
|
||||
|
||||
const autoprefixer = require('autoprefixer');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
const eslintFormatter = require('react-dev-utils/eslintFormatter');
|
||||
const resolve = require('resolve');
|
||||
const PnpWebpackPlugin = require('pnp-webpack-plugin');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
||||
const safePostCssParser = require('postcss-safe-parser');
|
||||
const ManifestPlugin = require('webpack-manifest-plugin');
|
||||
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
|
||||
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
|
||||
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
|
||||
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
|
||||
const paths = require('./paths');
|
||||
const getClientEnvironment = require('./env');
|
||||
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
|
||||
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin-alt');
|
||||
const typescriptFormatter = require('react-dev-utils/typescriptFormatter');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
const getPackageJson = require('./getPackageJson');
|
||||
|
||||
|
||||
// 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.
|
||||
@@ -17,6 +33,9 @@ const publicPath = paths.servedPath;
|
||||
const shouldUseRelativeAssetPaths = publicPath === './';
|
||||
// Source maps are resource heavy and can cause out of memory issue for large source files.
|
||||
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
|
||||
// Some apps do not need the benefits of saving a web request, so not inlining the chunk
|
||||
// makes for a smoother build process.
|
||||
const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false';
|
||||
// `publicUrl` is just like `publicPath`, but we will provide it to our app
|
||||
// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
|
||||
// Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz.
|
||||
@@ -30,90 +49,255 @@ if (env.stringified['process.env'].NODE_ENV !== '"production"') {
|
||||
throw new Error('Production builds must have NODE_ENV=production.');
|
||||
}
|
||||
|
||||
// Note: defined here because it will be used more than once.
|
||||
const cssFilename = 'css/index.css';
|
||||
// Check if TypeScript is setup
|
||||
const useTypeScript = fs.existsSync(paths.appTsConfig);
|
||||
|
||||
// ExtractTextPlugin expects the build output to be flat.
|
||||
// (See https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/27)
|
||||
// However, our output is structured with css, js and media folders.
|
||||
// To have this structure working with relative paths, we have to use custom options.
|
||||
const extractTextPluginOptions = shouldUseRelativeAssetPaths
|
||||
? // Making sure that the publicPath goes back to to build folder.
|
||||
{ publicPath: Array(cssFilename.split('/').length).join('../') }
|
||||
: {};
|
||||
// style files regexes
|
||||
const cssRegex = /\.css$/;
|
||||
const cssModuleRegex = /\.module\.css$/;
|
||||
const sassRegex = /\.(scss|sass)$/;
|
||||
const sassModuleRegex = /\.module\.(scss|sass)$/;
|
||||
|
||||
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.
|
||||
`;
|
||||
|
||||
// common function to get style loaders
|
||||
const getStyleLoaders = (cssOptions, preProcessor) => {
|
||||
const loaders = [
|
||||
{
|
||||
loader: MiniCssExtractPlugin.loader,
|
||||
options: Object.assign(
|
||||
{},
|
||||
shouldUseRelativeAssetPaths ? { publicPath: '../../' } : undefined
|
||||
),
|
||||
},
|
||||
{
|
||||
loader: require.resolve('css-loader'),
|
||||
options: cssOptions,
|
||||
},
|
||||
{
|
||||
// Options for PostCSS as we reference these options twice
|
||||
// Adds vendor prefixing based on your specified browser support in
|
||||
// package.json
|
||||
loader: require.resolve('postcss-loader'),
|
||||
options: {
|
||||
// Necessary for external CSS imports to work
|
||||
// https://github.com/facebook/create-react-app/issues/2677
|
||||
ident: 'postcss',
|
||||
plugins: () => [
|
||||
require('postcss-flexbugs-fixes'),
|
||||
require('postcss-preset-env')({
|
||||
autoprefixer: {
|
||||
flexbox: 'no-2009',
|
||||
},
|
||||
stage: 3,
|
||||
}),
|
||||
],
|
||||
sourceMap: shouldUseSourceMap,
|
||||
},
|
||||
},
|
||||
];
|
||||
if (preProcessor) {
|
||||
loaders.push({
|
||||
loader: require.resolve(preProcessor),
|
||||
options: {
|
||||
sourceMap: shouldUseSourceMap,
|
||||
},
|
||||
});
|
||||
}
|
||||
return loaders;
|
||||
};
|
||||
|
||||
// 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.
|
||||
module.exports = {
|
||||
mode: 'production',
|
||||
// Don't attempt to continue if there are any errors.
|
||||
bail: true,
|
||||
// We generate sourcemaps in production. This is slow but gives good results.
|
||||
// You can exclude the *.map files from the build during deployment.
|
||||
devtool: shouldUseSourceMap ? 'source-map' : false,
|
||||
// In production, we only want to load the app code.
|
||||
entry: [paths.appLibIndexJs], // CRL: library index file instead of app index
|
||||
entry: [paths.appLibIndexJs],
|
||||
output: {
|
||||
// CRL: Updated whole block with library specific info
|
||||
// The build folder.
|
||||
path: paths.appBuild,
|
||||
// Generated JS file names (with nested folders).
|
||||
// There will be one main bundle, and one file per asynchronous chunk.
|
||||
// We don't currently advertise code splitting but Webpack supports it.
|
||||
filename: 'index.js',
|
||||
chunkFilename: 'index.[chunkhash:8].chunk.js',
|
||||
// We inferred the "public path" (such as / or /my-project) from homepage.
|
||||
publicPath: publicPath,
|
||||
library: "SimpleKeyboard",
|
||||
libraryTarget: 'umd',
|
||||
library: 'SimpleKeyboard'
|
||||
umdNamedDefine: true,
|
||||
// Point sourcemap entries to original disk location (format as URL on Windows)
|
||||
devtoolModuleFilenameTemplate: info =>
|
||||
path
|
||||
.relative(paths.appSrcLib, info.absoluteResourcePath)
|
||||
.replace(/\\/g, '/'),
|
||||
},
|
||||
optimization: {
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
terserOptions: {
|
||||
parse: {
|
||||
// we want terser to parse ecma 8 code. However, we don't want it
|
||||
// to apply any minfication steps that turns valid ecma 5 code
|
||||
// into invalid ecma 5 code. This is why the 'compress' and 'output'
|
||||
// sections only apply transformations that are ecma 5 safe
|
||||
// https://github.com/facebook/create-react-app/pull/4234
|
||||
ecma: 8,
|
||||
},
|
||||
compress: {
|
||||
ecma: 5,
|
||||
warnings: false,
|
||||
// Disabled because of an issue with Uglify breaking seemingly valid code:
|
||||
// https://github.com/facebook/create-react-app/issues/2376
|
||||
// Pending further investigation:
|
||||
// https://github.com/mishoo/UglifyJS2/issues/2011
|
||||
comparisons: false,
|
||||
// Disabled because of an issue with Terser breaking valid code:
|
||||
// https://github.com/facebook/create-react-app/issues/5250
|
||||
// Pending futher investigation:
|
||||
// https://github.com/terser-js/terser/issues/120
|
||||
inline: 2,
|
||||
},
|
||||
mangle: {
|
||||
safari10: true,
|
||||
//keep_classnames: true,
|
||||
//keep_fnames: true,
|
||||
module: true
|
||||
},
|
||||
output: {
|
||||
ecma: 5,
|
||||
comments: false,
|
||||
// Turned on because emoji and regex is not minified properly using default
|
||||
// https://github.com/facebook/create-react-app/issues/2488
|
||||
ascii_only: true,
|
||||
},
|
||||
},
|
||||
// Use multi-process parallel running to improve the build speed
|
||||
// Default number of concurrent runs: os.cpus().length - 1
|
||||
parallel: true,
|
||||
// Enable file caching
|
||||
cache: true,
|
||||
sourceMap: shouldUseSourceMap,
|
||||
}),
|
||||
new webpack.BannerPlugin({
|
||||
banner: banner,
|
||||
entryOnly: true
|
||||
}),
|
||||
new OptimizeCSSAssetsPlugin({
|
||||
cssProcessorOptions: {
|
||||
parser: safePostCssParser,
|
||||
map: shouldUseSourceMap
|
||||
? {
|
||||
// `inline: false` forces the sourcemap to be output into a
|
||||
// separate file
|
||||
inline: false,
|
||||
// `annotation: true` appends the sourceMappingURL to the end of
|
||||
// the css file, helping the browser find the sourcemap
|
||||
annotation: true,
|
||||
}
|
||||
: false,
|
||||
},
|
||||
}),
|
||||
],
|
||||
// Automatically split vendor and commons
|
||||
// https://twitter.com/wSokra/status/969633336732905474
|
||||
// https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366
|
||||
splitChunks: {
|
||||
//chunks: 'all',
|
||||
cacheGroups: {
|
||||
default: false,
|
||||
}
|
||||
},
|
||||
// Keep the runtime chunk seperated to enable long term caching
|
||||
// https://twitter.com/wSokra/status/969679223278505985
|
||||
runtimeChunk: false,
|
||||
},
|
||||
resolve: {
|
||||
// This allows you to set a fallback for where Webpack should look for modules.
|
||||
// We placed these paths second because we want `node_modules` to "win"
|
||||
// if there are any conflicts. This matches Node resolution mechanism.
|
||||
// https://github.com/facebookincubator/create-react-app/issues/253
|
||||
modules: ['node_modules', paths.appNodeModules].concat(
|
||||
// https://github.com/facebook/create-react-app/issues/253
|
||||
modules: ['node_modules'].concat(
|
||||
// It is guaranteed to exist because we tweak it in `env.js`
|
||||
process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
|
||||
),
|
||||
// These are the reasonable defaults supported by the Node ecosystem.
|
||||
// We also include JSX as a common component filename extension to support
|
||||
// some tools, although we do not recommend using it, see:
|
||||
// https://github.com/facebookincubator/create-react-app/issues/290
|
||||
// https://github.com/facebook/create-react-app/issues/290
|
||||
// `web` extension prefixes have been added for better support
|
||||
// for React Native Web.
|
||||
extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx'],
|
||||
extensions: paths.moduleFileExtensions
|
||||
.map(ext => `.${ext}`)
|
||||
.filter(ext => useTypeScript || !ext.includes('ts')),
|
||||
alias: {
|
||||
|
||||
// Support React Native Web
|
||||
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
|
||||
'react-native': 'react-native-web',
|
||||
},
|
||||
plugins: [
|
||||
// Adds support for installing with Plug'n'Play, leading to faster installs and adding
|
||||
// guards against forgotten dependencies and such.
|
||||
PnpWebpackPlugin,
|
||||
// Prevents users from importing files from outside of src/ (or node_modules/).
|
||||
// This often causes confusion because we only process files within src/ with babel.
|
||||
// To fix this, we prevent you from importing files out of src/ -- if you'd like to,
|
||||
// please link the files into your node_modules/ and let module-resolution kick in.
|
||||
// Make sure your source files are compiled, as they will not be processed in any way.
|
||||
new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
|
||||
new ModuleScopePlugin(paths.appSrcLib, [paths.appPackageJson]),
|
||||
],
|
||||
},
|
||||
resolveLoader: {
|
||||
plugins: [
|
||||
// Also related to Plug'n'Play, but this time it tells Webpack to load its loaders
|
||||
// from the current package.
|
||||
PnpWebpackPlugin.moduleLoader(module),
|
||||
],
|
||||
},
|
||||
module: {
|
||||
strictExportPresence: true,
|
||||
rules: [
|
||||
// TODO: Disable require.ensure as it's not a standard language feature.
|
||||
// We are waiting for https://github.com/facebookincubator/create-react-app/issues/2176.
|
||||
// { parser: { requireEnsure: false } },
|
||||
// Disable require.ensure as it's not a standard language feature.
|
||||
{ parser: { requireEnsure: false } },
|
||||
|
||||
// First, run the linter.
|
||||
// It's important to do this before Babel processes the JS.
|
||||
{
|
||||
test: /\.(js|jsx|mjs)$/,
|
||||
test: /\.(js|mjs|jsx)$/,
|
||||
enforce: 'pre',
|
||||
use: [
|
||||
{
|
||||
options: {
|
||||
formatter: eslintFormatter,
|
||||
formatter: require.resolve('react-dev-utils/eslintFormatter'),
|
||||
eslintPath: require.resolve('eslint'),
|
||||
|
||||
|
||||
},
|
||||
loader: require.resolve('eslint-loader'),
|
||||
},
|
||||
],
|
||||
include: paths.appLibSrc, // CRL: updated with library src folder
|
||||
include: paths.appSrcLib,
|
||||
},
|
||||
{
|
||||
// "oneOf" will traverse all following loaders until one will
|
||||
@@ -127,77 +311,129 @@ module.exports = {
|
||||
loader: require.resolve('url-loader'),
|
||||
options: {
|
||||
limit: 10000,
|
||||
name: 'media/[name].[ext]',
|
||||
name: 'static/media/[name].[hash:8].[ext]',
|
||||
},
|
||||
},
|
||||
// Process JS with Babel.
|
||||
// Process application JS with Babel.
|
||||
// The preset includes JSX, Flow, TypeScript and some ESnext features.
|
||||
{
|
||||
test: /\.(js|jsx|mjs)$/,
|
||||
include: paths.appLibSrc, // CRL: updated with library src folder
|
||||
test: /\.(js|mjs|jsx|ts|tsx)$/,
|
||||
include: paths.appSrcLib,
|
||||
|
||||
loader: require.resolve('babel-loader'),
|
||||
options: {
|
||||
|
||||
customize: require.resolve(
|
||||
'babel-preset-react-app/webpack-overrides'
|
||||
),
|
||||
|
||||
plugins: [
|
||||
[
|
||||
require.resolve('babel-plugin-named-asset-import'),
|
||||
{
|
||||
loaderMap: {
|
||||
svg: {
|
||||
ReactComponent: '@svgr/webpack?-prettier,-svgo![path]',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
cacheDirectory: true,
|
||||
// Save disk space when time isn't as important
|
||||
cacheCompression: true,
|
||||
compact: true,
|
||||
},
|
||||
},
|
||||
// The notation here is somewhat confusing.
|
||||
// Process any JS outside of the app with Babel.
|
||||
// Unlike the application JS, we only compile the standard ES features.
|
||||
{
|
||||
test: /\.(js|mjs)$/,
|
||||
exclude: /@babel(?:\/|\\{1,2})runtime/,
|
||||
loader: require.resolve('babel-loader'),
|
||||
options: {
|
||||
babelrc: false,
|
||||
configFile: false,
|
||||
compact: false,
|
||||
presets: [
|
||||
[
|
||||
require.resolve('babel-preset-react-app/dependencies'),
|
||||
{ helpers: true },
|
||||
],
|
||||
],
|
||||
cacheDirectory: true,
|
||||
// Save disk space when time isn't as important
|
||||
cacheCompression: true,
|
||||
|
||||
// If an error happens in a package, it's possible to be
|
||||
// because it was compiled. Thus, we don't want the browser
|
||||
// debugger to show the original code. Instead, the code
|
||||
// being evaluated would be much more helpful.
|
||||
sourceMaps: false,
|
||||
},
|
||||
},
|
||||
// "postcss" loader applies autoprefixer to our CSS.
|
||||
// "css" loader resolves paths in CSS and adds assets as dependencies.
|
||||
// "style" loader normally turns CSS into JS modules injecting <style>,
|
||||
// but unlike in development configuration, we do something different.
|
||||
// `ExtractTextPlugin` first applies the "postcss" and "css" loaders
|
||||
// (second argument), then grabs the result CSS and puts it into a
|
||||
// separate file in our build process. This way we actually ship
|
||||
// a single CSS file in production instead of JS code injecting <style>
|
||||
// tags. If you use code splitting, however, any async bundles will still
|
||||
// use the "style" loader inside the async code so CSS from them won't be
|
||||
// in the main CSS file.
|
||||
// `MiniCSSExtractPlugin` extracts styles into CSS
|
||||
// files. If you use code splitting, async bundles will have their own separate CSS chunk file.
|
||||
// By default we support CSS Modules with the extension .module.css
|
||||
{
|
||||
test: /\.css$/,
|
||||
loader: ExtractTextPlugin.extract(
|
||||
Object.assign(
|
||||
{
|
||||
fallback: {
|
||||
loader: require.resolve('style-loader'),
|
||||
options: {
|
||||
hmr: false,
|
||||
},
|
||||
},
|
||||
use: [
|
||||
{
|
||||
loader: require.resolve('css-loader'),
|
||||
options: {
|
||||
importLoaders: 1,
|
||||
minimize: true,
|
||||
sourceMap: shouldUseSourceMap,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: require.resolve('postcss-loader'),
|
||||
options: {
|
||||
// Necessary for external CSS imports to work
|
||||
// https://github.com/facebookincubator/create-react-app/issues/2677
|
||||
ident: 'postcss',
|
||||
plugins: () => [
|
||||
require('postcss-flexbugs-fixes'),
|
||||
autoprefixer({
|
||||
browsers: [
|
||||
'>1%',
|
||||
'last 4 versions',
|
||||
'Firefox ESR',
|
||||
'not ie < 9', // React doesn't support IE8 anyway
|
||||
],
|
||||
flexbox: 'no-2009',
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
extractTextPluginOptions
|
||||
)
|
||||
test: cssRegex,
|
||||
exclude: cssModuleRegex,
|
||||
loader: getStyleLoaders({
|
||||
importLoaders: 1,
|
||||
sourceMap: shouldUseSourceMap,
|
||||
}),
|
||||
// Don't consider CSS imports dead code even if the
|
||||
// containing package claims to have no side effects.
|
||||
// Remove this when webpack adds a warning or an error for this.
|
||||
// See https://github.com/webpack/webpack/issues/6571
|
||||
sideEffects: true,
|
||||
},
|
||||
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
|
||||
// using the extension .module.css
|
||||
{
|
||||
test: cssModuleRegex,
|
||||
loader: getStyleLoaders({
|
||||
importLoaders: 1,
|
||||
sourceMap: shouldUseSourceMap,
|
||||
modules: true,
|
||||
getLocalIdent: getCSSModuleLocalIdent,
|
||||
}),
|
||||
},
|
||||
// Opt-in support for SASS. The logic here is somewhat similar
|
||||
// as in the CSS routine, except that "sass-loader" runs first
|
||||
// to compile SASS files into CSS.
|
||||
// By default we support SASS Modules with the
|
||||
// extensions .module.scss or .module.sass
|
||||
{
|
||||
test: sassRegex,
|
||||
exclude: sassModuleRegex,
|
||||
loader: getStyleLoaders(
|
||||
{
|
||||
importLoaders: 2,
|
||||
sourceMap: shouldUseSourceMap,
|
||||
},
|
||||
'sass-loader'
|
||||
),
|
||||
// Don't consider CSS imports dead code even if the
|
||||
// containing package claims to have no side effects.
|
||||
// Remove this when webpack adds a warning or an error for this.
|
||||
// See https://github.com/webpack/webpack/issues/6571
|
||||
sideEffects: true,
|
||||
},
|
||||
// Adds support for CSS Modules, but using SASS
|
||||
// using the extension .module.scss or .module.sass
|
||||
{
|
||||
test: sassModuleRegex,
|
||||
loader: getStyleLoaders(
|
||||
{
|
||||
importLoaders: 2,
|
||||
sourceMap: shouldUseSourceMap,
|
||||
modules: true,
|
||||
getLocalIdent: getCSSModuleLocalIdent,
|
||||
},
|
||||
'sass-loader'
|
||||
),
|
||||
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
|
||||
},
|
||||
// "file" loader makes sure assets end up in the `build` folder.
|
||||
// When you `import` an asset, you get its filename.
|
||||
@@ -206,12 +442,12 @@ module.exports = {
|
||||
{
|
||||
loader: require.resolve('file-loader'),
|
||||
// Exclude `js` files to keep "css" loader working as it injects
|
||||
// it's runtime that would otherwise processed through "file" loader.
|
||||
// it's runtime that would otherwise be processed through "file" loader.
|
||||
// Also exclude `html` and `json` extensions so they get processed
|
||||
// by webpacks internal loaders.
|
||||
exclude: [/\.js$/, /\.html$/, /\.json$/],
|
||||
exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
|
||||
options: {
|
||||
name: 'media/[name].[ext]',
|
||||
name: 'static/media/[name].[hash:8].[ext]',
|
||||
},
|
||||
},
|
||||
// ** STOP ** Are you adding a new loader?
|
||||
@@ -221,48 +457,111 @@ module.exports = {
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
// Generates an `index.html` file with the <script> injected.
|
||||
/*new HtmlWebpackPlugin({
|
||||
inject: true,
|
||||
template: paths.appHtml,
|
||||
minify: {
|
||||
removeComments: true,
|
||||
collapseWhitespace: true,
|
||||
removeRedundantAttributes: true,
|
||||
useShortDoctype: true,
|
||||
removeEmptyAttributes: true,
|
||||
removeStyleLinkTypeAttributes: true,
|
||||
keepClosingSlash: true,
|
||||
minifyJS: true,
|
||||
minifyCSS: true,
|
||||
minifyURLs: true,
|
||||
},
|
||||
}),*/
|
||||
// Inlines the webpack runtime script. This script is too small to warrant
|
||||
// a network request.
|
||||
shouldInlineRuntimeChunk &&
|
||||
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime~.+[.]js/]),
|
||||
// Makes some environment variables available in index.html.
|
||||
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
|
||||
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
// In production, it will be an empty string unless you specify "homepage"
|
||||
// in `package.json`, in which case it will be the pathname of that URL.
|
||||
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
|
||||
// This gives some necessary context to module not found errors, such as
|
||||
// the requesting resource.
|
||||
new ModuleNotFoundPlugin(paths.appPath),
|
||||
// Makes some environment variables available to the JS code, for example:
|
||||
// if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`.
|
||||
// It is absolutely essential that NODE_ENV was set to production here.
|
||||
// Otherwise React will be compiled in the very slow development mode.
|
||||
new webpack.DefinePlugin(env.stringified),
|
||||
// Minify the code.
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
compress: {
|
||||
warnings: false,
|
||||
// Disabled because of an issue with Uglify breaking seemingly valid code:
|
||||
// https://github.com/facebookincubator/create-react-app/issues/2376
|
||||
// Pending further investigation:
|
||||
// https://github.com/mishoo/UglifyJS2/issues/2011
|
||||
comparisons: false,
|
||||
},
|
||||
mangle: {
|
||||
safari10: true,
|
||||
},
|
||||
output: {
|
||||
comments: false,
|
||||
// Turned on because emoji and regex is not minified properly using default
|
||||
// https://github.com/facebookincubator/create-react-app/issues/2488
|
||||
ascii_only: true,
|
||||
},
|
||||
sourceMap: shouldUseSourceMap,
|
||||
}),
|
||||
// Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`.
|
||||
new ExtractTextPlugin({
|
||||
filename: cssFilename,
|
||||
new MiniCssExtractPlugin({
|
||||
// Options similar to the same options in webpackOptions.output
|
||||
// both options are optional
|
||||
filename: 'css/index.css',
|
||||
chunkFilename: 'css/index.[contenthash:8].chunk.css',
|
||||
}),
|
||||
// Generate a manifest file which contains a mapping of all asset filenames
|
||||
// to their corresponding output file so that tools can pick it up without
|
||||
// having to parse `index.html`.
|
||||
/*new ManifestPlugin({
|
||||
fileName: 'asset-manifest.json',
|
||||
publicPath: publicPath,
|
||||
}),*/
|
||||
// Moment.js is an extremely popular library that bundles large locale files
|
||||
// by default due to how Webpack interprets its code. This is a practical
|
||||
// solution that requires the user to opt into importing specific locales.
|
||||
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
|
||||
// You can remove this if you don't use Moment.js:
|
||||
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
|
||||
],
|
||||
// CRL: added externals block for library
|
||||
externals: {
|
||||
'react': 'react',
|
||||
'react-dom': 'react-dom'
|
||||
},
|
||||
new CopyWebpackPlugin([
|
||||
{
|
||||
from: `${paths.appSrcLibTypes}`,
|
||||
to: paths.appLayoutsBuild
|
||||
}
|
||||
]),
|
||||
// Generate a service worker script that will precache, and keep up to date,
|
||||
// the HTML & assets that are part of the Webpack build.
|
||||
/*new WorkboxWebpackPlugin.GenerateSW({
|
||||
clientsClaim: true,
|
||||
exclude: [/\.map$/, /asset-manifest\.json$/],
|
||||
importWorkboxFrom: 'cdn',
|
||||
navigateFallback: publicUrl + '/index.html',
|
||||
navigateFallbackBlacklist: [
|
||||
// Exclude URLs starting with /_, as they're likely an API call
|
||||
new RegExp('^/_'),
|
||||
// Exclude URLs containing a dot, as they're likely a resource in
|
||||
// public/ and not a SPA route
|
||||
new RegExp('/[^/]+\\.[^/]+$'),
|
||||
],
|
||||
}),*/
|
||||
// TypeScript type checking
|
||||
fs.existsSync(paths.appTsConfig) &&
|
||||
new ForkTsCheckerWebpackPlugin({
|
||||
typescript: resolve.sync('typescript', {
|
||||
basedir: paths.appNodeModules,
|
||||
}),
|
||||
async: false,
|
||||
checkSyntacticErrors: true,
|
||||
tsconfig: paths.appTsConfig,
|
||||
compilerOptions: {
|
||||
module: 'esnext',
|
||||
moduleResolution: 'node',
|
||||
resolveJsonModule: true,
|
||||
isolatedModules: true,
|
||||
noEmit: true,
|
||||
jsx: 'preserve',
|
||||
},
|
||||
reportFiles: [
|
||||
'**',
|
||||
'!**/*.json',
|
||||
'!**/__tests__/**',
|
||||
'!**/?(*.)(spec|test).*',
|
||||
'!src/setupProxy.js',
|
||||
'!src/setupTests.*',
|
||||
],
|
||||
watch: paths.appSrcLib,
|
||||
silent: true,
|
||||
formatter: typescriptFormatter,
|
||||
}),
|
||||
].filter(Boolean),
|
||||
// Some libraries import Node modules but don't use them in the browser.
|
||||
// Tell Webpack to provide empty mocks for them so importing them works.
|
||||
node: {
|
||||
@@ -272,4 +571,7 @@ module.exports = {
|
||||
tls: 'empty',
|
||||
child_process: 'empty',
|
||||
},
|
||||
// Turn off performance processing because we utilize
|
||||
// our own hints via the FileSizeReporter
|
||||
performance: false,
|
||||
};
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
const errorOverlayMiddleware = require('react-dev-utils/errorOverlayMiddleware');
|
||||
const evalSourceMapMiddleware = require('react-dev-utils/evalSourceMapMiddleware');
|
||||
const noopServiceWorkerMiddleware = require('react-dev-utils/noopServiceWorkerMiddleware');
|
||||
const path = require('path');
|
||||
const ignoredFiles = require('react-dev-utils/ignoredFiles');
|
||||
const config = require('./webpack.config.dev');
|
||||
const paths = require('./paths');
|
||||
const fs = require('fs');
|
||||
|
||||
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
|
||||
const host = process.env.HOST || '0.0.0.0';
|
||||
@@ -17,8 +19,8 @@ module.exports = function(proxy, allowedHost) {
|
||||
// https://medium.com/webpack/webpack-dev-server-middleware-security-issues-1489d950874a
|
||||
// However, it made several existing use cases such as development in cloud
|
||||
// environment or subdomains in development significantly more complicated:
|
||||
// https://github.com/facebookincubator/create-react-app/issues/2271
|
||||
// https://github.com/facebookincubator/create-react-app/issues/2233
|
||||
// https://github.com/facebook/create-react-app/issues/2271
|
||||
// https://github.com/facebook/create-react-app/issues/2233
|
||||
// While we're investigating better solutions, for now we will take a
|
||||
// compromise. Since our WDS configuration only serves files in the `public`
|
||||
// folder we won't consider accessing them a vulnerability. However, if you
|
||||
@@ -61,39 +63,42 @@ module.exports = function(proxy, allowedHost) {
|
||||
// as we specified in the config. In development, we always serve from /.
|
||||
publicPath: config.output.publicPath,
|
||||
// WebpackDevServer is noisy by default so we emit custom message instead
|
||||
// by listening to the compiler events with `compiler.plugin` calls above.
|
||||
// by listening to the compiler events with `compiler.hooks[...].tap` calls above.
|
||||
quiet: true,
|
||||
// Reportedly, this avoids CPU overload on some systems.
|
||||
// https://github.com/facebookincubator/create-react-app/issues/293
|
||||
// https://github.com/facebook/create-react-app/issues/293
|
||||
// src/node_modules is not ignored to support absolute imports
|
||||
// https://github.com/facebookincubator/create-react-app/issues/1065
|
||||
// https://github.com/facebook/create-react-app/issues/1065
|
||||
watchOptions: {
|
||||
ignored: new RegExp(
|
||||
`^(?!${path
|
||||
.normalize(paths.appSrc + '/')
|
||||
.replace(/[\\]+/g, '\\\\')}).+[\\\\/]node_modules[\\\\/]`,
|
||||
'g'
|
||||
),
|
||||
ignored: ignoredFiles(paths.appSrc),
|
||||
},
|
||||
// Enable HTTPS if the HTTPS environment variable is set to 'true'
|
||||
https: protocol === 'https',
|
||||
host: host,
|
||||
host,
|
||||
overlay: false,
|
||||
historyApiFallback: {
|
||||
// Paths with dots should still use the history fallback.
|
||||
// See https://github.com/facebookincubator/create-react-app/issues/387.
|
||||
// See https://github.com/facebook/create-react-app/issues/387.
|
||||
disableDotRule: true,
|
||||
},
|
||||
public: allowedHost,
|
||||
proxy,
|
||||
before(app) {
|
||||
before(app, server) {
|
||||
if (fs.existsSync(paths.proxySetup)) {
|
||||
// This registers user provided middleware for proxy reasons
|
||||
require(paths.proxySetup)(app);
|
||||
}
|
||||
|
||||
// This lets us fetch source contents from webpack for the error overlay
|
||||
app.use(evalSourceMapMiddleware(server));
|
||||
// This lets us open files from the runtime error overlay.
|
||||
app.use(errorOverlayMiddleware());
|
||||
|
||||
// This service worker file is effectively a 'no-op' that will reset any
|
||||
// previous service worker registered for the same host:port combination.
|
||||
// We do this in development to avoid hitting the production cache if
|
||||
// it used the same host and port.
|
||||
// https://github.com/facebookincubator/create-react-app/issues/2272#issuecomment-302832432
|
||||
// https://github.com/facebook/create-react-app/issues/2272#issuecomment-302832432
|
||||
app.use(noopServiceWorkerMiddleware());
|
||||
},
|
||||
};
|
||||
|
||||
2802
docs/ast/source/.external-ecmascript.js.json
Normal file
13309
docs/ast/source/demo/App.js.json
Normal file
513
docs/ast/source/demo/index.js.json
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
168118
docs/ast/source/lib/components/Keyboard.js.json
Normal file
407
docs/ast/source/lib/index.js.json
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
2296
docs/ast/source/lib/services/KeyboardLayout.js.json
Normal file
22321
docs/ast/source/lib/services/PhysicalKeyboard.js.json
Normal file
84963
docs/ast/source/lib/services/Utilities.js.json
Normal file
17449
docs/ast/source/lib/tests/TestUtility.js.json
Normal file
17
docs/badge.svg
Normal 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 |
563
docs/class/src/demo/App.js~App.html
Normal 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 '<span><a href="file/src/demo/App.js.html#lineNumber7">simple-keyboard/src/demo/App.js</a></span>'</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>
|
||||
3563
docs/class/src/lib/components/Keyboard.js~SimpleKeyboard.html
Normal 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 '<span><a href="file/src/lib/services/KeyboardLayout.js.html#lineNumber4">simple-keyboard/src/lib/services/KeyboardLayout.js</a></span>'</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>
|
||||
@@ -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 '<span><a href="file/src/lib/services/PhysicalKeyboard.js.html#lineNumber4">simple-keyboard/src/lib/services/PhysicalKeyboard.js</a></span>'</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's "key.code" 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's "key.code" 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>
|
||||
1631
docs/class/src/lib/services/Utilities.js~Utilities.html
Normal file
482
docs/class/src/lib/tests/TestUtility.js~TestUtility.html
Normal 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 '<span><a href="file/src/lib/tests/TestUtility.js.html#lineNumber4">simple-keyboard/src/lib/tests/TestUtility.js</a></span>'</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'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'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
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"coverage": "100%",
|
||||
"expectCount": 78,
|
||||
"actualCount": 78,
|
||||
"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": 16,
|
||||
"actualCount": 16,
|
||||
"undocumentLines": []
|
||||
},
|
||||
"src/lib/tests/TestUtility.js": {
|
||||
"expectCount": 6,
|
||||
"actualCount": 6,
|
||||
"undocumentLines": []
|
||||
}
|
||||
}
|
||||
}
|
||||
83
docs/css/github.css
Normal 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
@@ -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
@@ -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;
|
||||
}
|
||||
132
docs/css/prettify-tomorrow.css
Normal 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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
143
docs/file/src/demo/App.js.html
Normal 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 '../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,
|
||||
physicalKeyboardHighlight: true,
|
||||
});
|
||||
|
||||
/**
|
||||
* Adding preview (demo only)
|
||||
*/
|
||||
document.querySelector('.simple-keyboard').insertAdjacentHTML('beforebegin', `
|
||||
<div class="simple-keyboard-preview">
|
||||
<textarea class="input"></textarea>
|
||||
</div>
|
||||
`);
|
||||
|
||||
document.querySelector('.input').addEventListener('input', (event) => {
|
||||
this.keyboard.setInput(event.target.value);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles shift functionality
|
||||
*/
|
||||
handleShiftButton = () => {
|
||||
let layoutName = this.layoutName;
|
||||
let shiftToggle = this.layoutName = layoutName === "default" ? "shift" : "default";
|
||||
|
||||
this.keyboard.setOptions({
|
||||
layoutName: shiftToggle
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Shift functionality
|
||||
*/
|
||||
if(button === "{lock}" || button === "{shift}")
|
||||
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>
|
||||
64
docs/file/src/demo/index.js.html
Normal 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 './App';
|
||||
|
||||
/**
|
||||
* 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>
|
||||
874
docs/file/src/lib/components/Keyboard.js.html
Normal file
@@ -0,0 +1,874 @@
|
||||
<!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 './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];
|
||||
|
||||
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 element’s maxlengthattribute.
|
||||
* @property {object} maxLength Restrains simple-keyboard’s individual inputs to a certain length. This should be used in addition to the input element’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 {boolean} preventMouseDownDefault Calling preventDefault for the mousedown events keeps the focus on the input.
|
||||
* @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 input’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 || "default";
|
||||
this.options.theme = this.options.theme || "hg-theme-default";
|
||||
this.options.inputName = this.options.inputName || "default";
|
||||
this.options.preventMouseDownDefault = this.options.preventMouseDownDefault === false ? false : true;
|
||||
|
||||
/**
|
||||
* @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.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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles clicks made to keyboard buttons
|
||||
* @param {string} button The button's layout name.
|
||||
*/
|
||||
handleButtonClicked(button){
|
||||
let debug = this.options.debug;
|
||||
|
||||
/**
|
||||
* Ignoring placeholder buttons
|
||||
*/
|
||||
if(button === '{//}')
|
||||
return false;
|
||||
|
||||
/**
|
||||
* Calling onKeyPress
|
||||
*/
|
||||
if(typeof this.options.onKeyPress === "function")
|
||||
this.options.onKeyPress(button);
|
||||
|
||||
if(!this.input[this.options.inputName])
|
||||
this.input[this.options.inputName] = '';
|
||||
|
||||
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] = this.utilities.getUpdatedInput(
|
||||
button, this.input[this.options.inputName], this.options, this.caretPosition, true
|
||||
);
|
||||
|
||||
if(debug)
|
||||
console.log('Input changed:', this.input);
|
||||
|
||||
/**
|
||||
* Enforce syncInstanceInputs, if set
|
||||
*/
|
||||
if(this.options.syncInstanceInputs)
|
||||
this.syncInstanceInputs(this.input);
|
||||
|
||||
/**
|
||||
* Calling onChange
|
||||
*/
|
||||
if(typeof this.options.onChange === "function")
|
||||
this.options.onChange(this.input[this.options.inputName]);
|
||||
}
|
||||
|
||||
if(debug){
|
||||
console.log("Key pressed:", 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(() => {
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles button mouseup
|
||||
*/
|
||||
handleButtonMouseUp(){
|
||||
this.isMouseHold = false;
|
||||
if(this.holdInteractionTimeout)
|
||||
clearTimeout(this.holdInteractionTimeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles button hold
|
||||
*/
|
||||
/* istanbul ignore next */
|
||||
handleButtonHold(button){
|
||||
if(this.holdInteractionTimeout)
|
||||
clearTimeout(this.holdInteractionTimeout);
|
||||
|
||||
/**
|
||||
* @type {object} Timeout dictating the speed of key hold iterations
|
||||
*/
|
||||
this.holdInteractionTimeout = setTimeout(() => {
|
||||
if(this.isMouseHold){
|
||||
this.handleButtonClicked(button);
|
||||
this.handleButtonHold(button);
|
||||
} else {
|
||||
clearTimeout(this.holdInteractionTimeout);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a command to all simple-keyboard instances (if you have several instances).
|
||||
*/
|
||||
syncInstanceInputs(){
|
||||
this.dispatch((instance) => {
|
||||
instance.replaceInput(this.input);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the keyboard’s input.
|
||||
* @param {string} [inputName] optional - the internal input to select
|
||||
*/
|
||||
clearInput(inputName){
|
||||
inputName = inputName || this.options.inputName;
|
||||
this.input[inputName] = '';
|
||||
|
||||
/**
|
||||
* Enforce syncInstanceInputs, if set
|
||||
*/
|
||||
if(this.options.syncInstanceInputs)
|
||||
this.syncInstanceInputs(this.input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the keyboard’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’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 => {
|
||||
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 = '';
|
||||
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['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(){
|
||||
/**
|
||||
* Only first instance should insall the caret handling events
|
||||
*/
|
||||
this.caretPosition = null;
|
||||
let simpleKeyboardInstances = window['SimpleKeyboardInstances'];
|
||||
|
||||
if(
|
||||
(
|
||||
simpleKeyboardInstances &&
|
||||
Object.keys(simpleKeyboardInstances)[0] === this.utilities.camelCase(this.keyboardDOMClass)
|
||||
) ||
|
||||
!simpleKeyboardInstances
|
||||
){
|
||||
if(this.options.debug){
|
||||
console.log(`Caret handling started (${this.keyboardDOMClass})`)
|
||||
}
|
||||
|
||||
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;
|
||||
if(event.target.tagName){
|
||||
targetTagName = event.target.tagName.toLowerCase();
|
||||
}
|
||||
|
||||
this.dispatch(instance => {
|
||||
if(instance.isMouseHold){
|
||||
instance.isMouseHold = false;
|
||||
}
|
||||
|
||||
if(
|
||||
(targetTagName === "textarea" ||
|
||||
targetTagName === "input") &&
|
||||
!instance.options.disableCaretPositioning
|
||||
){
|
||||
/**
|
||||
* Tracks current cursor position
|
||||
* As keys are pressed, text will be added/removed at that position within the input.
|
||||
*/
|
||||
instance.caretPosition = event.target.selectionStart;
|
||||
|
||||
if(instance.options.debug){
|
||||
console.log('Caret at: ', event.target.selectionStart, event.target.tagName.toLowerCase(), `(${instance.keyboardDOMClass})`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the callback function once simple-keyboard is rendered for the first time (on initialization).
|
||||
*/
|
||||
onInit(){
|
||||
if(this.options.debug){
|
||||
console.log(`${this.keyboardDOMClass} 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.getDefaultLayout();
|
||||
let useTouchEvents = this.options.useTouchEvents || false
|
||||
|
||||
/**
|
||||
* Account for buttonTheme, if set
|
||||
*/
|
||||
let buttonThemesParsed = {};
|
||||
if(Array.isArray(this.options.buttonTheme)){
|
||||
this.options.buttonTheme.forEach(themeObj => {
|
||||
if(themeObj.buttons && themeObj.class){
|
||||
let 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){
|
||||
// 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 {
|
||||
console.warn(`buttonTheme row is missing the "buttons" or the "class". 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) => {
|
||||
let rowArray = row.split(' ');
|
||||
|
||||
/**
|
||||
* Creating empty row
|
||||
*/
|
||||
var rowDOM = document.createElement('div');
|
||||
rowDOM.className += "hg-row";
|
||||
|
||||
/**
|
||||
* Iterating through each button in row
|
||||
*/
|
||||
rowArray.forEach((button, bIndex) => {
|
||||
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('div');
|
||||
buttonDOM.className += `hg-button ${fctBtnClass}${buttonThemeClass ? " "+buttonThemeClass : ""}`;
|
||||
|
||||
if (useTouchEvents) {
|
||||
buttonDOM.ontouchstart = (e) => {
|
||||
this.handleButtonClicked(button);
|
||||
this.handleButtonMouseDown(button, e);
|
||||
}
|
||||
buttonDOM.ontouchend = e => this.handleButtonMouseUp();
|
||||
buttonDOM.ontouchcancel = e => this.handleButtonMouseUp();
|
||||
} else {
|
||||
buttonDOM.onclick = () => {
|
||||
this.isMouseHold = false;
|
||||
this.handleButtonClicked(button);
|
||||
}
|
||||
buttonDOM.onmousedown = (e) => {
|
||||
if (this.options.preventMouseDownDefault) e.preventDefault();
|
||||
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
|
||||
*/
|
||||
var buttonSpanDOM = document.createElement('span');
|
||||
buttonSpanDOM.innerHTML = buttonDisplayName;
|
||||
buttonDOM.appendChild(buttonSpanDOM);
|
||||
|
||||
/**
|
||||
* Adding to buttonElements
|
||||
*/
|
||||
if(!this.buttonElements[button])
|
||||
this.buttonElements[button] = [];
|
||||
|
||||
this.buttonElements[button].push(buttonDOM);
|
||||
|
||||
/**
|
||||
* Appending button to row
|
||||
*/
|
||||
rowDOM.appendChild(buttonDOM);
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
if (!useTouchEvents) {
|
||||
document.onmouseup = () => 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>
|
||||
61
docs/file/src/lib/index.js.html
Normal 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 './components/Keyboard';
|
||||
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>
|
||||
87
docs/file/src/lib/services/KeyboardLayout.js.html
Normal 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 {
|
||||
'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;</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>
|
||||
155
docs/file/src/lib/services/PhysicalKeyboard.js.html
Normal 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("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){
|
||||
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;</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>
|
||||
432
docs/file/src/lib/services/Utilities.js.html
Normal file
@@ -0,0 +1,432 @@
|
||||
<!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.updateCaretPosAction = this.updateCaretPosAction.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'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 = '';
|
||||
|
||||
if(buttonTypeClass !== "standardBtn")
|
||||
buttonNormalized = ` hg-button-${buttonWithoutBraces}`;
|
||||
|
||||
return `hg-${buttonTypeClass}${buttonNormalized}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
return display[button] || button;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param {boolean} moveCaret Whether to update simple-keyboard's cursor
|
||||
*/
|
||||
getUpdatedInput(button, input, options, caretPos, moveCaret){
|
||||
|
||||
let output = input;
|
||||
|
||||
if((button === "{bksp}" || button === "{backspace}") && output.length > 0){
|
||||
output = this.removeAt(output, caretPos, moveCaret);
|
||||
|
||||
} else if(button === "{space}")
|
||||
output = this.addStringAt(output, " ", caretPos, moveCaret);
|
||||
|
||||
else if(button === "{tab}" && !(typeof options.tabCharOnTab === "boolean" && options.tabCharOnTab === false)){
|
||||
output = this.addStringAt(output, "\t", caretPos, moveCaret);
|
||||
|
||||
} else if((button === "{enter}" || button === "{numpadenter}") && options.newLineOnEnter)
|
||||
output = this.addStringAt(output, "\n", caretPos, moveCaret);
|
||||
|
||||
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, moveCaret);
|
||||
|
||||
else if(button === "{numpadmultiply}")
|
||||
output = this.addStringAt(output, '*', caretPos, moveCaret);
|
||||
|
||||
else if(button === "{numpadsubtract}")
|
||||
output = this.addStringAt(output, '-', caretPos, moveCaret);
|
||||
|
||||
else if(button === "{numpadadd}")
|
||||
output = this.addStringAt(output, '+', caretPos, moveCaret);
|
||||
|
||||
else if(button === "{numpaddecimal}")
|
||||
output = this.addStringAt(output, '.', caretPos, moveCaret);
|
||||
|
||||
else if(button === "{" || button === "}")
|
||||
output = this.addStringAt(output, button, caretPos, moveCaret);
|
||||
|
||||
else if(!button.includes("{") && !button.includes("}"))
|
||||
output = this.addStringAt(output, button, caretPos, moveCaret);
|
||||
|
||||
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(this.simpleKeyboardInstance.options.syncInstanceInputs){
|
||||
this.simpleKeyboardInstance.dispatch(instance => {
|
||||
this.updateCaretPosAction(instance, length, minus);
|
||||
});
|
||||
} else {
|
||||
this.updateCaretPosAction(this.simpleKeyboardInstance, length, minus);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Action method of updateCaretPos
|
||||
*
|
||||
* @param {object} instance The instance whose position should be updated
|
||||
* @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.
|
||||
*/
|
||||
updateCaretPosAction(instance, length, minus){
|
||||
if(minus){
|
||||
if(instance.caretPosition > 0)
|
||||
instance.caretPosition = instance.caretPosition - length;
|
||||
} else {
|
||||
instance.caretPosition = instance.caretPosition + length;
|
||||
}
|
||||
|
||||
if(this.simpleKeyboardInstance.options.debug){
|
||||
console.log("Caret at:", instance.caretPosition, `(${instance.keyboardDOMClass})`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param {boolean} moveCaret Whether to update simple-keyboard's cursor
|
||||
*/
|
||||
addStringAt(source, string, position, moveCaret){
|
||||
let output;
|
||||
|
||||
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()){
|
||||
if(moveCaret) 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
|
||||
* @param {boolean} moveCaret Whether to update simple-keyboard's cursor
|
||||
*/
|
||||
removeAt(source, position, moveCaret){
|
||||
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);
|
||||
if(moveCaret) this.updateCaretPos(2, true);
|
||||
} else {
|
||||
output = source.substr(0, (position - 1)) + source.substr(position);
|
||||
if(moveCaret) this.updateCaretPos(1, true);
|
||||
}
|
||||
} else {
|
||||
prevTwoChars = source.slice(-2);
|
||||
emojiMatched = prevTwoChars.match(emojiMatchedReg);
|
||||
|
||||
if(emojiMatched){
|
||||
output = source.slice(0, -2);
|
||||
if(moveCaret) this.updateCaretPos(2, true);
|
||||
} else {
|
||||
output = source.slice(0, -1);
|
||||
if(moveCaret) 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;</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>
|
||||
165
docs/file/src/lib/tests/TestUtility.js.html
Normal 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'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);
|
||||
});
|
||||
});
|
||||
}
|
||||
}</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
@@ -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
@@ -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 |
BIN
docs/image/esdoc-logo-mini-black.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
docs/image/esdoc-logo-mini.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
docs/image/github.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
17
docs/image/manual-badge.svg
Normal 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
|
After Width: | Height: | Size: 12 KiB |
87
docs/index.html
Normal 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>
|
||||
<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"></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="📦-installation--amp--usage">📦 Installation & Usage</h2><p>You can use simple-keyboard as a <code><script></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="📖-documentation">📖 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&A / Use-cases</a> page for advanced use-cases.</p>
|
||||
<h2 id="🚀-demo">🚀 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="✅-contributing">✅ Contributing</h2><p>PR'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>
|
||||
2695
docs/index.json
Normal file
1
docs/lint.json
Normal file
@@ -0,0 +1 @@
|
||||
[]
|
||||
28
docs/script/inherited-summary.js
Normal 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
@@ -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
@@ -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);
|
||||
})();
|
||||
8
docs/script/patch-for-local.js
Normal 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';
|
||||
}
|
||||
}
|
||||
})();
|
||||
202
docs/script/prettify/Apache-License-2.0.txt
Normal 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.
|
||||
46
docs/script/prettify/prettify.js
Normal 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})})();}()
|
||||
25
docs/script/pretty-print.js
Normal 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
@@ -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 = '';
|
||||
});
|
||||
|
||||
})();
|
||||
800
docs/script/search_index.js
Normal file
@@ -0,0 +1,800 @@
|
||||
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/services/utilities.js~utilities#updatecaretposaction",
|
||||
"class/src/lib/services/Utilities.js~Utilities.html#instance-method-updateCaretPosAction",
|
||||
"src/lib/services/Utilities.js~Utilities#updateCaretPosAction",
|
||||
"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"
|
||||
]
|
||||
]
|
||||
54
docs/script/test-summary.js
Normal 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
@@ -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">78/78</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">1918 byte</td>
|
||||
<td style="display: none;" data-ice="lines">84</td>
|
||||
<td style="display: none;" data-ice="updated">2018-11-01 01:59:07 (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-11-06 21:41:50 (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">26391 byte</td>
|
||||
<td style="display: none;" data-ice="lines">815</td>
|
||||
<td style="display: none;" data-ice="updated">2018-11-01 01:52:55 (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-11-06 21:41:50 (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-11-06 21:41:48 (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">2908 byte</td>
|
||||
<td style="display: none;" data-ice="lines">96</td>
|
||||
<td style="display: none;" data-ice="updated">2018-11-06 21:41:48 (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">16/16</span></td>
|
||||
<td style="display: none;" data-ice="size">11708 byte</td>
|
||||
<td style="display: none;" data-ice="lines">373</td>
|
||||
<td style="display: none;" data-ice="updated">2018-11-01 01:55:18 (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-11-06 21:41:47 (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>
|
||||
16724
package-lock.json
generated
171
package.json
@@ -1,14 +1,17 @@
|
||||
{
|
||||
"name": "simple-keyboard",
|
||||
"version": "2.3.7",
|
||||
"description": "On-screen Virtual Keyboard",
|
||||
"version": "2.14.0",
|
||||
"description": "On-screen Javascript Virtual Keyboard",
|
||||
"main": "build/index.js",
|
||||
"types": "build/index.d.ts",
|
||||
"scripts": {
|
||||
"start": "node scripts/start.js",
|
||||
"build": "node scripts/build.js",
|
||||
"demo": "node scripts/demo.js",
|
||||
"test": "node scripts/test.js --env=jsdom",
|
||||
"prepublish": "npm run build"
|
||||
"test": "node scripts/test.js",
|
||||
"postinstall": "node bin/postinstall",
|
||||
"prepare": "npm run build",
|
||||
"docs": "esdoc"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -18,7 +21,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",
|
||||
@@ -26,87 +29,124 @@
|
||||
"keyboard",
|
||||
"onscreen",
|
||||
"virtual",
|
||||
"screen-keyboard",
|
||||
"component",
|
||||
"virtual-keyboard",
|
||||
"touchscreen",
|
||||
"touch-screen"
|
||||
"touch-screen",
|
||||
"kiosk",
|
||||
"osk",
|
||||
"js"
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "7.1.6",
|
||||
"babel-core": "^6.26.3",
|
||||
"babel-eslint": "7.2.3",
|
||||
"babel-jest": "20.0.3",
|
||||
"babel-loader": "7.1.2",
|
||||
"babel-preset-react-app": "^3.1.2",
|
||||
"babel-runtime": "6.26.0",
|
||||
"case-sensitive-paths-webpack-plugin": "2.1.1",
|
||||
"chalk": "1.1.3",
|
||||
"copy-webpack-plugin": "^4.3.1",
|
||||
"css-loader": "0.28.7",
|
||||
"dotenv": "4.0.0",
|
||||
"eslint": "4.10.0",
|
||||
"eslint-config-react-app": "^2.0.1",
|
||||
"eslint-loader": "1.9.0",
|
||||
"eslint-plugin-flowtype": "2.39.1",
|
||||
"eslint-plugin-import": "2.8.0",
|
||||
"eslint-plugin-jsx-a11y": "5.1.1",
|
||||
"eslint-plugin-react": "7.4.0",
|
||||
"extract-text-webpack-plugin": "3.0.2",
|
||||
"file-loader": "1.1.5",
|
||||
"fs-extra": "3.0.1",
|
||||
"html-webpack-plugin": "2.29.0",
|
||||
"jest": "20.0.4",
|
||||
"object-assign": "4.1.1",
|
||||
"postcss-flexbugs-fixes": "3.2.0",
|
||||
"postcss-loader": "2.0.8",
|
||||
"promise": "8.0.1",
|
||||
"prop-types": "^15.6.1",
|
||||
"raf": "3.4.0",
|
||||
"react": "^16.2.0",
|
||||
"react-dev-utils": "^4.2.1",
|
||||
"react-dom": "^16.2.0",
|
||||
"style-loader": "0.19.0",
|
||||
"sw-precache-webpack-plugin": "0.11.4",
|
||||
"url-loader": "0.6.2",
|
||||
"webpack": "3.8.1",
|
||||
"webpack-dev-server": "2.9.4",
|
||||
"webpack-manifest-plugin": "1.3.2",
|
||||
"whatwg-fetch": "2.0.3"
|
||||
"@babel/core": "7.2.2",
|
||||
"@babel/plugin-proposal-class-properties": "^7.2.3",
|
||||
"@babel/preset-env": "^7.2.3",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"@svgr/webpack": "4.1.0",
|
||||
"babel-core": "7.0.0-bridge.0",
|
||||
"babel-eslint": "10.0.1",
|
||||
"babel-jest": "23.6.0",
|
||||
"babel-loader": "8.0.5",
|
||||
"babel-plugin-named-asset-import": "^0.3.0",
|
||||
"babel-preset-react-app": "^7.0.0",
|
||||
"bfj": "6.1.1",
|
||||
"case-sensitive-paths-webpack-plugin": "2.1.2",
|
||||
"chalk": "2.4.2",
|
||||
"copy-webpack-plugin": "^4.6.0",
|
||||
"css-loader": "2.1.0",
|
||||
"dotenv": "6.2.0",
|
||||
"dotenv-expand": "4.2.0",
|
||||
"esdoc": "^1.1.0",
|
||||
"esdoc-ecmascript-proposal-plugin": "^1.0.0",
|
||||
"esdoc-standard-plugin": "^1.0.0",
|
||||
"eslint": "5.12.0",
|
||||
"eslint-config-react-app": "^3.0.6",
|
||||
"eslint-loader": "2.1.1",
|
||||
"eslint-plugin-flowtype": "3.2.0",
|
||||
"eslint-plugin-import": "2.14.0",
|
||||
"eslint-plugin-jsx-a11y": "6.1.2",
|
||||
"eslint-plugin-react": "7.12.3",
|
||||
"file-loader": "3.0.1",
|
||||
"fork-ts-checker-webpack-plugin-alt": "0.4.14",
|
||||
"fs-extra": "7.0.1",
|
||||
"html-webpack-plugin": "4.0.0-beta.5",
|
||||
"identity-obj-proxy": "3.0.0",
|
||||
"jest": "23.6.0",
|
||||
"jest-pnp-resolver": "1.0.2",
|
||||
"jest-resolve": "23.6.0",
|
||||
"mini-css-extract-plugin": "0.5.0",
|
||||
"optimize-css-assets-webpack-plugin": "5.0.1",
|
||||
"pnp-webpack-plugin": "1.2.1",
|
||||
"postcss-flexbugs-fixes": "4.1.0",
|
||||
"postcss-loader": "3.0.0",
|
||||
"postcss-preset-env": "6.5.0",
|
||||
"postcss-safe-parser": "4.0.1",
|
||||
"react": "^16.7.0",
|
||||
"react-app-polyfill": "^0.2.0",
|
||||
"react-dev-utils": "^7.0.1",
|
||||
"react-dom": "^16.7.0",
|
||||
"resolve": "1.9.0",
|
||||
"sass-loader": "7.1.0",
|
||||
"style-loader": "0.23.1",
|
||||
"terser-webpack-plugin": "1.2.1",
|
||||
"url-loader": "1.1.2",
|
||||
"webpack": "4.28.3",
|
||||
"webpack-dev-server": "3.1.14",
|
||||
"webpack-manifest-plugin": "2.0.4",
|
||||
"workbox-webpack-plugin": "3.6.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=0.14",
|
||||
"react-dom": ">=0.14"
|
||||
"eslintConfig": {
|
||||
"extends": "react-app",
|
||||
"settings": {
|
||||
"react": {
|
||||
"pragma": "React",
|
||||
"version": "detect"
|
||||
}
|
||||
}
|
||||
},
|
||||
"browserslist": [
|
||||
">0.2%",
|
||||
"not ie <= 11",
|
||||
"not op_mini all"
|
||||
],
|
||||
"jest": {
|
||||
"collectCoverageFrom": [
|
||||
"src/**/*.{js,jsx,mjs}"
|
||||
"src/**/*.{js,jsx,ts,tsx}",
|
||||
"!src/**/*.d.ts",
|
||||
"!**/tests/**"
|
||||
],
|
||||
"resolver": "jest-pnp-resolver",
|
||||
"setupFiles": [
|
||||
"<rootDir>/config/polyfills.js"
|
||||
"react-app-polyfill/jsdom"
|
||||
],
|
||||
"testMatch": [
|
||||
"<rootDir>/src/**/__tests__/**/*.{js,jsx,mjs}",
|
||||
"<rootDir>/src/**/?(*.)(spec|test).{js,jsx,mjs}"
|
||||
"<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}",
|
||||
"<rootDir>/src/**/?(*.)(spec|test).{js,jsx,ts,tsx}"
|
||||
],
|
||||
"testEnvironment": "node",
|
||||
"testEnvironment": "jsdom",
|
||||
"testURL": "http://localhost",
|
||||
"transform": {
|
||||
"^.+\\.(js|jsx|mjs)$": "<rootDir>/node_modules/babel-jest",
|
||||
"^.+\\.(js|jsx|ts|tsx)$": "<rootDir>/node_modules/babel-jest",
|
||||
"^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
|
||||
"^(?!.*\\.(js|jsx|mjs|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
|
||||
"^(?!.*\\.(js|jsx|ts|tsx|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
|
||||
},
|
||||
"transformIgnorePatterns": [
|
||||
"[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs)$"
|
||||
"[/\\\\]node_modules[/\\\\].+\\.(js|jsx|ts|tsx)$",
|
||||
"^.+\\.module\\.(css|sass|scss)$"
|
||||
],
|
||||
"moduleNameMapper": {
|
||||
"^react-native$": "react-native-web"
|
||||
"^react-native$": "react-native-web",
|
||||
"^.+\\.module\\.(css|sass|scss)$": "identity-obj-proxy"
|
||||
},
|
||||
"moduleFileExtensions": [
|
||||
"web.js",
|
||||
"mjs",
|
||||
"js",
|
||||
"web.ts",
|
||||
"ts",
|
||||
"web.tsx",
|
||||
"tsx",
|
||||
"json",
|
||||
"web.jsx",
|
||||
"jsx",
|
||||
@@ -115,10 +155,13 @@
|
||||
},
|
||||
"babel": {
|
||||
"presets": [
|
||||
"react-app"
|
||||
"@babel/preset-env",
|
||||
"@babel/preset-react"
|
||||
],
|
||||
"plugins": [
|
||||
[
|
||||
"@babel/plugin-proposal-class-properties"
|
||||
]
|
||||
]
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "react-app"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,37 +14,55 @@ process.on('unhandledRejection', err => {
|
||||
// Ensure environment variables are read.
|
||||
require('../config/env');
|
||||
|
||||
|
||||
const path = require('path');
|
||||
const chalk = require('chalk');
|
||||
const fs = require('fs-extra');
|
||||
const webpack = require('webpack');
|
||||
const bfj = require('bfj');
|
||||
const config = require('../config/webpack.config.prod');
|
||||
const paths = require('../config/paths');
|
||||
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
|
||||
const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
|
||||
const printHostingInstructions = require('react-dev-utils/printHostingInstructions');
|
||||
const FileSizeReporter = require('react-dev-utils/FileSizeReporter');
|
||||
const printBuildError = require('react-dev-utils/printBuildError');
|
||||
|
||||
const measureFileSizesBeforeBuild =
|
||||
FileSizeReporter.measureFileSizesBeforeBuild;
|
||||
const printFileSizesAfterBuild = FileSizeReporter.printFileSizesAfterBuild;
|
||||
const useYarn = fs.existsSync(paths.yarnLockFile);
|
||||
|
||||
// These sizes are pretty large. We'll warn for bundles exceeding them.
|
||||
const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024;
|
||||
const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024;
|
||||
|
||||
const isInteractive = process.stdout.isTTY;
|
||||
|
||||
// Warn and crash if required files are missing
|
||||
if (!checkRequiredFiles([paths.appLibIndexJs])) { // CRL: Updated with library index file
|
||||
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// First, read the current file sizes in build directory.
|
||||
// This lets us display how much they changed later.
|
||||
measureFileSizesBeforeBuild(paths.appBuild)
|
||||
// Process CLI arguments
|
||||
const argv = process.argv.slice(2);
|
||||
const writeStatsJson = argv.indexOf('--stats') !== -1;
|
||||
|
||||
// We require that you explicitly set browsers and do not fall back to
|
||||
// browserslist defaults.
|
||||
const { checkBrowsers } = require('react-dev-utils/browsersHelper');
|
||||
checkBrowsers(paths.appPath, isInteractive)
|
||||
.then(() => {
|
||||
// First, read the current file sizes in build directory.
|
||||
// This lets us display how much they changed later.
|
||||
return measureFileSizesBeforeBuild(paths.appBuild);
|
||||
})
|
||||
.then(previousFileSizes => {
|
||||
// Remove all content but keep the directory so that
|
||||
// if you're in it, you don't end up in Trash
|
||||
fs.emptyDirSync(paths.appBuild);
|
||||
|
||||
// Merge with the public folder
|
||||
//copyPublicFolder();
|
||||
// Start the webpack build
|
||||
return build(previousFileSizes);
|
||||
})
|
||||
@@ -76,13 +94,31 @@ measureFileSizesBeforeBuild(paths.appBuild)
|
||||
WARN_AFTER_CHUNK_GZIP_SIZE
|
||||
);
|
||||
console.log();
|
||||
|
||||
const appPackage = require(paths.appPackageJson);
|
||||
const publicUrl = paths.publicUrl;
|
||||
const publicPath = config.output.publicPath;
|
||||
const buildFolder = path.relative(process.cwd(), paths.appBuild);
|
||||
printHostingInstructions(
|
||||
appPackage,
|
||||
publicUrl,
|
||||
publicPath,
|
||||
buildFolder,
|
||||
useYarn
|
||||
);
|
||||
},
|
||||
err => {
|
||||
console.log(chalk.red('Failed to compile.\n'));
|
||||
printBuildError(err);
|
||||
process.exit(1);
|
||||
}
|
||||
);
|
||||
)
|
||||
.catch(err => {
|
||||
if (err && err.message) {
|
||||
console.log(err.message);
|
||||
}
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
// Create the production build and print the deployment instructions.
|
||||
function build(previousFileSizes) {
|
||||
@@ -91,10 +127,20 @@ function build(previousFileSizes) {
|
||||
let compiler = webpack(config);
|
||||
return new Promise((resolve, reject) => {
|
||||
compiler.run((err, stats) => {
|
||||
let messages;
|
||||
if (err) {
|
||||
return reject(err);
|
||||
if (!err.message) {
|
||||
return reject(err);
|
||||
}
|
||||
messages = formatWebpackMessages({
|
||||
errors: [err.message],
|
||||
warnings: [],
|
||||
});
|
||||
} else {
|
||||
messages = formatWebpackMessages(
|
||||
stats.toJson({ all: false, warnings: true, errors: true })
|
||||
);
|
||||
}
|
||||
const messages = formatWebpackMessages(stats.toJson({}, true));
|
||||
if (messages.errors.length) {
|
||||
// Only keep the first error. Others are often indicative
|
||||
// of the same problem, but confuse the reader with noise.
|
||||
@@ -117,11 +163,27 @@ function build(previousFileSizes) {
|
||||
);
|
||||
return reject(new Error(messages.warnings.join('\n\n')));
|
||||
}
|
||||
return resolve({
|
||||
|
||||
const resolveArgs = {
|
||||
stats,
|
||||
previousFileSizes,
|
||||
warnings: messages.warnings,
|
||||
});
|
||||
};
|
||||
if (writeStatsJson) {
|
||||
return bfj
|
||||
.write(paths.appBuild + '/bundle-stats.json', stats.toJson())
|
||||
.then(() => resolve(resolveArgs))
|
||||
.catch(error => reject(new Error(error)));
|
||||
}
|
||||
|
||||
return resolve(resolveArgs);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function copyPublicFolder() {
|
||||
fs.copySync(paths.appPublic, paths.appBuild, {
|
||||
dereference: true,
|
||||
filter: file => file !== paths.appHtml,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -14,37 +14,55 @@ process.on('unhandledRejection', err => {
|
||||
// Ensure environment variables are read.
|
||||
require('../config/env');
|
||||
|
||||
|
||||
const path = require('path');
|
||||
const chalk = require('chalk');
|
||||
const fs = require('fs-extra');
|
||||
const webpack = require('webpack');
|
||||
const bfj = require('bfj');
|
||||
const config = require('../config/webpack.config.demo');
|
||||
const paths = require('../config/paths');
|
||||
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
|
||||
const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
|
||||
const printHostingInstructions = require('react-dev-utils/printHostingInstructions');
|
||||
const FileSizeReporter = require('react-dev-utils/FileSizeReporter');
|
||||
const printBuildError = require('react-dev-utils/printBuildError');
|
||||
|
||||
const measureFileSizesBeforeBuild =
|
||||
FileSizeReporter.measureFileSizesBeforeBuild;
|
||||
const printFileSizesAfterBuild = FileSizeReporter.printFileSizesAfterBuild;
|
||||
const useYarn = fs.existsSync(paths.yarnLockFile);
|
||||
|
||||
// These sizes are pretty large. We'll warn for bundles exceeding them.
|
||||
const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024;
|
||||
const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024;
|
||||
|
||||
const isInteractive = process.stdout.isTTY;
|
||||
|
||||
// Warn and crash if required files are missing
|
||||
if (!checkRequiredFiles([paths.appDemoIndexJs])) { // CRL: Updated with library index file
|
||||
if (!checkRequiredFiles([paths.appHtml, paths.appDemoIndexJs])) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// First, read the current file sizes in build directory.
|
||||
// This lets us display how much they changed later.
|
||||
measureFileSizesBeforeBuild(paths.appDemoBuild)
|
||||
// Process CLI arguments
|
||||
const argv = process.argv.slice(2);
|
||||
const writeStatsJson = argv.indexOf('--stats') !== -1;
|
||||
|
||||
// We require that you explicitly set browsers and do not fall back to
|
||||
// browserslist defaults.
|
||||
const { checkBrowsers } = require('react-dev-utils/browsersHelper');
|
||||
checkBrowsers(paths.appPath, isInteractive)
|
||||
.then(() => {
|
||||
// First, read the current file sizes in build directory.
|
||||
// This lets us display how much they changed later.
|
||||
return measureFileSizesBeforeBuild(paths.appDemo);
|
||||
})
|
||||
.then(previousFileSizes => {
|
||||
// Remove all content but keep the directory so that
|
||||
// if you're in it, you don't end up in Trash
|
||||
fs.emptyDirSync(paths.appDemoBuild);
|
||||
|
||||
fs.emptyDirSync(paths.appDemo);
|
||||
// Merge with the public folder
|
||||
copyPublicFolder();
|
||||
// Start the webpack build
|
||||
return build(previousFileSizes);
|
||||
})
|
||||
@@ -71,30 +89,58 @@ measureFileSizesBeforeBuild(paths.appDemoBuild)
|
||||
printFileSizesAfterBuild(
|
||||
stats,
|
||||
previousFileSizes,
|
||||
paths.appDemoBuild,
|
||||
paths.appDemo,
|
||||
WARN_AFTER_BUNDLE_GZIP_SIZE,
|
||||
WARN_AFTER_CHUNK_GZIP_SIZE
|
||||
);
|
||||
console.log();
|
||||
|
||||
const appPackage = require(paths.appPackageJson);
|
||||
const publicUrl = paths.publicUrl;
|
||||
const publicPath = config.output.publicPath;
|
||||
const buildFolder = path.relative(process.cwd(), paths.appDemo);
|
||||
printHostingInstructions(
|
||||
appPackage,
|
||||
publicUrl,
|
||||
publicPath,
|
||||
buildFolder,
|
||||
useYarn
|
||||
);
|
||||
},
|
||||
err => {
|
||||
console.log(chalk.red('Failed to compile.\n'));
|
||||
printBuildError(err);
|
||||
process.exit(1);
|
||||
}
|
||||
);
|
||||
)
|
||||
.catch(err => {
|
||||
if (err && err.message) {
|
||||
console.log(err.message);
|
||||
}
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
// Create the production build and print the deployment instructions.
|
||||
function build(previousFileSizes) {
|
||||
console.log('Creating a build of the demo app...');
|
||||
console.log('Creating an optimized production build...');
|
||||
|
||||
let compiler = webpack(config);
|
||||
return new Promise((resolve, reject) => {
|
||||
compiler.run((err, stats) => {
|
||||
let messages;
|
||||
if (err) {
|
||||
return reject(err);
|
||||
if (!err.message) {
|
||||
return reject(err);
|
||||
}
|
||||
messages = formatWebpackMessages({
|
||||
errors: [err.message],
|
||||
warnings: [],
|
||||
});
|
||||
} else {
|
||||
messages = formatWebpackMessages(
|
||||
stats.toJson({ all: false, warnings: true, errors: true })
|
||||
);
|
||||
}
|
||||
const messages = formatWebpackMessages(stats.toJson({}, true));
|
||||
if (messages.errors.length) {
|
||||
// Only keep the first error. Others are often indicative
|
||||
// of the same problem, but confuse the reader with noise.
|
||||
@@ -117,11 +163,27 @@ function build(previousFileSizes) {
|
||||
);
|
||||
return reject(new Error(messages.warnings.join('\n\n')));
|
||||
}
|
||||
return resolve({
|
||||
|
||||
const resolveArgs = {
|
||||
stats,
|
||||
previousFileSizes,
|
||||
warnings: messages.warnings,
|
||||
});
|
||||
};
|
||||
if (writeStatsJson) {
|
||||
return bfj
|
||||
.write(paths.appDemo + '/bundle-stats.json', stats.toJson())
|
||||
.then(() => resolve(resolveArgs))
|
||||
.catch(error => reject(new Error(error)));
|
||||
}
|
||||
|
||||
return resolve(resolveArgs);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function copyPublicFolder() {
|
||||
fs.copySync(paths.appPublic, paths.appDemo, {
|
||||
dereference: true,
|
||||
filter: file => file !== paths.appHtml,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ process.on('unhandledRejection', err => {
|
||||
// Ensure environment variables are read.
|
||||
require('../config/env');
|
||||
|
||||
|
||||
const fs = require('fs');
|
||||
const chalk = require('chalk');
|
||||
const webpack = require('webpack');
|
||||
@@ -35,7 +36,7 @@ const useYarn = fs.existsSync(paths.yarnLockFile);
|
||||
const isInteractive = process.stdout.isTTY;
|
||||
|
||||
// Warn and crash if required files are missing
|
||||
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
|
||||
if (!checkRequiredFiles([paths.appHtml, paths.appDemoIndexJs])) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
@@ -43,9 +44,32 @@ if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
|
||||
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000;
|
||||
const HOST = process.env.HOST || '0.0.0.0';
|
||||
|
||||
// We attempt to use the default port but if it is busy, we offer the user to
|
||||
// run on a different port. `detect()` Promise resolves to the next free port.
|
||||
choosePort(HOST, DEFAULT_PORT)
|
||||
if (process.env.HOST) {
|
||||
console.log(
|
||||
chalk.cyan(
|
||||
`Attempting to bind to HOST environment variable: ${chalk.yellow(
|
||||
chalk.bold(process.env.HOST)
|
||||
)}`
|
||||
)
|
||||
);
|
||||
console.log(
|
||||
`If this was unintentional, check that you haven't mistakenly set it in your shell.`
|
||||
);
|
||||
console.log(
|
||||
`Learn more here: ${chalk.yellow('http://bit.ly/CRA-advanced-config')}`
|
||||
);
|
||||
console.log();
|
||||
}
|
||||
|
||||
// We require that you explictly set browsers and do not fall back to
|
||||
// browserslist defaults.
|
||||
const { checkBrowsers } = require('react-dev-utils/browsersHelper');
|
||||
checkBrowsers(paths.appPath, isInteractive)
|
||||
.then(() => {
|
||||
// We attempt to use the default port but if it is busy, we offer the user to
|
||||
// run on a different port. `choosePort()` Promise resolves to the next free port.
|
||||
return choosePort(HOST, DEFAULT_PORT);
|
||||
})
|
||||
.then(port => {
|
||||
if (port == null) {
|
||||
// We have not found a port.
|
||||
@@ -59,7 +83,7 @@ choosePort(HOST, DEFAULT_PORT)
|
||||
// Load proxy config
|
||||
const proxySetting = require(paths.appPackageJson).proxy;
|
||||
const proxyConfig = prepareProxy(proxySetting, paths.appPublic);
|
||||
// Serve webpack assets generated by the compiler over a web sever.
|
||||
// Serve webpack assets generated by the compiler over a web server.
|
||||
const serverConfig = createDevServerConfig(
|
||||
proxyConfig,
|
||||
urls.lanUrlForConfig
|
||||
|
||||
@@ -15,12 +15,38 @@ process.on('unhandledRejection', err => {
|
||||
// Ensure environment variables are read.
|
||||
require('../config/env');
|
||||
|
||||
const jest = require('jest');
|
||||
const argv = process.argv.slice(2);
|
||||
|
||||
// Watch unless on CI or in coverage mode
|
||||
if (!process.env.CI && argv.indexOf('--coverage') < 0) {
|
||||
argv.push('--watch');
|
||||
const jest = require('jest');
|
||||
const execSync = require('child_process').execSync;
|
||||
let argv = process.argv.slice(2);
|
||||
|
||||
function isInGitRepository() {
|
||||
try {
|
||||
execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' });
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function isInMercurialRepository() {
|
||||
try {
|
||||
execSync('hg --cwd . root', { stdio: 'ignore' });
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Watch unless on CI, in coverage mode, or explicitly running all tests
|
||||
if (
|
||||
!process.env.CI &&
|
||||
argv.indexOf('--coverage') === -1 &&
|
||||
argv.indexOf('--watchAll') === -1
|
||||
) {
|
||||
// https://github.com/facebook/create-react-app/issues/5210
|
||||
const hasSourceControl = isInGitRepository() || isInMercurialRepository();
|
||||
argv.push(hasSourceControl ? '--watch' : '--watchAll');
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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('input', (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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -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: 200px;
|
||||
border-top-right-radius: 5px;
|
||||
border-top-left-radius: 5px;
|
||||
padding: 10px;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
67
src/demo/tests/App.test.js
Normal 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('input'));
|
||||
|
||||
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");
|
||||
});
|
||||
199
src/lib/@types/index.d.ts
vendored
Normal file
@@ -0,0 +1,199 @@
|
||||
declare module 'simple-keyboard' {
|
||||
interface KeyboardLayoutObject {
|
||||
default: string[];
|
||||
shift?: string[];
|
||||
}
|
||||
|
||||
interface KeyboardButtonTheme {
|
||||
class: string;
|
||||
buttons: string;
|
||||
}
|
||||
|
||||
interface KeyboardOptions {
|
||||
/**
|
||||
* Modify the keyboard layout.
|
||||
*/
|
||||
layout?: KeyboardLayoutObject;
|
||||
|
||||
/**
|
||||
* Specifies which layout should be used.
|
||||
*/
|
||||
layoutName?: string;
|
||||
|
||||
/**
|
||||
* Replaces variable buttons (such as `{bksp}`) with a human-friendly name (e.g.: `backspace`).
|
||||
*/
|
||||
display?: { [button: string]: string };
|
||||
|
||||
/**
|
||||
* By default, when you set the display property, you replace the default one. This setting merges them instead.
|
||||
*/
|
||||
mergeDisplay?: boolean;
|
||||
|
||||
/**
|
||||
* A prop to add your own css classes to the keyboard wrapper. You can add multiple classes separated by a space.
|
||||
*/
|
||||
theme?: string;
|
||||
|
||||
/**
|
||||
* A prop to add your own css classes to one or several buttons.
|
||||
*/
|
||||
buttonTheme?: KeyboardButtonTheme[];
|
||||
|
||||
/**
|
||||
* Runs a `console.log` every time a key is pressed. Displays the buttons pressed and the current input.
|
||||
*/
|
||||
debug?: boolean;
|
||||
|
||||
/**
|
||||
* Specifies whether clicking the "ENTER" button will input a newline (`\n`) or not.
|
||||
*/
|
||||
newLineOnEnter?: boolean;
|
||||
|
||||
/**
|
||||
* Specifies whether clicking the "TAB" button will input a tab character (`\t`) or not.
|
||||
*/
|
||||
tabCharOnTab?: boolean;
|
||||
|
||||
/**
|
||||
* Allows you to use a single simple-keyboard instance for several inputs.
|
||||
*/
|
||||
inputName?: string;
|
||||
|
||||
/**
|
||||
* `number`: Restrains all of simple-keyboard inputs to a certain length. This should be used in addition to the input element’s maxlengthattribute.
|
||||
*
|
||||
* `{ [inputName: string]: number }`: Restrains simple-keyboard’s individual inputs to a certain length. This should be used in addition to the input element’s maxlengthattribute.
|
||||
*/
|
||||
maxLength?:
|
||||
| number
|
||||
| {
|
||||
[inputName: string]: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* When set to true, this option synchronizes the internal input of every simple-keyboard instance.
|
||||
*/
|
||||
syncInstanceInputs?: boolean;
|
||||
|
||||
/**
|
||||
* Enable highlighting of keys pressed on physical keyboard.
|
||||
*/
|
||||
physicalKeyboardHighlight?: boolean;
|
||||
|
||||
/**
|
||||
* Calling preventDefault for the mousedown events keeps the focus on the input.
|
||||
*/
|
||||
preventMouseDownDefault?: boolean;
|
||||
|
||||
/**
|
||||
* Define the text color that the physical keyboard highlighted key should have.
|
||||
*/
|
||||
physicalKeyboardHighlightTextColor?: string;
|
||||
|
||||
/**
|
||||
* Define the background color that the physical keyboard highlighted key should have.
|
||||
*/
|
||||
physicalKeyboardHighlightBgColor?: string;
|
||||
|
||||
/**
|
||||
* Render buttons as a button element instead of a div element.
|
||||
*/
|
||||
useButtonTag?: boolean;
|
||||
|
||||
/**
|
||||
* A prop to ensure characters are always be added/removed at the end of the string.
|
||||
*/
|
||||
disableCaretPositioning?: boolean;
|
||||
|
||||
/**
|
||||
* Restrains input(s) change to the defined regular expression pattern.
|
||||
*/
|
||||
inputPattern?: any;
|
||||
|
||||
/**
|
||||
* Executes the callback function on key press. Returns button layout name (i.e.: "{shift}").
|
||||
*/
|
||||
onKeyPress?: (button: string) => any;
|
||||
|
||||
/**
|
||||
* Executes the callback function on input change. Returns the current input's string.
|
||||
*/
|
||||
onChange?: (input: string) => any;
|
||||
|
||||
/**
|
||||
* Executes the callback function every time simple-keyboard is rendered (e.g: when you change layouts).
|
||||
*/
|
||||
onRender?: () => void;
|
||||
|
||||
/**
|
||||
* Executes the callback function once simple-keyboard is rendered for the first time (on initialization).
|
||||
*/
|
||||
onInit?: () => void;
|
||||
|
||||
/**
|
||||
* Executes the callback function on input change. Returns the input object with all defined inputs.
|
||||
*/
|
||||
onChangeAll?: (inputs: any) => any;
|
||||
}
|
||||
|
||||
class Keyboard {
|
||||
constructor(selector: string, options: KeyboardOptions);
|
||||
constructor(options: KeyboardOptions);
|
||||
options: KeyboardOptions;
|
||||
|
||||
/**
|
||||
* Adds/Modifies an entry to the `buttonTheme`. Basically a way to add a class to a button.
|
||||
* @param {string} buttons List of buttons to select (separated by a space).
|
||||
* @param {string} className Classes to give to the selected buttons (separated by space).
|
||||
*/
|
||||
addButtonTheme(buttons: string, className: string): void;
|
||||
|
||||
/**
|
||||
* Removes/Amends an entry to the `buttonTheme`. Basically a way to remove a class previously added to a button through buttonTheme or addButtonTheme.
|
||||
* @param {string} buttons List of buttons to select (separated by a space).
|
||||
* @param {string} className Classes to give to the selected buttons (separated by space).
|
||||
*/
|
||||
removeButtonTheme(buttons: string, className: string): void;
|
||||
|
||||
/**
|
||||
* Clear the keyboard's input.
|
||||
*
|
||||
* @param {string} [inputName] optional - the internal input to select
|
||||
*/
|
||||
clearInput(inputName?: string): void;
|
||||
|
||||
/**
|
||||
* Get the keyboard’s input (You can also get it from the onChange prop).
|
||||
* @param {string} [inputName] optional - the internal input to select
|
||||
*/
|
||||
getInput(inputName?: string): string;
|
||||
|
||||
/**
|
||||
* Set the keyboard’s input.
|
||||
* @param {string} input the input value
|
||||
* @param {string} inputName optional - the internal input to select
|
||||
*/
|
||||
setInput(input: string, inputName?: string): void;
|
||||
|
||||
/**
|
||||
* Set new option or modify existing ones after initialization.
|
||||
* @param {KeyboardOptions} option The option to set
|
||||
*/
|
||||
setOptions(options: KeyboardOptions): void;
|
||||
|
||||
/**
|
||||
* Send a command to all simple-keyboard instances at once (if you have multiple instances).
|
||||
* @param {function(instance: object, key: string)} callback Function to run on every instance
|
||||
*/
|
||||
dispatch(callback: (instance: any, key: string) => void): void;
|
||||
|
||||
/**
|
||||
* Get the DOM Element of a button. If there are several buttons with the same name, an array of the DOM Elements is returned.
|
||||
* @param {string} button The button layout name to select
|
||||
*/
|
||||
getButtonElement(button: string): HTMLElement | HTMLElement[];
|
||||
}
|
||||
|
||||
export default Keyboard;
|
||||
}
|
||||
@@ -30,7 +30,7 @@ body, html {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.simple-keyboard.hg-layout-default .hg-button.hg-standardBtn {
|
||||
.hg-standardBtn {
|
||||
max-width: 100px;
|
||||
}
|
||||
|
||||
@@ -51,8 +51,19 @@ body, html {
|
||||
padding: 5px;
|
||||
background: white;
|
||||
border-bottom: 1px solid #b5b5b5;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* When using option "useButtonTag" */
|
||||
.simple-keyboard button.hg-button {
|
||||
border-width: 0;
|
||||
outline: 0;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
.simple-keyboard.hg-theme-default .hg-button:active {
|
||||
background: #e4e4e4;
|
||||
}
|
||||
@@ -63,4 +74,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;
|
||||
}
|
||||
@@ -1,41 +1,169 @@
|
||||
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 keyboardDOMQuery = typeof params[0] === "string" ? params[0] : ".simple-keyboard";
|
||||
let options = typeof params[0] === "object" ? 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.: “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 element’s maxlengthattribute.
|
||||
* @property {object} maxLength Restrains simple-keyboard’s individual inputs to a certain length. This should be used in addition to the input element’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 {boolean} preventMouseDownDefault Calling preventDefault for the mousedown events keeps the focus on the input.
|
||||
* @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 input’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.
|
||||
* @property {boolean} useButtonTag Render buttons as a button element instead of a div element.
|
||||
* @property {boolean} disableCaretPositioning A prop to ensure characters are always be added/removed at the end of the string.
|
||||
* @property {object} inputPattern Restrains input(s) change to the defined regular expression pattern.
|
||||
*/
|
||||
this.options = options;
|
||||
this.options.layoutName = this.options.layoutName || "default";
|
||||
this.options.theme = this.options.theme || "hg-theme-default";
|
||||
this.options.inputName = this.options.inputName || "default";
|
||||
this.options.preventMouseDownDefault = this.options.preventMouseDownDefault || false;
|
||||
|
||||
/**
|
||||
* @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);
|
||||
this.inputPatternIsValid = this.inputPatternIsValid.bind(this);
|
||||
|
||||
/**
|
||||
* simple-keyboard uses a non-persistent internal input to keep track of the entered string (the variable `keyboard.input`).
|
||||
* 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 +175,46 @@ 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){
|
||||
this.input[this.options.inputName] = updatedInput;
|
||||
if(
|
||||
// If input will change as a result of this button press
|
||||
this.input[this.options.inputName] !== updatedInput &&
|
||||
// This pertains to the "inputPattern" option:
|
||||
(
|
||||
// If inputPattern isn't set
|
||||
!this.options.inputPattern ||
|
||||
// Or, if it is set and if the pattern is valid - we proceed.
|
||||
(this.options.inputPattern && this.inputPatternIsValid(updatedInput))
|
||||
)
|
||||
){
|
||||
|
||||
/**
|
||||
* If maxLength and handleMaxLength yield true, halting
|
||||
*/
|
||||
if(this.options.maxLength && this.utilities.handleMaxLength(this.input, this.options, updatedInput)){
|
||||
return false;
|
||||
}
|
||||
|
||||
this.input[this.options.inputName] = this.utilities.getUpdatedInput(
|
||||
button, this.input[this.options.inputName], this.options, this.caretPosition, true
|
||||
);
|
||||
|
||||
if(debug)
|
||||
console.log('Input changed:', this.input);
|
||||
|
||||
/**
|
||||
* Enforce syncInstanceInputs, if set
|
||||
*/
|
||||
if(this.options.syncInstanceInputs)
|
||||
this.syncInstanceInputs(this.input);
|
||||
|
||||
/**
|
||||
* Calling onChange
|
||||
*/
|
||||
@@ -78,39 +227,488 @@ 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){
|
||||
if(this.holdInteractionTimeout)
|
||||
clearTimeout(this.holdInteractionTimeout);
|
||||
|
||||
/**
|
||||
* @type {object} Timeout dictating the speed of key hold iterations
|
||||
*/
|
||||
this.holdInteractionTimeout = setTimeout(() => {
|
||||
if(this.isMouseHold){
|
||||
this.handleButtonClicked(button);
|
||||
this.handleButtonHold(button);
|
||||
} else {
|
||||
clearTimeout(this.holdInteractionTimeout);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a command to all simple-keyboard instances (if you have several instances).
|
||||
*/
|
||||
syncInstanceInputs(){
|
||||
this.dispatch((instance) => {
|
||||
instance.replaceInput(this.input);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the keyboard’s input.
|
||||
* @param {string} [inputName] optional - the internal input to select
|
||||
*/
|
||||
clearInput(inputName){
|
||||
inputName = inputName || this.options.inputName;
|
||||
this.input[inputName] = '';
|
||||
|
||||
/**
|
||||
* Enforce syncInstanceInputs, if set
|
||||
*/
|
||||
if(this.options.syncInstanceInputs)
|
||||
this.syncInstanceInputs(this.input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the keyboard’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];
|
||||
}
|
||||
|
||||
setInput = (input, inputName) => {
|
||||
/**
|
||||
* Set the keyboard’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 => {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* This handles the "inputPattern" option
|
||||
* by checking if the provided inputPattern passes
|
||||
*/
|
||||
inputPatternIsValid(inputVal){
|
||||
let inputPatternRaw = this.options.inputPattern;
|
||||
let inputPattern;
|
||||
|
||||
/**
|
||||
* Check if input pattern is global or targeted to individual inputs
|
||||
*/
|
||||
if(inputPatternRaw instanceof RegExp){
|
||||
inputPattern = inputPatternRaw;
|
||||
} else {
|
||||
inputPattern = inputPatternRaw[this.options.inputName];
|
||||
}
|
||||
|
||||
if(inputPattern && inputVal){
|
||||
let didInputMatch = inputPattern.test(inputVal);
|
||||
|
||||
if(this.options.debug){
|
||||
console.log(`inputPattern ("${inputPattern}"): ${didInputMatch ? "passed" : "did not pass!"}`);
|
||||
}
|
||||
|
||||
return didInputMatch;
|
||||
} else {
|
||||
/**
|
||||
* inputPattern doesn't seem to be set for the current input, or input is empty. Pass.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current cursor position within a input or textarea (if any)
|
||||
*/
|
||||
handleCaret(){
|
||||
/**
|
||||
* Only first instance should insall the caret handling events
|
||||
*/
|
||||
this.caretPosition = null;
|
||||
let simpleKeyboardInstances = window['SimpleKeyboardInstances'];
|
||||
|
||||
if(
|
||||
(
|
||||
simpleKeyboardInstances &&
|
||||
Object.keys(simpleKeyboardInstances)[0] === this.utilities.camelCase(this.keyboardDOMClass)
|
||||
) ||
|
||||
!simpleKeyboardInstances
|
||||
){
|
||||
if(this.options.debug){
|
||||
console.log(`Caret handling started (${this.keyboardDOMClass})`)
|
||||
}
|
||||
|
||||
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;
|
||||
if(event.target.tagName){
|
||||
targetTagName = event.target.tagName.toLowerCase();
|
||||
}
|
||||
|
||||
this.dispatch(instance => {
|
||||
if(instance.isMouseHold){
|
||||
instance.isMouseHold = false;
|
||||
}
|
||||
|
||||
if(
|
||||
(targetTagName === "textarea" ||
|
||||
targetTagName === "input") &&
|
||||
!instance.options.disableCaretPositioning
|
||||
){
|
||||
/**
|
||||
* Tracks current cursor position
|
||||
* As keys are pressed, text will be added/removed at that position within the input.
|
||||
*/
|
||||
instance.caretPosition = event.target.selectionStart;
|
||||
|
||||
if(instance.options.debug){
|
||||
console.log("Caret at: ", event.target.selectionStart, event.target.tagName.toLowerCase(), `(${instance.keyboardDOMClass})`);
|
||||
}
|
||||
} else if(instance.options.disableCaretPositioning){
|
||||
/**
|
||||
* If we toggled off disableCaretPositioning, we must ensure caretPosition doesn't persist once reactivated.
|
||||
*/
|
||||
instance.caretPosition = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the callback function once simple-keyboard is rendered for the first time (on initialization).
|
||||
*/
|
||||
onInit(){
|
||||
if(this.options.debug){
|
||||
console.log(`${this.keyboardDOMClass} 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 layoutClass = `hg-layout-${this.options.layoutName}`;
|
||||
let layout = this.options.layout || KeyboardLayout.getDefaultLayout();
|
||||
let useTouchEvents = this.options.useTouchEvents || false
|
||||
|
||||
/**
|
||||
* Account for buttonTheme, if set
|
||||
@@ -119,17 +717,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 {
|
||||
@@ -141,53 +747,90 @@ 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) => {
|
||||
let rowArray = row.split(' ');
|
||||
layout[this.options.layoutName].forEach((row, rIndex) => {
|
||||
let rowArray = row.split(" ");
|
||||
|
||||
/**
|
||||
* Creating empty row
|
||||
*/
|
||||
var rowDOM = document.createElement('div');
|
||||
let rowDOM = document.createElement("div");
|
||||
rowDOM.className += "hg-row";
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
var buttonDOM = document.createElement('div');
|
||||
let buttonType = this.options.useButtonTag ? "button" : "div";
|
||||
let buttonDOM = document.createElement(buttonType);
|
||||
buttonDOM.className += `hg-button ${fctBtnClass}${buttonThemeClass ? " "+buttonThemeClass : ""}`;
|
||||
buttonDOM.onclick = () => this.handleButtonClicked(button);
|
||||
|
||||
if (useTouchEvents) {
|
||||
buttonDOM.ontouchstart = (e) => {
|
||||
this.handleButtonClicked(button);
|
||||
this.handleButtonMouseDown(button, e);
|
||||
}
|
||||
buttonDOM.ontouchend = e => this.handleButtonMouseUp();
|
||||
buttonDOM.ontouchcancel = e => this.handleButtonMouseUp();
|
||||
} else {
|
||||
buttonDOM.onclick = () => {
|
||||
this.isMouseHold = false;
|
||||
this.handleButtonClicked(button);
|
||||
}
|
||||
buttonDOM.onmousedown = (e) => {
|
||||
if (this.options.preventMouseDownDefault) e.preventDefault();
|
||||
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
|
||||
*/
|
||||
var buttonSpanDOM = document.createElement('span');
|
||||
let buttonSpanDOM = document.createElement('span');
|
||||
buttonSpanDOM.innerHTML = buttonDisplayName;
|
||||
buttonDOM.appendChild(buttonSpanDOM);
|
||||
|
||||
/**
|
||||
* Adding to buttonElements
|
||||
*/
|
||||
if(!this.buttonElements[button])
|
||||
this.buttonElements[button] = [];
|
||||
|
||||
this.buttonElements[button].push(buttonDOM);
|
||||
|
||||
/**
|
||||
* Appending button to row
|
||||
*/
|
||||
rowDOM.appendChild(buttonDOM);
|
||||
|
||||
/**
|
||||
* Calling onInit
|
||||
*/
|
||||
if(typeof this.options.onInit === "function")
|
||||
this.options.onInit();
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -195,6 +838,30 @@ 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
|
||||
*/
|
||||
if (!useTouchEvents) {
|
||||
document.onmouseup = () => this.handleButtonMouseUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calling onInit
|
||||
*/
|
||||
this.onInit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
992
src/lib/components/tests/Keyboard.test.js
Normal file
@@ -0,0 +1,992 @@
|
||||
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 will use touch events', () => {
|
||||
let touched = false
|
||||
|
||||
testUtil.clear()
|
||||
|
||||
document.body.innerHTML = `
|
||||
<div id="keyboard"></div>
|
||||
`;
|
||||
|
||||
const keyboard = new Keyboard('#keyboard', {
|
||||
useTouchEvents: true,
|
||||
onChange: () => touched = true,
|
||||
layout: {
|
||||
default: ["q"]
|
||||
}
|
||||
});
|
||||
|
||||
keyboard.getButtonElement("q").ontouchstart();
|
||||
keyboard.getButtonElement("q").ontouchend();
|
||||
keyboard.getButtonElement("q").ontouchcancel();
|
||||
|
||||
expect(keyboard.options.useTouchEvents).toBeTruthy();
|
||||
expect(touched).toBeTruthy();
|
||||
expect(keyboard.getInput()).toBe('q');
|
||||
})
|
||||
|
||||
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({
|
||||
useButtonTag: true
|
||||
});
|
||||
|
||||
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 will not set caretPosition on disableCaretPositioning', () => {
|
||||
testUtil.setDOM();
|
||||
|
||||
let keyboard = new Keyboard();
|
||||
|
||||
keyboard.caretEventHandler({
|
||||
charCode: 0,
|
||||
code: "KeyF",
|
||||
key: "f",
|
||||
which: 70,
|
||||
target: {
|
||||
tagName: "input",
|
||||
selectionStart: 3
|
||||
}
|
||||
});
|
||||
|
||||
expect(keyboard.caretPosition).toBe(3);
|
||||
|
||||
keyboard.setOptions({
|
||||
disableCaretPositioning: true
|
||||
});
|
||||
|
||||
keyboard.caretEventHandler({
|
||||
charCode: 0,
|
||||
code: "KeyF",
|
||||
key: "f",
|
||||
which: 70,
|
||||
target: {
|
||||
tagName: "input",
|
||||
selectionStart: 3
|
||||
}
|
||||
});
|
||||
|
||||
expect(keyboard.caretPosition).toBeFalsy();
|
||||
});
|
||||
|
||||
it('Keyboard caretEventHandler ignore positioning if input, textarea is blur', () => {
|
||||
testUtil.setDOM();
|
||||
|
||||
let keyboard = new Keyboard();
|
||||
|
||||
keyboard.isMouseHold = true;
|
||||
|
||||
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")
|
||||
});
|
||||
|
||||
var clickEvent = document.createEvent('MouseEvents');
|
||||
clickEvent.initEvent('mousedown', true, true);
|
||||
keyboard.getButtonElement("q").dispatchEvent(clickEvent);
|
||||
document.onmouseup();
|
||||
|
||||
});
|
||||
|
||||
it('Keyboard handleButtonMouseDown will work with preventMouseDownDefault', () => {
|
||||
testUtil.setDOM();
|
||||
|
||||
let keyboard = new Keyboard();
|
||||
|
||||
keyboard.options.preventMouseDownDefault = true;
|
||||
|
||||
keyboard.handleButtonMouseDown("q", {
|
||||
target: keyboard.getButtonElement("q")
|
||||
});
|
||||
|
||||
var clickEvent = document.createEvent('MouseEvents');
|
||||
clickEvent.initEvent('mousedown', true, true);
|
||||
keyboard.getButtonElement("q").dispatchEvent(clickEvent);
|
||||
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");
|
||||
});
|
||||
|
||||
it('Keyboard inputPattern will work globally', () => {
|
||||
testUtil.setDOM();
|
||||
|
||||
let keyboard = new Keyboard({
|
||||
inputPattern: /^\d+$/
|
||||
});
|
||||
|
||||
keyboard.getButtonElement("q").onclick();
|
||||
|
||||
expect(keyboard.getInput()).toBeFalsy();
|
||||
|
||||
keyboard.getButtonElement("1").onclick();
|
||||
|
||||
expect(keyboard.getInput()).toBe("1");
|
||||
});
|
||||
|
||||
it('Keyboard inputPattern will work by input name', () => {
|
||||
testUtil.setDOM();
|
||||
|
||||
let keyboard = new Keyboard({
|
||||
debug: true,
|
||||
inputName: "test1",
|
||||
inputPattern: {
|
||||
test1: /^\d+$/
|
||||
}
|
||||
});
|
||||
|
||||
keyboard.getButtonElement("q").onclick();
|
||||
keyboard.getButtonElement("1").onclick();
|
||||
|
||||
expect(keyboard.getInput()).toBe("1");
|
||||
|
||||
keyboard.setOptions({
|
||||
inputName: "default"
|
||||
});
|
||||
|
||||
keyboard.getButtonElement("q").onclick();
|
||||
keyboard.getButtonElement("1").onclick();
|
||||
|
||||
expect(keyboard.getInput()).toBe("q1");
|
||||
});
|
||||
@@ -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;
|
||||
97
src/lib/services/PhysicalKeyboard.js
Normal 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){
|
||||
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;
|
||||
@@ -1,92 +1,383 @@
|
||||
/**
|
||||
* 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.updateCaretPosAction = this.updateCaretPosAction.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}': 'delete',
|
||||
'{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
|
||||
* @param {boolean} moveCaret Whether to update simple-keyboard's cursor
|
||||
*/
|
||||
getUpdatedInput(button, input, options, caretPos, moveCaret){
|
||||
|
||||
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, moveCaret);
|
||||
|
||||
} else if(button === "{space}")
|
||||
output = this.addStringAt(output, " ", caretPos, moveCaret);
|
||||
|
||||
else if(button === "{tab}" && !(typeof options.tabCharOnTab === "boolean" && options.tabCharOnTab === false)){
|
||||
output = this.addStringAt(output, "\t", caretPos, moveCaret);
|
||||
|
||||
} else if((button === "{enter}" || button === "{numpadenter}") && options.newLineOnEnter)
|
||||
output = this.addStringAt(output, "\n", caretPos, moveCaret);
|
||||
|
||||
else if(button.includes("numpad") && Number.isInteger(Number(button[button.length - 2]))){
|
||||
output = this.addStringAt(output, button[button.length - 2], caretPos, moveCaret);
|
||||
}
|
||||
else if(button === "{numpaddivide}")
|
||||
output = this.addStringAt(output, '/', caretPos, moveCaret);
|
||||
|
||||
else if(button === "{numpadmultiply}")
|
||||
output = this.addStringAt(output, '*', caretPos, moveCaret);
|
||||
|
||||
else if(button === "{numpadsubtract}")
|
||||
output = this.addStringAt(output, '-', caretPos, moveCaret);
|
||||
|
||||
else if(button === "{numpadadd}")
|
||||
output = this.addStringAt(output, '+', caretPos, moveCaret);
|
||||
|
||||
else if(button === "{numpaddecimal}")
|
||||
output = this.addStringAt(output, '.', caretPos, moveCaret);
|
||||
|
||||
else if(button === "{" || button === "}")
|
||||
output = this.addStringAt(output, button, caretPos, moveCaret);
|
||||
|
||||
else if(!button.includes("{") && !button.includes("}"))
|
||||
output = output + button;
|
||||
output = this.addStringAt(output, button, caretPos, moveCaret);
|
||||
|
||||
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){
|
||||
let newCaretPos = this.updateCaretPosAction(this.simpleKeyboardInstance, length, minus);
|
||||
|
||||
if(this.simpleKeyboardInstance.options.syncInstanceInputs){
|
||||
this.simpleKeyboardInstance.dispatch(instance => {
|
||||
instance.caretPosition = newCaretPos;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Action method of updateCaretPos
|
||||
*
|
||||
* @param {object} instance The instance whose position should be updated
|
||||
* @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.
|
||||
*/
|
||||
updateCaretPosAction(instance, length, minus){
|
||||
if(minus){
|
||||
if(instance.caretPosition > 0)
|
||||
instance.caretPosition = instance.caretPosition - length;
|
||||
} else {
|
||||
instance.caretPosition = instance.caretPosition + length;
|
||||
}
|
||||
|
||||
if(this.simpleKeyboardInstance.options.debug){
|
||||
console.log("Caret at:", instance.caretPosition, `(${instance.keyboardDOMClass})`);
|
||||
}
|
||||
|
||||
return instance.caretPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param {boolean} moveCaret Whether to update simple-keyboard's cursor
|
||||
*/
|
||||
addStringAt(source, string, position, moveCaret){
|
||||
let output;
|
||||
|
||||
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()){
|
||||
if(moveCaret) 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
|
||||
* @param {boolean} moveCaret Whether to update simple-keyboard's cursor
|
||||
*/
|
||||
removeAt(source, position, moveCaret){
|
||||
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);
|
||||
if(moveCaret) this.updateCaretPos(2, true);
|
||||
} else {
|
||||
output = source.substr(0, (position - 1)) + source.substr(position);
|
||||
if(moveCaret) this.updateCaretPos(1, true);
|
||||
}
|
||||
} else {
|
||||
prevTwoChars = source.slice(-2);
|
||||
emojiMatched = prevTwoChars.match(emojiMatchedReg);
|
||||
|
||||
if(emojiMatched){
|
||||
output = source.slice(0, -2);
|
||||
if(moveCaret) this.updateCaretPos(2, true);
|
||||
} else {
|
||||
output = source.slice(0, -1);
|
||||
if(moveCaret) 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) =>
|
||||
word.length ? string + word[0].toUpperCase() + word.slice(1) : string
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 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;
|
||||
export default Utilities;
|
||||
|
||||
118
src/lib/services/tests/PhysicalKeyboard.test.js
Normal 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"
|
||||
}
|
||||
}));
|
||||
});
|
||||
486
src/lib/services/tests/Utilities.test.js
Normal file
@@ -0,0 +1,486 @@
|
||||
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.options.syncInstanceInputs = true;
|
||||
|
||||
keyboard.caretPosition = 5;
|
||||
keyboard.utilities.updateCaretPos(2, true);
|
||||
|
||||
expect(keyboard.caretPosition).toBe(3);
|
||||
});
|
||||
|
||||
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");
|
||||
|
||||
keyboard.setInput("test");
|
||||
keyboard.caretPosition = 5;
|
||||
keyboard.utilities.removeAt(keyboard.getInput(), 0, true);
|
||||
expect(keyboard.caretPosition).toBe(4);
|
||||
});
|
||||
|
||||
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");
|
||||
|
||||
keyboard.caretPosition = 6;
|
||||
output = keyboard.utilities.removeAt("test\uD83D\uDE00", 6, true);
|
||||
expect(keyboard.caretPosition).toBe(4);
|
||||
});
|
||||
|
||||
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();
|
||||
|
||||
output = keyboard.utilities.removeAt("\uD83D\uDE00", 0, true);
|
||||
expect(output).toBeFalsy();
|
||||
});
|
||||
|
||||
it('Keyboard removeAt will remove regular strings', () => {
|
||||
testUtil.setDOM();
|
||||
|
||||
let keyboard = new Keyboard({
|
||||
debug: true
|
||||
});
|
||||
|
||||
keyboard.caretPosition = 6;
|
||||
let output = keyboard.utilities.removeAt("testie", 6);
|
||||
expect(output).toBe("testi");
|
||||
|
||||
keyboard.caretPosition = 6;
|
||||
output = keyboard.utilities.removeAt("testie", 6, true);
|
||||
expect(keyboard.caretPosition).toBe(5);
|
||||
});
|
||||
|
||||
it('Keyboard will work with custom (and weird) class', () => {
|
||||
testUtil.setDOM("my--weird--class");
|
||||
let keyboard = new Keyboard(".my--weird--class");
|
||||
expect(keyboard.keyboardDOMClass).toBe("my--weird--class");
|
||||
});
|
||||