Skip to content

Instantly share code, notes, and snippets.

@farishan
Created September 6, 2022 16:43
Show Gist options
  • Save farishan/23638e41a977e7ed013d03e2312e3e2f to your computer and use it in GitHub Desktop.
Save farishan/23638e41a977e7ed013d03e2312e3e2f to your computer and use it in GitHub Desktop.
Fake terminal for my future text-based RPG game
define(function () {
function Terminal($root, options = {}) {
if (!document) {
console.error("Cannot find HTML document.")
return
}
this.$root = $root || document.body
this.debug = options.debug || false
this.nodeMap = {
root: document.createElement('form'),
input: document.createElement('input')
}
this.lastInput = null
this.currentInput = null
this.onChange = null
this.listenerMap = {
/* key: callback */
}
}
Terminal.prototype.addListener = function (key, callback) {
if (!key || !callback) {
console.error('Invalid props for Terminal.addListener')
return
}
this.listenerMap[key] = callback
}
Terminal.prototype.emit = function (payload) {
if (this.onChange !== null && typeof this.onChange === 'function') {
this.onChange(payload)
}
const keys = Object.keys(this.listenerMap)
if (keys.length > 0) {
keys.forEach(key => {
// Dispatch the event.
this.listenerMap[key](payload);
});
}
}
/**
* @deps Terminal.emit
*/
Terminal.prototype.handleInput = function (value, callback) {
/* @TODO breakdown to a word processor module */
if (this.lastInput !== this.currentInput) {
this.lastInput = this.currentInput
}
if (this.currentInput !== value) this.currentInput = value
// @TODO enhance word processing
const word1 = value.split(" ")[0];
const word2 = value.split(" ")[1];
const word3 = value.split(" ")[2];
// Side-effects
this.emit([word1, word2, word3])
callback()
}
// Method to execute after terminal appended to document.body
Terminal.prototype.finalize = function () {
if (this.nodeMap.input.isConnected) {
this.nodeMap.input.focus();
}
}
/**
* @deps Terminal.handleInput
* @deps Terminal.finalize
*/
Terminal.prototype.init = function () {
this.nodeMap.input.name = 'input'
this.nodeMap.root.autocomplete = 'off'
this.nodeMap.root.onsubmit = (e) => {
e.preventDefault()
const { value } = this.nodeMap.input
if (this.debug) {
const log = document.createElement('p')
log.innerHTML = value
this.nodeMap.root.appendChild(log)
}
this.handleInput(value.toLowerCase(), () => {
this.nodeMap.input.value = "";
});
}
// Assemblages
this.nodeMap.root.appendChild(this.nodeMap.input);
this.$root.appendChild(this.nodeMap.root);
this.finalize()
}
return Terminal
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment