Skip to content
bjalder26 edited this page Nov 25, 2024 · 129 revisions

Introduction to Widgets

VirtualTabletop uses various types of widgets as a visual representation of objects you need for playing a particular game. Each of these types is described in detail below. To better illustrate their usage, it's helpful to consider typical pieces you find in a game box:

  • Boards. A board is typically represented as a BasicWidget as it's mostly just a background image. Many boards have designated areas to place cards on. Represent these areas with holders, which are drop-zones that automatically align cards dragged onto them. They can be configured with a background image, but also be made transparent or invisible as needed.

  • Seats. A player seat may be represented as a seat. Seats can be given indices to control the order of play, and widgets can be linked to seats so that they are visible only to that player (for this bit of functionality, see the onlyVisibleForSeat and linkedToSeat properties in the global properties section below).

  • Tokens (e.g. "flat" game pieces made out of cardboard or plastic). A token is typically represented as a BasicWidget or a card. Use BasicWidgets if all you need is to display an image and/or text. Use cards when you need the tokens to be stackable in a pile, so players can see how many are stacked together and move them as a group.

  • Writeable objects (e.g. paper/cardboard with blank areas to write on). A writeable object is typically represented by a label, a canvas, or a scoreboard because these widget types allow players to write and update the label text, draw on the canvas, or keep score.

  • 3D objects (e.g. meeples, chess pieces, etc.). A 3D object is typically represented as a BasicWidget, a card or a holder. Use cards when you need the object to be stackable in a pile, so players can see how many are stacked together and move them as a group. Use a holder when you need the object to have one or more "slots" where other game pieces can be placed in or taken out (e.g. a card holder).

  • Randomizer objects (e.g. dice, spin wheels, "tossable" figures, etc.). Anything that is used to determine a random value is typically represented as a spinner or a card. Use cards if you need the objects to be stackable in a pile, so players can see how many are stacked together and move them as a group. Note that cards in VirtualTabletop can have more than two sides/faces, so a typical die could be represented by a 6-sided card which can be flipped to a random side using routines.

  • Timers are represented by timers, which are programmable count-down or count-up widgets that can cause routines to execute at prespecified times.

  • A deck defines the properties of one or more cards. Think of cards as blank pieces of cardboard. The deck defines what image is shown on the card sides and how many cards of the same type should exist in the game. A standard deck with 52 playing cards has 52 individual card definitions, but many game boxes come with multiple cards of identical look, and that's where deck definitions become useful. In addition, when two or more cards are stacked on a game table, they may form a pile. Piles are visually represented by a circular handle displaying the number of cards it contains. The handle can be used to move the cards as a group. Clicking on the handle also allows players to shuffle or flip the cards within the pile. The section on Cards and Decks provides more detailed information on the attributes of decks and cards.

In addition, VirtualTabletop offers Button widgets which can be configured to execute one or more functions, such as moving cards, updating a label, performing math calculations or working with arrays. While these have no direct counterpart in the game box, they generally represent actions that someone playing the game might take. Note that while buttons are the most natural place to put a sequence of actions (called a routine), routines may in fact be added to any widget. Routines are discussed in more detail at Routines.

If you are familiar with the playingcards.io JSON format, you might be looking for boards, counters and hands. As noted above, boards are generally just BasicWidgets. Hands are just a holder with a few properties preset. Counters are just a combination of labels and buttons.

Widget Overview

VirtualTabletop offers the following widgets (in alphabetical order):

Each of these widgets has a number of properties that may be configured by the game creator to alter the function or appearance of the widget. In particular, each widget has a default color; these colors are summarized in the section on widget colors, along with information about how to change them.

Note that there are a number of global properties for every widget that provide defaults for any widget.

The VirtualTabletop room is 1600x1000px. It is then scaled to completely cover the browser window (while keeping the aspect ratio). All pixel values given below in the properties are relative to a 1600x1000 room.

Global properties for every widget

Please note that some widget types override the global default value. See tables below.

And keep in mind that any of these properties (except type and read-only properties) may be updated while playing the game. For example x, y and z will change when dragging widgets, and parent will change when moving a widget to a holder. But all of them can be changed using Functions.

