Dynamic Expressions in routines can be used to set/change variables. These variables can then be used to dynamically determine the values of properties or values in the routine itself.
Variable declarations
A dynamic expression is used to declare a variable, or to modify an existing variable or an indexed part of an existing variable, by using the var keyword followed by the variable name, an optional index, the = sign, and an expression. Only alphanumeric characters, underscore, and dash should be used in variable names. All variable names are case-sensitive. For an alternative method of declaring variables, see the [[VAR|Functions#var]] function. While a dynamic expression works for many use cases, to directly set arrays, objects, or multiple variables at the same time, use the VAR function.
Note that spaces are required on either side of the = sign, and also around other operators that appear (see below). Also, there can be no whitespace between the opening " and var, and no trailing whitespace between the end of the expression and the closing ".
"var a = 2 // sets variable a to 2",
"var b.1 = 3 // sets index 1 of variable b to 3",
"var aName = 4 // sets variable aName to 4",
"var my_name = 5 // sets variable my_name to 5",
"var other-name = 6 // sets variable other-name to 6"
Note that comments were made in the above variable declarations using '//'.
The variable name or index can also be expressed using another variable, by prefixing the variable name with a dollar sign ($):
"var a = 'abc'",
"var $a = 9 // sets variable abc (defined by variable a) to 9",
"var b = 1",
"var c.$b = 2 // sets index 1 (defined by variable b) of variable c to 2"
A variable can be assigned to a value of most common JavaScript types:
"var a = 1 // integer",
"var b = 1.05 // number",
"var c = null // null value",
"var d = 'abcd' // string",
"var e = true // boolean",
"var f = [] // array",
"var g = {} // object"
Variables can be set to the value of another variable. This requires the use of the syntax ${variable_name.index}:
"var a = 'foo'","
"var b = ${a} // sets b to 'foo' (value of variable a)","
"var c = ${a.1} // sets c to 'o' (index 1 of variable a)",
"var d = 1",
"var c = ${a.$d} // sets c to 'o' (index 1 of variable a)"
Note that while referencing a variable on the left-hand side of an assignment uses the syntax $variable_name, on the right-hand side you must use brackets: ${variable_name}. However, inner variable references (such as $d in the last line above) do not use nested brackets.
Variables can also be set to the property value of a widget. This requires the use of the syntax ${PROPERTY name OF 'widget_id'}:
"var a = ${PROPERTY x} // sets a to the x value of this widget",
"var b = ${PROPERTY x OF abcd} // sets a to the x value of widget with id 'abcd'",
"var prop_name = 'x'",
"var prop_widget = 'abcd'",
"var c = ${PROPERTY $prop_name OF $prop_widget} // sets c to the x value of widget with id 'abcd'",
Expressions can use multiple math operators such as +, -, *, and / for computations
"var a = 1 + 2 // sets variable a to 3",
"var b = 'read' + 'me' // sets variable b to 'readme'",
"var c = 100 / 2 // sets variable c to 50",
"var b = ${small} * ${big} // sets variable b to the product of the two variables"
"var d = 1 + 2 + (3 * 5) // sets variable d to 18",
Expressions allow for comparisons using == / != / < / <= / > / >= as well as logical operations (&& / || / !)
"var a = ${foo} == 'yes' // sets variable a to true if variable foo equals 'yes'",
"var b = ${small} < ${big} // sets variable a to true if variable small is less than variable big",
"var c = $a && $b // sets variable c to true if both variable a and b are true",
"var d = ! $c // sets variable d to true if variable c is false (or to false in the other case)"
"var e = ${w} && !${x} || ${y} && ${z}" is a valid syntax
Expressions can use a single operator keyword for advanced computations, using 1-3 operands in the form of op1 operation op2 op3
"var a = 'split.me.up' split '.' // sets variable a to the array ['split', 'me', 'up']",
"var b = ${a.0} concat 'me' // sets variable b to 'splitme'",
"var c = 'hello world' substr 0 5 // sets variable c to 'hello'"
The operation keyword can also be placed before the 1-3 operands to improve readability, i.e. operation op1 op2 op3
"var a = randInt 2 5 // sets variable a to a random integer between 2 and 5",
"var b = max ${a} 4 // sets variable b to the higher of the two numbers"
The supported operations for computation are discussed in detail in the section on Computations.
Error Handling
Variable names in declarations cannot use a space or some other special character:
"var my name = 'abc' // WRONG!!! (statement is ignored)",
"var my%name = 'abc' // WRONG!!! (statement is ignored)"
Variable declarations require an expression:
"var a // WRONG!!! (statement is ignored)",
"var b = // WRONG!!! (statement is ignored)"
Non-existent operations, variable names, properties or array indexes are substituted with null:
"var a = nonexistent // a is set to null",
"var b = ${nonexistent_variable_name} // b is set to null",
"var c = ${PROPERTY nonexistent_property_name} // c is set to null",
"var d = ${PROPERTY x OF nonexistent_widget_id} // d is set to null",
"var e = ${foo.999999} // e is set to null if variable foo does not have a valid index of 999999",
"var f = ${foo.bar} // f is set to null (as bar is not a valid index)"
Declaration Syntax
Variable declarations take one of these forms:
| Syntax | Example | |
|---|---|---|
var <varName> = <value> |
var a = 12 |
|
var <varName> = <operation>[ <value>][ <value>][ <value>] |
var a = max 3 ${a} |
|
var <varName> = <value> <operation>[ <value>][ <value>] |
var a = ${b} == ${c} |
|
<varName> |
<identifier>|<identifier>.<identifier> |
a, $a, a.0, a.$b, $a.$b |
<identifier> |
series of letters and numbers which form the variable name or the index each one can be prefixed by $ which causes the actual variable name or index to be read from a variable |
a, $a |
<operation> |
a valid operation of the former COMPUTE (described in Computations) |
+, ==, substr |
<value> |
null|false|true|[]|{}|<number>|<string>|<variable> |
4, -3.1, 'hello world', ${PROPERTY parent} |
<number> |
an integer or decimal | 4, -3.1 |
<string> |
a string in single quotes | 'example', 'new\\u00a0line' |
<variable> |
${<varName>}|${PROPERTY <identifier>[ OF <identifier>]} |
${a}, ${a.$b}, ${PROPERTY parent} |
Complex Objects
A dynamic expression can be used to set individual properties in complex objects such as "CSS", "cardDefaults", "cardTypes", and "faceTemplates." For example, a complex object form of CSS might look like the following:
"css": {
"default": {
"background": "white",
"font-size": "25px"
}
},
If you want to add a new "color" property and change the "font-size" to 20px in the widget "myWidget", you could use something such as:
"var newCSS = {}",
"var newProps = {}",
"var newProps = ${PROPERTY css OF myWidget}",
"var newProps = ${newProps.default}",
"var newProps.color = 'blue'",
"var newProps.font-size = '20px'",
"var newCSS.default = ${newProps}",
{
"func": "SET",
"collection": [
"myWidget"
],
"property": "css",
"value": "${newCSS}"
}
In the above example, you could just as easily replace "blue" and "20px" with variables such as "${newColor}" and "${newFont}" that contain the desired values.
Another situation you might encounter is when using fetch and jsonParse to retrieve JSON from another website or from another VTT room. For example, assume you want to get the value of the player property of a seat with id of "seat1" from another VTT room. You could use this code:
"var thisSeatID = 'seat1'",
"var json = fetch 'https://virtualtabletop.io/state/TutorialExampleSpectator'",
"var parsed = jsonParse ${json}",
"var otherSeat = ${parsed.$thisSeatID} //You could also use the seat id and not a variable like ${parsed.seat1}",
"var otherSeatPlayer = ${otherSeat.player}",
Variable references
Variables may be used in routines to dynamically determine the names of properties, values, and even functions. For example, consider the following example that would change CSS properties:
"clickRoutine": [
"var color1 = 'white'",
"var color2 = 'red'",
"var color3 = 'black'",
"var borderWidth = 5",
{
"func": "SET",
"collection": "thisButton",
"property": "css",
"value": "background: ${color1}; color: ${color2}; border-color: ${color3}; border-width: ${borderWidth}px"
}
],
After all substitutions get made, the CSS value looks like this:
"value": "background: white; color: red; border-color: black; border-width: 5px"
As another example, consider the (somewhat bizarre) clickRoutine below:
"clickRoutine": [
"var fname = 'func'",
"var fcn = 'SET'",
"var a = 'ropert'",
"var foo = ${a}",
"var bar = 'value'",
"var val = 'this'",
{
"${fname}": "${fcn}",
"collection": "thisButton",
"p${foo}y": "xyzzy",
"${bar}": "${val}IsTheValue"
}
],
After all substitutions get made, the result looks like this:
"clickRoutine": [
{
"func": "SET",
"collection": "thisButton",
"property": "xyzzy",
"value": "thisIsTheValue"
}
],
Thus the allowable dynamic syntax outside of the declaration context is much more general than within it, but the basic building blocks are the same. ${variable_name} gives the value of the variable variable_name, and ${PROPERTY x OF foo} gives the value of the x property of the widget whose id is foo (or of the current widget if the OF clause is omitted).
When determining the value of a string, each such dynamic declaration is expanded, and its contents inserted in its place in the string. Thus for example in the property-value pair "p${foo}y": "xyzzy", ${foo} is replaced by the value of foo, giving "property": "xyzzy", and similarly for "${val}IsTheValue". Note that while (as in the example above) it is possible to make the keyword func as well as the function name dynamically determined, this is discouraged, since it may make it difficult for conversion software to perform correctly in the future if needed.
Finally, note that the ${...} syntax can appear in nested expressions. For example, if you are defining faceTemplates you can use a dynamic substitution to set the width.
Edge cases and error handling
Note that the sequence
"var notso = false",
{
"func": "SET",
"collection": "thisButton",
"property": "movable",
"value": "${notso}"
}
will actually set movable to false, not to "false". However, the sequence
"var notso = false",
{
"func": "SET",
"collection": "thisButton",
"property": "myprop",
"value": "x${notso}y"
}
will set the custom property myprop to the string "xfalsey". This is true for other meaningful values as well; for example, if a variable evaluates to null or is undefined, using it as the value of a property in a dynamic expression will generally result in the default value for that property being used. However, if the variable is used as part of a string, the value of the variable will be interpreted as a string:
"var nullvar = null",
{
"func": "SET",
"collection": "thisButton",
"property": "myprop",
"value": "x${nullvar}y"
},
{
"func": "SET",
"collection": "thisButton",
"property": "myprop1",
"value": "x${undefinedvar}y"
}
results in myprop having the value "xnully" and myprop1 having the value "xy".
A note on valid string characters
Valid characters for variable and index names are alphanumerics, _ (underscore), and - (hyphen).
Valid characters for widget and property names expand the above list to include a space. Thus for example if have a property named "my custom property", you can refer to ${PROPERTY my custom property}. (It is recommended that you do not have custom properties containing the string OF!)
String literals in dynamic expressions can contain any printable ASCII character (\u0020 to \u007e) except single quote ' (\u0027), double quote " (\u0022), and backslash \ (\u005c).
In addition to these characters, additional characters can be added by using Unicode escapes. In contexts not involving dynamic expressions, a normal Unicode escape such as \u0024 for $ is allowed (or you can just paste in the appropriate character). However, in contexts where a dynamic expression is being evaluated, an extra backslash is required. Thus the above Unicode escape if written inside a variable declaration, or inside a ${...}, it must be written \\u0024. So for example
"\u0024": 1
defines a property whose name is $ and whose value is 1. Further, inside a routine,
"var \\u0024 = '\\u2605',
{
"func": "SET",
"collection": "thisButton",
"property": "text",
"value": "${\\u0024}"
}
sets the text property of the button to a star symbol.
Quick Links
Home
1. Basics
2. Developer Documentation
- Widgets
- Functions, automation, and routines
- Dynamic Expressions and using variables
- Math, string, array, color, JSON functions
- Cards and Decks
- Editing JSON
- Using CSS
- Fonts and Symbols
3. Available Resources
- Publicly available games
- Tutorials
- Demonstration Features
- Useful Code Snippets
- Useful Global CSS Snippets
4. Usage Guidelines and Copyrights
5. Other Technical Information
- Download Repository
- Using GitHub and creating Pull Requests
- Internals Overview
- Testing with TestCafé
- URL-addressing rooms
- Using Docker containers
- Config.json file