Skip to content

Instantly share code, notes, and snippets.

@brunosimon
Created November 1, 2021 11:22
  • Star 60 You must be signed in to star a gist
  • Fork 14 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save brunosimon/120acda915e6629e3a4d497935b16bdf to your computer and use it in GitHub Desktop.
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
}
}
@Beygs
Copy link

Beygs commented Sep 6, 2022

Thanks @chuckntaylor you're a legend

@rcarubbi
Copy link

rcarubbi commented Apr 9, 2023

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', () => {});
	}
}

@Neosoulink
Copy link

@rcarubbi, I think the big issue with EventTarget is the fact that you cannot pass arguments to the dispatchEvent method

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment