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

Need help altering values through a select input (New to HTML & Javascript)

August 04 (6 years ago)

Edited August 04 (6 years ago)

I am currently working on a custom character sheet and have run into a bit of a wall. I've been able to hurdle most, but this one I just can't seem to get around. On my character sheet, I have a <select> that allows the player to choose what type of soldier they have recruited. Beneath this <select>, I have a table that is filled with number inputs that correspond to stats of the soldier. As of now, you have to manually adjust each stat to correspond to what that soldier has.

So what I'd like to accomplish, is that when the player chooses an option from the soldier <select>, that it will adjust all the values within the number inputs within the table so they don't have to do this manually. Additionally, I'd like this to update if they ever switched their soldiers around on their sheet.

I've been digging into this everywhere and I really just can't figure out how it can be done, whether it be macros or javascripting. Any help would be appreciated.

August 04 (6 years ago)
GiGs
Pro
Sheet Author
API Scripter

This sounds like something you;d do with a sheet worker (javascript), but to be sure we'd have to see the html for the select and inputs, as well as the table of data for the soldier.

August 04 (6 years ago)
Finderski
Pro
Sheet Author
Compendium Curator

The other question would be, do those stats ever change for a given soldier? I realize you'd want them to change if the solder type changed, but say I select Solder 1 from the drop down, would Soldier 1's stats every change?

August 04 (6 years ago)

Edited August 05 (6 years ago)

So here's the html for the select inputs & the table beneath it. This is only one section of it, because you can have up to 8 soldiers. But the html is the same for each soldier other than the fact that the names of attr change to s2, s3, s4, etc. And to answer your question Finderski, the soldier's stats are permanent. However, there are a few spells and items that can give them a boost from game to game, but I figured the players could just manually adjust the base stats if they were updated to their defaults.

<div class="sheet-tab-content sheet-tab3">

    <p></p>

    <span <label><b> Soldier:</b> <input style="border: 1px solid black" type="text" placeholder="Name" name="attr_sname" /></label>

    <span <label><b>Type:</b>

    <select name="attr_s1" style="border: 1px solid black">

        <option name="attr_no" value="ns">No Soldier</option>

        <option name="attr_wh" value="wh">Warhound</option>

        <option name="attr_thug" value="thug">Thug</option>

        <option name="attr_thief" value="thief">Thief</option>

        <option name="attr_ar" value="ar">Archer</option>

        <option name="attr_xb" value="xb">Crossbowman</option>

        <option name="attr_inf" value="inf">Infantryman</option>

        <option name="attr_tr" value="tr">Tracker</option>

        <option name="attr_maa" value="maa">Man-at-Arms</option>

        <option name="attr_th" value="th">Treasure Hunter</option>

        <option name="attr_kn" value="kn">Knight</option>

        <option name="attr_te" value="te">Templar</option>

        <option name="attr_ra" value="ra">Ranger</option>

        <option name="attr_ba" value="ba">Barbarian</option>

        <option name="attr_ap" value="ap">Apothecary</option>

        <option name="attr_mm" value="mm">Marksman</option>

    </select></label>

    <span <label><b> Item:</b> <input style="border: 1px solid black" type="text" placeholder="Standard Equipment +1" name="attr_appname" /></label>

    <p></p>

    <table style="background-color: LightGray;width: 90%;margin: 1 auto;border: 2px solid black">

        <thead>

            <tr>

                <th> Move </th>

                <th> Fight </th>

                <th> Shoot </th>

                <th> Armor </th>

                <th> Will </th>

                <th> Max HP </th>

                <th> HP </th>

            </tr>

        </thead>

        <tbody>

            <tr>

                <td> <input type="number" name="attr_s1m" value="0"></td>

                <td> <input type="number" name="attr_s1f" value="0"></td>

                <td> <input type="number" name="attr_s1s" value="0"></td>

                <td> <input type="number" name="attr_s1a" value="0"></td>

                <td> <input type="number" name="attr_s1w" value="0"></td>

                <td> <input type="number" name="attr_ms1hp" value="0"></td>

                <td> <input type="number" name="attr_s1hp" value="0"></td>

            </tr>

        </tbody>

    </table>

August 04 (6 years ago)

Edited August 04 (6 years ago)
GiGs
Pro
Sheet Author
API Scripter

Add this to the bottom of your sheet's html page

<script type="text/worker">
const soldier_stats = {
no: {m: 3, f: 7, s: 1, a: 0, w: 1, hp_max: 12, hp: 12},
wh: { /* --- repeat table as above on same format */ },
};
const soldier_cells = ['s1', 's2', 's3', ]; // add in as many as you need.
soldier_cells.forEach(soldier => {
on(`change:${soldier}`, function () {
getAttrs(['soldier'], function (values) {
const which = values[`${soldier}_type`];
const stats = soldier_stats[which];
const settings = {};
Object.keys(stats).forEach(key => {
settings[`${soldier}${key}`] = stats[key];
});
setAttrs(settings);
});
});
});
</script>

