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

Using a sheetworker to read a value within a repeating section, then write values to that same section

The idea I'm going for is that, in a repeating_psychicability section, I would pick a dropdown value that sends 0, 1, or 2, for which Stat to use to cast the ability. The sheetworker would read the input number, then copy respective values from elsewhere in the sheet (with names like @{wpTotal}) and write out to two hidden inputs that could be easily referenced in a roll button. Trouble is, I don't know the first thing about how repeating sections and their IDs differ from any other part of the sheet, and reading other threads didn't help my understanding of how these worked. For reference, here's what I've cooked up so far, with some HTML: <input class='hidden' type='text' name='attr_psy_ab_total_finder' readonly /> <input class='hidden' type='text' name='attr_psy_ab_unnat_finder' readonly /> <select name='attr_P_focus' class='psykana_ability_gs_c2 full_width bottomless'> <option value='0' selected='selected'>Willpower</option> <option value='1'>Perception</option> <option value='2'>Psyniscience</option> </select> And some JS: on('sheet:opened change:p_focus change:wptotal change:wp_unnat', function() { getAttrs([ 'p_focus', 'wptotal', 'wp_unnat' ], function(values) { var p_focus = parseInt(values['p_focus']) || 0; var wptotal = values.wptotal; var wp_unnat = parseInt(values['wp_unnat']) || 0; switch (p_focus) { case 0: setAttrs({ psy_ab_total_finder: wptotal, psy_ab_unnat.finder: wp_unnat }); break; } }); }); I understand that the sheetworker I'm using hasn't had any real adjustment for the fact I'm trying to read a repeating value like getSectionID, but the functions related to that only seem to get harder to read the more I look at them. Any help would be greatly appreciated!
1617750856

