Callbacks

Before we proceed to plugins, we need to talk about callbacks. Spiritual promotes the use of callbacks as methods of objects instead of anonymous functions; such as this one.

document.addEventListener('click', function(e) {
	console.log(e.target);
});

The following code will do same. It's vanilla DOM.

document.addEventListener('click', {
	handleEvent: function(e) {
		console.log(e.target);
	}
});

Instead of a function, we have an object with a special method handleEvent. Spirits prefer this way of doing it, except the method is called onevent. Spirits can manage events using the event plugin.

gui.Spirit.extend({
	onenter: function() {
		this.super.onenter();
		this.event.add('click', document);
	},
	onevent: function(e) {
		this.super.onevent(e);
		console.log(e.type, e.target);	
	}
});

You can jump to a detailed description of the event plugin.

With this code, we note that it's always clear what this is. There's no need to bind the this keyword or use that=this. And as long as we know what this is, there's no need to keep track of a function reference in order to remove the event listener at a later stage. As the complexity of your website approaches the singularity, the need to remove event listeners always arise.

this.event.remove('click', document);

This allows us to navigate some pretty complex event business logic without getting trapped in callback hell. Like in this simplified drag and drop routine.

gui.Spirit.extend({
	onenter: function() {
		this.super.onenter();
		this.event.add('mousedown');
	},
	onevent: function(e) {
		this.super.onevent(e);
		switch(e.type) {
			case 'mousedown':
				this.event.remove('mousedown').
				this.event.add('mousemove mouseup');
				break;
			case 'mousemove':
				this.css.left = e.clientX;
				break;
			case 'mouseup':
				this.event.remove('mousedown mouseup');
				this.event.add('mousedown');
				break;
		}
	}
});

The flat structure makes it easy to avoid application state becoming trapped in deeply nested functions. We also note that:

The thruth is that the function pattern is a perfectly valid pattern. We simply haven't added support for it yet throughout the various plugins. We'll encourage the method pattern for now, but you can of course always bypass the event plugin and use a straight callback.

this.element.addEventListener('click', function(e) {
	console.log('Clicked');
});

With that in mind, let's continue to plugins.