Skip to content

Instantly share code, notes, and snippets.

@Sominemo
Last active January 5, 2021 05:23
Show Gist options
  • Save Sominemo/54db02875a6e8a3710b9bf3ca5b9d789 to your computer and use it in GitHub Desktop.
Save Sominemo/54db02875a6e8a3710b9bf3ca5b9d789 to your computer and use it in GitHub Desktop.
onWord (And OnWordListener) class to react on typing with a callback (minified: https://gist.github.com/Sominemo/ff8d65baf08e7dfaa24a2973f2bca4d6)
/**
* @typedef {Object} OnWordListenerInfo
* @property {function[]} callback Callbacks for the listener
* @property {boolean} case Case senisvity
* @property {boolean} debug Debug mode for the listener
* @property {number} stage Symbol number which will be checked on the next keypress
* @property {string} string String the item is listening for
*/
class OnWordListener {
/**
* @param {object} data Data to link
* @param {number} id ID to save
* @param {OnWord} parent Binded OnWord class
* @property {number} ID of the listener
*/
constructor(id, parent) {
this.parent = parent
this.id = id
}
/**
* Get listener info by details
* @param {number} i ID to get
* @returns {OnWordListenerInfo} The listener
*/
get info() {
return this.parent.getById(this.id)
}
/**
* Disable listener
* @param {number} id ID of the listener
*/
unset() {
this.parent.unset(this.id)
}
}
/** The class for listening words typed on keyboard
* @property {boolean} disabled OnWord status
* @property {[]} register Contains all listeners
* @property {function} listener Binded {@link OnWord.handler}
* @example
* let v = new OnWord(string, callback, cases = false, debug = false);
* @example
* let v = new OnWord();
* v.listen(string, callback, cases = false, debug = false);
*/
class OnWord {
constructor(string = false, callback, cases = false, debug = false) {
this.register = []
this.disabled = false
this.listener = this.handler.bind(this)
document.addEventListener("keypress", this.listener)
if (cases) this.listen(string, callback, cases, debug)
}
/**
* Add new listener
* Adds new string listener with a callback to the register.
* @param {string} string String for listening
* @param {function} callback Callback function
* @param {boolean} cases=false Case sensivity
* @param {boolean} debug=false Debug mode. Provides onkeypress feedback in console
* @returns {OnWordListener} Listener object
*/
listen(string, callback, cases = false, debug = false) {
let id = this.register.findIndex(
a => a.string === string
&& cases === a.case
&& debug === a.debug,
)
if (id === -1) {
this.register.push(
{
string: (cases ? string : string.toLowerCase()),
stage: 0,
callback: [callback],
case: cases,
debug,
},
)
} else {
this.register[id].callback.push(callback)
}
id = (id === -1 ? this.register.length - 1 : id)
return new OnWordListener(id, this)
}
/**
* Get data by ID
* @param {number} id ID of the listener
*/
getById(id) {
return this.register[id]
}
/**
* Handles onkeypress event
* @param {object} event The event
*/
handler(event) {
if (this.disabled) return
const { key } = event
const lKey = key.toLowerCase()
this.register.forEach((item) => {
const r = (item.case ? key : lKey)
if (item.string[item.stage] === r) {
item.stage++
if (item.debug) console.log(`${r} = ${item.string[item.stage - 1]}`)
} else {
if (item.debug) console.log(`${r} != ${item.string[item.stage]}`)
item.stage = 0
}
if (item.stage >= item.string.length) {
item.stage = 0
item.callback.forEach(a => a())
}
})
}
/**
* Disable listener
* @param {number} id ID of the listener
*/
unset(id) {
this.register.splice(id, 1)
}
/**
* Disable OnWord fully
* @param {boolean} f evaluate removeEventListener too (false by default)
*/
disable(f) {
this.disabled = true
if (f) {
document.removeEventListener("keypress", this.listener)
this.listener = false
}
}
/**
* Bring onWord back to work
*/
enable() {
this.disabled = false
if (!this.listener) {
this.listener = this.handler.bind(this)
document.addEventListener("keypress", this.listener)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment