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
This post has been closed. You can still view previous posts, but you can't post any new replies.

[Sheet workers] Default values for repeating row inputs undefined when referring to them via rowid

1503389001

Edited 1503946816
Jakob
Sheet Author
API Scripter
I'm not entirely sure if this is a bug, but default values for inputs in repeating rows are not returned by getAttrs when referring to them by the id. Example code: <fieldset class="repeating_example">     <input name="attr_name" type="text"/>     <input name="attr_default_text" type="hidden" value="somedefault"/>     <input name="attr_check" style="display:none" type="checkbox" value="1"/>     <input name="attr_checked" style="display:none" type="checkbox" value="1" checked/> </fieldset> <script type="text/worker">     on('change:repeating_example:name', function () {         getSectionIDs('repeating_example', function (idArray)  {             let attrs = [                 ...idArray.map(id => `repeating_example_${id}_check`),                 ...idArray.map(id => `repeating_example_${id}_checked`),                 ...idArray.map(id => `repeating_example_${id}_default_text`)             ];             getAttrs(attrs, function (v) {                // logs undefined                console.log('Attribute values by id.');                idArray.forEach(id => console.log(v[`repeating_example_${id}_check`]));                idArray.forEach(id => console.log(v[`repeating_example_${id}_checked`]));                idArray.forEach(id => console.log(v[`repeating_example_${id}_default_text`]));             });         });     });     on('change:repeating_example:name', function () {        getAttrs(['repeating_example_default_text', 'repeating_example_check', 'repeating_example_checked'], function (v) {            // logs the right defaults            console.log('Attribute values from within row.');            console.log(v.repeating_example_check);            console.log(v.repeating_example_checked);            console.log(v.repeating_example_default_text);        });     }); </script> Namely, when you refer to an attribute via repeating_example_${id}_attrname (via getSectionIDs), undefined is returned instead of the default. When you are inside a repeating row event (second event in the example), so you can refer to it via repeating_example_attrname, the default works correctly.
1503410794

Edited 1503411109
chris b.
Pro
Sheet Author
API Scripter
wow , that explains a lot. I've seen this same behavior too, and even added code to my sheet that sets the defaults for attributes when they are undefined .(I've also found setting them to '' does not work, since they are still undefined the next time)
1503412467
Jakob
Sheet Author
API Scripter
chris b. said: wow , that explains a lot. I've seen this same behavior too, and even added code to my sheet that sets the defaults for attributes when they are undefined .(I've also found setting them to '' does not work, since they are still undefined the next time) I'm not 100% sure how accurate this is, but I've heard somewhere that in Roll20's database model, an empty attribute is somehow treated the same as undefined. That's the reason why setting an attribute to "" resets it to the default in the first place.
1503945298
Stephen Koontz
Forum Champion
Marketplace Creator
Sheet Author
API Scripter
Compendium Curator
See my response  here .
1503946764

Edited 1503948920
Jakob
Sheet Author
API Scripter
Again, thanks for looking at my issues! Unfortunately, replacing all the arguments to getAttrs/on/getSectionIDs by normal functions doesn't change the result in this case. I've updated the OP with the non-lambda version, just to be sure.
1503949669
Stephen Koontz
Forum Champion
Marketplace Creator
Sheet Author
API Scripter
Compendium Curator
I'm getting exactly the results I'd expect from a non-lambda version.  <fieldset> <input name="attr_name" type="text"/> <input name="attr_default_text" type="hidden" value="somedefault"/> <input name="attr_check" style="display:none" type="checkbox" value="1"/> <input name="attr_checked" style="display:none" type="checkbox" value="1" checked/> </fieldset> <script type="text/worker"> on('change:repeating_example:name', function () { var attrs = []; getSectionIDs("repeating_example", function(idarray) { _.each(idarray, function(currentID, i) { attrs.push("repeating_example_" + currentID + "_name"); attrs.push("repeating_example_" + currentID + "_check"); attrs.push("repeating_example_" + currentID + "_checked"); attrs.push("repeating_example_" + currentID + "_default_text"); }); _.each(idarray, function(currentID, i) { getAttrs(attrs, function(v) { console.log(v["repeating_example_" + currentID + "_name"]); console.log(v["repeating_example_" + currentID + "_check"]); console.log(v["repeating_example_" + currentID + "_checked"]); console.log(v["repeating_example_" + currentID + "_default_text"]); }); }); }); }); </script>
1503951360

Edited 1503951436
Jakob
Sheet Author
API Scripter
Now I'm confused, I'm getting undefined with your code. This is on production just to be sure, I don't know if doing it on dev would make a difference.
1503959365

