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

How to check/uncheck a checkbox by changing some other element using sheet workers

September 18 (5 years ago)

I feel like this is really simple, but I'm stumped. Title pretty much says it all. I want to have a checkbox get checked when I make any change to some other element. How do I do this? Am I changing the values attribute? The checked attribute? What is it? 

September 18 (5 years ago)

Edited September 18 (5 years ago)
GiGs
Pro
Sheet Author
API Scripter

Can you be more specific? What specific changes would trigger the checkbox to be checked? Is it responding to just one other element, or a group of them?


As a guidelines, if you want the checkbox to get checked when you change some other element like an input or select, you need the following:

  • Each element needs a proper name (name="attr_something")
  • Need to define what changes cause the checkbox to be checked
  • Create a sheet worker to monitor the relevant attributes, and it will update the checkbox using the rule defined above

Also just as important, you want to consider: when should the checkbox become unchecked. This subtlety makes it a more complex problem than it might appear at first. Which is one of the reasons we need specifics.


September 18 (5 years ago)

Edited September 18 (5 years ago)
GiGs
Pro
Sheet Author
API Scripter

Here are three variants, that work for different cases.

Let's say you have an attribute named "hp", which tracks hitpoints.

And you have a checkbox input named "wounded", which gets checked when you have wounds.

Important: the checkbox needs value="1".


You might try this very simple sheet worker:

on('change:hp' function(){
    setAttrs({wounded:1});
});

Whenever hit point changes, the wounded checkbox will check. This will work for some cases, but not for hit points. The problem is that restoring HP to max is a change, and will cause the wounded checkbox to be checked. 

Here's an alternative, using eventInfo.

on('change:hp' function(eventInfo){
    let newScore = +eventInfo.newValue||0;
    let oldScore = +eventInfo.previousValue||0;
    if(newScore < oldScore) setAttrs({wounded:1});
});

whenever hp changes, this will grab the new HP value, and compare it to the previous value - the value it had before this change happened.

If HP is dropping, the wounded box will be marked. If its rising, it wont.

This will work for some situations, but you might want it to be automatically unmarked when HP restore to full.

For that you need to set a hp_max attribute, which doesnt automatically exist. You define that in the same way as hp, and once defined will be available on a token bar. You can then use

on('change:hp change:hp_max' function(eventInfo){
    getAttrs(['hp','hp_max'], function(values) {
        let current = +values.hp||0;
        let max = +values.hp_max||0;
        let wounded = (current < max) ? 1: 0;
        setAttrs({
            wounded: wounded
        });
    });
});

This will check the wounded checkbox if hp are less than max, and remove the checkbox if hp equal or exceeds hp_max.

You could also modify it so that hp cannot exceed max. That's left as an exercise for the reader :)

This:

        let wounded = (current < max) ? 1: 0;

Is the same as:

        let wounded = 0;
        if (current < max) wounded = 1;




September 18 (5 years ago)

The first example is what I was going with and all of them are nice to know. To give a little more specifics, I have a repeating section and a bunch of checkboxes that are going to be hidden and will serve some other purpose I'm not going to get into here. I need each checkbox to correspond to a specific row in the repeating section. That gets to my second question; how do I use a specific repeating section index in a change statement? 

September 18 (5 years ago)
GiGs
Pro
Sheet Author
API Scripter

for repeating sections, you just include the repeating section name before the attribute name. the syntax is different on the change line to the others. So that would look like

on('change:repeating_sectionname:hp' function(){
    setAttrs({repeating_sectionname_wounded:1});
});

The more complex one with a few more examples would be

on('change:repeating_sectionname:hp change:repeating_sectionname:hp_max' function(eventInfo){
    getAttrs(['repeating_sectionname_hp','repeating_sectionname_hp_max'], function(values) {
        let current = +values.repeating_sectionname_hp||0;
        let max = +values.repeating_sectionname_hp_max||0;
        let wounded = (current < max) ? 1: 0;
        setAttrs({
            repeating_sectionname_wounded: wounded
        });
    });
});


