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

Combine a bunch of on change events

1624307985

Edited 1624308112
.Hell
Sheet Author
Hey, I got a bunch of very similar on change sheet workers I would like to combine. They look like this: on( "change:skillattr56" , function () { getAttrs([ "skillattr56" ], function (value) { setAttrs({ skillattr_name56: value.skillattr56+ "_name}" , skillattr_value56: value.skillattr56+ "_total}" }); }); }); on( "change:skillattr57" , function () { getAttrs([ "skillattr57" ], function (value) { setAttrs({ skillattr_name57: value.skillattr57+ "_name}" , skillattr_value57: value.skillattr57+ "_total}" }); }); }); The only difference is the number of the attributes. I would really like to combine all of them to a single one which can act upon the number
The simplest way to do this would be something like: const skillList = Array.from(Array(58).keys()); // create an array of numbers from 0 to 57 for (const skill in skillList) { // select each item in skillList as const skill                 on( `change:skillattr${skill}` , function () { // use template literal to append skill value to on change.         ... do sheetworkers here ...           }); } You can use the same template literal syntax to do the same for the content of your sheetworker, too.
1624317592

Edited 1624318518
GiGs
Pro
Sheet Author
API Scripter
Firstly, If you're creating a long list of attributes where players fill in name and value, you might be better served by looking into repeating sections. The sheet worker needed for them would be very simple, and you only need create the HTML for one set of attributes not all 56 or 57 of them. But assuming you aren't using a repeating section, and we need to build a sheet worker for each linked set of attributes: Firstly, I assume you haven't tested the sheet workers you have there? Because the syntax for them is wrong, and won't work as listed. Here's what one of them should look like:    on ( "change:skillattr56_name change:skillattr56_total" ,  function  () {      getAttrs ([ "skillattr56_name" ,  "skillattr56_total" ],  function  ( value ) {        setAttrs ({          skillattr_name56 :   value . skillattr56_name ,          skillattr_value56 :   value . skillattr56_total       });     });   }); Seeing that makes me wonder what exactly you are doing - it looks like you are just copying the attributes from one place to another, and I'm wondering if you really need to do this. I'd like to see the HTML for this section of the sheet , because there is probably a better way to do this. But if this is really what you need, the most efficient way will be to use eventInfo to identify which attribute triggered, and update its corresponding value. Here's a quick-and-dirty method, with no error checking.    const   skillattrs  = [ 'skillattr56' ,  'skillattr57' ];    const   skillattrsArray  =  skillattrs . reduce (( arr ,  item )  =>  [... arr ,  ` ${ item } _name` ,  ` ${ item } _total` ], []); const   skillattrsChanges  =  skillattrsArray . reduce (( changes ,  item )  =>   ` ${ changes  ?  ` ${ changes }  `  :  '' } change: ${ item } ` ,  '' );    on ( skillattrsChanges ,  function  ( eventInfo ) {      getAttrs ( skillattrsArray ,  function  ( value ) {        const   attname  =  eventInfo . sourceAttribute ;        const   attvalue  =  eventInfo . newValue ;        const   parts  =  attname . split ( '_' );        const   num  =  parts [ 0 ]. replace ( 'skillattr' ,  '' );        const   which  =  parts [ 1 ] ===  'total'  ?  'value'  :  'name' ;        setAttrs ({          [ `skillattr_ ${ which }${ num } ` ]:   attvalue       });     });   }); If you haven't supplied the actual attribute names, this won't really work for you. But if those are your actual attributes, you just need to change this part:   const skillattrs = ['skillattr56', 'skillattr57']; and add in all the attribute bases you need. Again though, I suggest posting the HTML for your attributes, and describing what you're actually trying to achieve because there may be a much simpler or more appropriate way to do what you need.
1624317776

Edited 1624318117
GiGs
Pro
Sheet Author
API Scripter
Nics method to build the array of numbers from 0-57 can be used to build the skillattrs array I posted quite elegantly, but I wasn't sure about assuming you had a set from 0 to 57. If you do, I would change that one line in my code to   const skillattrs = Array.from(Array(58).keys()).map(num => `skillattr${num}`);
1624346670
.Hell
Sheet Author
I am not the original author of this piece of code. As far as I understood the code should update the "Dice" and ensure the name (e.g Artisan) is the name of this specific skill, whenever the "Attribute"-Dropdown is changed. If you want to take a look directly at the code you can find it under Shadowrun5th in the Roll20 repo
1624357370

Edited 1624358466
GiGs
Pro
Sheet Author
API Scripter
Oh I see, I misunderstood the code - the various attributes are of the form @{name - with no close brackets, and the sheet workers complete the name. Having a quick look at the sheet code, it could do with a massive overhaul, but for this specific problem, here's a version of Nic's code to do the job: // Nic's method  const   skillIndices  =  Array . from ( Array ( 77 ). keys ());  // create an array of numbers from 0 to 76 for  ( const   index   in   skillIndices ) {  // select each item in skillList as const skill    on ( `change:skillattr ${ index } ` ,  function  ( eventInfo ) {  // use template literal to append skill value to on change.       setAttrs ({        [ `skillattr_name ${ index } ` ]:   ` ${ eventInfo . newValue } _name}` ,        [ `skillattr_value ${ index } ` ]:   ` ${ eventInfo . newValue } _total}`     });   }); } That code creates 77 sheet workers, but you only write the code for one. The method I was using to do the same thing creates only one sheet worker, but its a bit of a monster: const   skillattrs  =  Array . from ( Array ( 77 ). keys ()). map ( num   =>   `skillattr ${ num } ` ) const   skillattrsChanges  =  skillattrs . reduce (( changes ,  item )  =>   ` ${ changes  ?  ` ${ changes }  `  :  '' } change: ${ item } ` ,  '' ); on ( skillattrsChanges ,  function  ( eventInfo ) {    getAttrs ( skillattrs ,  function  () {      const   index  =  eventInfo . sourceAttribute . replace ( 'skillattr' ,  '' );      const   value  =  eventInfo . newValue ;      setAttrs ({        [ `skillattr_name ${ index } ` ]:   ` ${ value } _name}` ,        [ `skillattr_value ${ index } ` ]:   ` ${ value } _total}`     });   }); }); Either approach will do the job (assuming I haven't made any typos or syntax errors!). Looking at the sheet, and knowing you are going to have to copy the technique for multiple other sets of stats, I'd use Nic's version. It's easier to understand and adapt to the other sets.
1624373465
.Hell
Sheet Author
I go with that. Thanks for all the help