So first, you don't need separate <script> tags. You can have multiple calls to on within a single sheet worker script. If I'm understanding the problem space correctly, this should get you close to what you want (code untested): const skills = [
'aethestics',
'composition',
'martial_arts_melee',
'social',
'courtesy', 'design',
'smithing',
// etc.
];
const repeatingSkillNames = []; const repeatingSkillApproaches = []; const ringMap = { '@{air}': 'Air', '@{earth}': 'Earth', '@{fire}': 'Fire',
'@{water}': 'Water',
'@{void}': 'Void', };
on('sheet:opened remove:repeating_skills', () => { // collect skills in repeating section repeatingSkillNames.splice(0, repeatingSkillNames.length); repeatingSkillApproaches.splice(0, repeatingSkillApproaches.length); TAS.repeating('skills') .each((row) => { repeatingSkillNames.push(`repeating_skills_${row.id}_name`); repeatingSkillApproaches.push(`repeating_skills_${row.id}_approach`); }) .execute(); });
on(`sheet:opened ${skills.map((s) => `change:${s}_approach`).join(' ')} change:repeating_skills:approach change:repeating_skills:name`, (e) => { if (e.sourceAttribute && /repeating_skills_.*/.test(e.sourceAttribute)) { // make sure the repeating item is tracked if it's new const source = e.sourceAttribute.substring(source.indexOf('_') + 1); const sourceId = source.substring(source.indexOf('_') + 1, source.lastIndexOf('_')); // sourceId is all lower-case, we need to find the correctly-cased value let trueSourceId; TAS.repeating('skills') .each((row) => { if (row.id.toLowerCase() === sourceId) { trueSourceId = row.id; } }) .execute(); const sourceName = `repeating_skills_${trueSourceId}_name`; const sourceApproach = `repeating_skills_${trueSourceId}_approach`; // if the changed repeating name/approach value isn't in the list, it's new if (repeatingSkillNames.indexOf(sourceName) < 0) { repeatingSkillNames.push(sourceName); } if (repeatingSkillApproaches.indexOf(sourceApproach) < 0) { repeatingSkillApproaches.push(sourceApproach); } } getAttrs(skills.map((s) => `${s}_approach`).concat(repeatingSkills, repeatingSkillApproaches), (values) => { const attrs = {}; _.each(skills, (skillName) { // <skill>_approach_selected for non-repeating skills attrs[`${skillName}_approach_selected`] = ringMap[values[`${skillName}_approach`]] || 'Air'; }); _.each(repeatingSkills, (skillAttrName) { const skillName = values[skillAttrName]; // name of repeating skill const rowId = skillAttrName.substring( // row of repeating skill skillAttrName.indexOf('_', skillAttrName.indexOf('_') + 1) + 1, skillAttrName.lastIndexOf('_')); const skillAttrApproach = repeatingSkillApproached.find( // approach attribute in the same row (a) => a.substring(a.indexOf('_', a.indexOf('_') + 1) + 1, a.lastIndexOf('_')) === rowId); attrs[`${skillName}_approach_selected`] = ringMap[values[skillAttrApproach]] || 'Air'; }); }); }); The above code will leave orphaned attributes when you change a repeating skill's name. For example, if you create skill "Piracy" the script will create @{Piracy_approach_selected} (with the value "Air" or whatever). If you later change the name of the attribute to "Sailing", the script will create @{Sailing_approach_selected}, but won't delete @{Piracy_approach_selected}. It will also create @{_approach_selected} if you change the approach selection before setting the repeating skill's name.