Property Default value Description Tutorial
_absoluteRotation null
(read-only)
_absoluteRotation returns the total rotation of a widget including the rotation that occurs in parent widgets. Read-only properties do not trigger change routines - this value is the sum of rotation for this widget and each of its parent widgets.
_absoluteScale null
(read-only)
_absoluteScale returns the effective scale of a widget including scale that occurs in parent widgets. Read-only properties do not trigger change routines - this value is the product of scale for this widget and each of its parent widgets.
_absoluteX null
(read-only)
_absoluteX returns the room x coordinate of the widget's insertion point (x,y in the parent widget's coordinate system). Read-only properties do not trigger change routines - this value can be affected by x, y, scale, and rotation of any of the widget's parents in addition to the widget's own x and y value.
_absoluteY null
(read-only)
_absoluteY returns the room y coordinate of the widget's insertion point (x,y in the parent widget's coordinate system). Read-only properties do not trigger change routines - this value can be affected by x, y, scale, and rotation of any of the widget's parents in addition to the widget's own x and y value.
_ancestor null (read-only) _ancestor is the same as parent unless the type of the parent widget is pile. If the parent widget is a pile then the closest ancestor that is not a pile (usually the pile's parent, null if the pile's parent is null) is returned. Read-only properties do not trigger change routines - if you want to run a routine when _ancestor changes, check for changes to _ancestor using a parentGlobalUpdateRoutine .
audio null Temporary property to trigger audio to play. The audio property will not trigger a changeRoutine (to prevent infinite loops), but will trigger an audioChangeRoutine. Do not try to use your own audio property on a widget, because the property will get deleted automatically. Audio
borderRadius null Applies the css border-radius property to the widget. Using border-radius in the css widget property is deprecated in favor of setting the borderRadius widget property instead. A positive numerical value will set the radius for all corners in pixels. String values such as "50%" can also be used. String values must only use literal numerical values (no use of css calc() or var() functions) and all units must be px or % (other css length units are not supported), but otherwise follow the css specification allowing the x and y radius for each corner to be set separately.
_centerAbsoluteX null
(read-only)
_centerAbsoluteX returns the room x coordinate of the center of the widget. Read-only properties do not trigger change routines - this value can be affected by x, y, scale, and rotation of any of the widget's parents in addition to the widget's own x and y value.
_centerAbsoluteY null
(read-only)
_centerAbsoluteY returns the room y coordinate of the center of the widget. Read-only properties do not trigger change routines - this value can be affected by x, y, scale, and rotation of any of the widget's parents in addition to the widget's own x and y value.
changeRoutine [] When any property of the widget changes, this routine is called. If you want to restrict execution to changes in a particular property, use <propertyName>ChangeRoutine (for example, millisecondsChangeRoutine will fire only when the milliseconds value of its timer changes). Routines
classes "" CSS classes separated by spaces that will be added to the widget. This is currently mainly used for BasicWidgets and for transparent Holders.
clickable true When set to false, the widget will ignore clicking (manually as well as via CLICK operation)
clickRoutine [] This routine is called when the widget is clicked, assuming its clickable property is true. Routines
clickSound null Indicates the url of a sound to automatically play when the widget is clicked on. The sound plays for all players. Placing an AUDIO function in a clickRoutine will override this. Audio
css "" Custom CSS that will be added to the widget. For example "border-radius: 100%; background: red". More details: Using-CSS CSS
display true Indicates whether the widget is visible in the room. When set to false, a button on the top of the screen in Edit Mode will alternately show and hide widgets with false. When not in Edit Mode, widgets with false cannot be seen or used by players.
dragging null The playerName of the player currently dragging the widget. Used internally along with hoverTarget to implement behavior of hoverInheritVisibleForSeat; not intended to be set by game. Dragging
dragLimit {} If values in the object are set, the widget's top-left corner coordinates cannot go beyond the boundaries set. Each value is optional. Takes the form "dragLimit": { "minX": 0, "maxX": 100, "minY": 0, "maxY": 100}
dropLimit -1 Usually only holders accept widgets being dropped into them, but if dropLimit is set to something other than 0 and dropTarget is also set, then widgets matching the dropTarget requirements will become a child of the widget they are dropped on to.
dropOffsetX, dropOffsetY 0 IF this widget gets another widget as child, the child will get these x,y coordinates relative to the widget. Holders (Offset variants)
dropTarget null Usually only holders accept widgets being dropped into them, but if dropLimit is set to something other than 0 and dropTarget is also set, then widgets matching the dropTarget requirements will become a child of the widget they are dropped on to.
enlarge false This can be false or a number. If it's a number, a version of the widget will be displayed as an overlay. Enlarge is activated when a player mouses-over a widget or when they touch a widget on a touchscreen for half a second or longer. The number is the scale applied to the enlarged widget (the scale property of the widget is ignored in the enlarged widget). So a 3 says that the enlarged version is 3x the size of the widget. A 0.5 would actually show a version that's half as big as the original.

The enlarged widget gets styles from the widget's stylesheet by making a copy of the stylesheet with the id of the widget replaced with the id of the enlarged widget. Styles targeting only the enlarged widget can be created in a widget stylesheet by starting a selector with #enlarged. The enlarged widget uses css position: fixed to be positioned near the edge of the viewport; defaulting to the top corner on the opposite side of the viewport as the pointer. CSS variables containing the viewport position of the room (--roomTop, --roomLeft) and original widget (--originalLeft, --originalTop, --originalRight, --originalBottom) are provided; use --scale when calculating offsets from these variables if you want the offset scaled to match the room. The enlarged widget can be positioned relative to the pointer by styling with position: relative.
Enlarge
enterRoutine [] Triggers the activation of Functions or Dynamic Expressions when a widget "enters," in the same way that clicking a button activates a clickRoutine. In this case, entering takes place when a widget becomes a child of the widget with the enterRoutine. Routines
fixedParent false When set to true the parent of this widget will not change when it is being dragged by a player (or editor). Automation can still change it though.
grid [] This is an array of "snap to grid" definitions. Each object in the array must have x and y (distance between two objects). Example: [{ "x": 100, "y": 150 }]

Optionally it can contain minX/Y and maxX/Y to limit where the grid takes effect. Example: [{ "x": 103, "y": 60, "minX": 400, "maxX": 1200, "minY": 300, "maxY": 700}]

It can also have other grid location specific properties. For example, you can use image to change the image displayed at that snap point. Or use rotation to force the widget's rotation at that snap point plus offsetX/Y for offsetting the complete grid. Example: [{ "offsetX": 200, "x": 300, "y": 173.2, "rotation": 90 }, { "offsetX": 350, "offsetY": 86.6, "x": 300, "y": 173.2, "rotation": 90 }, … ]