Edited 1503960526
chris b.
Pro
Sheet Author
API Scripter
I'm still getting the same as Jakob: sheet: <fieldset class="repeating_example">     <input name="attr_name" type="text"/>     <input name="attr_default_text" type="hidden" value="somedefault"/>     <input name="attr_check" style="display:none;" type="checkbox" value="1"/>     <input name="attr_checked" style="display:none;" type="checkbox" value="1" checked/> <input type="text" name="attr_checkcopy" value="@{check}" disabled /> <input type="text" name="attr_dummy" value="@{checked}" disabled /> </fieldset> <br/> Check me:<input name="attr_non_repeating_checkbox" type="checkbox" value="1" /> <script type="text/worker">     on('change:repeating_example:name', function (eventInfo) {        console.log(' received input: event: '+ eventInfo.sourceAttribute+', type: '+eventInfo.sourceType); getAttrs(['repeating_example_name','repeating_example_check','repeating_example_checked','repeating_example_default_text'],function(v1){ var id='',strs; strs = eventInfo.sourceAttribute.split('_'); if (strs && _.size(strs) >= 3) { id = strs[2]; } console.log('################## without specifying ID ####################'); console.log(v1.repeating_example_name) console.log(v1.repeating_example_check); console.log(v1.repeating_example_checked); console.log(v1.repeating_example_default_text); getAttrs(['repeating_example_'+id+'_name','repeating_example_'+id+'_check','repeating_example_'+id+'_checked','repeating_example_'+id+'_default_text'],function(v2){ console.log('======================== specify ID ========================='); console.log(v2['repeating_example_'+id+'_name']) console.log(v2['repeating_example_'+id+'_check']); console.log(v2['repeating_example_'+id+'_checked']); console.log(v2['repeating_example_'+id+'_default_text']); }); });         getSectionIDs("repeating_example", function(idarray) { var attrs=[];             _.each(idarray, function(currentID, i) {                 attrs.push("repeating_example_" + currentID + "_name");                 attrs.push("repeating_example_" + currentID + "_check");                 attrs.push("repeating_example_" + currentID + "_checked");                 attrs.push("repeating_example_" + currentID + "_default_text");             });             _.each(idarray, function(currentID, i) {                 getAttrs(attrs, function(v) { console.log('xxxxxxxxxxxxxxxxxxxxxxxxx ALL ROWS  xxxxxxxxxxxxxxxxxxxxxxxxx');                     console.log(currentID + ': '+ v["repeating_example_" + currentID + "_name"]);                     console.log(currentID + ': '+ v["repeating_example_" + currentID + "_check"]);                     console.log(currentID + ': '+ v["repeating_example_" + currentID + "_checked"]);                     console.log(currentID + ': '+ v["repeating_example_" + currentID + "_default_text"]);                 });             });         });     }); on('change:non_repeating_checkbox',function(eventInfo){        console.log(' received input: event: '+ eventInfo.sourceAttribute+', type: '+eventInfo.sourceType);         getSectionIDs("repeating_example", function(idarray) { var attrs=[];             _.each(idarray, function(currentID, i) {                 attrs.push("repeating_example_" + currentID + "_name");                 attrs.push("repeating_example_" + currentID + "_check");                 attrs.push("repeating_example_" + currentID + "_checked");                 attrs.push("repeating_example_" + currentID + "_default_text");             });             _.each(idarray, function(currentID, i) {                 getAttrs(attrs, function(v) { console.log('zzzzzzzzzzzzzzzzzz ALL ROWS FROM CHECKBOX OUTSIDE FIELDSET xzzzzzzzzzzzzzzzzzzzzzz');                     console.log(currentID + ': '+ v["repeating_example_" + currentID + "_name"]);                     console.log(currentID + ': '+ v["repeating_example_" + currentID + "_check"]);                     console.log(currentID + ': '+ v["repeating_example_" + currentID + "_checked"]);                     console.log(currentID + ': '+ v["repeating_example_" + currentID + "_default_text"]);                 });             });         }); }); </script> and the results when I add a row , and set name to "test one": ################## without specifying ID #################### VM30:11 test one VM30:12 0 VM30:13 1 VM30:14 somedefault VM30:16 ======================== specify ID ========================= VM30:17 test one VM30:18 undefined VM30:19 undefined VM30:20 undefined VM30:34 xxxxxxxxxxxxxxxxxxxxxxxxx ALL ROWS  xxxxxxxxxxxxxxxxxxxxxxxxx VM30:35 -ksex5dlfwokmp0gtra0: test one VM30:36 -ksex5dlfwokmp0gtra0: undefined VM30:37 -ksex5dlfwokmp0gtra0: undefined VM30:38 -ksex5dlfwokmp0gtra0: undefined when adding a second row with name "test two": ################## without specifying ID #################### VM30:11 test two VM30:12 0 VM30:13 1 VM30:14 somedefault VM30:16 ======================== specify ID ========================= VM30:17 test two VM30:18 undefined VM30:19 undefined VM30:20 undefined VM30:34 xxxxxxxxxxxxxxxxxxxxxxxxx ALL ROWS  xxxxxxxxxxxxxxxxxxxxxxxxx VM30:35 -ksex5dlfwokmp0gtra0: test one VM30:36 -ksex5dlfwokmp0gtra0: undefined VM30:37 -ksex5dlfwokmp0gtra0: undefined VM30:38 -ksex5dlfwokmp0gtra0: undefined VM30:34 xxxxxxxxxxxxxxxxxxxxxxxxx ALL ROWS  xxxxxxxxxxxxxxxxxxxxxxxxx VM30:35 -ksexttvzb4mff0c4onf: test two VM30:36 -ksexttvzb4mff0c4onf: undefined VM30:37 -ksexttvzb4mff0c4onf: undefined VM30:38 -ksexttvzb4mff0c4onf: undefined I tried seeing if behavior changes when the event comes from outside the fieldset but its the same: zzzzzzzzzzzzzzzzzz ALL ROWS FROM CHECKBOX OUTSIDE FIELDSET xzzzzzzzzzzzzzzzzzzzzzz VM30:15 -ksex5dlfwokmp0gtra0: test one VM30:16 -ksex5dlfwokmp0gtra0: undefined VM30:17 -ksex5dlfwokmp0gtra0: undefined VM30:18 -ksex5dlfwokmp0gtra0: undefined VM30:14 zzzzzzzzzzzzzzzzzz ALL ROWS FROM CHECKBOX OUTSIDE FIELDSET xzzzzzzzzzzzzzzzzzzzzzz VM30:15 -ksexttvzb4mff0c4onf: test three VM30:16 -ksexttvzb4mff0c4onf: undefined VM30:17 -ksexttvzb4mff0c4onf: undefined VM30:18 -ksexttvzb4mff0c4onf: undefined
1503960567
chris b.
Pro
Sheet Author
API Scripter
note when i added the disabled attributes that show copies of the checkboxes, they show the correct values. So autocalc is grabbing the right defaults but sheetworkers are not
1503962063
Stephen Koontz
Forum Champion
Marketplace Creator
Sheet Author
API Scripter
Compendium Curator
That's very strange. I'll dig into this and let you guys know what I find. The problem I'm having is in reproducing your problem. If there's a hidden race condition happening here, that'll make it very difficult to track down the culprit.
1503962903
chris b.
Pro
Sheet Author
API Scripter
this is repeatable and has been happening in the Pathfinder sheet for a long time. But I never tried to test on a brand new almost empty sheet. I thought it had to do with adding attributes to already-existing rows that was the issue, so I never brought it up. At least now I have a better idea of what is happening :)
1504113825
Stephen Koontz
Forum Champion
Marketplace Creator
Sheet Author
API Scripter
Compendium Curator
It looks like the culprit was over aggressive caching on behalf of our security layer. The sheetworker code that was being deployed on the live site was old code, which is why it was giving slightly different results than on the Dev server. Let me know if you're still having any issues.
1504119661

