Skip to content

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: test rows and form trials. Practice, learn and instructions rows never run the end stage, and CFPT trials do not either.

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.
Cell valueBehavior
emptyNo scripts for this row
JavaScript onlyTaken as the start stage, runs before the trial displays
JavaScript, then a line starting end:, then more JavaScriptStart 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 JavaScriptEmpty 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

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.

  • Results: after every saved trial, all of your variables are written into the tallies results column as name : value; pairs, and a final snapshot is stored with the session summary. completionCode is 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, so 2.5 appears as 2.50.
  • Dynamic stim lists: they read your own lists, so an addToList in 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: then and key logic is separate, and script takes no part in branching or scoring. A start-stage script can, however, call skipTrial().
  1. Count errors on test trials (end stage, so %correct% is the current trial’s correctness):
typestim1keyscript
testword_afend:
if(%correct% == 0){ %errors% = (%errors% || 0) + 1; }"

errors : N; appears in the tallies column of every subsequent saved trial.

  1. Custom completion code, set on the first row (start stage):
typecontentbutton1script
instructionsWelcomeNEXT%completionCode% = 'AB' + Math.floor(Math.random()*90000 + 10000);

The end screen shows this value as the completion code.

  1. Collect each response into a list for a later dynamic list:
typestim1script
testpick a wordend:
addToList(%chosenWords% %response%)"

Each response is appended to a list called chosenWords, which later trials can draw their stimuli from.

  • There are only two stages, start and end. There are no beforeScreen, afterScreen, keypress or response events, and no event: 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 the tallies results 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.
  • addToList silently ignores empty values: appending 0, an empty string, null or an unset variable does nothing.
  • Case matters for the reserved names: %Response% is a variable of your own called Response, 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 .random and .sample suffixes are ignored here: %list.random% in a script cell is just the variable list. Those suffixes only work in stimulus and text columns.
  • Only the first end: line splits the cell; anything after a second end: 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 tallies column is the record that survives.
  • response, RT and correct cannot be used as names for your own variables.