Enyo Daily #16 - Events - Part 4
A question came up on the forums regarding global custom events. The use case described was the need to pass an event up or down the object hierarchy just to react to it at the appropriate level. Enyo actually can support this with the current architecture using its event dispatcher and it only requires a couple lines of code to implement.[[MORE]]
To fire the event, use window.enyo.dispatch(eventObject). eventObject must define a type member.
window.enyo.dispatch({type:"customGlobalEvent", data:"something to pass"});
To catch the event, add your control to the rootHandler's listeners and implement a xxxHandler method for the event.
create:function() {
this.inherited(arguments);
enyo.dispatcher.rootHandler.addListener(this);
},
customGlobalEventHandler:function(sender, param) {
enyo.log("customGlobalEvent", param.data); // logs: customGlobalEvent something to pass
}
Here it is in action in my continuing events example:
var _Example = {
name:"com.technisode.example.App",
kind:"Control",
components:[
{kind:"ApplicationEvents", name:"appEvents"},
{kind:"EventSender", name:"eventSender", onSend:"sent"},
{kind:"Button", onclick:"clicked"},
{kind:"Input", onkeypress:"press"}
],
create:function() {
this.inherited(arguments);
// map all ApplicationEvents to logAppEvent
var ae = this.$.appEvents;
Object.keys(enyo.ApplicationEvents.prototype.events).forEach(function(key) {
//enyo.log("setting handler for ",key);
ae[key] = "logAppEvent";
});
enyo.dispatcher.rootHandler.addListener(this);
},
logAppEvent:function(source, e) {
enyo.log("logAppEvent",e.type);
},
resizeHandler:function() {
enyo.log("dimensions",window.document.body.offsetWidth,window.document.body.offsetHeight);
},
captureDomEvent:function(e) {
enyo.log("A DOM event occured", e.type);
// returning true would indicated the event is captured and prevent the bubble phase
// thereby preventing the declared handlers (clicked in this case) from being called
// returning false (or no explicit return) lets things continue
return false;
},
dispatchDomEvent:function(e) {
// like any other method, you could override dispatchDomEvent and implement custom routing
e.myCustomField = "This is a custom field";
return this.inherited(arguments);
},
press:function(source, event) {
enyo.log(source, event);
},
clickHandler:function(source, event) {
enyo.log("bubbled up to me", event.myCustomField);
// calling event.stopPropagation() or returning true will end the bubble phase
},
clicked:function(source, event) {
// trigger my custom events
this.$.eventSender.go();
// toggles event handler between send and secondSent ... just because ...
this.$.eventSender.onSend = (this.$.eventSender.onSend === "sent") ? "secondSent" : "sent";
// calling event.stopPropagation() or returning true will end the bubble phase
},
sent:function(source, one, two, three) {
enyo.log("sent", one, two, three)
},
handleOnAlert:function(source, obj) {
enyo.log("alerted", enyo.json.stringify(obj));
},
secondSent:function(source, one, two, three) {
enyo.log("secondSent handles onSend now", one, two, three)
},
customGlobalEventHandler:function(sender, param) {
enyo.log("customGlobalEvent", param.data);
}
}
var _EventSender = {
name:"EventSender",
kind:"Component",
events:{
onSend:"handleOnSend",
onAlert:{value:"handleOnAlert", caller:"sendAlert"}
},
create:function() {
this.inherited(arguments);
enyo.dispatcher.rootHandler.addListener(this);
},
go:function() {
this.doSend(1,2,3); // dispatchIndirectly
this.sendAlert({a:1, b:2});
window.enyo.dispatch({type:"customGlobalEvent", data:"something to pass"});
},
customGlobalEventHandler:function(sender, e) {
enyo.log("also caught customGlobalEvent");
}
}
enyo.kind(_EventSender);
enyo.kind(_Example);