simple-keyboard/build/index.js.map
2020-10-16 00:09:09 -04:00

1 line
94 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{"version":3,"sources":["../../webpack/universalModuleDefinition","../../webpack/bootstrap","services/Utilities.js","services/PhysicalKeyboard.js","components/Keyboard.js","services/KeyboardLayout.js","index.js"],"names":["root","factory","exports","module","define","amd","this","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","Utilities","getOptions","getCaretPosition","getCaretPositionEnd","dispatch","bindMethods","myClass","instance","getOwnPropertyNames","myMethod","button","buttonTypeClass","includes","buttonWithoutBraces","replace","buttonNormalized","display","mergeDisplay","assign","getDefaultDiplay","input","caretPos","caretPosEnd","moveCaret","options","commonParams","output","length","removeAt","addStringAt","tabCharOnTab","newLineOnEnter","Number","isInteger","minus","newCaretPos","updateCaretPosAction","setCaretPosition","caretPosition","debug","console","log","keyboardDOMClass","source","str","position","positionEnd","slice","join","isMaxLengthReached","updateCaretPos","emojiMatchedReg","substring","match","substr","inputObj","updatedInput","maxLength","currentInput","inputName","condition","maxLengthReached","Boolean","window","navigator","maxTouchPoints","PointerEvent","toLowerCase","trim","split","reduce","word","toUpperCase","PhysicalKeyboard","event","buttonPressed","getSimpleKeyboardLayoutKey","buttonDOM","getButtonElement","style","backgroundColor","physicalKeyboardHighlightBgColor","color","physicalKeyboardHighlightTextColor","removeAttribute","code","SimpleKeyboard","params","keyboardDOM","document","querySelector","HTMLDivElement","className","warn","Error","caretPositionEnd","initCallback","baseDOMClasses","keyboardClasses","filter","DOMClass","handleParams","utilities","layoutName","theme","preventMouseDownDefault","keyboardPluginClasses","buttonElements","currentInstanceName","camelCase","allKeyboardInstances","keyboardInstanceNames","keys","isFirstKeyboardInstance","physicalKeyboard","render","loadModules","endPosition","onKeyPress","getUpdatedInput","inputPattern","inputPatternIsValid","handleMaxLength","getAllInputs","syncInstanceInputs","onChange","getInput","onChangeAll","e","preventDefault","stopMouseDownPropagation","stopPropagation","target","classList","add","activeButtonClass","holdInteractionTimeout","clearTimeout","holdTimeout","isMouseHold","disableButtonHold","setTimeout","handleButtonHold","preventMouseUpDefault","stopMouseUpPropagation","recurseButtons","buttonElement","remove","onKeyReleased","handleButtonClicked","replaceInput","skipSync","rtl","inputWithoutRTLControl","forEach","changedOptions","onSetOptions","newOptions","optionName","JSON","stringify","innerHTML","callback","buttons","classNameItem","buttonTheme","classNameFound","map","class","buttonThemeArray","push","Array","isArray","index","filteredButtonArray","item","splice","buttonArr","inputVal","inputPatternRaw","RegExp","didInputMatch","test","addEventListener","handleKeyUp","handleKeyDown","handleMouseUp","handleTouchEnd","caretEventHandler","physicalKeyboardHighlight","handleHighlightKeyUp","handleHighlightKeyDown","targetTagName","tagName","isKeyboard","contains","disableCaretPositioning","selectionStart","selectionEnd","fn","buttonName","removeEventListener","onpointerup","ontouchend","ontouchcancel","onmouseup","deleteButton","onpointerdown","onpointercancel","ontouchstart","onclick","onmousedown","clear","initialized","buttonClasses","themeObj","themeObjClasses","buttonAttributes","attrObj","attribute","processAutoTouchEvents","disableContextualWindow","oncontextmenu","autoUseTouchEvents","useTouchEvents","setEventListeners","onInit","isTouchDevice","onTouchDeviceDetected","beforeFirstRender","pointerEventsSupported","useMouseEvents","beforeRender","onRender","onModulesLoaded","KeyboardModule","keyboardModule","constructor","classStr","init","prop","rowDOM","rowIndex","containerStartIndexes","containerEndIndexes","rowDOMArray","from","children","removedElements","startIndex","arrIndex","endIndex","updated_startIndex","updated_endIndex","containerDOM","createElement","containerUID","setAttribute","containedElements","element","appendChild","layoutClass","layout","default","shift","useTouchEventsClass","disableRowButtonContainers","getKeyboardClassString","row","rIndex","rowArray","bIndex","buttonHasContainerStart","indexOf","buttonHasContainerEnd","fctBtnClass","getButtonClass","buttonDisplayName","getButtonDisplayName","buttonType","useButtonTag","getButtonThemeClasses","setDOMButtonAttributes","handleButtonMouseDown","handleButtonMouseUp","buttonUID","buttonSpanDOM","parseRowDOMContainers","handleKeyboardContainerMouseDown"],"mappings":"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","file":"index.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"SimpleKeyboard\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"SimpleKeyboard\"] = factory();\n\telse\n\t\troot[\"SimpleKeyboard\"] = factory();\n})(this, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","/**\r\n * Utility Service\r\n */\r\nclass Utilities {\r\n /**\r\n * Creates an instance of the Utility service\r\n */\r\n constructor({ getOptions, getCaretPosition, getCaretPositionEnd, dispatch }) {\r\n this.getOptions = getOptions;\r\n this.getCaretPosition = getCaretPosition;\r\n this.getCaretPositionEnd = getCaretPositionEnd;\r\n this.dispatch = dispatch;\r\n\r\n /**\r\n * Bindings\r\n */\r\n Utilities.bindMethods(Utilities, this);\r\n }\r\n\r\n /**\r\n * Adds default classes to a given button\r\n *\r\n * @param {string} button The button's layout name\r\n * @return {string} The classes to be added to the button\r\n */\r\n getButtonClass(button) {\r\n const buttonTypeClass =\r\n button.includes(\"{\") && button.includes(\"}\") && button !== \"{//}\"\r\n ? \"functionBtn\"\r\n : \"standardBtn\";\r\n const buttonWithoutBraces = button.replace(\"{\", \"\").replace(\"}\", \"\");\r\n let buttonNormalized = \"\";\r\n\r\n if (buttonTypeClass !== \"standardBtn\")\r\n buttonNormalized = ` hg-button-${buttonWithoutBraces}`;\r\n\r\n return `hg-${buttonTypeClass}${buttonNormalized}`;\r\n }\r\n\r\n /**\r\n * Default button display labels\r\n */\r\n getDefaultDiplay() {\r\n return {\r\n \"{bksp}\": \"backspace\",\r\n \"{backspace}\": \"backspace\",\r\n \"{enter}\": \"< enter\",\r\n \"{shift}\": \"shift\",\r\n \"{shiftleft}\": \"shift\",\r\n \"{shiftright}\": \"shift\",\r\n \"{alt}\": \"alt\",\r\n \"{s}\": \"shift\",\r\n \"{tab}\": \"tab\",\r\n \"{lock}\": \"caps\",\r\n \"{capslock}\": \"caps\",\r\n \"{accept}\": \"Submit\",\r\n \"{space}\": \" \",\r\n \"{//}\": \" \",\r\n \"{esc}\": \"esc\",\r\n \"{escape}\": \"esc\",\r\n \"{f1}\": \"f1\",\r\n \"{f2}\": \"f2\",\r\n \"{f3}\": \"f3\",\r\n \"{f4}\": \"f4\",\r\n \"{f5}\": \"f5\",\r\n \"{f6}\": \"f6\",\r\n \"{f7}\": \"f7\",\r\n \"{f8}\": \"f8\",\r\n \"{f9}\": \"f9\",\r\n \"{f10}\": \"f10\",\r\n \"{f11}\": \"f11\",\r\n \"{f12}\": \"f12\",\r\n \"{numpaddivide}\": \"/\",\r\n \"{numlock}\": \"lock\",\r\n \"{arrowup}\": \"↑\",\r\n \"{arrowleft}\": \"←\",\r\n \"{arrowdown}\": \"↓\",\r\n \"{arrowright}\": \"→\",\r\n \"{prtscr}\": \"print\",\r\n \"{scrolllock}\": \"scroll\",\r\n \"{pause}\": \"pause\",\r\n \"{insert}\": \"ins\",\r\n \"{home}\": \"home\",\r\n \"{pageup}\": \"up\",\r\n \"{delete}\": \"del\",\r\n \"{end}\": \"end\",\r\n \"{pagedown}\": \"down\",\r\n \"{numpadmultiply}\": \"*\",\r\n \"{numpadsubtract}\": \"-\",\r\n \"{numpadadd}\": \"+\",\r\n \"{numpadenter}\": \"enter\",\r\n \"{period}\": \".\",\r\n \"{numpaddecimal}\": \".\",\r\n \"{numpad0}\": \"0\",\r\n \"{numpad1}\": \"1\",\r\n \"{numpad2}\": \"2\",\r\n \"{numpad3}\": \"3\",\r\n \"{numpad4}\": \"4\",\r\n \"{numpad5}\": \"5\",\r\n \"{numpad6}\": \"6\",\r\n \"{numpad7}\": \"7\",\r\n \"{numpad8}\": \"8\",\r\n \"{numpad9}\": \"9\"\r\n };\r\n }\r\n /**\r\n * Returns the display (label) name for a given button\r\n *\r\n * @param {string} button The button's layout name\r\n * @param {object} display The provided display option\r\n * @param {boolean} mergeDisplay Whether the provided param value should be merged with the default one.\r\n */\r\n getButtonDisplayName(button, display, mergeDisplay) {\r\n if (mergeDisplay) {\r\n display = Object.assign({}, this.getDefaultDiplay(), display);\r\n } else {\r\n display = display || this.getDefaultDiplay();\r\n }\r\n\r\n return display[button] || button;\r\n }\r\n\r\n /**\r\n * Returns the updated input resulting from clicking a given button\r\n *\r\n * @param {string} button The button's layout name\r\n * @param {string} input The input string\r\n * @param {number} caretPos The cursor's current position\r\n * @param {number} caretPosEnd The cursor's current end position\r\n * @param {boolean} moveCaret Whether to update simple-keyboard's cursor\r\n */\r\n getUpdatedInput(\r\n button,\r\n input,\r\n caretPos,\r\n caretPosEnd = caretPos,\r\n moveCaret = false\r\n ) {\r\n const options = this.getOptions();\r\n const commonParams = [caretPos, caretPosEnd, moveCaret];\r\n\r\n let output = input;\r\n\r\n if (\r\n (button === \"{bksp}\" || button === \"{backspace}\") &&\r\n output.length > 0\r\n ) {\r\n output = this.removeAt(output, ...commonParams);\r\n } else if (button === \"{space}\")\r\n output = this.addStringAt(output, \" \", ...commonParams);\r\n else if (\r\n button === \"{tab}\" &&\r\n !(\r\n typeof options.tabCharOnTab === \"boolean\" &&\r\n options.tabCharOnTab === false\r\n )\r\n ) {\r\n output = this.addStringAt(output, \"\\t\", ...commonParams);\r\n } else if (\r\n (button === \"{enter}\" || button === \"{numpadenter}\") &&\r\n options.newLineOnEnter\r\n )\r\n output = this.addStringAt(output, \"\\n\", ...commonParams);\r\n else if (\r\n button.includes(\"numpad\") &&\r\n Number.isInteger(Number(button[button.length - 2]))\r\n ) {\r\n output = this.addStringAt(\r\n output,\r\n button[button.length - 2],\r\n ...commonParams\r\n );\r\n } else if (button === \"{numpaddivide}\")\r\n output = this.addStringAt(output, \"/\", ...commonParams);\r\n else if (button === \"{numpadmultiply}\")\r\n output = this.addStringAt(output, \"*\", ...commonParams);\r\n else if (button === \"{numpadsubtract}\")\r\n output = this.addStringAt(output, \"-\", ...commonParams);\r\n else if (button === \"{numpadadd}\")\r\n output = this.addStringAt(output, \"+\", ...commonParams);\r\n else if (button === \"{numpaddecimal}\")\r\n output = this.addStringAt(output, \".\", ...commonParams);\r\n else if (button === \"{\" || button === \"}\")\r\n output = this.addStringAt(output, button, ...commonParams);\r\n else if (!button.includes(\"{\") && !button.includes(\"}\"))\r\n output = this.addStringAt(output, button, ...commonParams);\r\n\r\n return output;\r\n }\r\n\r\n /**\r\n * Moves the cursor position by a given amount\r\n *\r\n * @param {number} length Represents by how many characters the input should be moved\r\n * @param {boolean} minus Whether the cursor should be moved to the left or not.\r\n */\r\n updateCaretPos(length, minus) {\r\n const newCaretPos = this.updateCaretPosAction(length, minus);\r\n\r\n this.dispatch(instance => {\r\n instance.setCaretPosition(newCaretPos);\r\n });\r\n }\r\n\r\n /**\r\n * Action method of updateCaretPos\r\n *\r\n * @param {number} length Represents by how many characters the input should be moved\r\n * @param {boolean} minus Whether the cursor should be moved to the left or not.\r\n */\r\n updateCaretPosAction(length, minus) {\r\n const options = this.getOptions();\r\n let caretPosition = this.getCaretPosition();\r\n\r\n if (minus) {\r\n if (caretPosition > 0) caretPosition = caretPosition - length;\r\n } else {\r\n caretPosition = caretPosition + length;\r\n }\r\n\r\n if (options.debug) {\r\n console.log(\"Caret at:\", caretPosition, `(${this.keyboardDOMClass})`);\r\n }\r\n\r\n return caretPosition;\r\n }\r\n\r\n /**\r\n * Adds a string to the input at a given position\r\n *\r\n * @param {string} source The source input\r\n * @param {string} str The string to add\r\n * @param {number} position The (cursor) position where the string should be added\r\n * @param {boolean} moveCaret Whether to update simple-keyboard's cursor\r\n */\r\n addStringAt(\r\n source,\r\n str,\r\n position = source.length,\r\n positionEnd = source.length,\r\n moveCaret = false\r\n ) {\r\n let output;\r\n\r\n if (!position && position !== 0) {\r\n output = source + str;\r\n } else {\r\n output = [source.slice(0, position), str, source.slice(positionEnd)].join(\r\n \"\"\r\n );\r\n\r\n /**\r\n * Avoid caret position change when maxLength is set\r\n */\r\n if (!this.isMaxLengthReached()) {\r\n if (moveCaret) this.updateCaretPos(str.length);\r\n }\r\n }\r\n\r\n return output;\r\n }\r\n\r\n /**\r\n * Removes an amount of characters at a given position\r\n *\r\n * @param {string} source The source input\r\n * @param {number} position The (cursor) position from where the characters should be removed\r\n * @param {boolean} moveCaret Whether to update simple-keyboard's cursor\r\n */\r\n removeAt(\r\n source,\r\n position = source.length,\r\n positionEnd = source.length,\r\n moveCaret = false\r\n ) {\r\n if (position === 0 && positionEnd === 0) {\r\n return source;\r\n }\r\n\r\n let output;\r\n\r\n if (position === positionEnd) {\r\n let prevTwoChars;\r\n let emojiMatched;\r\n const emojiMatchedReg = /([\\uD800-\\uDBFF][\\uDC00-\\uDFFF])/g;\r\n\r\n /**\r\n * Emojis are made out of two characters, so we must take a custom approach to trim them.\r\n * For more info: https://mathiasbynens.be/notes/javascript-unicode\r\n */\r\n if (position && position >= 0) {\r\n prevTwoChars = source.substring(position - 2, position);\r\n emojiMatched = prevTwoChars.match(emojiMatchedReg);\r\n\r\n if (emojiMatched) {\r\n output = source.substr(0, position - 2) + source.substr(position);\r\n if (moveCaret) this.updateCaretPos(2, true);\r\n } else {\r\n output = source.substr(0, position - 1) + source.substr(position);\r\n if (moveCaret) this.updateCaretPos(1, true);\r\n }\r\n } else {\r\n prevTwoChars = source.slice(-2);\r\n emojiMatched = prevTwoChars.match(emojiMatchedReg);\r\n\r\n if (emojiMatched) {\r\n output = source.slice(0, -2);\r\n if (moveCaret) this.updateCaretPos(2, true);\r\n } else {\r\n output = source.slice(0, -1);\r\n if (moveCaret) this.updateCaretPos(1, true);\r\n }\r\n }\r\n } else {\r\n output = source.slice(0, position) + source.slice(positionEnd);\r\n if (moveCaret) {\r\n this.dispatch(instance => {\r\n instance.setCaretPosition(position);\r\n });\r\n }\r\n }\r\n\r\n return output;\r\n }\r\n /**\r\n * Determines whether the maxLength has been reached. This function is called when the maxLength option it set.\r\n *\r\n * @param {object} inputObj\r\n * @param {string} updatedInput\r\n */\r\n handleMaxLength(inputObj, updatedInput) {\r\n const options = this.getOptions();\r\n const maxLength = options.maxLength;\r\n const currentInput = inputObj[options.inputName];\r\n const condition = updatedInput.length - 1 >= maxLength;\r\n\r\n if (\r\n /**\r\n * If pressing this button won't add more characters\r\n * We exit out of this limiter function\r\n */\r\n updatedInput.length <= currentInput.length\r\n ) {\r\n return false;\r\n }\r\n\r\n if (Number.isInteger(maxLength)) {\r\n if (options.debug) {\r\n console.log(\"maxLength (num) reached:\", condition);\r\n }\r\n\r\n if (condition) {\r\n /**\r\n * @type {boolean} Boolean value that shows whether maxLength has been reached\r\n */\r\n this.maxLengthReached = true;\r\n return true;\r\n } else {\r\n this.maxLengthReached = false;\r\n return false;\r\n }\r\n }\r\n\r\n if (typeof maxLength === \"object\") {\r\n const condition = currentInput.length === maxLength[options.inputName];\r\n\r\n if (options.debug) {\r\n console.log(\"maxLength (obj) reached:\", condition);\r\n }\r\n\r\n if (condition) {\r\n this.maxLengthReached = true;\r\n return true;\r\n } else {\r\n this.maxLengthReached = false;\r\n return false;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Gets the current value of maxLengthReached\r\n */\r\n isMaxLengthReached() {\r\n return Boolean(this.maxLengthReached);\r\n }\r\n\r\n /**\r\n * Determines whether a touch device is being used\r\n */\r\n isTouchDevice() {\r\n return \"ontouchstart\" in window || navigator.maxTouchPoints;\r\n }\r\n\r\n /**\r\n * Determines whether pointer events are supported\r\n */\r\n pointerEventsSupported() {\r\n return window.PointerEvent;\r\n }\r\n\r\n /**\r\n * Bind all methods in a given class\r\n */\r\n\r\n static bindMethods(myClass, instance) {\r\n // eslint-disable-next-line no-unused-vars\r\n for (const myMethod of Object.getOwnPropertyNames(myClass.prototype)) {\r\n const excludeMethod =\r\n myMethod === \"constructor\" || myMethod === \"bindMethods\";\r\n if (!excludeMethod) {\r\n instance[myMethod] = instance[myMethod].bind(instance);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Transforms an arbitrary string to camelCase\r\n *\r\n * @param {string} str The string to transform.\r\n */\r\n camelCase(str) {\r\n if (!str) return false;\r\n\r\n return str\r\n .toLowerCase()\r\n .trim()\r\n .split(/[.\\-_\\s]/g)\r\n .reduce((str, word) =>\r\n word.length ? str + word[0].toUpperCase() + word.slice(1) : str\r\n );\r\n }\r\n}\r\n\r\nexport default Utilities;\r\n","import Utilities from \"../services/Utilities\";\r\n\r\n/**\r\n * Physical Keyboard Service\r\n */\r\nclass PhysicalKeyboard {\r\n /**\r\n * Creates an instance of the PhysicalKeyboard service\r\n */\r\n constructor({ dispatch, getOptions }) {\r\n /**\r\n * @type {object} A simple-keyboard instance\r\n */\r\n this.dispatch = dispatch;\r\n this.getOptions = getOptions;\r\n\r\n /**\r\n * Bindings\r\n */\r\n Utilities.bindMethods(PhysicalKeyboard, this);\r\n }\r\n\r\n handleHighlightKeyDown(event) {\r\n const options = this.getOptions();\r\n const buttonPressed = this.getSimpleKeyboardLayoutKey(event);\r\n\r\n this.dispatch(instance => {\r\n const buttonDOM =\r\n instance.getButtonElement(buttonPressed) ||\r\n instance.getButtonElement(`{${buttonPressed}}`);\r\n\r\n if (buttonDOM) {\r\n buttonDOM.style.backgroundColor =\r\n options.physicalKeyboardHighlightBgColor || \"#dadce4\";\r\n buttonDOM.style.color =\r\n options.physicalKeyboardHighlightTextColor || \"black\";\r\n }\r\n });\r\n }\r\n\r\n handleHighlightKeyUp(event) {\r\n const buttonPressed = this.getSimpleKeyboardLayoutKey(event);\r\n\r\n this.dispatch(instance => {\r\n const buttonDOM =\r\n instance.getButtonElement(buttonPressed) ||\r\n instance.getButtonElement(`{${buttonPressed}}`);\r\n\r\n if (buttonDOM && buttonDOM.removeAttribute) {\r\n buttonDOM.removeAttribute(\"style\");\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Transforms a KeyboardEvent's \"key.code\" string into a simple-keyboard layout format\r\n * @param {object} event The KeyboardEvent\r\n */\r\n getSimpleKeyboardLayoutKey(event) {\r\n let output;\r\n\r\n if (\r\n event.code.includes(\"Numpad\") ||\r\n event.code.includes(\"Shift\") ||\r\n event.code.includes(\"Space\") ||\r\n event.code.includes(\"Backspace\") ||\r\n event.code.includes(\"Control\") ||\r\n event.code.includes(\"Alt\") ||\r\n event.code.includes(\"Meta\")\r\n ) {\r\n output = event.code;\r\n } else {\r\n output = event.key;\r\n }\r\n\r\n /**\r\n * If button is not uppercase, casting to lowercase\r\n */\r\n if (\r\n output !== output.toUpperCase() ||\r\n (event.code[0] === \"F\" &&\r\n Number.isInteger(Number(event.code[1])) &&\r\n event.code.length <= 3)\r\n ) {\r\n output = output.toLowerCase();\r\n }\r\n\r\n return output;\r\n }\r\n}\r\n\r\nexport default PhysicalKeyboard;\r\n","import \"./Keyboard.css\";\r\n\r\n// Services\r\nimport { getDefaultLayout } from \"../services/KeyboardLayout\";\r\nimport PhysicalKeyboard from \"../services/PhysicalKeyboard\";\r\nimport Utilities from \"../services/Utilities\";\r\n\r\n/**\r\n * Root class for simple-keyboard\r\n * This class:\r\n * - Parses the options\r\n * - Renders the rows and buttons\r\n * - Handles button functionality\r\n */\r\nclass SimpleKeyboard {\r\n /**\r\n * Creates an instance of SimpleKeyboard\r\n * @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.\r\n */\r\n constructor(...params) {\r\n const { keyboardDOMClass, keyboardDOM, options = {} } = this.handleParams(\r\n params\r\n );\r\n\r\n /**\r\n * Initializing Utilities\r\n */\r\n this.utilities = new Utilities({\r\n getOptions: this.getOptions,\r\n getCaretPosition: this.getCaretPosition,\r\n getCaretPositionEnd: this.getCaretPositionEnd,\r\n dispatch: this.dispatch\r\n });\r\n\r\n /**\r\n * Caret position\r\n */\r\n this.caretPosition = null;\r\n\r\n /**\r\n * Caret position end\r\n */\r\n this.caretPositionEnd = null;\r\n\r\n /**\r\n * Processing options\r\n */\r\n this.keyboardDOM = keyboardDOM;\r\n\r\n /**\r\n * @type {object}\r\n * @property {object} layout Modify the keyboard layout.\r\n * @property {string} layoutName Specifies which layout should be used.\r\n * @property {object} display Replaces variable buttons (such as {bksp}) with a human-friendly name (e.g.: “backspace”).\r\n * @property {boolean} mergeDisplay By default, when you set the display property, you replace the default one. This setting merges them instead.\r\n * @property {string} theme A prop to add your own css classes to the keyboard wrapper. You can add multiple classes separated by a space.\r\n * @property {array} buttonTheme A prop to add your own css classes to one or several buttons.\r\n * @property {array} buttonAttributes A prop to add your own attributes to one or several buttons.\r\n * @property {boolean} debug Runs a console.log every time a key is pressed. Displays the buttons pressed and the current input.\r\n * @property {boolean} newLineOnEnter Specifies whether clicking the “ENTER” button will input a newline (\\n) or not.\r\n * @property {boolean} tabCharOnTab Specifies whether clicking the “TAB” button will input a tab character (\\t) or not.\r\n * @property {string} inputName Allows you to use a single simple-keyboard instance for several inputs.\r\n * @property {number} maxLength Restrains all of simple-keyboard inputs to a certain length. This should be used in addition to the input elements maxlengthattribute.\r\n * @property {object} maxLength Restrains simple-keyboards individual inputs to a certain length. This should be used in addition to the input elements maxlengthattribute.\r\n * @property {boolean} syncInstanceInputs When set to true, this option synchronizes the internal input of every simple-keyboard instance.\r\n * @property {boolean} physicalKeyboardHighlight Enable highlighting of keys pressed on physical keyboard.\r\n * @property {boolean} preventMouseDownDefault Calling preventDefault for the mousedown events keeps the focus on the input.\r\n * @property {boolean} preventMouseUpDefault Calling preventDefault for the mouseup events.\r\n * @property {boolean} stopMouseDownPropagation Stops pointer down events on simple-keyboard buttons from bubbling to parent elements.\r\n * @property {boolean} stopMouseUpPropagation Stops pointer up events on simple-keyboard buttons from bubbling to parent elements.\r\n * @property {string} physicalKeyboardHighlightTextColor Define the text color that the physical keyboard highlighted key should have.\r\n * @property {string} physicalKeyboardHighlightBgColor Define the background color that the physical keyboard highlighted key should have.\r\n * @property {function(button: string):string} onKeyPress Executes the callback function on key press. Returns button layout name (i.e.: “{shift}”).\r\n * @property {function(input: string):string} onChange Executes the callback function on input change. Returns the current inputs string.\r\n * @property {function} onRender Executes the callback function every time simple-keyboard is rendered (e.g: when you change layouts).\r\n * @property {function} onInit Executes the callback function once simple-keyboard is rendered for the first time (on initialization).\r\n * @property {function(inputs: object):object} onChangeAll Executes the callback function on input change. Returns the input object with all defined inputs.\r\n * @property {boolean} useButtonTag Render buttons as a button element instead of a div element.\r\n * @property {boolean} disableCaretPositioning A prop to ensure characters are always be added/removed at the end of the string.\r\n * @property {object} inputPattern Restrains input(s) change to the defined regular expression pattern.\r\n * @property {boolean} useTouchEvents Instructs simple-keyboard to use touch events instead of click events.\r\n * @property {boolean} autoUseTouchEvents Enable useTouchEvents automatically when touch device is detected.\r\n * @property {boolean} useMouseEvents Opt out of PointerEvents handling, falling back to the prior mouse event logic.\r\n * @property {function} destroy Clears keyboard listeners and DOM elements.\r\n * @property {boolean} disableButtonHold Disable button hold action.\r\n * @property {boolean} rtl Adds unicode right-to-left control characters to input return values.\r\n * @property {function} onKeyReleased Executes the callback function on key release.\r\n * @property {array} modules Module classes to be loaded by simple-keyboard.\r\n */\r\n this.options = options;\r\n this.options.layoutName = this.options.layoutName || \"default\";\r\n this.options.theme = this.options.theme || \"hg-theme-default\";\r\n this.options.inputName = this.options.inputName || \"default\";\r\n this.options.preventMouseDownDefault =\r\n this.options.preventMouseDownDefault || false;\r\n\r\n /**\r\n * @type {object} Classes identifying loaded plugins\r\n */\r\n this.keyboardPluginClasses = \"\";\r\n\r\n /**\r\n * Bindings\r\n */\r\n Utilities.bindMethods(SimpleKeyboard, this);\r\n\r\n /**\r\n * simple-keyboard uses a non-persistent internal input to keep track of the entered string (the variable `keyboard.input`).\r\n * This removes any dependency to input DOM elements. You can type and directly display the value in a div element, for example.\r\n * @example\r\n * // To get entered input\r\n * const input = keyboard.getInput();\r\n *\r\n * // To clear entered input.\r\n * keyboard.clearInput();\r\n *\r\n * @type {object}\r\n * @property {object} default Default SimpleKeyboard internal input.\r\n * @property {object} myInputName Example input that can be set through `options.inputName:\"myInputName\"`.\r\n */\r\n this.input = {};\r\n this.input[this.options.inputName] = \"\";\r\n\r\n /**\r\n * @type {string} DOM class of the keyboard wrapper, normally \"simple-keyboard\" by default.\r\n */\r\n this.keyboardDOMClass = keyboardDOMClass;\r\n\r\n /**\r\n * @type {object} Contains the DOM elements of every rendered button, the key being the button's layout name (e.g.: \"{enter}\").\r\n */\r\n this.buttonElements = {};\r\n\r\n /**\r\n * Simple-keyboard Instances\r\n * This enables multiple simple-keyboard support with easier management\r\n */\r\n if (!window[\"SimpleKeyboardInstances\"])\r\n window[\"SimpleKeyboardInstances\"] = {};\r\n\r\n this.currentInstanceName = this.utilities.camelCase(this.keyboardDOMClass);\r\n window[\"SimpleKeyboardInstances\"][this.currentInstanceName] = this;\r\n\r\n /**\r\n * Instance vars\r\n */\r\n this.allKeyboardInstances = window[\"SimpleKeyboardInstances\"];\r\n this.keyboardInstanceNames = Object.keys(window[\"SimpleKeyboardInstances\"]);\r\n this.isFirstKeyboardInstance =\r\n this.keyboardInstanceNames[0] === this.currentInstanceName;\r\n\r\n /**\r\n * Physical Keyboard support\r\n */\r\n this.physicalKeyboard = new PhysicalKeyboard({\r\n dispatch: this.dispatch,\r\n getOptions: this.getOptions\r\n });\r\n\r\n /**\r\n * Rendering keyboard\r\n */\r\n if (this.keyboardDOM) this.render();\r\n else {\r\n console.warn(`\".${keyboardDOMClass}\" was not found in the DOM.`);\r\n throw new Error(\"KEYBOARD_DOM_ERROR\");\r\n }\r\n\r\n /**\r\n * Modules\r\n */\r\n this.modules = {};\r\n this.loadModules();\r\n }\r\n\r\n /**\r\n * parseParams\r\n */\r\n handleParams = params => {\r\n let keyboardDOMClass;\r\n let keyboardDOM;\r\n let options;\r\n\r\n /**\r\n * If first parameter is a string:\r\n * Consider it as an element's class\r\n */\r\n if (typeof params[0] === \"string\") {\r\n keyboardDOMClass = params[0].split(\".\").join(\"\");\r\n keyboardDOM = document.querySelector(`.${keyboardDOMClass}`);\r\n options = params[1];\r\n\r\n /**\r\n * If first parameter is an HTMLDivElement\r\n * Consider it as the keyboard DOM element\r\n */\r\n } else if (params[0] instanceof HTMLDivElement) {\r\n /**\r\n * This element must have a class, otherwise throw\r\n */\r\n if (!params[0].className) {\r\n console.warn(\"Any DOM element passed as parameter must have a class.\");\r\n throw new Error(\"KEYBOARD_DOM_CLASS_ERROR\");\r\n }\r\n\r\n keyboardDOMClass = params[0].className.split(\" \")[0];\r\n keyboardDOM = params[0];\r\n options = params[1];\r\n\r\n /**\r\n * Otherwise, search for .simple-keyboard DOM element\r\n */\r\n } else {\r\n keyboardDOMClass = \"simple-keyboard\";\r\n keyboardDOM = document.querySelector(`.${keyboardDOMClass}`);\r\n options = params[0];\r\n }\r\n\r\n return {\r\n keyboardDOMClass,\r\n keyboardDOM,\r\n options\r\n };\r\n };\r\n\r\n /**\r\n * Getters\r\n */\r\n getOptions = () => this.options;\r\n getCaretPosition = () => this.caretPosition;\r\n getCaretPositionEnd = () => this.caretPositionEnd;\r\n\r\n /**\r\n * Setters\r\n */\r\n setCaretPosition(position, endPosition) {\r\n this.caretPosition = position;\r\n this.caretPositionEnd = endPosition || position;\r\n }\r\n\r\n /**\r\n * Handles clicks made to keyboard buttons\r\n * @param {string} button The button's layout name.\r\n */\r\n handleButtonClicked(button) {\r\n const debug = this.options.debug;\r\n\r\n /**\r\n * Ignoring placeholder buttons\r\n */\r\n if (button === \"{//}\") return false;\r\n\r\n /**\r\n * Calling onKeyPress\r\n */\r\n if (typeof this.options.onKeyPress === \"function\")\r\n this.options.onKeyPress(button);\r\n\r\n if (!this.input[this.options.inputName])\r\n this.input[this.options.inputName] = \"\";\r\n\r\n const updatedInput = this.utilities.getUpdatedInput(\r\n button,\r\n this.input[this.options.inputName],\r\n this.caretPosition,\r\n this.caretPositionEnd\r\n );\r\n\r\n if (\r\n // If input will change as a result of this button press\r\n this.input[this.options.inputName] !== updatedInput &&\r\n // This pertains to the \"inputPattern\" option:\r\n // If inputPattern isn't set\r\n (!this.options.inputPattern ||\r\n // Or, if it is set and if the pattern is valid - we proceed.\r\n (this.options.inputPattern && this.inputPatternIsValid(updatedInput)))\r\n ) {\r\n /**\r\n * If maxLength and handleMaxLength yield true, halting\r\n */\r\n if (\r\n this.options.maxLength &&\r\n this.utilities.handleMaxLength(this.input, updatedInput)\r\n ) {\r\n return false;\r\n }\r\n\r\n this.input[this.options.inputName] = this.utilities.getUpdatedInput(\r\n button,\r\n this.input[this.options.inputName],\r\n this.caretPosition,\r\n this.caretPositionEnd,\r\n true\r\n );\r\n\r\n if (debug) console.log(\"Input changed:\", this.getAllInputs());\r\n\r\n if (this.options.debug) {\r\n console.log(\r\n \"Caret at: \",\r\n this.getCaretPosition(),\r\n this.getCaretPositionEnd(),\r\n `(${this.keyboardDOMClass})`\r\n );\r\n }\r\n\r\n /**\r\n * Enforce syncInstanceInputs, if set\r\n */\r\n if (this.options.syncInstanceInputs) this.syncInstanceInputs();\r\n\r\n /**\r\n * Calling onChange\r\n */\r\n if (typeof this.options.onChange === \"function\")\r\n this.options.onChange(this.getInput(this.options.inputName, true));\r\n\r\n /**\r\n * Calling onChangeAll\r\n */\r\n if (typeof this.options.onChangeAll === \"function\")\r\n this.options.onChangeAll(this.getAllInputs());\r\n }\r\n\r\n if (debug) {\r\n console.log(\"Key pressed:\", button);\r\n }\r\n }\r\n\r\n /**\r\n * Handles button mousedown\r\n */\r\n /* istanbul ignore next */\r\n handleButtonMouseDown(button, e) {\r\n /**\r\n * Handle event options\r\n */\r\n if (this.options.preventMouseDownDefault) e.preventDefault();\r\n if (this.options.stopMouseDownPropagation) e.stopPropagation();\r\n\r\n /**\r\n * Add active class\r\n */\r\n if (e) e.target.classList.add(this.activeButtonClass);\r\n\r\n if (this.holdInteractionTimeout) clearTimeout(this.holdInteractionTimeout);\r\n if (this.holdTimeout) clearTimeout(this.holdTimeout);\r\n\r\n /**\r\n * @type {boolean} Whether the mouse is being held onKeyPress\r\n */\r\n this.isMouseHold = true;\r\n\r\n /**\r\n * @type {object} Time to wait until a key hold is detected\r\n */\r\n if (!this.options.disableButtonHold) {\r\n this.holdTimeout = setTimeout(() => {\r\n if (\r\n (this.isMouseHold &&\r\n // TODO: This needs to be configurable through options\r\n ((!button.includes(\"{\") && !button.includes(\"}\")) ||\r\n button === \"{delete}\" ||\r\n button === \"{backspace}\" ||\r\n button === \"{bksp}\" ||\r\n button === \"{space}\" ||\r\n button === \"{tab}\")) ||\r\n button === \"{arrowright}\" ||\r\n button === \"{arrowleft}\" ||\r\n button === \"{arrowup}\" ||\r\n button === \"{arrowdown}\"\r\n ) {\r\n if (this.options.debug) console.log(\"Button held:\", button);\r\n\r\n this.handleButtonHold(button, e);\r\n }\r\n clearTimeout(this.holdTimeout);\r\n }, 500);\r\n }\r\n }\r\n\r\n /**\r\n * Handles button mouseup\r\n */\r\n handleButtonMouseUp(button = null, e = null) {\r\n if (e) {\r\n /**\r\n * Handle event options\r\n */\r\n if (this.options.preventMouseUpDefault) e.preventDefault();\r\n if (this.options.stopMouseUpPropagation) e.stopPropagation();\r\n }\r\n\r\n /**\r\n * Remove active class\r\n */\r\n this.recurseButtons(buttonElement => {\r\n buttonElement.classList.remove(this.activeButtonClass);\r\n });\r\n\r\n this.isMouseHold = false;\r\n if (this.holdInteractionTimeout) clearTimeout(this.holdInteractionTimeout);\r\n\r\n /**\r\n * Calling onKeyReleased\r\n */\r\n if (button && typeof this.options.onKeyReleased === \"function\")\r\n this.options.onKeyReleased(button);\r\n }\r\n\r\n /**\r\n * Handles container mousedown\r\n */\r\n handleKeyboardContainerMouseDown(e) {\r\n /**\r\n * Handle event options\r\n */\r\n if (this.options.preventMouseDownDefault) e.preventDefault();\r\n }\r\n\r\n /**\r\n * Handles button hold\r\n */\r\n /* istanbul ignore next */\r\n handleButtonHold(button) {\r\n if (this.holdInteractionTimeout) clearTimeout(this.holdInteractionTimeout);\r\n\r\n /**\r\n * @type {object} Timeout dictating the speed of key hold iterations\r\n */\r\n this.holdInteractionTimeout = setTimeout(() => {\r\n if (this.isMouseHold) {\r\n this.handleButtonClicked(button);\r\n this.handleButtonHold(button);\r\n } else {\r\n clearTimeout(this.holdInteractionTimeout);\r\n }\r\n }, 100);\r\n }\r\n\r\n /**\r\n * Send a command to all simple-keyboard instances (if you have several instances).\r\n */\r\n syncInstanceInputs() {\r\n this.dispatch(instance => {\r\n instance.replaceInput(this.input);\r\n instance.setCaretPosition(this.caretPosition, this.caretPositionEnd);\r\n });\r\n }\r\n\r\n /**\r\n * Clear the keyboards input.\r\n * @param {string} [inputName] optional - the internal input to select\r\n */\r\n clearInput(inputName) {\r\n inputName = inputName || this.options.inputName;\r\n this.input[inputName] = \"\";\r\n\r\n /**\r\n * Reset caretPosition\r\n */\r\n this.setCaretPosition(0);\r\n\r\n /**\r\n * Enforce syncInstanceInputs, if set\r\n */\r\n if (this.options.syncInstanceInputs) this.syncInstanceInputs();\r\n }\r\n\r\n /**\r\n * Get the keyboards input (You can also get it from the onChange prop).\r\n * @param {string} [inputName] optional - the internal input to select\r\n */\r\n getInput(inputName, skipSync = false) {\r\n inputName = inputName || this.options.inputName;\r\n\r\n /**\r\n * Enforce syncInstanceInputs, if set\r\n */\r\n if (this.options.syncInstanceInputs && !skipSync) this.syncInstanceInputs();\r\n\r\n if (this.options.rtl) {\r\n // Remove existing control chars\r\n const inputWithoutRTLControl = this.input[inputName]\r\n .replace(\"\\u202B\", \"\")\r\n .replace(\"\\u202C\", \"\");\r\n\r\n return \"\\u202B\" + inputWithoutRTLControl + \"\\u202C\";\r\n } else {\r\n return this.input[inputName];\r\n }\r\n }\r\n\r\n /**\r\n * Get all simple-keyboard inputs\r\n */\r\n getAllInputs() {\r\n const output = {};\r\n const inputNames = Object.keys(this.input);\r\n\r\n inputNames.forEach(inputName => {\r\n output[inputName] = this.getInput(inputName, true);\r\n });\r\n\r\n return output;\r\n }\r\n\r\n /**\r\n * Set the keyboards input.\r\n * @param {string} input the input value\r\n * @param {string} inputName optional - the internal input to select\r\n */\r\n setInput(input, inputName) {\r\n inputName = inputName || this.options.inputName;\r\n this.input[inputName] = input;\r\n\r\n /**\r\n * Enforce syncInstanceInputs, if set\r\n */\r\n if (this.options.syncInstanceInputs) this.syncInstanceInputs();\r\n }\r\n\r\n /**\r\n * Replace the input object (`keyboard.input`)\r\n * @param {object} inputObj The input object\r\n */\r\n replaceInput(inputObj) {\r\n this.input = inputObj;\r\n }\r\n\r\n /**\r\n * Set new option or modify existing ones after initialization.\r\n * @param {object} options The options to set\r\n */\r\n setOptions(options = {}) {\r\n const changedOptions = this.changedOptions(options);\r\n this.options = Object.assign(this.options, options);\r\n\r\n if (changedOptions.length) {\r\n if (this.options.debug) {\r\n console.log(\"changedOptions\", changedOptions);\r\n }\r\n\r\n /**\r\n * Some option changes require adjustments before re-render\r\n */\r\n this.onSetOptions(options);\r\n\r\n /**\r\n * Rendering\r\n */\r\n this.render();\r\n }\r\n }\r\n\r\n /**\r\n * Detecting changes to non-function options\r\n * This allows us to ascertain whether a button re-render is needed\r\n */\r\n changedOptions(newOptions) {\r\n return Object.keys(newOptions).filter(\r\n optionName =>\r\n JSON.stringify(newOptions[optionName]) !==\r\n JSON.stringify(this.options[optionName])\r\n );\r\n }\r\n\r\n /**\r\n * Executing actions depending on changed options\r\n * @param {object} options The options to set\r\n */\r\n onSetOptions(options) {\r\n if (options.inputName) {\r\n /**\r\n * inputName changed. This requires a caretPosition reset\r\n */\r\n if (this.options.debug) {\r\n console.log(\"inputName changed. caretPosition reset.\");\r\n }\r\n this.setCaretPosition(null);\r\n }\r\n }\r\n\r\n /**\r\n * Remove all keyboard rows and reset keyboard values.\r\n * Used internally between re-renders.\r\n */\r\n clear() {\r\n this.keyboardDOM.innerHTML = \"\";\r\n this.keyboardDOM.className = this.keyboardDOMClass;\r\n this.buttonElements = {};\r\n }\r\n\r\n /**\r\n * Send a command to all simple-keyboard instances at once (if you have multiple instances).\r\n * @param {function(instance: object, key: string)} callback Function to run on every instance\r\n */\r\n dispatch(callback) {\r\n if (!window[\"SimpleKeyboardInstances\"]) {\r\n console.warn(\r\n `SimpleKeyboardInstances is not defined. Dispatch cannot be called.`\r\n );\r\n throw new Error(\"INSTANCES_VAR_ERROR\");\r\n }\r\n\r\n return Object.keys(window[\"SimpleKeyboardInstances\"]).forEach(key => {\r\n callback(window[\"SimpleKeyboardInstances\"][key], key);\r\n });\r\n }\r\n\r\n /**\r\n * Adds/Modifies an entry to the `buttonTheme`. Basically a way to add a class to a button.\r\n * @param {string} buttons List of buttons to select (separated by a space).\r\n * @param {string} className Classes to give to the selected buttons (separated by space).\r\n */\r\n addButtonTheme(buttons, className) {\r\n if (!className || !buttons) return false;\r\n\r\n buttons.split(\" \").forEach(button => {\r\n className.split(\" \").forEach(classNameItem => {\r\n if (!this.options.buttonTheme) this.options.buttonTheme = [];\r\n\r\n let classNameFound = false;\r\n\r\n /**\r\n * If class is already defined, we add button to class definition\r\n */\r\n this.options.buttonTheme.map(buttonTheme => {\r\n if (buttonTheme.class.split(\" \").includes(classNameItem)) {\r\n classNameFound = true;\r\n\r\n const buttonThemeArray = buttonTheme.buttons.split(\" \");\r\n if (!buttonThemeArray.includes(button)) {\r\n classNameFound = true;\r\n buttonThemeArray.push(button);\r\n buttonTheme.buttons = buttonThemeArray.join(\" \");\r\n }\r\n }\r\n return buttonTheme;\r\n });\r\n\r\n /**\r\n * If class is not defined, we create a new entry\r\n */\r\n if (!classNameFound) {\r\n this.options.buttonTheme.push({\r\n class: classNameItem,\r\n buttons: buttons\r\n });\r\n }\r\n });\r\n });\r\n\r\n this.render();\r\n }\r\n\r\n /**\r\n * Removes/Amends an entry to the `buttonTheme`. Basically a way to remove a class previously added to a button through buttonTheme or addButtonTheme.\r\n * @param {string} buttons List of buttons to select (separated by a space).\r\n * @param {string} className Classes to give to the selected buttons (separated by space).\r\n */\r\n removeButtonTheme(buttons, className) {\r\n /**\r\n * When called with empty parameters, remove all button themes\r\n */\r\n if (!buttons && !className) {\r\n this.options.buttonTheme = [];\r\n this.render();\r\n return false;\r\n }\r\n\r\n /**\r\n * If buttons are passed and buttonTheme has items\r\n */\r\n if (\r\n buttons &&\r\n Array.isArray(this.options.buttonTheme) &&\r\n this.options.buttonTheme.length\r\n ) {\r\n const buttonArray = buttons.split(\" \");\r\n buttonArray.forEach(button => {\r\n this.options.buttonTheme.map((buttonTheme, index) => {\r\n /**\r\n * If className is set, we affect the buttons only for that class\r\n * Otherwise, we afect all classes\r\n */\r\n if (\r\n (className && className.includes(buttonTheme.class)) ||\r\n !className\r\n ) {\r\n const filteredButtonArray = buttonTheme.buttons\r\n .split(\" \")\r\n .filter(item => item !== button);\r\n\r\n /**\r\n * If buttons left, return them, otherwise, remove button Theme\r\n */\r\n if (filteredButtonArray.length) {\r\n buttonTheme.buttons = filteredButtonArray.join(\" \");\r\n } else {\r\n this.options.buttonTheme.splice(index, 1);\r\n buttonTheme = null;\r\n }\r\n }\r\n\r\n return buttonTheme;\r\n });\r\n });\r\n\r\n this.render();\r\n }\r\n }\r\n\r\n /**\r\n * Get the DOM Element of a button. If there are several buttons with the same name, an array of the DOM Elements is returned.\r\n * @param {string} button The button layout name to select\r\n */\r\n getButtonElement(button) {\r\n let output;\r\n\r\n const buttonArr = this.buttonElements[button];\r\n if (buttonArr) {\r\n if (buttonArr.length > 1) {\r\n output = buttonArr;\r\n } else {\r\n output = buttonArr[0];\r\n }\r\n }\r\n\r\n return output;\r\n }\r\n\r\n /**\r\n * This handles the \"inputPattern\" option\r\n * by checking if the provided inputPattern passes\r\n */\r\n inputPatternIsValid(inputVal) {\r\n const inputPatternRaw = this.options.inputPattern;\r\n let inputPattern;\r\n\r\n /**\r\n * Check if input pattern is global or targeted to individual inputs\r\n */\r\n if (inputPatternRaw instanceof RegExp) {\r\n inputPattern = inputPatternRaw;\r\n } else {\r\n inputPattern = inputPatternRaw[this.options.inputName];\r\n }\r\n\r\n if (inputPattern && inputVal) {\r\n const didInputMatch = inputPattern.test(inputVal);\r\n\r\n if (this.options.debug) {\r\n console.log(\r\n `inputPattern (\"${inputPattern}\"): ${\r\n didInputMatch ? \"passed\" : \"did not pass!\"\r\n }`\r\n );\r\n }\r\n\r\n return didInputMatch;\r\n } else {\r\n /**\r\n * inputPattern doesn't seem to be set for the current input, or input is empty. Pass.\r\n */\r\n return true;\r\n }\r\n }\r\n\r\n /**\r\n * Handles simple-keyboard event listeners\r\n */\r\n setEventListeners() {\r\n /**\r\n * Only first instance should set the event listeners\r\n */\r\n if (this.isFirstKeyboardInstance || !this.allKeyboardInstances) {\r\n if (this.options.debug) {\r\n console.log(`Caret handling started (${this.keyboardDOMClass})`);\r\n }\r\n\r\n /**\r\n * Event Listeners\r\n */\r\n document.addEventListener(\"keyup\", this.handleKeyUp);\r\n document.addEventListener(\"keydown\", this.handleKeyDown);\r\n document.addEventListener(\"mouseup\", this.handleMouseUp);\r\n document.addEventListener(\"touchend\", this.handleTouchEnd);\r\n }\r\n }\r\n\r\n /**\r\n * Event Handler: KeyUp\r\n */\r\n handleKeyUp(event) {\r\n this.caretEventHandler(event);\r\n\r\n if (this.options.physicalKeyboardHighlight) {\r\n this.physicalKeyboard.handleHighlightKeyUp(event);\r\n }\r\n }\r\n\r\n /**\r\n * Event Handler: KeyDown\r\n */\r\n handleKeyDown(event) {\r\n if (this.options.physicalKeyboardHighlight) {\r\n this.physicalKeyboard.handleHighlightKeyDown(event);\r\n }\r\n }\r\n\r\n /**\r\n * Event Handler: MouseUp\r\n */\r\n handleMouseUp(event) {\r\n this.caretEventHandler(event);\r\n }\r\n\r\n /**\r\n * Event Handler: TouchEnd\r\n */\r\n /* istanbul ignore next */\r\n handleTouchEnd(event) {\r\n this.caretEventHandler(event);\r\n }\r\n\r\n /**\r\n * Called by {@link setEventListeners} when an event that warrants a cursor position update is triggered\r\n */\r\n caretEventHandler(event) {\r\n let targetTagName;\r\n if (event.target.tagName) {\r\n targetTagName = event.target.tagName.toLowerCase();\r\n }\r\n\r\n this.dispatch(instance => {\r\n const isKeyboard =\r\n event.target === instance.keyboardDOM ||\r\n (event.target && instance.keyboardDOM.contains(event.target));\r\n\r\n if (instance.isMouseHold) {\r\n instance.isMouseHold = false;\r\n }\r\n\r\n if (\r\n (targetTagName === \"textarea\" || targetTagName === \"input\") &&\r\n !instance.options.disableCaretPositioning\r\n ) {\r\n /**\r\n * Tracks current cursor position\r\n * As keys are pressed, text will be added/removed at that position within the input.\r\n */\r\n instance.setCaretPosition(\r\n event.target.selectionStart,\r\n event.target.selectionEnd\r\n );\r\n\r\n if (instance.options.debug) {\r\n console.log(\r\n \"Caret at: \",\r\n instance.getCaretPosition(),\r\n instance.getCaretPositionEnd(),\r\n event && event.target.tagName.toLowerCase(),\r\n `(${instance.keyboardDOMClass})`\r\n );\r\n }\r\n } else if (instance.options.disableCaretPositioning || !isKeyboard) {\r\n /**\r\n * If we toggled off disableCaretPositioning, we must ensure caretPosition doesn't persist once reactivated.\r\n */\r\n instance.setCaretPosition(null);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Execute an operation on each button\r\n */\r\n recurseButtons(fn) {\r\n if (!fn) return false;\r\n\r\n Object.keys(this.buttonElements).forEach(buttonName =>\r\n this.buttonElements[buttonName].forEach(fn)\r\n );\r\n }\r\n\r\n /**\r\n * Destroy keyboard listeners and DOM elements\r\n */\r\n destroy() {\r\n if (this.options.debug)\r\n console.log(\r\n `Destroying simple-keyboard instance: ${this.currentInstanceName}`\r\n );\r\n\r\n /**\r\n * Remove document listeners\r\n */\r\n document.removeEventListener(\"keyup\", this.handleKeyUp);\r\n document.removeEventListener(\"keydown\", this.handleKeyDown);\r\n document.removeEventListener(\"mouseup\", this.handleMouseUp);\r\n document.removeEventListener(\"touchend\", this.handleTouchEnd);\r\n document.onpointerup = null;\r\n document.ontouchend = null;\r\n document.ontouchcancel = null;\r\n document.onmouseup = null;\r\n\r\n /**\r\n * Remove buttons\r\n */\r\n let deleteButton = buttonElement => {\r\n buttonElement.onpointerdown = null;\r\n buttonElement.onpointerup = null;\r\n buttonElement.onpointercancel = null;\r\n buttonElement.ontouchstart = null;\r\n buttonElement.ontouchend = null;\r\n buttonElement.ontouchcancel = null;\r\n buttonElement.onclick = null;\r\n buttonElement.onmousedown = null;\r\n buttonElement.onmouseup = null;\r\n\r\n buttonElement.remove();\r\n buttonElement = null;\r\n };\r\n\r\n this.recurseButtons(deleteButton);\r\n\r\n this.recurseButtons = null;\r\n deleteButton = null;\r\n\r\n /**\r\n * Remove wrapper events\r\n */\r\n this.keyboardDOM.onpointerdown = null;\r\n this.keyboardDOM.ontouchstart = null;\r\n this.keyboardDOM.onmousedown = null;\r\n\r\n /**\r\n * Clearing keyboard wrapper\r\n */\r\n this.clear();\r\n\r\n /**\r\n * Remove instance\r\n */\r\n window[\"SimpleKeyboardInstances\"][this.currentInstanceName] = null;\r\n delete window[\"SimpleKeyboardInstances\"][this.currentInstanceName];\r\n\r\n /**\r\n * Reset initialized flag\r\n */\r\n this.initialized = false;\r\n }\r\n\r\n /**\r\n * Process buttonTheme option\r\n */\r\n getButtonThemeClasses(button) {\r\n const buttonTheme = this.options.buttonTheme;\r\n let buttonClasses = [];\r\n\r\n if (Array.isArray(buttonTheme)) {\r\n buttonTheme.forEach(themeObj => {\r\n if (\r\n themeObj.class &&\r\n typeof themeObj.class === \"string\" &&\r\n themeObj.buttons &&\r\n typeof themeObj.buttons === \"string\"\r\n ) {\r\n const themeObjClasses = themeObj.class.split(\" \");\r\n const themeObjButtons = themeObj.buttons.split(\" \");\r\n\r\n if (themeObjButtons.includes(button)) {\r\n buttonClasses = [...buttonClasses, ...themeObjClasses];\r\n }\r\n } else {\r\n console.warn(\r\n `Incorrect \"buttonTheme\". Please check the documentation.`,\r\n themeObj\r\n );\r\n }\r\n });\r\n }\r\n\r\n return buttonClasses;\r\n }\r\n\r\n /**\r\n * Process buttonAttributes option\r\n */\r\n setDOMButtonAttributes(button, callback) {\r\n const buttonAttributes = this.options.buttonAttributes;\r\n\r\n if (Array.isArray(buttonAttributes)) {\r\n buttonAttributes.forEach(attrObj => {\r\n if (\r\n attrObj.attribute &&\r\n typeof attrObj.attribute === \"string\" &&\r\n attrObj.value &&\r\n typeof attrObj.value === \"string\" &&\r\n attrObj.buttons &&\r\n typeof attrObj.buttons === \"string\"\r\n ) {\r\n const attrObjButtons = attrObj.buttons.split(\" \");\r\n\r\n if (attrObjButtons.includes(button)) {\r\n callback(attrObj.attribute, attrObj.value);\r\n }\r\n } else {\r\n console.warn(\r\n `Incorrect \"buttonAttributes\". Please check the documentation.`,\r\n attrObj\r\n );\r\n }\r\n });\r\n }\r\n }\r\n\r\n onTouchDeviceDetected() {\r\n /**\r\n * Processing autoTouchEvents\r\n */\r\n this.processAutoTouchEvents();\r\n\r\n /**\r\n * Disabling contextual window on touch devices\r\n */\r\n this.disableContextualWindow();\r\n }\r\n\r\n /**\r\n * Disabling contextual window for hg-button\r\n */\r\n /* istanbul ignore next */\r\n disableContextualWindow() {\r\n window.oncontextmenu = event => {\r\n if (event.target.classList.contains(\"hg-button\")) {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n return false;\r\n }\r\n };\r\n }\r\n\r\n /**\r\n * Process autoTouchEvents option\r\n */\r\n processAutoTouchEvents() {\r\n if (this.options.autoUseTouchEvents) {\r\n this.options.useTouchEvents = true;\r\n\r\n if (this.options.debug) {\r\n console.log(\r\n `autoUseTouchEvents: Touch device detected, useTouchEvents enabled.`\r\n );\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Executes the callback function once simple-keyboard is rendered for the first time (on initialization).\r\n */\r\n onInit() {\r\n if (this.options.debug) {\r\n console.log(`${this.keyboardDOMClass} Initialized`);\r\n }\r\n\r\n /**\r\n * setEventListeners\r\n */\r\n this.setEventListeners();\r\n\r\n if (typeof this.options.onInit === \"function\") this.options.onInit();\r\n }\r\n\r\n /**\r\n * Executes the callback function before a simple-keyboard render.\r\n */\r\n beforeFirstRender() {\r\n /**\r\n * Performing actions when touch device detected\r\n */\r\n if (this.utilities.isTouchDevice()) {\r\n this.onTouchDeviceDetected();\r\n }\r\n\r\n if (typeof this.options.beforeFirstRender === \"function\")\r\n this.options.beforeFirstRender();\r\n\r\n /**\r\n * Notify about PointerEvents usage\r\n */\r\n if (\r\n this.isFirstKeyboardInstance &&\r\n this.utilities.pointerEventsSupported() &&\r\n !this.options.useTouchEvents &&\r\n !this.options.useMouseEvents\r\n ) {\r\n if (this.options.debug) {\r\n console.log(\"Using PointerEvents as it is supported by this browser\");\r\n }\r\n }\r\n\r\n /**\r\n * Notify about touch events usage\r\n */\r\n if (this.options.useTouchEvents) {\r\n if (this.options.debug) {\r\n console.log(\r\n \"useTouchEvents has been enabled. Only touch events will be used.\"\r\n );\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Executes the callback function before a simple-keyboard render.\r\n */\r\n beforeRender() {\r\n if (typeof this.options.beforeRender === \"function\")\r\n this.options.beforeRender();\r\n }\r\n\r\n /**\r\n * Executes the callback function every time simple-keyboard is rendered (e.g: when you change layouts).\r\n */\r\n onRender() {\r\n if (typeof this.options.onRender === \"function\") this.options.onRender();\r\n }\r\n\r\n /**\r\n * Executes the callback function once all modules have been loaded\r\n */\r\n onModulesLoaded() {\r\n if (typeof this.options.onModulesLoaded === \"function\")\r\n this.options.onModulesLoaded(this);\r\n }\r\n\r\n /**\r\n * Register module\r\n */\r\n registerModule = (name, initCallback) => {\r\n if (!this.modules[name]) this.modules[name] = {};\r\n\r\n initCallback(this.modules[name]);\r\n };\r\n\r\n /**\r\n * Load modules\r\n */\r\n loadModules() {\r\n if (Array.isArray(this.options.modules)) {\r\n this.options.modules.forEach(KeyboardModule => {\r\n const keyboardModule = new KeyboardModule();\r\n\r\n /* istanbul ignore next */\r\n if (\r\n keyboardModule.constructor.name &&\r\n keyboardModule.constructor.name !== \"Function\"\r\n ) {\r\n const classStr = `module-${this.utilities.camelCase(\r\n keyboardModule.constructor.name\r\n )}`;\r\n this.keyboardPluginClasses =\r\n this.keyboardPluginClasses + ` ${classStr}`;\r\n }\r\n\r\n keyboardModule.init(this);\r\n });\r\n\r\n this.keyboardPluginClasses =\r\n this.keyboardPluginClasses + \" modules-loaded\";\r\n\r\n this.render();\r\n this.onModulesLoaded();\r\n }\r\n }\r\n\r\n /**\r\n * Get module prop\r\n */\r\n getModuleProp(name, prop) {\r\n if (!this.modules[name]) return false;\r\n\r\n return this.modules[name][prop];\r\n }\r\n\r\n /**\r\n * getModulesList\r\n */\r\n getModulesList() {\r\n return Object.keys(this.modules);\r\n }\r\n\r\n /**\r\n * Parse Row DOM containers\r\n */\r\n parseRowDOMContainers(\r\n rowDOM,\r\n rowIndex,\r\n containerStartIndexes,\r\n containerEndIndexes\r\n ) {\r\n const rowDOMArray = Array.from(rowDOM.children);\r\n let removedElements = 0;\r\n\r\n if (rowDOMArray.length) {\r\n containerStartIndexes.forEach((startIndex, arrIndex) => {\r\n const endIndex = containerEndIndexes[arrIndex];\r\n\r\n /**\r\n * If there exists a respective end index\r\n * if end index comes after start index\r\n */\r\n if (!endIndex || !(endIndex > startIndex)) {\r\n return false;\r\n }\r\n\r\n /**\r\n * Updated startIndex, endIndex\r\n * This is since the removal of buttons to place a single button container\r\n * results in a modified array size\r\n */\r\n const updated_startIndex = startIndex - removedElements;\r\n const updated_endIndex = endIndex - removedElements;\r\n\r\n /**\r\n * Create button container\r\n */\r\n const containerDOM = document.createElement(\"div\");\r\n containerDOM.className += \"hg-button-container\";\r\n const containerUID = `${this.options.layoutName}-r${rowIndex}c${arrIndex}`;\r\n containerDOM.setAttribute(\"data-skUID\", containerUID);\r\n\r\n /**\r\n * Taking elements due to be inserted into container\r\n */\r\n const containedElements = rowDOMArray.splice(\r\n updated_startIndex,\r\n updated_endIndex - updated_startIndex + 1\r\n );\r\n removedElements = updated_endIndex - updated_startIndex;\r\n\r\n /**\r\n * Inserting elements to container\r\n */\r\n containedElements.forEach(element => containerDOM.appendChild(element));\r\n\r\n /**\r\n * Adding container at correct position within rowDOMArray\r\n */\r\n rowDOMArray.splice(updated_startIndex, 0, containerDOM);\r\n\r\n /**\r\n * Clearing old rowDOM children structure\r\n */\r\n rowDOM.innerHTML = \"\";\r\n\r\n /**\r\n * Appending rowDOM new children list\r\n */\r\n rowDOMArray.forEach(element => rowDOM.appendChild(element));\r\n\r\n if (this.options.debug) {\r\n console.log(\r\n \"rowDOMContainer\",\r\n containedElements,\r\n updated_startIndex,\r\n updated_endIndex,\r\n removedElements + 1\r\n );\r\n }\r\n });\r\n }\r\n\r\n return rowDOM;\r\n }\r\n\r\n /**\r\n * getKeyboardClassString\r\n */\r\n getKeyboardClassString = (...baseDOMClasses) => {\r\n const keyboardClasses = [this.keyboardDOMClass, ...baseDOMClasses].filter(\r\n DOMClass => !!DOMClass\r\n );\r\n\r\n return keyboardClasses.join(\" \");\r\n };\r\n\r\n /**\r\n * Renders rows and buttons as per options\r\n */\r\n render() {\r\n /**\r\n * Clear keyboard\r\n */\r\n this.clear();\r\n\r\n /**\r\n * Calling beforeFirstRender\r\n */\r\n if (!this.initialized) {\r\n this.beforeFirstRender();\r\n }\r\n\r\n /**\r\n * Calling beforeRender\r\n */\r\n this.beforeRender();\r\n\r\n const layoutClass = `hg-layout-${this.options.layoutName}`;\r\n const layout = this.options.layout || getDefaultLayout();\r\n const useTouchEvents = this.options.useTouchEvents || false;\r\n const useTouchEventsClass = useTouchEvents ? \"hg-touch-events\" : \"\";\r\n const useMouseEvents = this.options.useMouseEvents || false;\r\n const disableRowButtonContainers = this.options.disableRowButtonContainers;\r\n\r\n /**\r\n * Adding themeClass, layoutClass to keyboardDOM\r\n */\r\n this.keyboardDOM.className = this.getKeyboardClassString(\r\n this.options.theme,\r\n layoutClass,\r\n this.keyboardPluginClasses,\r\n useTouchEventsClass\r\n );\r\n\r\n /**\r\n * Iterating through each row\r\n */\r\n layout[this.options.layoutName].forEach((row, rIndex) => {\r\n const rowArray = row.split(\" \");\r\n\r\n /**\r\n * Creating empty row\r\n */\r\n let rowDOM = document.createElement(\"div\");\r\n rowDOM.className += \"hg-row\";\r\n\r\n /**\r\n * Tracking container indicators in rows\r\n */\r\n const containerStartIndexes = [];\r\n const containerEndIndexes = [];\r\n\r\n /**\r\n * Iterating through each button in row\r\n */\r\n rowArray.forEach((button, bIndex) => {\r\n /**\r\n * Check if button has a container indicator\r\n */\r\n const buttonHasContainerStart =\r\n !disableRowButtonContainers &&\r\n typeof button === \"string\" &&\r\n button.length > 1 &&\r\n button.indexOf(\"[\") === 0;\r\n\r\n const buttonHasContainerEnd =\r\n !disableRowButtonContainers &&\r\n typeof button === \"string\" &&\r\n button.length > 1 &&\r\n button.indexOf(\"]\") === button.length - 1;\r\n\r\n /**\r\n * Save container start index, if applicable\r\n */\r\n if (buttonHasContainerStart) {\r\n containerStartIndexes.push(bIndex);\r\n\r\n /**\r\n * Removing indicator\r\n */\r\n button = button.replace(/\\[/g, \"\");\r\n }\r\n\r\n if (buttonHasContainerEnd) {\r\n containerEndIndexes.push(bIndex);\r\n\r\n /**\r\n * Removing indicator\r\n */\r\n button = button.replace(/\\]/g, \"\");\r\n }\r\n\r\n /**\r\n * Processing button options\r\n */\r\n const fctBtnClass = this.utilities.getButtonClass(button);\r\n const buttonDisplayName = this.utilities.getButtonDisplayName(\r\n button,\r\n this.options.display,\r\n this.options.mergeDisplay\r\n );\r\n\r\n /**\r\n * Creating button\r\n */\r\n const buttonType = this.options.useButtonTag ? \"button\" : \"div\";\r\n const buttonDOM = document.createElement(buttonType);\r\n buttonDOM.className += `hg-button ${fctBtnClass}`;\r\n\r\n /**\r\n * Adding buttonTheme\r\n */\r\n buttonDOM.classList.add(...this.getButtonThemeClasses(button));\r\n\r\n /**\r\n * Adding buttonAttributes\r\n */\r\n this.setDOMButtonAttributes(button, (attribute, value) => {\r\n buttonDOM.setAttribute(attribute, value);\r\n });\r\n\r\n this.activeButtonClass = \"hg-activeButton\";\r\n\r\n /**\r\n * Handle button click event\r\n */\r\n /* istanbul ignore next */\r\n if (\r\n this.utilities.pointerEventsSupported() &&\r\n !useTouchEvents &&\r\n !useMouseEvents\r\n ) {\r\n /**\r\n * Handle PointerEvents\r\n */\r\n buttonDOM.onpointerdown = e => {\r\n this.handleButtonClicked(button);\r\n this.handleButtonMouseDown(button, e);\r\n };\r\n buttonDOM.onpointerup = e => {\r\n this.handleButtonMouseUp(button, e);\r\n };\r\n buttonDOM.onpointercancel = e => {\r\n this.handleButtonMouseUp(button, e);\r\n };\r\n } else {\r\n /**\r\n * Fallback for browsers not supporting PointerEvents\r\n */\r\n if (useTouchEvents) {\r\n /**\r\n * Handle touch events\r\n */\r\n buttonDOM.ontouchstart = e => {\r\n this.handleButtonClicked(button);\r\n this.handleButtonMouseDown(button, e);\r\n };\r\n buttonDOM.ontouchend = e => {\r\n this.handleButtonMouseUp(button, e);\r\n };\r\n buttonDOM.ontouchcancel = e => {\r\n this.handleButtonMouseUp(button, e);\r\n };\r\n } else {\r\n /**\r\n * Handle mouse events\r\n */\r\n buttonDOM.onclick = () => {\r\n this.isMouseHold = false;\r\n this.handleButtonClicked(button);\r\n };\r\n buttonDOM.onmousedown = e => {\r\n this.handleButtonMouseDown(button, e);\r\n };\r\n buttonDOM.onmouseup = e => {\r\n this.handleButtonMouseUp(button, e);\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * Adding identifier\r\n */\r\n buttonDOM.setAttribute(\"data-skBtn\", button);\r\n\r\n /**\r\n * Adding unique id\r\n * Since there's no limit on spawning same buttons, the unique id ensures you can style every button\r\n */\r\n const buttonUID = `${this.options.layoutName}-r${rIndex}b${bIndex}`;\r\n buttonDOM.setAttribute(\"data-skBtnUID\", buttonUID);\r\n\r\n /**\r\n * Adding button label to button\r\n */\r\n const buttonSpanDOM = document.createElement(\"span\");\r\n buttonSpanDOM.innerHTML = buttonDisplayName;\r\n buttonDOM.appendChild(buttonSpanDOM);\r\n\r\n /**\r\n * Adding to buttonElements\r\n */\r\n if (!this.buttonElements[button]) this.buttonElements[button] = [];\r\n\r\n this.buttonElements[button].push(buttonDOM);\r\n\r\n /**\r\n * Appending button to row\r\n */\r\n rowDOM.appendChild(buttonDOM);\r\n });\r\n\r\n /**\r\n * Parse containers in row\r\n */\r\n rowDOM = this.parseRowDOMContainers(\r\n rowDOM,\r\n rIndex,\r\n containerStartIndexes,\r\n containerEndIndexes\r\n );\r\n\r\n /**\r\n * Appending row to keyboard\r\n */\r\n this.keyboardDOM.appendChild(rowDOM);\r\n });\r\n\r\n /**\r\n * Calling onRender\r\n */\r\n this.onRender();\r\n\r\n if (!this.initialized) {\r\n /**\r\n * Ensures that onInit and beforeFirstRender are only called once per instantiation\r\n */\r\n this.initialized = true;\r\n\r\n /**\r\n * Handling parent events\r\n */\r\n /* istanbul ignore next */\r\n if (\r\n this.utilities.pointerEventsSupported() &&\r\n !useTouchEvents &&\r\n !useMouseEvents\r\n ) {\r\n document.onpointerup = () => this.handleButtonMouseUp();\r\n this.keyboardDOM.onpointerdown = e =>\r\n this.handleKeyboardContainerMouseDown(e);\r\n } else if (useTouchEvents) {\r\n /**\r\n * Handling ontouchend, ontouchcancel\r\n */\r\n document.ontouchend = () => this.handleButtonMouseUp();\r\n document.ontouchcancel = () => this.handleButtonMouseUp();\r\n\r\n this.keyboardDOM.ontouchstart = e =>\r\n this.handleKeyboardContainerMouseDown(e);\r\n } else if (!useTouchEvents) {\r\n /**\r\n * Handling mouseup\r\n */\r\n document.onmouseup = () => this.handleButtonMouseUp();\r\n this.keyboardDOM.onmousedown = e =>\r\n this.handleKeyboardContainerMouseDown(e);\r\n }\r\n\r\n /**\r\n * Calling onInit\r\n */\r\n this.onInit();\r\n }\r\n }\r\n}\r\n\r\nexport default SimpleKeyboard;\r\n","export const getDefaultLayout = () => {\r\n return {\r\n default: [\r\n \"` 1 2 3 4 5 6 7 8 9 0 - = {bksp}\",\r\n \"{tab} q w e r t y u i o p [ ] \\\\\",\r\n \"{lock} a s d f g h j k l ; ' {enter}\",\r\n \"{shift} z x c v b n m , . / {shift}\",\r\n \".com @ {space}\"\r\n ],\r\n shift: [\r\n \"~ ! @ # $ % ^ & * ( ) _ + {bksp}\",\r\n \"{tab} Q W E R T Y U I O P { } |\",\r\n '{lock} A S D F G H J K L : \" {enter}',\r\n \"{shift} Z X C V B N M < > ? {shift}\",\r\n \".com @ {space}\"\r\n ]\r\n };\r\n};\r\n","import SimpleKeyboard from \"./components/Keyboard\";\r\nexport default SimpleKeyboard;\r\n"],"sourceRoot":""}