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

Set String with Script

1577619748
Axel
Pro
Sheet Author
I need to set the string of a text attribute based on the value of a number attribute, but I don't think I'm getting the script right. What needs to change to get this to work?     on("sheet:opened change:number", function() {         getAttrs(["number", "text"], function(values) {             if(values.number == 1) {                 setAttrs({                     text: "string1"                 })             }             else if(values.number == 2) {                 setAttrs({                     text: "string2"                 })             }         });     }); I need the string to be displayed in a span. Do I need to use a hidden attribute for the script? <span name="attr_text"/>
I am no expert, but I think you should have closing semi-colons on lines 7, 11, and 12, closing out the setAttrs and the if loop.
1577640123
Axel
Pro
Sheet Author
Thanks, that seems like a good point, but it didn't make it work unfortunately. It does work if the string is a number through, which is weird. maybe I need to change "function(values)" for it to work?
1577656423
GiGs
Pro
Sheet Author
API Scripter
What do you mean by  "It does work if the string is a number through, " Which string? There's a couple of minor issues with your code, but none that would stop it working. It should work, so I'd be looking at your html. What is the code for the html tags for number and text?
1577664197
Axel
Pro
Sheet Author
Never mind, I've chosen a different solution for the effect I want. Thanks for looking at my code though. For the sake of curiosity, what minor issues were there in my script? I'm always willing to learn.
1577671525

Edited 1577734293
GiGs
Pro
Sheet Author
API Scripter
What a can of worms you've opened. I love answering questions like this. Rabulias mentioned the closing semicolons. This line getAttrs(["number", "text"], function(values) { in your script you get the number from the sheet, but you never read the text value from the sheet. You set it, overwriting whats already there, so you dont need to get it in this line. So it should be getAttrs(["number"], function(values) { There are a LOT of optimisations you could do with the if statement. I'll show them one at a time. Firstly when you access the values.number , you should make sure it is the data type you want - string, number, etc. It looks like you want a number here, so you should do one of these: let mynumber = parseInt(values.number) || 0; let mynumber = parseFloat(values.number) || 0; let mynumber = +values.number || 0; let mynumber = Number(values.number) || 0; All attributes in a character sheet are technically strings (text), so you should coerce them into numbers. The above are four (and not the only three) ways of coercing a string to a number. Each has its own little quirks, but usually its a matter of personal preference. The first does have a very specific difference from the others - it ensures the number is always an integer (dropping anything after the decimal point). Sometimes thats important, and sometimes you definitely dont want that. The other three convert it into a floating point number, if the number has decimals. The ending bit ||0 says "OR 0" - this means if the attempt to convert it into number fails, you get a 0. This is a great way to set default values, and you can change the 0 part to whatever number you want to set as default. Now, it's really good practice to get in the habit of only having exactly one setAttrs statement in each worker. It's not always essential, but it's a good habit to learn, because multiple setAttrrs are slow to process. To do that, create a variable first, then do the set at the end, like this:             let mytext = '';             if(mynumber === 1) {                 mytext = "string1";             }             else if(mynumber === 2) {                 mytext = "string2";             } else { // what to do if the value doesnt match 1 or 2? }             setAttrs({ text: mytext }); Notice also in the if statement is used triple equals. Javascript practice is to avoid double ==, because it can allow subtle errors that are hard to identify. When you know the data type (in this case we have coerced it to a number, so we know it is always a number), you can use triple equals, which means "if the values are equal, and also of the same data type). Notice my commented section: you need to know what to do if the value doesnt match the values you test for. Sometimes its impossible to get an invalid value (like a checkbox can only have two values, or a select - if you set a default value with selected - can only have the values listed). But when the input is, say, a textbox, you need to handle all eventualities.  You could create a list of valid values, and check the input matches, and only proceed if it does, For example const validvalues = [1, 2]; if(!validvalues.includes(mynumber)) return; The ! there means NOT, so if validvalues doesnt include the mynumber variable, end the worker. you can streamline this as  if(![1, 2].includes(mynumber)) return; So right now the code looks like this: on("sheet:opened change:number", function() {         getAttrs(["number"], function(values) {             let mynumber = parseInt(values.number) || 0;             if(![1, 2].includes(mynumber)) return;                          let mytext = '';             if(mynumber === 1) {                 mytext = "string1";             }             else if(mynumber === 2) {                 mytext = "string2";             } setAttrs({              text: mytext                       });         });     }); One comment: note that the mynumber has a default value of 0. So if attempting to convert the value to a number fails, it becomes 0. Then the following line checks its 1 or 2. So if you had an invalid value, it wont match and the script will end. You might want to handle that error in other ways (like giving feedback through setting a value that lets the user know its invalid, but we are ignoring that here). Finally, since the text value includes  the number value (string1, string2 each include the number 1 or 2), you can dispense with the if statement completely. Thanks to the includes  test, we know the number must be a valid value, so we can do this: const mytext = 'string' + mynumber; This will give you a value of either string1 or string2, exactly what you want. Thus the sheet worker would be: on("sheet:opened change:number", function() {         getAttrs(["number"], function(values) {             let mynumber = parseInt(values.number) || 0;             if(![1, 2].includes(mynumber)) return;                          const mytext = 'string' + mynumber; setAttrs({              text: mytext                       });         });     }); You could even set the value within the setAttrs itself, like setAttrs({              text: 'string' + mynumber             }); But generally speaking i think you are better of setting it in a variable first, because if the code has a bug in it, it makes things much easier to find them when you can access the value through a variable. Hope this is informative!
1577729084
Axel
Pro
Sheet Author
This is a can of worms I'd be glad to open again! I'm sure I'll need to use scripts again at some point, so learning more about how is not only a good idea, but also sounds like fun. Thanks for the lesson!