fix(#700): fix terminal emulator on mobile

This commit is contained in:
Alexander Wunschik
2022-04-13 22:16:46 +02:00
parent 235e6484de
commit 1f02b11c74
5 changed files with 37 additions and 42 deletions

View File

@@ -17,7 +17,7 @@
overflow-y: scroll; overflow-y: scroll;
width: 100%; width: 100%;
max-width: 60rem; max-width: 640px;
margin: 0 auto; margin: 0 auto;
} }
@@ -32,10 +32,7 @@
padding: 0; padding: 0;
} }
/* The "terminal" has one "prompt" element. /* The "terminal" has one "prompt" input-element. */
* This prompt is not any kind of input, but just a simple <span>
* with an id "prompt" and a
*/
@keyframes prompt-blink { @keyframes prompt-blink {
100% { 100% {
opacity: 0; opacity: 0;
@@ -57,6 +54,15 @@
width: 0.75rem; width: 0.75rem;
opacity: 1; opacity: 1;
} }
.terminal input#prompt {
text-transform: uppercase;
background: none;
border: none;
outline: none;
caret-color: var(--text);
color: var(--text);
font: var(--terminal-font);
}
/* Terminal scrollbar */ /* Terminal scrollbar */

View File

@@ -26,7 +26,7 @@ class HtmlTerminal {
* @private * @private
* @type {HTMLElement} * @type {HTMLElement}
*/ */
#$prompt = undefined; #$prompt;
/** /**
* Constructor * Constructor
@@ -45,13 +45,18 @@ class HtmlTerminal {
this.$output.classList.add('terminal'); this.$output.classList.add('terminal');
// Create a prompt element. // Create a prompt element.
// This element gets added if input is needed // This element gets added if input is needed.
this.#$prompt = document.createElement("span"); this.#$prompt = document.createElement("input");
this.#$prompt.setAttribute("id", "prompt"); this.#$prompt.setAttribute("id", "prompt");
this.#$prompt.innerText = ""; this.#$prompt.setAttribute("type", "text");
this.#$prompt.setAttribute("length", "50");
this.#$prompt.addEventListener("keydown", this.#handleKey.bind(this));
//TODO: this handler shouls be only on the propt element and only active if cursor is visible // Force focus on the promt on each click.
document.addEventListener("keyup", this.#handleKey.bind(this)); // This is needed for mobile support.
document.body.addEventListener('click', () => {
this.#$prompt.focus();
});
} }
/** /**
@@ -77,37 +82,16 @@ class HtmlTerminal {
* @param {*} e * @param {*} e
*/ */
#handleKey(e) { #handleKey(e) {
// if no input-callback is defined // if no input-callback is defined just return
if (!this.#inputCallback) { if (!this.#inputCallback) {
return; return;
} }
if (e.keyCode === 13 /* ENTER */) { if (e.keyCode == 13) {
// create a new line with the text input and remove the prompt const text = this.#$prompt.value;
const text = this.#$prompt.innerText; this.#$prompt.value = '';
this.write(text + "\n");
this.#$prompt.innerText = "";
this.#$prompt.remove(); this.#$prompt.remove();
this.#inputCallback(text + '\n');
// return the inputed text
this.#inputCallback(text);
// remove the callback and the key handler
this.#inputCallback = undefined;
} else if (e.keyCode === 8 /* BACKSPACE */) {
this.#$prompt.innerText = this.#$prompt.innerText.slice(0, -1);
} else if (
e.keyCode == 16 // "Shift"
|| e.keyCode == 17 // "Control"
|| e.keyCode == 20 // "CapsLock"
|| !e.key.match(/^[a-z0-9!"§#$%&'()*+,.\/:;<=>?@\[\] ^_`{|}~-]$/i)
) {
// ignore non-visible characters
return e;
} else {
this.#$prompt.innerHtml = '';
const key = e.shiftKey ? e.key.toUpperCase() : e.key;
this.#$prompt.innerText = this.#$prompt.innerText + key;
} }
} }
@@ -122,7 +106,7 @@ class HtmlTerminal {
} }
/** /**
* TODO: * Create a new div and add html content.
* *
* @public * @public
* @param {*} htmlContent * @param {*} htmlContent
@@ -189,7 +173,8 @@ class HtmlTerminal {
*/ */
input(callback) { input(callback) {
// show prompt with a blinking prompt // show prompt with a blinking prompt
this.$output.appendChild(this.#$prompt);
this.#inputCallback = callback; this.#inputCallback = callback;
this.$output.appendChild(this.#$prompt);
this.#$prompt.focus();
} }
} }

View File

@@ -1,7 +1,7 @@
<html> <html>
<head> <head>
<title>Minimal node.js terminal</title> <title>Minimal node.js terminal</title>
<meta name="viewport" content="width=device-width, initial-scale=.75"> <meta name="viewport" content="width=640, initial-scale=1">
<link <link
rel="stylesheet" rel="stylesheet"
href="../../../00_Utilities/javascript/style_terminal.css" href="../../../00_Utilities/javascript/style_terminal.css"

View File

@@ -57,9 +57,13 @@ export async function input(message = '') {
* First we need to convert it into a string. */ * First we need to convert it into a string. */
const data = input.toString(); const data = input.toString();
/* add input to terminal
* The data should end with a newline! */
process.stdout.write(data);
/* The result fo onData is a string ending with an `\n`. /* The result fo onData is a string ending with an `\n`.
* We just need the actual content so let's remove the newline at the end: */ * We just need the actual content so let's remove the newline at the end: */
const content = data[data.length] === '\n' ? data.slice(0, -1) : data; const content = data.endsWith('\n') ? data.slice(0, -1) : data;
resolve(content); resolve(content);
}); });

File diff suppressed because one or more lines are too long