By default, offset calculations are made from the top left corner of the widget, but you can use alignX and alignY in each grid element to modify that. Example: [{"x": 100, "y": 100, "alignX": 0.5, "alignY": 0.9}] where the values for alignX and alignY represent a percentage of the width and height of the widget from 0 to 1. offsetX and offsetY are expressed in pixels.
Grids, Hexagonal grids (Grid variant)
globalUpdateRoutine [] When any property of any widget changes, this routine is called. If you want to restrict execution to changes in a particular property, use <propertyName>GlobalUpdateRoutine (for example, ownerGlobalUpdateRoutine will fire only when the owner value of any widget changes so you could update a label with the count of player owned cards). Routines
hidePlayerCursors false When set to true, the cursor indicator for other players is hidden over this widget.
hotkey null When set to an alphanumeric value (case sensitive), pressing the corresponding key on the keyboard has the same effect as clicking the widget with the mouse.
hoverInheritVisibleForSeat true Widgets dragged over the hover area of a valid dropTarget implement the most restrictive onlyVisibleForSeat property of any ancestor with this property set to true. This creates an effect similar to the childrenPerOwner property of holders.
hoverParent null Added to a widget picked up from a holder. The value is the id of the previous parent. The value remains on the widget until it is mostly out of the holder or until dropped back into the same holder. Used internally to determine when the 'showInactiveFaceToSeat` property is applied. Not intended to be set by a game.
hoverTarget null Added to a widget picked up from or being dragged over a holder. The value is the id of the widget that will become the parent of a widget being dragged if it is dropped. The value remains on the widget as long as it could be dropped into that holder. Used internally along with dragging property to implement behavior of hoverInheritVisibleForSeat. Not intended to be set by game.
id A unique identifier of a widget. Pretty much any string but control characters like newlines will probably break somewhere.
ignoreOnLeave false If set to true, this widget will ignore the onLeave property of a holder.
In practice this can be used to set if a card will be flipped to its back side when leaving the hand.
inheritChildZ false See z and layer. If this is set to true, the widget will inherit the largest layer+z combination of its children.
Makes it possible to have a button on top of a holder that disappears when cards are put into the holder.
As a child, the card just becomes part of the holder and will be rendered at the same Z coordinate. So without this property the button would be above the card.
inheritFrom null If a property is not defined in this widget, you can choose another widget from which to inherit the property. Most simply: "inheritFrom": "otherWidgetID" will cause any properties defined in otherWidgetID to have the same values in this widget, if they are not already defined in this widget. You can also use an object to specify which properties to inherit: "inheritFrom": { "otherWidgetID": [ "image", "svgReplaces" ] }, and you can provide multiple widgets (and use "*" for the simple "inherit all"): "inheritFrom": { "otherWidgetID": [ "image", "svgReplaces" ], thirdWidgetID": "*" }. As an alternative, you can inherit all properties except for a set of specified properties. For example, "inheritFrom": {"otherWidgetID": ["!image"]} inherits all heritable properties except image. Note: You should either specify properties that should not be inherited, such as "!image", or properties that should be inherited, such as "image", but should not mix and match both types in a single statement. The properties id, type, deck, and cardType cannot be inherited. Multiple nested layers of inheritance with many widgets can substantially slow down the room. (For example, if D inherits from C which inherits from B, which inherits from A). Finally, inheritFrom must be defined directly in the widget's JSON rather than through cardDefaults or similar constructs. See examples below this table for valid syntax. inheritFrom
layer 0 Widgets with layer 0 are always below widgets with layer 1 (if they have the same parent).
Technically, the real CSS z-index is calculated by (layer+10)*100000+z. See inheritChildZ.
leaveRoutine [] Triggers the activation of Functions or Dynamic Expressions when a widget "leaves," in the same way that clicking a button activates a clickRoutine. In this case, leaving takes place when a widget that is the child of the widget with a leaveRoutine changes its parent to null or a different parent. Routines
linkedToSeat null If set to the id of a seat widget or to an array of seat widget id's, the containing widget will be visible only if that any of those seats is occupied (PCIO compatibility). Seats (Basic variant)
_localOriginAbsoluteX null
(read-only)
_localOriginAbsoluteX returns the room x coordinate of (0,0) within the widget. This value is the same as _absoluteX unless the widget itself is transformed with scale and/or rotate. Read-only properties do not trigger change routines - this value can be affected by x, y, scale, and rotation of this widget or any of the widget's parents.
_localOriginAbsoluteY null
(read-only)
_localOriginAbsoluteY returns the room y coordinate of (0,0) within the widget. This value is the same as _absoluteY unless the widget itself is transformed with scale and/or rotation. Read-only properties do not trigger change routines - this value can be affected by x, y, scale, and rotation of this widget or any of the widget's parents.
movable true If set to false, the widget will not be movable during play by clicking and dragging.
movableInEdit true If set to false, the widget will not be movable in edit mode.
This is sometimes useful for child widgets of more complex widget groups. For example buttons of counters.
onlyVisibleForSeat null If set to the id of a seat widget or to an array of seat widget id's, the containing widget will be visible only to players sitting in those seats. Seats (Basic variant)
overlap true If set to false, this widget will override the stackOffsetX/Y of a holder so that it will be completely visible.
owner null If this is not null, it is the name of a player (see player list overlay) or an array of player names. This widget will only be visible for the specified player(s). See childrenPerOwner of holder.
This makes the hand only show your own cards.
parent null This is null if the widget is directly on the main room surface. Otherwise it is the id of another widget.
rotation 0 Rotation of the widget in degrees (any value should work - even below -360 or above 360) around the center (can be changed using "transform-origin" in the css property).
It is worth noting that children "inherit" this because they become part of their parent. So if you create a holder with a 15° rotation, any cards put into it will be rotated 15° (plus their own rotation value).
Rotation
scale 1 Scale factor of the widget.
The same inheritance as for rotation applies. So if you scale the hand by 2, all cards in it will be displayed at twice their normal size.
As with rotation the origin is the center of the widget and can be changed using "transform-origin" in the css property).
type This is a special value that determines what class the widget instantiates. See below for further properties of the different types. Valid values are: "button", "canvas", "card", "deck", "holder", "label", "pile", "spinner", and "timer" (no capital letters allowed). If no value (or any other value) is given, it will become a BasicWidget.
typeClasses "widget" Further CSS classes that will be added to the widget. These are the internal ones: "widget" and the ones specific to the widget type.
Not intended to be changed.
width, height 100 The width and height of the widget in pixels.
x, y 0 The left and top offsets in pixels relative to the parent widget.
z 0 The Z coordinate. Widgets with higher Z coordinate are on top of others.
The property layer divides the Z coordinates into different layers.
The Z coordinate only affects children of the same parent. See inheritChildZ.

Examples of valid inheritFrom syntax:

{
  "inheritFrom": "seat"
}
{
  "inheritFrom": {
    "seat": "*"
  }
}
{
  "inheritFrom": {
    "seat": [
      "width",
      "height"
     ]
  }
}
{
  "inheritFrom": {
    "seat": [
      "!width",
      "!height"
    ]
  }
}
{
  "inheritFrom": {
    "seat": "width"
  }
}
{
  "inheritFrom": {
    "seat": "!width"
  }
}

BasicWidget

This is a somewhat generic widget. It can be used to add an image but it also has some additional features making it useful for other purposes. For example, basic widgets are a good way to place text (that does not need to be edited during the game) on the board.

