C and assembly! Now you're speaking my language. =D You are almost entirely correct about the code above, what you're missing is that RegisterEventHandlers() is only executed once to setup the events. The function HandleInput() is what gets invoked for each chat message. In javascript, you don't (previous to ES6) have an explicit separation between public and private variables (objects/ functions /arrays/strings/etc). To get around this, you can create a things in a function (which has it's own scope) and return them out of that scope (causing the scope to persist, a closure). Things created in the inner function scope (the closure) have access to the other things in that scope. Here's a bit of pseudo code that might help: // create module object
var pubObj = (function(){
// setup private things
var privateFunc1 = function(){
/* do stuff */
},
privateFunc2 = function(){
/* do other stuff */
},
privateFunc3 = function(){
/* do stuff and call function in closure */
privateFunc2();
};
// return the object to assign to pubObj
return {
publicAliasFunc1: privateFunc1,
publicAliasFunc2: privateFunc3 //<-- The names don't matter, 2 and 3 here are intentional
};
}());
on('ready',function(){
pubObj.publicAliasFunc1(); pubObj.publicAliasFunc2();
}); pubObj gets assigned the object literal created at the return statement, which has 2 properties which happen to be functions. Those properties are assigned the function in the closure, bringing them out so they can be executed lower down in the on('ready',...) event. You can see that privateFunc3() calls privateFunc2() which is still inside the closure. It has access to that function because it was created in that scope. That should arm you with the tools to understand what's going on in my scripts. Definitely ask if you want more details! Simplified event handler examples (Same event, multiple handlings.): on('ready',function(){
log('ready fired.');
});
// -----------------ALTERNATIVE--------------------
var handleReady = function(){
log('ready fired.');
};
on('ready',handleReady);
// -----------------ALTERNATIVE--------------------
var readyObj = (function(){
var internalHandleReady = function(){
log('ready fired.');
};
return {
readyHandler: internalHandleReady
};
}());
// either:
on('ready',readyObj.readyHandler);
// or
on('ready',function(){
readyObj.readyHandler();
}); Here's one for chat messages: var chatObj = (function(){
var handleInput = function(msg){
log('Got msg: '+msg.content);
},
registerEventHandlers(){
on('chat:message',handleInput);
};
return {
RegisterEventHandlers: registerEventHandlers
};
}());
on('ready',function(){
chatObj.RegisterEventHandlers();
}); My having a registerEventHandlers() is largely a organizational convenience. I use the following template to create all my scripts, with a bash script that subs for the NAME part: // Github: <a href="https://github.com/shdwjk/Roll20API/blob/master/NAME/NAME.js" rel="nofollow">https://github.com/shdwjk/Roll20API/blob/master/NAME/NAME.js</a>
// By: The Aaron, Arcane Scriptomancer
// Contact: <a href="https://app.roll20.net/users/104025/the-aaron" rel="nofollow">https://app.roll20.net/users/104025/the-aaron</a>
var NAME = NAME || (function() {
'use strict';
var version = '0.1.0',
lastUpdate = 1427601167,
schemaVersion = 0.1,
checkInstall = function() {
log('-=> NAME v'+version+' <=- ['+(new Date(lastUpdate*1000))+']');
if( ! _.has(state,'NAME') || state.NAME.version !== schemaVersion) {
log(' > Updating Schema to v'+schemaVersion+' <');
state.NAME = {
version: schemaVersion
};
}
},
handleInput = function(msg) {
var args;
if (msg.type !== "api") {
return;
}
args = msg.content.split(/\s+/);
switch(args[0]) {
case '!NAME':
break;
}
},
registerEventHandlers = function() {
on('chat:message', handleInput);
};
return {
CheckInstall: checkInstall,
RegisterEventHandlers: registerEventHandlers
};
}());
on('ready',function() {
'use strict';
NAME.CheckInstall();
NAME.RegisterEventHandlers();
});
Let me know if you want more! =D