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

Change Output based on Dropdowns

I'm aware Roll20 is limited in the javascript it uses, so I wanted to know if its possible to change text based on the combination of two dropdowns in a Roll20 sheet. Based on what you chose for either dropdown, the output changes.  I have been trying myself, but I'm unaware if it's a restriction, or my inexperience at javascript. 
1711233174
vÍnce
Pro
Sheet Author
Hi FurryOwO, I would say it's definitely possible. ;-) What "text" do you want to change?  Can you share some minimal, relevant code (HTML, js) to help others better find a solution?
1711233563
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
Hi FurryOwO! Is this for  developing    a script or for developing a character sheet? There might be better subforums to post in to get a useful answer.
vÍnce said: Hi FurryOwO, I would say it's definitely possible. ;-) What "text" do you want to change?  Can you share some minimal, relevant code (HTML, js) to help others better find a solution? I wish to have a sort of "recipe" list. Two ingredients combine to show what it can create, and it's effects and rolls in a character sheet. I have an attribute named textoutput I want to change the outcome to.  The ingredients/outputs are just placeholders.  Here is the Javascript: <script> function generateRecipe() { getAttrs(["ingredient1", "ingredient2", "textoutput"], function(values) { var ingredient1Value = values.ingredient1; var ingredient2Value = values.ingredient2; var recipeOutput = ""; if (ingredient1Value === "apple" && ingredient2Value === "peach") { recipeOutput = "Apple Peach Thingr"; } else if (ingredient1Value === "peach" && ingredient2Value === "apple") { recipeOutput = "Apple Peach Thing"; } else { recipeOutput = "No recipe available for selected ingredients"; } if (recipeOutput !== values.textoutput) { setAttrs({ "textoutput": recipeOutput }); } }); } </script> Here is my HTML: <label for="ingredient1">Select Ingredient 1:</label> <select id="ingredient1"> <option value="apple">Apple</option> <option value="banana">Banana</option> <option value="peach">Peach</option> </select> <label for="ingredient2">Select Ingredient 2:</label> <select id="ingredient2"> <option value="apple">Apple</option> <option value="banana">Banana</option> <option value="peach">Peach</option> </select> <button onclick="generateRecipe()">Generate Combination</button> <input type="text" name="textoutput" value="">
keithcurtis said: Hi FurryOwO! Is this for  developing    a script or for developing a character sheet? There might be better subforums to post in to get a useful answer. Apologies, this is for a character sheet. I was going through the subforums for a good place to post, I must have missed some. 
1711277915

Edited 1711306166
GiGs
Pro
Sheet Author
API Scripter
You missed the character sheet forum, which is ideal for questions like this. Your javascript is not written for roll20, and will not work here. You also have an onclick in your html, which won't work either. This code: <button onclick="generateRecipe()">Generate Combination</button> should be <button type="action" name="act_recipe">Generate Combination</button> I chose the name recipe (what follows act_) rather than generate_recipe, because there are places in roll20 whether an underscore there will break the code. Since you can't use onclick and a standard function call, you sheet worker looks like this: on('clicked:recipe', function() { getAttrs(["ingredient1", "ingredient2", "textoutput"], function(values) { var ingredient1Value = values.ingredient1; var ingredient2Value = values.ingredient2; var recipeOutput = ""; if ( (ingredient1Value === "apple" && ingredient2Value === "peach") || (ingredient1Value === "peach" && ingredient2Value === "apple") ){ recipeOutput = "Apple Peach Thing"; } else { recipeOutput = "No recipe available for selected ingredients"; } setAttrs({ "textoutput": recipeOutput }); }); });
1711278081

Edited 1711280595
GiGs
Pro
Sheet Author
API Scripter
You can also change the sheet worker to run when the attributes ingredient1 or ingredient2 change, and dispense with the need for the button. You'd only have to change the first line of the sheet worker from on('clicked:recipe', function() { to on('change:ingredient1 change:ingredient2', function() {
1711278697

Edited 1711280653
GiGs
Pro
Sheet Author
API Scripter
Two things I forgot (or overlooked, really) in the earlier code: Your text output should look like this: < input type= "text" name= "attr_textoutput" value= "" > (notice attr_ needs to be before each attribute name) you also need to have each select inked to an attribute name, like this: < select name= "attr_ingredient1" >   < option value= "apple" > Apple </ option >   < option value= "banana" > Banana </ option >   < option value= "peach" > Peach </ option > </ select > Separately, in your original dropdowns, I wouldn't do the HTML this way - <label for="ingredient1">Select Ingredient 1:</label> <select id="ingredient1" name="attr_ingredient1"> <option value="apple">Apple</option> <option value="banana">Banana</option> <option value="peach">Peach</option> </select> <label for="ingredient2">Select Ingredient 2:</label> <select id="ingredient2" name="attr_ingredient2"> <option value="apple">Apple</option> <option value="banana">Banana</option> <option value="peach">Peach</option> </select> The selects will work, but clicking the label will have no effect. I think you'll have an effect closer to what you expect by putting the select inside the label, like so: <label for="ingredient1">Select Ingredient 1: <select name="attr_ingredient1"> <option value="apple">Apple</option> <option value="banana">Banana</option> <option value="peach">Peach</option> </select> </label> But I would write closer to the first, replacing both for= and id= with class=, and use CSS to arrange the layout I want.
1711278875

Edited 1711279222
GiGs
Pro
Sheet Author
API Scripter
Another thing I overlooked: you start the JS like this: <script> That will not work on Roll20. Replace that with <script type="text/worker"> and you are ready to go.
1711279196