Edited 1504120314
Jakob
Sheet Author
API Scripter
Now it works for me, lambda or no lambda, perfect. Thank you Steve K.!
1504121717
chris b.
Pro
Sheet Author
API Scripter
awesome, thanks!
1504447886
Kryx
Pro
Sheet Author
API Scripter
Steve, Changing this behavior has a huge change on the behavior that has been around for quite a while. Let's use a simple example: <input type="checkbox" name="attr_test" value="1"> If I were to previously get the value of "test" there were 3 possible states: The value is set to 1 (either by the user, the sheet, or some script) The value is set to 0 (either by the user, the sheet, or some script) The value is undefined (never been edited by the user, the sheet, or some script) Case 3 is no longer detectable. That case was incredibly useful to determine if a user has ever edited a field. For example I could detect that a user had not purposefully turned off a toggle. I would use that detect to prevent my sheet from automatically setting those fields. Now the sheet has no way of detecting that I believe. I use this method all over my sheet. The loss of it would require significant changes with no alternative option to detect that a user has not edited a field. Is there some resolution here that can allow me to detect this case?
1504451165

Edited 1504452414
Jakob
Sheet Author
API Scripter
I don't want to say that knowing about case 3 is not desirable, but as far as I know, this was only ever detectable for inputs in repeating sections before the latest change, not for those outside.
1504454474
Kryx
Pro
Sheet Author
API Scripter
Jakob said: as far as I know, this was only ever detectable for inputs in repeating sections before the latest change, not for those outside. Looking at my code this is probably correct. I use the undefined check a few times outside of repeating sections on text inputs, though I check if it's undefined or empty so they may have just returned an empty string. Every place I use undefined is indeed on repeating sections, though that's the majority of my sheet's processing. :P
1504461591
chris b.
Pro
Sheet Author
API Scripter
I didn't even think to use it this way, I just detected undefined and then set it to default myself :)
1504539947
Stephen Koontz
Forum Champion
Marketplace Creator
Sheet Author
API Scripter
Compendium Curator
Kryx said: Steve, Changing this behavior has a huge change on the behavior that has been around for quite a while. Let's use a simple example: <input type="checkbox" name="attr_test" value="1"> If I were to previously get the value of "test" there were 3 possible states: The value is set to 1 (either by the user, the sheet, or some script) The value is set to 0 (either by the user, the sheet, or some script) The value is undefined (never been edited by the user, the sheet, or some script) Case 3 is no longer detectable. That case was incredibly useful to determine if a user has ever edited a field. For example I could detect that a user had not purposefully turned off a toggle. I would use that detect to prevent my sheet from automatically setting those fields. Now the sheet has no way of detecting that I believe. I use this method all over my sheet. The loss of it would require significant changes with no alternative option to detect that a user has not edited a field. Is there some resolution here that can allow me to detect this case? I hear what you're saying, this change causes you to lose a piece of information for repeating section attributes. But it's also now returning the default value, making it so you don't have to guess or rely on sheet workers to put in the default value when the attribute hasn't been set before. I think that's the more useful and obvious interaction. As for toggles and default values, the way I handle that issue is by designing the sheet to use settings that I believe will be most useful and intuitive to the general user. I.E. toggle whispering roll templates defaults to "off", which I believe is what most people want and expect. Then if the user cares, allow them to find the option. In other sections I'll clear attributes by turning them into empty strings "" when I'm not using them, based on how the option is toggled. I'm open to hearing about situations or interactions you guys think are negatively impacted by this change. Also, there will be a couple more sheet worker updates in the next release that will give you guys more information in change events. I'm going to try and get these out on Dev before the release to give you guys time to review before they go live.
1504542517