You'll need to edit two sections. First: 

    const soldier_stats = {
no: {m: 3, f: 7, s: 1, a: 0, w: 1, hp_max: 12, hp: 12},
wh: { /* --- repeat table as above on same format */ },
};

add a row for each soldier type, in EXACTLY the format above. The first bit (no, wh, etc) should be spelled exactly the same as the attribute on the character sheet.

The stats (m, f, etc) should be exactly the same as the attribute names, with the s1 removed. So s1w becomes w. 

One important change here: change the max hp attribute names in the html, to s1hp_max, s2hp_max, etc. 

Finally, this line:

    const soldier_cells = ['s1', 's2', 's3', ]; 

add s4, s5, etc like this, for each soldier you have. if you have 8 soldiers, add s4 to s8.

And that's it. Reload your campaign and enjoy. If you have issues, post back the complete code you are using between the script start and end.


I use this technique all the time for filling in preset weapons, mounts, and the like.

August 04 (6 years ago)
GiGs
Pro
Sheet Author
API Scripter

I just noticed there's an error in your select code

This

<select name="attr_s1" style="border: 1px solid black">

        <option name="attr_no" value="ns">No Soldier</option>

        <option name="attr_wh" value="wh">Warhound</option>

should be

<select name="attr_s1" style="border: 1px solid black">
        <option value="ns">No Soldier</option>
        <option value="wh">Warhound</option>

You dont set a name on each option. The name is set by the select line, and the option value is what gets saved in that name.


August 04 (6 years ago)

Edited August 05 (6 years ago)

Alright, I still seem to be having issues. I put your code in exactly but it doesn't want to change the values of the stats for some reason. Side note, how do you paste the code as you have it so it's not one big ball of text? Anyways, here's the code:

August 04 (6 years ago)
GiGs
Pro
Sheet Author
API Scripter

I had a couple of typos in the code, oops. Here's the corrected code:

const soldier_stats = {
        no: {m: 0, f: 0, s: 0, a: 0, w: 0, hp_max: 0, hp: 0},
        wh: {m: 8, f: 1, s: 0, a: 10, w: 2, hp_max: 8, hp: 8},
        thug: {m: 6, f: 2, s: 0, a: 10, w: -1, hp_max: 10, hp: 10},
        thief: {m: 7, f: 1, s: 0, a: 10, w: 0, hp_max: 10, hp: 10},
        ar: {m: 6, f: 2, s: 2, a: 11, w: 0, hp_max: 10, hp: 10},
        xb: {m: 6, f: 2, s: 2, a: 11, w: 0, hp_max: 10, hp: 10},
        inf: {m: 6, f: 3, s: 0, a: 11, w: 0, hp_max: 10, hp: 10},
        tr: {m: 7, f: 2, s: 2, a: 11, w: 1, hp_max: 12, hp: 12},
        maa: {m: 6, f: 3, s: 0, a: 12, w: 1, hp_max: 12, hp: 12},
        th: {m: 7, f: 4, s: 0, a: 11, w: 2, hp_max: 12, hp: 12},
        kn: {m: 5, f: 4, s: 0, a: 13, w: 1, hp_max: 12, hp: 12},
        te: {m: 5, f: 4, s: 0, a: 12, w: 1, hp_max: 12, hp: 12},
        ra: {m: 7, f: 2, s: 2, a: 11, w: 2, hp_max: 12, hp: 12},
        ba: {m: 6, f: 4, s: 0, a: 10, w: 3, hp_max: 14, hp: 14},
        ap: {m: 6, f: 0, s: 0, a: 10, w: 0, hp_max: 12, hp: 12},
        mm: {m: 5, f: 2, s: 3, a: 12, w: 1, hp_max: 12, hp: 12},
    };

    const soldier_cells = ['s1', 's2', 's3', 's4', 's5', 's6', 's7', 's8' ]; // add in as many as you need.

    soldier_cells.forEach(soldier => {
        on(`change:${soldier}`, function () {
            getAttrs([soldier], function (values) {
                const which = values[soldier];
                const stats = soldier_stats[which];
                const settings = {};
                Object.keys(stats).forEach(key => {
                    settings[`${soldier}${key}`] = stats[key];
                });
                setAttrs(settings);
            });
        });
    });

To enter code blocks like this, look at the formatting bar at the top of the edit window. On the far left, is a dropdown button (just to the left of B I U), and you can select Code from that drop down.


August 05 (6 years ago)

Edited August 05 (6 years ago)
It works! Thanks so much! I am curious though, there are some other areas of the character sheet that I'd like things similar to this. Is there anything I should know about the code you provided? Can I simply copy/paste it again and tweak it to make it work or is this something that is too specific? 
August 05 (6 years ago)
GiGs
Pro
Sheet Author
API Scripter

It's hard to answer your question about things you should know. If there's anything specific you'd like explaining, I can answer questions. I also have a wiki page talking a bit about this kind of construction: Universal Sheet Workers.

You can copy and reuse the code, tweaking it as needed. Just make sure to change the outer variable names (soldier_cells and soldier_stats), which need to be unique.