Edited 1617762134
Sammy Silver
Sheet Author
Update: I worked out this problem with someone else over PMs. The troubleshooting process was long and arduous, and would have owed itself to quite a long thread had it been done here, but the results work excellently. The HTML looked like: <input class='hidden' type='text' name='attr_psy_ab_total_finder' readonly /> <input class='hidden' type='text' name='attr_psy_ab_unnat_finder' readonly /> <select name='attr_P_focus' class=''> <option value='wp' selected='selected'>Willpower</option> <option value='per'>Perception</option> <option value='psyniscience'>Psyniscience</option> </select> And the JS came out with: on('sheet:opened change:repeating_psychicabilities:p_focus', function() { getSectionIDs('psychicabilities', function(idarray) { // first get the attribute names for all rows in put in one array const fieldnames = []; idarray.forEach(id => fieldnames.push(`repeating_psychicabilities_${id}_P_focus`)); getAttrs(fieldnames, values => { // create a variable to hold all the attribute values you re going to create. const attr = {}; // now loop through the rows again idarray.forEach(id => { let row = 'repeating_psychicabilities_' + id; let p_focus = values[`${row}_P_focus`] || wp; if (p_focus.length > 3) { attr[`${row}_psy_ab_total_finder`] = `@{${p_focus}_total}`; attr[`${row}_psy_ab_unnat_finder`] = `@{${p_focus}_unnat}`; } else { attr[`${row}_psy_ab_total_finder`] = `@{${p_focus}Total}`; attr[`${row}_psy_ab_unnat_finder`] = `@{${p_focus.toUpperCase()}_unnat}`; } }); console.log(values,attr) setAttrs(attr); }); }); }); @{wpTotal} and @{WP_unnat} had to be handled differently from @{psyniscience_total} and @{psyniscience_unnat}, hence the if statement.
1617791427
Andreas J.
Forum Champion
Sheet Author
Translator
Cold you show how the full code for the repeating section looks like? I coped this to the wiki so that there is at least one example on how working within a repeating section works, as it's pretty common in itself. Having the complete code for the section would make it a complete example others could use. <a href="https://wiki.roll20.net/Sheet_Worker_Snippets#Repeating_Section" rel="nofollow">https://wiki.roll20.net/Sheet_Worker_Snippets#Repeating_Section</a>
1617800344
Finderski
Pro
Sheet Author
Compendium Curator
It should also be noted that if the fields are only dependent on things in the same row, you don't need sheet:opened &nbsp;and then you could get by without the need for a getSectionIDs bit and the getAttrs becomes a lot easier, too.
1617824959

Edited 1617825456
Sammy Silver
Sheet Author
Finderski said: It should also be noted that if the fields are only dependent on things in the same row Would you be willing to provide an example? Although the outputs my sheetworker stitches together serve to reference outside values, the text of the output is made entirely within the repeating section and sheetworker. Andreas J. said: Cold you show how the full code for the repeating section looks like? My code's pretty beefy, it might need to be cut down pretty heavily if the idea was only to show how my repeating section is set up. Its features include min/max buttons that partially collapse the section, and Cast/Dmg buttons that send quite a bit of information to rolltemplate, and the self-writing text inputs that this thread is about. &lt;fieldset name='psychicabilities' class='repeating_psychicabilities'&gt; &lt;div class='psykana_ability_rep'&gt; &lt;div class='psykana_ability_grid1'&gt; &lt;input name='attr_wep_display' type='checkbox' value='min' class='collapsible_entity_switch hidden' /&gt; &lt;input name='attr_wep_display' type='checkbox' value='half' class='collapsible_entity_switch_half hidden' /&gt; &lt;label title='Minimal' class='psykana_ability_gs_a1'&gt;&lt;input type='checkbox' name='attr_wep_display' value='min' class='select_button hidden' /&gt;&lt;span class='select_text bottomless'&gt;&amp;#128469;&lt;/span&gt;&lt;/label&gt; &lt;label title='Limited' class='psykana_ability_gs_a2'&gt;&lt;input type='checkbox' name='attr_wep_display' value='half' class='select_button hidden' /&gt;&lt;span class='select_text bottomless'&gt;&amp;#128471;&lt;/span&gt;&lt;/label&gt; &lt;div class='psykana_ability_gs_a3'&gt;Name&lt;/div&gt; &lt;input class='psykana_ability_gs_a4 full_width' type='text' name='attr_P_name' /&gt; &lt;div class='psykana_ability_gs_a5'&gt;Subtype&lt;/div&gt; &lt;input class='psykana_ability_gs_a6 full_width' type='text' name='attr_P_subtype' /&gt; &lt;/div&gt; &lt;input name='attr_wep_display' type='checkbox' value='min' class='collapsible_entity_switch hidden' /&gt; &lt;input name='attr_wep_display' type='checkbox' value='half' class='collapsible_entity_switch_half hidden' /&gt; &lt;div class='psykana_ability_grid2 collapsible_entity_toggle'&gt; &lt;div class='psykana_ability_gs_b1'&gt;Range&lt;/div&gt; &lt;input class='psykana_ability_gs_b2 full_width' type='text' value='0' name='attr_P_range' /&gt; &lt;div class='psykana_ability_gs_b3'&gt;Damage&lt;/div&gt; &lt;input class='psykana_ability_gs_b4 full_width' type='text' value='0' name='attr_P_dam-roll' /&gt; &lt;div class='psykana_ability_gs_b5'&gt;Type&lt;/div&gt; &lt;input class='psykana_ability_gs_b6 full_width' type='text' name='attr_P_type' /&gt; &lt;div class='psykana_ability_gs_b7'&gt;Pen&lt;/div&gt; &lt;input class='psykana_ability_gs_b8 full_width' type='text' value='0' name='attr_P_pen' /&gt; &lt;/div&gt; &lt;input class='hidden' type='text' name='attr_psy_ab_total_finder' readonly /&gt; &lt;input class='hidden' type='text' name='attr_psy_ab_unnat_finder' readonly /&gt; &lt;div class='psykana_ability_grid3'&gt; &lt;div class='psykana_ability_gs_c1'&gt;Focus Power&lt;/div&gt; &lt;select name='attr_P_focus' class='psykana_ability_gs_c2 full_width bottomless'&gt; &lt;option value='wp' selected='selected'&gt;Willpower&lt;/option&gt; &lt;option value='per'&gt;Perception&lt;/option&gt; &lt;option value='psyniscience'&gt;Psyniscience&lt;/option&gt; &lt;/select&gt; &lt;div class='psykana_ability_gs_c3 collapsible_entity_toggle'&gt;Power Mod&lt;/div&gt; &lt;input class='psykana_ability_gs_c4 full_width' type='text' value='0' name='attr_P_mod1' /&gt; &lt;button name='psy_hit' class='equipment_weapon_rep_c5_psy full_width clear' type='roll' value='@{to-gm}&amp;{template:mythic} {{character= @{character_name}}}{{psy= }}{{attack= }}{{weapon= @{P_name}}} {{burstwin=[[ceil([[ [[1+floor(abs([[{{ {@{P_total}+@{inlinemod-toggle}}, {@{psy_ab_total_finder}-@{limiter}}}kh1, {@{psy_ab_total_finder}+@{limiter}}}kl1]]-[[1d100cs&gt;90@{psy_roll}]])/10)]]+ceil(@{psy_ab_unnat_finder}/2)]]/2)]]}} {{target=$[[0]]}} {{roll=$[[1]]}} {{dof=$[[2]]}} {{dos=$[[3]]}} {{class=[[@{psykana_class}]]}} {{limit=[[@{psykana_limit}]]}} {{focus= [[@{psy_ab_total_finder}]]}} {{pmod=[[@{P_mod1}]]}} {{sustain=[[@{psykana_sustain}]]}} {{modifier=[[@{inlinemod-toggle}]]}} {{P_multi=[[@{P_multi}]]}} {{eprmod=[[5*@{effective_psy_rating}]]}} {{epr=[[@{effective_psy_rating}]]}}'&gt;Cast |&lt;input name='attr_P_total' value='@{psy_ab_total_finder}+@{P_mod1}+5*@{effective_psy_rating}+@{psykana_sustain}' class='input_background input_char_background' disabled /&gt;&lt;/button&gt; &lt;button name='psy_dmg' class='psykana_ability_gs_c6 full_width clear' type='roll' value='@{to-gm}&amp;{template:mythic} {{character= @{character_name}}} {{type= @{P_type}}} {{weapon= @{P_name}}} {{damage=[[@{P_dam-roll}]] }} {{pen=[[@{P_pen}]] }} {{@{settings_weapondescription}=@{P_ability_r} }}' &gt;DMG&lt;/button&gt; &lt;/div&gt; &lt;div class='psykana_ability_grid4 collapsible_entity_toggle collapsible_entity_toggle_half'&gt; &lt;select name='attr_P_multi' class='psykana_ability_gs_d1 full_width bottomless'&gt; &lt;option value='0'&gt;N-A&lt;/option&gt; &lt;option value='1'&gt;Psychic Bolt&lt;/option&gt; &lt;option value='2'&gt;Psychic Barrage&lt;/option&gt; &lt;option value='3'&gt;Psychic Storm&lt;/option&gt; &lt;option value='4'&gt;Psychic Blast&lt;/option&gt; &lt;/select&gt; &lt;div class='psykana_ability_gs_d2'&gt;Action&lt;/div&gt; &lt;input class='psykana_ability_gs_d3 full_width' type='text' name='attr_P_action' /&gt; &lt;div class='psykana_ability_gs_d4'&gt;Sustained&lt;/div&gt; &lt;input class='psykana_ability_gs_d5 full_width' type='text' name='attr_P_sustained' /&gt; &lt;/div&gt; &lt;div class='collapsible_entity_toggle'&gt; &lt;input name='attr_P_ability_r' type='text' placeholder='Special' class='full_width_49px border_none' /&gt; &lt;label title='Expand' class='margin_adjust_wep'&gt;&lt;input type='checkbox' name='attr_collapse' value='3' class='collapsible_entity_switch select_button hidden' /&gt;&lt;span class='select_text radius_border_right_wep'&gt;▼&lt;/span&gt;&lt;/label&gt; &lt;label title='Posts description in chat' class='margin_adjust_wep2'&gt;&lt;button type='roll' value='@{to-gm}&amp;{template:mythic} {{name=@{P_name} }} {{description=@{P_desc_r} }}' class='hidden'&gt;&lt;/button&gt;&lt;span class='select_text'&gt;&lt;/span&gt;&lt;/label&gt; &lt;input name='attr_collapse' type='checkbox' value='3' class='collapsible_entity_switch hidden' /&gt; &lt;textarea name='attr_P_desc_r' class='collapsible_entity_block description_rounded_margin' placeholder='Description'&gt;&lt;/textarea&gt; &lt;/div&gt; &lt;/div&gt; &lt;br /&gt; &lt;/fieldset&gt; Did you also want the CSS? It shows how the repeating section is split into 4 instances of CSS Grid, one for each row.
1617871553

Edited 1617871580
Finderski
Pro
Sheet Author
Compendium Curator
Sammy Silver said: Finderski said: It should also be noted that if the fields are only dependent on things in the same row Would you be willing to provide an example? Although the outputs my sheetworker stitches together serve to reference outside values, the text of the output is made entirely within the repeating section and sheetworker. Sure, using the one already done, just removing the requirement to re-check everything when the sheet is opened, you get this: on('change:repeating_psychicabilities:p_focus', function(eventInfo) { let p_focus = eventInfo.newValue || wp; let attr = {}; if (p_focus.length &gt; 3) { attr.repeating_psychicabilities_psy_ab_total_finder = `@{${p_focus}_total}`; attr.repeating_psychicabilities_psy_ab_unnat_finder = `@{${p_focus}_unnat}`; } else { attr.repeating_psychicabilities_psy_ab_total_finder = `@{${p_focus}Total}`; attr.repeating_psychicabilities_psy_ab_unnat_finder = `@{${p_focus.toUpperCase()}_unnat}`; } console.log(eventInfo.newValue, attr) setAttrs(attr); }); I didn't test this, because I don't have all the values necessary, but essentially, if you only need the value of P_focus from the repeating section, then eventInfo will give you the newValue that triggered the change (thus eliminating the need for getAttrs). And if you are simply manipulating other fields in the same row, you don't need the row ID for the setAttrs call, just those other field names, because the system will automatically use the row ID of the triggering field.