Edited 1504542627
Kryx
Pro
Sheet Author
API Scripter
Steve K. said: I hear what you're saying, this change causes you to lose a piece of information for repeating section attributes. But it's also now returning the default value, making it so you don't have to guess or rely on sheet workers to put in the default value when the attribute hasn't been set before. I think that's the more useful and obvious interaction. Hi Steve, I agree that this new behavior makes sense. I'd like to address two issues though: Lack of communication . This change is what SemVer would consider a breaking change as the API endpoint is now returning a different value. As a result of this change, code that previously worked no longer works. As an author I need some notificaiton for breaking changes to the current behavior of sheet workers. Without that notification we end up in situations like we can currently see on the forums here with the code causing breaking problems for users. Loss of functionality . How you manage your codebase is ultimately up to you, but this change will be significantly painful for me as a developer using your API. This isn't a result of some amateur coding some poor HTML - I built functionality based on logical behavior. With notification this change could be handled before users see it, but even then the change you have made here will cause me to spend a significant amount of hours solving issues related to the change you have made. In my best guess this change will cost me 10-20 hours of free time to reimplement this in another way. This cannot be the norm
1504649199
Stephen Koontz
Forum Champion
Marketplace Creator
Sheet Author
API Scripter
Compendium Curator
This change was one put in place over a year ago, shortly after the inclusion of sheet workers. You can see related forum posts  here and  here . The mistake we made was in not noticing the patched behavior didn't actually make it live. Because of the different nature of the sheet worker code and how it's distributed, it got caught behind overly aggressive caching at our security layer. When I busted the cache and the new code went out, this fix along with several sheet worker optimizations I've made actually went live.  This wasn't a thoughtless change, it wasn't uncommunicated back when we thought we pushed the change live, and it certainly wasn't something done maliciously. We're sorry that you became invested in that unintended and undocumented behavior and that this change will require you to update your code. We continue to appreciate community coders such as yourself, and we do apologize for the inconvenience this has caused you.