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

Repeating sections

1484917878
Laurent
Pro
Sheet Author
API Scripter
Hi. I have some issues with repeating sections in worksheet. From the API, is there a way to get the number of elements in a repeating section (other that reading them in order until it fails)? Also, I noticed that the numbering of the repeating sections does not match the order on the sheet, or even the order of creation of the items. Is that expected?
1484919515
The Aaron
Pro
API Scripter
Here is a series of messages where we talked about repeating sections that might clear that all up: &nbsp;<a href="https://app.roll20.net/forum/permalink/4483678/" rel="nofollow">https://app.roll20.net/forum/permalink/4483678/</a>
1484920181

Edited 1484920242
Jakob
Sheet Author
API Scripter
Okay, so I've struggled a bit with this issue recently, so I can maybe offer a bit of insight. 1) Not as far as I know. What I do in ChatSetAttr is I collect all attributes in a given section, then I extract their rowid via regexp and eliminate duplicates. This gives me a list of all rows/rowids in that section, ordered by creation date . (EDIT: thinking about it, that is substantially different than reading until it fails). 2) If the elements of that section have ever been reordered , the character will have a _reporder_prefix attribute (e.g. _reporder_repeating_attack), whose current value is a comma-separated list of rowids. However, this need not be up-to-date, in fact it is only up-to-date with the last reordering. Any repeating sections deleted after the last reordering will still be in that list, and sections added afterwards will not be in that list. That's enough to reconstruct the real order: first, eliminate any rowids from the list that do not exist anymore, and then tack on newly-added sections at the end. I achieve that with code that looks like this: // repRowIds[charid][prefix] contains all actually-existing rowids for the section, ordered by creation date // repOrders[charid][prefix] contains the value of _reporder_prefix, split along commata repRowIds[charid][prefix] = _.chain(repOrders[charid][prefix]) .intersection(repRowIds[charid][prefix]) // get rid of deleted rows .union(repRowIds[charid][prefix]) // add new rows at the end in order of creation .value();
1484920770
The Aaron
Pro
API Scripter
Nice Jakob!
1484922358
Laurent
Pro
Sheet Author
API Scripter
Thanks for the insights!
1485288439

Edited 1485290833
The Aaron
Pro
API Scripter
I finally had a chance to dig into this. &nbsp;Here's a function I just wrote that will handle repeating_ lookups automatically for a given character and a name like 'repeating_groupname_$0_fieldname': &nbsp; &nbsp; var attrLookup = function(character,name){ &nbsp; &nbsp; &nbsp; &nbsp; let match=name.match(/^(repeating_.*)_\$(\d+)_.*$/); &nbsp; &nbsp; &nbsp; &nbsp; if(match){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let index=match[2], &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; attrMatcher=new RegExp(`^${name.replace(/_\$\d+_/,'_([-\\da-zA-Z]+)_')}$`), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; createOrderKeys=[], &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; attrs=_.chain(findObjs({type:'attribute', characterid:character.id})) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .map((a)=&gt;{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return {attr:a,match:a.get('name').match(attrMatcher)}; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .filter((o)=&gt;o.match) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .each((o)=&gt;createOrderKeys.push(o.match[1])) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .reduce((m,o)=&gt;{ m[o.match[1]]=o.attr; return m;},{}) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .value(), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sortOrderKeys = _.chain( ((findObjs({ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; type:'attribute', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; characterid:character.id, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name: `_reporder_${match[1]}` &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; })[0]||{get:_.noop}).get('current') || '' ).split(/\s*,\s*/)) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .intersection(createOrderKeys) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .union(createOrderKeys) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .value(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(index&lt;sortOrderKeys.length && _.has(attrs,sortOrderKeys[index])){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return attrs[sortOrderKeys[index]]; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return findObjs({ type:'attribute', characterid:character.id, name: name})[0]; &nbsp; &nbsp; }; Called in the code like: var character; // get somewhere var attrname; // get somewhere var attribute = attrLookup(character,attrname); If the name isn't an indexed repeating attribute name, it will perform the simple lookup. Big thanks to Jakob for spelling out the steps!
1485332583
Jakob
Sheet Author
API Scripter
The Aaron said: Big thanks to Jakob for spelling out the steps! Glad I could help! One suggestion: you might want to make it an option to perform a case-insensitive attribute lookup. And afterwards, it should probably go into the wiki cookbook or something similar :).
1485351996
The Aaron
Pro
API Scripter
Great point! (And into the cookbook is my intent once it's vetted with comments like that! &nbsp;:) )