Property Default value Description Tutorial
activeFace 0 The index of the faces array that is currently active. This is what changes when you click the widget.
classes "" The same global default. Supported classes the default game pieces are: "classicPiece", "checkersPiece" and "pinPiece".
color "black" The color can be any value supported by CSS. It is exposed as the CSS variable --color and is used by the game piece classes.
faceCycle "ordered" Can be "ordered" or "random". The "ordered" faceCycle allows to iteratively cycle through the faces
faces [ {} ] When clicking a widget, it cycles through its faces (you can prevent this by setting the property "clickable" to "false"). This property is an array of objects that each contain widget properties. This way you can override any property of the widget. Example: [{ "classes": "checkersPiece" }, { "classes": "checkersPiece crowned" }]
Make sure that when you use a property in one face definition, you set that same property in all the other face definitions as well. For example if you override the property image in face 0, but not in face 1, it won't be removed when switching to face 1.
An example for this is the default checkers piece that adds the class "crowned" to its classes on click.
html null Allows use of most html and inline css. If both html and text properties are not null, html overrides the text property. Can also use "${PROPERTY <property name>}" anywhere in the html property, but the specified property must be on the same widget and not on another widget. HTML
image "" Adds an image to the widget, for example '"image": "/assets/-1499118311_13369"'.
layer 1 Same property as in the global properties but with a different default value. Puts the widget above cards (assuming this will be used mostly for tokens / game pieces).
If you add a board using the "Upload board" button on the "Add widget" overlay, the generated widget will have its layer set to -4.
svgReplaces {} Use to change the color of SVG images. You must know the color(s) used in the SVG image. For example, most VirtualTabletop assets use currentColor so the color can be changed by "svgReplaces": {"currentColor": "myColor"} and then by setting the property myColor to the desired color. Can be used to change multiple colors in the image. For example, "svgReplaces": {"topColor": "newTop", "leftColor": "newLeft"} will replace the colors topColor and leftColor in the SVG image with the colors that are in the properties newTop and newLeft.
text "" Text that will be displayed on the widget. Use css to change size and other properties.
See the unicode images at the bottom of the "Game Pieces" column in the "Add widget" overlay as examples.

Button

This widget is intended to reflect actions that a player might take during a game. For example, a button labeled Deal might deal a card to one or more players. While actions can be associated with any widget, they are more naturally associated with buttons.

Click to see tutorial on Button Appearance

Click to see tutorial on button operation/routines

Property Default value Description
backgroundColor null Changes the background color of the button. Has the same affect as changing the CSS property to something like "css":"background: ..." or "css":"--wcMain: ...".
backgroundColorOH null Changes the background color of the button when the mouse hovers over it. Has the same affect as changing the CSS property to "css":"--wcMainOH: ...". The onhover property is disabled if the CSS background property is used instead of --wcMain.
borderColor null Changes the border color of the button. Has the same affect as changing the CSS property to something like "css":"border-color: ..." or "css":"--wcBorder: ...".
borderColorOH null Changes the border color of the button when the mouse hovers over it. Has the same affect as changing the CSS property to "css":"--wcBorderOH: ...". The onhover property is disabled if the CSS border-color property is used instead of --wcBorder.
borderRadius 800 Same property as in the global properties but with a different default value.
classes "" The same global default. But buttons support a "transparent" class here that removes the default white background.
clickRoutine [] This is what happens when you click the button. See Functions and Dynamic Expressions.
color null Has no effect on buttons.
image null Adds an image to the button, for example '"image": "/assets/-1499118311_13369"'.
layer -1 Same property as in the global properties but with a different default value. Puts the button below cards/tokens.
movable false Same property as in the global properties but with a different default value.
svgReplaces {} Works the same as it does for basic widgets.
text "" The text displayed on the button.
textColor null Changes the text color of the button. Has the same affect as changing the CSS property to something like "css":"color: ..." or "css":"--wcFont: ...".
textColorOH null Changes the text color of the button when the mouse hovers over it. Has the same affect as changing the CSS property to "css":"--wcFontOH: ...". The onhover property is disabled if the CSS color property is used instead of --wcBorder.
typeClasses "widget button" Same property as in the global properties but with a different default value. This gives a button its default appearance. Removing the class "button" MIGHT also break its functionality so just don't touch this property. Consider using "transparent" in classes or set custom appearance with the css property.
width, height 80 Same property as in the global properties but with a different default value.

Canvas

A canvas is a surface upon which players may do free-form drawing. The resolution of the canvas is 100x100 pixels which gets scaled to the size of the widget. It supports 64 colors that can be defined in the property colorMap (only the first 6 are currently defined by default). When drawing it uses the color at index activeColor.

Click to see tutorial