Edited 1711285837
GiGs
Pro
Sheet Author
API Scripter
To understand how to write code for roll20 check out the wiki:&nbsp; <a href="https://wiki.roll20.net/Building_Character_Sheets" rel="nofollow">https://wiki.roll20.net/Building_Character_Sheets</a> or my site (which is designed specifically to help new sheet authors): <a href="https://cybersphere.me/roll20-sheet-author-master-list/" rel="nofollow">https://cybersphere.me/roll20-sheet-author-master-list/</a> The code used is HTML, CSS, and JavaScript, but it has just enough peculiarities that code suggested by sites outside of these two will usually not work and will drive you crazy trying to figure out why it doesn't work. Use those two sites (and this forum).
1711280400

Edited 1711289344
GiGs
Pro
Sheet Author
API Scripter
Here's an expansion of your code, based on the direction I think you are going. First, the selects: &lt; select name= "attr_ingredient1" &gt; &nbsp; &lt; option value= "" selected&gt; (Click One) &lt;/ option &gt; &nbsp; &lt; option &gt; Apple &lt;/ option &gt; &nbsp; &lt; option &gt; Banana &lt;/ option &gt; &nbsp; &lt; option &gt; Peach &lt;/ option &gt; &lt;/ select &gt; &lt; select name= "attr_ingredient2" &gt; &nbsp; &lt; option value= "" selected &gt; (Click One) &lt;/ option &gt; &nbsp; &lt; option &gt; Apple &lt;/ option &gt; &nbsp; &lt; option &gt; Banana &lt;/ option &gt; &nbsp; &lt; option &gt; Peach &lt;/ option &gt; &lt;/ select &gt; This is just the selects - you'll need to include your own labels. This takes into account two things: In Roll20, a select has a value before you click it (undefined), even though it looks like the first item in the list is selected (it isn't). That's why a dummy first item is added here. In a select, you only need a value if the option value is different from the text you included. Here we are using the text as written (Apply, etc), so we don't need a separate value. Then in the HTML, we add an array of valid ingredient names, and check the selected options against those. Ifyou change the ingredients, you'll need to expand this array but the required format should be obvious. on ( 'change:ingredient1 change:ingredient2' , function () { &nbsp; &nbsp; getAttrs ([ "ingredient1" , "ingredient2" ], function ( values ) { &nbsp; &nbsp; &nbsp; &nbsp; var ingredient1Value = values . ingredient1 ; &nbsp; &nbsp; &nbsp; &nbsp; var ingredient2Value = values . ingredient2 ; &nbsp; &nbsp; &nbsp; &nbsp; var recipeOutput = "" ; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var ingredients = [ "Apple" , "Banana" , "Peach" ]; &nbsp; &nbsp; &nbsp; &nbsp; if ( ingredients . includes ( ingredient1Value ) &amp;&amp; ingredients . includes ( ingredient2Value )) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; recipeOutput = ` ${ ingredient1Value } ${ ingredient2Value } Thing` ; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; recipeOutput = "No recipe available for selected ingredients" ; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; setAttrs ({ "textoutput" : recipeOutput }); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); });
Thank you very much for the in depth break down/critique, it really does help someone like me who's still learning! I apologize for missing the custom sheet forum initially, but I still appreciate the response given. I wasn't aware of your site which seems like a really great resource for me to read up on. Thanks a bunch! GiGs said: Here's an expansion of your code, based on the direction I think you are going. First, the selects: &lt; select name= "attr_ingredient1" &gt; &nbsp; &lt; option value= "" selected&gt; (Click One) &lt;/ option &gt; &nbsp; &lt; option &gt; Apple &lt;/ option &gt; &nbsp; &lt; option &gt; Banana &lt;/ option &gt; &nbsp; &lt; option &gt; Peach &lt;/ option &gt; &lt;/ select &gt; &lt; select name= "attr_ingredient2" &gt; &nbsp; &lt; option value= "" selected &gt; (Click One) &lt;/ option &gt; &nbsp; &lt; option &gt; Apple &lt;/ option &gt; &nbsp; &lt; option &gt; Banana &lt;/ option &gt; &nbsp; &lt; option &gt; Peach &lt;/ option &gt; &lt;/ select &gt; This is just the selects - you'll need to include your own labels. This takes into account two things: In Roll20, a select has a value before you click it (undefined), even though it looks like the first item in the list is selected (it isn't). That's why a dummy first item is added here. In a select, you only need a value if the option value is different from the text you included. Here we are using the text as written (Apply, etc), so we don't need a separate value. Then in the HTML, we add an array of valid ingredient names, and check the selected options against those. Ifyou change the ingredients, you'll need to expand this array but the required format should be obvious. on ( 'change:ingredient1 change:ingredient2' , function () { &nbsp; &nbsp; getAttrs ([ "ingredient1" , "ingredient2" ], function ( values ) { &nbsp; &nbsp; &nbsp; &nbsp; var ingredient1Value = values . ingredient1 ; &nbsp; &nbsp; &nbsp; &nbsp; var ingredient2Value = values . ingredient2 ; &nbsp; &nbsp; &nbsp; &nbsp; var recipeOutput = "" ; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var ingredients = [ "Apple" , "Banana" , "Peach" ]; &nbsp; &nbsp; &nbsp; &nbsp; if ( ingredients . includes ( ingredient1Value ) &amp;&amp; ingredients . includes ( ingredient2Value )) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; recipeOutput = ` ${ ingredient1Value } ${ ingredient2Value } Thing` ; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; recipeOutput = "No recipe available for selected ingredients" ; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; setAttrs ({ "textoutput" : recipeOutput }); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); });