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

[sheet worker] getAttr and SetAttrs

August 14 (6 years ago)

Edited August 14 (6 years ago)
Mike W.
Pro
Sheet Author

I am having some trouble coding the following when a character sheet is opened (I am brand new to HTML and CSS and JavaScript)

I have an attribute named attr_modifier

It can have one of two values;
Either it  equals: ?{Modifier|0}
Or it equals: ?{Modifier|0} +?{Shock|0} +?{Reeling or Staggered|0} + ?{Off-Hand|0} + ?{Familiarity|0}

If it equals: ?{Modifier|0}, I need to change it to: [[?{Modifier|0}]]
If it equals: ?{Modifier|0} +?{Shock|0} +?{Reeling or Staggered|0} + ?{Off-Hand|0} + ?{Familiarity|0}, I need to change it to: [[?{Modifier|0}]] +[[?{Shock|0}]] +[[?{Reeling or Staggered|0}]] + [[?{Off-Hand|0}]] + [[?{Familiarity|0}]]

I know the code starts as;

on('sheet:opened', function() {

I started the rest of the code (but I know it is all wrong)

		getAttr([‘attr_modifier’], function(v){
if(v. attr_modifier)== ?{Modifier|0} {
setAttrs({attr_modifier})== [[?{Modifier|0}]];
}
if(v. attr_modifier)==?{Modifier|0} +?{Shock|0} +?{Reeling or Staggered|0} + ?{Off-Hand|0} + ?{Familiarity|0}{
setAttrs({attr_modifier})== [[?{Modifier|0}]] +[[?{Shock|0}]] + [[?{Reeling or Staggered|0}]] + [[?{Off-Hand|0}]] + [[?{Familiarity|0}]];
}
}

I really need some help here- Thanks.

August 14 (6 years ago)
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator

Well, doesn't help with your actual question, but why do you need this? It sounds like this attribute is either a select or radio. If you set the attribute like that, you're going to deselect whatever the user has selected. Why not just set the possible values of the attribute to be in inline roll format to begin with?

August 14 (6 years ago)

Edited August 14 (6 years ago)
Mike W.
Pro
Sheet Author
It is a radio. The reason I need this is I am changing the value in the selection. For those people who already have a value chosen, the new values do not match and thus their macro will not function properly unless they reelect. I am trying to do this for them automatically..
August 14 (6 years ago)

Edited August 14 (6 years ago)
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator

Ah, gotcha.

I'm back on my computer, so now I can actually show some code :). There's several issues with your code

getAttr([‘attr_modifier’], function(v){
if(v. attr_modifier)== ?{Modifier|0} {//Not sure if this is just copy paste error, but you've got a space between "v." and attr_modifier                                               //also, the "attr_" is not used when working with attributes, it simply tells the tabletop to make an attribute with the appropriate name                                               //and finally, your comparison is outside of your if declaration, should be "if(v.modifier==='?{Modifier|0}'){"                                               //You'll also note that I used === instead of ==. This is to avoid erroneous positives when the type of the variable is different.
setAttrs({attr_modifier})== [[?{Modifier|0}]];//setAttrs expects an object with key:value pairs where the key is the attribute name and the value is the attribute value. You're also attempting to do a comparison between the setAttrs and the value you want.
}
if(v. attr_modifier)==?{Modifier|0} +?{Shock|0} +?{Reeling or Staggered|0} + ?{Off-Hand|0} + ?{Familiarity|0}{
setAttrs({attr_modifier})== [[?{Modifier|0}]] +[[?{Shock|0}]] + [[?{Reeling or Staggered|0}]] + [[?{Off-Hand|0}]] + [[?{Familiarity|0}]];
}
}

You can also do this without needing the if statements. Here's how I'd do it, taking the corrections above into account:

getAttrs(['modifier'], function(v){
	const setObj = {};
	
	setObj.modifier = v.modifier.replace(/(^|[^\[])\?/g,'$1[[?').replace(/}([^\]]|$)/g,'}]]$1');
	setAttrs(setObj,{silent:true});
});


August 14 (6 years ago)
Mike W.
Pro
Sheet Author


Scott C. said:

Ah, gotcha.

I'm back on my computer, so now I can actually show some code :). There's several issues with your code

getAttr([‘attr_modifier’], function(v){
if(v. attr_modifier)== ?{Modifier|0} {//Not sure if this is just copy paste error, but you've got a space between "v." and attr_modifier                                               //also, the "attr_" is not used when working with attributes, it simply tells the tabletop to make an attribute with the appropriate name                                               //and finally, your comparison is outside of your if declaration, should be "if(v.modifier==='?{Modifier|0}'){"                                               //You'll also note that I used === instead of ==. This is to avoid erroneous positives when the type of the variable is different.
setAttrs({attr_modifier})== [[?{Modifier|0}]];//setAttrs expects an object with key:value pairs where the key is the attribute name and the value is the attribute value. You're also attempting to do a comparison between the setAttrs and the value you want.
}
if(v. attr_modifier)==?{Modifier|0} +?{Shock|0} +?{Reeling or Staggered|0} + ?{Off-Hand|0} + ?{Familiarity|0}{
setAttrs({attr_modifier})== [[?{Modifier|0}]] +[[?{Shock|0}]] + [[?{Reeling or Staggered|0}]] + [[?{Off-Hand|0}]] + [[?{Familiarity|0}]];
}
}

You can also do this without needing the if statements. Here's how I'd do it, taking the corrections above into account:

getAttrs(['modifier'], function(v){
	const setObj = {};
	
	setObj.modifier = v.modifier.replace(/(^|[^\[])\?/g,'$1[[?').replace(/}([^\]]|$)/g,'}]]$1');
	setAttrs(setObj,{silent:true});
});


Yeah mostly pasting errors and forgetting things, old age, life interruptions, etc, so I realize my code is terrible.

Yours is so much simpler and way above my pay grade and I do nto understand it at all but will try it out.




August 14 (6 years ago)

Edited August 14 (6 years ago)
Mike W.
Pro
Sheet Author

OK worked partially

for the ?{Modifier|0} to [[?{Modifier|0}]] alone it worked fine but

for the ?{Modifier|0} +?{Shock|0} + ?{Reeling or Staggered|0} + ?{Off-Hand|0} + ?{Familiarity|0} to [[?{Modifier|0}]] +[[?{Shock|0}]] + [[?{Reeling or Staggered|0}]] + [[?{Off-Hand|0}]] + [[?{Familiarity|0}]] it did not work (note sure what value it placed there as I cannot figure out your code)


August 14 (6 years ago)

Edited August 14 (6 years ago)
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator

Hmm, ok, what did it set the value to?

You could try this instead (this is actually a better way to do it anyways):

getAttrs(['modifier'], function(v){
	const setObj = {}; //make an empty object. I prefer making an object that will then be used for the setAttrs rather than manually assembling it.
	setObj.modifier = v.modifier.replace(/(^|[^\[])(\?{.+?})($|[^\]])/g,'$1[[$2]]$3'); //set the "modifier" property of the setObj to be equal to the value of modifier replacing the non inline roll version with the inline roll version
	setAttrs(setObj,{silent:true}); //Set the attributes and don't trigger sheetworker on('change:...') events from this change.
                                        //This is the same thing as doing setAttrs({modifier:'correct string'});
});

As for what this is, don't let the strange syntax between the forward slashes fool or scare you. This is just using regular expressions to match and replace specific strings. I like to use regexr.com to test regex patterns and learn more about them.

August 14 (6 years ago)
Mike W.
Pro
Sheet Author


Scott C. said:

Hmm, ok, what did it set the value to?

You could try this instead (this is actually a better way to do it anyways):

getAttrs(['modifier'], function(v){
	const setObj = {}; //make an empty object. I prefer making an object that will then be used for the setAttrs rather than manually assembling it.
	setObj.modifier = v.modifier.replace(/(^|[^\[])(?{.+?})($|[^\]])/g,'$1[[$2]]$3'); //set the "modifier" property of the setObj to be equal to the value of modifier replacing the non inline roll version with the inline roll version
	setAttrs(setObj,{silent:true}); //Set the attributes and don't trigger sheetworker on('change:...') events from this change.
                                        //This is the same thing as doing setAttrs({modifier:'correct string'});
});

As for what this is, don't let the strange syntax between the forward slashes fool or scare you. This is just using regular expressions to match and replace specific strings. I like to use regexr.com to test regex patterns and learn more about them.


I do not know what value it set from your first code.

Your second really has me confused but I will trust you on this.

August 14 (6 years ago)

Edited August 14 (6 years ago)
Mike W.
Pro
Sheet Author

Scott

I really appreciate your help but I am afraid that has made matter worse. Whatever the value it is setting the Modifier to, it does not match any of the Radio selections.

I realize your code is much more sophisticated then I can ever do but is there a way to to make t  more simpler and exact values that I can just type in? This also would help that if in he future I may have to change some of these names because of other modification in the pipe.


Opening  the console log I see this;

SyntaxError: Invalid regular expression: /(^|[^\[])(?{.+?})($|[^\]])/: Invalid group
    at Object.eval [as -LI9j5Bx0fp0Lmvc1UKH//false//0.010372578532258814] (eval at messageHandler (sheetsandboxworker.js?1534214581435:548), <anonymous>:21:33)
    at _fullfillAttrReq (sheetsandboxworker.js?1534214581435:523)
    at messageHandler (sheetsandboxworker.js?1534214581435:555)
sheetsandboxworker.js?1534214581435:581 SyntaxError: Invalid regular expression: /(^|[^\[])(?{.+?})($|[^\]])/: Invalid group
    at Object.eval [as -LI9j5Bx0fp0Lmvc1UKH//false//0.010372578532258814] (eval at messageHandler (sheetsandboxworker.js?1534214581435:548), <anonymous>:21:33)
    at _fullfillAttrReq (sheetsandboxworker.js?1534214581435:523)
    at messageHandler (sheetsandboxworker.js?1534214581435:555)
August 14 (6 years ago)

Edited August 14 (6 years ago)
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator

Just realized, I had an invalid pattern in that regex. Edited the code in the post to be correct.

So, let's break down what the regular expression is looking for. There are three capturing groups in the regex expression. A capturing group is just a subset of the pattern that will be returned as an individual result in the array of results and are denoted by parentheses wrapping. The groups are:

  1. (^|[^\[])
    1. This group looks for the beginning of the string (the ^ before the bar), or a character that is not an opening square bracket (the [^\[] )
  2. (\?{.+?})
    1. This group looks for a question mark (the \?, question marks have to be escaped like this because they have special meaning in regex), followed by an opening curly brace followed by 1 or more characters, ending at the first closing curly brace encountered (the question mark here tells the regex to match as few characters as possible)
  3. ($|[^\]])
    1. This group looks for the end of the string (the $) or a non closing square bracket (the [^\]] ).

Taken altogether these will look for a roll query that is not wrapped in inline brackets.

Then there is the second argument of the replace function: "$1[[$2]]$3". This is a string that tells the replace function to take capturing group 1 and put it at the start of the string followed by two opening square brackets. Then follow this with capture group 2 and two closing square brackets. Finally put capture group 3 at the end.

It may be easier to see how this all works by seeing the pattern in action.

August 14 (6 years ago)

Edited August 14 (6 years ago)
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator

Mike W. said:

Scott

I really appreciate your help but I am afraid that has made matter worse. Whatever the value it is setting the Modifier to, it does not match any of the Radio selections.

I realize your code is much more sophisticated then I can ever do but is there a way to to make t  more simpler and exact values that I can just type in? This also would help that if in he future I may have to change some of these names because of other modification in the pipe.


Opening  the console log I see this;

SyntaxError: Invalid regular expression: /(^|[^\[])(?{.+?})($|[^\]])/: Invalid group
    at Object.eval [as -LI9j5Bx0fp0Lmvc1UKH//false//0.010372578532258814] (eval at messageHandler (sheetsandboxworker.js?1534214581435:548), <anonymous>:21:33)
    at _fullfillAttrReq (sheetsandboxworker.js?1534214581435:523)
    at messageHandler (sheetsandboxworker.js?1534214581435:555)
sheetsandboxworker.js?1534214581435:581 SyntaxError: Invalid regular expression: /(^|[^\[])(?{.+?})($|[^\]])/: Invalid group
    at Object.eval [as -LI9j5Bx0fp0Lmvc1UKH//false//0.010372578532258814] (eval at messageHandler (sheetsandboxworker.js?1534214581435:548), <anonymous>:21:33)
    at _fullfillAttrReq (sheetsandboxworker.js?1534214581435:523)
    at messageHandler (sheetsandboxworker.js?1534214581435:555)

Sorry, didn't get my post done soon enough. I had made an error in the regex pattern in the code. See my post right above this.

Edit:

You could certainly do this with if's:

getAttrs(['modifier'], function(v){
	const setObj = {};
        if(v.modifier==='?{Modifier|0}'){
            setObj.modifier = '[[?{Modifier|0}]]'         }else if(v.modifier==='?{Modifier|0} +?{Shock|0} + ?{Reeling or Staggered|0} + ?{Off-Hand|0} + ?{Familiarity|0}'){
            setObj.modifier = '[[?{Modifier|0}]] +[[?{Shock|0}]] + [[?{Reeling or Staggered|0}]] + [[?{Off-Hand|0}]] + [[?{Familiarity|0}]]'         } setAttrs(setObj,{silent:true}); });
August 14 (6 years ago)
Mike W.
Pro
Sheet Author

I figures out why the multiple inline entries we not working

there was a space missing from +?{Shock|0}, should have been + ?{Shock|0}, that was why the strings were not matching.

Of all things.

Scott again thank you so very very much for your time. All is working now as intended.

Mike

August 14 (6 years ago)
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator

Excellent to hear, and you're welcome. Just passing on what the community has taught me. Pay it forward!