UNPKG

terminal-js-emulator

Version:

terminal.js is a dead simple JavaScript library for emulating a shell environment

244 lines (200 loc) 7.21 kB
/*! terminal.js | https://github.com/eosterberg/terminaljs */ module.exports = (function () { var VERSION = '3.0.1'; // PROMPT_TYPE var PROMPT_INPUT = 1, PROMPT_PASSWORD = 2, PROMPT_CONFIRM = 3; var firstPrompt = true; promptInput = function (terminalObj, message, PROMPT_TYPE, callback) { var shouldDisplayInput = (PROMPT_TYPE === PROMPT_INPUT || PROMPT_TYPE === PROMPT_CONFIRM); var inputField = document.createElement('input'); inputField.style.position = 'absolute'; inputField.style.zIndex = '-100'; inputField.style.outline = 'none'; inputField.style.border = 'none'; inputField.style.opacity = '0'; inputField.style.fontSize = '0.2em'; terminalObj._inputLine.textContent = ''; terminalObj._input.style.display = 'block'; terminalObj.html.appendChild(inputField); terminalObj.fireCursorInterval(inputField); if (message.length) { terminalObj.print(PROMPT_TYPE === PROMPT_CONFIRM ? message + ' (y/n)' : message); } inputField.onblur = function () { terminalObj._cursor.style.display = 'none'; } inputField.onfocus = function () { inputField.value = terminalObj._inputLine.textContent; terminalObj._cursor.style.display = 'inline'; } terminalObj.html.onclick = function () { inputField.focus(); } inputField.onkeydown = function (e) { if (e.code === 'ArrowUp' || e.code === 'ArrowRight' || e.code === 'ArrowLeft' || e.code === 'ArrowDown' || e.code === 'Tab') { e.preventDefault(); } } inputField.onkeyup = function (e) { var inputValue = inputField.value; if (shouldDisplayInput && e.code !== 'Enter') { terminalObj._inputLine.textContent = inputField.value; } if (PROMPT_TYPE === PROMPT_CONFIRM && e.code !== 'Enter') { if (e.code !== 'KeyY' && e.code !== 'KeyN') { // PROMPT_CONFIRM accept only "Y" and "N" terminalObj._inputLine.textContent = inputField.value = ''; return; } if (terminalObj._inputLine.textContent.length > 1) { // PROMPT_CONFIRM accept only one character terminalObj._inputLine.textContent = inputField.value = terminalObj._inputLine.textContent.substr(-1); } } if (e.code === "Enter") { if (PROMPT_TYPE === PROMPT_CONFIRM) { if (!inputValue.length) { // PROMPT_CONFIRM doesn't accept empty string. It requires answer. return; } } terminalObj._input.style.display = 'none'; if (shouldDisplayInput) { terminalObj.print(inputValue); } if (typeof(callback) === 'function') { if (PROMPT_TYPE === PROMPT_CONFIRM) { if (inputValue.toUpperCase()[0] === 'Y') { callback(true); } else if (inputValue.toUpperCase()[0] === 'N') { callback(false); } else { throw `PROMPT_CONFIRM failed: Invalid input (${inputValue.toUpperCase()[0]}})`; } } else { callback(inputValue); } terminalObj.html.removeChild(inputField); // remove input field in the end of each callback terminalObj.scrollBottom(); // scroll to the bottom of the terminal } } } inputField.focus(); } var TerminalConstructor = function (containerId) { let terminalObj = this; this.html = document.createElement('div'); this.html.className = 'Terminal'; this._innerWindow = document.createElement('div'); this._output = document.createElement('p'); this._promptPS = document.createElement('span'); this._inputLine = document.createElement('span'); //the span element where the users input is put this._cursor = document.createElement('span'); this._input = document.createElement('p'); //the full element administering the user input, including cursor this._shouldBlinkCursor = true; this.cursorTimer; this.fireCursorInterval = function (inputField) { if (terminalObj.cursorTimer) { clearTimeout(terminalObj.cursorTimer); } terminalObj.cursorTimer = setTimeout(function () { if (inputField.parentElement && terminalObj._shouldBlinkCursor) { terminalObj._cursor.style.visibility = terminalObj._cursor.style.visibility === 'visible' ? 'hidden' : 'visible'; terminalObj.fireCursorInterval(inputField); } else { terminalObj._cursor.style.visibility = 'visible'; } }, 500); }; this.scrollBottom = function() { this.html.scrollTop = this.html.scrollHeight; } this.print = function (message) { var newLine = document.createElement('div'); newLine.textContent = message; this._output.appendChild(newLine); this.scrollBottom(); return this; } this.input = function (message, callback) { promptInput(this, message, PROMPT_INPUT, callback); return this; } this.password = function (message, callback) { promptInput(this, message, PROMPT_PASSWORD, callback); return this; } this.confirm = function (message, callback) { promptInput(this, message, PROMPT_CONFIRM, callback); return this; } this.clear = function () { this._output.innerHTML = ''; return this; } this.sleep = function (milliseconds, callback) { setTimeout(callback, milliseconds); return this; } this.setTextSize = function (size) { this._output.style.fontSize = size; this._input.style.fontSize = size; return this; } this.setTextColor = function (col) { this.html.style.color = col; this._cursor.style.background = col; return this; } this.setBackgroundColor = function (col) { this.html.style.background = col; return this; } this.setWidth = function (width) { this.html.style.width = width; return this; } this.setHeight = function (height) { this.html.style.height = height; return this; } this.blinkingCursor = function (bool) { bool = bool.toString().toUpperCase(); this._shouldBlinkCursor = (bool === 'TRUE' || bool === '1' || bool === 'YES'); return this; } this.setPrompt = function (promptPS) { this._promptPS.textContent = promptPS; return this; } this.getVersion = function() { console.info(`TerminalJS ${VERSION}`) return VERSION; } this._input.appendChild(this._promptPS); this._input.appendChild(this._inputLine); this._input.appendChild(this._cursor); this._innerWindow.appendChild(this._output); this._innerWindow.appendChild(this._input); this.html.appendChild(this._innerWindow); this.setBackgroundColor('black') .setTextColor('white') .setTextSize('1em') .setWidth('100%') .setHeight('100%'); this.html.style.fontFamily = 'Ubuntu Mono, Monaco, Courier'; this.html.style.margin = '0'; this.html.style.overflow = 'auto'; this.html.style.whiteSpace = 'pre'; this._innerWindow.style.padding = '10px'; this._input.style.margin = '0'; this._output.style.margin = '0'; this._cursor.style.background = 'white'; this._cursor.innerHTML = 'C'; //put something in the cursor.. this._cursor.style.display = 'none'; //then hide it this._input.style.display = 'none'; if (typeof(containerId) === 'string') { let container = document.getElementById(containerId); container.innerHTML = ""; container.appendChild(this.html); } else { throw "terminal-js-emulator requires (string) parent container id in the constructor"; } } return TerminalConstructor; }())