Property Default value Description
activeColor 1 The default color is VirtualTableTop blue (#1F5CA6).
artist null Indicates the playerName of the player or players that can use the canvas. It can accept a single playerName (e.g. "artist": "guest1234") or an array of playerName (e.g. "artist": ["guest1234", "guest2222"]). The default value null allows anyone to use the canvas.
c00 - c99 null Canvas encodes pixels and colors into properties labeled c00 to c99. These change dynamically as the canvas is used.
colorMap [ ] A button cycles through the default color palette in the following order: #1F5CA6, #000000, #FF0000, #008000, #FFFF00, #FFA500, #FFC0CB, #800080, #A52A2A,#F0F0F0. The array values may be also be custom modified as desired. To make the drawing surface transparent, add 'transparent' as the first item in the colorMap array.
clickable true This is the default. Setting it to false prevents changes to the canvas drawing, but does not prevent using the Reset or color change buttons.
resolution 100 Controls size of pixels displayed on the canvas. The larger the number, the finer the detail.
typeClasses "widget canvas" Same property as in the global properties but with a different default value. This gives a canvas its default appearance. You should not alter this property or the canvas widget might break.
width, height 400, 400 Same property as in the global properties but with a different default value. Although the default values are 400x400, the composed widget that is added through the Add Widget button is 800x800.

Card

See Cards and Decks for more information.

Click to see tutorial about decks

Property Default value Description
activeFace 0 The index of the currently visible card face. This is what changes when you click the card (or flip the card using a button). The faces are defined in the deck.
deck null This is the id of a deck.
Leaving this null will probably break or at least make the card REALLY useless.
If you want to create a card without a deck, consider using a BasicWidget.
faceCycle "ordered" Can be "ordered" or "random". The "ordered" faceCycle allows to iteratively cycle through the faces
height 160 Same property as in the global properties but with a different default value. Typically, this is set using deck's cardDefaults.
onPileCreation {} Should usually be placed in the cardDefaults section of a deck. When cards from that deck form a new pile, the set of properties in onPileCreation will be applied to the pile in order to customize the pile handle. Only cards with the same value for onPileCreation will be able to form piles. This is a simple example: "onPileCreation": { "handleCSS": "background:green;color:white; border-radius:5px"}. This is a more complicated example: "onPileCreation": { "handleCSS": "background:green;color:white; border-radius:5px", "text": "pile", "font-size":"20", "handleOffset": 50, "handlePosition": "bottom left", "handleSize": 60, "rotation":90}.
typeClasses "widget card" Same property as in the global properties but with a different default value. This gives the card its default appearance. Without the class "card" the objects defined in the deck will not display properly. Use classes or css to customize its appearance.
width 103 Same property as in the global properties but with a different default value. Typically, this is set using deck's cardDefaults.

Deck

See Cards and Decks for more detailed information regarding these properties.

Click to see tutorial

Property Default value Description
cardDefaults {} An object of any properties that will be "added" to all the cards belonging to this deck. See cards. Example: { "width": 70, "height": 70 }
cardTypes {} The definition of all different card types. Here is an example: { "1J": {"image": "/i/cards-default/1J.svg"}, "2J": {"image": "/i/cards-default/2J.svg"}, ... }.
clickable false Same property as in the global properties but with a different default value.
faceTemplates [] The definition of how the different faces of the cards look like. Here is an example from the Rotation tutorial: [ {"border": false,"radius": 8,"objects": [{"type": "image", "x": 0, "y": 0, "width": 103, "height": 160, "valueType": "static", "value": "/i/cards-default/2B.svg"}] }, {"border": false,"radius": 8,"objects": [{"type": "image", "x": 0, "y": 0, "width": 103, "height": 160, "valueType": "dynamic", "value": "image" }] } ].
typeClasses "widget deck" Same property as in the global properties but with a different default value. This gives the deck its default appearance and hides it in play mode.
width, height 86 Same property as in the global properties but with a different default value. Please note that this has nothing to do with the cards and only affects the edit mode representation of the deck.

Dice

Dice consist of 1 to n faces. When clicked, a random face is chosen and displayed and a short animation activates to indicate that a dice roll has taken place. Dice faces can be pips, alphanumeric text, images, or any combination of those. Several standard dice types that have analogs in the physical world can also have a 3D appearance.

Click to see tutorial

Property Default value Description
activeFace 0 The index of the currently visible dice face. This is what changes when you click the dice (or activate the dice using a routine). The faces are defined in the faces.
borderColor null The border color to use. If not set, pipColor is used. It is exposed as css variable --borderColor and used in building the css variable --faceBorder. Set --faceBorder in a css property if further customization of the border is desired. Works as a property on the dice for all faces or as an individual parameter on specific faces.
borderRadius 16% Same property as in the global properties but with a different default value. Ignored for 3D dice except d2 and d6.
classes "shaking" Same property as in the the global properties but with a different default value. "shaking" triggers a shaking animation when 2D dice are rolled. "shaking" has no effect on 3D dice. 2D dice can also be shaped with shape classes: "triangle", "pentagon".
clickable true Same property as in the global properties but with a different default value.
color "white" This is the color of the die face. The color can be any value supported by CSS. It is exposed as the CSS variable --backgroundColor. Works as a property on the dice for all faces or as an individual parameter on specific faces.
layer 1 Same property as in the global properties but with a different default value. This puts dice on the same layer as basic widgets.
movable false Same property as in the global properties but with a different default value.
faces [1,2,3,4,5,6] Sets the number of faces and what displays on each face. To display text, use something like ["A","B","C"]. To display images, use something like ["/assets/-842670760_893","/assets/1040634397_2463"]. Array items can also be objects that set widget properties similar to faces on [[Basic Widget
faceCSS null When used as a property on the dice, sets css parameters for all faces. Can also be used on individual face(s) when using the object form of faces in which case it sets css parameters only for that face.
image null The url to an image to display on dice faces. Typically set via an object in faces. If set in the widget, it will be applied as a background image for any face that does not specify an image. If set via an object in faces, value will not be used to create text on the face (use text or pips if both the image and text should appear).
imageScale 0.8 When using images on a die, this property provides a convenient way to adjust the image size. Decrease this value to make the image smaller if undesired clipping occurs, increase this value to make the image larger (clipping image edges). Works as a property on the dice for all faces or as an individual parameter on specific faces.
pips null If set to an integer from 1 to 9, the dice face will display a pip symbol for the number (regardless of other properties). Returned for value if neither text nor value are set. Typically set via an object in faces.
pipColor null (but displays as either black or white) This is the color of the pips (or text) on the dice as well as the border (unless borderColor is set). It is exposed as the CSS variable --pipColor. If not set, it defaults to black or white to contrast with color. Works as a property on the dice for all faces or as an individual parameter on specific faces.
pipSymbols null This property controls how value is displayed if it is a whole number 1-9. When true, pip symbols will be used. When false numerals will be used. For 2D dice and "d6" the default is equivalent to true, otherwise the default is equivalent to false. Does not apply to faces created from an object.
rollCount 0 Used in the randomization and animation process. Increments by 1 each time the dice is rolled. Changing this will trigger an animation but will return to the same face.
rollTime 800 The length of time the dice animation displays, in milliseconds. Applies to both 3D roll animation and 2D shaking animation
shape3d false When false, will display a dice with a 2-dimensional appearance. When true, will display a dice with a 3-dimensional appearance. Shapes with 2, 4, 6, 8, 10, 12, and 20 sides are available. The shape with the fewest excess sides is chosen. For example, with 5 faces in faces and this property set to true, a 6-sided dice will display with one side missing (the missing side will never come up in a roll). When clicked, the dice is "rolled" in 3-dimensions.

Setting this property to a number that matches the number of sides on an available shape will force that shape to be used regardless of the number of faces defined by faces. If more faces are defined then the shape has sides, some faces will share a side. Each face in faces will still have equal probability of being rolled and the correct face will be displayed.

Specific shape options can also be selected by name. The shapes are "d2", "d4", "d6", "d8", "d12", and "d20". The "d2" shape is 2-sided but has some thickness and spins around the horizontal axis when rolled. The color of the "d2-flip" edge is exposed as css variable --edgeColor and defaults to --borderColor.
swapTime 500 The length of time of the transition between face changes, in milliseconds. Effective only for 3D dice. Should not be greater than rollTime.
text null The text to display on the dice face (ignored if pips is defined). Use empty string "" if image without text is desired. Returned for value if value is not set. Typically set via an object in faces.
typeClasses "widgetDice" Same property as in the global properties but with a different default value. This gives the dice its appearance and should not be changed.
value null The value associated with a face. This property is not visible in the JSON Editor. Will be displayed on the face if neither pips nor text is set. Can be read by routines to take actions based on what dice face is visible after a roll. If set by a routine, the activeFace will be changed to the first face matching the value (if one exists, this check includes values returned from pips and text in a face object). This is the default property set if the item from faces is not an object.
width, height 50 Same property as in the global properties but with a different default value.

Holder

Holders are marked areas on a board you can put cards (or other widgets if you override dropTarget) into. If multiple cards are inside a holder (or piled anywhere on the board), by default they form a pile with the number of cards attached to it as a drag handle.

Click to see tutorial

Property Default value Description
alignChildren true If set to false, a new child will not be aligned to the holder. So you can have a hand area where the player can put widgets wherever he wants.
borderRadius 8 Same property as in the global properties but with a different default value.
childrenPerOwner false If set to true, a new child will have its owner set to the player that drags the child into the holder. It will also remove the owner when the card is dragged out of the holder. This is set to true when you add a new hand. Click to see tutorial
dropLimit -1 (no limit) The holder will not act as a valid drop target if adding the widgets would exceed the limit
dropOffsetX, dropOffsetY 4 Same property as in the global properties but with a different default value.
dropTarget { "type": "card" } This defines what widgets can be put into a holder and what widgets are affected by button operations using the holder. It can check any property of the potential child.
The default is that any card works. It can also accept an array of objects, and if the widget matches all criteria in any object, then it will be able to be dropped into the holder.
For example, [{"deck": "deck1", "cardType": "thisCardType"}, {"deck": "deck2", "cardType": "thatCardType"}] would allow dropping of cards of type thisCardtype from deck1 and cards of type thatCardType from deck2, but no others. Note that "dropTarget": { } and "dropTarget": [{ }] will not filter the dropTargets, thus will accept any widget, while "dropTarget": [] will not match any widgets.
dropShadow false If true, when a widget that matches the dropTarget is dragged over the holder, a gray shadow will appear where the widget will be when dropped. The shadow is a cloned widget with a property dropShadowOwner. When a shadow is created, the value will be the playerName. The clone will activate enterRoutine and leaveRoutine, so you may need to counteract that by using IF statements filtering out the clone looking for non-null values. The css of the shadow can be modified using .dragging-shadow.
height 168 Same property as in the global properties but with a different default value. It's the default card height plus two times dropOffsetY.
hidePlayerCursors false (but true if the holder is a "hand") Same property as in the global properties but with a different default value for "hands."
layer -3 Same property as in the global properties but with a different default value. Above boards but below everything else.
movable false Same property as in the global properties but with a different default value.
onEnter {} A set of properties that is applied to new children when they enter this holder.
For example setting the activeFace to 1 so cards flip to their front face when putting them into the hand. To perform some type of automation when a widget enters the holder, use [[enterRoutine
onLeave {} See onEnter. Only applied when the child leaves the holder. To perform some type of automation when a widget enters the holder, use [[leaveRoutine
preventPiles false If set to true, cards in this holder will not form a pile, so they won't have a handle to move all of them at once. (Note however that if a pile was already present and then this property is changed to true programmatically, the pile will remain.)
showInactiveFaceToSeat null When set to a seat id (or array of ids), the inactive face of a card will be displayed to the specified seats. This only works with cards, not basic widget faces. This will produce strange results if the card has more than 2 faces. This does not work as described on holders with childrenPerOwner set to true since the other players will not see any visual representation of cards not owned by them.
stackOffsetX, stackOffsetY 0 If alignChildren is true, the first child will get dropOffsetX as its x; the second child will get dropOffsetX+stackOffsetX as its x and so forth. So this is the offset between children (cards) for example in the hand. See overlap for an exception.
typeClasses "widget holder" Same property as in the global properties but with a different default value. This gives the holder its default appearance. No guarantees if you change this.
width 111 Same property as in the global properties but with a different default value. It's the default card width plus two times dropOffsetX.

Label

A label provides the ability to place arbitrary text on the game board. The text is not editable by default, but can be made editable to allow game players to alter the text.

Click to see tutorial

Property Default value Description
clickable false Same property as in the global properties but with a different default value.
editable false If this is set to true, players can edit the text while playing. A label that is editable cannot be moved by dragging in the text area, but dragging the border does work.
height 20 Same property as in the global properties but with a different default value.
layer -2 Same property as in the global properties but with a different default value. Above boards and holders but below everything else.
movable false Same property as in the global properties but with a different default value.
placeholderText "" Specifies placeholder text to display in the label.
spellCheck false If true and if editable is also true, the browser's built-in spell check will be applied when typing in the label.
tabIndex null If set to a value and if editable is also true, then pressing tab will cause the focus to move between the labels in order of their index value.
text "" The text displayed on the label.
twoRowBottomAlign false This is a pretty hack way to make the label resemble playingcards.io holder labels. If the text does not span two rows, a padding-top value is applied to make it bottom aligned. The problem is that labels are always a <textarea>. That will probably change.
typeClasses "widget label" Same property as in the global properties but with a different default value. Without "label" it will be weird. Because editable.

Pile

Piles are multiple cards with a handle to move, shuffle or flip all of them.

Click to see tutorial

Property Default value Description
alignChildren true This is a holder property but if this is false, the pile would not properly stack its children/cards.
handleCSS " " Custom css for the pile's handle. See onPileCreation in Card for more information.
handleOffset 15 Shifts handle this many pixels away from the pile.
handlePosition "top right" The position of the handle on the pile. Options include "top"/"middle"/"bottom" vertically and "left"/"center"/"right" horizontally. Can also be set to "static" to prevent handle from changing positions at room border. When set to "static" the handle is fixed in the upper left corner.
handleSize auto Pixel size of the handle (both width and height). When left as the default of "auto", it will use 40 but switch to 20 when the pile is less than 50px in any dimension.
inheritChildZ true Same property as in the global properties but with a different default value. For the player the pile is just a "virtual" object so it should inherit the Z value of its children.
layer -2 Same property as in the global properties but with a different default value. Above boards and holders but below everything else.
movable false Same property as in the global properties but with a different default value.
pileSnapRange 10 The distance at which cards will form new piles or join existing piles. This is measured in pixels from the upper-left corner of the widget being dragged to the upper-left corner of the card or pile which it will join. If either x or y is less than this distance, the card being dragged will join the pile when dropped. Set this value in onPileCreation (see Card for more information).
text null When left as default, the pile handle displays a count of the cards in the pile. This property can be set to override the count with other text.
typeClasses "widget pile" Same property as in the global properties but with a different default value. Without "pile" the handle probably totally breaks.
width, height 1 Same property as in the global properties but with a different default value. This is set to its first child when it is created on the fly.
x, y 4 Same property as in the global properties but with a different default value. It's 4 because the dropOffsetX/Y on holders is 4 by default.

Scoreboard

Scoreboard widgets work in connection with Seats to display information in table form. A typical use case would be displaying a score tally. There can be one or more scoreboard widgets in a room.

Click to see tutorial

Property Default value Description Tutorial
autosizeColumns true When true (default), the various column sizes will all be equalized so that the entire table fits in the width of the widget (the widget may still scroll vertically). Note that this may result in crowding if there are too many players, in which case the game designer should adjust the widget width. When false, the column sizes will be whatever the default rendering assigns them.
currentRound null If set to a number, the corresponding round in the table will be highlighted in a different color (default #fdf5e6, governed by .scoreboard .currentRound). If the value is not a number, or there is no round corresponding to its value, it is ignored.
editPaneTitle 'Set score' Sets the title of the overlay opened when clicking on a scoreboard.
firstColWidth 50 Sets the width, in pixels, of the first column.
playersInColumns true When true, player scores are displayed in columns with the player name in the top header row. When false, player scores are displayed in rows with the player names in the far left column.
roundLabel 'Round' The text for the column or row of round names.
rounds null When null, the rounds are filled out with consecutive whole numbers starting with 1. Otherwise, this should be an array containing the names of the various scoring rounds. If there are fewer rounds in this array than there are scoring rounds, subsequent round names will be blank.
scoreProperty 'score' Says which field in the associated seats will be displayed in the scoreboard. Each seat with an active player should have an array or scalar property with this name. If it is an array, the elements of the array will be used for scoring the various rounds. Otherwise, if it is just a number, that value will be used for the total and no round-by-round scoring will be done for that player. Strings are converted to numbers if possible (for example, "7" is converted to 7). Non-numbers displayed as-is but are treated as 0 for purposes of computing totals.
seats null This is used to specify seats, or alternatively to define teams, that will be displayed in the scoreboard. When null, all seats are included. See below for a more detailed discussion. See also showAllSeats.
showAllRounds false When false, only the first n round names are displayed in the scoreboard, where n is the length of the largest score array for the scoreboard. When true, all round names from the round array will be shown, even if there is no score in those rounds.
showAllSeats false When false, only seats with players in them are displayed in the scoreboard. When true, all seats specified by the seats property will be included in the scoreboard, even if nobody is sitting there.
showPlayerColors true When true, the row or column header containing each player's name will have that player's background color. Otherwise, all player name background colors will be gray.
showTotals true When true, a row (or column) will be added to the display in the scoreboard that will contain the sum of the scores for each seat or team. Note that non-numbers in the scores will be treated as zero.
sortAscending true When true, the sorting specified by sortField will be ascending. When false, the sorting specified by sortField will be descending.
sortField 'index' By default, sorting in the scoreboard is by the index property of the seat. This can be changed to be any property of a seat. It can also be set to total, which will sort by the scoreboard's calculated total row.
_totals (read-only) This property is an array of scores; the i th element of the array is the score for the player whose seat index is i. (Note that indices start at 1 in both cases; the zeroth element of the property array is null). Players not included in the scoreboard display have the corresponding elements of the array set to null. Non-numeric values are treated as 0. See below for more details.
totalsLabel 'Totals' This property is the text that displays on the totals row when showTotals is true.
verticalHeader false If set to true, the header text will be rotated 90 degrees so that it displays vertically.
width, height 300, 200 Same property as in the global properties but with a different default value.

To add basic scoreboard functionality to a room, add seats and a scoreboard using the Add Widget overlay. Then add a "score" property to each seat. The initial value of the score should be 0 if using totals only and [0] if using rounds. Players can then click on the scoreboard to update their scores. It is up to the game designer to keep the number of rounds in sync among the various seats if desired. Note in particular that if some seats in a scoreboard use rounds (i.e. their score property is an array) while others just use totals (i.e. their score property is just a number), the results are undefined.

The seats parameter can have several forms. If it is of the form

"seats": [ "Seat1", "Seat2", "Seat3" ]

where "Seat?" is a seat widget id, then these three seats will be included in the scoreboard display. (If seats is null, all seats in the room will be included). Alternatively, "seast": "Seat1" is shorthand for "seats": [ "Seat1" ].

If instead seats is of the form

"seats": {
  "team1": ["Seat1", "Seat4"],
  "team2": ["Seat2", "Seat3"]
}

then this defines two teams, named team1 and team2. The scoreboard will display, in each round, the combined scores of the seats participating in that team. Note that the team scores will be displayed in the order in which they were specified in the parameter, and that sortField and showPlayerColors are ignored. Again, "team1": "Seat1" is shorthand for "team1": ["Seat1"].

In all forms, the seats that are actually displayed are also modified by the showAllSeats parameter.

If seats specifies an array of seats (or is null), then the _totals property is an array as described above. If it specifies teams, then _totals is an array whose zeroth entry is null and whose subsequent entries are the total score for each team in turn, again in the same order as specified in the seats parameter. In all cases, if showTotals is false, _totals will be null.

Clicking on a scoreboard will bring up a dialog that allows the user to set the score of any existing round (or to add a new round) of any player in that scoreboard (or, if the scoreboard shows totals only, to set the total for any player). Note that the current value of the player's score is not populated in the edit field. However, the playerName and `currentRound are pre-selected in the drop-down menu.

Seat

Seats are a indicators of a player's position (seat) in the room. Seats take on the playerColor of the player in the seat and can be used to indicate whose turn it is by a glow effect.

Click to see tutorial

Property Default value Description
borderRadius 5 Same property as in the global properties but with a different default value.
color playerColor The color can be any value supported by CSS. It is exposed as the CSS variable --color, and controls the color of the border of an occupied seat widget. The property may be altered in code to change the displayed border color.
colorEmpty #999999 The color can be any value supported by CSS. It is exposed as the CSS variable --color, and controls the color of the border of an unoccupied seat widget. The property may be altered in code to change the displayed border color.
display 'playerName' The text to display when a seat is occupied. This can be an arbitrary string. Before display, all instances of 'playerName' will be replaced by player, and all instances of 'seatIndex' will be replaced by index.
displayEmpty 'click to sit' The text to display in an empty seat.
hand 'hand' The widget id of the players hand. (Note that the first hand added to a table will by default be given the id hand.)
hideTurn false If false, seat will glow when turn is true.
hideWhenUnused false If true, this seat will be hidden to players already seated if it is empty. (PCIO compatibility)
index 1 The position of this seat at the table. Although it can be something other than a number, some features of VTT (including the TURN function and scoreboards) will not work correctly if it is not a number. When adding a seat through the Add Widget interface or the JSON Editor duplicate widget button, the index number is automatically set to the next higher number. If you copy and paste the seat, you will need to manually change the index.
layer -1 Same property as in the global properties but with a different default value. Above boards, holders, labels, and piles; at the same level as buttons and timers.
movable false Same property as in the global properties but with a different default value.
player '' When a seat is empty, this property will be ''. When someone sits down, the default value of this property will be the playerName. The property may be altered in code to change the displayed player name.
score null Used in connection with a scoreboard widget to indicate the score value for that seat. Can be scalar or an array.
skipTurn false Any seat(s) with this property set to true will be skipped during a TURN function. However, if the turn is set using "turnCycle":"seat", then that overrides "skipTurn":true on a seat.
turn false Indicates whether it is this seat's turn (true) or not (false).
typeClasses "widget seat" Same property as in the global properties but with a different default value. This gives the seat its default appearance. No guarantees if you change this.
width, height 400, 150 Same property as in the global properties but with a different default value.

Spinner

Spinners are round objects with an arrow that spins when clicked to indicate a random selection.

Click to see tutorial

Property Default value Description
angle 0 The angle of the arrow in degrees. It determines the value but if you edit the widget directly, they can differ until someone spins the spinner again. Right is 0, Bottom is 90.
backgroundCSS "" Custom CSS that will be added to the generated background SVG (the options).
borderRadius "50%" Same property as in the global properties but with a different default value. Does not impact spinner appearance because the spinner face is a child element of the widget.
lineColor "'#d2d2d2'" Changes the color of the lines that divides the options.
movable false Same property as in the global properties but with a different default value.
options [1,2,3,4,5,6] The different values the spinner can output. The default is equivalent to a normal die.
spinnerCSS "" Custom CSS that will be added to the spinning arrow (the arrow itself is the background-image).
textColor "#000000" Changes the font color of the spinner's options.
typeClasses "widget spinner" Same property as in the global properties but with a different default value. Without "spinner" the spinner will die a horrible death.
value "🎲" The current value of the spinner that is displayed on top of it. Changed when clicking/spinning it.
valueCSS "" Custom CSS that will be added to the overlay circle that shows the current value.
width, height 110 Same property as in the global properties but with a different default value. Non-square spinners probably break in horrible ways.

Timer

Timers can be used to count up to (or down to) a prespecified value. Each time precision milliseconds passes, the milliseconds property of the timer is updated. This can be used in conjunction with a changeRoutine to cause an action to happen on a regular basis.

Click to see tutorial

Property Default value Description
alert false If set to true the timer color is set to red. When end time is set and timer reaches the end time, this property changes to true automatically.
countdown false If set to true the timer will countdown when activated.
end null Time, in milliseconds, used as a reference to activate the alert property.
height 36 Same property as in the global properties but with a different default value.
layer -1 Same property as in the global properties but with a different default value. Above boards and holders but below everything else.
milliseconds 0 Time displayed by the timer. This value is converted to minutes and seconds in the timer.
movable false Same property as in the global properties but with a different default value.
paused true If set to false the timer will start running.
precision 1000 Time, in milliseconds, between each update of the property "milliseconds." Values below 100 (1/10 of a second) will be converted to 100 although the user entered value will still be displayed
start 0 Time used by click routines to reset the timer.
typeClasses "widget timer" Same property as in the global properties but with a different default value. Without "widget timer" the css for the timer will be the same as for a default widget.
width 74 Same property as in the global properties but with a different default value.

Widget Colors

Each widget has a variety of preset colors, most of which can be changed through widget-specific properties or through CSS. The following table is a listing of those colors in case you want to match or coordinate other widgets in your room with those default colors. A few of them have names listed in parenthesis after the color value. You can substitute directly for that color by using the format “var(--VTTblue)” in lieu of a hexadecimal value, where –VTTblue is one of the listed names. The room background color is not in the table as it is not a widget, but the color is #f0f0f0 (--room Color).

Widget Type Component Color Value
Basic widget Text #000000
Game pieces* Purple
Blue
Green
Yellow
Orange
Red
Black
Grey
White
#bc5bee
#4c5fea
#23ca5b
#e0cb0b
#e2a633
#e84242
#000000
#4a4a4a
#ffffff
Button Background
Background onhover
Border
Border onhover
Text
#1f5ca6 (--VTTblue)
#0d2f5e (--VTTblueDark)
#0d2f5e (--VTTblueDark)
#1f5ca6 (--VTTblue)
#ffffff (--wcFont)
Canvas Border
Background
Reset button background
Reset button background onhover
Color button background
Reset and Color buttons border
Reset and Color buttons onhover border
#1f5ca6 (--VTTblue)
#f0f0f0 (--room Color)
#1f5ca6 (--VTTblue)
#0d2f5e (--VTTblueDark)
Varies but starts as #1f5ca6 (--VTTblue)
#555
black
Holder Background
Border color (top and left)
Border color (bottom and right)
Border color onhover
white
#d8d8d8
#ccc
#333
Label Text #6d6d6d
Pile handle Background
Text
#e4e4e4
#6d6d6d
Scoreboard Overall background for vacant areas
Cell background
Border
Header/Footer Row/Column background
Current row
Cell borders
Text
white
#f8f8f8
black
#ddd
#fdf5e6
#ddd
#333
Seat Background
Text
Border when vacant
#ffffff
#222222
#999999
Spinner Solid center area
Rotating swirling area
Center text
List of values text around edge
Border
Arrow
Background
#1f5ca6 (--VTTblue)
#1f5ca6 (--VTTblue) and #a9c6e8 (--VTTblueLight)
#ffffffblack
#d2d2d2
#222222
white
Timer Buttons
Numbers text when active
Numbers text when paused
Numbers text when alert
Same as button widget
#525252
#6d6d6d
red

*Notes: The pin piece has additional properties that give it a 3D effect. The color for the crown and inner ring of the checker is the same hexadecimal value with 51 added at the end for opacity. For example, purple would be #bc5bee51.

Clone this wiki locally