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 .
×
May your rolls be chill this holiday season!
Create a free account

If Else Clause Not Working

Hello! Revised version of my earlier post. I am a total beginner to coding. I am trying to use Sheet Worker to change an attribute if a checkbox is checked. When the Frenzy checkbox or the health attribute changes I want the sheet to change the injury attribute to zero but ONLY if the Frenzy checkbox is checked. If the checkbox is not checked I want the injury attribute to be changd to the arbitrary number 5. The way I have it coded does not work and it confuses me: I had this written with one "=" in the if condition and the sheet executes the setAttr injury (0) but ignores the else, I thought this was because there need to be 2 "==" but when I change it the entire script stops working. Any ideas what I am doing wrong?   < tr >   < h3 > Frenzy </ h3 >   < td ></ td >   < div >       < th >< input type = "checkbox" class = "frenzybox" name = "attr_frenzy" value = "Frenzied" checked >< span ></ span ></ th >     </ div >   </ tr > on("change:health change:frenzy", function() {     getAttrs(['health'], function(values) {          if(frenzy = Frenzied) {             setAttrs({injury:(0)});         } else {             setAttrs({injury:(5)})         }         })
1639379012

Edited 1639379921
GiGs
Pro
Sheet Author
API Scripter
You have three problems here that I see, all on the if line: The first problem is, what is frenzy ? I assume it is the attribute named frenzy. In this case, it is contained in the values data object you refer to on the line above. So it should be if(values.frenzy = Frenzied) { Basically a sheet worker has no access to the character sheet. It does not know what the sheet contains. So to be able to use attribute values, you use the getAttrs line: first you pass attribute names in the first part (enclosed in the [ ]), that is a list of attribute names that the code grabs from the sheet, and puts them inside the values object you declare after the word function. So in your code above, values contains the attribute health , and the health value can be retrieved by using values.health . That points to another problem, your code uses the frenzy attribute, so you need getAttrs to grab the frenzy attribute, like so: getAttrs(['health', 'frenzy'], function(values) { Note: you dont actually need the health attribute in the code provided, but I've left it there in case you intend to expand this code. The next problem is that javascript uses the = operator in a funny way. Whenever you use =, the value is assigned. = always means "set this value to". So in your if line, frenzy is being set to Frenzied, so the if side is always true, and the else never runs. You need to use == or === in this case (always use ===). The double or triple equalities are comparison operators, they check if something matches without actually setting the value. So that should be if(frenzy === Frenzied) { The final problem is if you use a name, without quotes, like Frenzied, it is a variable name. I'm guessing here you are testing if frenzy has the text 'Frenzied'. For that you need to put it in quotes (making it a string) like so: if(frenzy === 'Frenzied') { Oh, there's another issue. All sheet workers need to be contained in a script block. That looks like this: <script text="worker"> </script> That block should be put either at the beginning or end of your entire html page, and all of the sheet workers you create go inside there. So putting you fixed sheet worker in there it would look like So fixing that code, it should be: <script text="worker">     on("change:health change:frenzy", function() {         getAttrs(['health', 'frenzy'], function(values) {              if(frenzy === 'Frenzied') {                 setAttrs({injury:(0)});             } else {                 setAttrs({injury:(5)})             }         });     }); </script> While doing this I noticed that you didnt have an closing }); for the getAttrs - you need to close both the on and getAttrs brackets you opened.
1639379427

Edited 1639474952
GiGs
Pro
Sheet Author
API Scripter
Here's a couple more suggestions. It's a good idea to only include one setAttrs in each worker. In this code it doesnt matter much since only one will ever run, but when you build more complex workers, you might have multiple setAttrs scattered about within it. So its a good idea to know how to handle that situation. You need to create a variable, assign the attributes and their values to it, and give that attribute to setAttrs. You do that like this: <script text="worker">     on("change:health change:frenzy", function() {         getAttrs(['health', 'frenzy'], function(values) {             const output = {};              if(frenzy === 'Frenzied') {                 output.injury = 0;             } else {                 output.injury = 5;             }             setAttrs(output);         });     }); </script> In this code i have initialised (created) a variable named output. Because I used the ={} code, it tells javascript that this is a special kind of variable, an object variable. These variables can hold many values. I could later use the line:     output.green = "yes"; and that output variable would contain both the green attribute and the injury attribute together. Then when setAttrs is called, it sets both those attributes at the same time. Since you only have one attribute in this worker, it;s not strictly necessary to use an approach like this - the worker in the previous reply is fine. But it's handy to know the technique and get familiar with it, for those workers where you are setting multiple attributes.
1639379721
GiGs
Pro
Sheet Author
API Scripter
Finally, this code looks fine, but the value doesnt need to be that specific: <input type="checkbox" class="frenzybox" name="attr_frenzy" value="Frenzied" checked > Since this is setting something to on or off, a traditional programming method is to set value to 1 or 0. That works great for toggles. Checkboxes automatically have a value of 0 when unchecked, so you would just need to set value to 1. That would look like: <input type="checkbox" class="frenzybox" name="attr_frenzy" value="1" checked > You'd need to update the worker to account for that. like so: <script text="worker">     on("change:health change:frenzy", function() {         getAttrs(['health', 'frenzy'], function(values) {             const output = {};              if(frenzy === '1') {                 output.injury = 0;             } else {                 output.injury = 5;             }             setAttrs(output);         });     }); </script> Note we are still testing for '1' and not 1 here, because roll20 stores all values as strings. If you want to use that value in arithmetic, you would need to convert it to a number first, but that isnt necessary here. Hope this all helps.
Thank you so much, GiGs, that was incredibly helpful! Now it works and I learned some other things I did not know!
1639389742
GiGs
Pro
Sheet Author
API Scripter
I'm happy to hear it :)
1639416386
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Great write up as always GiGs. My only addition is that a general coding best practice is for script blocks to always come after your html itself. This is because the html is parsed top to bottom, and putting the script block first requires that all it's JS be parsed and initialized before your html gets rendered. This won't often be an issue with sheetworkers because of their async nature, but putting the script block at the bottom eliminates one possible source of startup lag on the sheet.
1639431915
GiGs
Pro
Sheet Author
API Scripter
Thanks Scott. That sounds very reasonable.
Thank you for the tip, Scott! In my full page the script block is all the way at the bottom, good to know why it is that way, I just did it because I saw other people did it.