September 18 (5 years ago)

The checkboxes are outside the repeating section due to the fact that I need each one to have a unique class name so I can use them to make a another hidden element visible since sheet worker can't do that apparently. This is what I have for the code if it helps.

on("change:repeating_body_$0", function () {
        setAttrs ({
            optVisCheck0: 1
        });     
    });
September 18 (5 years ago)

Edited September 18 (5 years ago)
GiGs
Pro
Sheet Author
API Scripter

css styles depend on the class name, not the attribute name. You can have css responding to things inside repeating sections.

You cant do this:

change:repeating_body_$0

If you want the outer checkbox to respond to any attribute inside the repeating section, that owuld look like

on("change:repeating_body", function () {
        setAttrs ({
            optVisCheck0: 1
        });     
    });

You almost certainly don't want that.

If you give all the interactions, with specific attribute names, I can show you the sheet worker you need. I cant give the code without that - I can't guess your attribute names, or the way you have the sheet set up. Be specific. List every check box's attributes, and every attribute on the repeating section that triggers them.

September 18 (5 years ago)

Checkbox html:

<input type="checkbox" name="attr_optVisCheck0" class="sheet-optVisCheckClass0" value="1">
<input type="checkbox" name="attr_optVisCheck1" class="sheet-optVisCheckClass1" value="1">
<input type="checkbox" name="attr_optVisCheck2" class="sheet-optVisCheckClass2" value="1">
<input type="checkbox" name="attr_optVisCheck3" class="sheet-optVisCheckClass3" value="1">
<input type="checkbox" name="attr_optVisCheck4" class="sheet-optVisCheckClass4" value="1">

The final count of checkboxes is 100 but I’ll just put 5 for the example.

Relevant repeating section html:

<fieldset class="repeating_body">

    <input type="text" name="attr_bodySegmentName">

</fieldset>

There’s more to the repeating section than just that input but for the sake of simplicity I’ll just put that. Also, if needed the bodySegmentName can be the thing being changed to activate the checkbox instead of just anything in the repeating section.

Changing repeating_body_$0_bodySegmentName (or however that’s supposed to look) should check optVisCheck0, changing repeating_body_$1_bodySegmentName should check optVisCheck1 and so on.

September 18 (5 years ago)
GiGs
Pro
Sheet Author
API Scripter

