This entry explained how to use the JSON Editor prior to September 20, 2023 when PR 1482 was merged and created the new edit mode. This information is now out of date. Refer to the Edit Mode wiki entry for information about current functions and capabilities.
The JSON editor provides the ability to directly edit the JSON defining all the game elements in a live visual environment. You can add, remove, or edit widgets, execute game elements, and examine trace information that can help you diagnose problems.
- Overview
- Selecting widgets
- Editing widgets
- Interpreting trace information
- Using the global commands
- Duplicating and aligning widgets
Overview
From the game screens, pressing Ctrl-J will enter the JSON editor. (Another Ctrl-J will return you to normal game mode.) You will be presented with a screen similar to this:
As you can see, the room containing the game takes up the left-hand portion of the screen. To its right, in the editing area, is a tree listing of each widget in the game, showing widget types, location, and parent relationships; below it is an area (currently empty) that will contain the JSON describing a widget during widget editing. The upper portion of the right-hand area contains commands that are applicable in most situations (such as adding or deleting a widget, zooming in, and the like), while the area below that, currently containing only the words "No widget selected.", will contain buttons that allow you to insert context-specific properties into the widget being edited.
Selecting widgets
There are several ways to select a widget for editing:
-
If no widgets are currently selected, a Ctrl-click in the room will select the topmost widget at that location. By default, in most cases the selected widget will also be outlined in yellow in the room, so that you can tell which widget in the room you have actually selected. (There are cases, mostly involving widgets with CSS masks, in which the yellow outline will not be displayed). You can turn off the highlighting by clicking on the yellow flashlight in the global commands area in the upper right-hand corner.
-
If one or more widgets is currently selected, a Ctrl-Shift-click (for PC) or Ctrl-click (for Mac) will add the selected widget to the set of selected widgets. See more on multi-select editing below.
-
If you hover over a point in the room, the widgets at that point will be displayed above the room area: /images/fkeys.png In the image above, the cursor was above the pawn on the h7 square (the square containing the rightmost black pawn). The widgets at that point are displayed at top left. You can see from this that the h7 square itself is a holder and that the pawn is a basic widget. If, without moving the mouse, you press F2, the black pawn will be selected for editing (and any other already-selected widgets will be deselected). You can also press F1 to select the H7 holder for editing.
-
If you click on a widget in the tree, that widget will be selected. To select multiple widgets using the tree, use Shift-click (PC and Mac).
-
If you click in the white typing box at the top of the tree, all widgets in the room will be listed alphabetically without regard to parent. Entering text in that box will narrow the search results to anything including the text that you enter. For example, just entering the number 4 will make the tree display all widgets with the number 4 anywhere in the id. The search feature also works on widget types, so entering "holder" will find all widgets with "holder" in their id or their type. Clicking on one of the available widgets in the search results will select that widget for editing.
-
If you are examining a widget's JSON in the editing area, you can highlight the id of a referenced widget (for example, its parent); at that point, a button labeled "open widget by ID" will appear in the context commands panel. Clicking that button will select the referenced widget and display it in the editing area instead of the current widget.
Once a widget is selected, the JSON for that widget will be displayed in the editing area if it is the only widget selected. Additionally, the selected widget will be highlighted in the tree, and will be centered in the tree display. The size of the tree display will be reduced to allow more space for the widget's code. You can manually resize the tree display by clicking and dragging the gray bar between the tree and the widget's code. If multiple widgets have been selected, the editing area will show their widget ids together with their x
, y
, width
, height
, parent
, z
, and layer
properties. Additional properties can be added to the list by clicking on the "add property" button that appears in the context-specific area when multiple widgets are selected. Then enter the name of the property in the white typing area and press the Go button. Then scroll to the bottom of the widget and enter the new property value after the property name. It will be applied to all selected widgets. In any event, the displayed JSON can be edited in place.
Editing widgets
Widget JSON displayed in the editing area is color-coded to make it easier for the user to interpret. Further, commands are made available in the context-specific area that correspond to the place in the JSON where the cursor is. Note that syntax highlighting and command context detection work best when the JSON is formatted like the editor does when loading a widget. If you are having issues in this regard, try reselecting the widget.
The coloring conventions used are as follows; you can compare these with the screenshot below to see how the various elements appear:
- Gray: used to indicate a default property and value, or the
var
keyword. - Yellow: used for properties and other keys.
- Orange: used for custom properties or keys added by the game room designer and unique to certain widget(s) in that room. This includes the names of custom variables.
- Teal: used for variable references (items enclosed in
${}
). - Red: used for
cardType
andcardDefault
. Also used in the context commands panel to indicate an error in the JSON. - Green: used for strings contained within quotation marks.
- Purple: used for numbers (treated as numbers, rather than strings)
- Blue: used for
true
,false
, andnull
. - White: Once you type or paste something in the editing area, it will automatically be colorized in most situations. If it is invalid JSON, it will remain white, and an error indication will appear in the context panel (see below for more information). There are also cases where the JSON is valid but cannot be interpreted properly by the colorization code, and it will remain white. In this case, reselecting the widget should solve the problem.
When you place the cursor at some point in the JSON, a set of commands will appear in the context commands panel. In the screenshot below, the "K" key was selected, either by Ctrl-clicking on it or by clicking "letterK" in the tree display. Then, the cursor was placed in the highlighted area. (Note: you do not need to highlight information to use the context-dependent menus. All you need do is to click where you want to edit. The screenshot highlighted this area to make it easier to describe where the cursor was.)
The actions you are likely to want to take are divided into several sections, with the most local (deeply nested) section first. The first section, then, presents several likely replacements for the value of the property
key. The second section gives additional properties you might wish to add to the SET
function, and the third gives additional functions that you might want to add to the thenRoutine
. There are additional sections further down, reachable by scrolling, that contain information for outer contexts.
Clicking on any of the blue buttons in this section will take the appropriate action. For the buttons in the first group, it will replace the existing property value clickable
with the chosen item; for buttons in the other two groups, a new key or function will be added.
In general, the code tries to figure out where the most likely desired location is for a new function. But it is always worth checking to make sure that the software correctly interpreted your intentions.
Note that changes you make take effect immediately, and that at present there is no undo capability in the editor except for whatever might be provided by your browser or operating system.
If your edits produce syntactically invalid JSON, the changes will not take effect, and the context area will be replaced by information similar to the screenshot below:
When this happens, entering Ctrl-space will move the cursor to the most likely location of the error. Generally this is a nesting error, or an extra or missing comma or quote mark.
Interpreting trace information
If you want to follow along with this portion of the documentation in a live room, load up the Hangman game from the Public Games section. Start a game by pressing the "1 player button", then select the "J" button and press that button in the room. Then click on the bug icon (Toggle debug information) in the upper right-hand corner. The bug will turn from white to yellow and you should see the following screen (the context-specific column is not shown):
The first line indicates that what follows is the clickRoutine
for the letter J
widget. Each line after that is a single function in that routine; by comparing with the text at the right, you can see that this is the case. the information on each line tells you what was done, and what the results were. For example, the first line inverts the clickable
property for the widgets in thisButton
(which contains only letter J
), while the second line puts the widget mainCheck
into the DEFAULT
collection. At the end of the line, in yellow, is the time in milliseconds that it took to complete the operation. If you notice lag time in your room during routine execution, you can look at these times to get an idea of where the slowdown is taking place.
You can get more detail on any of these operations by clicking on a line with a triangle on it. For example, clicking on the final line produces
Here you can see what happened when the letter J
routine caused a click on each button in the DEFAULT
collection (in this case, the mainCheck
button). The purpose of this routine is to check if the guessed letter is in fact in the word, and to fill the appropriate blanks with the letter if it matches.
Next, note that the CLICK
function in the letter J
clickRoutine
has no explicit parameters. To see how this function was interpreted, click on the line labeled "Original and applied operation". This shows you the function as it appears in the JSON together with the fully expanded version:
If the original function invocation had had a variable expansion, for example
{
"func": "CLICK",
"count": "${number}"
}
then the applied operation would show you what value had been substituted for ${number}
.
If you also click on the final line in the CLICK
function invocation, labeled "Variables and collections afterwards", you will see all the variables and collections that are defined at the end of that function invocation.
Finally, suppose that your JSON contained some error. For example, if you change the relation
in the letter J
clickRoutine
to "no such relation"
and click the button, the debug information, after a little bit of expansion, looks like this:
From this, you can find, from the red text, the offending statement, together with an explanation of what is wrong. If the erroneous statement is nested within some routines or other nested construct, the expandable arrows for the ancestors of that statement will be red as well. This allows you to quickly locate any erroneous statements.
Using the global commands
At the top of the right-hand column are a number of buttons that are always available for use. (There are some situations in which one or more of them will be disabled because their use doesn't make sense in the current situation.)
These buttons perform the following functions. The descriptions below are in the same order as the buttons themselves:
- Toggle zoom: Normally the room pane shows only the widgets whose xy coordinates place them in the visible room. Clicking this button will zoom the view out so that you can examine offscreen widgets as well. Any such widgets can be edited in the normal manner. The button turns yellow when zoomed in and is white when zoomed out.
- Copy state from another room/server: This button requests a URL, then replaces the current contents of the room by the room at that URL. If the URL does not specify a valid VTT room, the command silently has no effect.
- Macro: This button brings up a JavaScript code snippet in the editing area:
As noted in the comment in the screen, any macro defined here will be executed for each widget in the room. This allows you to code an arbitrarily complex set of actions to take on various widgets. Pressing the macro button again (which now appears as ▶) will execute the macro. [NOTE: Macro execution will proceed without a request for confirmation, and cannot be undone. It is very easy to completely mess up your room. We strongly suggest that you back up your VTT file before executing a macro. It should be obvious that some knowledge of JavaScript and the code base would be useful if you want to use this feature.]
- Show this widget below: This button shows an uncolorized copy of the current widget's JSON at the bottom of the context-specific panel. This can be useful if you want to navigate to another widget but want to be able to simultaneously view the current widget.
- Reverse order of F-key shortcuts: Initially, when the mouse is over a point containing multiple widgets, the widgets are assigned F-keys with the topmost widget getting F1. Clicking this button will reverse the ordering so that the bottom-most widget will instead get F1. Note that regardless of this setting, cards are always sorted below (assigned higher F-key numbers) than other widgets, and that widgets owned by a different player are always sorted below cards.
- Add new widget: Pressing this button will bring up a screen that allows you to add a widget from a selection of predefined widgets including all the common widget types.
- Remove widget: This button will remove the currently selected widget(s) from the game. NOTE: this action will occur immediately, without a request for confirmation, and cannot be undone.
- Duplicate widget: Pressing this button will allow you to make one or more duplicates of the selected widget (or widgets, if more than one is selected). See the section on duplicating widgets below for more information.
- Edit mode: This button sets the room into edit mode, so that you are then running the basic editor inside the JSON editor. The button is yellow when in edit mode and white when in normal mode.
- Open parent: This button selects the parent of the selected widget. It is disabled if the selected widget has no parent, or if more than one widget is selected.
- Toggle wide: This button controls the relative width of the room area. At startup, the button is white and the room consumes about 2/3 of the entire window width, and the remaining width is divided between the editing pane and the commands pane. If you click this button, it turns yellow and the amount of space taken up by the room will be reduced to about half the window width. This can be useful if you are looking at the JSON for a complicated, deeply nested routine.
- Toggle highlighting: This button, initially on (yellow), controls whether selected widgets are highlighted in the room. If clicked, the button turns off (white) and the selected widgets will still be highlighted in the widget tree display, but there will be no yellow highlight around the widgets in the room.
- Toggle debug information: When clicked, this button turns yellow and displays the debug trace information in place of the room area of the screen. Click it again to hide the debug trace display and turn the button white.
Duplicating and aligning widgets
When duplicating a widget (using the yellow stars button), you will see the following options:
- Increment IDs controls how the widget
id
for created widgets is determined. The default is Numbers. With this setting, the last set of numbers in the source widget will be incremented for successive duplicates. For example,v1x8
will have successive duplicates namedv1x9
,v1x10
, andv1x11
. If the source widget has no numbers in it, the first duplicate will have a1
appended. Thusvaxb
duplicates tovaxb1
,vaxb2
, and so forth. If you select Letters, the last set of capital letters in the source widget will be lexically incremented. Thus for examplePlayerA
is duplicated toPlayerB
,PlayerC
, and so forth. If the last set of capital letters consists of allZ
s, the next value will be determined in "Excel style". Thus for example the widgets afterPlayerZZ
arePlayerAAA
,PlayerAAB
, andPlayerAAC
. If the widget has no capital letters, the first duplicate will have anA
appended, similarly to the Numbers case. If you select None, widget copies will be given randomid
s. - Increment In defaults to
dropTarget, hand, index, inheritFrom, linkedToSeat, onlyVisibleForSeat, text
. You can remove any of the default properties from the list or add other standard or custom properties. This setting is ignored if Increment IDs is None. Otherwise, for each of those properties, if theid
contains a number (if Numbers is selected) or a letter (if Letters is selected) and if the the value of that property contains the same number or last capital letter as in theid
, then those properties will also be incremented in exactly the same way theid
is. For example, if"id":"widget1"
and"linkedToSeat":"seat1"
, then the next copy will have"id":"widget2"
and"linkedToSeat":"seat2"
. - Copy using inheritFrom is not initially selected. Selecting it means that all copied widgets will have the
inheritFrom
property applied rather than duplicating all of the source widget's properties. You can learn more about that at Global properties for every widget. - Inherit properties is ignored if Copy using inheritFrom is unchecked. Otherwise, this allows you to select the individual properties that will be inherited from the specified widget. If the box is empty, all heritable properties will be inherited.
- Recursive is initially selected. Leaving it selected means that all child widgets of the widget(s) being duplicated will also be duplicated and their parent properties will automatically be updated.
- X offset and Y offset each default to
0
. Change this (to a positive or negative number) to make the copied widgets appear in a different location on the screen. For example, if the x value is set to 25 and you are making 3 copies of a widget at x coordinate 100, the first copy will be at 125, the second at 150, and the third at 175. - # Copies X and # Copies Y: X defaults to 1 and Y defaults to 0. Use this to set the number of copies across (x) or up/down (y). If you set a value in both x and y, a grid of copies will be made.
To align widgets, multi-select the widgets you want (see Selecting widgets for how). Then in the widget code area, put the cursor on either the x or y value that you want to modify. You will then see blue buttons with options to align, center in parent or distribute. Once you select the desired option, additional menu options will be presented to determine which coordinates to apply (center, top left, or bottom right), and which widget value to use as the baseline. Press the Go button to implement the change. As with many things in the JSON Editor, the effect is immediate and not reversible. So make a back-up copy of your room before changing the location of a lot of widgets.
If you want to practice more with the JSON Editor, the JSON Editor User Guide in the tutorials section of the public library (also available at https://virtualtabletop.io/Tutorials) has some hands on demonstrations. The tutorial will lag slightly behind the wiki when new features are added. For example, the tutorial currently does not discuss the widget tree as currently implemented.
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
- Available icons, card backs, button styles, and other images
- Demonstration Features
- Useful Code 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