mirror of
https://github.com/hodgef/simple-keyboard.git
synced 2026-02-03 00:06:50 +08:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
652084cabb | ||
|
|
39c4acba85 | ||
|
|
69b830c632 | ||
|
|
cd909cffa8 | ||
|
|
92d2b381db | ||
|
|
96206d1b47 | ||
|
|
19f6ac9ac1 | ||
|
|
90b67ec416 | ||
|
|
6208d5f7e1 | ||
|
|
bd0274415b | ||
|
|
30941f4ba0 | ||
|
|
48a15e6715 | ||
|
|
f8ee859bb0 | ||
|
|
3012ce24e2 | ||
|
|
6e54729f46 | ||
|
|
5ab58f2528 | ||
|
|
47ddf0b1e8 |
@@ -6,7 +6,6 @@
|
||||
<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>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*!
|
||||
*
|
||||
* simple-keyboard v2.16.0
|
||||
* simple-keyboard v2.18.1
|
||||
* https://github.com/hodgef/simple-keyboard
|
||||
*
|
||||
* Copyright (c) Francisco Hodge (https://github.com/hodgef)
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
||||
/*!
|
||||
*
|
||||
* simple-keyboard v2.16.0 (Non-minified build)
|
||||
* simple-keyboard v2.18.1 (Non-minified build)
|
||||
* https://github.com/hodgef/simple-keyboard
|
||||
*
|
||||
* Copyright (c) Francisco Hodge (https://github.com/hodgef)
|
||||
|
||||
10
build/index.d.ts
vendored
10
build/index.d.ts
vendored
@@ -10,6 +10,11 @@ declare module 'simple-keyboard' {
|
||||
}
|
||||
|
||||
interface KeyboardOptions {
|
||||
/**
|
||||
* Utilities
|
||||
*/
|
||||
utilities?: any;
|
||||
|
||||
/**
|
||||
* Modify the keyboard layout.
|
||||
*/
|
||||
@@ -121,6 +126,11 @@ declare module 'simple-keyboard' {
|
||||
*/
|
||||
autoUseTouchEvents?: boolean;
|
||||
|
||||
/**
|
||||
* Opt out of PointerEvents handling, falling back to the prior mouse event logic.
|
||||
*/
|
||||
useMouseEvents?: boolean;
|
||||
|
||||
/**
|
||||
* Executes the callback function on key press. Returns button layout name (i.e.: "{shift}").
|
||||
*/
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
||||
/*!
|
||||
*
|
||||
* simple-keyboard v2.16.0 (Non-minified build)
|
||||
* simple-keyboard v2.18.1 (Non-minified build)
|
||||
* https://github.com/hodgef/simple-keyboard
|
||||
*
|
||||
* Copyright (c) Francisco Hodge (https://github.com/hodgef)
|
||||
@@ -660,6 +660,13 @@
|
||||
return "ontouchstart" in window || navigator.maxTouchPoints;
|
||||
}
|
||||
/**
|
||||
* Determines whether pointer events are supported
|
||||
*/ }, {
|
||||
key: "pointerEventsSupported",
|
||||
value: function pointerEventsSupported() {
|
||||
return window.PointerEvent;
|
||||
}
|
||||
/**
|
||||
* Bind all methods in a given class
|
||||
*/ }, {
|
||||
key: "camelCase",
|
||||
@@ -842,6 +849,7 @@
|
||||
* @property {object} inputPattern Restrains input(s) change to the defined regular expression pattern.
|
||||
* @property {boolean} useTouchEvents Instructs simple-keyboard to use touch events instead of click events.
|
||||
* @property {boolean} autoUseTouchEvents Enable useTouchEvents automatically when touch device is detected.
|
||||
* @property {boolean} useMouseEvents Opt out of PointerEvents handling, falling back to the prior mouse event logic.
|
||||
*/ this.options = options;
|
||||
this.options.layoutName = this.options.layoutName || "default";
|
||||
this.options.theme = this.options.theme || "hg-theme-default";
|
||||
@@ -941,6 +949,11 @@
|
||||
*/ }
|
||||
if (typeof this.options.onChange === "function") {
|
||||
this.options.onChange(this.input[this.options.inputName]);
|
||||
/**
|
||||
* Calling onChangeAll
|
||||
*/ }
|
||||
if (typeof this.options.onChangeAll === "function") {
|
||||
this.options.onChangeAll(this.input);
|
||||
}
|
||||
}
|
||||
if (debug) {
|
||||
@@ -1040,7 +1053,7 @@
|
||||
*/ if (this.options.syncInstanceInputs) {
|
||||
this.syncInstanceInputs(this.input);
|
||||
}
|
||||
return this.input[this.options.inputName];
|
||||
return this.input[inputName];
|
||||
}
|
||||
/**
|
||||
* Set the keyboard’s input.
|
||||
@@ -1363,6 +1376,20 @@
|
||||
}
|
||||
if (typeof this.options.beforeFirstRender === "function") {
|
||||
this.options.beforeFirstRender();
|
||||
/**
|
||||
* Notify about PointerEvents usage
|
||||
*/ }
|
||||
if (this.utilities.pointerEventsSupported() && !this.options.useTouchEvents && !this.options.useMouseEvents) {
|
||||
if (this.options.debug) {
|
||||
console.log("Using PointerEvents as it is supported by this browser");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Notify about touch events usage
|
||||
*/ if (this.options.useTouchEvents) {
|
||||
if (this.options.debug) {
|
||||
console.log("useTouchEvents has been enabled. Only touch events will be used.");
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
@@ -1437,6 +1464,7 @@
|
||||
var layout = this.options.layout || services_KeyboardLayout.getDefaultLayout();
|
||||
var useTouchEvents = this.options.useTouchEvents || false;
|
||||
var useTouchEventsClass = useTouchEvents ? "hg-touch-events" : "";
|
||||
var useMouseEvents = this.options.useMouseEvents || false;
|
||||
/**
|
||||
* Account for buttonTheme, if set
|
||||
*/ var buttonThemesParsed = Array.isArray(this.options.buttonTheme) ? this.getButtonTheme() : {};
|
||||
@@ -1462,28 +1490,53 @@
|
||||
*/ var buttonType = _this9.options.useButtonTag ? "button" : "div";
|
||||
var buttonDOM = document.createElement(buttonType);
|
||||
buttonDOM.className += "hg-button ".concat(fctBtnClass).concat(buttonThemeClass ? " " + buttonThemeClass : "");
|
||||
if (useTouchEvents) {
|
||||
buttonDOM.ontouchstart = function(e) {
|
||||
_this9.handleButtonClicked(button);
|
||||
_this9.handleButtonMouseDown(button, e);
|
||||
};
|
||||
buttonDOM.ontouchend = function(e) {
|
||||
return _this9.handleButtonMouseUp();
|
||||
};
|
||||
buttonDOM.ontouchcancel = function(e) {
|
||||
return _this9.handleButtonMouseUp();
|
||||
};
|
||||
} else {
|
||||
buttonDOM.onclick = function() {
|
||||
_this9.isMouseHold = false;
|
||||
_this9.handleButtonClicked(button);
|
||||
};
|
||||
buttonDOM.onmousedown = function(e) {
|
||||
/**
|
||||
* Handle button click event
|
||||
*/ /* istanbul ignore next */ if (_this9.utilities.pointerEventsSupported() && !useTouchEvents && !useMouseEvents) {
|
||||
/**
|
||||
* PointerEvents support
|
||||
*/ buttonDOM.onpointerdown = function(e) {
|
||||
if (_this9.options.preventMouseDownDefault) {
|
||||
e.preventDefault();
|
||||
}
|
||||
_this9.handleButtonClicked(button);
|
||||
_this9.handleButtonMouseDown(button, e);
|
||||
};
|
||||
buttonDOM.onpointerup = function(e) {
|
||||
if (_this9.options.preventMouseDownDefault) {
|
||||
e.preventDefault();
|
||||
}
|
||||
_this9.handleButtonMouseUp();
|
||||
};
|
||||
buttonDOM.onpointercancel = function(e) {
|
||||
return _this9.handleButtonMouseUp();
|
||||
};
|
||||
} else {
|
||||
/**
|
||||
* Fallback for browsers not supporting PointerEvents
|
||||
*/ if (useTouchEvents) {
|
||||
buttonDOM.ontouchstart = function(e) {
|
||||
_this9.handleButtonClicked(button);
|
||||
_this9.handleButtonMouseDown(button, e);
|
||||
};
|
||||
buttonDOM.ontouchend = function(e) {
|
||||
return _this9.handleButtonMouseUp();
|
||||
};
|
||||
buttonDOM.ontouchcancel = function(e) {
|
||||
return _this9.handleButtonMouseUp();
|
||||
};
|
||||
} else {
|
||||
buttonDOM.onclick = function() {
|
||||
_this9.isMouseHold = false;
|
||||
_this9.handleButtonClicked(button);
|
||||
};
|
||||
buttonDOM.onmousedown = function(e) {
|
||||
if (_this9.options.preventMouseDownDefault) {
|
||||
e.preventDefault();
|
||||
}
|
||||
_this9.handleButtonMouseDown(button, e);
|
||||
};
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Adding identifier
|
||||
|
||||
36
package-lock.json
generated
36
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "simple-keyboard",
|
||||
"version": "2.16.0",
|
||||
"version": "2.18.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -5312,7 +5312,7 @@
|
||||
},
|
||||
"duplexer": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
|
||||
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
|
||||
"integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
|
||||
"dev": true
|
||||
},
|
||||
@@ -13879,9 +13879,9 @@
|
||||
}
|
||||
},
|
||||
"react-dev-utils": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-7.0.3.tgz",
|
||||
"integrity": "sha512-KEFsH1CewnmddPLXIuU+QWKTH/hpJKZClL2+74XN54NkPnR2KnB5gGmuQ0E7DwcCkUpdMxxqBX+rB7aB5sZS4A==",
|
||||
"version": "7.0.5",
|
||||
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-7.0.5.tgz",
|
||||
"integrity": "sha512-zJnqqb0x6gd63E3xoz5pXAxBPNaW75Hyz7GgQp0qPhMroBCRQtRvG67AoTZZY1z4yCYVJQZAfQJFdnea0Ujbug==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "7.0.0",
|
||||
@@ -13902,7 +13902,7 @@
|
||||
"loader-utils": "1.2.3",
|
||||
"opn": "5.4.0",
|
||||
"pkg-up": "2.0.0",
|
||||
"react-error-overlay": "^5.1.3",
|
||||
"react-error-overlay": "^5.1.4",
|
||||
"recursive-readdir": "2.2.2",
|
||||
"shell-quote": "1.6.1",
|
||||
"sockjs-client": "1.3.0",
|
||||
@@ -13934,9 +13934,9 @@
|
||||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30000938",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000938.tgz",
|
||||
"integrity": "sha512-ekW8NQ3/FvokviDxhdKLZZAx7PptXNwxKgXtnR5y+PR3hckwuP3yJ1Ir+4/c97dsHNqtAyfKUGdw8P4EYzBNgw==",
|
||||
"version": "1.0.30000942",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000942.tgz",
|
||||
"integrity": "sha512-wLf+IhZUy2rfz48tc40OH7jHjXjnvDFEYqBHluINs/6MgzoNLPf25zhE4NOVzqxLKndf+hau81sAW0RcGHIaBQ==",
|
||||
"dev": true
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
@@ -14012,18 +14012,18 @@
|
||||
"dev": true
|
||||
},
|
||||
"node-releases": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.7.tgz",
|
||||
"integrity": "sha512-bKdrwaqJUPHqlCzDD7so/R+Nk0jGv9a11ZhLrD9f6i947qGLrGAhU3OxRENa19QQmwzGy/g6zCDEuLGDO8HPvA==",
|
||||
"version": "1.1.9",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.9.tgz",
|
||||
"integrity": "sha512-oic3GT4OtbWWKfRolz5Syw0Xus0KRFxeorLNj0s93ofX6PWyuzKjsiGxsCtWktBwwmTF6DdRRf2KreGqeOk5KA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"semver": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"p-limit": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz",
|
||||
"integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==",
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
|
||||
"integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-try": "^2.0.0"
|
||||
@@ -14068,9 +14068,9 @@
|
||||
}
|
||||
},
|
||||
"react-error-overlay": {
|
||||
"version": "5.1.3",
|
||||
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-5.1.3.tgz",
|
||||
"integrity": "sha512-GoqeM3Xadie7XUApXOjkY3Qhs8RkwB/Za4WMedBGrOKH1eTuKGyoAECff7jiVonJchOx6KZ9i8ILO5XIoHB+Tg==",
|
||||
"version": "5.1.4",
|
||||
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-5.1.4.tgz",
|
||||
"integrity": "sha512-fp+U98OMZcnduQ+NSEiQa4s/XMsbp+5KlydmkbESOw4P69iWZ68ZMFM5a2BuE0FgqPBKApJyRuYHR95jM8lAmg==",
|
||||
"dev": true
|
||||
},
|
||||
"read-pkg": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "simple-keyboard",
|
||||
"version": "2.16.0",
|
||||
"version": "2.19.0",
|
||||
"description": "On-screen Javascript Virtual Keyboard",
|
||||
"main": "build/index.js",
|
||||
"types": "build/index.d.ts",
|
||||
|
||||
10
src/lib/@types/index.d.ts
vendored
10
src/lib/@types/index.d.ts
vendored
@@ -10,6 +10,11 @@ declare module 'simple-keyboard' {
|
||||
}
|
||||
|
||||
interface KeyboardOptions {
|
||||
/**
|
||||
* Utilities
|
||||
*/
|
||||
utilities?: any;
|
||||
|
||||
/**
|
||||
* Modify the keyboard layout.
|
||||
*/
|
||||
@@ -121,6 +126,11 @@ declare module 'simple-keyboard' {
|
||||
*/
|
||||
autoUseTouchEvents?: boolean;
|
||||
|
||||
/**
|
||||
* Opt out of PointerEvents handling, falling back to the prior mouse event logic.
|
||||
*/
|
||||
useMouseEvents?: boolean;
|
||||
|
||||
/**
|
||||
* Executes the callback function on key press. Returns button layout name (i.e.: "{shift}").
|
||||
*/
|
||||
|
||||
@@ -26,6 +26,18 @@ html {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.simple-keyboard .hg-row .hg-button-container {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.simple-keyboard .hg-row > div:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.simple-keyboard .hg-row .hg-button-container {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.simple-keyboard .hg-button {
|
||||
display: inline-block;
|
||||
flex-grow: 1;
|
||||
|
||||
@@ -63,6 +63,7 @@ class SimpleKeyboard {
|
||||
* @property {object} inputPattern Restrains input(s) change to the defined regular expression pattern.
|
||||
* @property {boolean} useTouchEvents Instructs simple-keyboard to use touch events instead of click events.
|
||||
* @property {boolean} autoUseTouchEvents Enable useTouchEvents automatically when touch device is detected.
|
||||
* @property {boolean} useMouseEvents Opt out of PointerEvents handling, falling back to the prior mouse event logic.
|
||||
*/
|
||||
this.options = options;
|
||||
this.options.layoutName = this.options.layoutName || "default";
|
||||
@@ -207,6 +208,12 @@ class SimpleKeyboard {
|
||||
*/
|
||||
if (typeof this.options.onChange === "function")
|
||||
this.options.onChange(this.input[this.options.inputName]);
|
||||
|
||||
/**
|
||||
* Calling onChangeAll
|
||||
*/
|
||||
if (typeof this.options.onChangeAll === "function")
|
||||
this.options.onChangeAll(this.input);
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
@@ -312,7 +319,7 @@ class SimpleKeyboard {
|
||||
*/
|
||||
if (this.options.syncInstanceInputs) this.syncInstanceInputs(this.input);
|
||||
|
||||
return this.input[this.options.inputName];
|
||||
return this.input[inputName];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -717,6 +724,30 @@ class SimpleKeyboard {
|
||||
|
||||
if (typeof this.options.beforeFirstRender === "function")
|
||||
this.options.beforeFirstRender();
|
||||
|
||||
/**
|
||||
* Notify about PointerEvents usage
|
||||
*/
|
||||
if (
|
||||
this.utilities.pointerEventsSupported() &&
|
||||
!this.options.useTouchEvents &&
|
||||
!this.options.useMouseEvents
|
||||
) {
|
||||
if (this.options.debug) {
|
||||
console.log("Using PointerEvents as it is supported by this browser");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify about touch events usage
|
||||
*/
|
||||
if (this.options.useTouchEvents) {
|
||||
if (this.options.debug) {
|
||||
console.log(
|
||||
"useTouchEvents has been enabled. Only touch events will be used."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -782,18 +813,104 @@ class SimpleKeyboard {
|
||||
/**
|
||||
* Get module prop
|
||||
*/
|
||||
getModuleProp = (name, prop) => {
|
||||
getModuleProp(name, prop) {
|
||||
if (!this.modules[name]) return false;
|
||||
|
||||
return this.modules[name][prop];
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* getModulesList
|
||||
*/
|
||||
getModulesList = () => {
|
||||
getModulesList() {
|
||||
return Object.keys(this.modules);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse Row DOM containers
|
||||
*/
|
||||
parseRowDOMContainers(
|
||||
rowDOM,
|
||||
rowIndex,
|
||||
containerStartIndexes,
|
||||
containerEndIndexes
|
||||
) {
|
||||
let rowDOMArray = Array.from(rowDOM.children);
|
||||
let removedElements = 0;
|
||||
|
||||
if (rowDOMArray.length) {
|
||||
containerStartIndexes.forEach((startIndex, arrIndex) => {
|
||||
let endIndex = containerEndIndexes[arrIndex];
|
||||
|
||||
/**
|
||||
* If there exists a respective end index
|
||||
* if end index comes after start index
|
||||
*/
|
||||
if (!endIndex || !(endIndex > startIndex)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updated startIndex, endIndex
|
||||
* This is since the removal of buttons to place a single button container
|
||||
* results in a modified array size
|
||||
*/
|
||||
let updated_startIndex = startIndex - removedElements;
|
||||
let updated_endIndex = endIndex - removedElements;
|
||||
|
||||
/**
|
||||
* Create button container
|
||||
*/
|
||||
let containerDOM = document.createElement("div");
|
||||
containerDOM.className += "hg-button-container";
|
||||
let containerUID = `${
|
||||
this.options.layoutName
|
||||
}-r${rowIndex}c${arrIndex}`;
|
||||
containerDOM.setAttribute("data-skUID", containerUID);
|
||||
|
||||
/**
|
||||
* Taking elements due to be inserted into container
|
||||
*/
|
||||
let containedElements = rowDOMArray.splice(
|
||||
updated_startIndex,
|
||||
updated_endIndex - updated_startIndex + 1
|
||||
);
|
||||
removedElements = updated_endIndex - updated_startIndex;
|
||||
|
||||
/**
|
||||
* Inserting elements to container
|
||||
*/
|
||||
containedElements.forEach(element => containerDOM.appendChild(element));
|
||||
|
||||
/**
|
||||
* Adding container at correct position within rowDOMArray
|
||||
*/
|
||||
rowDOMArray.splice(updated_startIndex, 0, containerDOM);
|
||||
|
||||
/**
|
||||
* Clearing old rowDOM children structure
|
||||
*/
|
||||
rowDOM.innerHTML = "";
|
||||
|
||||
/**
|
||||
* Appending rowDOM new children list
|
||||
*/
|
||||
rowDOMArray.forEach(element => rowDOM.appendChild(element));
|
||||
|
||||
if (this.options.debug) {
|
||||
console.log(
|
||||
"rowDOMContainer",
|
||||
containedElements,
|
||||
updated_startIndex,
|
||||
updated_endIndex,
|
||||
removedElements + 1
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return rowDOM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders rows and buttons as per options
|
||||
@@ -820,6 +937,8 @@ class SimpleKeyboard {
|
||||
let layout = this.options.layout || KeyboardLayout.getDefaultLayout();
|
||||
let useTouchEvents = this.options.useTouchEvents || false;
|
||||
let useTouchEventsClass = useTouchEvents ? "hg-touch-events" : "";
|
||||
let useMouseEvents = this.options.useMouseEvents || false;
|
||||
let disableRowButtonContainers = this.options.disableRowButtonContainers;
|
||||
|
||||
/**
|
||||
* Account for buttonTheme, if set
|
||||
@@ -847,10 +966,52 @@ class SimpleKeyboard {
|
||||
let rowDOM = document.createElement("div");
|
||||
rowDOM.className += "hg-row";
|
||||
|
||||
/**
|
||||
* Tracking container indicators in rows
|
||||
*/
|
||||
let containerStartIndexes = [];
|
||||
let containerEndIndexes = [];
|
||||
|
||||
/**
|
||||
* Iterating through each button in row
|
||||
*/
|
||||
rowArray.forEach((button, bIndex) => {
|
||||
/**
|
||||
* Check if button has a container indicator
|
||||
*/
|
||||
let buttonHasContainerStart =
|
||||
!disableRowButtonContainers &&
|
||||
button.includes("[") &&
|
||||
button.length > 1;
|
||||
let buttonHasContainerEnd =
|
||||
!disableRowButtonContainers &&
|
||||
button.includes("]") &&
|
||||
button.length > 1;
|
||||
|
||||
/**
|
||||
* Save container start index, if applicable
|
||||
*/
|
||||
if (buttonHasContainerStart) {
|
||||
containerStartIndexes.push(bIndex);
|
||||
|
||||
/**
|
||||
* Removing indicator
|
||||
*/
|
||||
button = button.replace(/\[/g, "");
|
||||
}
|
||||
|
||||
if (buttonHasContainerEnd) {
|
||||
containerEndIndexes.push(bIndex);
|
||||
|
||||
/**
|
||||
* Removing indicator
|
||||
*/
|
||||
button = button.replace(/\]/g, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Processing button options
|
||||
*/
|
||||
let fctBtnClass = this.utilities.getButtonClass(button);
|
||||
let buttonThemeClass = buttonThemesParsed[button];
|
||||
let buttonDisplayName = this.utilities.getButtonDisplayName(
|
||||
@@ -868,22 +1029,49 @@ class SimpleKeyboard {
|
||||
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 => {
|
||||
/**
|
||||
* Handle button click event
|
||||
*/
|
||||
/* istanbul ignore next */
|
||||
if (
|
||||
this.utilities.pointerEventsSupported() &&
|
||||
!useTouchEvents &&
|
||||
!useMouseEvents
|
||||
) {
|
||||
/**
|
||||
* PointerEvents support
|
||||
*/
|
||||
buttonDOM.onpointerdown = e => {
|
||||
if (this.options.preventMouseDownDefault) e.preventDefault();
|
||||
this.handleButtonClicked(button);
|
||||
this.handleButtonMouseDown(button, e);
|
||||
};
|
||||
buttonDOM.onpointerup = e => {
|
||||
if (this.options.preventMouseDownDefault) e.preventDefault();
|
||||
this.handleButtonMouseUp();
|
||||
};
|
||||
buttonDOM.onpointercancel = e => this.handleButtonMouseUp();
|
||||
} else {
|
||||
/**
|
||||
* Fallback for browsers not supporting PointerEvents
|
||||
*/
|
||||
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);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -923,6 +1111,16 @@ class SimpleKeyboard {
|
||||
rowDOM.appendChild(buttonDOM);
|
||||
});
|
||||
|
||||
/**
|
||||
* Parse containers in row
|
||||
*/
|
||||
rowDOM = this.parseRowDOMContainers(
|
||||
rowDOM,
|
||||
rIndex,
|
||||
containerStartIndexes,
|
||||
containerEndIndexes
|
||||
);
|
||||
|
||||
/**
|
||||
* Appending row to keyboard
|
||||
*/
|
||||
|
||||
@@ -186,6 +186,22 @@ it('Keyboard onChange will work', () => {
|
||||
expect(output).toBe("q");
|
||||
});
|
||||
|
||||
it('Keyboard onChangeAll will work', () => {
|
||||
testUtil.setDOM();
|
||||
|
||||
let output;
|
||||
|
||||
let keyboard = new Keyboard({
|
||||
onChangeAll: (input) => {
|
||||
output = input ? input.default : null;
|
||||
}
|
||||
});
|
||||
|
||||
keyboard.getButtonElement("q").onclick();
|
||||
|
||||
expect(output).toBe("q");
|
||||
});
|
||||
|
||||
it('Keyboard clearInput will work', () => {
|
||||
testUtil.setDOM();
|
||||
|
||||
@@ -1023,6 +1039,23 @@ it('Keyboard beforeFirstRender method will work', () => {
|
||||
expect(timesCalled).toBe(1);
|
||||
});
|
||||
|
||||
it('Keyboard beforeFirstRender will show PointerEvents warning', () => {
|
||||
testUtil.setDOM();
|
||||
|
||||
let timesCalled = 0;
|
||||
|
||||
window.PointerEvent = window.PointerEvent ? window.PointerEvent : () => {};
|
||||
|
||||
let keyboard = new Keyboard({
|
||||
debug: true,
|
||||
beforeFirstRender: () => {
|
||||
timesCalled++;
|
||||
}
|
||||
});
|
||||
|
||||
expect(timesCalled).toBe(1);
|
||||
});
|
||||
|
||||
it('Keyboard beforeRender method will work', () => {
|
||||
testUtil.setDOM();
|
||||
|
||||
@@ -1042,4 +1075,100 @@ it('Keyboard beforeRender method will work', () => {
|
||||
});
|
||||
|
||||
expect(timesCalled).toBe(2);
|
||||
});
|
||||
|
||||
it('Keyboard parseRowDOMContainers will work', () => {
|
||||
testUtil.setDOM();
|
||||
|
||||
let keyboard = new Keyboard({
|
||||
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} {arrowleft} [{arrowup} {arrowdown}] {arrowright}'
|
||||
],
|
||||
'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}'
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
let containers = Array.from(document.querySelectorAll(".hg-button-container"));
|
||||
|
||||
expect(containers.length).toBe(5);
|
||||
|
||||
keyboard.setOptions({
|
||||
debug: true
|
||||
});
|
||||
|
||||
expect(containers.length).toBe(5);
|
||||
});
|
||||
|
||||
it('Keyboard parseRowDOMContainers will ignore empty rows', () => {
|
||||
testUtil.setDOM();
|
||||
|
||||
let failed = false;
|
||||
|
||||
try {
|
||||
let keyboard = new Keyboard();
|
||||
keyboard.parseRowDOMContainers({
|
||||
children: []
|
||||
});
|
||||
} catch (e) {
|
||||
failed = true;
|
||||
}
|
||||
|
||||
expect(failed).toBeFalsy();
|
||||
});
|
||||
|
||||
|
||||
it('Keyboard parseRowDOMContainers will ignore missing endIndex or endIndex before startIndex', () => {
|
||||
testUtil.setDOM();
|
||||
|
||||
let keyboard = new Keyboard({
|
||||
layout: {
|
||||
'default': [
|
||||
'` [1 2 3 4 5 6 7 8 9 0 - = {bksp}',
|
||||
'` 1 2 3] 4 5 6 7 8 9 [0 - = {bksp}',
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
let containers = Array.from(document.querySelectorAll(".hg-button-container"));
|
||||
|
||||
expect(containers.length).toBe(0);
|
||||
});
|
||||
|
||||
it('Keyboard disableRowButtonContainers will bypass parseRowDOMContainers', () => {
|
||||
testUtil.setDOM();
|
||||
|
||||
let keyboard = new Keyboard({
|
||||
disableRowButtonContainers: true,
|
||||
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} {arrowleft} [{arrowup} {arrowdown}] {arrowright}'
|
||||
],
|
||||
'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}'
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
let containers = Array.from(document.querySelectorAll(".hg-button-container"));
|
||||
|
||||
expect(containers.length).toBe(0);
|
||||
});
|
||||
@@ -372,6 +372,13 @@ class Utilities {
|
||||
return "ontouchstart" in window || navigator.maxTouchPoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether pointer events are supported
|
||||
*/
|
||||
pointerEventsSupported() {
|
||||
return window.PointerEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind all methods in a given class
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user