import { DosKeyEventConsumer } from "../js-dos-ci"; import * as DosDom from "../js-dos-dom"; export interface QwertyOptions { uppercase: boolean; cssText?: string; } const defaultOptions: QwertyOptions = { uppercase: true, }; function convert(input: string): string { const controlChars: any[] = [ { name: "Backspace", code: 8 }, { name: "Tab", code: 9 }, { name: "Enter", code: 13 }, { name: "Shift", code: 16 }, { name: "Ctrl", code: 17 }, { name: "Alt", code: 18 }, { name: "Pause", code: 19 }, { name: "Caps", code: 20 }, { name: "Esc", code: 27 }, { name: "PgUp", code: 33 }, { name: "PgDn", code: 34 }, { name: "End", code: 35 }, { name: "Home", code: 36 }, { name: "Left", code: 37 }, { name: "Up", code: 38 }, { name: "Right", code: 39 }, { name: "Down", code: 40 }, { name: "Insert", code: 45 }, { name: "Delete", code: 46 }, ]; let i: number = 0; let output: string = ""; while (i < input.length) { if (input[i] === "<") { const index: number = controlChars.findIndex((key: any) => { return input.substr(i + 1, key.name.length + 1).toLowerCase() === key.name.toLowerCase() + ">"; }); if (index !== -1) { output += String.fromCharCode(controlChars[index].code); i += controlChars[index].name.length + 2; } else { output += input[i]; i++; } } else { output += input[i]; i++; } } return output; } export default function Qwerty(zone: HTMLDivElement, consumer: DosKeyEventConsumer, options: QwertyOptions = defaultOptions) { DosDom.applyCss("lqwerty-css", css + "\n\n" + (options.cssText || "")); const sendFn = () => { const value = options.uppercase ? input.value.toUpperCase() : input.value; input.value = ""; input.blur(); container.style.visibility = "hidden"; if (value.length === 0) { return; } let i = 0; const convertedValue: string = convert(value); const id = setInterval(() => { if (i >= convertedValue.length * 2) { clearInterval(id); return; } if (i % 2 === 0) { consumer.onPress(convertedValue.charCodeAt(i / 2)); } else { consumer.onRelease(convertedValue.charCodeAt((i - 1) / 2)); } i++; }, 100); }; const container = DosDom.createDiv("qwerty-container") as HTMLDivElement; container.innerHTML = `
ENTER CHARS:
:> 
Send
`; container.style.visibility = "hidden"; const noPropagationFn = (e: KeyboardEvent) => { e.stopPropagation(); }; container.addEventListener("keydown", noPropagationFn); container.addEventListener("keyup", noPropagationFn); container.addEventListener("keypress", (e: KeyboardEvent) => { if (e.keyCode === 13) { sendFn(); } }); container.addEventListener("keypress", noPropagationFn); const input = container.getElementsByTagName("input")[0] as HTMLInputElement; const resizeFn = () => { input.style.width = Math.max(2, input.value.length + 1) + "ch"; }; input.tabIndex = 1; input.addEventListener("input", resizeFn); input.addEventListener("blur", sendFn); const send = container.getElementsByClassName("qwerty-send")[0] as HTMLButtonElement; DosDom.addButtonListener(send, () => {/**/}, sendFn); const key = DosDom.createDiv("qwerty-key"); DosDom.addButtonListener(key, () => { // nothing }, () => { if (container.style.visibility === "hidden") { resizeFn(); container.style.visibility = "visible"; input.focus(); } else { container.style.visibility = "hidden"; } }); zone.appendChild(key); zone.appendChild(container); } const css = ` .qwerty-container { position: absolute; left: 0; top: 0; right: 0; display: flex; flex-direction: column; padding: 10px 20px; font-size: 1em; background: #000000e3; border-bottom: 2px solid white; font-family: monospace; color: white; line-height: 1.4em; } .qwerty-input-row { display: flex; flex-grow: 1; align-items: center; } .qwerty-input, .qwerty-input:focus { padding: 0; margin: 0; border: none; background: black; color: white; font: inherit; display: inline-block; outline: none; } .qwerty-send { color: black; padding: 5px 0.5em; margin-left: 0.5em; padding: 5px; background: lightgray; border-left: 1px solid white; border-top: 1px solid white; border-right: 1px solid darkgray; border-bottom: 1px solid darkgray; } .qwerty-key { display: flex; position: absolute; left: 10px; bottom: 10px; align-items: center; justify-content: center; color: black; font-size: 2em; width: 48px; height: 48px; background: lightgray url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAZRJREFUWIXtlr9KA0EQxn9ngmBroY0W/k0stZbYKFqICD6DYCFiLfgIgtG8iGIkRcBGsLGx8Q+JYAhcwDdQE8/iZsncesgpeCuYDw72+2bmZnZ3bhLooYf/Dg8YBIYc5X/2gDcg66iAtgcEjpID3Z0vAo2Uc08AFVNAA6inXEAWoM8SN4ASsKm0omg54QXhe8pnX7R54TPCi8pnS7R1u5IAmJR1SfiZZQ+AFeG7wu+VT120beGrKs6gIvxQeB4I7O6/AcrAldJOgQzQUsnKRHumKgU9CvfFp23vNg76BH4TsSdg90DqsAs4ont3AdBRtnPRDoRPK78xK/5Exb2LtpykgK+4WWdibLaWUTYvLrE2BsAUYXPl6O4GwiaqynoWGCZstBowACyI7QJ4UfEtwoYGWLIKMvF54A7Sa0IbsZ9hAZgjPA0zC3b4fDVJ0QGOZb0GjAPXwKV2SjqIfvoYJBpEPvBAdMjcEr3D70APoid5t287Oe0B54PIfIZN4DXl3P3AqPN/RB7h7/OIo/xNR3l7+EP4AJe/eBF8vW9QAAAAAElFTkSuQmCC) no-repeat center center; border-left: 1px solid white; border-top: 1px solid white; border-right: 1px solid darkgray; border-bottom: 1px solid darkgray; } .qwerty-cursor { background: white; width: 0.5em; height: 1em; animation: qwerty-blink 1s; -moz-animation: qwerty-blink 1s infinite; -webkit-animation: qwerty-blink 1s infinite; } @-moz-keyframes qwerty-blink { 0% {background:white;} 50% {background:black;} 100% {background:white;} } @-webkit-keyframes qwerty-blink { 0% {background:white;} 50% {background:black;} 100% {background:white;} } `;