script
Experiments Surveys & forms The start stage runs before any row; the end stage runs only after test rows and form pages.
script injects custom JavaScript into a trial. Use it to keep running tallies across trials (error counts, scores), build lists of responses for later trials, compute a completion code, or run arbitrary side effects. The cell is raw JavaScript, prepared once per row when the experiment loads.
There are exactly two execution moments per trial:
- start stage: runs right before the trial’s screens are shown, for every displayed row of any type.
- end stage: runs when the trial’s response is saved, but ONLY for
type: testrows and form trials. Practice, learn and instructions rows never run the end stage, and CFPT trials do not either.
Syntax
Section titled “Syntax”Write plain JavaScript in the cell. It runs at the start of the trial, just before anything is shown.
To run code after the response instead, put it below a line beginning with end:. Everything before that line is the start stage, everything after it is the end stage. The end: must start its own line inside the (quoted, multi-line) cell, and a cell that starts with end: has an end stage only.
Inside a script, %name% placeholders stand for values Testable keeps for you:
%response%,%RT%and%correct%(in exactly that spelling) are the recorded response, reaction time and correctness. On their own they are the most recent one; a negative suffix steps back through the history, so%response-1%is the response before the most recent.- A positive suffix is a trial-file row number, counting the header as row 1:
%response2%is the first data row’s response. - Any other name, such as
%errors%, is a variable of your own. It keeps its value for the rest of the session and is available to every later trial. - A variable you have never set, whose name matches one of your stimulus lists, starts out as a copy of that list.
Two helper functions are available:
addToList(%listName%, value)appends to one of your own lists, starting it from the stimulus list of the same name if it does not exist yet. A string value containing;is split into several items.skipTrial()immediately advances to the next trial. It does nothing on the last trial or after the end screen.
Options
Section titled “Options”| Cell value | Behavior |
|---|---|
| empty | No scripts for this row |
| JavaScript only | Taken as the start stage, runs before the trial displays |
JavaScript, then a line starting end:, then more JavaScript | Start stage plus end stage; the end stage runs when the response is saved, on test and form trials only |
end: as the first line, then JavaScript | Empty start stage, end stage only |
%response% / %RT% / %correct% (+ optional integer suffix) | Replaced with the recorded response, reaction time or correctness |
%anythingElse% | A variable of your own, kept for the whole session |
%completionCode% (a variable of your own, by the mechanism above) | If set, its value replaces the generated completion code on the end screen, but only when the project has completion codes enabled and set to a random (not fixed) code; it is excluded from the tallies output |
Defaults & missing values
Section titled “Defaults & missing values”An empty cell means the row runs no script at all, in either stage, and a file without a script column simply runs no scripts.
Your own variables start out unset: reading one before you have assigned to it gives undefined, unless its name matches one of your stimulus lists, in which case it starts as a copy of that list.
Works with
Section titled “Works with”- Results: after every saved trial, all of your variables are written into the
talliesresults column asname : value;pairs, and a final snapshot is stored with the session summary.completionCodeis left out of both. - Text columns:
%name%placeholders in displayed text are replaced with your variables’ values as the text is shown. Numbers get two decimals, so2.5appears as2.50. - Dynamic stim lists: they read your own lists, so an
addToListin an end stage can feed the stimuli of later trials. - Quotes and tabs: curly (smart) quotes are turned into straight quotes before the script runs, and tab characters become
\t. - then and key:
thenandkeylogic is separate, andscripttakes no part in branching or scoring. A start-stage script can, however, callskipTrial().
Examples
Section titled “Examples”- Count errors on test trials (end stage, so
%correct%is the current trial’s correctness):
| type | stim1 | key | script |
|---|---|---|---|
| test | word_a | f | end: |
| if(%correct% == 0){ %errors% = (%errors% || 0) + 1; }" |
type,stim1,key,script
test,word_a,f,"end:
if(%correct% == 0){ %errors% = (%errors% || 0) + 1; }"errors : N; appears in the tallies column of every subsequent saved trial.
- Custom completion code, set on the first row (start stage):
| type | content | button1 | script |
|---|---|---|---|
| instructions | Welcome | NEXT | %completionCode% = 'AB' + Math.floor(Math.random()*90000 + 10000); |
type,content,button1,script instructions,Welcome,NEXT,%completionCode% = 'AB' + Math.floor(Math.random()*90000 + 10000);
The end screen shows this value as the completion code.
- Collect each response into a list for a later dynamic list:
| type | stim1 | script |
|---|---|---|
| test | pick a word | end: |
| addToList(%chosenWords% | %response%)" |
type,stim1,script test,pick a word,"end: addToList(%chosenWords%, %response%)"
Each response is appended to a list called chosenWords, which later trials can draw their stimuli from.
Tips & gotchas
Section titled “Tips & gotchas”- There are only two stages, start and end. There are no
beforeScreen,afterScreen,keypressorresponseevents, and noevent: code;inline syntax. - The end stage only ever fires on test and form trials. An
end:stage on a practice, learn, instructions or CFPT row is never executed, and thetalliesresults column likewise only gets a row per saved test or form trial. - Errors raised while a script is running are not caught either: they stop the trial.
addToListsilently ignores empty values: appending0, an empty string,nullor an unset variable does nothing.- Case matters for the reserved names:
%Response%is a variable of your own calledResponse, not the response history. %response1%is always undefined, because row 1 is the header row.- In the start stage,
%response%,%RT%and%correct%refer to the PREVIOUS trial, because the current one has not run yet; in the end stage they refer to the current trial. - The
.randomand.samplesuffixes are ignored here:%list.random%in a script cell is just the variablelist. Those suffixes only work in stimulus and text columns. - Only the first
end:line splits the cell; anything after a secondend:line is silently dropped. - Keep each
addToList(...)call on its own line, and do not put a second call or a trailing)on the same line. - Your variables live only for the session; the
talliescolumn is the record that survives. response,RTandcorrectcannot be used as names for your own variables.