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

Sheetworker Script Help: Summary of a Fieldset

1489611467
Diana P
Pro
Sheet Author
Hi, I'm having an issue with sheetworker scripts that I was hoping someone could help me with.  I am working on building a summary of several fields and values from both within a fieldset and outside of it but am running into issues.  If I change a value within the fieldset, the sheetworker fires and correctly builds my summary.  However if I change one of the external fields, the fieldset changes twice (once when the field mirroring the external field changes, and once when the line total field changes:  ie my language skill is the sum of the rank bonus for that skill, the stat bonus, and a couple other bonuses and when the stat bonus changes, the sheetworker fires twice simultaneously, once when the stat bonus in the field set changes and once when the skill total changes.  This is causing those situations to have a summary which is also doubled (each language appears in it twice). How can I prevent either the sheetworker from firing the second time or the summary from being doubled if it does fire the second time?  (My scripting skill mostly consists of cannibalizing other code and I have not found examples of anything like this yet...)  Bonus question(s):  right now I am dumping my summary into two different summary areas so it is more readable.  Is there anyway to insert a carriage return or line feed into the javascript-created string which my span will interpret correctly giving me a nicer output?  Or is there a better way of doing this? Thanks for your help. My Sample Code Html: <table cellpadding="0" cellspacing="0">     <td>         <tr class="sheet-table-row">             <td class="sheet-table-header2">Stat</td>             <td class="sheet-table-header2">Stat<br>Bonus</td>         </tr>             <tr class="sheet-table-row">             <td class="sheet-table-header">Memory</td>             <td class="sheet-table-data-center-stats"><input type="text" name="attr_mebonus" title="mebonus" value="0"  /></td>         </tr>               <tr class="sheet-table-row">             <td class="sheet-table-header">Reasoning</td>             <td class="sheet-table-data-center-stats"><input type="text" name="attr_rebonus" title="rebonus" value="0"  /></td>         </tr>         <tr class="sheet-table-row">             <td class="sheet-table-header">Empathy</td>             <td class="sheet-table-data-center-stats"><input type="text" name="attr_embonus" title="embonus" value="0"  /></td>         </tr>     </td> </table> <hr/> <div class="sheet-table">     <div class="sheet-table-data-center" style="vertical-align:top;">         <span class="sheet-table-data-left" style="width: 192px;" name="attr_knownlanguagesl"></span>         <span class="sheet-table-data-left" style="width: 192px;" name="attr_knownlanguagesr"></span>     </div> </div> <hr/> <div class="sheet-table-row">     <span class="sheet-table-header2" style="width: 200px;">Category/Skill</span>     <span class="sheet-table-header2" style="width: 40px;">Cat/Total<br>Bonus</span>     <span class="sheet-table-header2" style="width: 60px;">Ranks</span>     <span class="sheet-table-header2" style="width: 40px;">Rank<br>Bonus</span>     <span class="sheet-table-header2" style="width: 55px;">Stat</span>     <span class="sheet-table-header2" style="width: 40px;">Stat<br>Bonus</span>     <span class="sheet-table-header2" style="width: 40px;">Profession<br>or Category<br>Bonus</span>     <span class="sheet-table-header2" style="width: 40px;">Special<br>Bonus</span>     <span class="sheet-table-header2" style="width: 40px;">Item<br>Bonus</span> </div> <div class="sheet-table-row">     <span class="sheet-table-data-skills-cat-name">Communications</span>     <span class="sheet-table-data-skills-cat"><input type="text" name="attr_cat-communications" title="cat-communications" value="@{cat-communications-rankbonus}+@{cat-communications-statbonus}+@{cat-communications-profbonus}+@{cat-communications-specialbonus}+@{cat-communications-itembonus} " disabled="true" /></span>     <input type="hidden" name="attr_cat-communications-prog" title="cat-communications-prog (progression)" value="2" />     <span class="sheet-table-data-skills-cat-wide"><input type="text" name="attr_cat-communications-ranks" title="cat-communications-ranks (Number of Ranks)" value="0" /></span>     <span class="sheet-table-data-skills-cat"><input type="text" name="attr_cat-communications-rankbonus" title="cat-communications-rankbonus (Skill Rank Bonus)" value="-15" /></span>     <span class="sheet-table-data-skills-cat-wide"><b>Re/Me</b></span>     <span class="sheet-table-data-skills-cat"><input type="text" name="attr_cat-communications-statbonus" title="cat-communications-statbonus" value="@{rebonus}+@{mebonus}" disabled="true" /></span>     <span class="sheet-table-data-skills-cat"><input type="text" name="attr_cat-communications-profbonus" title="cat-communications-profbonus (Profession bonus to category if applicable.)" value="0" /></span>     <span class="sheet-table-data-skills-cat"><input type="text" name="attr_cat-communications-specialbonus" title="cat-communications-specialbonus (Special bonus to category if applicable.)" value="0" /></span>     <span class="sheet-table-data-skills-cat"><input type="text" name="attr_cat-communications-itembonus" title="cat-communications-itembonus (Item bonus to category if applicable.)" value="0" /></span>     <span class="sheet-table-data-skills-cat-sm" style="width: 210px;">   </span> </div> <div class="sheet-table-row">     <span class="sheet-table-data-skills-name">Language</span>     <span class="sheet-table-data-skills"></span>     <span class="sheet-table-data-skills-wide"></span>     <span class="sheet-table-data-skills"></span>     <span class="sheet-table-data-skills-wide"></span>     <span class="sheet-table-data-skills"></span>     <span class="sheet-table-data-skills"></span>     <span class="sheet-table-data-skills"></span>     <span class="sheet-table-data-skills"></span> </div> <fieldset class="repeating_langs" colspan="11">     <div class="sheet-table-row" >         <span class="sheet-table-data-skills" style="width: 200px;" ><input type="text" style="width: 140px;" name="attr_languagename" title="repeating_langs_#_languagename" placeholder="Language Name" />(Spoken)</span>         <span class="sheet-table-data-skills"><input type="text" style="width: 40px;" name="attr_languagespoken" title="repeating_langs_#_languagespoken" value="@{languagespokenrankbonus}+@{languagespokenstat}+@{languagespokencatbonus}+@{languagespokenspecialmod}+@{languagespokenitemmod}" disabled="true" /></span>         <span class="sheet-table-data-skills"><input type="text" style="width: 65px;" name="attr_languagespokenranks" title="repeating_langs_#_languagespokenranks (Number of Ranks)" value="0" />         <input type="hidden" name="attr_languagespokenprog" title="repeating_langs_#_languagespokenprog(Skill Progression Type)" value="3" /></span>         <span class="sheet-table-data-skills"><input type="text" style="width: 40px;" name="attr_languagespokenrankbonus" title="repeating_langs_#_languagespokenrankbonus" value="-15"/></span>         <span class="sheet-table-data-skills" style="width: 60px;"><b>Em</b></span>         <span class="sheet-table-data-skills"><input type="text" style="width: 40px;" name="attr_languagespokenstat" title="repeating_langs_#_languagespokenstat (Stat Bonus)" value="@{embonus}" disabled="true" /></span>         <span class="sheet-table-data-skills"><input type="text" style="width: 40px;" name="attr_languagespokencatbonus" title="repeating_langs_#_languagespokencatbonus (Category Bonus)"  value="@{cat-communications}" disabled="true" /></span>         <span class="sheet-table-data-skills"><input type="text" style="width: 40px;" name="attr_languagespokenspecialmod" title="repeating_langs_#_languagespokenspecialmod (Any Special bonuses)" value="0" /></span>         <span class="sheet-table-data-skills"><input type="text" style="width: 40px;" name="attr_languagespokenitemmod" title="repeating_langs_#_languagespokenitemmod (Bonus modification from Item)" value="0" /></span>     </div>     <div class="sheet-table-row" >         <span class="sheet-table-data-skills" style="width: 200px; border-bottom-style: solid; border-color: LightGrey;" ><span style="width: 140px;">                                   </span>(Written)</span>         <span class="sheet-table-data-skills" style="border-bottom-style: solid; border-color: LightGrey;"><input type="text" style="width: 40px;" name="attr_languagewritten" title="repeating_langs_#_languagewritten" value="@{languagewrittenrankbonus}+@{languagewrittenstat}+@{languagewrittencatbonus}+@{languagewrittenspecialmod}+@{languagewrittenitemmod}" disabled="true" /></span>         <span class="sheet-table-data-skills" style="border-bottom-style: solid; border-color: LightGrey;"><input type="text" style="width: 65px;" name="attr_languagewrittenranks" title="repeating_langs_#_languagewrittenranks (Number of Ranks)" value="0" />         <input type="hidden" name="attr_languagewrittenprog" title="repeating_langs_#_languagewrittenprog(Skill Progression Type)" value="3" /></span>         <span class="sheet-table-data-skills" style="border-bottom-style: solid; border-color: LightGrey;"><input type="text" style="width: 40px;" name="attr_languagewrittenrankbonus" title="repeating_langs_#_languagewrittenrankbonus" value="-15"/></span>         <span class="sheet-table-data-skills" style="width: 60px; border-bottom-style: solid; border-color: LightGrey;">   </span>         <span class="sheet-table-data-skills" style="border-bottom-style: solid; border-color: LightGrey;"><input type="hidden" style="width: 40px;" name="attr_languagewrittenstat" title="repeating_langs_#_languagewrittenstat (Stat Bonus)" value="@{embonus}" disabled="true" /></span>         <span class="sheet-table-data-skills" style="border-bottom-style: solid; border-color: LightGrey;"><input type="hidden" style="width: 40px;" name="attr_languagewrittencatbonus" title="repeating_langs_#_languagewrittencatbonus (Category Bonus)"  value="@{cat-communications}" disabled="true" /></span>         <span class="sheet-table-data-skills" style="border-bottom-style: solid; border-color: LightGrey;"><input type="text" style="width: 40px;" name="attr_languagewrittenspecialmod" title="repeating_langs_#_languagewrittenspecialmod (Any Special bonuses)" value="0" /></span>         <span class="sheet-table-data-skills" style="border-bottom-style: solid; border-color: LightGrey;"><input type="text" style="width: 40px;" name="attr_languagewrittenitemmod" title="repeating_langs_#_languagewrittenitemmod (Bonus modification from Item)" value="0" /></span>     </div> </fieldset> <!-- start Sheet Workers Script section--> <script type="text/worker">      //  <!---- If repeating_langs_* changes, make a nice summary for the front page for me ----> on("change:repeating_langs", function() {     console.log('/*----------- create rep-languages summary------*/');         getAttrs(["cat-communications-rankbonus","rebonus","mebonus","embonus","cat-communications-profbonus","cat-communications-specialbonus","cat-communications-itembonus"], function(values){             catbonus=parseInt(values["cat-communications-rankbonus"], 10) +parseInt(values.rebonus, 10) +parseInt(values.mebonus, 10) +parseInt(values["cat-communications-profbonus"], 10) +parseInt(values["cat-communications-specialbonus"], 10) +parseInt(values["cat-communications-itembonus"], 10); console.log("catbonus: "+catbonus);             getSectionIDs("repeating_langs", function(idarray){                 langpt1 = "";                 langs1 = "";                 langs2 = "";                 if (idarray.length>0) { console.log("ID array length: "+idarray.length);                     var count=0;                     _.each(idarray, function(currentID) {                         getAttrs(["repeating_langs_"+currentID+"_languagename",                                     "repeating_langs_"+currentID+"_languagespokenranks",                                     "repeating_langs_"+currentID+"_languagespokenrankbonus",                                     "repeating_langs_"+currentID+"_languagespokenspecialmod",                                     "repeating_langs_"+currentID+"_languagespokenitemmod",                                     "repeating_langs_"+currentID+"_languagewrittenranks",                                     "repeating_langs_"+currentID+"_languagewrittenrankbonus",                                     "repeating_langs_"+currentID+"_languagewrittenspecialmod",                                     "repeating_langs_"+currentID+"_languagewrittenitemmod"], function(x) {                                       console.log("current id: "+currentID); console.log("languagename: "+x["repeating_langs_"+currentID+"_languagename"]);                                       langspokenspecial=parseInt(x["repeating_langs_"+currentID+"_languagespokenspecialmod"], 10);                                       if (isNaN(langspokenspecial))                                             langspokenspecial = 0; console.log("langspokenspecial: "+langspokenspecial);                                       langspokenitem=parseInt(x["repeating_langs_"+currentID+"_languagespokenitemmod"], 10);                                       if (isNaN(langspokenitem))                                             langspokenitem = 0; console.log("langspokenitem: "+langspokenitem);                                       langwrittenspecial=parseInt(x["repeating_langs_"+currentID+"_languagewrittenspecialmod"], 10);                                       if (isNaN(langwrittenspecial))                                             langwrittenspecial = 0; console.log("langwrittenspecial: "+langwrittenspecial);                                       langwrittenitem=parseInt(x["repeating_langs_"+currentID+"_languagewrittenitemmod"], 10);                                       if (isNaN(langwrittenitem))                                             langwrittenitem = 0; console.log("langwrittenitem: "+langwrittenitem);                                       langspoken = parseInt(x["repeating_langs_"+currentID+"_languagespokenrankbonus"], 10) +parseInt(values.embonus, 10) +catbonus +langspokenspecial +langspokenitem; console.log("langspoken: "+langspoken);                                       langwritten = parseInt(x["repeating_langs_"+currentID+"_languagewrittenrankbonus"], 10) +parseInt(values.embonus, 10) +catbonus +langwrittenspecial +langwrittenitem; console.log("langwritten: "+langwritten);                                       langpt1 =x["repeating_langs_"+currentID+"_languagename"]+                                             " S:"+x["repeating_langs_"+currentID+"_languagespokenranks"]+                                             "/"+langspoken+                                             " W:"+x["repeating_langs_"+currentID+"_languagewrittenranks"]+                                             "/"+langwritten+ ". ";                                         l=29-langpt1.length; //console.log("l:"+l);                                         for( var i=0; i<l; i++){                ////  pad out the width so it is about one lang/line. //console.log("--------------index: "+i+"  length:"+langpt1.length+"/"+l);                                             langpt1 +=". ";                                         } console.log("count: "+count);                                         if (x["repeating_langs_"+currentID+"_languagename"]){                                             if((count%2)==1){                                                 langs1 +=langpt1;                                             }else{                                                 langs2 +=langpt1;                                             }                                         } console.log("Langs1: "+langs1); console.log("Langs2: "+langs2);                                         count++; console.log("end langs?");                     setAttrs({                         knownlanguagesr : langs1,                         knownlanguagesl    : langs2                     });                                     }                         );                     });                 }             });                     }); }); </script> <!-- end Sheet Workers Section--> CSS: .charsheet table td {     font-weight: bold;     text-align: center; } .sheet-table-header {     display:table-cell;     text-align:center;     font-weight:bold;     vertical-align:bottom; } .sheet-table-header2-left {     display:table-cell;     text-align:left;     font-weight:bold;     font-size: 0.7em; } .sheet-table-header2 {     display:table-cell;     text-align:center;     font-weight:bold;     font-size: 0.7em;     vertical-align:bottom; } .sheet-table-left {     display:table-cell;     text-align:left; } .sheet-table-data-left {     display:table-cell;     text-align:left;     vertical-align:top; } .sheet-table-data-center {     display:table-cell;     text-align:center;     vertical-align:top; } .sheet-table-data-center-stats {     display:table-cell;     text-align:center;     font-size: 0.7em;     vertical-align:top;     width:35px; } .sheet-table-data-skills-cat {     display:table-cell;     text-align:center;     vertical-align:bottom;     background-color:aliceblue;     width:40px; } .sheet-table-data-skills-cat-name {     display:table-cell;     text-align:center;     vertical-align:bottom;     background-color:aliceblue;     width:200px; } .sheet-table-data-skills-cat-wide {     display:table-cell;     text-align:center;     vertical-align:bottom;     background-color:aliceblue;     width:55px; } .sheet-table-data-skills-cat-wide {     display:table-cell;     text-align:center;     vertical-align:bottom;     background-color:aliceblue;     width:65px; } .sheet-table-data-skills-cat-sm {     display:table-cell;     text-align:center;     font-size: 0.7em;     vertical-align:bottom;     background-color:aliceblue; } .sheet-table-data-skills-cat-sm-bold {     display:table-cell;     text-align:center;     font-weight:bold;     font-size: 0.7em;     vertical-align:bottom;     background-color:aliceblue; } .sheet-table-data-skills {     display:table-cell;     text-align:center;     vertical-align:bottom;     width:40px; } .sheet-table-data-skills-name {     display:table-cell;     text-align:center;     font-size: 0.9em;     vertical-align:bottom;     width:200px; } .sheet-table-data-skills-name-fillin {     display:table-cell;     text-align:center;     vertical-align:bottom;     width:200px; } .sheet-table-data-skills-wide {     display:table-cell;     text-align:center;     vertical-align:bottom;     width:55px; } .sheet-table-data-skills-wide {     display:table-cell;     text-align:center;     vertical-align:bottom;     width:65px; } .sheet-table-data-skills-sm {     display:table-cell;     text-align:center;     font-size: 0.7em;     vertical-align:bottom; } .sheet-table-data-skills-sm-bold {     display:table-cell;     text-align:center;     font-weight:bold;     font-size: 0.7em;     vertical-align:bottom; } .sheet-table-row {     display:table-row;     vertical-align:top;     width:100%; } .sheet-table-row-name {     display:table-cell;     text-align:center;     color:white;     background-color:black;     font-weight:bold; } textarea { height: auto; margin-bottom: 0; } select { margin-bottom: 0; } input, select {     width:100%; } Picture of doubling:
1489622755
Lithl
Pro
Sheet Author
API Scripter
Diana P said: Bonus question(s):  right now I am dumping my summary into two different summary areas so it is more readable.  Is there anyway to insert a carriage return or line feed into the javascript-created string which my span will interpret correctly giving me a nicer output?  Or is there a better way of doing this? You can style the span with white-space: pre (or pre-wrap or pre-line) in order to make it line-break at newline characters ('\n'). pre will only  break at line-breaks (and <br>, but if you try to include '<br>' it'll come out as <br>), so if you've got a long line it will overflow (control overflow behavior with overflow property, such as overflow:hidden or overflow:scroll). pre-wrap will break at new-lines, <br>s, and as appropriate for the line's content, so if you've got a long line it'll wrap as normal. pre-line works just like pre-wrap, except multiple whitespace characters in a row will be collapsed (whereas pre and pre-wrap will preserve them).
1489641256
Diana P
Pro
Sheet Author
Brian said: You can style the span with white-space: pre (or pre-wrap or pre-line) in order to make it line-break at newline characters ('\n'). pre will only  break at line-breaks (and <br>, but if you try to include '<br>' it'll come out as <br>), so if you've got a long line it will overflow (control overflow behavior with overflow property, such as overflow:hidden or overflow:scroll). pre-wrap will break at new-lines, <br>s, and as appropriate for the line's content, so if you've got a long line it'll wrap as normal. pre-line works just like pre-wrap, except multiple whitespace characters in a row will be collapsed (whereas pre and pre-wrap will preserve them). Thank you very much!  I managed to get this part of it working with the pre-wrap. :) Now if I can get the other bit fixed.... :)
1489651789

Edited 1489656723
Jakob
Sheet Author
API Scripter
So, I'll try helping. This is a bit messy since I just quickly hacked your code, but perhaps you can get the idea: the main point is to not start several asynchronous calls, one for each row, but to get all the attributes at once and then do your processing. I don't really know what is going in with the doubling in your original code, but this way the summary should be completely regenerated from within the innermost function each time, no chance of doubling even if 2 events fire at once. Should be easier to debug, at least: // <!---- If repeating_langs_* changes, make a nice summary for the front page for me ----> on("change:repeating_langs", function () { console.log('/*----------- create rep-languages summary------*/'); getAttrs(["cat-communications-rankbonus", "rebonus", "mebonus", "embonus", "cat-communications-profbonus", "cat-communications-specialbonus", "cat-communications-itembonus"], function (values) { let catbonus = parseInt(values["cat-communications-rankbonus"], 10) + parseInt(values.rebonus, 10) + parseInt(values.mebonus, 10) + parseInt(values["cat-communications-profbonus"], 10) + parseInt(values["cat-communications-specialbonus"], 10) + parseInt(values["cat-communications-itembonus"], 10); getSectionIDs("repeating_langs", function (idarray) { let attrArray = _.chain(idarray) .map(function (id) { return ["repeating_langs_" + id + "_languagename", "repeating_langs_" + id + "_languagespokenranks", "repeating_langs_" + id + "_languagespokenrankbonus", "repeating_langs_" + id + "_languagespokenspecialmod", "repeating_langs_" + id + "_languagespokenitemmod", "repeating_langs_" + id + "_languagewrittenranks", "repeating_langs_" + id + "_languagewrittenrankbonus", "repeating_langs_" + id + "_languagewrittenspecialmod", "repeating_langs_" + id + "_languagewrittenitemmod" ]; }) .flatten().value(); getAttrs(attrArray, function (x) { let count = 0, langs1 = "", langs2 = ""; _.each(idarray, function (currrentID) { let langspokenspecial = parseInt(x["repeating_langs_" + currentID + "_languagespokenspecialmod"], 10); if (isNaN(langspokenspecial)) langspokenspecial = 0; let langspokenitem = parseInt(x["repeating_langs_" + currentID + "_languagespokenitemmod"], 10); if (isNaN(langspokenitem)) langspokenitem = 0; let langwrittenspecial = parseInt(x["repeating_langs_" + currentID + "_languagewrittenspecialmod"], 10); if (isNaN(langwrittenspecial)) langwrittenspecial = 0; let langwrittenitem = parseInt(x["repeating_langs_" + currentID + "_languagewrittenitemmod"], 10); if (isNaN(langwrittenitem)) langwrittenitem = 0; let langspoken = parseInt(x["repeating_langs_" + currentID + "_languagespokenrankbonus"], 10) + parseInt(values.embonus, 10) + catbonus + langspokenspecial + langspokenitem; let langwritten = parseInt(x["repeating_langs_" + currentID + "_languagewrittenrankbonus"], 10) + parseInt(values.embonus, 10) + catbonus + langwrittenspecial + langwrittenitem; let langpt1 = x["repeating_langs_" + currentID + "_languagename"] + " S:" + x["repeating_langs_" + currentID + "_languagespokenranks"] + "/" + langspoken + " W:" + x["repeating_langs_" + currentID + "_languagewrittenranks"] + "/" + langwritten + ". "; let l = 29 - langpt1.length; for (var i = 0; i < l; i++) { // pad out the width so it is about one lang/line. langpt1 += ". "; // unnecessary now, change it } if (x["repeating_langs_" + currentID + "_languagename"]) { if ((count % 2) == 1) { langs1 += langpt1; } else { langs2 += langpt1; } } count++; }); setAttrs({ knownlanguagesr: langs1, knownlanguagesl: langs2 }); }); }); }); }); Incidentally, I think you can, for all practical purposes, replace these expressions: let langspokenspecial = parseInt(x["repeating_langs_" + currentID + "_languagespokenspecialmod"], 10); if (isNaN(langspokenspecial)) langspokenspecial = 0; by let langspokenspecial = parseInt(x["repeating_langs_" + currentID + "_languagespokenspecialmod"], 10) || 0; since NaN is falsy anyway.
1489693525
Diana P
Pro
Sheet Author
@Jakob  It works!   It works in my little snippet and it works when I plug it into the main sheet with all the rest of my sheetworkers! Thank you so much!!!!  I've been poking at this for over a month so it's wonderful to get it working. (now to see if I can actually understand it... :)
1489707722
Jakob
Sheet Author
API Scripter
Happy I could help!