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:
- All DOM event handling gets channeled into single method. That's nice for maintenance, especially when we add support for other types of callbacks such as
onlife
,onaction
andonbroadcast
. - It's easy to manage
this.super.onevent(e)
. This makes it particularly easy for a subclass to not do the normal thing under certain conditions.
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.