Created
November 1, 2021 11:22
-
-
Save brunosimon/120acda915e6629e3a4d497935b16bdf to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export default class EventEmitter | |
{ | |
constructor() | |
{ | |
this.callbacks = {} | |
this.callbacks.base = {} | |
} | |
on(_names, callback) | |
{ | |
// Errors | |
if(typeof _names === 'undefined' || _names === '') | |
{ | |
console.warn('wrong names') | |
return false | |
} | |
if(typeof callback === 'undefined') | |
{ | |
console.warn('wrong callback') | |
return false | |
} | |
// Resolve names | |
const names = this.resolveNames(_names) | |
// Each name | |
names.forEach((_name) => | |
{ | |
// Resolve name | |
const name = this.resolveName(_name) | |
// Create namespace if not exist | |
if(!(this.callbacks[ name.namespace ] instanceof Object)) | |
this.callbacks[ name.namespace ] = {} | |
// Create callback if not exist | |
if(!(this.callbacks[ name.namespace ][ name.value ] instanceof Array)) | |
this.callbacks[ name.namespace ][ name.value ] = [] | |
// Add callback | |
this.callbacks[ name.namespace ][ name.value ].push(callback) | |
}) | |
return this | |
} | |
off(_names) | |
{ | |
// Errors | |
if(typeof _names === 'undefined' || _names === '') | |
{ | |
console.warn('wrong name') | |
return false | |
} | |
// Resolve names | |
const names = this.resolveNames(_names) | |
// Each name | |
names.forEach((_name) => | |
{ | |
// Resolve name | |
const name = this.resolveName(_name) | |
// Remove namespace | |
if(name.namespace !== 'base' && name.value === '') | |
{ | |
delete this.callbacks[ name.namespace ] | |
} | |
// Remove specific callback in namespace | |
else | |
{ | |
// Default | |
if(name.namespace === 'base') | |
{ | |
// Try to remove from each namespace | |
for(const namespace in this.callbacks) | |
{ | |
if(this.callbacks[ namespace ] instanceof Object && this.callbacks[ namespace ][ name.value ] instanceof Array) | |
{ | |
delete this.callbacks[ namespace ][ name.value ] | |
// Remove namespace if empty | |
if(Object.keys(this.callbacks[ namespace ]).length === 0) | |
delete this.callbacks[ namespace ] | |
} | |
} | |
} | |
// Specified namespace | |
else if(this.callbacks[ name.namespace ] instanceof Object && this.callbacks[ name.namespace ][ name.value ] instanceof Array) | |
{ | |
delete this.callbacks[ name.namespace ][ name.value ] | |
// Remove namespace if empty | |
if(Object.keys(this.callbacks[ name.namespace ]).length === 0) | |
delete this.callbacks[ name.namespace ] | |
} | |
} | |
}) | |
return this | |
} | |
trigger(_name, _args) | |
{ | |
// Errors | |
if(typeof _name === 'undefined' || _name === '') | |
{ | |
console.warn('wrong name') | |
return false | |
} | |
let finalResult = null | |
let result = null | |
// Default args | |
const args = !(_args instanceof Array) ? [] : _args | |
// Resolve names (should on have one event) | |
let name = this.resolveNames(_name) | |
// Resolve name | |
name = this.resolveName(name[ 0 ]) | |
// Default namespace | |
if(name.namespace === 'base') | |
{ | |
// Try to find callback in each namespace | |
for(const namespace in this.callbacks) | |
{ | |
if(this.callbacks[ namespace ] instanceof Object && this.callbacks[ namespace ][ name.value ] instanceof Array) | |
{ | |
this.callbacks[ namespace ][ name.value ].forEach(function(callback) | |
{ | |
result = callback.apply(this, args) | |
if(typeof finalResult === 'undefined') | |
{ | |
finalResult = result | |
} | |
}) | |
} | |
} | |
} | |
// Specified namespace | |
else if(this.callbacks[ name.namespace ] instanceof Object) | |
{ | |
if(name.value === '') | |
{ | |
console.warn('wrong name') | |
return this | |
} | |
this.callbacks[ name.namespace ][ name.value ].forEach(function(callback) | |
{ | |
result = callback.apply(this, args) | |
if(typeof finalResult === 'undefined') | |
finalResult = result | |
}) | |
} | |
return finalResult | |
} | |
resolveNames(_names) | |
{ | |
let names = _names | |
names = names.replace(/[^a-zA-Z0-9 ,/.]/g, '') | |
names = names.replace(/[,/]+/g, ' ') | |
names = names.split(' ') | |
return names | |
} | |
resolveName(name) | |
{ | |
const newName = {} | |
const parts = name.split('.') | |
newName.original = name | |
newName.value = parts[ 0 ] | |
newName.namespace = 'base' // Base namespace | |
// Specified namespace | |
if(parts.length > 1 && parts[ 1 ] !== '') | |
{ | |
newName.namespace = parts[ 1 ] | |
} | |
return newName | |
} | |
} |
Using EventTarget, you can also dispatch a CustomEvent which includes a detail property for any additional data
Interestingly, Three.js has it's own EventDispatcher
Bruno, thank you for being you!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@rcarubbi, I think the big issue with
EventTarget
is the fact that you cannot pass arguments to thedispatchEvent
method