You have a problem here, because rows in a repeating section can be reordered. Each row has a unique id (you cant use the $0 syntax in code, it's purely for macros), so if someone reorders the rows, the ordering of the checkboxes will be wrong.

Also if you have a fixed total of 100 rows, you are better off not using a repeating section, just create the 100 rows. If you dont have a fixed total of rows, you dont need 100 checkboxes.

Can you describe the purpose of these checkboxes? I may be able to suggest a more practical solution.



September 18 (5 years ago)

I’ll do the best I can in describing.

I have a repeating section that the player is supposed to fill with body segments of their character. I also have a repeating section that is for armor the player has. Among other info in the armor repeating section is a box for the player to select which of the segments they listed in the body segment repeating section apply to that armor piece.

I was going to use a <select> element to make a dropdown menu and add <option>s via how many rows in the body segment repeating section but I can’t create elements with sheet workers. Also, if I want to select multiple body segments I would have to hold ctrl and select the ones I want and that seems kind of stupid. So I opted to make my own dropdown menu using text inputs and checkboxes.

Theoretically, the max number of body segments a character could have is 100 so I would have to make 100 blank text inputs with corresponding checkboxes and hide all of them until they show up in the body segment repeating section.

This is where the checkboxes I was asking about come in. Sheet workers apparently can’t change css but a checkbox can. That means I need to make 100 checkboxes, one for every possible row in the body segment repeating section. Upon naming a body segment, the corresponding checkbox is ticked. Since every checkbox will have a unique class name, I can us css to change the visibility of the corresponding segment option in the armor repeating section and its corresponding checkbox.

The checkbox we are working with would also aid in knowing when to copy the name of the body segment from the body segment repeating section to the armor repeating section.

September 18 (5 years ago)

Here's a visual I made to wrap my head around it if it helps

September 19 (5 years ago)

Edited September 19 (5 years ago)
GiGs
Pro
Sheet Author
API Scripter

If you use the same repeating section name for your armour and body segments sections, then when you create a row in one of them, a matching row will become visible in the other section, letting players create a body segment in one, and add its armour in the other.

It will look like two repeating sections to the player, but under the hood it will actually be the same repeating section. The attribute names you put in each will exist in both (because they are both the same section) but will only appear in their defined section.

You can exploit that to get the behaviour you want without having to create 100 checkboxes. 

September 19 (5 years ago)

I don't know if I don't understand what you're trying to say or you misunderstood me. The repeating body and repeating armor have other elements in each that are not in the other. The name is the only thing that would carry over. Does you're Idea still work in this case? If so how?

September 19 (5 years ago)

Edited September 19 (5 years ago)
GiGs
Pro
Sheet Author
API Scripter

Yes, it still works. By using the same name, you have just one repeating section.

Imagine it like this. That one section has all the attributes in both your armour section and your body section.

But it doesnt show them all. Only the attributes you explicitly create in your code are displayed. The others are hidden. They do exist, they just don't get displayed.

In the body section, you show the body related attributes, and the armour ones are hidden. In the armour section, only the armour attributes are visible, the body ones are hidden.

It is a bit of a mindbender, but try it out.


September 19 (5 years ago)

That would require a lot of reworking of what I've already done and I would have to lump a few other repeating sections in there to get other things to work. If it's the only way I guess I have no choice, but is there a way to get the idea I had in mind to work?

September 19 (5 years ago)
GiGs
Pro
Sheet Author
API Scripter

Your way wouldnt work. Or at least would require a lot of retooling too. There's no way to associate each row of a repeating section with arbitrary checkboxes you have already created outside the section. Repeating sections have no permanent order (no concept of which is the first row, second row, etc) - users can change the order. So you have no way to reliably link a repeating section row with a specific checkbox, and users would have no way to tell which is which. So you'd likely need to add another 100 input boxes (one for each checkbox) to hold the row id that checkbox refers to, in order to maintain a link between the checkbox and the correct row. And another 100 input boxes to give a visible label for the cehckbox so users can tell which row of the repeating section it refers to. 

My suggestion involves mostly just removing stuff - you can get rid of 100 wasteful checkboxes, and have a much simpler design that just works - no extra coding needed.

September 19 (5 years ago)

I'll give it a shot and come back with any questions I have. Thanks for the help.

September 19 (5 years ago)

First problem I've run into is when I add a row for the body section it adds an armor piece as well and if I add a armor piece it adds a body section. Do you mean to have the repeating section with the same name nested inside of the armor repeating section? I didn't think that was a thing that could be done.

September 19 (5 years ago)
GiGs
Pro
Sheet Author
API Scripter

You cant nest repeating sections inside repeating sections. This is working as I intended. 

The way I'm envisioning it: the user adds a body section, and it creates a matching row in the armour section to hold the armour details.  Wouldnt that do what you need?

If you used CSS to hide the add/remove buttons in the armour section, players wouldnt be able to add armour sections, they'd just get one automatically every time they add a body section. 


September 19 (5 years ago)

unfortunately that's not what I'm going for. An armor piece can be for multiple body sections. Say you have a leather jacket. That could cover body sections named torso, right arm, and left arm.

September 19 (5 years ago)
GiGs
Pro
Sheet Author
API Scripter

In that case, you'll probably have to go with a non-automated approach. I;m not sure what you were using the checkboxes for, then?