diff --git a/_build_js.sh b/_build_js.sh index fa03512..21c1196 100755 --- a/_build_js.sh +++ b/_build_js.sh @@ -18,6 +18,7 @@ npm run babel -- -o "out/js/app.$FRONT_END_HASH.js" ${smarg} js/lib \ js/lib/chibi.js \ js/lib/keymaster.js \ js/lib/polyfills.js \ + js/event_emitter.js \ js/utils.js \ js/modal.js \ js/notif.js \ diff --git a/js/demo.js b/js/demo.js index 8901611..85b7979 100644 --- a/js/demo.js +++ b/js/demo.js @@ -304,47 +304,7 @@ class ScrollingTerminal { } } -class Process { - constructor (args) { - // event listeners - this._listeners = {} - } - on (event, listener) { - if (!this._listeners[event]) this._listeners[event] = [] - this._listeners[event].push({ listener }) - } - once (event, listener) { - if (!this._listeners[event]) this._listeners[event] = [] - this._listeners[event].push({ listener, once: true }) - } - off (event, listener) { - let listeners = this._listeners[event] - if (listeners) { - for (let i in listeners) { - if (listeners[i].listener === listener) { - listeners.splice(i, 1) - break - } - } - } - } - emit (event, ...args) { - let listeners = this._listeners[event] - if (listeners) { - let remove = [] - for (let listener of listeners) { - try { - listener.listener(...args) - if (listener.once) remove.push(listener) - } catch (err) { - console.error(err) - } - } - for (let listener of remove) { - listeners.splice(listeners.indexOf(listener), 1) - } - } - } +class Process extends EventEmitter { write (data) { this.emit('in', data) } diff --git a/js/event_emitter.js b/js/event_emitter.js new file mode 100644 index 0000000..88d6db7 --- /dev/null +++ b/js/event_emitter.js @@ -0,0 +1,70 @@ +if (!('EventEmitter' in window)) { + window.EventEmitter = class EventEmitter { + constructor () { + this._listeners = {} + } + + /** + * Bind an event listener to an event + * @param {string} event - the event name + * @param {Function} listener - the event listener + */ + on (event, listener) { + if (!this._listeners[event]) this._listeners[event] = [] + this._listeners[event].push({ listener }) + } + + /** + * Bind an event listener to be run only once the next time the event fires + * @param {string} event - the event name + * @param {Function} listener - the event listener + */ + once (event, listener) { + if (!this._listeners[event]) this._listeners[event] = [] + this._listeners[event].push({ listener, once: true }) + } + + /** + * Remove an event listener + * @param {string} event - the event name + * @param {Function} listener - the event listener + */ + off (event, listener) { + let listeners = this._listeners[event] + if (listeners) { + for (let i in listeners) { + if (listeners[i].listener === listener) { + listeners.splice(i, 1) + break + } + } + } + } + + /** + * Emits an event + * @param {string} event - the event name + * @param {...any} args - arguments passed to all listeners + */ + emit (event, ...args) { + let listeners = this._listeners[event] + if (listeners) { + let remove = [] + for (let listener of listeners) { + try { + listener.listener(...args) + if (listener.once) remove.push(listener) + } catch (err) { + console.error(err) + } + } + + // this needs to be done in this roundabout way because for loops + // do not like arrays with changing lengths + for (let listener of remove) { + listeners.splice(listeners.indexOf(listener), 1) + } + } + } + } +} diff --git a/js/term_screen.js b/js/term_screen.js index b734771..57e8167 100644 --- a/js/term_screen.js +++ b/js/term_screen.js @@ -68,8 +68,10 @@ for (let gray = 0; gray < 24; gray++) { colorTable256.push(`rgb(${value}, ${value}, ${value})`) } -window.TermScreen = class TermScreen { +window.TermScreen = class TermScreen extends EventEmitter { constructor () { + super() + this.canvas = mk('canvas') this.ctx = this.canvas.getContext('2d') @@ -145,9 +147,6 @@ window.TermScreen = class TermScreen { // mouse features this.mouseMode = { clicks: false, movement: false } - // event listeners - this._listeners = {} - // make writing to window update size and draw const self = this this.window = new Proxy(this._window, { @@ -350,69 +349,6 @@ window.TermScreen = class TermScreen { }) } - /** - * Bind an event listener to an event - * @param {string} event - the event name - * @param {Function} listener - the event listener - */ - on (event, listener) { - if (!this._listeners[event]) this._listeners[event] = [] - this._listeners[event].push({ listener }) - } - - /** - * Bind an event listener to be run only once the next time the event fires - * @param {string} event - the event name - * @param {Function} listener - the event listener - */ - once (event, listener) { - if (!this._listeners[event]) this._listeners[event] = [] - this._listeners[event].push({ listener, once: true }) - } - - /** - * Remove an event listener - * @param {string} event - the event name - * @param {Function} listener - the event listener - */ - off (event, listener) { - let listeners = this._listeners[event] - if (listeners) { - for (let i in listeners) { - if (listeners[i].listener === listener) { - listeners.splice(i, 1) - break - } - } - } - } - - /** - * Emits an event - * @param {string} event - the event name - * @param {...any} args - arguments passed to all listeners - */ - emit (event, ...args) { - let listeners = this._listeners[event] - if (listeners) { - let remove = [] - for (let listener of listeners) { - try { - listener.listener(...args) - if (listener.once) remove.push(listener) - } catch (err) { - console.error(err) - } - } - - // this needs to be done in this roundabout way because for loops - // do not like arrays with changing lengths - for (let listener of remove) { - listeners.splice(listeners.indexOf(listener), 1) - } - } - } - /** * The color palette. Should define 16 colors in an array. * @type {number[]}