<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Console</title>
<style>
* {
margin: 0;
padding: 0;
}
li {
list-style: none;
}
#container {
padding: 10px;
display: block;
overflow-y: auto;
cursor: pointer;
}
#container div {
display: inline-block;
min-width: 100px;
}
#container #placer {
display: flex;
align-items: stretch;
}
#container #placer span {
text-align: left;
}
#container #placer div {
text-align: left;
}
#container #placer div:focus {
outline-width: 0;
}
</style>
</head>
<body>
<divlabel onclick="document.getElementById('inputArea').focus()" id="container">
<ul id="commandsHistory"></ul>
<span id="placer">
<span id="prefixHolder">Gabriel: </span>
<div id="inputArea" contenteditable="true"></div>
</span>
</divlabel>
</body>
</html>
<script>
function init(){
const commands = ["history", "reset", "exit", "help"];
const options = {
backgroundColor: "black",
fontColor: "white",
fontSize: 20,
};
const container = document.getElementById("container");
const commandsHistory = document.getElementById("commandsHistory");
const prefixHolder = document.getElementById("prefixHolder");
const inputArea = document.getElementById("inputArea");
inputArea.addEventListener("keydown", send);
function setStyles() {
container.style.backgroundColor = options.backgroundColor;
container.style.color = options.fontColor;
container.style.fontSize = options.fontSize + "px";
inputArea.style.caratColor = options.fontColor;
container.style.maxHeight = options.fontSize * 5 + "px";
}
setStyles();
function getPrefix() {
const prefixText = prefixHolder.innerText;
return prefixText + " ";
}
function tabEvent(text) {
const splitText = text.split(" ");
if (splitText.length > 0) {
const lastWorld = splitText[splitText.length - 1];
const targetWord = commands.find((e) => e.startsWith(lastWorld));
if (targetWord) {
return text + targetWord.substring(lastWorld.length, targetWord.length) + " ";
}
return text;
}
return text;
}
function send(e) {
const element = e.target;
if (e.keyCode === 13) {
if(e.shiftKey) {
element.innerHTML += "<br>";
return false;
}
e.preventDefault();
const commandText = element.innerText;
element.innerHTML = "";
addText(commandText);
container.scrollTop = container.scrollHeight;
return false
}
if (e.keyCode === 9) {
e.preventDefault();
element.innerHTML = tabEvent(element.innerText);
setCursor(0, element.innerText.length);
return false;
}
}
function setCursor(line, position) {
const range = document.createRange();
const sel = window.getSelection();
range.setStart(inputArea.childNodes[line], position);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
function addText(text, addPrefix= true) {
const newLi = document.createElement("li");
const prefix = addPrefix ? getPrefix() : "";
newLi.innerText = prefix + text;
commandsHistory.appendChild(newLi);
}
}
init();
</script>