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 | |
} | |
} |
Thanks @chuckntaylor you're a legend
why not use the native EventTarget?
like this:
export default class Sizes extends EventTarget {
constructor() {
super();
this.setSizes();
window.addEventListener('resize', () => {
this.setSizes();
this.dispatchEvent(new Event('resize'));
});
}
setSizes() {
this.width = window.innerWidth;
this.height = window.innerHeight;
this.pixelRation = Math.min(window.devicePixelRatio, 2);
}
}
import Sizes from './Utils/Sizes.js';
export default class Experience {
constructor(canvas) {
// global access
globalThis.experience = this;
this.canvas = canvas;
// Setup
this.sizes = new Sizes();
this.sizes.addEventListener('resize', () => {});
}
}
@rcarubbi, I think the big issue with EventTarget
is the fact that you cannot pass arguments to the dispatchEvent
method
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
For anyone following Bruno's course and using Typescript, here is my adaptation.