Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

A few questions on function expressions and Roll20 events...

Hi all, still fairly new to javascript and the Roll20 API environment as well... though I do have years of programming experience. I have a couple of questions that I can't seem to find answers to no matter how hard I try looking on the web at multiple resources, so since I see them used pretty commonly in the Roll20APIScript GitHub repository, I'm hoping someone can point me in the right direction. First, I am not understanding the following function expression syntax which I see used a lot: var <varName> = <varName> || (function () {     <function code here> ... }()); What exactly is going on here? Is this unique to Roll20 API? If not (or even if so), can anyone point me to a good resource that might explain this to me? Also, I guess another concept that I don't quite understand, is that while I know the closing syntax at the end of the function expression shown here indicates that it 'self invokes', what is the purpose of that? Why would you want it to run before an explicit call or an event trigger? Finally, is it just my imagination, or is the Roll20 API documentation on EVENTS sorely lacking in scope and depth? Has anyone compiled a more complete reference that isn't listed on the standard Roll20 Help Search results? Thanks much for any help! Lou-T
1602617134
Andreas J.
Forum Champion
Sheet Author
Translator
Lou-T said: Finally, is it just my imagination, or is the Roll20 API documentation on EVENTS sorely lacking in scope and depth? Has anyone compiled a more complete reference that isn't listed on the standard Roll20 Help Search results? Maybe? Did you look at both the Help Center for API documentation , as well as the Community/Help Wiki , in case some things are better detailed by the community? With API, the Help Center seems to have better(Roll20-provided) documentation, while anything related to Character Sheet Creation is vastly better documented/updated by the community on the Community Wiki.
1602624452
GiGs
Pro
Sheet Author
API Scripter
ᐰndreas J. said: Maybe? Did you look at both the Help Center for API documentation , as well as the Community/Help Wiki , in case some things are better detailed by the community? With API, the Help Center seems to have better(Roll20-provided) documentation, while anything related to Character Sheet Creation is vastly better documented/updated by the community on the Community Wiki. Is the Help Center better? All the pages I've looked at are exactly  the same as the wiki. I havent seen any improved documentation there at all, and the navigation system is worse than the wiki. In my estimation, It is just using different styling, so it looks fancier. But all the content I've looked at is directly copied from the wiki. (Not saying they are plagiarising - they wrote the initial pages on the wiki too. Just saying its not better .)
1602624998
GiGs
Pro
Sheet Author
API Scripter
Lou-T said: First, I am not understanding the following function expression syntax which I see used a lot: var &lt;varName&gt; = &lt;varName&gt; || (function () { &nbsp;&nbsp;&nbsp; &lt;function code here&gt; ... }()); What exactly is going on here? Is this unique to Roll20 API? If not (or even if so), can anyone point me to a good resource that might explain this to me? Also, I guess another concept that I don't quite understand, is that while I know the closing syntax at the end of the function expression shown here indicates that it 'self invokes', what is the purpose of that? Why would you want it to run before an explicit call or an event trigger? This is the Revealing Module Pattern, which is illustrated on the wiki here: <a href="https://wiki.roll20.net/API:Cookbook#Revealing_Module_Pattern" rel="nofollow">https://wiki.roll20.net/API:Cookbook#Revealing_Module_Pattern</a> &nbsp;and described here:&nbsp; <a href="https://www.oreilly.com/library/view/learning-javascript-design/9781449334840/ch09s03.html" rel="nofollow">https://www.oreilly.com/library/view/learning-javascript-design/9781449334840/ch09s03.html</a> &nbsp;(among many other places). It's not roll20-specific, its a javascript design pattern, made to solve a problem that is useful on roll20. In roll20, you set up your individual scripts in the API page. But when a campaign is loaded, roll20 compiles them, and starts by basically just combining them into a long text file - with every script one after the other. That means if any scripts use the same variable names or function names as other scripts, there can be problems.&nbsp; This design pattern solves that problem by putting each script in its own namespace, and effectively hiding its functions and variables from other scripts. So you dont get name collisions, and your scripts dont break other scripts. The "immediately invoking" part is a necessity - the script is run immediately when roll20 compiles the API sandbox, and that sets up any events in the script to be ready for action. In roll20, the scripts are event driven - they respond to events like chat messages or token changes. So you need the scripts to be set up to catch those events as they happen.
1602626544
Andreas J.
Forum Champion
Sheet Author
Translator
GiGs said: Is the Help Center better? All the pages I've looked at are exactly &nbsp;the same as the wiki. I havent seen any improved documentation there at all, and the navigation system is worse than the wiki. I was about to say <a href="https://wiki.roll20.net/API:Objects#Player" rel="nofollow">https://wiki.roll20.net/API:Objects#Player</a> vs <a href="https://roll20.zendesk.com/hc/en-us/articles/360037772793-API-Objects#API:Objects-Player" rel="nofollow">https://roll20.zendesk.com/hc/en-us/articles/360037772793-API-Objects#API:Objects-Player</a> , but it seems they probably have the same info. I recently tried to search the wiki for mentions of "d20userid" after having seen it in a script, but didn't find it, and then someone posted a link to the Help Center that had it. In my estimation, It is just using different styling, so it looks fancier. But all the content I've looked at is directly copied from the wiki. (Not saying they are plagiarising - they wrote the initial pages on the wiki too. Just saying its not better .) Yeah, I prefer the wiki too, but also acknowledge the Help Center documentation is in some cases better (mostly when new pages are created that never existed on the wiki), even if this time it didn't seem to be so. With API documentation, there is very little changes on the wiki, while character sheet/other macro documentation is constantly updated on the wiki. So the API stuff on the Help Center isn't really falling behind due to community improvement, but have a chance of mentioning new stuff Roll20 introduces related to UDL, for example.
Thank you both. I have looked at many, but not all of the references you site. And your explanation GiGs definitely helps me to understand what is going on there. I had browsed over the Revealing Module Pattern before, but I hadn't really seen it used in many of the examples I had been looking at online while trying to learn the basics and syntax. Looks like I'll need to look at it more closely and get a firm understanding of it. I wrote what I thought would be an easy little token health / bloodied script that might take a few hours, ended up taking a few days... but I'm learning, lol. And that was really the purpose anyway, so not really complaining. It works now, though it's pretty simplistic, and there's already some great API scripts out there for doing stuff like that.
1602632473
The Aaron
Roll20 Production Team
API Scripter
I'm on my phone and traveling so I have to be brief, but here are a few minor points of clarity: The Roll20 API "concatenates" all scripts, not compiles them. Javascript is interpreted, not compiled, but the salient point is that all API scripts share a single global scope. &nbsp; The concatenated API scripts are executed only once, all further interaction occurs due to events the scripts have registered for in the single execution. At that point, scripts get re-entered in those registered event handlers.&nbsp; The revealing module pattern, coined by Douglas Crockford (author of Javascript: the good parts), is a way of creating a private scope where you can encapsulate your private implementation details. It is made up of an Immediately Invoked Function Expeession (IIFE, "iffy") which (usually) returns an interface object. Javascript has a concept call a "closure", which is the scope of a function's execution, i.e. each call to the function creates a new closure. The closure persists as long as any reference to it remains, and it is only accessible to things created within that specific closure. An IIFE that returns a collection of functions in an object thus create a private scope for that object's functions. The practical up shot being that this is how you create a private implementation with a public interface as of Javascript ES2017.&nbsp;
1602633179
The Aaron
Roll20 Production Team
API Scripter
Also I want to mention, there isn't that much to the events at all. There are 5 types of events: ready -- called once when the API is fully started up. No parameters. You almost always want to wait and register your event handlers when this fires. This only fires once.&nbsp; chat:message &nbsp;-- what happens when you put anything in chat. Only has one parameter, a message object with some properties about the message.&nbsp; add: &lt;type&gt; -- creation event for any Roll20 object, one parameter, the object created (possibly not fully formed in the case of graphics).&nbsp; change:&lt;type&gt; [:&lt;property&gt; ] &nbsp;-- when an existing object is changed. You register to an object type, and possibly a specific property. Callback has a Roll20 object gfkrvtge currency statement, and a javascript object of the prior state.&nbsp; destroy:&lt;type&gt; &nbsp;-- called when an object is removed. One parameter of the destroyed object.&nbsp; Note that changes by the API mostly don't trigger events.&nbsp;
Thanks Aaron, very helpful and answers more questions that I had. Most of my programming experience comes from very heavily event driven code, but the much more simplified way that javascript deals with events and object function interfaces make more sense the more I understand it. One of the few questions I'm still not sure about, is some of Roll20 API event documentation seems to show that certain event will trigger others... like I understand that a change:&lt;type&gt;[:&lt;property&gt;] &nbsp; event will follow with a <a href="change: ">change: &lt;type &gt;&nbsp; event, but still unclear if something like&nbsp; an add:tpye wil be followed by a change:type etc. But I'm getting the big picture I believe.
1602659707
The Aaron
Roll20 Production Team
API Scripter
In general, an add event is all you will get, except for graphics, where you'll get an add followed by 1-3 change events as various subsystems apply their changes. These are things like global defaults and default token for character sheet, etc.&nbsp; Javascript has the capability for some really complicated event systems, but Roll20's event system is very, very basic.&nbsp; With the specific property events, such as "change:graphic:top", you'll get the specific events, if you've registered a handler for them, then you'll get the general "change:graphic" event.&nbsp;
Quick question, do the Javascripts in Roll20 support Export / Import module structure? or JQuery, or such?
1602723478
Andreas J.
Forum Champion
Sheet Author
Translator
no JQuery, and you can't import or use other libraries than Underscore.
Got it, thanks Ǻndreas!
1602766233
Andreas J.
Forum Champion
Sheet Author
Translator
Lou-T said: Got it, thanks Ǻndreas! Lol maybe I should switch back to using an "A", instead of the Stargate character. Anyway, general info on Sheet workers can be found here: <a href="https://wiki.roll20.net/Sheet_Worker_Scripts#JavaScript_Restrictions" rel="nofollow">https://wiki.roll20.net/Sheet_Worker_Scripts#JavaScript_Restrictions</a>
Not precisely the same Subject, but since I have your attention, I've been parsing scripts written by The Aaron to help with how to write well structured Roll20 API scripts. I got stuck on this line of code (from your short script AISelection.js ) for over an hour: const getList = (id) =&gt; [...(state.APISelection.lists[id] || [])]; For two reasons. 1. I had no idea what was happening with the '...' syntax. I had not ever seen it before. I was going to ask what the heck this was, but finally found an explanation. &nbsp;&nbsp;&nbsp; <a href="https://www.quora.com/What-does-the-mean-in-Javascript" rel="nofollow">https://www.quora.com/What-does-the-mean-in-Javascript</a> Definitely NOT well documented functionality... 2. And this part I have NOT figured out yet, and would like someone to explain it to me, or send me a link, although I think I get what it's doing from the context. What does the ' || [])' at the end do? Is it saying that if the state.APISelection.lists[id] doesn't exist, it evaluates to false, and so moves on to the OR '||' statement to assign the return value as an empty array []? In other words, is this whole line of code: const getList = (id) =&gt; [...(state.APISelection.lists[id] || [])]; equivalent to: const getList = (id) =&gt; (state.APISelection.lists[id] === undefinded) ? [] : state.APISelection.lists[id] ; Or am I even close?
1602804884
Andreas J.
Forum Champion
Sheet Author
Translator
Aaron is our greatest scriptomancer, and I have seldom any idea idea how his arcane rituals works, you'll have to wait for him to answer I suspect. I remember having used the spread operator after having seen that at one point, but had already forgotten the name for it. Thanks for the reminder. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax" rel="nofollow">https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax</a>
1602805443
The Aaron
Roll20 Production Team
API Scripter
The ... in Javascript is one of two things: The Rest operator -- A means of collecting all the remaining parameters to a function into a single array variable.&nbsp; It's very similar to the way variadic parameters in C/C++ work. so this: const labelAndContents = (label, ...contents) =&gt; `&lt;div&gt;&lt;h3&gt;${label}&lt;/h3&gt;&lt;div&gt;${contents.join(', ')}&lt;/div&gt;&lt;/div&gt;`; could be called with a variable number of additional parameters which would all end up as part of the array contents: let theDice = labelAndContents("Dice","d4","d6","d8","d10","d12","d20","d42"); let short = labelAndContents("Thing","Just this."); or the Spread operator -- A means of spreading the contents of an array or object within the context of creating a new array or object: let a = [1,2,3]; let b = [4,5,6]; let c = [...a, ...b]; // the same as saying [1,2,3,4,5,6] I'm using it as the Spread operator above. For the second question, you're correct.&nbsp; This exploits a feature of Javascript that everything has a "truthy" value, and that boolean operations do not return explicitly 'true' and 'false' values, but rather the value that was evaluated as 'true' or 'false'.&nbsp; For example, this: let value = undefined || false || 0 || "" || {foo: 3} || 1 || true; Will result in value being assigned {foo: 3} because it is the first value that is "true".&nbsp; It's common in Javascript to initialize things by trailing an || &lt;default value&gt;: let numDice = params[2] || 3; In the case that params[2] has a defined value that is "true", it numDice will get that value, otherwise it will get 3. I'll post some good links a bit later, dinner calls!
1602807750
The Aaron
Roll20 Production Team
API Scripter
Here's a few threads where we talked a bunch of writing API Scripts: <a href="https://app.roll20.net/forum/post/6605115/namespaces-novice-seeks-help-exploring-the-revealing-module-pattern" rel="nofollow">https://app.roll20.net/forum/post/6605115/namespaces-novice-seeks-help-exploring-the-revealing-module-pattern</a> <a href="https://app.roll20.net/forum/post/6584105/creating-an-object-that-holds-specific-character-dot-id-and-character-name/?pagenum=1" rel="nofollow">https://app.roll20.net/forum/post/6584105/creating-an-object-that-holds-specific-character-dot-id-and-character-name/?pagenum=1</a> <a href="https://app.roll20.net/forum/post/6237754/slug%7D" rel="nofollow">https://app.roll20.net/forum/post/6237754/slug%7D</a>
Thanks again, both of you! While I'm learning this for fun right now to write my own Roll20 API scripts, I can see this knowledge being turned into an additional marketable skill ;)
1602813355
The Aaron
Roll20 Production Team
API Scripter
Definitely!&nbsp; When I started doing API scripts, my knowledge of Javascript was "Javascript, isn't that what you want validate input boxes with?" After working on API scripts for a while, one of the VPs at the company I worked for asked me to write a Browser Extension to compete with another one that was popular at the time, which I was able to finish in 18 clock hours thanks to all the Roll20 API experience. =D