TerminalHomepage/js/main.js

211 lines
7.0 KiB
JavaScript
Raw Normal View History

2023-01-13 11:37:25 +00:00
// Initiating variables
2023-01-18 13:35:17 +00:00
const length = pretext.current.length+1;
2022-05-27 16:13:33 +00:00
let cursorPosition = 0;
2023-01-12 14:10:13 +00:00
let cursorYOffset = 7;
2023-01-17 18:15:49 +00:00
let history = { index: 0, list: [] };
2022-05-27 16:13:33 +00:00
2023-01-13 11:37:25 +00:00
// Initiating constants
const tbDiv = document.getElementById("textbox");
const textIn = document.getElementById("input");
const textCur = document.getElementById("current");
const cursor = document.getElementById("cursor");
2023-02-02 07:12:12 +00:00
// Set initial pretext
const pretextElement = document.createElement('a');
pretextElement.innerHTML = pretext.original;
tbDiv.insertBefore(pretextElement, tbDiv.children[1]);
2023-01-13 11:37:25 +00:00
// Initial cursor offset
2023-01-12 14:10:13 +00:00
cursor.style.transform = `translate(${length-1}ch,${2.222*7-0.4}ch)`;
2023-01-13 11:37:25 +00:00
// Handle user input
textIn.oninput = () => {
2023-01-13 06:27:13 +00:00
const text = textCur.textContent;
2023-01-13 11:37:25 +00:00
// If cursor at end of text
2023-01-13 06:27:13 +00:00
if (cursorPosition === text.length)
textCur.textContent += textIn.value;
else {
2023-01-13 11:37:25 +00:00
// Insert input at cursor position
2023-01-13 06:27:13 +00:00
const left = text.substring(0, cursorPosition);
const right = text.substring(cursorPosition, text.length);
textCur.textContent = left + textIn.value + right;
}
2023-01-13 11:37:25 +00:00
// Increment by input length
2023-01-13 06:27:13 +00:00
cursorPosition += textIn.value.length;
textIn.value = "";
updateCursor();
};
// Autofocus on start
textIn.focus();
2023-02-08 14:30:06 +00:00
// Key Listener
2023-01-18 07:02:41 +00:00
document.addEventListener("keydown", e => {
const text = textCur.textContent;
2022-05-27 16:13:33 +00:00
switch (e.key) {
case "Backspace":
2023-02-08 14:30:06 +00:00
// Delete one character to the left
2023-01-13 06:27:13 +00:00
if (cursorPosition === 0)
2022-05-27 16:13:33 +00:00
return;
2023-02-08 14:30:06 +00:00
// Cursor is in the middle of the input
2023-01-13 06:27:13 +00:00
if (cursorPosition <= textCur.textContent.length-1) {
const a = text.substring(0, cursorPosition-1);
const b = text.substring(cursorPosition, text.length);
textCur.textContent=a+b;
2023-02-08 14:30:06 +00:00
// Cursor is at the end of input
2022-05-27 16:13:33 +00:00
} else
textCur.textContent = text.substring(0,text.length-1);
2023-02-08 14:30:06 +00:00
// Update cursor visuals
2022-05-27 16:13:33 +00:00
cursorPosition--;
updateCursor();
2022-05-27 16:13:33 +00:00
break;
case "ArrowLeft":
2023-02-08 14:30:06 +00:00
// Go one cursor position to the left
2023-01-13 06:27:13 +00:00
if (cursorPosition > 0) {
2022-05-27 16:13:33 +00:00
cursorPosition--;
updateCursor();
}
2022-05-27 16:13:33 +00:00
break;
case "ArrowRight":
2023-02-08 14:30:06 +00:00
// Go one cursor position to the right
2023-01-13 06:27:13 +00:00
if (cursorPosition < textCur.textContent.length) {
2022-05-27 16:13:33 +00:00
cursorPosition++;
updateCursor();
}
2022-05-27 16:13:33 +00:00
break;
case "Delete":
2023-02-08 14:30:06 +00:00
// Delete one character to the left
2023-01-13 06:27:13 +00:00
if (cursorPosition >= textCur.textContent.length)
return;
2023-02-08 14:30:06 +00:00
// No input given yet
if (textCur.textContent.length === 0)
2022-05-27 16:13:33 +00:00
return;
2023-01-13 06:27:13 +00:00
const a = text.substring(0, cursorPosition);
const b = text.substring(cursorPosition+1, text.length);
2023-02-08 14:30:06 +00:00
textCur.textContent = a+b;
2022-05-27 16:13:33 +00:00
break;
case "Enter":
2023-02-08 14:30:06 +00:00
// Send out command / line break
2023-01-18 07:02:41 +00:00
outputText({user: text});
2023-02-08 14:30:06 +00:00
// Refocus
textIn.focus();
2022-05-27 16:13:33 +00:00
break;
case "ArrowUp":
2023-02-08 14:30:06 +00:00
// Go back one command in the history
2023-01-13 11:57:46 +00:00
if (history.index > 0) {
history.index--;
textCur.textContent = history.list[history.index];
cursorPosition = textCur.textContent.length;
}
2023-02-08 14:30:06 +00:00
// Update cursor position
2023-01-13 11:57:46 +00:00
updateCursor();
2022-05-27 16:13:33 +00:00
break;
case "ArrowDown":
2023-02-08 14:30:06 +00:00
// Go forward one command in the history
2023-01-13 11:57:46 +00:00
if (history.index < history.list.length-1) {
history.index++;
textCur.textContent = history.list[history.index];
cursorPosition = textCur.textContent.length;
2023-02-08 14:30:06 +00:00
// Reached end of history
2023-01-16 10:08:21 +00:00
} else if (history.index < history.list.length) {
2023-01-13 11:57:46 +00:00
history.index++;
textCur.textContent = "";
cursorPosition = 0;
}
2023-02-08 14:30:06 +00:00
// Update cursor position
2023-01-13 11:57:46 +00:00
updateCursor();
2022-05-27 16:13:33 +00:00
break;
case "Tab":
2023-02-08 14:30:06 +00:00
// Auto complete
2022-05-27 16:13:33 +00:00
break;
}
});
2023-02-08 14:30:06 +00:00
// Text output or user input handler
2023-01-18 07:02:41 +00:00
function outputText(params) {
2023-02-08 14:30:06 +00:00
// Unpack parameters
const { user, output, preNext } = params;
2023-01-18 07:02:41 +00:00
2023-02-08 14:30:06 +00:00
// Temporarily remove core elements
2023-01-18 07:02:41 +00:00
tbDiv.removeChild(textIn);
tbDiv.removeChild(textCur);
2023-01-19 12:52:23 +00:00
let inputSet, whitespaceOnly = false;
2023-01-18 07:02:41 +00:00
if (user !== undefined) {
// Save input into history if it's not empty
2023-01-19 12:52:23 +00:00
inputSet = new Set(user.split(''));
whitespaceOnly = inputSet.has(" ") && inputSet.size === 1;
if (user !== "" && !whitespaceOnly) {
2023-01-18 07:02:41 +00:00
history.list.push(user);
history.index = history.list.length;
}
2023-02-08 14:30:06 +00:00
// Fixate current input to page
2023-01-18 07:02:41 +00:00
tbDiv.appendChild(createText(user));
tbDiv.innerHTML += `<br>`;
cursorYOffset++;
}
2023-02-08 14:30:06 +00:00
// Replace text on last pretext
if (preNext !== undefined) {
const tbc = tbDiv.children;
tbc[tbc.length - 1].innerHTML = preNext;
}
2023-02-08 14:30:06 +00:00
// Run as command if it's user input and display output
const isUserInput = output === undefined && user !== undefined;
2023-01-19 12:52:23 +00:00
let commandOutput = (isUserInput && !whitespaceOnly) ? runCommand(user) : (output ? output : "");
2023-01-18 07:02:41 +00:00
if (commandOutput !== "" && commandOutput !== null) {
// If output is given, display it as text with formatting
tbDiv.append(createText(commandOutput, false))
tbDiv.innerHTML += `<br>`;
// Offset cursor by at least one line, and as many more as there are line breaks
cursorYOffset += commandOutput.split("<br>").length;
}
2023-02-08 14:30:06 +00:00
2023-01-18 07:02:41 +00:00
// Add new pretext to terminal
if (commandOutput !== null) {
const prelink = document.createElement('a');
prelink.innerHTML = pretext.current;
tbDiv.appendChild(prelink);
}
2023-02-08 14:30:06 +00:00
// Add core elements back on top of div
2023-01-18 07:02:41 +00:00
tbDiv.appendChild(textCur);
tbDiv.appendChild(textIn);
2023-02-08 14:30:06 +00:00
// Reset variables and position cursor
if (isUserInput) {
textCur.textContent = "";
cursorPosition = 0;
}
2023-01-18 07:02:41 +00:00
updateCursor();
}
2023-01-13 11:37:25 +00:00
// Create an 'a' element with input string as its contents
function createText(str, safe=true) {
const link = document.createElement("a");
link.style.color = "lightgrey";
2023-01-13 12:05:59 +00:00
link.style.whiteSpace = "pre";
2023-01-13 11:37:25 +00:00
// No "HTML injection"
if (safe)
link.textContent = str;
// "Anything goes" and keep formatting
2023-01-13 12:05:59 +00:00
else
2023-01-13 11:37:25 +00:00
link.innerHTML = str;
return link;
}
// Rename last-posted pretext to own username
function renameToSelf() {
const tbc = tbDiv.children;
2023-02-02 07:12:12 +00:00
tbc[tbc.length - 3].innerHTML = `${window.localStorage.getItem("name")}#${window.localStorage.getItem("id")}: `;
}
2023-01-13 11:37:25 +00:00
// Update cursor position based on coordinates
function updateCursor() {
let cursor = document.getElementById("cursor");
2023-01-18 13:35:17 +00:00
cursor.style.transform = `translate(${pretext.current.length+cursorPosition}ch, ${2.222*cursorYOffset-0.4}ch)`;
}
2023-01-13 11:37:25 +00:00
// Toggle cursor visibility
2022-05-27 16:13:33 +00:00
setInterval(()=>{
cursor.style.opacity = !parseInt(cursor.style.opacity)+0;
2022-05-27 16:13:33 +00:00
},1000);