The best thing to do is to try it, see if it works, and if not, come back and ask for help. That's the best way to learn. Though this is javascript, so there's plenty of online sites that help too.

Something very basic: if you create any more sheet workers, they have to go inside that script block (the two script tags start and end the script region, where roll20 will recognise this kind of javascript).  Don't create extra script blocks, it sometimes causes problems-  just use the one.


August 05 (6 years ago)

Edited August 05 (6 years ago)

Alright, so I've been tinkering with the sheet all morning thinking I was on the right track only to find that I broke what you helped me get working. I was able to fix that though by basically undoing what I tried to do, however that means I've met another wall. The thing I'm trying to accomplish is similar to what you helped me with earlier (which is why I thought I could tinker with it) but different enough to where I still can't wrap my head around it.

Basically, I have a <select> list where you choose a school of magic, and on a seperate page I have 10 tables with 8 spells in each of them. The 10 tables correspond to the 10 available schools of magic, but based off of what 1 school you chose, it adjusts all the other spells within the 9 other schools. So my question is, how can I make it so when you select a school from the dropdown, it will modify each schools' spells differently? Essentially, it would add 2 to the base scores of the spells for 3 of the schools, add 4 to the base scores of the spells for 5 of the schools, and add 6 to the base scores of the spells of the remaining school. 

I hope I'm being clear enough on what I'm trying to do, but of course I'm happy to explain more if it doesn't make sense. I just want to have it where you select an option from the dropdown, and then adjust all the spells within a table for the 9 options you didn't pick.

August 05 (6 years ago)
GiGs
Pro
Sheet Author
API Scripter

I'd need details on the attribute names, and what the tables actually consist of. 

If you;re tinkering, you shouldnt break the code I already gave you. Leave that untouched, and make a new copy of the code and change the names it uses.

If you post the code you attempted, we might be able to see what went wrong and how to tweak it to make it work.

August 05 (6 years ago)

Edited August 05 (6 years ago)

I tried just copying/pasting what you gave me just slightly below that block, but maybe I pasted it in the wrong spot? Either way, here's the dropdown that I want to have trigger the altering of the other values:

<span <label><b>School:</b>
    <select name="attr_school" style="border: 1px solid black">
        <option value="pas">Pick a school</option>
        <option value="chron">Chronomancer</option>
        <option value="elem">Elementalist</option>
        <option value="ench">Enchanter</option>
        <option value="illu">Illusionist</option>
        <option value="necro">Necromancer</option>
        <option value="sigi">Sigilist</option>
        <option value="sooth">Soothsayer</option>
        <option value="summ">Summoner</option>
        <option value="thau">Thaumaturge</option>
        <option value="wit">Witch</option>
    </select></label>

And then here's one of the code blocks for the spell tables:

<table style="float: left;width: 32%;margin-right: 2px;margin-top: 5px;border: 2px solid black">
        <thead style="background-color: #5DB5C3">
            <tr>
                <th style="text-align: center;border: 2px solid black"><b> Chronomancer </b></th>
            </tr>
        <tbody style="background-color: #D5ECEB;border: 2px solid black">
            <tr style="border: 2px solid black">
                <td> Crumble <input style="float: right" type="checkbox"><input style="width: 40px;height: 17px;float: right" type="number" name="attr_c1a" value="0"></td>
            <tr style="border: 2px solid black">
                <td> Decay <input style="float: right" type="checkbox"><input style="width: 40px;height: 17px;float: right" type="number" name="attr_c1b" value="0"></td>
            <tr style="border: 2px solid black">
                <td> Fast Act <input style="float: right" type="checkbox"><input style="width: 40px;height: 17px;float: right" type="number" name="attr_c1c" value="0"></td>
            <tr style="border: 2px solid black">
                <td> Fleet Feet <input style="float: right" type="checkbox"><input style="width: 40px;height: 17px;float: right" type="number" name="attr_c1d" value="0"></td>
            <tr style="border: 2px solid black">
                <td> Petrify <input style="float: right" type="checkbox"><input style="width: 40px;height: 17px;float: right" type="number" name="attr_c1e" value="0"></td>
            <tr style="border: 2px solid black">
                <td> Slow <input style="float: right" type="checkbox"><input style="width: 40px;height: 17px;float: right" type="number" name="attr_c1f" value="0"></td>
            <tr style="border: 2px solid black">
                <td> Time Store <input style="float: right" type="checkbox"><input style="width: 40px;height: 17px;float: right" type="number" name="attr_c1g" value="0"></td>
            <tr style="border: 2px solid black">
                <td> Time Walk <input style="float: right" type="checkbox"><input style="width: 40px;height: 17px;float: right" type="number" name="attr_c1h" value="0"></td>
            </tr>
        </tbody>
        </thead>

The other spell tables' attributes are just named "c2a" - "c2h" , "c3a" - "c3h" , etc.

August 05 (6 years ago)
GiGs
Pro
Sheet Author
API Scripter

I wont get a chance to look at this till tomorrow, but whatever you copied, should go inside the script block. In case of ambiguity, it should be after the

<script type="text/worker">

line and before the

</script>

line