From 208db50aceab72cb0f3215583fc7ec3800b4ef9c Mon Sep 17 00:00:00 2001
From: docs-bot About jsPsychjsPsych was created by Josh de Leeuw.
If you use this library in academic work, the preferred citation is:
+de Leeuw, J.R., Gilbert, R.A., & Luchterhandt, B. (2023). jsPsych: Enabling an open-source collaborative ecosystem of behavioral experiments. Journal of Open Source Software, 8(85), 5351, https://joss.theoj.org/papers/10.21105/joss.05351.
+
This paper is an updated description of jsPsych and includes all current core team members. It replaces the earlier paper that described jsPsych:
+de Leeuw, J.R. (2015). jsPsych: A JavaScript library for creating behavioral experiments in a Web browser. Behavior Research Methods, 47(1), 1-12. doi:10.3758/s13428-014-0458-y
+
Citations help us demonstrate that this library is used and valued, which allows us to continue working on it.
+jsPsych is an open-source, collaborative ecosystem, and many of the plugins/extensions you end up using may be contributed by third-party developers! We want to make sure they get recognition for their good work, so we made a command-line citation tool that you should use to cite this library and the plugins/extensions used in your experiment. You can see this tool in action by following these steps:
+jsPsych.getCitations()
This should print the APA format citation for the jsPsych library, which you can then copy and paste into your working document. To cite the plugins/extensions in your experiment, you should pass in an array containing the name of each plugin/extension to generate a list of citations, e.g. jsPsych.getCitations([jsPsychHtmlKeyboardResponse, jsPsychMouseTrackingExtension])
. You can also pass in the desired output citation format as the second argument, e.g. jsPsych.getCitations([jsPsychHtmlKeyboardResponse, jsPsychMouseTrackingExtension], "apa")
. We currently support APA formatting ("apa"
) and BibTex formatting ("bibtex"
).
A changeset must be included in the pull request. We use changesets to generate new releases and their corresponding release notes. This is a good overview of changesets that explains how to add one to your pull request. Feel free to ask for help with this!
jspsych
vs. jspsych-contrib
¶
If you are developing a new plugin or extension there are two different repositories that you can contribute to: jspsych
or jspsych-contrib
.
The main jspsych
repository is open to new plugins and extensions that are likely to be widely used. We require that contributions to main repository are well documented and tested before they are merged. Contributions to the main repository must use TypeScript. We limit contributions to this repository because once a plugin or extension is in the main codebase we are generally committed to providing updates as we develop new versions of jsPsych. Each new plugin and extension potentially increases the amount of development work that we will need to do in the future, so we are somewhat selective about what we will merge. If you have an idea that you'd like to discuss please open a discussion thread and we'd love to chat about it!
The jspsych-contrib
repository is open to any contributions that are complete and working code. There are some minimal guidelines in place about basic documentation that should be provided. Contributors can choose whether to develop their plugin or extension using our TypeScript template or using our JavaScript template. Contributions to jspsych-contrib
are not evaluated for general usefulness in the same way that contributions to the main repository are. We also periodically consider whether to move contributions into the main repository from jspsych-contrib
based on their popularity and completeness (documentation and testing).
The jspsych-contrib
repository is open to any contributions that are complete and working code. There are some minimal guidelines in place about basic documentation that should be provided. Contributors can choose whether to develop their plugin or extension using our TypeScript template or using our JavaScript template. Check our plugin developer documentation for additional guidance.
Contributions to jspsych-contrib
are not evaluated for general usefulness in the same way that contributions to the main repository are. We also periodically consider whether to move contributions into the main repository from jspsych-contrib
based on their popularity and completeness (documentation and testing).
trial()
method that accepts an HTMLElement
as its first argument and an object
of trial parameters as its second argument. There is an optional third argument to handle the on_load
event in certain cirumstances. The trial()
method should either invoke jsPsych.finishTrial()
or should be an async
function that returns a data object to end the trial and save data.
info
property on the class that contains an object describing the plugin's parameters, data generated, and version.Plugins can be written in either plain JavaScript or in TypeScript. Template files for both JavaScript and TypeScript are available in the jspsych-contrib repository.
+Templates for plugins are available in the jspsych-contrib repository. Plugins can be written in either plain JavaScript or in TypeScript.
+To get started with a template, we recommend using the CLI tool that we have published in jspsych-contrib. This automates the setup of a new plugin in either JavaScript or TypeScript. Additional information about the CLI tool is available in the README
of jspsych-contrib.
The plugin's constructor()
will be passed a reference to the instance of the JsPsych
class that is running the experiment. The constructor should store this reference so that the plugin can access functionality from the core library and its modules.
If you are developing a plugin with the aim of including it in the main jsPsych repository we encourage you to follow the contribution guidelines.
We also recommend that you make your plugin as general as possible. Consider using parameters to give the user of the plugin as many options for customization as possible. For example, if you have any text that displays in the plugin including things like button labels, implement the text as a parameter. This allows users running experiments in other languages to replace text values as needed.
-Templates for plugins are available in the jspsych-contrib repository. There is a command-line tool for generating a new plugin from these templates in that repository. See the README file in the jspsych-contrib repository for more information.
diff --git a/v8/plugins/survey-multi-choice/index.html b/v8/plugins/survey-multi-choice/index.html index e062c31e75..a6b2c350bb 100644 --- a/v8/plugins/survey-multi-choice/index.html +++ b/v8/plugins/survey-multi-choice/index.html @@ -2921,7 +2921,7 @@Using the CDN-hosted JavaScript file:
-<script src="https://unpkg.com/@jspsych/plugin-survey-multi-choice@2.0.1"></script>
+<script src="https://unpkg.com/@jspsych/plugin-survey-multi-choice@2.0.2"></script>
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src="jspsych/plugin-survey-multi-choice.js"></script>
diff --git a/v8/reference/jspsych/index.html b/v8/reference/jspsych/index.html
index 9cae809552..f38981a369 100644
--- a/v8/reference/jspsych/index.html
+++ b/v8/reference/jspsych/index.html
@@ -1345,13 +1345,13 @@
-
+
- jsPsych.getCurrentTrial
+ jsPsych.getCitations
-
+jsPsych.getCitations¶
+jsPsych.getCitations(plugins, format)
+
+Parameters¶
+
+
+
+Parameter
+Type
+Description
+
+
+
+
+plugins
+array
+Array containing list of plugins/extensions by name.
+
+
+format
+string
+Output citation format ("apa"
+
+
+
+Return value¶
+String of generated citations in the specified format for the jsPsych library, followed by that for each input plugin/extension, separated with a "\n" character.
+Description¶
+Get citations in a specified format for the jsPsych library and input list of plugins/extensions, usually those used within an experiment.
+Example¶
+// in browser console
+jsPsych.getCitations() // prints citation for jsPsych library in APA format
+jsPsych.getCitations([TestPlugin], "bibtex") // prints citation for jsPsych library and TestPlugin (if different) in BibTex format
+
+
jsPsych.getCurrentTrial¶
jsPsych.getCurrentTrial()
-Parameters¶
+Parameters¶
None.
-Return value¶
+Return value¶
Returns the object describing the current trial. The object will contain all of the parameters associated with the current trial.
-Description¶
+Description¶
Get a description of the current trial
-Example¶
+Example¶
var trial = jsPsych.getCurrentTrial();
console.log('The current trial is using the '+trial.type+' plugin');
@@ -5411,13 +5548,13 @@ ExamplejsPsych.getDisplayElement¶
jsPsych.getDisplayElement()
-Parameters¶
+Parameters¶
None.
-Return value¶
+Return value¶
Returns the HTML DOM element used for displaying the experiment.
-Description¶
+Description¶
Get the DOM element that displays the experiment.
-Example¶
+Example¶
var el = jsPsych.getDisplayElement();
// hide the jsPsych display
@@ -5426,13 +5563,13 @@ jsPsych.getInitSettings¶
jsPsych.getInitSettings()
-Parameters¶
+Parameters¶
None
-Return value¶
+Return value¶
Returns the settings object used to initialize the experiment.
-Description¶
+Description¶
Gets the object containing the settings for the current experiment.
-Example¶
+Example¶
var settings = jsPsych.getInitSettings();
// check the experiment structure
@@ -5442,9 +5579,9 @@ ExamplejsPsych.getProgress¶
jsPsych.getProgress()
-Parameters¶
+Parameters¶
None.
-Return value¶
+Return value¶
Returns an object with the following properties:
@@ -5472,9 +5609,9 @@ Return valueDescription¶
+Description¶
This method returns information about the length of the experiment and the participant's current location in the experiment timeline.
-Example¶
+Example¶
var progress = jsPsych.getProgress();
alert('You have completed approximately '+progress.percent_complete+'% of the experiment');
@@ -5482,39 +5619,39 @@ ExamplejsPsych.getProgressBarCompleted¶
jsPsych.getProgressBarCompleted()
-Parameters¶
+Parameters¶
None.
-Return value¶
+Return value¶
Returns a value between 0 and 1 representing how full the progress bar currently is.
-Description¶
+Description¶
Used to get the current value of the progress bar. Works for automated and manual control.
-Example¶
+Example¶
var progress_bar_amount = jsPsych.getProgressBarCompleted();
jsPsych.getStartTime¶
jsPsych.getStartTime()
-Parameters¶
+Parameters¶
None.
-Return value¶
+Return value¶
Returns a Date
object indicating when the experiment began.
-Description¶
+Description¶
Get the time that the experiment began.
-Example¶
+Example¶
var start_time = jsPsych.getStartTime();
jsPsych.getTotalTime¶
jsPsych.getTotalTime()
-Parameters¶
+Parameters¶
None.
-Return value¶
+Return value¶
Returns a numeric value indicating the number of milliseconds since jsPsych.run
was called.
-Description¶
+Description¶
Gets the total time the participant has been in the experiment.
-Example¶
+Example¶
var time = jsPsych.getTotalTime();
console.log(time);
@@ -5522,13 +5659,13 @@ ExamplejsPsych.pauseExperiment¶
jsPsych.pauseExperiment()
-Parameters¶
+Parameters¶
None.
-Return value¶
+Return value¶
None.
-Description¶
+Description¶
Pauses the experiment. The experiment will finish the current trial, but will not execute any additional trials until jsPsych.resumeExperiment()
is called.
-Example¶
+Example¶
var trial = {
type: jsPsychHtmlKeyboardResponse,
stimulus: 'Press p to take a 30 second break. Otherwise, press c to continue immediately.',
@@ -5545,13 +5682,13 @@ ExamplejsPsych.resumeExperiment¶
jsPsych.resumeExperiment()
-Parameters¶
+Parameters¶
None.
-Return value¶
+Return value¶
None.
-Description¶
+Description¶
Resumes the experiment after a call to jsPsych.pauseExperiment()
. If the post trial delay (post_trial_gap
) has not yet been reached, then the experiment will not continue until the delay is finished. For example, if post_trial_gap
was 10,000ms and jsPsych.resumeExperiment()
was called 6,000ms after the previous trial finished, then the experiment would not continue for another 4,000ms.
-Example¶
+Example¶
var trial = {
type: jsPsychHtmlKeyboardResponse,
stimulus: 'Press p to take a 30 second break. Otherwise, press c to continue immediately.',
@@ -5568,7 +5705,7 @@ ExamplejsPsych.run¶
jsPsych.run(timeline)
-Parameters¶
+Parameters¶
@@ -5585,11 +5722,11 @@ Parameters
-Return value¶
+Return value¶
None.
-Description¶
+Description¶
Start the jsPsych experiment with the specified timeline.
-Example¶
+Example¶
var timeline = [trial1, trial2, trial3];
jsPsych.run(timeline);
@@ -5598,7 +5735,7 @@ ExamplejsPsych.setProgressBar¶
jsPsych.setProgressBar(value)
-Parameters¶
+Parameters¶
@@ -5615,18 +5752,18 @@ Parameters
-Return value¶
+Return value¶
None.
-Description¶
+Description¶
Set the progress bar to a custom amount. Proportion must be between 0 and 1. Values larger than 1 are treated as 1.
-Example¶
+Example¶
jsPsych.setProgressBar(0.85);
jsPsych.timelineVariable¶
jsPsych.timelineVariable(variable)
-Parameters¶
+Parameters¶
@@ -5643,9 +5780,9 @@ Parameters
-Return value¶
+Return value¶
Returns a placeholder object that jsPsych uses to evaluate the timeline variable when the trial runs.
-Description¶
+Description¶
Timeline variables are a powerful technique for generating experiments with repetitive procedures but different parameter values. This function fetches the current value of a particular timeline variable. It must be used in conjunction with a timeline that has timeline variables. See the timeline variable section for details.
Examples¶
Use as a parameter for a trial¶
@@ -5668,13 +5805,13 @@ Use as a parameter for a trialjsPsych.version¶
jsPsych.version()
-Parameters¶
+Parameters¶
None.
-Return value¶
+Return value¶
Returns the version number as a string.
-Description¶
+Description¶
Gets the version of jsPsych.
-Example¶
+Example¶
var version = jsPsych.version();
console.log(version);
diff --git a/v8/search/search_index.json b/v8/search/search_index.json
index e590608ece..ec8287a07d 100644
--- a/v8/search/search_index.json
+++ b/v8/search/search_index.json
@@ -1 +1 @@
-{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Introduction","text":"jsPsych is a JavaScript framework for creating behavioral experiments that run in a web browser.
Experiments in jsPsych are created using plugins. Each plugin defines different kinds of events, like showing an image on the screen, and collects different kinds of data, like recording which key was pressed at which time. You can use the plugins that are included with jsPsych, use plugins that are developed by community members in the contrib repository, or create your own plugins. By assembling different plugins together into a timeline, it is possible to create a wide range of experiments.
The page on timelines is a good place to start learning about jsPsych. From there, you might want to complete the hello world tutorial to learn how to set up a jsPsych experiment and the reaction time experiment tutorial to learn the core features of the framework.
"},{"location":"about/about/","title":"About jsPsych","text":"jsPsych is open source project with numerous contributors. The project is currently managed by the core team of Josh de Leeuw (@jodeleeuw), Becky Gilbert (@becky-gilbert), and Bj\u00f6rn Luchterhandt (@bjoluc).
jsPsych was created by Josh de Leeuw.
"},{"location":"about/about/#citation","title":"Citation","text":"If you use this library in academic work, the preferred citation is:
de Leeuw, J.R., Gilbert, R.A., & Luchterhandt, B. (2023). jsPsych: Enabling an open-source collaborative ecosystem of behavioral experiments. Journal of Open Source Software, 8(85), 5351, https://joss.theoj.org/papers/10.21105/joss.05351.
This paper is an updated description of jsPsych and includes all current core team members. It replaces the earlier paper that described jsPsych:
de Leeuw, J.R. (2015). jsPsych: A JavaScript library for creating behavioral experiments in a Web browser. Behavior Research Methods, 47(1), 1-12. doi:10.3758/s13428-014-0458-y
Citations help us demonstrate that this library is used and valued, which allows us to continue working on it.
"},{"location":"about/license/","title":"License","text":"jsPsych is licensed under the MIT license.
The MIT License (MIT)\n\nCopyright (c) 2014-2022 Joshua R. de Leeuw\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n
"},{"location":"developers/configuration/","title":"Configuring the jsPsych development environment","text":""},{"location":"developers/configuration/#setup","title":"Setup","text":"JsPsych is written using TypeScript, a superset of JavaScript that adds static typing, but compiles to plain JavaScript. The TypeScript compiler itself is written in JavaScript and can be run by Node.js, a runtime to execute JavaScript code without a web browser. Node.js comes with a package manager called NPM (Node Package Manager) that can install JavaScript libraries to run on your machine, such as TypeScript and other build tools for jsPsych. In order to work on code in the jsPsych or the jspsych-contrib repository, it is recommended that you follow the steps below to set up your development environment.
"},{"location":"developers/configuration/#install-nodejs","title":"Install Node.js","text":"The jsPsych development setup requires a Node.js LTS version to be installed on your machine.
"},{"location":"developers/configuration/#clone-the-repository-and-install-the-dependencies","title":"Clone the repository and install the dependencies","text":"Clone either the jsPsych repository or the jspsych-contrib repository by running
git clone https://github.com/jspsych/jsPsych.git && cd jsPsych\n
or
git clone https://github.com/jspsych/jspsych-contrib.git && cd jspsych-contrib\n
in a terminal.
Then run npm install
. This will create a node_modules
directory and install all the dependencies into it that are required to build and test jsPsych.
Info
The jsPsych (-contrib) repositories depend on the canvas
package which comes with pre-built binaries. On systems for which no pre-built binaries are available, npm install
will try to build the binaries from scratch, sometimes failing with an error message mentioning the canvas
package. If you are facing such installation issues, please follow the installation instructions of the canvas
package and run npm install
again afterwards.
Info
If you are running npm install
in the core jsPsych repository, this will also execute the build chain for all packages in the jsPsych repository. This step may take a few minutes. If you would like to use that time efficiently, consider reading the following two sections to know what's happening.
"},{"location":"developers/configuration/#repository-structure","title":"Repository structure","text":"A Node.js package is a directory that contains a package.json
file describing it. Most importantly, a package.json
file lists other packages that the package depends on. The jsPsych and jspsych-contrib repositories use NPM workspaces. That means, running npm install
in the repository root will install the dependencies for all packages in the packages
directory. The core jsPsych library and every jsPsych plugin or extension is laid out as an individual package. These packages are published to the NPM registry where they can be downloaded by NPM or any CDN (such as unpkg).
"},{"location":"developers/configuration/#build-chain-and-build-artifacts","title":"Build chain and build artifacts","text":"JsPsych comes with a build chain (specified in the @jspsych/config
package) that can be executed by running npm run build
in a package's directory. The build chain will read the package (starting at its src/index.ts
file) and create the following build artifacts in the package's dist
directory:
-
index.js
This file contains everything from index.ts
, but as plain JavaScript and bundled in a single file (i.e. without import
ing files from the same package). It is used by bundlers like webpack.
-
index.cjs
Like index.js
, but using the old CommonJS standard to support tools like the Jest testing framework.
-
index.browser.js
This file, like index.js
, contains the entire package as plain JavaScript, but this time wrapped in a function so that it can be included directly by browsers using the <script>
tag. For plugins or extensions, the default export of a module (i.e. whatever statement comes after export default
in the index.ts
file) is assigned to a global variable. The name of this global variable is specified in the package's rollup.config.mjs
file, as a parameter to the makeRollupConfig()
function. Hence, for instance, including the index.browser.js
file from the plugin-html-keyboard-response
package would assign the HtmlKeyboardResponsePlugin
class to the global jsPsychHtmlKeyboardResponse
variable. Because the code in index.browser.js
looks very similar to the index.ts
code but is fully supported by modern web browsers, all examples in the examples
directory reference the index.browser.js
files so users can also modify the source code directly without running the build chain.
-
index.browser.min.js
There are different versions of the JavaScript language specification and not all web browsers and browser versions support all JavaScript features. That's why the jsPsych build chain uses esbuild to translate the source files into code that a majority of web browsers can understand. The result of this operation is index.browser.min.js
. It behaves just like index.browser.js
, but adds support for older browsers by substituting new JavaScript features using older ones. Because this is the recommended build artifact for production use (and is automatically served by unpkg), the code in index.browser.min.js
is also minified to reduce its size and speed up experiment loading times.
-
*.js.map
When debugging code in a browser (especially index.browser.min.js
, which is minified and hence not easily readable), it is important to be able to read the original source code in the debugger. For every build artifact, there is a .map
file which contains a mapping of the generated code to the original source code. Browsers automatically read these .map
files and display the original code in their debuggers instead of the generated one.
-
index.d.ts
This file contains the TypeScript type definitions that would otherwise be lost during compilation to plain JavaScript. They are read by Typescript and editors when a package is imported into another TypeScript project.
"},{"location":"developers/configuration/#testing","title":"Testing","text":"Automated code testing for jsPsych is implemented with Jest.
To run the tests, install Node and npm. Run npm install
in the root jsPsych directory. Then run npm test
. You can also run npm test
in the directory of the package that you would like to test. For example, if you are developing tests for the html-keyboard-response
plugin you can run npm test
in /packages/plugin-html-keyboard-response
. If you want to run one file from the root directory, using the aforementioned example, you can run npm test -- /packages/plugin-html-keyboard-response/src/index.spec.ts
.
Tests for the core jsPsych library are located in /packages/jspsych/tests
.
Tests for plugins and extensions are located in the /src
folder of the corresponding package. Test files for plugins and extensions are named index.spec.ts
.
There are helper functions for testing in /packages/test-utils
. We recommend looking at other test files to observe conventions for testing.
"},{"location":"developers/contributing/","title":"Contributing to jsPsych","text":"We welcome contributions of all kinds, including changes to the core codebase, the development of new plugins and extensions, and improvements to the documentation.
The project is managed entirely through the GitHub repository. There you can:
- Use discussions to propose ideas for development and seek feedback on contributions, such as a new plugin.
- Use issues to identify anything with an actionable next step. For example, a page in the documentation that needs to be fixed, a bug in the code, or a specific feature that has a clear scope.
- Submit a pull request with modifications to the codebase. Pull requests will be reviewed by one or more members of the core team.
"},{"location":"developers/contributing/#guidelines-for-contibuting","title":"Guidelines for contibuting","text":""},{"location":"developers/contributing/#contributing-to-the-codebase","title":"Contributing to the codebase","text":"We welcome contributions of any scope. Before we can merge changes into the main codebase, we generally require a few things. Note that you are welcome to contribute code without these things in place, but it will help us get to your contribution faster if you take care of whatever components you are comfortable doing.
-
The code must be tested through our automated testing system. We use Jest as the testing framework. If you are fixing a bug, consider adding a test case that shows the bug has been resolved. If you are contributing new features, like a new plugin, a test suite for the plugin is very helpful. See testing jsPsych for more information about configuring the test tools and writing tests.
-
Relevant documentation must be updated. Any pages in /docs
that are affected by the contribution should be updated, and if new pages are needed they should be created. For example, if you are contributing a plugin then adding documentation for the plugin and updating the list of available plugins as well as the mkdocs configuration file is very helpful!
-
An example file should be included if applicable. If you are contributing a new feature, new plugin, or new extension, or contributing a modification that changes the behavior of the library in some important way, consider adding an example file to the /examples
folder in the repository.
-
A changeset must be included in the pull request. We use changesets to generate new releases and their corresponding release notes. This is a good overview of changesets that explains how to add one to your pull request. Feel free to ask for help with this!
-
Update the contributors.md file. If you are a first time contributor to jsPsych please add your name to our contributors file. And thanks!
"},{"location":"developers/contributing/#contributing-to-the-documentation","title":"Contributing to the documentation","text":"We are very appreciative of both small and large contributions to the documentation, from fixing a typo to adding a whole new tutorial. All of the documentation that appears on this site is contained in the /docs
folder of the repository. The documentation is built using MkDocs and themed using Material for MkDocs. You can edit any of the markdown files and submit a pull request to modify documentation.
If you'd like to test your changes to the documentation locally you'll need to install MkDocs and Material for MkDocs. Then you can run the command mike serve
in the root folder of the repository to launch a local webserver and view the documentation.
"},{"location":"developers/contributing/#contributing-to-jspsych-vs-jspsych-contrib","title":"Contributing to jspsych
vs. jspsych-contrib
","text":"If you are developing a new plugin or extension there are two different repositories that you can contribute to: jspsych
or jspsych-contrib
.
The main jspsych
repository is open to new plugins and extensions that are likely to be widely used. We require that contributions to main repository are well documented and tested before they are merged. Contributions to the main repository must use TypeScript. We limit contributions to this repository because once a plugin or extension is in the main codebase we are generally committed to providing updates as we develop new versions of jsPsych. Each new plugin and extension potentially increases the amount of development work that we will need to do in the future, so we are somewhat selective about what we will merge. If you have an idea that you'd like to discuss please open a discussion thread and we'd love to chat about it!
The jspsych-contrib
repository is open to any contributions that are complete and working code. There are some minimal guidelines in place about basic documentation that should be provided. Contributors can choose whether to develop their plugin or extension using our TypeScript template or using our JavaScript template. Contributions to jspsych-contrib
are not evaluated for general usefulness in the same way that contributions to the main repository are. We also periodically consider whether to move contributions into the main repository from jspsych-contrib
based on their popularity and completeness (documentation and testing).
"},{"location":"developers/documentation/","title":"Building the jsPsych documentation","text":"The documentation hosted at https://www.jspsych.org is generated using mkdocs and the mkdocs-material theme. The documentation files are located in the /docs
directory of the GitHub repository. The documentation is written using markdown.
To build a local copy of the docs, you will need to install mkdocs
, mkdocs-material
, and mike
using poetry
.
"},{"location":"developers/documentation/#install-poetry","title":"Install poetry","text":"Poetry is a package manager for python. Follow the install instructions on the poetry
website to get it running.
"},{"location":"developers/documentation/#install-dev-dependencies","title":"Install dev dependencies","text":"Run the command poetry install
in the root directory of jsPsych to install mkdocs
, mkdocs-material
, and their dependencies.
"},{"location":"developers/documentation/#building-a-local-copy-of-the-docs","title":"Building a local copy of the docs","text":"Run poetry run mike deploy [version] -u
to build a new version of the documentation or to override an existing version. For example, if you are testing an edit to version 7.2
of the documentation, run poetry run mike deploy 7.2 -u
.
You can also use jsPsych's custom npm command: npm run docs:deploy [version]
, e.g. npm run docs:deploy 7.2
.
This will build the documentation and commit it directly to the gh-pages
branch.
We use mike
instead of mkdocs
for the build step to support versioning of the documentation. mike
runs the mkdocs
command under the hood.
"},{"location":"developers/documentation/#viewing-the-local-docs","title":"Viewing the local docs","text":"To launch a local webserver, run poetry run mike serve
, or use jsPsych's custom npm command: npm run docs:serve
.
The docs will be viewable at http://localhost:8000
.
"},{"location":"developers/documentation/#updating-the-public-docs-site","title":"Updating the public docs site","text":"For core maintainers only
After the documentation has been built locally (and therefore committed to your local gh-pages
branch), you can update the live documentation site by switching to your gh-pages
branch and pushing to the remote gh-pages
branch.
"},{"location":"developers/extension-development/","title":"Extension development","text":""},{"location":"developers/extension-development/#requirements-for-an-extension","title":"Requirements for an extension","text":"As of version 7.0, extensions are JavaScript Classes. An extension must implement:
- A
constructor()
that accepts an instance of jsPsych. - An
initialize()
function to handle the initialize event of the extension. - An
on_start()
function to handle the on_start event of the extension. - An
on_load()
function to handle the on_load event of the extension. - An
on_finish()
function to handle the on_finish event of the extension and store data that the extension collects. - A static
info
property containing a unique name, version parameter, and data property for the extension.
"},{"location":"developers/extension-development/#templates","title":"Templates","text":"Plugins can be written in either plain JavaScript or in TypeScript. Template files for both JavaScript and TypeScript are available in the jspsych-contrib repository.
"},{"location":"developers/extension-development/#extension-components","title":"Extension components","text":""},{"location":"developers/extension-development/#constructor","title":"constructor()","text":"The extension's constructor()
will be passed a reference to the instance of the JsPsych
class that is running the experiment. The constructor should store this reference so that the plugin can access functionality from the core library and its modules.
class MyAwesomeExtension {\n constructor(jsPsych){\n this.jsPsych = jsPsych;\n }\n}\n
"},{"location":"developers/extension-development/#initialize","title":"initialize()","text":"The initialize()
function is called when an instance of jsPsych is first initialized, either through initJsPsych()
or new JsPsych()
. This is where setup code for the extension should be run. This event will happen once per experiment, unlike the other events which occur with each trial. The params
object can include whatever parameters are necessary to configure the extension. The params
object is passed from the call to initJsPsych()
to initialize()
method. initialize()
must return a Promise
that resolves when the extension is finished initializing.
//... experiment code ...//\nlet jsPsych = initJsPsych({\n extensions: [\n {type: myAwesomeExtension, params: {demo: 'value'}}\n ]\n});\n\n//... extension code ...//\nclass MyAwesomeExtension {\n\n initialize(params){\n return new Promise((resolve, reject)=>{\n console.log(params.demo); // will output 'value'\n\n resolve(); // finish initialzing\n })\n }\n}\n
"},{"location":"developers/extension-development/#on_start","title":"on_start()","text":"on_start()
is called at the start of the plugin execution, prior to calling plugin.trial
. This is where trial-specific initialization can happen, such as creating empty containers to hold data or resetting internal state. The params
object is passed from the declaration of the extension in the trial object. You can use params
to customize the behavior of the extension for each trial.
//... experiment code ...//\nlet trial = {\n type: htmlKeyboardResponse,\n stimulus: \"You're awesome!\",\n extensions: [\n {type: myAwesomeExtension, params: {demo: 'value'}}\n ]\n});\n\n//... extension code ...//\nclass MyAwesomeExtension {\n\n initialize(params){ ... }\n\n on_start(params){\n console.log(params.demo); // outputs 'value' before the trial begins.\n }\n}\n
"},{"location":"developers/extension-development/#on_load","title":"on_load()","text":"on_load()
is called after the on_load
event for the plugin has completed, which is typically when the plugin has finished executing initial DOM-modifying code and has set up various event listeners. This is where the extension can begin actively interacting with the DOM and recording data. The params
object is passed from the declaration of the extension in the trial object. You can use params
to customize the behavior of the extension for each trial.
//... experiment code ...//\nlet trial = {\n type: htmlKeyboardResponse,\n stimulus: \"You're awesome!\",\n extensions: [\n {type: myAwesomeExtension, params: {demo: 'value'}}\n ]\n});\n\n//... extension code ...//\nclass MyAwesomeExtension {\n\n initialize(params){ ... }\n\n on_start(params){ ... }\n\n on_load(params){\n // replaces the contents of the display with 'value';\n this.jsPsych.getDisplayElement().innerHTML = params.demo;\n }\n}\n
"},{"location":"developers/extension-development/#on_finish","title":"on_finish()","text":"on_finish()
is called after the plugin invokes jsPsych.finishTrial()
. This can be used for any teardown at the end of the trial. This method should return an object of data to append to the plugin's data. Note that this event fires before the on_finish
event for the plugin, so data added by the extension is accessible in any trial on_finish
event handlers. The params
object is passed from the declaration of the extension in the trial object. You can use params
to customize the behavior of the extension for each trial.
//... experiment code ...//\nlet trial = {\n type: htmlKeyboardResponse,\n stimulus: \"You're awesome!\",\n extensions: [\n {type: myAwesomeExtension, params: {demo: 'value'}}\n ],\n on_finish: (data) => {\n console.log(data.awesome); // will output 'value'.\n }\n});\n\n//... extension code ...//\nclass MyAwesomeExtension {\n\n initialize(params){ ... }\n\n on_start(params){ ... }\n\n on_load(params){ ... }\n\n on_finish(params){\n return {\n awesome: params.value\n }\n }\n}\n
"},{"location":"developers/extension-development/#static-info","title":"static .info","text":"The info
property for the class must contain an object with a name
property that has a unique name for the extension, a version
property that has the version string, and a data
parameter that includes information about the data
generated by the extension.
import { version } from '../package.json';\n\nclass MyAwesomeExtension {\n\n}\n\nMyAwesomeExtension.info = {\n name: 'awesome',\n version: version, // Should be hardcoded as `version: \"1.0.1\"` if not using build tools.\n data: {\n /** This will be scraped as metadata describing tracking_data and used to create the JsPsych docs */\n tracking_data: {\n type: ParameterType.STRING,\n }\n }\n}\n
The version
field describes the version of the extension used and then durin the experiment will be part of the generated data. This is used generate metadata and help maintain the Psych-DS standard. It should imported from the package.json file by including an import statement in the top of the index.ts file. This allows the version
field be automatically updated with each changeset. If you are not using a build environment and instead writing a plain JS file, you can manually enter the version
as a string as done in the comment.
The data
field is an object containing all of the data
generated for the plugin. Each 'data' object has a type
and default
property. Additionally, this should be only used for data you choose to generate. Any jsdoc (comments included in the /* / tags) you include will be scraped as metadata if you are choosing to generate metadata. This scraped metadata will also be used to create the JsPsych documentation.
"},{"location":"developers/extension-development/#optional-methods","title":"Optional methods","text":"The extension can also include any additional methods that are necessary for interacting with it. See the webgazer extension for an example.
"},{"location":"developers/extension-development/#advice-for-writing-extensions","title":"Advice for writing extensions","text":"If you are developing an extension with the aim of including it in the main jsPsych repository we encourage you to follow the contribution guidelines.
In general, extensions should be able to work with any plugin. They should make very few assumptions about what the DOM will contain beyond the container elements generated by jsPsych. If you are making an extension targeted at one or a small number of specific plugins, consider modifying the plugin code instead.
"},{"location":"developers/plugin-development/","title":"Plugin development","text":""},{"location":"developers/plugin-development/#requirements-for-a-plugin","title":"Requirements for a plugin","text":"As of version 7.0, plugins are JavaScript Classes. A plugin must implement:
- A
constructor()
that accepts an instance of jsPsych. - A
trial()
method that accepts an HTMLElement
as its first argument and an object
of trial parameters as its second argument. There is an optional third argument to handle the on_load
event in certain cirumstances. The trial()
method should either invoke jsPsych.finishTrial()
or should be an async
function that returns a data object to end the trial and save data. - A static
info
property on the class that contains an object describing the plugin's parameters, data generated, and version.
"},{"location":"developers/plugin-development/#templates","title":"Templates","text":"Plugins can be written in either plain JavaScript or in TypeScript. Template files for both JavaScript and TypeScript are available in the jspsych-contrib repository.
"},{"location":"developers/plugin-development/#plugin-components","title":"Plugin components","text":""},{"location":"developers/plugin-development/#constructor","title":"constructor()","text":"The plugin's constructor()
will be passed a reference to the instance of the JsPsych
class that is running the experiment. The constructor should store this reference so that the plugin can access functionality from the core library and its modules.
constructor(jsPsych){\n this.jsPsych = jsPsych;\n}\n
"},{"location":"developers/plugin-development/#trial","title":"trial()","text":"The plugin's trial()
method is responsible for running a single trial. When the jsPsych timeline reaches a trial using the plugin it will invoke the trial()
method for the plugin.
There are three parameters that are passed into the trial method.
display_element
is the DOM element where jsPsych content is being rendered. This parameter will be an HTMLElement
, and you can use it to modify the portion of the document that jsPsych controls. trial
is an object containing all of the parameters specified in the corresponding TimelineNode. on_load
is an optional parameter that contains a callback function to invoke when trial()
has completed its initial loading. See handling the on_load event.
The only requirement for the trial
method is that it calls jsPsych.finishTrial()
when it is done. This is how jsPsych knows to advance to the next trial in the experiment (or end the experiment if it is the last trial). The plugin can do whatever it needs to do before that point.
"},{"location":"developers/plugin-development/#static-info","title":"static info","text":"The plugin's info
property is an object with a name
, version
, parameters
, and data
property.
const info = {\n name: 'my-awesome-plugin',\n version: version,\n parameters: { },\n data: { }\n}\n
The version
field describes the version of the plugin. The version will be automatically included in the data generated by the plugin. In most cases, the version should imported from the package.json
file by including an import statement at the top of the file. This allows the version
field be automatically updated.
import { version } from '../package.json';\n\nconst info = {\n ...\n version: version;\n ...\n}\n
If you are not using a build environment that supports import
and package.json
(such as writing a plain JS file), you can manually enter the version
as a string.
const info = {\n ...\n version: \"1.0.0\";\n ...\n}\n
The parameters
property is an object containing all of the parameters for the plugin. Each parameter has a type
and default
property.
The data
field describes the types of data generated by the plugin. Each parameter has a type
property.
const info = {\n name: 'my-awesome-plugin',\n version: version,\n parameters: { \n image: {\n type: ParameterType.IMAGE,\n default: undefined\n },\n image_duration: {\n type: ParameterType.INT,\n default: 500\n }\n },\n data: {\n response: {\n type: ParameterType.STRING,\n },\n },\n}\n
If the default
value is undefined
then a user must specify a value for this parameter when creating a trial using the plugin on the timeline. If they do not, then an error will be generated and shown in the console. If a default
value is specified in info
then that value will be used by the plugin unless the user overrides it by specifying that property.
jsPsych allows most plugin parameters to be dynamic, which means that the parameter value can be a function that will be evaluated right before the trial starts. However, if you want your plugin to have a parameter that is a function that shouldn't be evaluated before the trial starts, then you should make sure that the parameter type is 'FUNCTION'
. This tells jsPsych not to evaluate the function as it normally does for dynamic parameters. See the canvas-*
plugins for examples.
We strongly encourage using JSDoc comments to document the parameters and data generated by the plugin, as shown below. We use these comments to automatically generate documentation for the plugins and to generate default descriptions of variables for experiment metadata.
const info = {\n name: 'my-awesome-plugin',\n version: version,\n parameters: { \n /** The path to the image file to display. */\n image: {\n type: ParameterType.IMAGE,\n default: undefined\n },\n /** The duration to display the image in milliseconds. */\n image_duration: {\n type: ParameterType.INT,\n default: 500\n }\n },\n data: {\n /** The text of the response generated by the participant. */\n response: {\n type: ParameterType.STRING,\n },\n },\n}\n
The info
object must be a static
member of the class, as shown below.
const info = {\n name: 'my-awesome-plugin',\n version: version,\n parameters: { \n /** The path to the image file to display. */\n image: {\n type: ParameterType.IMAGE,\n default: undefined\n },\n /** The duration to display the image in milliseconds. */\n image_duration: {\n type: ParameterType.INT,\n default: 500\n }\n },\n data: {\n /** The text of the response generated by the participant. */\n response: {\n type: ParameterType.STRING,\n },\n },\n}\n\nclass MyAwesomePlugin {\n constructor(...)\n\n trial(...)\n}\n\nMyAwesomePlugin.info = info;\n
"},{"location":"developers/plugin-development/#plugin-functionality","title":"Plugin functionality","text":"Inside the .trial()
method you can do pretty much anything that you want, including modifying the DOM, setting up event listeners, and making asynchronous requests. In this section we'll highlight a few common things that you might want to do as examples.
"},{"location":"developers/plugin-development/#changing-the-content-of-the-display","title":"Changing the content of the display","text":"There are a few ways to change the content of the display. The display_element
parameter of the trial method contains the HTMLElement
for displaying jsPsych content, so you can use various JavaScript methods for interaction with the display element. A common one is to change the innerHTML
. Here's an example of using innerHTML
to display an image specified in the trial
parameters.
trial(display_element, trial){\n let html_content = `<img src=\"${trial.image}\"></img>`;\n\n display_element.innerHTML = html_content;\n}\n
"},{"location":"developers/plugin-development/#waiting-for-specified-durations","title":"Waiting for specified durations","text":"If you need to delay code execution for a fixed amount of time, we recommend using jsPsych's wrapper of the setTimeout()
function, jsPsych.pluginAPI.setTimeout()
. Any timeouts that are created using jsPsych's setTimeout()
will be automatically cleared when the trial ends, which prevents one plugin from interfering with the timing of another plugin.
In future versions we may replace the implementation of jsPsych.pluginAPI.setTimeout()
with improved timing functionality based on requestAnimationFrame
.
trial(display_element, trial){\n // show image\n display_element.innerHTML = `<img src=\"${trial.image}\"></img>`;\n\n // hide image after trial.image_duration milliseconds\n this.jsPsych.pluginAPI.setTimeout(()=>{\n display_element.innerHTML = '';\n }, trial.image_duration);\n}\n
"},{"location":"developers/plugin-development/#responding-to-keyboard-events","title":"Responding to keyboard events","text":"While the plugin framework allows you to set up any events that you would like to, including normal handling of keyup
or keydown
events, the jsPsych.pluginAPI
module contains the getKeyboardResponse
function, which implements some additional helpful functionality for key responses in an experiment.
Here's a basic example. See the getKeyboardResponse
docs for additional examples.
trial(display_element, trial){\n // show image\n display_element.innerHTML = `<img src=\"${trial.image}\"></img>`;\n\n const after_key_response = (info) => {\n // hide the image\n display_element.innerHTML = '';\n\n // record the response time as data\n let data = {\n rt: info.rt\n }\n\n // end the trial\n this.jsPsych.finishTrial(data);\n }\n\n // set up a keyboard event to respond only to the spacebar\n this.jsPsych.pluginAPI.getKeyboardResponse({\n callback_function: after_key_response,\n valid_responses: [' '],\n persist: false\n });\n}\n
"},{"location":"developers/plugin-development/#asynchronous-loading","title":"Asynchronous loading","text":"One of the trial events is on_load
, which is normally triggered automatically when the .trial()
method returns. In most cases, this return happens after the plugin has done its initial setup of the DOM (e.g., rendering an image, setting up event listeners and timers, etc.). However, in some cases a plugin may implement an asynchronous operation that needs to complete before the initial loading of the plugin is considered done. An example of this is the audio-keyboard-response
plugin, in which the check to see if the audio file is loaded is asynchronous and the .trial()
method returns before the audio file has been initialized and the display updated.
If you would like to manually trigger the on_load
event for a plugin, the .trial()
method accepts an optional third parameter that is a callback function to invoke when loading is complete.
In order to tell jsPsych to not invoke the regular callback when the .trial()
method returns, you need to explicitly return a Promise
. As of version 8.0
, we recommend making the trial
function an async
function to handle this.
Here's a sketch of how the on_load
event can be utilized in a plugin. Note that this example is only a sketch and leaves out all the stuff that happens between loading and finishing the trial. See the source for the audio-keyboard-response
plugin for a complete exampe.
async trial(display_element, trial, on_load){\n let trial_complete;\n\n await do_something_asynchronous()\n\n on_load();\n\n await do_the_rest_of_the_trial();\n\n return data_generated_by_the_trial;\n}\n
"},{"location":"developers/plugin-development/#save-data","title":"Save data","text":"To write data to jsPsych's data collection pass an object of data as the parameter to jsPsych.finishTrial()
.
constructor(jsPsych){\n this.jsPsych = jsPsych;\n}\n\ntrial(display_element, trial){\n let data = {\n correct: true,\n rt: 350\n }\n\n this.jsPsych.finishTrial(data);\n}\n
As of version 8.0
you may also return the data object from the trial()
method when the method is an async
function. This is equivalent to calling jsPsych.finishTrial(data)
.
constructor(jsPsych){\n this.jsPsych = jsPsych;\n}\n\nasync trial(display_element, trial){\n\n let data = {\n correct: true,\n rt: 350\n }\n\n return data;\n}\n
The data recorded will be that correct
is true
and that rt
is 350
. Additional data for the trial will also be collected automatically.
"},{"location":"developers/plugin-development/#when-a-plugin-finishes","title":"When a plugin finishes","text":"When a plugin finishes, it should call jsPsych.finishTrial()
or return a data object if the trial()
method is an async
function. This is how jsPsych knows to advance to the next trial in the experiment (or end the experiment if it is the last trial).
As of version 8.0
, ending the trial will automatically clear the display element and automatically clear any timeouts that are still pending.
"},{"location":"developers/plugin-development/#simulation-mode","title":"Simulation mode","text":"Plugins can optionally support simulation modes.
To add simulation support, a plugin needs a simulate()
function that accepts four arguments
simulate(trial, simulation_mode, simulation_options, load_callback)
trial
: This is the same as the trial
parameter passed to the plugin's trial()
method. It contains an object of the parameters for the trial. simulation_mode
: A string, either \"data-only\"
or \"visual\"
. This specifies which simulation mode is being requested. Plugins can optionally support \"visual\"
mode. If \"visual\"
mode is not supported, the plugin should default to \"data-only\"
mode when \"visual\"
mode is requested. simulation_options
: An object of simulation-specific options. load_callback
: A function handle to invoke when the simulation is ready to trigger the on_load
event for the trial. It is important to invoke this at the correct time during the simulation so that any on_load
events in the experiment execute as expected.
Typically the flow for supporting simulation mode involves:
- Generating artificial data that is consistent with the
trial
parameters. - Merging that data with any data specified by the user in
simulation_options
. - Verifying that the final data object is still consistent with the
trial
parameters. For example, checking that RTs are not longer than the duration of the trial. - In
data-only
mode, call jsPsych.finishTrial()
with the artificial data. - In
visual
mode, invoke the trial()
method of the plugin and then use the artificial data to trigger the appropriate events. There are a variety of methods in the Plugin API module to assist with things like simulating key presses and mouse clicks.
We plan to add a longer guide about simulation development in the future. For now, we recommend browsing the source code of plugins that support simulation mode to see how the flow described above is implemented.
"},{"location":"developers/plugin-development/#advice-for-writing-plugins","title":"Advice for writing plugins","text":"If you are developing a plugin with the aim of including it in the main jsPsych repository we encourage you to follow the contribution guidelines.
We also recommend that you make your plugin as general as possible. Consider using parameters to give the user of the plugin as many options for customization as possible. For example, if you have any text that displays in the plugin including things like button labels, implement the text as a parameter. This allows users running experiments in other languages to replace text values as needed.
"},{"location":"developers/plugin-development/#plugin-templates","title":"Plugin templates","text":"Templates for plugins are available in the jspsych-contrib repository. There is a command-line tool for generating a new plugin from these templates in that repository. See the README file in the jspsych-contrib repository for more information.
"},{"location":"extensions/list-of-extensions/","title":"List of Plugins","text":"These are the extensions that are included in the jsPsych release.
Additional extensions may be available in the community contributions repository.
For an overview of what extensions are and how they work, see our extensions overview.
Extension Description mouse\u2011tracking Enables tracking of mouse events and recording location of objects on screen. record\u2011video Record video data from the participant's webcam during a trial. webgazer Enables eye tracking using the WebGazer library."},{"location":"extensions/mouse-tracking/","title":"mouse-tracking","text":"This extension supports mouse tracking. Specifically, it can record the x
and y
coordinates, along with the time of mousemove events, mousedown events, and mouseup events. It also allows recording of the bounding rectangle of elements on the screen to support the calculation of mouse events relative to different elements.
"},{"location":"extensions/mouse-tracking/#parameters","title":"Parameters","text":""},{"location":"extensions/mouse-tracking/#initialization-parameters","title":"Initialization Parameters","text":"Initialization parameters can be set when calling initJsPsych()
initJsPsych({\n extensions: [\n {type: jsPsychExtensionMouseTracking, params: {...}}\n ]\n})\n
Parameter Type Default Value Description minimum_sample_time number 0 The minimum time between samples for mousemove
events in milliseconds. If mousemove
events occur more rapidly than this limit, they will not be recorded. Use this if you want to keep the data files smaller and don't need high resolution tracking data. The default value of 0 means that all events will be recorded."},{"location":"extensions/mouse-tracking/#trial-parameters","title":"Trial Parameters","text":"Trial parameters can be set when adding the extension to a trial object.
var trial = {\n type: jsPsych...,\n extensions: [\n {type: jsPsychExtensionMouseTracking, params: {...}}\n ]\n}\n
Parameter Type Default Value Description targets array [] A list of elements on the page that you would like to record the coordinates of for comparison with the mouse tracking data. Each entry in the array should be a valid CSS selector string that identifies the element. The selector string should be valid for exactly one element on the page. If the selector is valid for more than one element then only the first matching element will be recorded. events array ['mousemove'] A list of events to track. Can include 'mousemove', 'mousedown', and 'mouseup'."},{"location":"extensions/mouse-tracking/#data-generated","title":"Data Generated","text":"Name Type Value mouse_tracking_data array An array of objects containing mouse movement data for the trial. Each object has an x
, a y
, a t
, and an event
property. The x
and y
properties specify the mouse coordinates in pixels relative to the top left corner of the viewport and t
specifies the time in milliseconds since the start of the trial. The event
will be either 'mousemove', 'mousedown', or 'mouseup' depending on which event was generated. mouse_tracking_targets object An object contain the pixel coordinates of elements on the screen specified by the .targets
parameter. Each key in this object will be a selector
property, containing the CSS selector string used to find the element. The object corresponding to each key will contain x
and y
properties specifying the top-left corner of the object, width
and height
values, plus top
, bottom
, left
, and right
parameters which specify the bounding rectangle of the element."},{"location":"extensions/mouse-tracking/#examples","title":"Examples","text":"Record mouse movement data and play it back CodeDemo var trial = {\n type: jsPsychHtmlButtonResponse,\n stimulus: '<div id=\"target\" style=\"width:250px; height: 250px; background-color: #333; margin: auto;\"></div>',\n choices: ['Done'],\n prompt: \"<p>Move your mouse around inside the square.</p>\",\n extensions: [\n {type: jsPsychExtensionMouseTracking, params: {targets: ['#target']}}\n ],\n data: {\n task: 'draw'\n }\n};\n\nvar replay = {\n type: jsPsychHtmlButtonResponse,\n stimulus: '<div id=\"target\" style=\"width:250px; height: 250px; background-color: #333; margin: auto; position: relative;\"></div>',\n choices: ['Done'],\n prompt: \"<p>Here's the recording of your mouse movements</p>\",\n on_load: function(){\n var mouseMovements = jsPsych.data.get().last(1).values()[0].mouse_tracking_data;\n var targetRect = jsPsych.data.get().last(1).values()[0].mouse_tracking_targets['#target'];\n\n var startTime = performance.now();\n\n function draw_frame() {\n var timeElapsed = performance.now() - startTime;\n var points = mouseMovements.filter((x) => x.t <= timeElapsed);\n var html = ``;\n for(var p of points){\n html += `<div style=\"width: 3px; height: 3px; background-color: blue; position: absolute; top: ${p.y - 1 - targetRect.top}px; left: ${p.x - 1 - targetRect.left}px;\"></div>`\n }\n document.querySelector('#target').innerHTML = html;\n if(points.length < mouseMovements.length) {\n requestAnimationFrame(draw_frame);\n }\n }\n\n requestAnimationFrame(draw_frame);\n\n },\n data: {\n task: 'replay'\n }\n}\n
Open demo in new tab
"},{"location":"extensions/record-video/","title":"record-video","text":"This extension records video from the participant's webcam during a trial.
This extension encodes the video data in base 64 format. This is a text-based representation of the video which can be coverted to various video formats using a variety of online tools as well as in languages like python and R.
"},{"location":"extensions/record-video/#parameters","title":"Parameters","text":""},{"location":"extensions/record-video/#initialization-parameters","title":"Initialization Parameters","text":"Initialization parameters can be set when calling initJsPsych()
initJsPsych({\n extensions: [\n {type: jsPsychExtensionRecordVideo, params: {...}}\n ]\n})\n
Parameter Type Default Value Description None"},{"location":"extensions/record-video/#trial-parameters","title":"Trial Parameters","text":"Trial parameters can be set when adding the extension to a trial object.
var trial = {\n type: jsPsych...,\n extensions: [\n {type: jsPsychExtensionRecordVideo, params: {...}}\n ]\n}\n
Parameter Type Default Value Description None"},{"location":"extensions/record-video/#data-generated","title":"Data Generated","text":"Name Type Value record_video_data base64 string Base 64 encoded representation of the video data."},{"location":"extensions/record-video/#examples","title":"Examples","text":"Record video data during a trial CodeDemo const init_camera = {\n type: jsPsychInitializeCamera\n};\n\nconst trial = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `<div id=\"target\" style=\"width:250px; height: 250px; background-color: #333; position: relative; margin: 2em auto;\">\n <div class=\"orbit\" style=\"width:25px; height:25px; border-radius:25px;background-color: #f00; position: absolute; top:calc(50% - 12px); left:calc(50% - 12px);\"></div>\n </div>\n <style>\n .orbit {\n transform: translateX(100px);\n animation: orbit 4s infinite;\n }\n @keyframes orbit {\n 0% {\n transform: rotate(0deg) translateX(100px);\n }\n 100% {\n transform: rotate(360deg) translateX(100px);\n }\n }\n </style>`,\n choices: ['Done'],\n prompt: \"<p>Video is recording. Click done after a few seconds.</p>\",\n extensions: [\n {type: jsPsychExtensionRecordVideo}\n ]\n};\n
Open demo in new tab
"},{"location":"extensions/webgazer/","title":"webgazer","text":"This extension supports eye tracking through the WebGazer library. For a narrative description of how to use this extension see the eye tracking overview.
"},{"location":"extensions/webgazer/#parameters","title":"Parameters","text":""},{"location":"extensions/webgazer/#initialization-parameters","title":"Initialization Parameters","text":"Initialization parameters can be set when calling initJsPsych()
initJsPsych({\n extensions: [\n {type: jsPsychExtensionWebgazer, params: {...}}\n ]\n})\n
Parameter Type Default Value Description webgazer object undefined
You can explicitly pass a reference to a loaded instance of the webgazer.js library. If no explicit reference is passed then the extension will look for a global webgazer
object. If you are loading webgazer.js via a <script>
tag you do not need to set this parameter in most circumstances. auto_initialize bool false Whether to automatically initialize webgazer when the experiment begins. If set to true
then the experiment will attempt to access the user's webcam immediately upon page load. The default value is false
because it is probably a good idea to explain to the user why camera permission will be needed before asking for it. The webgazer-init-camera
plugin can be used to initialize the camera during the experiment. round_predictions bool true Whether to round the x
,y
coordinates predicted by WebGazer to the nearest whole number. This greatly reduces the size of the data, as WebGazer records data to 15 decimal places by default. Given the noise of the system, there's really no need to record data to this level of precision. sampling_interval numeric 34 Sets the interval between gaze predictions. Because the underlying code is partially asynchronous, this interval is only approximate. The sampling interval will not be faster than this, on average, but the time between samples may fluctuate. Setting the interval too fast will create performance problems and produce redundant data, as the video feed from most webcams only updates about 30 times per second."},{"location":"extensions/webgazer/#trial-parameters","title":"Trial Parameters","text":"Trial parameters can be set when adding the extension to a trial object.
var trial = {\n type: jsPsych...,\n extensions: [\n {type: jsPsychExtensionWebgazer, params: {...}}\n ]\n}\n
Parameter Type Default Value Description targets array [] A list of elements on the page that you would like to record the coordinates of for comparison with the WebGazer data. Each entry in the array should be a valid CSS selector string that identifies the element. The selector string should be valid for exactly one element on the page. If the selector is valid for more than one element then only the first matching element will be recorded."},{"location":"extensions/webgazer/#data-generated","title":"Data Generated","text":"Name Type Value webgazer_data array An array of objects containing gaze data for the trial. Each object has an x
, a y
, and a t
property. The x
and y
properties specify the gaze location in pixels and t
specifies the time in milliseconds since the start of the trial. webgazer_targets object An object contain the pixel coordinates of elements on the screen specified by the .targets
parameter. Each key in this object will be a selector
property, containing the CSS selector string used to find the element. The object corresponding to each key will contain x
and y
properties specifying the top-left corner of the object, width
and height
values, plus top
, bottom
, left
, and right
parameters which specify the bounding rectangle of the element."},{"location":"extensions/webgazer/#functions","title":"Functions","text":"In addition to the jsPsych webgazer-* plugins, the jsPsych webgazer extension provides a set of functions that allow the researcher to interact more directly with WebGazer. These functions can be called at any point during an experiment, and are crucial for building trial plugins that interact with WebGazer. All of the functions below must be prefixed with jsPsych.extensions.webgazer
(e.g. jsPsych.extensions.webgazer.faceDetected()
).
"},{"location":"extensions/webgazer/#start","title":"start()","text":"Performs initialization of webgazer, including requesting permissions from the user to access the camera. Returns a Promise
that resolves when the camera is initialized and fails if the camera cannot be accessed, e.g., because the user denies permission. This is handled automatically if using the webgazer-init-camera
plugin or setting auto_initialize
to true
in the extension parameters.
"},{"location":"extensions/webgazer/#isinitialized","title":"isInitialized()","text":"Returns true
if start()
has been successfully called at some point, and false
otherwise.
"},{"location":"extensions/webgazer/#facedetected","title":"faceDetected()","text":"Returns true
if WebGazer is ready to make predictions (webgazer.getTracker().predictionReady
is true
).
"},{"location":"extensions/webgazer/#showpredictions","title":"showPredictions()","text":"Turns on WebGazer's real-time visualization of predicted gaze location.
"},{"location":"extensions/webgazer/#hidepredictions","title":"hidePredictions()","text":"Turns off WebGazer's real-time visualization of predicted gaze location.
"},{"location":"extensions/webgazer/#showvideo","title":"showVideo()","text":"Turns on a display of the webcam image, guiding box for positioning the face, and WebGazer's estimate of the location of facial landmarks.
"},{"location":"extensions/webgazer/#hidevideo","title":"hideVideo()","text":"Turns off the camera display.
"},{"location":"extensions/webgazer/#resume","title":"resume()","text":"Turns on gaze prediction. The extension will automatically handle this for you in most cases. You probably only need to use this if you are writing your own plugin that interfaces directly with WebGazer.
"},{"location":"extensions/webgazer/#pause","title":"pause()","text":"Turns off gaze prediction. The extension will automatically handle this for you in most cases. You probably only need to use this if you are writing your own plugin that interfaces directly with WebGazer.
"},{"location":"extensions/webgazer/#resetcalibration","title":"resetCalibration()","text":"Clears all calibration data.
"},{"location":"extensions/webgazer/#startmousecalibration","title":"startMouseCalibration()","text":"Turns on mouse movement and mouse clicks as calibration events. While the webgazer-calibration
plugin can also be used to run a parmeterized calibration routine, this calibration function call allows you to continuously calibrate WebGazer to any mouse movements or clicks throughout the experiment. For example, any *-button-response trial would also function as a WebGazer calibration event.
"},{"location":"extensions/webgazer/#stopmousecalibration","title":"stopMouseCalibration()","text":"Stops WebGazer from using mouse movements and mouse clicks as calibration events.
"},{"location":"extensions/webgazer/#calibratepointx-y","title":"calibratePoint(x, y)","text":"Instructs WebGazer to register the location x
, y
(in screen pixel coordinates) as a calibration event. Can be used for passive viewing calibration, i.e., instructing participants to fixate at a particular location.
"},{"location":"extensions/webgazer/#setregressiontyperegression_type","title":"setRegressionType(regression_type)","text":"Change the method that WebGazer is using to perform feature -> location regression. Valid options are ridge
, weightedRidge
, and threadedRidge
. See the WebGazer docs for more information about these options. The extension uses the default mode specified by WebGazer (currently ridge
).
"},{"location":"extensions/webgazer/#getcurrentprediction","title":"getCurrentPrediction()","text":"Get the current predicted gaze location from WebGazer. This returns a Promise that resolves once WebGazer has finished computing the gaze prediction. The Promise has a single parameter with an object with x
, y
, and, t
parameters. t
will be the value of performance.now()
at approximately the time that the video frame was recorded.
"},{"location":"extensions/webgazer/#startsampleintervalinterval","title":"startSampleInterval(interval)","text":"Starts sampling gaze predictions every interval
milliseconds. If interval
is left undefined then the default value at extension initialization is used. Every sample will trigger an onGazeUpdate
callback, as well as side effects that result in data storage within the extension.
"},{"location":"extensions/webgazer/#stopsampleinterval","title":"stopSampleInterval()","text":"Stops the sampling started by startSampleInterval()
.
"},{"location":"extensions/webgazer/#ongazeupdatecallback","title":"onGazeUpdate(callback)","text":"Subscribe to gaze updates. The callback
will be invoked every time a new gaze prediction is generated. The first argument of the callback
will be an object with x
, y
, and, if currently in a trial with the extension turned on, the time t
in ms since the start of the trial. t
will be the value of performance.now()
at approximately the time that the video frame was recorded. If currently in an active trial then t
will be relative to the start of the trial.
This function returns a close handler. When you no longer need to subscribe to gaze updates, call the close handler. Example:
var cancelGazeUpdateHandler = jsPsych.extensions.webgazer.onGazeUpdate(function(prediction){\n console.log(`Currently looking at ${prediction.x}, ${prediction.y}`);\n});\n\ncancelGazeUpdateHandler();\n
You can add multiple handlers. Handlers are not closed automatically, so be sure to cancel them when no longer needed.
"},{"location":"newsletter/subscribe/","title":"Subscribe to our newsletter","text":"Subscribe to our newsletter to stay up to date with the latest news and updates from the jsPsych team. We send out newsletters about once a month. The newsletter includes information about new releases, upcoming events, community spotlights, and other news related to jsPsych. You can unsubscribe at any time.
Subscribe"},{"location":"overview/browser-device-support/","title":"Browser and Device Support","text":""},{"location":"overview/browser-device-support/#desktop-and-laptop-browsers","title":"Desktop and Laptop Browsers","text":"Supported
jsPsych supports recent versions of the four most commonly-used web browsers:
- Chrome
- Firefox
- Safari
- Edge
This means that jsPsych should work on these browsers. If something doesn't work as you expect on one of the browsers above, it might be a bug that should be fixed. You can search for and report bugs on the jsPsych GitHub Issues page. We're very grateful for anyone who takes the time to report bugs - it helps improve the library for everyone!
Unsupported
There are many other web browsers that are available, but that are not commonly used. The most well-known of these are Internet Explorer and Opera. jsPsych is not tested on these and other browsers not listed in the Supported section above. jsPsych experiments might work in these browsers, but they might not. If you want to give participants the option to use unsupported browsers, then we recommend carefully testing your experiment to make sure that everything works as expected. Otherwise, we suggest asking your participants to only use a supported browser, or incorporating browser, device, and/or feature checks at the start of your experiment. jsPsych offers built-in methods for exclusion based on minimum browser size and WebAudio API compatibility. You can incorporate other browser/device/feature checks into your experiment by adding custom JavaScript code.
"},{"location":"overview/browser-device-support/#mobile-devices","title":"Mobile Devices","text":"In general, jsPsych experiments can be run on mobile devices (smartphones and tablets). However, certain plugins will not work on mobile. For instance, any plugin that requires a keyboard response without a text input box, such as the *-keyboard-response plugins, will not work. Even plugins that do work on mobile might work differently than they do on desktop and laptop computers. For instance, on mobile devices, a text input box will cause an on-screen keyboard to pop up, which affects the visible content on the screen.
If you plan to run an experiment that allows people to use mobile devices, we recommend doing some extra testing to make sure that everything works as expected. In particular, you may want to check that: * Font sizes are readable on smaller screens * Stimuli sizes are large enough and appropriate for the task * Page is laid out as intended (e.g. elements are centered and do not overlap) * Response options are touchscreen-friendly (e.g. buttons rather than key presses) * Response options (e.g. buttons, text boxes, radio buttons) are large enough and far enough apart to be easily selected with a finger tap
It's possible to use your browser's developer tools to emulate mobile devices (this page shows how to do it in Chrome), which is useful for getting a sense of how your experiment will look on mobile devices. Just be aware that there are limitations to emulator tools, and there are some aspects of mobile devices/browsers that a desktop browser will not be able to simulate.
"},{"location":"overview/browser-device-support/#mobile-browsers","title":"Mobile Browsers","text":"The browser options for mobile phones and tablets are slightly different than those for desktop and laptop computers. In addition to mobile versions of Chrome, Firefox, Safari, and Edge, other notable mobile browsers include Opera Mobile, Samsung Internet, UC Browser, and Dolphin. Because of the greater diversity of mobile browsers and volatility in their usage statistics, jsPsych does not officially support any particular set of mobile browsers. However, we do anticipate that most experiments should work in most mobile browsers, especially the mobile versions of browsers that we do support in Desktop mode. If you run into a problem using jsPsych in mobile browsers, please report it on the jsPsych GitHub Issues page! We do our best to fix browser incompatibilities that are not specific to a single experiment.
"},{"location":"overview/building-surveys/","title":"Building Surveys in jsPsych","text":""},{"location":"overview/building-surveys/#choosing-which-jspsych-survey-plugin-to-use","title":"Choosing which jsPsych survey plugin to use","text":"jsPsych has several plugins that allow you to present survey questions during your experiment. The one you choose will depend on what exactly you'd like to do, and your preferences for convenience/parameterization versus flexibility.
- Survey-* plugins:
survey-likert
, survey-multi-choice
, survey-multi-select
, survey-text
- Only one question type and one page per trial
- Parameterization makes it easy to define questions
- Work well with timeline variables
- Ideal for adding survey-style questions into repetitive trial procedures
- Limited functionality and customization options
survey-html-form
plugin - Can mix different question types on the same page
- No parameters for defining questions - you write the form HTML
- Maximally flexible, so ideal if you need a lot of control over the survey content and style
survey
plugin - Not well-suited for use with timeline variables
- Large set of built-in question types and parameterized customization options
- Can mix different question types on the same page
- Can present mutliple pages that participants can navigate back and forth through, without losing responses
- Parameters for defining questions, but more config/code than the
survey-*
plugins - Built-in convenience parameters for many survey question types and features (e.g. response validation, conditional question display, 'other'/'none'/'select all' options)
The survey
plugin differs from most other jsPsych plugins in that is a simple wrapper for an external JavaScript library called SurveyJS. This allows jsPsych users to take advantage of all of the SurveyJS features, documentation, and example code, but it also means that the survey
plugin does not follow the same familiar conventions as most other jsPsych plugins. Users will need to familiarize themselves somewhat with the SurveyJS library in order to use the plugin. The remaining documentation on this page provides some guidance for getting started with SurveyJS and the jsPsych survey
plugin.
"},{"location":"overview/building-surveys/#getting-started-with-surveyjs","title":"Getting started with SurveyJS","text":"The SurveyJS form library is a large and powerful survey-building framework with its own helpful documentation, examples, and demos. Here we have tried to orient jsPsych users to the basic steps for constructing surveys and highlight the features that jsPsych users may find most useful. However, it is not possible for us to reproduce the SurveyJS documentation here, so we encourage you to take advantage of their comprehensive documentation and demo/code examples.
SurveyJS allows you to build surveys using a JavaScript/JSON object, a JavaScript function, or a combination of both. You can read more about these options in the SurveyJS documentation:
- Define a survey in JSON
- Define a survey with JavaScript
The jsPsych survey
plugin provides the survey_json
and survey_function
parameters to allow you to construct a SurveyJS survey using these JSON and JavaScript methods. The next two sections on this page explain more about each method: Creating a survey with JSON and Using JavaScript to create or modify the survey.
Here are some other places to start learning about SurveyJS:
- Add multiple pages to a survey
- Configure conditional page visibility
- Page navigation UI (previous, next, and submit buttons)
- Add conditional logic and dynamic texts
- Set default values
SurveyJS has some more specific features that some researchers might find useful, including:
- Automatic question numbering (across the survey, within each page, and using custom values/characters)
- Response validation
- Table of contents and navigation across sections
- Progress bar
- Carry responses forward from a selection question
- Carry responses forward from a dynamic matrix/panel
- Conditional visibility for elements/questions (see also this example)
- Special choices for multi-choice-type questions: None, Other, Select All, Refuse to answer, and Don't know
- Localization (adapting the survey's language based on a country/region value)
- Text piping (dynamically insert text into questions/answers based on previous responses)
You can find realistic examples on the SurveyJS examples/demos page. And to view all of the survey-level options, see the Survey API documentation.
"},{"location":"overview/building-surveys/#creating-a-survey-with-json","title":"Creating a survey with JSON","text":"SurveyJS allows you to define the survey contents using an object with parameters names and values. At a minimum, the survey JSON object should contain a property called 'elements'. The value of 'elements' is an array that contains at least one element/question to be shown on the page.
// Survey with a single text entry question.\nconst survey_json = {\n elements: [{\n name: \"example\",\n title: \"Enter some text in the box below!\",\n type: \"text\"\n }]\n};\n
Each element is an object with a 'type', which is the element/question type (see the survey
plugin's Questions/Elements section for a list of type options). The element objects should also contain any other parameters and configuration options for that question, such as the question name (used to identify the question in the data), title (prompt shown to the participant), whether or not a response is required, and other parameters that might be relevant to that particular question type. The Questions/Elements section in the survey
plugin documentation contains links to the SurveyJS documentation for each question type, where you can find more information about the required and optional parameters.
Once you've created the survey JSON object, as we've done above, it can be used as the survey_json
parameter in a jsPsych survey
trial:
const survey_trial = {\n type: jsPsychSurvey,\n survey_json: survey_json\n};\n\ntimeline.push(survey_trial);\n
That's it! The code above will create a valid survey.
JSON vs JavaScript objects
JSON (JavaScript Object Notation) is a text format for organizing data. It is very similar to a JavaScript object, but not exactly the same. The survey_json
parameter takes a JSON-compatible JavaScript object, rather than a JSON string. We use the 'JSON' term for this parameter to make it clear that this parameter should not contain functions, and for consistency with SurveyJS documentation. To read more about JSON vs JavaScript objects, see e.g. here and here.
"},{"location":"overview/building-surveys/#multiple-pages","title":"Multiple pages","text":"You can specify 'elements' as a top-level property in the survey JSON, and those elements will be shown on a single page. If you'd like the survey to have more than one page, then you can add a 'pages' property to the survey JSON object. The value of 'pages' should be an array of objects, where each object defines a single page. Each page object should contain its own 'elements' array.
The example below defines a survey with two pages. Each page has a set of elements/questions, as well as some optional parameters (page name and title).
const survey_json = {\n pages: [\n {\n name: \"page_1\",\n title: \"Your Name\",\n elements: [{\n type: \"text\",\n name: \"first_name\",\n title: \"Enter your first name:\"\n }, {\n type: \"text\",\n name: \"last_name\",\n title: \"Enter your last name:\"\n }\n }, {\n name: \"page_2\",\n title: \"Personal Information\",\n elements: [{\n type: \"text\",\n name: \"location\",\n title: \"Where do you live?\"\n }, {\n type: \"text\",\n name: \"occupation\",\n title: \"What is your occupation?\"\n }, {\n type: \"text\",\n name: \"age\",\n title: \"How old are you?\",\n inputType: \"number\",\n min: 0,\n max: 120\n }\n }]\n};\n
"},{"location":"overview/building-surveys/#survey-level-options","title":"Survey-level options","text":"Along with either the 'elements' or 'pages' property, you can add optional survey-level properties to the top-level of your survey JSON object. The survey-level properties might include things like: a title (shown at the top of each page), whether to use automatic question numbering, labels for the page navigation buttons, and text to use for marking required questions. These and other survey-level parameters are not required - you only need to set these values if you want to change them from the defaults.
const survey_json = {\n title: \"Survey title\",\n showQuestionNumbers: \"off\",\n completeText: \"Done\",\n pageNextText: \"Next\",\n pagePrevText: \"Back\",\n requiredText: \"[REQUIRED]\",\n pages: [{\n elements: {\n // ... page 1 questions\n }\n }, {\n elements: {\n // ... page 2 questions\n }\n }]\n};\n
Some of the survey-level options can also be set a the page level. See the Page API documentation for more information.
For more survey JSON examples, see the SurveyJS JSON documentation, the Examples section on the survey
plugin documentation page, and the examples folder in the survey
plugin package.
"},{"location":"overview/building-surveys/#using-javascript-to-create-or-modify-the-survey","title":"Using JavaScript to create or modify the survey","text":"SurveyJS allows you to create or modify your survey using JavaScript. The JavaScript approach can do any of the configuration that can be done in JSON, plus it allows you to make your survey more dynamic. For instance, you could use the survey function parameter to change the contents of the survey based on the participant's earlier responses. The survey function parameter also allows you to define any other functions that should run during the survey. For instance, you might want to run custom code in response to a page change or response input event.
In the jsPsych survey
plugin, the survey_function
parameter receives a 'survey' argument, which is a SurveyJS survey model that you can manipulate. If you do not include a value for the survey_json
parameter, then the survey_function
will receive an empty survey. In this case, your survey_function
must add at least one page with at least one element/question to produce a valid survey.
Here's the JavaScript function that would create the same survey that's defined in the first JSON example above:
const survey_function = (survey) => {\n // add page\n const page = survey.addNewPage(\"page1\");\n // add question\n const text_question = page.addNewQuestion(\"text\", \"example\");\n text_question.title = \"Enter some text in the box below!\";\n};\n\nconst survey_trial = {\n type: jsPsychSurvey,\n survey_function: survey_function\n};\n\ntimeline.push(survey_trial);\n
"},{"location":"overview/building-surveys/#combining-json-and-function-parameters","title":"Combining JSON and function parameters","text":"If you specify survey JSON using the survey_json
parameter, then the survey_function
will receive a survey object that was created using your JSON. This means that, in your survey function, you can access all of the survey elements that you have defined in the JSON.
Here's a slightly more realistic case for when you might want to use the survey_function
parameter. In this example, we want to ask the participant to make a color choice at the start of the experiment, and then reference their choice in a later survey
trial question. We can't do this with the JSON configuration because we cannot know the participant's color choice in advance - it only becomes available during the experiment.
However, we can use the survey_function
to dynamically access the participant's color response from the jsPsych data and use that value in the survey question title. We'll use the survey_function
just for this one dynamic part of the survey, and define everything else in JSON.
// Create an array of color choices\nconst color_choices = ['red', 'green', 'blue', 'yellow', 'pink', 'orange', 'purple'];\n\n// Create an html-button-response trial where the participant can choose a color\nconst select_color_trial = {\n type: jsPsychHtmlButtonResponse,\n stimulus: '<p>Which of these is your favorite color?</p>',\n choices: color_choices,\n button_html: '<button class=\"jspsych-btn\" style=\"color:%choice%\";\">%choice%</button>',\n data: {trial_id: 'color_trial'}\n};\n\n// Create the survey JSON \nconst color_survey_json = {\n elements: [{\n type: \"boolean\",\n renderAs: \"radio\",\n name: \"color_confirmation\",\n title: \"\" // This value will be set in the survey function\n }]\n};\n\n// Create a survey function to access the participant's response \n// from an earlier trial and modify the survey accordingly\nconst color_survey_function = (survey) => {\n // Get the earlier color selection response (button index) from the jsPsych data\n const color_choice_index = jsPsych.data.get().filter({trial_id: 'color_trial'}).values()[0].response;\n const color_choice = color_choices[color_choice_index];\n // Get the question that we want to modify\n const color_confirmation_question = survey.getQuestionByName('color_confirmation');\n // Change the question title to include the name of the color that was selected\n color_confirmation_question.title = `\n Earlier you chose ${color_choice.toUpperCase()}. Do you still like that color?\n `;\n}\n\n// Create the jsPsych survey trial using both the survey JSON and survey function\nconst color_survey_trial = {\n type: jsPsychSurvey,\n survey_json: color_survey_json,\n survey_function: color_survey_function\n};\n\njsPsych.run([select_color_trial, color_survey_trial]);\n
For more information about creating/modifying surveys with JavaScript, see the SurveyJS documentation. The SurveyJS API reference contains all of the properties (parameters), methods, and events you can use when working with the survey, page, and question objects.
"},{"location":"overview/building-surveys/#deciding-between-json-and-function-parameters","title":"Deciding between JSON and function parameters","text":"You can create survey
trials entirely with JSON, entirely with a JavaScript function, or using a combination of both. Sometimes this is just a matter of preference. But you must use the JavaScript survey_function
method when you want to:
- Dynamically modify the survey based on a participant's response from an earlier trial, or any other information you don't have access to before the survey trial begins.
- Use custom functions as part of your survey's configuration. For instance, you might want to write a function that is triggered by a particular survey event, such as when response values change or when the survey is completed. You cannot put JavaScript functions into the
survey_json
object, so you will need to add them using the survey_function
parameter.
Custom response validation
There is a special case where you don't need to use the survey_function
parameter for running a custom function, which is for adding custom response validation. The survey
plugin includes a convenience parameter called validation_function
, which allows you to add some custom JavaScript code to validate responses. Of course, you can also use the survey_function
parameter for this, in which case you would set your custom function to run in response to the survey's onValidateQuestion
event.
"},{"location":"overview/building-surveys/#creating-dynamic-surveys-with-json","title":"Creating dynamic surveys with JSON","text":"Although you cannot include JavaScript functions as values in your survey_json
, SurveyJS has implemented some convenience options for setting up certain kinds of dynamic survey behavior from within the JSON configuration. For instance, you can define a condition expression from within the JSON that will dynamically show/hide a question or choice/column/row (see Conditional Visibility and Expressions). As another example, you can use a placeholder value inside a text string to insert the response from a particular question into that string (see Dynamic Texts: Question Values).
In general, you can access information in the survey JSON that exists within that same survey
trial and use it to produce dynamic behavior (e.g. putting placeholder values in text strings, automatically populating choice values, etc.). But if you need to access information that becomes available during the experiment but outside of that particular survey
trial, you will need to use the survey_function
parameter.
"},{"location":"overview/building-surveys/#defining-survey-trialsquestions-programmatically","title":"Defining survey trials/questions programmatically","text":"Sometimes it's useful to be able to create your survey content programmatically. For instance, let's say you want to present a page with questions that all use the exact same format but with different prompts. You could define them one-by-one in a survey_json
object, but doing it this way might produce a very large JSON object with lots of repeated configuration across all questions.
Instead, it's often preferrable to separate the information that changes across questions from the things that stay the same. This can make it easier to make changes and prevent errors, since the things that are common across questions only need to be defined once. Similarly, if you are repeating a trial procedure lots of times, then you might want to define a single survey
trial that repeats with slightly different parameters.
The following section presents some different options for programmatically defining multiple questions in a survey trial, or multiple survey trials, based on an array of values that should change across questions or trials.
The example below shows how to use the survey_function
to loop over a set of question-level variables (titles/prompts and names), and dynamically add each question to a single survey page. You could use this same approach to add questions across multiple pages within the same survey trial.
const survey_function = (survey) => {\n\n // this array stores any information that changes across questions\n const questions = [\n {title: \"Question 1\", name: \"q1\"},\n {title: \"Question 2\", name: \"q2\"},\n // ... more question-level variables ...\n {title: \"Question N\", name: \"qN\"}\n ];\n\n // create a single page\n const page = survey.addNewPage(\"questions\");\n\n for (let i=0; i<questions.length; i++) {\n // for each object in the questions array,\n // create a new question and add it to the same page\n let q = page.addNewQuestion(\"text\", questions[i].name, i);\n q.title = questions[i].title;\n q.inputType = \"range\";\n q.min = 0;\n q.max = 100;\n q.step = 10;\n q.defaultValue = 50;\n q.isRequired = true;\n }\n\n}\n
Use the 'matrix' question type for repeated response options
The example above was used to illustrate how you can loop over information to programmatically construct a series of questions that are shown on the same page. But in cases where you have different question prompts that all use the same multiple choice options, you might prefer to use the the SurveyJS \"matrix\" question type. This question type creates a table where each row is a question and each column is a response option. The table format is often used for Likert scales, satisfaction surveys, etc. You can even create a table that repeats a set of questions with different response types using the SurveyJS multi-select matrix (\"matrixdropdown\") question type.
Rather than repeating a question format within the same trial, perhaps you want to use trial-level variables to generate separate survey
trials, for instance in order to incorporate them into a larger repeating trial procedure. jsPsych's timeline variables feature was designed to address this use case, but the use of timeline variables looks a little different with the survey
plugin. This is because the various individual parameters that you might want to change across survey
trials don't have their own plugin parameters - instead everything is nested within the survey_json
parameter. Below are some examples showing how you can programmatically generate survey trials using a set of trial-level variables.
-
Use the conventional timeline variables approach with the survey_json
parameter. This approach is probably not ideal, because the timeline variables array has to contain the entire survey_json
object for each trial. This kind of defeats the purpose of timeline variables, because you are still defining all of the survey JSON separately for each question/trial. In any case, here's what it looks like:
const word_trials = {\n timeline: [\n {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '+',\n choices: \"NO_KEYS\",\n trial_duration: 500\n },\n {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: jsPsych.timelineVariable('word'),\n choices: \"NO_KEYS\",\n trial_duration: 1000\n },\n {\n type: jsPsychSurvey,\n survey_json: jsPsych.timelineVariable('survey_json'),\n data: { word: jsPsych.timelineVariable('word') }\n }\n ],\n timeline_variables: [\n {\n word: 'cheese',\n survey_json: { elements: [ {type: \"text\", title: \"Enter a word related to CHEESE:\", autocomplete: \"off\" } ], showQuestionNumbers: false, completeText: \"Next\", focusFirstQuestionAutomatic: true } \n },\n {\n word: 'ring',\n survey_json: { elements: [ {type: \"text\", title: \"Enter a word related to RING:\", autocomplete: \"off\" } ], showQuestionNumbers: false, completeText: \"Next\", focusFirstQuestionAutomatic: true } \n },\n {\n word: 'bat',\n survey_json: { elements: [ {type: \"text\", title: \"Enter a word related to BAT:\", autocomplete: \"off\" } ], showQuestionNumbers: false, completeText: \"Next\", focusFirstQuestionAutomatic: true }\n },\n {\n word: 'cow',\n survey_json: { elements: [ {type: \"text\", title: \"Enter a word related to COW:\", autocomplete: \"off\" } ], showQuestionNumbers: false, completeText: \"Next\", focusFirstQuestionAutomatic: true }\n }\n ]\n};\n
Consider using a survey-* plugin for presenting a single question type
The example above was created just to demonstrate how to combine the survey
plugin and timeline variables. But if this were a real experiment, since each survey trial contains just one question, we'd be better off using one of the other survey-* plugins because the parameterization of those plugins works well with timeline variables. Of course, you may have other reasons for wanting to use the survey
plugin in this type of trial procedure, for instance to take advantage of some its convenience features (e.g. different question types on the same page, response validation).
-
Use jsPsych's functions-as-parameters approach for the survey_json
parameter. With this approach, instead of defining a static JSON object for the value of survey_json
, you would write a function that returns the survey JSON object for that specific trial.
This approach allows you to define the survey content using a combination of variable and static values. Also, jsPsych will run this function right before the trial begins, which means that you can change the survey content dynamically based on information that only becomes available during the experiment. Here's an example using timeline variables, though you can use the same approach to dynamically create the survey content without using timeline variables.
const word_trials = {\n timeline: [\n {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '+',\n choices: \"NO_KEYS\",\n trial_duration: 500\n },\n {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: jsPsych.timelineVariable('word'),\n choices: \"NO_KEYS\",\n trial_duration: 1000\n },\n {\n type: jsPsychSurvey,\n survey_json: function() {\n // This is a function that dynamically creates the JSON configuration for each trial.\n // Inside the function, you can access timeline variables, jsPsych data, and other global variables\n // that you define. This function will be called right before the trial starts.\n const this_trial_json = { \n elements: [\n {\n type: \"text\", \n title: `Enter a word related to ${jsPsych.timelineVariable('word').toUpperCase()}:`, \n autocomplete: \"off\" \n }\n ], \n showQuestionNumbers: false, \n completeText: \"Next\", \n focusFirstQuestionAutomatic: true \n }\n return this_trial_json;\n },\n data: { word: jsPsych.timelineVariable('word') }\n }\n ],\n timeline_variables: [\n { word: 'cheese' },\n { word: 'ring' },\n { word: 'bat' },\n { word: 'cow' }\n ]\n};\n
-
Use the survey_function
parameter. You can reference trial-level variables from inside this function, so the general idea here is the same as the example above. The difference is that here you are using SurveyJS's JavaScript API syntax to create the survey content, instead of the JSON configuration. Again, this could be done without timeline variables, but this example uses timeline variables for convenience:
const create_word_survey = (survey) => {\n // Create question using timeline variables\n const page = survey.addNewPage('page1');\n const question = page.addNewQuestion('text'); \n question.title = `Enter a word related to ${jsPsych.timelineVariable('word').toUpperCase()}`;\n question.autocomplete = \"off\";\n // Set survey-level parameters\n survey.showQuestionNumbers = false;\n survey.completeText = \"Next\";\n survey.focusFirstQuestionAutomatic = true;\n}\n\nconst word_trials = {\n timeline: [\n {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '+',\n choices: \"NO_KEYS\",\n trial_duration: 500\n },\n {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: jsPsych.timelineVariable('word'),\n choices: \"NO_KEYS\",\n trial_duration: 1000\n },\n {\n type: jsPsychSurvey,\n survey_function: create_word_survey,\n data: { word: jsPsych.timelineVariable('word') }\n }\n ],\n timeline_variables: [\n { word: 'cheese' },\n { word: 'ring' },\n { word: 'bat' },\n { word: 'cow' }\n ]\n};\n
"},{"location":"overview/data/","title":"Data Storage, Aggregation, and Manipulation","text":""},{"location":"overview/data/#data-in-jspsych-permanent-and-non-permanent-data","title":"Data in jsPsych: permanent and non-permanent data.","text":"There are two very different kinds of data storage: data stored in memory and data stored permanently. Data stored permanently exists even after the browser running jsPsych closes, typically in a database or in a file on a server. Data stored in memory exists only as long the browser window running jsPsych is open.
jsPsych has many features for interacting with data stored in memory, but few for permanent data storage. This is a deliberate choice, as there are dozens of ways that data could be stored permanently. jsPsych does not lock you into one particular solution. However, saving data permanently is obviously a crucial component of any experiment, and the second half of this page contains a few suggestions on how to accomplish permanent data storage.
"},{"location":"overview/data/#storing-data-in-jspsychs-data-structure","title":"Storing data in jsPsych's data structure","text":"jsPsych has a centralized collection of data that is built as the experiment runs. Each trial adds to the collection, and you can access the data with various functions, including jsPsych.data.get()
, which returns the entire set of data.
In most cases, data collection will be automatic and hidden. Plugins save data on their own so it is not uncommon to have the only interaction with the data be at the end of the experiment when it is time to save it in a permanent manner (see sections below about how to do this). However, there are some situations in which you may want to interact with the data; in particular, you may want to store additional data that the plugins are not recording, like a subject identifier or condition assignment. You may also want to add data on a trial by trial basis. For example, in a Stroop paradigm you would want to label which trials are congruent and which are incongruent. These scenarios are explored below.
"},{"location":"overview/data/#adding-data-to-all-trials","title":"Adding data to all trials","text":"Often it is useful to add a piece of data to all of the trials in the experiment. For example, appending the subject ID to each trial. This can be done with the jsPsych.data.addProperties()
function. Here is an example:
// generate a random subject ID with 15 characters\nvar subject_id = jsPsych.randomization.randomID(15);\n\n// pick a random condition for the subject at the start of the experiment\nvar condition_assignment = jsPsych.randomization.sampleWithoutReplacement(['conditionA', 'conditionB', 'conditionC'], 1)[0];\n\n// record the condition assignment in the jsPsych data\n// this adds a property called 'subject' and a property called 'condition' to every trial\njsPsych.data.addProperties({\n subject: subject_id,\n condition: condition_assignment\n});\n
"},{"location":"overview/data/#adding-data-to-a-particular-trial-or-set-of-trials","title":"Adding data to a particular trial or set of trials","text":"Data can be added to a particular trial by setting the data
parameter for the trial. The data
parameter is an object of key-value pairs, and each pair is added to the data for that trial.
var trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'imgA.jpg',\n data: { image_type: 'A' }\n}\n
Data declared in this way is also saved in the trials on any nested timelines:
var block = {\n type: jsPsychImageKeyboardResponse,\n data: { image_type: 'A' },\n timeline: [\n {stimulus: 'imgA1.jpg'},\n {stimulus: 'imgA2.jpg'}\n ]\n}\n
The data object for a trial can also be updated in the on_finish
event handler. You can override properties or add new ones. This is particularly useful for cases where the value depends on something that happened during the trial.
var trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'imgA.jpg',\n on_finish: function(data){\n if(jsPsych.pluginAPI.compareKeys(data.response, 'j')){\n data.correct = true;\n } else {\n data.correct = false;\n }\n }\n}\n
"},{"location":"overview/data/#skipping-data-collection-for-a-particular-trial","title":"Skipping data collection for a particular trial","text":"Sometimes you may want to skip data collection for a particular trial. This can be done by setting the record_data
parameter to false
. This is useful if you want your data output to only contain the trials that collect relevant responses from the participant. For example, you might want to skip data collection for trials that just present a fixation cross for a fixed period of time.
var trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'imgA.jpg',\n record_data: false\n}\n
"},{"location":"overview/data/#aggregating-and-manipulating-jspsych-data","title":"Aggregating and manipulating jsPsych data","text":"When accessing the data with jsPsych.data.get()
the returned object is a special data collection object that exposes a number of methods for aggregating and manipulating the data. The full list of methods is detailed in the data module documentation.
Here are some examples of data collection manipulation.
All data generated by the image-keyboard-response plugin:
var data = jsPsych.data.get().filter({trial_type: 'image-keyboard-response'});\n
All data generated by the categorize-image plugin with a correct response:
var data = jsPsych.data.get().filter({trial_type: 'categorize-image', correct: true});\n
All data with a response time between 100 and 500ms:
var data = jsPsych.data.get().filterCustom(function(x){ return x.rt >= 100 && x.rt <=500 });\n
Applying filters consecutively to get all trials from a particular plugin with a response time above 100ms:
var data = jsPsych.data.get().filter({trial_type: 'image-keyboard-response'}).filterCustom(function(x){ return x.rt > 100; });\n
Getting the data from the last n trials:
var n = 3;\nvar data = jsPsych.data.get().last(n);\n
Getting the data from the last n trials with a correct response:
var n = 3;\nvar data = jsPsych.data.get().filter({correct: true}).last(n);\n
Getting the data from the first n trials:
var n = 3;\nvar data = jsPsych.data.get().first(n);\n
Counting the number of trials with a correct response in a data collection:
var count = jsPsych.data.get().filter({correct: true}).count();\n
Selecting all of the response times from a data collection:
var response_times = jsPsych.data.get().select('rt');\n
Calculating various descriptive statistics on the response times in a data collection:
jsPsych.data.get().select('rt').mean();\njsPsych.data.get().select('rt').sum();\njsPsych.data.get().select('rt').min();\njsPsych.data.get().select('rt').max();\njsPsych.data.get().select('rt').variance();\njsPsych.data.get().select('rt').sd();\njsPsych.data.get().select('rt').median();\njsPsych.data.get().select('rt').count();\n
"},{"location":"overview/data/#storing-data-permanently-as-a-file","title":"Storing data permanently as a file","text":"This is one of the simplest methods for saving jsPsych data on the server that is running the experiment. It involves a short PHP script and a few lines of JavaScript code. This method will save each participant's data as a CSV file on the server. This method will only work if you are running on a web server with PHP installed, or a local server with PHP (e.g., XAMPP).
This method uses a short PHP script to write files to the server:
<?php\n// get the data from the POST message\n$post_data = json_decode(file_get_contents('php://input'), true);\n$data = $post_data['filedata'];\n// generate a unique ID for the file, e.g., session-6feu833950202 \n$file = uniqid(\"session-\");\n// the directory \"data\" must be writable by the server\n$name = \"data/{$file}.csv\"; \n// write the file to disk\nfile_put_contents($name, $data);\n?>\n
The file_put_contents($name, $data)
method requires permission to write new files. An easy way to solve this is to create a directory on the server that will store the data and use the chmod command to give all users write permission to that directory. In the above example, the directory data/
is used to store files.
To use the PHP script, the JavaScript that runs jsPsych needs to send the filedata
information. This is done through an AJAX call.
function saveData(name, data){\n var xhr = new XMLHttpRequest();\n xhr.open('POST', 'write_data.php'); // 'write_data.php' is the path to the php file described above.\n xhr.setRequestHeader('Content-Type', 'application/json');\n xhr.send(JSON.stringify({filedata: data}));\n}\n\n// call the saveData function after the experiment is over\ninitJsPsych({\n on_finish: function(){ saveData(jsPsych.data.get().csv()); }\n});\n
Danger
The example above has minimal security and should probably not be used without additional security measures put in place. The risk is that someone can write arbitrary data using the saveData()
function and store it to a file on your webserver. If they can guess the file name generated by the PHP script, or access a directory listing containing all of the filenames, then they can potentially write executable code to your server and run it.
One fix is to store the CSV files outside the web directory on the server. This requires changing the path in the PHP script above from /data
to a folder that is not accessible on the web. You should only use this solution if you have access to more than just the web directory on your server.
You can also configure your web server to block access to the folder you are storing data in.
The MySQL option below is more secure.
"},{"location":"overview/data/#storing-data-permanently-in-a-mysql-database","title":"Storing data permanently in a MySQL database","text":"Another solution for storing data generated by jsPsych is to write it to a database.
There are dozens of database options. MySQL is one of the most popular relational databases, is free to use, and relatively easy to install. This code will assume that you have a MySQL database installed on your server that is hosting the jsPsych experiment, and that your server is able to execute PHP code. If you are trying to run on a local machine, you'll need to install a local server environment like XAMPP.
You'll need two PHP scripts. The first is a configuration file for your database. Save it as database_config.php
on your server. Within this file are configuration options for the database. You'll need to change these according to how you have configured your MySQL installation.
<?php\n $servername = \"localhost\";\n $port = 3306;\n $username = \"username\";\n $password = \"password\";\n $dbname = \"database\";\n $table = \"tablename\";\n?>\n
The second PHP file will write data to the database. This script reads the database to discover what columns are in the table, and then only allows data to be entered in that matches those columns. This is a security feature. Save this file as write_data.php
on your server.
<?php\n\n// this path should point to your configuration file.\ninclude('database_config.php');\n\n$data_array = json_decode(file_get_contents('php://input'), true);\n\ntry {\n $conn = new PDO(\"mysql:host=$servername;port=$port;dbname=$dbname\", $username, $password);\n $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);\n // First stage is to get all column names from the table and store\n // them in $col_names array.\n $stmt = $conn->prepare(\"SHOW COLUMNS FROM `$table`\");\n $stmt->execute();\n $col_names = array();\n while($row = $stmt->fetchColumn()) {\n $col_names[] = $row;\n }\n // Second stage is to create prepared SQL statement using the column\n // names as a guide to what values might be in the JSON.\n // If a value is missing from a particular trial, then NULL is inserted\n $sql = \"INSERT INTO $table VALUES(\";\n for($i = 0; $i < count($col_names); $i++){\n $name = $col_names[$i];\n $sql .= \":$name\";\n if($i != count($col_names)-1){\n $sql .= \", \";\n }\n }\n $sql .= \");\";\n $insertstmt = $conn->prepare($sql);\n for($i=0; $i < count($data_array); $i++){\n for($j = 0; $j < count($col_names); $j++){\n $colname = $col_names[$j];\n if(!isset($data_array[$i][$colname])){\n $insertstmt->bindValue(\":$colname\", null, PDO::PARAM_NULL);\n } else {\n $insertstmt->bindValue(\":$colname\", $data_array[$i][$colname]);\n }\n }\n $insertstmt->execute();\n }\n echo '{\"success\": true}';\n} catch(PDOException $e) {\n echo '{\"success\": false, \"message\": ' . $e->getMessage();\n}\n$conn = null;\n?>\n
To send the data, we use an XMLHttpRequest
request in JavaScript.
function saveData() {\n var xhr = new XMLHttpRequest();\n xhr.open('POST', 'write_data.php'); // change 'write_data.php' to point to php script.\n xhr.setRequestHeader('Content-Type', 'application/json');\n xhr.onload = function() {\n if(xhr.status == 200){\n var response = JSON.parse(xhr.responseText);\n console.log(response.success);\n }\n };\n xhr.send(jsPsych.data.get().json());\n}\n
It's important that the XMLHttpRequest
is able to complete before the experiment is closed. If you invoke the saveData()
function at the end of your experiment and the participant closes the window before all of the data has been transferred you will lose that data. To mitigate this risk, you can use the call-function
plugin's async
option to prevent the experiment from progressing until the request is complete.
var trial = {\n type: jsPsychCallFunction,\n async: true,\n func: function(done){\n var xhr = new XMLHttpRequest();\n xhr.open('POST', 'write_data.php');\n xhr.setRequestHeader('Content-Type', 'application/json');\n xhr.onload = function() {\n if(xhr.status == 200){\n var response = JSON.parse(xhr.responseText);\n console.log(response.success);\n }\n done(); // invoking done() causes experiment to progress to next trial.\n };\n xhr.send(jsPsych.data.get().json());\n }\n}\n
"},{"location":"overview/dynamic-parameters/","title":"Dynamic parameters","text":"Most trial parameters can also be specified as functions. In a typical declaration of a jsPsych trial, parameters are known at the start of the experiment. This makes it impossible to alter the content of the trial based on the outcome of previous trials. However, when functions are used as the parameter value, the function is evaluated right before the trial starts, and the return value of the function is used as the parameter value for that trial. This enables dynamic updating of the parameter based on data that a participant has generated or any other information that you do not know in advance.
"},{"location":"overview/dynamic-parameters/#examples","title":"Examples","text":""},{"location":"overview/dynamic-parameters/#providing-feedback","title":"Providing Feedback","text":"Here is a sketch of how this functionality could be used to display feedback to a participant in the Flanker Task.
var timeline = [];\n\nvar trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<<<<<',\n choices: ['f','j'],\n data: {\n stimulus_type: 'congruent',\n target_direction: 'left'\n },\n on_finish: function(data){\n // Score the keyboard response as correct or incorrect.\n if(jsPsych.pluginAPI.compareKeys(data.response, \"f\")){\n data.correct = true;\n } else {\n data.correct = false; \n }\n }\n}\n\nvar feedback = {\n type: jsPsychHtmlKeyboardResponse,\n trial_duration: 1000,\n stimulus: function(){\n // The feedback stimulus is a dynamic parameter because we can't know in advance whether\n // the stimulus should be 'correct' or 'incorrect'.\n // Instead, this function will check the accuracy of the last response and use that information to set\n // the stimulus value on each trial.\n var last_trial_correct = jsPsych.data.get().last(1).values()[0].correct;\n if(last_trial_correct){\n return \"<p>Correct!</p>\"; // the parameter value has to be returned from the function\n } else {\n return \"<p>Wrong.</p>\"; // the parameter value has to be returned from the function\n }\n }\n}\n\ntimeline.push(trial, feedback);\n
Note
When scoring a participant's response, the jsPsych.pluginAPI.compareKeys
function is only needed to compare keyboard responses. For other kinds of response types, such as button presses, you can compare the participant's response and correct response values directly, e.g.
if (data.response == 0)){\n data.correct = true;\n} else {\n data.correct = false; \n}\n
Or: data.correct = data.response === data.correct_response;\n
"},{"location":"overview/dynamic-parameters/#randomizing-a-parameter-value","title":"Randomizing a parameter value","text":"Here's an example of using a dynamic parameter to randomize the inter-trial interval (ITI) duration. This time, the dynamic parameter is created using a named function instead of an anonymous function.
var random_duration = function() {\n var rand_dur = jsPsych.randomization.sampleWithoutReplacement([500,600,700,800],1)[0];\n return rand_dur;\n}\n\nvar trial = {\n type: jsPsychHtmlKeyboardResponse\n stimulus: '+',\n post_trial_gap: random_duration // if you use a named function for a dynamic parameter, then just use the function name (without parentheses after it)\n}\n
"},{"location":"overview/dynamic-parameters/#storing-changing-variables-in-the-data","title":"Storing changing variables in the data","text":"The trial's data
parameter can be also function, which is useful for when you want to save information to the data that can change during the experiment. For example, if you have a global variable called current_difficulty
that tracks the difficulty level in an adaptive task, you can save the current value of this variable to the trial data like this:
var current_difficulty; // value changes during the experiment\n\nvar trial = {\n type: jsPsychSurveyText,\n questions: [{prompt: \"Please enter your response.\"}]\n data: function() { \n return {difficulty: current_difficulty}; \n }\n}\n
It's also possible to use a function for any of the individual properties in the trial's data
object, for instance if you want to combine static and dynamic information in the data:
var trial = {\n type: jsPsychSurveyText,\n questions: [{prompt: \"Please enter your response.\"}]\n data: {\n difficulty: function() { \n return current_difficulty; // the difficulty value changes during the experiment\n },\n task_part: 'recall', // this part of the data is always the same\n block_number: 1\n }\n}\n
"},{"location":"overview/dynamic-parameters/#nested-parameters","title":"Nested Parameters","text":"Dyanmic parameters work the same way with nested parameters, which are parameters that contain one or more sets of other parameters. For instance, many survey-* plugins have a questions
parameter that is a nested parameter: it is an array that contains the parameters for one or more questions on the page. To make the questions
parameter dynamic, you can use a function that returns the array with all of the parameters for each question:
var subject_id; // value is set during the experiment\n\nvar trial = {\n type: jsPsychSurveyText,\n questions: function(){\n var questions_array = [ \n {prompt: \"Hi \"+subject_id+\"! What's your favorite city?\", required: true, name: 'fav_city'},\n {prompt: \"What is your favorite fruit?\", required: true, name: 'fav_fruit'},\n ];\n return questions_array;\n }\n}\n
You can also use a function for any of the individual parameters inside of a nested parameter.
var trial = {\n type: jsPsychSurveyText,\n questions: [\n { \n prompt: function() { \n // this question prompt is dynamic - the text that is shown \n // will change based on the participant's earlier response\n var favorite_city = jsPsych.data.getLastTrialData().values()[0].response.fav_city;\n var text = \"Earlier you said your favorite city is \"+favorite_city+\". What do you like most about \"+favorite_city+\"?\"\n return text;\n }, \n required: true,\n rows: 40,\n columns: 10\n },\n { prompt: \"What is your favorite fruit?\", required: true, name: 'fav_fruit' }\n ]\n}\n
"},{"location":"overview/dynamic-parameters/#when-dynamic-parameters-cant-be-used","title":"When dynamic parameters can't be used","text":"Note that if the plugin expects the value of a given parameter to be a function, then this function will not be evaluated at the start of the trial. This is because some plugins allow the researcher to specify functions that should be called at some point during the trial. Some examples of this include the stimulus
parameter in the canvas-* plugins, the mistake_fn
parameter in the cloze plugin, and the stim_function
parameter in the reconstruction plugin. If you want to check whether this is the case for a particular plugin and parameter, then the parameter's type
in the plugin.info
section of the plugin file. If the parameter type is ParameterType.FUNCTION
, then this parameter must be a function and it will not be executed before the trial starts.
Even though function evaluation doesn't work the same way with these parameters, the fact that the parameters are functions means that you can get the same dynamic functionality. These functions are typically evaluated at some point during the trial, so you still get updates to values within the function during the trial.
"},{"location":"overview/events/","title":"Event-related callback functions","text":"jsPsych offers the ability to call arbitrary functions in response to certain events occurring, like the end of a trial or when new data is saved. This page summarizes the different opportunities for callback functions and how to specify them.
"},{"location":"overview/events/#on_close","title":"on_close","text":"The on_close
callback can be declared in the initJsPsych
method. The callback triggers when the user leaves the page, but before any content on the page is removed from the browser's memory. This can be used, for example, to save data as the user is leaving the page.
initJsPsych({\n on_close: function(){\n var data = jsPsych.data.get().json();\n save_data_to_server(data);\n }\n});\n
"},{"location":"overview/events/#on_data_update","title":"on_data_update","text":"The on_data_update
callback can be declared in the initJsPsych
method. The callback triggers at the end of a data update cycle. This happens after every trial, after the on_finish (trial) and on_trial_finish events execute, allowing you to modify the data in those callbacks, and then use this callback to store the data. The function will be passed a single argument, which contains the data that was written.
initJsPsych({\n on_data_update: function(data) {\n console.log('Just added new data. The contents of the data are: '+JSON.stringify(data));\n }\n});\n
"},{"location":"overview/events/#on_finish-trial","title":"on_finish (trial)","text":"The on_finish
callback can be added to any trial. The callback will trigger whenever the trial ends. The callback function will be passed a single argument, containing the data object from the trial. This data object is editable. Any changes made in the on_finish function will be stored in the internal data collection.
var trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'imgA.png',\n on_finish: function(data) {\n if(jsPsych.pluginAPI.compareKeys(data.response, 'j')){\n data.correct = true;\n } else {\n data.correct = false;\n }\n }\n};\n
"},{"location":"overview/events/#on_finish-experiment","title":"on_finish (experiment)","text":"The on_finish
callback can be declared in the initJsPsych
method. The callback will trigger once all trials in the experiment have been run. The method will be passed a single argument, containing all of the data generated in the experiment.
initJsPsych({\n on_finish: function(data) {\n console.log('The experiment is over! Here is all the data: '+JSON.stringify(data));\n }\n});\n
"},{"location":"overview/events/#on_load","title":"on_load","text":"The on_load
callback can be added to any trial. The callback will trigger once the trial has completed loading. For most plugins, this will occur once the display has been initially updated but before any user interactions or timed events (e.g., animations) have occurred.
var trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'imgA.png',\n on_load: function() {\n console.log('The trial just finished loading.');\n }\n};\n
"},{"location":"overview/events/#on_start-trial","title":"on_start (trial)","text":"The on_start
callback can be added to any trial. The callback will trigger right before the trial begins. The callback function will be passed a single argument, containing the trial object. If any of the parameters of the trial are functions or timeline variables, these will be evaluated before on_start
is called, and the trial object will contain the evaluated value. The trial object is modifiable, and any changes made will affect the trial.
var trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'imgA.png',\n on_start: function(trial) {\n console.log('The trial is about to start.');\n trial.stimulus = 'imgB.png'; // this will change what stimulus is displayed in the trial\n }\n};\n
"},{"location":"overview/events/#on_timeline_finish","title":"on_timeline_finish","text":"The on_timeline_finish
callback can be declared in a timeline node. The callback will be triggered when the timeline ends. The event will trigger only once if the timeline loops, after all repetitions are complete.
var procedure = {\n timeline: [trial1, trial2],\n timeline_variables: [\n { stimulus: 'person-1.jpg' },\n { stimulus: 'person-2.jpg' },\n { stimulus: 'person-3.jpg' },\n { stimulus: 'person-4.jpg' }\n ],\n on_timeline_finish: function() {\n console.log('This timeline has finished.');\n }\n}\n
"},{"location":"overview/events/#on_timeline_start","title":"on_timeline_start","text":"The on_timeline_start
callback can be declared in a timeline node. The callback will be triggered when the timeline starts during the experiment. If a conditional_function
is used, then the conditional function will execute first, and the on_timeline_start
function will only execute if the conditional function returns true
. The event is triggered once, even if the timeline has a loop_function
or repetitions
.
var procedure = {\n timeline: [trial1, trial2],\n conditional_function: function() {\n console.log('This conditional function will execute first.')\n return true;\n },\n on_timeline_start: function() {\n console.log('This timeline has started');\n }\n}\n
"},{"location":"overview/events/#on_trial_finish","title":"on_trial_finish","text":"The on_trial_finish
callback can be declared in the initJsPsych
method. The callback will trigger at the end of every trial in the experiment, after the trial object's on_finish
callback has been run. The callback function will be passed a single argument, containing the data object from the trial. If you want a callback to trigger only for the end of certain trials, use the on_finish
callback on the trial object instead.
initJsPsych({\n on_trial_finish: function(data) {\n console.log('A trial just ended.');\n console.log(JSON.stringify(data));\n }\n});\n
"},{"location":"overview/events/#on_trial_start","title":"on_trial_start","text":"The on_trial_start
callback can be declared in the initJsPsych
method. The callback will trigger at the start of every trial in the experiment, before the trial-specific on_start
callback is executed. The function receives a single argument: a modifiable copy of the trial object that will be used to run the next trial. Changes can be made to this object to alter the parameters of the upcoming trial.
var current_score = 0; // a variable that is updated throughout the experiment to keep track of the current score.\n\ninitJsPsych({\n on_trial_start: function(trial) {\n trial.data.score_at_start_of_trial = current_score;\n console.log('A trial just started.');\n }\n});\n
"},{"location":"overview/exclude-browser/","title":"Exclude Participants Based on Browser Features","text":"Changed in 7.1
Online participants will use many different kinds of browsers. Depending on the experiment, it may be important to specify a minimum feature set of the browser.
As of v7.1 of jsPsych, the recommended way to do this is using the browser-check plugin. This plugin can record many features of the participant's browser and exclude participants who do not meet a defined set of inclusion criteria. Please see the browser-check plugin documentation for more details.
The prior approach of using the exclusions
parameter in initJsPsych()
is deprecated. It was removed as of v8.0
. You can find the documentation for it in the 7.0 docs.
"},{"location":"overview/experiment-options/","title":"Experiment-wide settings","text":"There are several options that can be set when calling initJsPsych()
to initialize the jsPsych experiment.
Options are specified in the object passed to initJsPsych
. For example, to specify a default inter-trial interval, a minimum valid response time duration, and a maximum width for all of the experiment's page content, the object would contain:
initJsPsych({\n default_iti: 250, \n minimum_valid_rt: 100, \n experiment_width: 800 \n});\n
"},{"location":"overview/experiment-options/#controlling-where-jspsych-renders-on-the-page","title":"Controlling where jsPsych renders on the page","text":"By default, jsPsych will render the experiment in the <body>
element of a page. It is possible to display the experiment in a different element (e.g., a <div>
) by specifying the display_element
parameter.
<body>\n <div id=\"jspsych-target\"></div>\n</body>\n<script>\n\n initJsPsych({\n display_element: 'jspsych-target'\n });\n\n</script>\n
This option is useful if the experiment needs to be rendered on a page with other content (e.g., a demo version of the experiment with annotation text), or if additional control over the display element is desired. Custom CSS rules can be applied to position, size, scale, etc. the display element.
"},{"location":"overview/experiment-options/#experiment-events","title":"Experiment events","text":"Several experiment-wide events can trigger functions. This is documented in more detail on the event-related callback functions page. The events that trigger functions are:
on_finish
: Called at the end of the experiment. on_trial_start
: Called at the beginning of every trial. on_trial_finish
: Called at the end of every trial. on_data_update
: Called whenever new data is added to the jsPsych data object. on_interaction_data_update
: Called whenever new interaction data (e.g., the participant enters or exits fullscreen mode) is added. on_close
: Called right before the page closes, such as when a participant closes the experiment early.
"},{"location":"overview/experiment-options/#specify-exclusion-criteria","title":"Specify exclusion criteria","text":"Exclusion criteria can be specified based on features of the user's web browser, such as the display size and whether certain features are reported. See the page on excluding participants based on browser features.
"},{"location":"overview/experiment-options/#display-a-progress-bar","title":"Display a progress bar","text":"An automatic or manually updated progress bar can be displayed at the top of the screen. By default, the text next to the progress bar is \"Completion Progress\", but this text can be changed with the message_progress_bar
parameter in initJsPsych
. See the progress bar page for more details.
"},{"location":"overview/experiment-options/#choose-the-method-for-playing-audio-files","title":"Choose the method for playing audio files","text":"Specifying the use_webaudio
parameter in initJsPsych()
allows you to choose whether to use the WebAudio API or HTML5 audio for playing audio files during your experiment. By default, jsPsych uses the WebAudio API to play audio files. Among other features, the WebAudio API allows for more precise measurement of response times relative to the onset of the audio.
However, loading files through the WebAudio API causes errors when running an experiment offline (i.e., by double-clicking on the HTML file, rather than hosting it on a web server). This is due to the cross-origin security policy implemented by web browsers. For this reason, jsPsych switches to a 'safe mode' when it detects that the webpage is running offline, and automatically uses HTML5 audio to prevent errors, even when use_webaudio
has been explicitly set to true
. For more information, see the section Cross-origin requests (CORS) and safe mode on the Running Experiments page.
initJsPsych({\n use_webaudio: false\n});\n
"},{"location":"overview/experiment-options/#set-the-default-intertrial-interval","title":"Set the default intertrial interval","text":"By default the next trial in a timeline will begin immediately after the conclusion of the previous trial. An experiment-wide delay can be specified using the default_iti
parameter to initJsPsych()
.
initJsPsych({\n default_iti: 500\n});\n
This parameter is specified in milliseconds. A blank screen will display between each trial for the duration of the ITI.
"},{"location":"overview/experiment-options/#specify-the-maximum-width-of-the-experiment","title":"Specify the maximum width of the experiment","text":"The experiment will, by default, take up 100% of the display element. Usually the display element is the <body>
, and the experiment is the full width of the screen. (This can be overridden by specifying the display_element
parameter described above).
Specifying the experiment_width
parameter will set a maximum width for the display. The parameter is specified in pixels.
initJsPsych({\n experiment_width: 750\n});\n
"},{"location":"overview/experiment-options/#specify-a-minimum-valid-response-time","title":"Specify a minimum valid response time","text":"By default, jsPsych will treat any keyboard response time as valid. However, it's possible to specify a minimum valid response time (in ms) for key presses. Any key press that is less than this value will be treated as invalid and ignored. Note that this parameter only applies to keyboard responses, and not to other response types such as buttons and sliders. The default value is 0.
// ignore any keyboard responses that are less than 100 ms\ninitJsPsych({\n minimum_valid_rt: 100\n});\n
"},{"location":"overview/experiment-options/#choose-whether-you-want-keyboard-choicesresponses-to-be-case-sensitive","title":"Choose whether you want keyboard choices/responses to be case-sensitive","text":"JavaScript keyboard events make a distinction between uppercase and lowercase key responses (e.g. 'a' and 'A'). Often the researcher just cares about which physical key was pressed, and not whether the key press would result in an uppercase letter (for instance, if CapsLock is on or if the Shift key is held down). For this reason, jsPsych converts all key choice parameters and key responses as lowercase by default. This makes it easier to specify key choices (e.g. choices: ['a']
, instead of choices: ['a','A']
), and it makes it easier to check and score a participant's response.
There may be situations when you want key choices and responses to be case-sensitive. You can change this by setting the case_sensitive_responses
parameter to true
in initJsPsych
.
// use case-sensitive key choices and responses, \n// i.e. uppercase and lower case letters ('a' and 'A') will be treated as different key choices, \n// and will be recorded this way in the data\ninitJsPsych({\n case_sensitive_responses: true\n});\n
Note that this setting only applies to key choices and responses that use jsPsych's keyboard response listener, such as in the *-keyboard-response
plugins. This does NOT apply to responses that are made by typing into a text box, such as in the survey-text
and cloze
plugins.
"},{"location":"overview/experiment-options/#override-safe-mode-when-running-experiments-offline","title":"Override 'safe mode' when running experiments offline","text":"By default, jsPsych switches to a 'safe mode' when it detects that the webpage is running offline (via the file://
protocol) in order to prevent certain errors. Specifically, in safe mode, HTML5 audio is used to play audio files (even when use_webaudio
has been explicitly set to true
) and video preloading is disabled (both automatic and manual preloading). For more information, see the Cross-origin requests (CORS) and safe mode section on the Running Experiments page.
It's possible to override this safe mode feature by setting the override_safe_mode
parameter to true
in initJsPsych
. This is something you might do if you've disabled certain security settings in your browser for testing purposes. This parameter has no effect when your experiment is running online (on a server), because it will be using the http://
or https://
protocol, which does not trigger safe mode.
initJsPsych({\n override_safe_mode: true\n});\n
"},{"location":"overview/experiment-options/#add-extensions","title":"Add extensions","text":"Extensions are jsPsych modules that can run throughout the experiment and interface with any plugin to extend the functionality of the plugin. One example of an extension is eye tracking, which allows you to gather gaze data during any trial and add it to that trial's data object. If you want to use extensions in your experiment, you must specify this when you initialize the experiment with initJsPsych
. The extensions
parameter in initJsPsych
is an array of objects, where each object specifies the extension that you'd like to use in the experiment. Below is an example of adding the webgazer extension.
initJsPsych({\n extensions: [\n {type: jsPsychExtensionWebgazer}\n ]\n});\n
"},{"location":"overview/extensions/","title":"Extensions","text":"Extensions are jsPsych modules that can interface with any plugin to extend the functionality of the plugin. A canonical example of an extension is eye tracking. An eye tracking extension allows a plugin to gather gaze data and add it to the plugin's data object.
"},{"location":"overview/extensions/#using-an-extension","title":"Using an Extension","text":"To use an extension in an experiment, you'll load the extension file via a <script>
tag (just like adding a plugin) and then initialize the extension in the parameters of initJsPsych()
.
<head>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/extension-example@1.0.0\"></script>\n</head>\n
initJsPsych({\n extensions: [\n {type: jsPsychExtensionExample, params: {...} }\n ]\n})\n
To enable an extension during a trial, add the extension to the extensions
list for the trial. Some extensions may also support or require an object of parameters to configure the extension:
var trial = {\n extensions: [\n {type: jsPsychExtensionExample, params: {...} }\n ]\n}\n
"},{"location":"overview/extensions/#list-of-extensions","title":"List of Extensions","text":"Extension Description jspsych\u2011ext\u2011webgazer.js Enables eye tracking using the WebGazer library."},{"location":"overview/extensions/#writing-an-extension","title":"Writing an Extension","text":"See our developer's guide for extensions for information about how to create a new extension.
"},{"location":"overview/eye-tracking/","title":"Eye Tracking","text":"jsPsych supports eye tracking through the WebGazer library. WebGazer uses computer vision techniques to identify features of the participant's eyes via a webcam and predicts gaze location. The system is calibrated by having the participant click on or look at known locations on the screen. These locations are linked to eye features. Gaze location is predicted using regression.
"},{"location":"overview/eye-tracking/#getting-started","title":"Getting Started","text":""},{"location":"overview/eye-tracking/#load-webgazerjs","title":"Load webgazer.js","text":"The official version of WebGazer is currently not supported by jsPsych. Our fork of the library contains some minor improvements aimed at the kind of experiments that jsPsych is typically used for, e.g., situations in which the timing of display screens needs to be accurate.
You must include the webgazer.js
file in your experiment via a <script>
tag. However, the webgazer.js
file is not part of any of the jsPsych NPM packages and is therefore not available via the unpkg.com CDN. Instead, it can be found on the jsdelivr.net CDN at: \"https://cdn.jsdelivr.net/gh/jspsych/jspsych@jspsych@7.0.0/examples/js/webgazer/webgazer.js\".
<head>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://cdn.jsdelivr.net/gh/jspsych/jspsych@jspsych@7.0.0/examples/js/webgazer/webgazer.js\"></script>\n</head>\n
Note
A copy of our forked webgazer.js
file is also included in the jsPsych release, in the /examples/js/webgazer
folder. So if you prefer to download and host all of your jsPsych files (i.e. set-up option 2 in the Hello World tutorial), then another option is to load that file rather than using the jsdelivr link above. Assuming you downloaded the release and copied the webgazer.js
file into a folder called js/webgazer
in your root project directory, then you would load the file like this:
<script src=\"js/webgazer/webgazer.js\"></script>\n
"},{"location":"overview/eye-tracking/#load-the-jspsych-webgazer-extension","title":"Load the jsPsych webgazer extension","text":"The webgazer extension adds functionality to jsPsych for interacting with webgazer. Load it like you would a plugin file.
<head>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://cdn.jsdelivr.net/gh/jspsych/jspsych@jspsych@7.0.0/examples/js/webgazer/webgazer.js\"></script>\n <script src=\"https://unpkg.com/@jspsych/extension-webgazer@1.1.0\"></script>\n</head>\n
To use the WebGazer extension in an experiment, include it in the list of extensions passed to initJsPsych()
initJsPsych({\n extensions: [\n {type: jsPsychExtensionWebgazer}\n ]\n})\n
"},{"location":"overview/eye-tracking/#initialize-the-camera","title":"Initialize the camera","text":"To help the participant position their face correctly for eye tracking you can use the webgazer-init-camera plugin. This will show the participant what the camera sees, including facial feature landmarks, and prevent the participant from continuing until their face is in good position for eye tracking. This plugin will also trigger the experiment to request permission to access the user's webcam if it hasn't already been granted.
var init_camera_trial = {\n type: jsPsychWebgazerInitCamera\n}\n
"},{"location":"overview/eye-tracking/#calibration","title":"Calibration","text":"To calibrate WebGazer, you can use the webgazer-calibrate plugin. This plugin allows you to specify a set of points on the screen for calibration and to choose the method for calibrating -- either clicking on each point or simply fixating on each point. The location of calibration points is specified in percentages, e.g., [25,50]
will result in a point that is 25% of the width of the screen from the left edge and 50% of the height of the screen from the top edge. Options for controlling other details of the calibration are explained in the documentation for the plugin.
Note that instructions are not included in the calibration plugin, so you'll likely want to use a different plugin (e.g., html-button-response
) to display instructions prior to running the calibration.
var calibration_trial = {\n type: jsPsychWebgazerCalibrate,\n calibration_points: [[25,50], [50,50], [75,50], [50,25], [50,75]],\n calibration_mode: 'click'\n}\n
"},{"location":"overview/eye-tracking/#validation","title":"Validation","text":"To measure the accuracy and precision of the calibration, you can use the webgazer-vaidate plugin. Like the calibration plugin, you can specify a list of points to perform validation on. Here you can specify the points as either percentages or in terms of the distance from the center of the screen in pixels. Which mode you use will probably depend on how you are defining your stimuli throughout the experiment. You can also specify the radius of tolerance around each point, and the plugin will calculate the percentage of measured gaze samples within that radius. This is a potentially useful heuristic for deciding whether or not to calibrate again. Options for controlling other details of the validation are explained in the documentation for the plugin.
var validation_trial = {\n type: jsPsychWebgazerValidate,\n validation_points: [[-200,200], [200,200],[-200,-200],[200,-200]],\n validation_point_coordinates: 'center-offset-pixels',\n roi_radius: 100\n}\n
The validation procedure stores the raw gaze data for each validation point, the computed average offset from each validation point, the percentage of samples within the roi_radius
for each validation point, and the number of samples collected per second.
{\n raw_gaze: [...],\n percent_in_roi: [...],\n average_offset: [...],\n samples_per_sec: ...\n}\n
We recommend performing calibration and validation periodically throughout your experiment.
"},{"location":"overview/eye-tracking/#adding-eye-tracking-to-a-trial","title":"Adding eye tracking to a trial","text":"To enable eye tracking for a trial in your experiment, you can simply add the WebGazer extension to the trial.
var trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<img id=\"scene\" src=\"my-scene.png\"></img>',\n extensions: [\n {\n type: jsPsychExtensionWebgazer, \n params: { \n targets: ['#scene']\n }\n }\n ]\n}\n
This will turn on WebGazer at the start of the trial.
The params
property in the extensions
declaration allows you to pass in a list of CSS selector strings. The bounding rectangle of the DOM element that matches each selector will be recorded in the data for that trial. This allows for easy alignment of the gaze data and objects on the screen.
webgazer_targets : {\n 'selector': {x: ..., y: ..., height: ..., width: ..., top: ..., left: ..., right: ..., bottom:...}\n 'selector': {x: ..., y: ..., height: ..., width: ..., top: ..., left: ..., right: ..., bottom:...}\n}\n
Gaze data will be added to the trial's data under the property webgazer_data
. The gaze data is an array of objects. Each object has an x
, a y
, and a t
property. The x
and y
properties specify the gaze location in pixels and t
specifies the time in milliseconds since the start of the trial. Note that establishing the precision and accuracy of these measurements across the variety of web browsers and systems that your experiment participants might be using is quite difficult. For example, different browsers may cause small systematic shifts in the accuracy of t
values.
webgazer_data: [\n {x: ..., y: ..., t: ...},\n {x: ..., y: ..., t: ...},\n {x: ..., y: ..., t: ...},\n {x: ..., y: ..., t: ...}\n]\n
"},{"location":"overview/eye-tracking/#tips-for-improving-data-quality","title":"Tips for Improving Data Quality","text":"These are some anecdotal observations about factors that improve data quality.
- The quality of the camera feed is essential. Good lighting makes a big difference. You may want to encourage participants to perform any eye tracking experiments in a well-lit room.
- Participants need to keep their head relatively still during and after calibration. The calibration is not robust to head movements.
- WebGazer's click-based calibration can be used throughout the experiment. You can turn this on by calling
jsPsych.extensions.webgazer.startMouseCalibration()
at any point in the experiment. If you use a continue button to advance through the experiment and move the location of the continue button around you can be making small adjustments to the calibration throughout. - Computing the gaze predictions consumes more computational resources than most other things that jsPsych is typically used for. The sampling rate that WebGazer is able to achieve will depend on the computing power of the participant's device. You may want to ask the participant to close any non-essential software and browser windows prior to completing the experiment. You may also want to check that the sampling rate is sufficiently high as part of validation.
If you have tips based on your own experience please consider sharing them on our discussion forum and we'll add to this list!
"},{"location":"overview/eye-tracking/#example","title":"Example","text":"Tip
Additional example experiments using WebGazer are available in the /examples folder of the jsPsych release. See webgazer.html
, webgazer_image.html
, and webgazer_audio.html
.
Example
Here's an example of putting all of the pieces above together. This example also shows how to use data from the validation to decide whether or not to recalibrate. You can try this experiment here (opens in new tab).
<!DOCTYPE html>\n<html>\n <head>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-preload@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-button-response@2.0.1\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-webgazer-init-camera@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-webgazer-calibrate@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-webgazer-validate@2.0.0\"></script>\n <script src=\"https://cdn.jsdelivr.net/gh/jspsych/jspsych@jspsych@7.0.0/examples/js/webgazer/webgazer.js\"></script>\n <script src=\"https://unpkg.com/@jspsych/extension-webgazer@1.1.0\"></script>\n <link\n rel=\"stylesheet\"\n href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\"\n />\n <style>\n .jspsych-btn {\n margin-bottom: 10px;\n }\n </style>\n </head>\n <body></body>\n <script>\n\n var jsPsych = initJsPsych({\n extensions: [\n {type: jsPsychExtensionWebgazer}\n ]\n });\n\n var preload = {\n type: jsPsychPreload,\n images: ['img/blue.png']\n }\n\n var camera_instructions = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `\n <p>In order to participate you must allow the experiment to use your camera.</p>\n <p>You will be prompted to do this on the next screen.</p>\n <p>If you do not wish to allow use of your camera, you cannot participate in this experiment.<p>\n <p>It may take up to 30 seconds for the camera to initialize after you give permission.</p>\n `,\n choices: ['Got it'],\n }\n\n var init_camera = {\n type: jsPsychWebgazerInitCamera\n }\n\n var calibration_instructions = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `\n <p>Now you'll calibrate the eye tracking, so that the software can use the image of your eyes to predict where you are looking.</p>\n <p>You'll see a series of dots appear on the screen. Look at each dot and click on it.</p>\n `,\n choices: ['Got it'],\n }\n\n var calibration = {\n type: jsPsychWebgazerCalibrate,\n calibration_points: [\n [25,25],[75,25],[50,50],[25,75],[75,75]\n ],\n repetitions_per_point: 2,\n randomize_calibration_order: true\n }\n\n var validation_instructions = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `\n <p>Now we'll measure the accuracy of the calibration.</p>\n <p>Look at each dot as it appears on the screen.</p>\n <p style=\"font-weight: bold;\">You do not need to click on the dots this time.</p>\n `,\n choices: ['Got it'],\n post_trial_gap: 1000\n }\n\n var validation = {\n type: jsPsychWebgazerValidate,\n validation_points: [\n [25,25],[75,25],[50,50],[25,75],[75,75]\n ],\n roi_radius: 200,\n time_to_saccade: 1000,\n validation_duration: 2000,\n data: {\n task: 'validate'\n }\n }\n\n var recalibrate_instructions = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `\n <p>The accuracy of the calibration is a little lower than we'd like.</p>\n <p>Let's try calibrating one more time.</p>\n <p>On the next screen, look at the dots and click on them.<p>\n `,\n choices: ['OK'],\n }\n\n var recalibrate = {\n timeline: [recalibrate_instructions, calibration, validation_instructions, validation],\n conditional_function: function(){\n var validation_data = jsPsych.data.get().filter({task: 'validate'}).values()[0];\n return validation_data.percent_in_roi.some(function(x){\n var minimum_percent_acceptable = 50;\n return x < minimum_percent_acceptable;\n });\n },\n data: {\n phase: 'recalibration'\n }\n }\n\n var calibration_done = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `\n <p>Great, we're done with calibration!</p>\n `,\n choices: ['OK']\n }\n\n var begin = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `<p>The next screen will show an image to demonstrate adding the webgazer extension to a trial.</p>\n <p>Just look at the image while eye tracking data is collected. The trial will end automatically.</p>\n <p>Press any key to start.</p>\n `\n }\n\n var trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/blue.png',\n choices: \"NO_KEYS\",\n trial_duration: 2000,\n extensions: [\n {\n type: jsPsychExtensionWebgazer, \n params: {targets: ['#jspsych-image-keyboard-response-stimulus']}\n }\n ]\n }\n\n var show_data = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: function() {\n var trial_data = jsPsych.data.getLastTrialData().values();\n var trial_json = JSON.stringify(trial_data, null, 2);\n return `<p style=\"margin-bottom:0px;\"><strong>Trial data:</strong></p>\n <pre style=\"margin-top:0px;text-align:left;\">${trial_json}</pre>`;\n },\n choices: \"NO_KEYS\"\n };\n\n jsPsych.run([\n preload, \n camera_instructions, \n init_camera, \n calibration_instructions, \n calibration, \n validation_instructions, \n validation, \n recalibrate,\n calibration_done,\n begin, \n trial, \n show_data\n ]);\n\n </script>\n</html>\n
Below is example data from the image-keyboard-response trial taken from the experiment above. In addition to the standard data that is collected for this plugin, you can see the additional webgazer_data
and webgazer_targets
arrays. The webgazer_data
shows 21 gaze location estimates during the 1-second image presentation. The webgazer_targets
array shows that there was one target, the image-keyboard-response stimulus, and tells you the x- and y-coordinate boundaries for the target (image) rectangle. By comparing each of the x/y locations from the webgazer_data
locations array with the target boundaries in webgazer_targets
, you can determine if/when the estimated gaze location was inside the target area.
{\n \"rt\": null,\n \"stimulus\": \"img/blue.png\",\n \"response\": null,\n \"trial_type\": \"image-keyboard-response\",\n \"trial_index\": 4,\n \"time_elapsed\": 30701,\n \"webgazer_data\": [\n { \"x\": 1065, \"y\": 437, \"t\": 39},\n { \"x\": 943, \"y\": 377, \"t\": 79},\n { \"x\": 835, \"y\": 332, \"t\": 110},\n { \"x\": 731, \"y\": 299, \"t\": 146},\n { \"x\": 660, \"y\": 271, \"t\": 189},\n { \"x\": 606, \"y\": 251, \"t\": 238},\n { \"x\": 582, \"y\": 213, \"t\": 288},\n { \"x\": 551, \"y\": 200, \"t\": 335},\n { \"x\": 538, \"y\": 183, \"t\": 394},\n { \"x\": 514, \"y\": 177, \"t\": 436},\n { \"x\": 500, \"y\": 171, \"t\": 493},\n { \"x\": 525, \"y\": 178, \"t\": 542},\n { \"x\": 537, \"y\": 182, \"t\": 592},\n { \"x\": 543, \"y\": 178, \"t\": 633},\n { \"x\": 547, \"y\": 177, \"t\": 691},\n { \"x\": 558, \"y\": 174, \"t\": 739},\n { \"x\": 574, \"y\": 183, \"t\": 789},\n { \"x\": 577, \"y\": 197, \"t\": 838},\n { \"x\": 584, \"y\": 214, \"t\": 889},\n { \"x\": 603, \"y\": 218, \"t\": 937},\n { \"x\": 606, \"y\": 221, \"t\": 987}\n ],\n \"webgazer_targets\": [\n \"#jspsych-image-keyboard-response-stimulus\": {\n \"x\": 490,\n \"y\": 135,\n \"height\": 300,\n \"width\": 300,\n \"top\": 135,\n \"bottom\": 435,\n \"left\": 490,\n \"right\": 790\n }\n ]\n}\n
"},{"location":"overview/fullscreen/","title":"Fullscreen Experiments","text":"You can run your experiment in fullscreen mode by using the jspsych-fullscreen plugin.
var jsPsych = initJsPsych();\n\nvar timeline = [];\n\ntimeline.push({\n type: jsPsychFullscreen,\n fullscreen_mode: true\n});\n\ntimeline.push({\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'This trial will be in fullscreen mode.'\n});\n\n// exit fullscreen mode\ntimeline.push({\n type: jsPsychFullscreen,\n fullscreen_mode: false\n});\n\ntimeline.push({\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'This trial will NOT be in fullscreen mode.'\n});\n\njsPsych.run(timeline);\n
For security reasons, web browsers require that users initiate an action to launch fullscreen mode. The fullscreen plugin displays a button that the user must click to change the display to fullscreen.
Safari does not support keyboard input when the browser is in fullscreen mode. Therefore, the function will not launch fullscreen mode on Safari. The experiment will ignore any trials using the fullscreen plugin in Safari.
"},{"location":"overview/media-preloading/","title":"Media Preloading","text":"If an experiment uses image, audio, or video files as stimuli, it is a good idea to preload the files before running the experiment. You can preload files at any point in your experiment using the jsPsych preload
plugin. Preloading files means that the participant's browser will download the files and store them in local memory on the participant's computer. This is important because displaying or playing a media file is much faster if it is already in memory on the participant's computer. Without preloading, there will be noticeable delays in the display of media, which will affect any timing measurements (such as how long an image is displayed, or a participant's response time since first viewing an image). For particularly large files, like video, preloading content avoids lengthy pauses in the middle of the experiment that can be disruptive to the flow of the experiment.
Warning
Note that video preloading will not work when you run your experiment offline (e.g., by double-clicking on the HTML file), but it will work once your experiment is running online (hosted on a server). The [Cross-origin requests (CORS) and safe mode](running-experiments.md#cross-origin-requests-cors-and-safe-mode) section on the Running Experiments page contains more information about this.\n
"},{"location":"overview/media-preloading/#automatic-preloading","title":"Automatic Preloading","text":"jsPsych can automatically preload audio, video, and image files that are used as parameters for the standard set of plugins, based on the timeline that is passed to jsPsych.run
. You must initiate this preloading using a preload
trial. You should add this preload
trial into your timeline when you want the preloading to occur, and set the auto_preload
parameter to true
.
// the \"auto_preload: true\" setting tells the plugin to automatically find \n// stimuli to preload based the main experiment timeline (used in jsPsych.run)\nvar preload = {\n type: jsPsychPreload,\n auto_preload: true \n}\n\n// this image file can be automatically preloaded \nvar image_trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/file1.png'\n}\n\n// the sound file can be automatically preloaded \nvar sound_trial = {\n type: jsPsychAudioKeyboardResponse,\n stimulus: 'audio/hello.mp3'\n}\n\n// the video file can be automatically preloaded (as long as the experiment \n// is running on a server)\nvar video_trial = {\n type: jsPsychVideoKeyboardResponse,\n stimulus: ['video/sample_video.mp4']\n}\n\njsPsych.run([preload, image_trial, sound_trial, video_trial]);\n
"},{"location":"overview/media-preloading/#manual-preloading","title":"Manual preloading","text":"If you are using media files in your experiment but they are not being passed directly as parameters to the trials (e.g., because you are using functions as parameters that return the media files, you are using timeline variables, or you are embedding the media files in an HTML string), then these files will not be detected when you use the auto_preload
option, so you must manually specify them. The preload
plugin allows you to add these files using the images
, audio
and video
parameters.
// this image file cannot be automatically preloaded because it is embedded in \n// an HTML string\nvar image_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<img src=\"img/file1.png\"></img>',\n}\n\n// this audio file cannot be automatically preloaded because it is returned \n// from a function\nvar sound_trial = {\n type: jsPsychAudioKeyboardResponse,\n stimulus: function() { return 'audio/sound1.mp3' }\n}\n\n// these video files cannot be automatically preloaded because they are passed \n// into a trial using the jsPsych.timelineVariable function\nvar video_trials = {\n timeline: [\n {\n type: jsPsychVideoKeyboardResponse,\n stimulus: jsPsych.timelineVariable('video')\n }\n ],\n timeline_variables: [\n {video: ['video/1.mp4']},\n {video: ['video/2.mp4']}\n ]\n}\n\n// to manually preload media files, create an array of file paths for each \n// media type\nvar images = ['img/file1.png'];\nvar audio = ['audio/sound1.mp3'];\nvar video = ['video/1.mp4', 'video/2.mp4'];\n\n// these array can be passed into the preload plugin using the images, audio \n// and video parameters\nvar preload = {\n type: jsPsychPreload,\n images: images,\n audio: audio,\n video: video\n}\n\njsPsych.run([preload, image_trial, sound_trial, video_trials]);\n
"},{"location":"overview/media-preloading/#combining-automatic-and-manual-preloading","title":"Combining automatic and manual preloading","text":"It's possible to combine automatic and manual preloading. For instance, you may want to automatically preload all of the media files based on your experiment timeline, while also manually preloading any files that can't be automatically preloaded. Any duplicate file names across all preloading methods will be removed before preloading starts, so including the same file names in multiple preload
parameters will not affect the preloading duration.
// this file can be preloaded automatically\nvar image_trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/file1.png'\n}\n\n// this file can be preloaded automatically\nvar sound_trial = {\n type: jsPsychAudioKeyboardResponse,\n stimulus: 'audio/hello.mp3'\n}\n\n// these files must be preloaded manually\nvar video_trials = {\n timeline: [\n {\n type: jsPsychVideoKeyboardResponse,\n stimulus: jsPsych.timelineVariable('video')\n }\n ],\n timeline_variables: [\n {video: ['video/1.mp4']},\n {video: ['video/2.mp4']}\n ]\n}\n\nvar video = ['video/1.mp4', 'video/2.mp4'];\n\nvar preload = {\n type: jsPsychPreload,\n auto_preload: true, // automatically preload the image and audio files\n video: video // manually preload the videos used with timeline variables\n}\n\njsPsych.run([preload, image_trial, sound_trial, video_trials]);\n
"},{"location":"overview/media-preloading/#preloading-in-batches","title":"Preloading in batches","text":"Some experiments use many and/or large media files. This can cause problems when participants have slow and/or unreliable internet connections, because it increases the chances of loading errors during preloading. This can also cause problems with file caching, i.e. ensuring that the preloaded files remain in the browser's memory, because loading all stimuli at once may exceed the browser's cache limits. One option for mitigating these problems is to load the media files in smaller batches throughout the experiment. Files should be preloaded as close as possible to when they will be needed. For instance, if you have several blocks of trials, then right before each block, you can preload the stimuli that are needed for that block.
Here is an example with trials where the stimuli files can be preloaded automatically. In this case, the trials
parameter is used to tell the preload
plugin to preload the stimuli from a specific part of the timeline.
// these image files in these trial blocks can be automatically preloaded\nvar block_1 = {\n timeline: [\n {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/file1.png'\n },\n {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/file2.png'\n }\n ]\n}\n\nvar block_2 = {\n timeline: [\n {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/file3.png'\n },\n {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/file4.png'\n }\n ]\n}\n\nvar preload_1 = {\n type: jsPsychPreload,\n trials: block_1 // automatically preload just the images from block_1 trials\n}\n\nvar preload_2 = {\n type: jsPsychPreload,\n trials: block_2 // automatically preload just the images from block_2 trials\n}\n\njsPsych.run(\n // add each preload trial onto the timeline before the appropriate trial block\n [preload_1, block_1, preload_2, block_2]\n);\n
Below is an example with trials where the stimuli files cannot be preloaded automatically, because the stimuli files are passed to the trials via jsPsych.timelineVariable
. In this case, we create separate arrays for each batch of files, and then pass those arrays to the each preload trial.
// these trial blocks cannot be automatically preloaded because \n// the media files are passed to the trial parameters with timeline variables\nvar block_1 = {\n timeline: [...],\n timeline_variables: [\n {stim: 'file1.png'},\n {stim: 'file1.png'}\n ]\n}\n\nvar block_2 = {\n timeline: [...],\n timeline_variables: [\n {stim: 'file3.png'},\n {stim: 'file4.png'}\n ]\n}\n\nvar images_block_1 = ['file1.png', 'file2.png'];\nvar images_block_2 = ['file3.png', 'file4.png'];\n\n// preload trial for preloading the block 1 stimuli\nvar preload_1 = {\n type: jsPsychPreload,\n images: images_block_1\n}\n\n// preload trial for preloading the block 2 stimuli\nvar preload_2 = {\n type: jsPsychPreload,\n images: images_block_2\n}\n\njsPsych.run(\n // add each preload trial to the timeline before the appropriate trial block\n [preload_1, block_1, preload_2, block_2]\n);\n
"},{"location":"overview/media-preloading/#preloading-progress-bar","title":"Preloading progress bar","text":"By default, the preload
plugin will display a progress bar while files are being preloaded. This progress bar represents all files that are being preloaded during the trial, regardless of whether the file is being preloaded automatically via the auto_preload
or trials
parameters, or manually via the audio
, images
, and video
parameters. You may wish to turn the preload progress bar off if you are only loading a small number of files, as it will appear and disappear so quickly that the participant may be confused about what it was. You can control whether the preloading progress bar appears by setting the show_progress_bar
parameter in the preload
trial.
var preload_trial = {\n type: jsPsychPreload,\n auto_preload: true\n show_progress_bar: false // hide progress bar\n}\n
"},{"location":"overview/media-preloading/#loading-time-limits","title":"Loading time limits","text":"It's usually a good idea to set a time limit for file loading, to ensure that participants aren't waiting for an unreasonable amount of time. Time limits can be specified in milliseconds using the max_load_time
parameter. If you set a loading time limit and all files haven't finished loading before this time, then the preload
trial will either stop an error (if continue_after_error
is false, the default) or the trial will end and the experiment will continue (if continue_after_error
is true
). If max_load_time
is null
(the default), then there is no time limit.
var preload_trial = {\n type: jsPsychPreload,\n auto_preload: true\n max_load_time: 60000 // 1 minute\n}\n
"},{"location":"overview/media-preloading/#loading-and-error-messages","title":"Loading and error messages","text":"It's possible to specify custom messages to be shown on the page while the media files are loading, and in case of one or more file loading errors. The message
parameter allows you to customize the loading message using an HML-formatted string. If show_progress_bar
is true
, then this message will be shown above the progress bar.
var preload_trial = {\n type: jsPsychPreload,\n auto_preload: true\n message: 'Please wait while the experiment loads. This may take a few minutes.',\n}\n
A preloading error will occur when either (a) one or more files produces a loading error, and/or (b) all files have not finished loading before the max_load_time
duration. The error_message
parameter allows you to customize the messsage that's shown on the page in these cases. This message will only be shown if continue_after_error
is false
(the default).
var preload_trial = {\n type: jsPsychPreload,\n auto_preload: true,\n error_message: 'The experiment failed to load. Please contact the researcher.'\n}\n
In addition to the error_message
parameter, it's also possible to show more detailed error messages on the page about any files that failed to load. You can control this with the show_detailed_errors
parameter. Detailed error messages will appear below the general error message. This only applies if continue_after_error
is false
(the default).
Detailed error messages can be useful when testing and debugging your experiment. If show_detailed_errors
is true
, then if one or more loading errors occurs before the max_load_time
is reached, then the error page will also contian a list of the file(s) that produced an error, along with error information (if there is any). Note that this may not be a complete list, because it will only report any errors that occurred before the max_load_time
was reached. If there are no file loading errors but preloading hasn't finished before the max_load_time
, then detailed error message will just tell you that loading timed out.
var preload_trial = {\n type: jsPsychPreload,\n auto_preload: true,\n // show details of any file loading errors and/or loading time out\n show_detailed_errors: true \n}\n
"},{"location":"overview/media-preloading/#options-for-handling-errors","title":"Options for handling errors","text":"If continue_after_error
is true
, then the experiment will not stop if one or more files fails to load. Instead, the trial will end and the experiment will continue. However, the preload trial data will contain a property called success
, which is whether or not all files were loaded successfully, timeout
, which is whether or not the files loaded successfully before the max_load_time
. The preload trial data will also contain lists of any image
, audio
, and video
files that failed to load. This gives you the option to continue the experiment after preloading fails and use the preload trial data decide what to do next. For instance, you may decide to skip the trials that use the stimuli files that failed to load, or try loading the failed files again. Another option is to simply end the experiment when preloading fails, but send the data back to your server so that you have more information about the loading failure.
var preload_trial = {\n type: jsPsychPreload,\n auto_preload: true,\n message: 'Please wait while the experiment loads...',\n // don't stop the experiment if there are file loading errors or if loading times out\n continue_after_error: true \n}\n\nvar save_data = {\n type: jsPsychCallFunction,\n async: true,\n func: function(done){\n var data = jsPsych.data.get().json();\n save_data(data, function() {done()})\n }\n}\n\n// the experiment will stop here, since there are no valid key choices or trial duration \nvar fail_message = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'The experiment failed to load. Please contact the researcher.',\n choices: \"NO_KEYS\",\n trial_duration: null \n}\n\nvar if_loading_fails = {\n timeline: [save_data, fail_message],\n conditional_function: function() {\n if (jsPsych.data.getLastTrialData()[0].values().success) {\n // preloading was successful, so skip this conditional timeline\n // and move on with the experiment\n return false;\n } else {\n // preloading failed, so run this conditional timeline:\n // save the data to the server and show the fail message\n return true;\n }\n }\n}\n\n// ... rest of experiment\n\njsPsych.run([preload_trial, if_loading_fails, ... ])\n
The preload
plugin's on_success
and on_error
callback functions provide another way of tracking preloading progress and handling file loading errors. These functions are called after any file either loads successfully or produces an error, respectively. These functions receive a single argument, which is the path of the file (string) that loaded or produced an error.
var file_load_count = 0;\nvar file_error_count = 0;\n\nvar preload_trial = {\n type: jsPsychPreload,\n auto_preload: true,\n on_error: function(file) {\n file_error_count++;\n console.log('Error: ',file);\n },\n on_success: function(file) {\n file_load_count++;\n console.log('Loaded: ',file);\n }\n};\n
Note that there's no guarantee that any/all files will trigger one of these two callback functions, because they are cancelled after the preload
trial ends. For instance, if a file takes longer to load then the max_load_time
, then the preload
trial will end due to timing out, and the on_success
and on_error
callbacks for any in-progress files will be cancelled.
"},{"location":"overview/mturk/","title":"Integrating with Mechanical Turk","text":"A common use of jsPsych is to build an online experiment and find participants using Mechanical Turk. Once an experiment is available through a web server and data is being saved on the server, connecting the experiment with Mechanical Turk takes only a few additional steps. jsPsych has some built-in functionality to assist with this process.
"},{"location":"overview/mturk/#the-jspsychturk-module","title":"The jsPsych.turk module","text":"The jsPsych.turk module contains functions that are relevant for experiments running on Mechanical Turk.
"},{"location":"overview/mturk/#creating-an-advertisement-page","title":"Creating an advertisement page","text":"When potential participants view your experiment on Mechanical Turk, they will be able to see a single webpage before deciding whether or not to accept the HIT (start the experiment). This first page is often used as an advertisement for the experiment, similar to posting a flier in a department hallway. The important thing to remember about this page is that potential participants will be able to interact with it even if they haven't accepted the HIT. Therefore, it can be useful to change the content of the page depending on whether the HIT has been accepted or not. This is relatively easy to do:
<div id=\"experiment_link\">You must accept the HIT to begin the experiment</div>.\n\n<script>\n// jsPsych has a method turkInfo() which can determine whether or not the\n// HIT has been accepted.\nvar turkInfo = jsPsych.turkInfo();\n\n// turkInfo.previewMode is true in two cases: when the HIT has not been\n// accepted yet OR when the page is viewed outside of mechanical turk.\n// The second property, outsideTurk, is true when the page is viewed\n// outside of mechanical turk, so together, the statement will be true\n// only when in Turk and when the HIT is not accepted yet.\nif(!turkInfo.previewMode && !turkInfo.outsideTurk) {\n document.querySelector('#experiment_link').innerHMTL = '<a href=\"link_to_experiment.html\" target=\"_blank\">Click Here to Start Experiment</a>';\n}\n</script>\n
One important issue with advertisement pages is that they must be served using the https protocol, which requires having an SSL certificate on the web server hosting the page. Instructions for how to do this vary depending on what kind of server you are using, so the best advice is to simply Google for instructions on how to acquire and install an SSL certificate on your particular server.
"},{"location":"overview/mturk/#getting-the-worker-id","title":"Getting the worker ID","text":"Every account on Mechanical Turk is given a unique identification string. Recording this ID is a useful way to keep track of who is doing your experiment. In particular, while Turk has built in tools for preventing the same person from doing a HIT more than once, there may be cases where you don't want participants to complete related experiments. If you store the worker ID of every person who starts an experiment in a database, then you can exclude people by running a query on the database to check for the ID. jsPsych can get the workerID, assignmentID, and hitID with the turkInfo method.
var turkInfo = jsPsych.turk.turkInfo();\n\n// workerID\nturkInfo.workerId\n\n// hitID\nturkInfo.hitId\n\n// assignmentID\nturkInfo.assignmentId\n
Recording the workerId at the start of the experiment is also a good way to track dropouts.
"},{"location":"overview/mturk/#submitting-results-to-mechanical-turk","title":"Submitting results to Mechanical Turk","text":"If you are running a HIT on Mechanical Turk using the ExternalQuestion template, then you'll need to provide a way for participants to indicate that they have completed the HIT. (If you are using another template, then the template will provide this code for you). jsPSych makes this a relatively easy task. A common strategy for external HITs is to display an HTML page on the Mechanical Turk website that links to your HIT. Participants click the link, which opens the actual experiment content in a new browser window or tab, allowing the experiment to take up the whole browser window instead of just the iframe that displays content on Mechanical Turk.
On this page, you might include a submit button for workers to indicate that they have finished the experiment. The page would look something like this:
<p>Enter the code you were given:</p>\n<input type=\"text\" id=\"code\"></input>\n<button onclick=\"sendData();\">Submit HIT</button>\n\n<script>\nfunction sendData() {\n jsPsych.turk.submitToTurk({\n code: document.getElementById('code').value\n });\n}\n</script>\n
When workers click the button, the contents of the code
text field will be sent to Mechanical Turk, and you'll be able to view the participants and the codes that they entered in the Mechanical Turk GUI. You can then approve or reject work using the Mechanical Turk website.
"},{"location":"overview/mturk/#limitations","title":"Limitations","text":"jsPsych is not designed to communicate with the Mechanical Turk API in a comprehensive manner. If you are looking for software to help you post and manage HITs, then you may want to look at PsiTurk. jsPsych and PsiTurk complement each other nicely, and there is an example of combining the two platforms on PsiTurk's experiment exchange.
"},{"location":"overview/plugins/","title":"Plugins","text":"In jsPsych, plugins define the kinds of trials or events that should occur during the experiment. Some plugins define very general events, like displaying a set of instructions pages, displaying an image and recording a keyboard response, or playing a sound file and recording a button response. Other plugins are more specific, like those that display particular kinds of stimuli (e.g., a circular visual search array), or run a specific version of particular kind of task (e.g., the Implicit Association Test). Part of creating an experiment with jsPsych involves figuring out which plugins are needed to create the tasks you want your participants to perform.
Plugins provide a structure for a particular trial or task, but often allow for significant customization and flexibility. For example, the image-keyboard-response plugin defines a simple structure for showing an image and collecting a keyboard response. You can specify the what the stimulus is, what keys the participant is allowed to press, how long the stimulus should be on the screen, how long the participant has to respond, and so on. Many of these options have reasonable default values; even though the image plugin has many different parameters, you only need to specify the image stimulus in order to use it. Each plugin has its own documentation page, which describes what the plugin does, what options are available, and what kind of data it collects.
"},{"location":"overview/plugins/#using-a-plugin","title":"Using a plugin","text":"To use a plugin, you'll need to load the plugin's JavaScript file in your experiment's HTML page. All jsPsych experiments also need to load the \"jsPsych.js\" file.
<head>\n <script src=\"https://unpkg.com/jspsych@8.1.0\" type=\"text/javascript\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\" type=\"text/javascript\"></script>\n</head>\n
Once a plugin is loaded, you can use JavaScript to define a trial that uses that plugin. All jsPsych trials need a type
parameter, which tells jsPsych what plugin to use to run the trial. The trial's type
is similar to the plugin name, but it always starts with \"jsPsych\" and is written in camel case rather than with dashes between the words. The trial's type
parameter should NOT be a string (i.e., no quotes around the type
value). Here are some examples of plugin names and types:
Plugin name Type image-keyboard-response jsPsychImageKeyboardResponse fullscreen jsPsychFullscreen webgazer-init-camera jsPsychWebgazerInitCamera The following JavaScript code defines a trial using the image-keyboard-response
plugin to display an image file. This trial uses the default values for valid keys, stimulus duration, trial duration, and other parameters.
var image_trial = {\n type: jsPsychImageKeyboardResponse, \n stimulus: 'images/happy_face.jpg'\n}\n
You can override any default parameter values by adding them into your trial object. Here's an example of overriding the default values for trial_duration
and post_trial_gap
:
var image_trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'images/happy_face.jpg',\n trial_duration: 3000,\n post_trial_gap: 2000\n}\n
"},{"location":"overview/plugins/#parameters-available-in-all-plugins","title":"Parameters available in all plugins","text":"Each plugin specifies its own set of parameters. Check the documentation for a plugin to see what parameters are available and what they do.
There is also a set of parameters that can be specified for any plugin:
Parameter Type Default Value Description data object undefined An object containing additional data to store for the trial. See the Data page for more details. post_trial_gap numeric null Sets the time, in milliseconds, between the current trial and the next trial. If null, there will be no gap. on_start function function(){ return; }
A callback function to execute when the trial begins, before any loading has occurred. See the Event-Related Callbacks page for more details. on_finish function function(){ return; }
A callback function to execute when the trial finishes, and before the next trial begins. See the Event-Related Callbacks page for more details. on_load function function(){ return; }
A callback function to execute when the trial has loaded, which typically happens after the initial display of the plugin has loaded. See the Event-Related Callbacks page for more details. css_classes string null A list of CSS classes to add to the jsPsych display element for the duration of this trial. This allows you to create custom formatting rules (CSS classes) that are only applied to specific trials. For more information and examples, see the Controlling Visual Appearance page and the \"css-classes-parameter.html\" file in the jsPsych examples folder. save_trial_parameters object {}
An object containing any trial parameters that should or should not be saved to the trial data. Each key is the name of a trial parameter, and its value should be true
or false
, depending on whether or not its value should be saved to the data. If the parameter is a function that returns the parameter value, then the value that is returned will be saved to the data. If the parameter is always expected to be a function (e.g., an event-related callback function), then the function itself will be saved as a string. For more examples, see the \"save-trial-parameters.html\" file in the jsPsych examples folder. save_timeline_variables boolean or array false
If set to true
, then all timeline variables will have their current value recorded to the data for this trial. If set to an array, then any variables listed in the array will be saved. record_data boolean true
If set to false
, then the data for this trial will not be recorded."},{"location":"overview/plugins/#the-data-parameter","title":"The data parameter","text":"The data
parameter allows you to add additional properties to the trial data. This can be useful for storing properties of the trial that are not directly apparent from the values that the plugin records. The data
parameter value must be an object that contains key-value pairs.
A simple example is the Flanker Task. In this experiment, participants respond to the direction of a central arrow by pressing a key to the left for a left-pointing arrow (<) and a key to the right for a right-pointing arrow (>). The arrow appears in the center of flankers, or arrows that the participant should ignore. Those flankers can be congruent (>>>>>) or incongruent (<<><<).
A trial for the Flanker Task written with jsPsych might look like this:
var trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<<<<<',\n choices: ['f','j'],\n data: {\n stimulus_type: 'congruent',\n target_direction: 'left'\n }\n}\n
Note the use of the data parameter to add a property stimulus_type
with the value congruent
and a property target_direction
with the value left
. Having these properties recorded directly in the data simplifies data analysis, making it easy to aggregate data by stimulus_type
and/or target_direction
.
"},{"location":"overview/plugins/#the-post_trial_gap-iti-parameter","title":"The post_trial_gap (ITI) parameter","text":"The default inter-trial interval (ITI) in jsPsych is 0 ms. This can be adjusted at the experiment-wide level by changing the default_iti
parameter in initJsPsych()
.
The ITI can also be controlled at the trial level through the post_trial_gap
parameter. Setting this parameter to a positive integer x will cause a blank screen to display after the trial for x milliseconds. Setting this parameter for a trial will override the default_iti
value set in initJsPsych
.
var trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'There will be a 1.5 second blank screen after this trial.',\n post_trial_gap: 1500\n}\n
"},{"location":"overview/plugins/#the-on_start-parameter","title":"The on_start parameter","text":"Immediately before a trial runs, there is an opportunity to run an arbitrary function through the on_start
event handler. This event handler is passed a single argument containing an editable copy of the trial parameters. This function can therefore be used to alter the trial based on the state of the experiment, among other uses.
// when this trial runs, the on_start function will change the trial's stimulus and data parameters,\n// so the trial will display an incongruent Flanker stimulus with a right-facing central arrow\nvar trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<<<<<',\n choices: ['f','j'],\n data: {\n stimulus_type: 'congruent',\n target_direction: 'left'\n },\n on_start: function(trial){\n trial.stimulus = '<<><<';\n trial.data.stimulus_type = 'incongruent';\n trial.data.target_direction = 'right';\n }\n}\n
"},{"location":"overview/plugins/#the-on_finish-parameter","title":"The on_finish parameter","text":"After a trial is completed, there is an opportunity to run an arbitrary function through the on_finish
event handler. This function is passed a single argument containing an editable copy of the data recorded for that trial. This function can therefore be used to update the state of the experiment based on the data collected, or modify the data collected.
The on_finish
function can be useful to calculate new data properties that were unknowable at the start of the trial. For example, with the Flanker Task example above, the on_finish
function could check the response and use to this information to add a new property to the data called correct
, which is either true
or false
.
// in addition to all of the standard data collected for this trial, \n// this on_finish function adds a property called 'correct' \n// which is either 'true' or 'false'\n// depending on the response that was made\nvar trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<<<<<',\n choices: ['f','j'],\n data: {\n stimulus_type: 'congruent',\n target_direction: 'left',\n correct_response: 'f'\n },\n on_finish: function(data){\n if(jsPsych.pluginAPI.compareKeys(data.response, data.correct_response)){\n data.correct = true;\n } else {\n data.correct = false;\n }\n }\n}\n
"},{"location":"overview/plugins/#the-on_load-parameter","title":"The on_load parameter","text":"The on_load
callback function will trigger once the trial has completed loading. For most plugins, this will occur once the display has been initially updated but before any user interactions or timed events (e.g., animations) have occurred. This can be useful for changing various aspects of the page elements and their properties that would otherwise require modifying the plugin file.
var trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'imgA.png',\n on_load: function() {\n // this will change the src attribute of the image after 500ms\n setTimeout(function(){\n document.querySelector('img').src = 'imgB.png'\n }, 500);\n }\n};\n
"},{"location":"overview/plugins/#the-css_classes-parameter","title":"The css_classes parameter","text":"The css_classes
parameter allows you to add an array of CSS class names to the jsPsych display element on that specific trial. This allows you to create custom style and formatting rules that are only applied to specific trials. If you want CSS rules that only apply to specific elements during a trial, you can use additional CSS selectors.
<style>\n .flanker-stimulus {\n font-size: 500%;\n }\n .flanker-stimulus #prompt {\n font-size: 18px;\n }\n .fixation {\n font-size: 80px;\n }\n</style>\n<script>\n var fixation_trial = {\n type: jsPsychHtmlKeyboardResponse,\n choices: \"NO_KEYS\",\n stimulus: '+',\n css_classes: ['fixation']\n };\n var flanker_trial = {\n type: jsPsychHtmlKeyboardResponse,\n choices: [\"ArrowLeft\", \"ArrowRight\"],\n stimulus: '>>>>>',\n prompt: '<span id=\"prompt\">Press the left or right arrow key.</span>',\n css_classes: ['flanker-stimulus']\n };\n</script>\n
"},{"location":"overview/plugins/#the-save_trial_parameters-parameter","title":"The save_trial_parameters parameter","text":"The save_trial_parameters
parameter allows you to tell jsPsych what parameters you want to be saved to the data. This can be used to override the parameter values that the plugin saves by default. You can add more parameter values to the data that are not normally saved, or remove parameter values that normally are saved. This can be especially useful when the parameter value is dynamic (i.e. a function) and you want to record the value that was used during the trial.
var trial = {\n type: jsPsychHtmlButtonResponse,\n stimulus: '<p style=\"color: orange; font-size: 48px; font-weight: bold;\">BLUE</p>',\n choices: function() {\n return jsPsych.randomization.shuffle(['Yes','No']);\n },\n post_trial_gap: function() {\n return jsPsych.randomization.sampleWithoutReplacement([200,300,400,500],1)[0];\n },\n save_trial_parameters: {\n // save the randomly-selected button order and post trial gap duration to the trial data\n choices: true,\n post_trial_gap: true,\n // don't save the stimulus\n stimulus: false\n }\n}\n
Note
You cannot remove the trial_index
value from the trial data.
"},{"location":"overview/plugins/#data-collected-by-all-plugins","title":"Data collected by all plugins","text":"Each plugin defines what data is collected on the trial. The documentation for each plugin specifies what information will be stored in the trial data.
In addition to the data collected by a plugin, there is a default set of data that is collected on every trial.
Name Type Value trial_type string The name of the plugin used to run the trial. trial_index numeric The index of the current trial across the whole experiment. time_elapsed numeric The number of milliseconds between the start of the experiment and when the trial ended."},{"location":"overview/plugins/#creating-a-new-plugin","title":"Creating a new plugin","text":"See our developer's guide for plugins for information about how to create a new plugin.
"},{"location":"overview/progress-bar/","title":"Automatic Progress Bar","text":"jsPsych can show a progress bar at the top of the experiment page indicating the participant's overall completion progress. The progress bar is rendered outside the jsPsych display element, and it requires the jspsych.css
file to be loaded on the page. As of version 6.0, the progress bar looks like this:
To show the progress bar, set the show_progress_bar
option in initJsPsych
to true
:
const jsPsych = initJsPsych({\n show_progress_bar: true\n});\n
The progress bar automatically updates after every trial.
"},{"location":"overview/progress-bar/#manual-control","title":"Manual Control","text":"The progress bar can also be manually controlled by setting jsPsych.progressBar.progress
. The value of jsPsych.progressBar.progress
should be a number between 0 and 1. For example, to set the progress bar to 85% full, you would do this:
const trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Almost done...',\n on_finish: function(){\n jsPsych.progressBar.progress = 0.85; // set progress bar to 85% full.\n }\n}\n
You can also get the current value of the progress bar as jsPsych.progressBar.progress
const proportion_complete = jsPsych.progressBar.progress;\n
If you are going to use manual progress bar control, you may want to disable the automatic progress bar updates by setting the auto_update_progress_bar
property in initJsPsych()
to false
.
const jsPsych = initJsPsych({\n show_progress_bar: true,\n auto_update_progress_bar: false\n});\n
Here's a complete example showing how to use these functions and initJsPsych()
settings to manually update the progress bar:
const jsPsych = initJsPsych({\n show_progress_bar: true,\n auto_update_progress_bar: false\n});\n\nconst n_trials = 5;\n\nconst start = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Press any key to start!',\n on_start: function() {\n // set progress bar to 0 at the start of experiment\n jsPsych.progressBar.progress = 0\n }\n};\n\nconst trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'This is a trial!',\n on_finish: function() {\n // at the end of each trial, update the progress bar\n // based on the current value and the proportion to update for each trial\n var curr_progress_bar_value = jsPsych.progressBar.progress;\n jsPsych.progressBar.progress = curr_progress_bar_value + (1/n_trials)\n }\n};\n\nconst trials = {\n timeline: [trial],\n repetitions: n_trials\n};\n\nconst done = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Done!'\n};\n\njsPsych.run([start, trials, done]);\n
"},{"location":"overview/progress-bar/#custom-text","title":"Custom Text","text":"By default, jsPsych adds the text \"Completion Progress\" to the left of the progress bar. You can specify custom text using the message_progress_bar
parameter in initJsPsych
.
// support for different spoken languages\nconst jsPsych = initJsPsych({\n show_progress_bar: true,\n message_progress_bar: 'Porcentaje completo'\n});\n
// no message\nconst jsPsych = initJsPsych({\n show_progress_bar: true,\n message_progress_bar: ''\n});\n
"},{"location":"overview/prolific/","title":"Integrating with Prolific","text":"Prolific is a participant recruitment service aimed at research. Integrating a jsPsych experiment with Prolific requires capturing the participant's ID and sending the participant to a completion URL at the end of the experiment.
"},{"location":"overview/prolific/#capturing-the-participant-id-study-id-and-session-id","title":"Capturing the Participant ID, Study ID, and Session ID","text":"When creating a study on Prolific you must provide the URL to your study. You can host your jsPsych experiment however you'd like - some options are discussed in the Running Experiments documentation page. Once you've got a URL to your experiment, you can enter that in the study link section of Prolific. Then, click the option to record Prolific IDs via URL parameters.
This will append information about the participant's prolific ID (PROLIFIC_PID
), the study's ID (STUDY_ID
), and the session ID (SESSION_ID
) to the URL that participants use to access your experiment.
We can capture these variables with jsPsych, and add them to jsPsych's data. This can be done anywhere in your code. This code does not need to run as part of your experiment timeline.
<script>\n var jsPsych = initJsPsych();\n\n // capture info from Prolific\n var subject_id = jsPsych.data.getURLVariable('PROLIFIC_PID');\n var study_id = jsPsych.data.getURLVariable('STUDY_ID');\n var session_id = jsPsych.data.getURLVariable('SESSION_ID');\n\n jsPsych.data.addProperties({\n subject_id: subject_id,\n study_id: study_id,\n session_id: session_id\n });\n\n // create the rest of the experiment\n var timeline = [...]\n\n jsPsych.run(timeline)\n</script>\n
"},{"location":"overview/prolific/#completing-the-experiment","title":"Completing the Experiment","text":"When the experiment is complete, Prolific requires that you send the participant to a specific URL that marks the session as complete on Prolific's server. The link is provided to you by Prolific in the study completion section of the setup.
You can accomplish this in a couple different ways.
Warning
It's important that you've saved all the data from your experiment before the participant returns to Prolific. Make sure that any server communication has completed prior to redirecting the participant. One way to do this is by using the async features of the call-function
plugin (example).
"},{"location":"overview/prolific/#participant-clicks-a-link","title":"Participant clicks a link","text":"One option is to create a trial that contains a link that the participant clicks to end the experiment and return to Prolific. For example, the html-keyboard-response
plugin can be used to display text that includes a link. This could go on a debriefing page.
Here's an example trial that could be used. Note that choices
is set to \"NO_KEYS\"
, which will prevent the participant from continuing past this point in the experiment.
var final_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `<p>You've finished the last task. Thanks for participating!</p>\n <p><a href=\"https://app.prolific.co/submissions/complete?cc=XXXXXXX\">Click here to return to Prolific and complete the study</a>.</p>`,\n choices: \"NO_KEYS\"\n}\n
"},{"location":"overview/prolific/#automatically-redirect","title":"Automatically redirect","text":"A second option is to automatically redirect the participant to the completion URL when the experiment is finished. You could do this in a number of places in the jsPsych timeline.
Here's an example using the on_finish
event for the entire experiment.
var jsPsych = initJsPsych({\n on_finish: function(){\n window.location = \"https://app.prolific.co/submissions/complete?cc=XXXXXXX\"\n }\n});\n
"},{"location":"overview/record-browser-interactions/","title":"Record browser interactions","text":"Participants in an online experiment have the freedom to multitask while performing an experiment. jsPsych automatically records information about when the user clicks on a window that is not the experiment, and about when the user exits full screen mode if the experiment is running in full screen mode. This data is stored separately from the main experiment data, and can be accessed with jsPsych.data.getInteractionData().
Each time the user leaves the experiment window, returns to the experiment window, exits full screen mode, or enters full screen mode, the event is recorded in the interaction data. Each event has the following structure.
Event recording stops when the experiment ends.
{\n event: 'focus', // 'focus' or 'blur' or 'fullscreenenter' or 'fullscreenexit'\n trial: 12, // the index of the active trial when the event happened\n time: 1240543 // time in ms since the start of the experiment\n}\n
You can specify a custom function, in the initJsPsych() method, that is called whenever one of these events occurs
initJsPsych({\n on_interaction_data_update: function(data) {\n console.log(JSON.stringify(data))\n }\n});\n
"},{"location":"overview/running-experiments/","title":"Running Experiments","text":"You can run your jsPsych experiment:
Offline, by opening the HTML file directly in the browser using the file://
protocol.
Online, by hosting the files on a web server using the http://
or https://
protocol.
The way that you run your experiment will have consequences for certain aspects about how the experiment works, and what your experiment will be able to do. This page explains what you need to know about both of these options.
Info
If you are looking for a tool to automate deployment-related tasks, check out the jsPsych Builder CLI utility. It automatically bundles scripts and style sheets, configures media preloading, and yields a zip file that contains all files for deployment (online or offline). jsPsych Builder can also directly build JATOS experiment files (.jzip) that you can upload to a JATOS server (see this section below for more info about JATOS and other server options).
"},{"location":"overview/running-experiments/#offline","title":"Offline","text":"You can run your jsPsych experiment offline by opening the HTML file directly in a web browser, for instance by double-clicking on it. This uses the file://
protocol. It's usually the fastest and easiest way to run through an experiment, and is very useful while writing and testing the code.
At some point you will need to move your experiment files onto a server and send the data to a database, since this is how you will ultimately collect the data (unless you're planning to collect data on your local computer). There are some important differences between the way the experiment runs offline compared to online via a web server.
Note that, unless noted, here we're using the word \"server\" to mean either a local server (which runs on your computer and only makes the experiment files available from within that computer, and is often used during development), or a remote server (which does not run on your computer and does share your experiment files over the internet).
"},{"location":"overview/running-experiments/#cross-origin-requests-cors-and-safe-mode","title":"Cross-origin requests (CORS) and safe mode","text":"Web browsers have a security policy called cross-origin resource sharing (CORS) that determines whether the webpage can request files that come from a different origin (i.e. protocol, host/domain, and port). This isn't a problem when your study runs online, because in that case your experiment files all have the same origin. However, when you run your experiment offline, the CORS policy blocks some jsPsych features that require loading local files. If your experiment uses these features, then CORS errors will prevent the experiment from running.
To prevent these errors, jsPsych uses a 'safe mode' when it detects that the HTML page is running via the file://
protocol, and if so, automatically disables the features that don't work in that context. Specifically, when a jsPsych experiment runs offline:
- Web Audio is disabled (even if
use_webaudio
is set to true
in initJsPsych
). The WebAudio API option is used by default because it allows more precise measurement of response times relative to the onset of the audio. But because WebAudio doesn't work offline, audio will be played using HTML5 audio instead. This is equivalent to setting use_webaudio
to false
in initJsPsych
. - Video preloading is disabled (both automatic and manual preloading via the
preload
plugin). Videos will still play when you run your experiment offline, but they will load during the experiment, which might cause noticeable delays before video playback starts.
This safe mode feature is controlled by the override_safe_mode
parameter in initJsPsych
, which defaults to false
. If you leave this setting as the default, then you won't need to worry about CORS errors while running your experiment offline, or remembering to change your initJsPsych
settings when you move the experiment online.
It's possible to override jsPsych's safe mode by setting override_safe_mode
to true
in initJsPsych
. One reason you might do this is if you've disabled web security features in your browser (see here and here for instructions in Chrome), which is safe to do if you know what you're doing. If your experiment does not use Web Audio or preloaded videos, then jsPsych's safe mode feature will not have any effect.
The override_safe_mode
parameter also has no effect when your experiment is running online a web server, because the page will be loaded via the http://
or https://
protocol.
"},{"location":"overview/running-experiments/#media-loading","title":"Media loading","text":"While running your experiment offline, any media files are likely to load very quickly because they are stored on your own computer's disk. Therefore you may not notice problems with file loading delays while running your experiment locally (either offline or on a local server) because the files will load fast enough that they never cause disruption. However, when your experiment is hosted on a remote server, the files will need to be transferred over the internet, which means they will take longer to load - in some cases much longer. Loading delays are most noticeable with media files: images, audio, and video. As explained on the Media Preloading page, loading delays during your experiment can cause problems for stimulus display and response times.
It is important to test your experiment to ensure that any media files are preloading successfully and not being requested again during the experiment. You can use the Network tab in your browser's developer tools to see when files are loaded and to simulate a slow internet connection (see here for Chrome Network tab documentation). If you are preloading many and/or large files, such as videos, you may want to increase the max_load_time
parameter in the preload plugin
so that participants with slow/unreliable internet connections will be able to take part in your experiment.
"},{"location":"overview/running-experiments/#permanent-data-storage","title":"Permanent data storage","text":"As explained in the Data Storage, Aggregation, and Manipulation page, jsPsych stores information in the participant's browser. While running an experiment offline, you won't be able to send the data to a database. However you can still see the data that jsPsych collects by saving it as a local file (using jsPsych.data.get().localSave
), displaying it in the webpage at the end of the experiment (using jsPsych.data.displayData
), or printing it to the browser's console (using console.log
).
Permanent data storage is also necessary when the code that runs the experiment depends on information that can't be known in advance, and that changes throughout data collection. Some common examples of this in cognitive behavioral research are version counterbalancing, where the experiment code needs to access and update the history of version assignment in order to determine which version should be assigned, and multi-session/training studies, where the experiment might need to access and update information about each participant like their current session number, task difficulty level, etc.
Doing these things in an automated way requires the use of a server. While developing and testing your experiment offline, you might choose to simulate some of these things and then implement them properly once you move your experiment online. For instance, you could randomize instead of counterbalancing version assignment:
var versions = [1,2];\nvar random_version = jsPsych.randomization.sampleWithoutReplacement(versions,1)[0];\n
And use URL query parameters to pass in variables like session number and difficulty level:
// add the variables onto the end of the URL that appears in the browser when you open the file \n// e.g., file:///C:/my_experiment.html?id=1&sess=2&diff=3\nvar participant_id = jsPsych.data.getURLVariable('id');\nvar session = jsPsych.data.getURLVariable('sess');\nvar difficulty = jsPsych.data.getURLVariable('diff');\n
"},{"location":"overview/running-experiments/#online","title":"Online","text":""},{"location":"overview/running-experiments/#hosting-the-experiment-and-saving-the-data","title":"Hosting the Experiment and Saving the Data","text":"jsPsych is a front-end JavaScript library that runs entirely on the participant's computer. To run a jsPsych experiment over the internet, the files need to be hosted on a public web server so that participants can access the experiment using a web browser. When the participant completes the experiment in the browser, all of the data that jsPsych collects is stored on the participant's computer in the browser's memory. To get access to this data, it needs to be sent from the participant's browser back to the web server and stored in a database or a file.
To be maximally flexible, jsPsych doesn't provide a single built-in solution for the web server component of your experiment. This makes jsPsych compatible with a wide range of hosting services and tools, allowing researchers to choose the web server option that best suit their needs.
Some options for running your jsPsych experiment online include:
- Cognition.run - A free service designed specifically for hosting jsPsych experiments, with an easy-to-use interface.
- JATOS - A free program that runs on your own server and provides a GUI for setting up experiments and accessing the data. Offers lots of features for creating more complex experiments and managing multiple researchers.
- Pavlovia - A paid hosting service for web-based experiments, run by the PsychoPy team. Experiment files are managed on a GitLab repository. Participants will access the experiment through a link to Pavlovia.
- PsiTurk - Python-based program to help you host your experiment on your own computer and collect data from MTurk (see Recruiting Participants below). Relatively easy for a DIY option.
- Pushkin - A set of tools to help you set up your own virtual laboratory for online experiments. This option differs from the others in that it helps you set up a complete website that may contain many different experiments, information about the laboratory, participant logins, and other features that are targeted at hosting large-scale data collection efforts.
- Full DIY - You can setup your own web server and database and handle the communication yourself. Traditional web server 'stacks' include LAMP/LEMP (Linux operating system, Apache or Nginx server application, MySQL database, and PHP programming language). Other common web server frameworks include Flask (Python) and Node.js (JavaScript).
"},{"location":"overview/running-experiments/#recruiting-participants","title":"Recruiting Participants","text":"Once your experiment is running online, you could recruit participants in the same way that you would for lab-based studies. For instance, if your institution uses SONA, you can advertise your web-based study link on SONA. SONA allows you to automactically embed a unique ID in online study URLs, which you can then save in your data using jsPsych's URL query parameters function. SONA will also generate a completion URL that you can redirect participants to at the end of the study, and this will mark them as having completed the study in SONA.
To take full advantage of hosting an experiment online, many researchers advertise their experiments more widely. Social media and other media outlets provide one option for reaching a large number of potential participants. There are also some commercial platforms that you can use to advertise your study and pay anonymous online participants. These recruitment platforms charge a fee for use. The advantages of these platforms are that they handle the participant payments and allow you to specify pre-screening criteria. The most commonly used recruitment platforms in online behavioral research are:
- Prolific: An online labor market designed specifically for web-based research.
- Amazon Mechanical Turk (MTurk): An online labor market designed for advertising paid 'human intelligence tasks'. This service was designed for use by commercial businesses but has been used by behavioral researchers for many years.
Like SONA, Prolific and MTurk use URL query parameters to get participant information, and redirection to specific URLs to mark participants as having finished the study. jsPsych includes convenience functions for interacting with MTurk participants. Information about integrating with Prolific can be found in the researcher support section of their website.
"},{"location":"overview/simulation/","title":"Simulation Modes","text":"Added in 7.1
Simulation mode allows you run your experiment automatically and generate artificial data.
Info
For a detailed description of the motivation behind simulation mode and a discussion of different use cases of simulation mode, see de Leeuw, J.R., Gilbert, R.A., Petrov, N.B., & Luchterhandt, B. (2022). Simulation behavior to help researchers build experiments. Behavior Research Methods, https://doi.org/10.3758/s13428-022-01899-0.
A pre-print version is available on PsyArXiv.
"},{"location":"overview/simulation/#getting-started","title":"Getting Started","text":"To use simulation mode, replace jsPsych.run()
with jsPsych.simulate()
.
jsPsych.simulate(timeline);\n
This will run jsPsych in the default data-only
simulation mode. To use the visual
simulation mode you can specify the second parameter.
jsPsych.simulate(timeline, \"data-only\");\njsPsych.simulate(timeline, \"visual\");\n
"},{"location":"overview/simulation/#what-happens-in-simulation-mode","title":"What happens in simulation mode","text":"In simulation mode, plugins call their simulate()
method instead of calling their trial()
method. If a plugin doesn't implement a simulate()
method, then the trial will run as usual (using the trial()
method) and any interaction that is needed to advance to the next trial will be required. If a plugin doesn't support visual
mode, then it will run in data-only
mode.
"},{"location":"overview/simulation/#data-only-mode","title":"data-only
mode","text":"In data-only
mode plugins typically generate resonable artificial data given the parameters specified for the trial. For example, if the trial_duration
parameter is set to 2,000 ms, then any response times generated will be capped at this value. Generally the default data generated by the plugin randomly selects any available options (e.g., buttons to click) with equal probability. Response times are usually generated by sampling from an exponentially-modified Gaussian distribution truncated to positive values using jsPsych.randomization.sampleExGaussian()
.
In data-only
mode, the plugin's trial()
method usually does not run. The data are simply calculated based on trial parameters and the finishTrial()
method is called immediately with the simulated data.
"},{"location":"overview/simulation/#visual-mode","title":"visual
mode","text":"In visual
mode a plugin will typically generate simulated data for the trial and then use that data to mimic the kinds of actions that a participant would do. The plugin's trial()
method is called by the simulation, and you'll see the experiment progress in real time. Mouse, keyboard, and touch events are simulated to control the experiment.
In visual
mode each plugin will generate simulated data in the same manner as data-only
mode, but this data will instead be used to generate actions in the experiment and the plugin's trial()
method will ultimately be responsible for generating the data. This can create some subtle differences in data between the two modes. For example, if the simulated data generates a response time of 500 ms, the data.rt
value will be exactly 500
in data-only
mode, but may be 501
or another slightly larger value in visual
mode. This is because the simulated response is triggered at 500
ms and small delays due to JavaScript's event loop might add a few ms to the measure.
"},{"location":"overview/simulation/#controlling-simulation-mode-with-simulation_options","title":"Controlling simulation mode with simulation_options
","text":"The parameters for simulation mode can be set using the simulation_options
parameter in both jsPsych.simulate()
and at the level of individual trials.
"},{"location":"overview/simulation/#trial-level-options","title":"Trial-level options","text":"You can specify simulation options for an individual trial by setting the simulation_options
parameter.
const trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<p>Hello!</p>',\n simulation_options: {\n data: {\n rt: 500\n }\n }\n}\n
Currently the three options that are available are data
, mode
, and simulate
.
"},{"location":"overview/simulation/#data","title":"data
","text":"Setting the data
option will replace the default data generated by the plugin with whatever data you specify. You can specify some or all of the data
parameters. Any parameters you do not specify will be generated by the plugin.
In most cases plugins will try to ensure that the data generated is consistent with the trial parameters. For example, if a trial has a trial_duration
parameter of 2000
but the simulation_options
specify a rt
of 2500
, this creates an impossible situation because the trial would have ended before the response at 2,500ms. In most cases, the plugin will act as if a response was attempted at 2500
, which will mean that no response is generated for the trial. As you might imagine, there are a lot of parameter combinations that can generate peculiar cases where data may be inconsistent with trial parameters. We recommend double checking the simulation output, and please alert us if you discover a situation where the simulation produces inconsistent data.
"},{"location":"overview/simulation/#mode","title":"mode
","text":"You can override the simulation mode specified in jsPsych.simulate()
for any trial. Setting mode: 'data-only'
will run the trial in data-only mode and setting mode: 'visual'
will run the trial in visual mode.
"},{"location":"overview/simulation/#simulate","title":"simulate
","text":"If you want to turn off simulation mode for a trial, set simulate: false
.
"},{"location":"overview/simulation/#functions-and-timeline-variables","title":"Functions and timeline variables","text":"The simulation_options
parameter is compatible with both dynamic parameters and timeline variables. Dynamic parameters can be especially useful if you want to randomize the data for each run of the simulation. For example, you can specify the rt
as a sample from an ExGaussian distribution.
const trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<p>Hello!</p>',\n simulation_options: {\n data: {\n rt: ()=>{\n return jsPsych.randomization.sampleExGaussian(500, 50, 1/100, true)\n }\n }\n }\n}\n
"},{"location":"overview/simulation/#experiment-level-options","title":"Experiment-level options","text":"You can also control the parameters for simulation by passing in an object to the simulation_options
argument of jsPsych.simulate()
.
const simulation_options = {\n default: {\n data: {\n rt: 200\n }\n }\n}\n\njsPsych.simulate(timeline, \"visual\", simulation_options)\n
The above example will set the rt
for any trial that doesn't have its own simulation_options
specified to 200
. This could be useful, for example, to create a very fast preview of the experiment to verify that everything is displaying correctly without having to wait through longer trials.
You can also specify sets of parameters by name using the experiment-level simulation options.
const simulation_options = {\n default: {\n data: {\n rt: 200\n }\n },\n long_response: {\n data: {\n rt: () => {\n return jsPsych.randomization.sampleExGaussian(5000, 500, 1/500, true)\n }\n }\n }\n}\n\nconst trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<p>This is gonna take a bit.</p>',\n simulation_options: 'long_response'\n}\ntimeline.push(trial);\n\njsPsych.simulate(timeline, \"visual\", simulation_options)\n
In the example above, we specified the simulation_options
for trial
using a string ('long_response'
). This will look up the corresponding set of options in the experiment-level simulation_options
.
We had a few use cases in mind with this approach:
- You could group together trials with similar behavior without needing to specify unique options for each trial.
- You could easily swap out different simulation options to test different kinds of behavior. For example, if you want to test that a timeline with a
conditional_function
is working as expected, you could have one set of simulation options where the data will cause the conditional_function
to evaluate to true
and another to false
. By using string-based identifiers, you don't need to change the timeline code at all. You can just change the object being passed to jsPsych.simulate()
. - In an extreme case of the previous example, every trial on the timeline could have its own unique identifier and you could have multiple sets of simulation options to have very precise control over the data output.
"},{"location":"overview/simulation/#current-limitations","title":"Current Limitations","text":"Simulation mode is not yet as comprehensively tested as the rest of jsPsych. While we are confident that the simulation is accurate enough for many use cases, it's very likely that there are circumstances where the simulated behavior will be inconsistent with what is actually possible in the experiment. If you come across any such circumstances, please let us know!
Currently extensions are not supported in simulation mode. Some plugins are also not supported. This will be noted on their documentation page.
"},{"location":"overview/style/","title":"Controlling Visual Appearance","text":"Your experiment's style and formatting comes from the CSS (cascading style sheet) rules that are stored in the jspsych.css file, and the browser's defaults. There are a few ways to change the style and formatting in your experiment. The method that you choose is partly a matter of personal preference. It might also depend on whether you want the style/formatting change(s) to apply to specific trials, to the whole experiment (HTML page), or across different experiments. This section discusses the different ways of incorporating CSS into your jsPsych experiment. You can also see this page about adding CSS to web pages to learn more.
"},{"location":"overview/style/#inline-css","title":"Inline CSS","text":"Whenever you're using a parameter that accepts an HTML-formatted string, you have the option to include inline CSS. Inline CSS is a way of adding style and formatting directly into a specific HTML element using its \"style\" attribute. This is a good option for when you want to make few and/or simple style changes to an HTML trial parameter.
To change an element's style using inline CSS, you can set the element's \"style\" attribute to a string that contains the CSS parameters that you want to change, along with the values that you want to use. The syntax is \" <parameter-name> : <parameter-value> ;\".
In the example below, the stimulus font size is set to 30px and the text color is set to red. These changes will only be applied to this stimulus text in this specific trial.
const trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<p style=\"font-size:30px;color:red;\">hello world!</p>'\n}\n
You can also use a dynamic parameter to combine inline CSS and trial-specific variables. This allows you to easily apply the same inline CSS to multiple trials. Here's an example using a dynamic stimulus parameter and timeline variables:
const trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: function() {\n const stim = `<p style=\"font-size:30px;font-weight:bold;\">${jsPsych.evaluatetimelineVariable('text')}</p>`;\n return stim;\n }\n}\nconst trial_procedure = {\n timeline: [trial],\n timeline_variables: [\n {text: 'Welcome'},\n {text: 'to'},\n {text: 'the'},\n {text: 'experiment!'}\n ]\n}\n
"},{"location":"overview/style/#adding-css-rules","title":"Adding CSS rules","text":"You may want to add a lot of different CSS changes to your experiment, re-use the same change(s) across lots of different trials, and/or separate the style/formatting from the HTML string. In these cases, you might find it useful to create CSS rules rather than using inline CSS.
Creating CSS rules is a lot like using inline CSS, except that you also need to use a CSS selector. This is because your CSS rules aren't attached to any specific HTML element (unlike inline CSS), so you need to tell the browser which element(s) the style rules should apply to. The syntax is \"css-selector { <parameter-name> : <parameter-value> ; }\".
In the example below, the CSS selector \"p\" tells the browser to apply the font size change to any text that is inside of a <p> element.
p {\n font-size: 30px;\n}\n
You can make more specific changes using CSS rules. The specificity will depend on the CSS selectors that are used. In addition to using the tag name (e.g. \"p\"), other common CSS selectors include the element's ID or class. If you are selecting an element using it's ID, then the CSS selector needs to have a # in front of the ID, e.g. \"#stimulus\". If you are selecting elements based on their class, then you need to include a . in front of the class, e.g. \".large-text\".
In the example below, the \"#stimulus\" CSS selector means that the width change will only affect elements with the \"stimulus\" ID, and the \".large-text\" CSS selector means that the font size change will only affect elements that have the \"large-text\" class.
#stimulus \n width: 300px;\n}\n.large-text {\n font-size: 200%;\n}\n
It is possible to create even more specific CSS selectors, for instance by combining tags, IDs, and/or classes. For example, let's say that you are showing feedback text to participants, and that this text is inside of a <p> tag. You could add the ID \"correct\" to the <p> element for correct response feedback, and the ID \"incorrect\" to the <p> element for incorrect response feedback. Then you can define separate styles for correct and incorrect feedback text like this:
p#incorrect {\n color: red;\n}\np#correct {\n color: green;\n}\n
See this page about CSS selectors for a complete reference of CSS selector patterns and their meanings.
"},{"location":"overview/style/#with-style-tags","title":"With style tags","text":"You can add CSS rules to your HTML page by putting them inside of <style> tags. These rules will be applied to your whole experiment. This method can be useful for making general changes to the way that your experiment looks.
In the example below, the default font size is set to 25px throughout the experiment. This will overrule the default font size of 18px that is set in the jspsych.css file.
<head>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <link rel=\"stylesheet\" href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\">\n <style> \n .jspsych-display-element {\n font-size: 25px;\n }\n </style>\n</head>\n
"},{"location":"overview/style/#with-a-stylesheet","title":"With a stylesheet","text":"CSS rules can also be applied to your experiment with a link to an external CSS file. This is the same method that is usually used to apply the style from jspsych.css to an experiment. These rules will be applied to your whole experiment. You may find it useful to use a custom stylesheet when you want to re-use the same CSS rules across multiple experiments (HTML files).
This example shows how to add a custom CSS file in addition to the styles provided in jspsych.css. In this example, the custom CSS file is called \"my_experiment_style.css\" and it is located in the same directory as your HTML file.
<head>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <link rel=\"stylesheet\" href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\">\n <link rel=\"stylesheet\" href=\"my_experiment_style.css\">\n</head>\n
Below are the some example contents of an external CSS file, like the \"my_experiment_style.css\" from the example above. This CSS will (1) change the page background color to black, (2) change the default font to 25px and white, and (3) limit the width of the page content so that it can only take up to 80% of its normal width.
body {\n background-color: black;\n}\n.jspsych-display-element {\n font-size: 25px;\n color: white;\n}\n.jspsych-content {\n max-width: 80%; \n}\n
Note
<style> tags are not used inside of an external CSS file.
"},{"location":"overview/style/#using-the-css_classes-trial-parameter","title":"Using the css_classes trial parameter","text":"CSS rules can also be applied in a trial-specific way using the css_classes
parameter. This parameter will apply one or more class to the <div> element that holds all of the jsPsych page content during that specific trial. This way you can treat CSS styles just like any other trial parameter.
You can use a static css_classes
parameter value if you always want to apply the same CSS rules to the trial. In the 'fixation' example below, separating the style rules from the stimulus
string makes the code a little bit 'cleaner', and this makes it easier to re-use the same style rules in other parts of the experiment.
<head>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <link rel=\"stylesheet\" href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\">\n <style> \n .fixation {font-size: 90px; font-weight: bold; color: gray;}\n </style>\n</head>\n<script>\nconst fixation = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '+',\n choices: \"NO_KEYS\",\n trial_duration: 500,\n css_classes: ['fixation']\n}\n// ...\n</script>\n
You may want the css_classes
parameter to vary across trials. If so, you can turn it into a dynamic parameter or use timeline variables (see examples below).
One thing to note about the css_classes
parameter is that it only adds the class(es) to the jspsych-content <div> element, which is the \"parent\" element that contains all of the experiment content. Often you'll want your CSS rules to be applied to other elements inside of this jspsych-content div. Sometimes your CSS rules will be \"inherited\" by all of the other jsPsych content inside of this parent <div>. For instance, in the fixation
example above, the CSS rules that change the font size, weight and color are applied to the parent <div> and automatically passed on to the stimulus text through inheritance.
There are two reasons why a CSS rule like the one above for fixation
may not work the way you expect:
-
Not all CSS properties are inherited from the parent element.
-
When a CSS property is inherited from the parent element, it will affect all elements in a given trial.
In these cases, you can change your CSS selector to make it more specific: add a space after class name, then add more CSS selectors to select the specific element(s) that you want to change.
Tip
To find out this more specific CSS selector, you can right-click on the element and select Inspect. In the inspector window, right-click on the property corresponding to the element and copy the selector. You might need to increase the trial's trial_duration
to give yourself enough time to inspect the elements on the page. See more tips for working with CSS below.
In the example below, the CSS selector .left-align #stimulus
selects the element with the ID \"stimulus\" that is inside of an element with the class \"left-align\".
<head>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <link rel=\"stylesheet\" href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\">\n <style> \n .left-align #stimulus {text-align: left; width: 600px;}\n .right-align #stimulus {text-align: right; width: 600px;}\n </style>\n</head>\n<script>\nconst trial_procedure = {\n timeline: [{\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<p id=\"stimulus\">This is the stimulus.</p>',\n prompt: '<p>This text will not be affected by the CSS classes '+\n 'because it does not have the \"stimulus\" ID.</p>',\n css_classes: jsPsych.timelineVariable('css_classes')\n }],\n timeline_variables: [\n {css_classes: ['left-align']},\n {css_classes: ['right-align']}\n ]\n}\n// ...\n</script>\n
It's also possible to pass multiple class names to the css_classes
parameter. This can be useful for creating conditions that involve crossing different style-related factors. This example shows you to combine two text alignment and two text color factors to produce four different stimulus conditions:
<head>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <link rel=\"stylesheet\" href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\">\n <style> \n .left-align #stimulus {text-align: left; width: 600px;}\n .right-align #stimulus {text-align: right; width: 600px;}\n .teal #stimulus {color: teal;}\n .purple #stimulus {color: purple;}\n </style>\n</head>\n<script>\nconst trial_procedure = {\n timeline: [{\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<p id=\"stimulus\">This is the stimulus.</p>',\n prompt: '<p>This text will not be affected by the CSS classes '+\n 'because it does not have the \"stimulus\" ID.</p>',\n css_classes: jsPsych.timelineVariable('css_classes'),\n data: {\n condition: jsPsych.timelineVariable('condition')\n }\n }],\n timeline_variables: [\n {css_classes: ['left-align','teal'], condition: 'left-teal'},\n {css_classes: ['right-align','teal'], condition: 'right-teal'},\n {css_classes: ['left-align','purple'], condition: 'left-purple'},\n {css_classes: ['right-align','purple'], condition: 'right-purple'}\n ]\n}\n// ...\n</script>\n
See the \"css-classes-parameter.html\" file in jsPsych's examples subfolder for more explanation and examples.
"},{"location":"overview/style/#tips-for-working-with-css","title":"Tips for working with CSS","text":"Your browser's developer tools contain very useful features for exploring and debugging your experiment's style and formatting. Open your browser's developer tools and click on the Element Inspector button or go to the Elements tab. Once you have selected an element on the page, you can see all of the information that can be used to select it, including:
- tag name, e.g., \"div\", \"p\", \"img\", \"button\"
- ID, if it has one
- class(es), if it has any
You can then use this information to create a CSS selector to modify that element's style.
As you can see, jsPsych adds its own IDs and classes to many elements. You can use the developer tools to determine what IDs and classes already exist for the elements that you want to modify, as you may can often just use these instead of adding your own. For instance, in the \"html-keyboard-response\" plugin, the stimulus will always be shown in a <div> with the ID \"jspsych-html-keyboard-response-stimulus\". So you can create a CSS rule that is applied to all \"html-keyboard-response\" stimuli like this:
#jspsych-html-keyboard-response-stimulus {\n color: white;\n background-color: blue;\n width: 100px;\n border: 4px solid black;\n}\n
As another example, most jsPsych buttons have the class \"jspsych-btn\", so you can use this class to change the default button styling:
.jspsych-btn {\n padding: 20px 20px;\n font-size: 25px;\n border-color: black;\n}\n
You can also use the developer tools to change an element's CSS and immediately see the effect that the changes will have on the page. These changes are just temporary, so you will still need to use one of methods described above to add the CSS changes to your experiment. However, making changes in the developer tools is very useful for figuring out which CSS properties to change and which values to use. This area of the developer tools also shows what styles are currently applied to the element and where those style rules are coming from.
There are a few things to be aware of while debugging problems with CSS.
- When there are conflicting CSS rules, some CSS rules will take precedence over others. For instance, inline CSS usually takes precedence over other CSS rules, and more specific CSS selectors usually take precedence over less specific ones.
- When there are conflicting CSS rules that have the same level of precedence, the last rule will override any earlier rules. For that reason it's important to add your own custom stylesheet after the default jspsych.css stylesheet. See this page about CSS precedence for more information.
If one CSS style rule is overridden by another one, the rule that is overridden will appear in strikethrough text in the element's \"Styles\" section. Also, if you are using an incorrect CSS property name or an invalid value, then that will show up here as an error, indicated by both strikethrough text and a little yellow warning symbol.
"},{"location":"overview/timeline/","title":"Creating an Experiment: The Timeline","text":"To create an experiment using jsPsych, you need to specify a timeline that describes the structure of the experiment. The timeline is an ordered set of trials. You must create the timeline before launching the experiment. Most of the code you will write for an experiment will be code to create the timeline. This page walks through the creation of timelines, including very basic examples and more advanced features.
"},{"location":"overview/timeline/#a-single-trial","title":"A single trial","text":"To create a trial, you need to create an object that describes the trial. The most important feature of this object is the type
parameter. This tells jsPsych which plugin to use to run the trial. For example, if you want to use the html-keyboard-response plugin to display a short message, the trial object would look like this:
const trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Welcome to the experiment.'\n}\n
The parameters for this object (e.g., stimulus
) will depend on the plugin that you choose. Each plugin defines the set of parameters that are needed to run a trial with that plugin. Visit the documentation for a plugin to learn about the parameters that you can use with that plugin.
To create a timeline with the single trial and run the experiment, just embed the trial object in an array. A timeline can simply be an array of trials.
const timeline = [trial];\n\njsPsych.run(timeline);\n
To create and run a simple experiment like this complete the hello world tutorial.
"},{"location":"overview/timeline/#multiple-trials","title":"Multiple trials","text":"Scaling up to multiple trials is straightforward. Create an object for each trial, and add each object to the timeline array.
// with lots of trials, it might be easier to add the trials\n// to the timeline array as they are defined.\nconst timeline = [];\n\nconst trial_1 = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'This is trial 1.'\n}\ntimeline.push(trial_1);\n\nconst trial_2 = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'This is trial 2.'\n}\ntimeline.push(trial_2);\n\nconst trial_3 = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'This is trial 3.'\n}\ntimeline.push(trial_3);\n
"},{"location":"overview/timeline/#nested-timelines","title":"Nested timelines","text":"Each object on the timeline can also have its own timeline. This is useful for many reasons. One is that it allows you to define common parameters across trials once and have them apply to all the trials on the nested timeline. The example below creates a series of trials using the image-keyboard-response plugin, where the only thing that changes from trial-to-trial is the image file being displayed on the screen.
const judgment_trials = {\n type: jsPsychImageKeyboardResponse,\n prompt: '<p>Press a number 1-7 to indicate how unusual the image is.</p>',\n choices: ['1','2','3','4','5','6','7'],\n timeline: [\n {stimulus: 'image1.png'},\n {stimulus: 'image2.png'},\n {stimulus: 'image3.png'}\n ]\n}\n
In the above code, the type
, prompt
, and choices
parameters are automatically applied to all of the objects in the timeline
array. This creates three trials with the same type
, prompt
, and choices
parameters, but different values for the stimulus
parameter.
You can also override the values by declaring a new value in the timeline
array. In the example below, the second trial will display a different prompt message.
const judgment_trials = {\n type: jsPsychImageKeyboardResponse,\n prompt: '<p>Press a number 1-7 to indicate how unusual the image is.</p>',\n choices: ['1','2','3','4','5','6','7'],\n timeline: [\n {stimulus: 'image1.png'},\n {stimulus: 'image2.png', prompt: '<p>Press 1 for this trial.</p>'},\n {stimulus: 'image3.png'}\n ]\n}\n
Timelines can be nested any number of times.
"},{"location":"overview/timeline/#timeline-variables","title":"Timeline variables","text":"A common pattern in behavioral experiments is to repeat the same procedure/task many times with slightly different parameters. A procedure might be a single trial, but it also might be a series of trials. For example, a task might involve a fixation cross appearing, followed by a blank screen, followed by an image for a short duration, followed by a prompt and a text box to report on some aspect of the image.
One shortcut to implement this pattern is with the nested timeline approach described in the previous section, but this only works if all the trials use the same plugin type. Timeline variables are a more general solution. With timeline variables you define the procedure once (as a timeline) and specify a set of parameters and their values for each iteration through the timeline.
What follows is an example of how to use timeline variables. The simple reaction time tutorial also explains how to use timeline variables.
Suppose we want to create an experiment where people see a set of faces. Perhaps this is a memory experiment and this is the phase of the experiment where the faces are being presented for the first time. In between each face, a fixation cross is displayed on the screen. Without timeline variables, we would need to add many trials to the timeline, alternating between trials showing the fixation cross and trials showing the face and name. This could be done efficiently using a loop or function to create the timeline, but timeline variables make it even easier - as well as adding extra features like sampling and randomization.
Here's a basic version of the task with timeline variables.
const face_name_procedure = {\n timeline: [\n {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '+',\n choices: \"NO_KEYS\",\n trial_duration: 500\n },\n {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('face'),\n choices: \"NO_KEYS\",\n trial_duration: 2500\n }\n ],\n timeline_variables: [\n { face: 'person-1.jpg' },\n { face: 'person-2.jpg' },\n { face: 'person-3.jpg' },\n { face: 'person-4.jpg' }\n ]\n}\n
In the above version, there are four separate trials defined in the timeline_variables
parameter. Each trial has a variable face
and a variable name
. The timeline
defines a procedure of showing a fixation cross for 500ms followed by the face and name for 2500ms. This procedure will repeat four times, with the first trial showing 'person-1.jpg'
, the second 'person-2.jpg'
, and so on. The variables are referenced within the procedure by calling the jsPsych.timelineVariable()
method and passing in the name of the variable.
What if we wanted to add an additional step to the task where the name is displayed prior to the face appearing? (Maybe this is one condition of an experiment investigating whether the order of name-face or face-name affects retention.) We can add another variable to our list that gives the name associated with each image. Then we can add another trial to our timeline to show the name.
const face_name_procedure = {\n timeline: [\n {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '+',\n choices: \"NO_KEYS\",\n trial_duration: 500\n },\n {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: jsPsych.timelineVariable('name'),\n trial_duration: 1000,\n choices: \"NO_KEYS\"\n },\n {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('face'), \n choices: \"NO_KEYS\",\n trial_duration: 1000\n }\n ],\n timeline_variables: [\n { face: 'person-1.jpg', name: 'Alex' },\n { face: 'person-2.jpg', name: 'Beth' },\n { face: 'person-3.jpg', name: 'Chad' },\n { face: 'person-4.jpg', name: 'Dave' }\n ]\n}\n
"},{"location":"overview/timeline/#using-timeline-variables-in-a-function","title":"Using timeline variables in a function","text":"Continuing the example from the previous section, what if we wanted to show the name with the face, combining the two variables together? To do this, we can use a dynamic parameter (a function) to create an HTML-string that uses both variables in a single parameter. However, because we are getting the value of a timeline variable in a function, we need to use jsPsych.evaluateTimelineVariable()
instead of jsPsych.timelineVariable()
. Calling .evaluateTimelineVariable()
immediately gets the value of the variable, while .timelineVariable()
creates a placeholder that jsPsych evaluates at the appropriate time during the execution of the experiment. The value of the stimulus
parameter will be a function that returns an HTML string that contains both the image and the name.
const face_name_procedure = {\n timeline: [\n {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '+',\n choices: \"NO_KEYS\",\n trial_duration: 500\n },\n {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: jsPsych.timelineVariable('name'),\n trial_duration: 1000,\n choices: \"NO_KEYS\"\n },\n {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: function(){\n const html = `\n <img src=\"${jsPsych.evaluateTimelineVariable('face')}\">\n <p>${jsPsych.evaluateTimelineVariable('name')}</p>`;\n return html;\n }, \n choices: \"NO_KEYS\",\n trial_duration: 2500\n }\n ],\n timeline_variables: [\n { face: 'person-1.jpg', name: 'Alex' },\n { face: 'person-2.jpg', name: 'Beth' },\n { face: 'person-3.jpg', name: 'Chad' },\n { face: 'person-4.jpg', name: 'Dave' }\n ]\n}\n
"},{"location":"overview/timeline/#random-orders-of-trials","title":"Random orders of trials","text":"If we want to randomize the order of the trials defined with timeline variables, we can set randomize_order
to true
.
const face_name_procedure = {\n timeline: [...],\n timeline_variables: [\n { face: 'person-1.jpg', name: 'Alex' },\n { face: 'person-2.jpg', name: 'Beth' },\n { face: 'person-3.jpg', name: 'Chad' },\n { face: 'person-4.jpg', name: 'Dave' }\n ],\n randomize_order: true\n}\n
"},{"location":"overview/timeline/#sampling-methods","title":"Sampling methods","text":"There are also sampling methods that can be used to select a set of trials from the timeline_variables. Sampling is declared by creating a sample
parameter. The sample
parameter is given an object of arguments. The type
parameter in this object controls the type of sampling that is done. Valid values for type
are:
\"with-replacement\"
: Sample size
items from the timeline variables with the possibility of choosing the same item multiple time. \"without-replacement\"
: Sample size
items from timeline variables, with each item being selected a maximum of 1 time. \"fixed-repetitons\"
: Repeat each item in the timeline variables size
times, in a random order. Unlike using the repetitons
parameter, this method allows for consecutive trials to use the same timeline variable set. \"alternate-groups\"
: Sample in an alternating order based on a declared group membership. Groups are defined by the groups
parameter. This parameter takes an array of arrays, where each inner array is a group and the items in the inner array are the indices of the timeline variables in the timeline_variables
array that belong to that group. \"custom\"
: Write a function that returns a custom order of the timeline variables.
"},{"location":"overview/timeline/#sampling-with-replacement","title":"Sampling with replacement","text":"This sample
parameter will create 10 repetitions, sampling with replacement.
const face_name_procedure = {\n timeline: [...],\n timeline_variables: [\n { face: 'person-1.jpg', name: 'Alex' },\n { face: 'person-2.jpg', name: 'Beth' },\n { face: 'person-3.jpg', name: 'Chad' },\n { face: 'person-4.jpg', name: 'Dave' }\n ],\n sample: {\n type: 'with-replacement',\n size: 10\n }\n}\n
"},{"location":"overview/timeline/#sampling-with-replacement-unequal-probabilities","title":"Sampling with replacement, unequal probabilities","text":"This sample
parameter will make the \"Alex\" trial three times as likely to be sampled as the others.
const face_name_procedure = {\n timeline: [...],\n timeline_variables: [\n { face: 'person-1.jpg', name: 'Alex' },\n { face: 'person-2.jpg', name: 'Beth' },\n { face: 'person-3.jpg', name: 'Chad' },\n { face: 'person-4.jpg', name: 'Dave' }\n ],\n sample: {\n type: 'with-replacement',\n size: 10, \n weights: [3, 1, 1, 1]\n }\n}\n
"},{"location":"overview/timeline/#sampling-without-replacement","title":"Sampling without replacement","text":"This sample
parameter will pick three of the four possible trials to run at random.
const face_name_procedure = {\n timeline: [...],\n timeline_variables: [\n { face: 'person-1.jpg', name: 'Alex' },\n { face: 'person-2.jpg', name: 'Beth' },\n { face: 'person-3.jpg', name: 'Chad' },\n { face: 'person-4.jpg', name: 'Dave' }\n ],\n sample: {\n type: 'without-replacement',\n size: 3 \n }\n}\n
"},{"location":"overview/timeline/#repeating-each-trial-a-fixed-number-of-times-in-a-random-order","title":"Repeating each trial a fixed number of times in a random order","text":"This sample
parameter will create 3 repetitions of each trial, for a total of 12 trials, with a random order.
const face_name_procedure = {\n timeline: [...],\n timeline_variables: [\n { face: 'person-1.jpg', name: 'Alex' },\n { face: 'person-2.jpg', name: 'Beth' },\n { face: 'person-3.jpg', name: 'Chad' },\n { face: 'person-4.jpg', name: 'Dave' }\n ],\n sample: {\n type: 'fixed-repetitions',\n size: 3\n }\n}\n
"},{"location":"overview/timeline/#alternating-groups","title":"Alternating groups","text":"This sample
parameter puts the \"Alex\" and \"Chad\" trials in group 1 and the \"Beth\" and \"Dave\" trials in group 2. The resulting sample of trials will follow the pattern group 1
-> group 2
-> group 1
-> group 2
. Each trial will be selected only one time. If you wanted group 2
to sometimes be first, you could set randomize_group_order: true
.
const face_name_procedure = {\n timeline: [...],\n timeline_variables: [\n { face: 'person-1.jpg', name: 'Alex' },\n { face: 'person-2.jpg', name: 'Beth' },\n { face: 'person-3.jpg', name: 'Chad' },\n { face: 'person-4.jpg', name: 'Dave' }\n ],\n sample: {\n type: 'alternate-groups',\n groups: [[0,2],[1,3]], \n randomize_group_order: false\n }\n}\n
"},{"location":"overview/timeline/#custom-sampling-function","title":"Custom sampling function","text":"Any sampling method can be implemented using the custom
type sampler. The order of trials will be determined by running the function supplied as fn
. The function has a single parameter, t
, which is an array of integers from 0
to n-1
, where n
is the number of trials in the timeline_variables
array. The function must return an array that specifies the order of the trials, e.g., returning [3,3,2,2,1,1,0,0]
would result in the order Dave
-> Dave
-> Chad
-> Chad
-> Beth
-> Beth
-> Alex
-> Alex
.
const face_name_procedure = {\n timeline: [...],\n timeline_variables: [\n { face: 'person-1.jpg', name: 'Alex' },\n { face: 'person-2.jpg', name: 'Beth' },\n { face: 'person-3.jpg', name: 'Chad' },\n { face: 'person-4.jpg', name: 'Dave' }\n ],\n sample: {\n type: 'custom',\n fn: function(t){\n return t.reverse(); // show the trials in the reverse order\n }\n }\n}\n
"},{"location":"overview/timeline/#repeating-a-set-of-trials","title":"Repeating a set of trials","text":"To repeat a timeline multiple times, you can create an object (node) that contains a timeline
, which is the timeline array to repeat, and repetitions
, which is the number of times to repeat that timeline.
const trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'This trial will be repeated twice.'\n}\n\nconst node = {\n timeline: [trial],\n repetitions: 2\n}\n
The repetitions
parameter can be used alongside other node parameters, such as timeline variables, loop functions, and/or conditional functions. If you are using timeline_variables
and randomize_order
is true
, then the order of the timeline variables will re-randomize before every repetition.
const face_name_procedure = {\n timeline: [...],\n timeline_variables: [\n { face: 'person-1.jpg', name: 'Alex' },\n { face: 'person-2.jpg', name: 'Beth' },\n { face: 'person-3.jpg', name: 'Chad' },\n { face: 'person-4.jpg', name: 'Dave' }\n ],\n randomize_order: true,\n repetitions: 3 \n}\n
"},{"location":"overview/timeline/#looping-timelines","title":"Looping timelines","text":"Any timeline can be looped using the loop_function
option. The loop function must be a function that evaluates to true
if the timeline should repeat, and false
if the timeline should end. It receives a single parameter, named data
by convention. This parameter will be the DataCollection object with all of the data from the trials executed in the last iteration of the timeline. The loop function will be evaluated after the timeline is completed.
const trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'This trial is in a loop. Press R to repeat this trial, or C to continue.'\n}\n\nconst loop_node = {\n timeline: [trial],\n loop_function: function(data){\n if(jsPsych.pluginAPI.compareKeys(data.values()[0].response, 'r')){\n return true;\n } else {\n return false;\n }\n }\n}\n
"},{"location":"overview/timeline/#conditional-timelines","title":"Conditional timelines","text":"A timeline can be skipped or not based on the evaluation of the conditional_function
option. If the conditional function evaluates to true
, the timeline will execute normally. If the conditional function evaluates to false
then the timeline will be skipped. The conditional function is evaluated whenever jsPsych is about to run the first trial on the timeline.
If you use a conditional function and a loop function on the same timeline, the conditional function will only evaluate once.
const jsPsych = initJsPsych();\n\nconst pre_if_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'The next trial is in a conditional statement. Press S to skip it, or V to view it.'\n}\n\nconst if_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'You chose to view the trial. Press any key to continue.'\n}\n\nconst if_node = {\n timeline: [if_trial],\n conditional_function: function(){\n // get the data from the previous trial,\n // and check which key was pressed\n const data = jsPsych.data.get().last(1).values()[0];\n if(jsPsych.pluginAPI.compareKeys(data.response, 's')){\n return false;\n } else {\n return true;\n }\n }\n}\n\nconst after_if_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'This is the trial after the conditional.'\n}\n\njsPsych.run([pre_if_trial, if_node, after_if_trial]);\n
"},{"location":"overview/timeline/#modifying-timelines-at-runtime","title":"Modifying timelines at runtime","text":"Although this functionality can also be achieved through a combination of the conditional_function
and the use of dynamic variables in the stimulus
parameter, our timeline implementation allows you to dynamically add or remove trials and nested timelines during runtime.
"},{"location":"overview/timeline/#adding-timeline-nodes-at-runtime","title":"Adding timeline nodes at runtime","text":"For example, you may have a branching point in your experiment where the participant is given 3 choices, each leading to a different timeline:
const jspsych = initJsPsych();\nlet main_timeline = [];\n\nconst part1_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Part 1'\n}\n\nconst choice_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Press 1 if you are a new participant. Press 2 for inquiries about an existing experiment run. Press 3 for Spanish.',\n choices: ['1','2','3']\n}\n
This would be trickier to implement with the conditional_function
since it can only handle 2 branches -- case when True
or case when False
. Instead, you can modify the timeline by modifying choice_trial
to dynamically adding a timeline at the end of the choice trial according to the chosen condition: const english_trial1 = {...};\nconst english_trial2 = {...};\nconst english_trial3 = {...};\n// So on and so forth\nconst spanish_trial3 = {...};\n\nconst english_branch = [b1_t1, b1_t2, b1_t3];\nconst mandarin_branch = [b2_t1, b2_t2, b2_t3];\nconst spanish_branch = [b3_t1, b3_t2, b3_t3];\n\nconst choice_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Press 1 for English. Press 2 for Mandarin. Press 3 for Spanish.',\n choices: ['1','2','3'],\n on_finish: (data) => {\n switch(data.response) {\n case '1':\n main_timeline.push(english_branch);\n break;\n case '2':\n main_timeline.push(mandarin_branch);\n break;\n case '3':\n main_timeline.push(spanish_branch);\n break;\n }\n }\n}\nmain_timeline.push(part1_trial, choice_trial);\n
During runtime, choices 1, 2 and 3 will dynamically add a different (nested) timeline, english_branch
, mandarin_branch
and spanish_branch
respectively, to the end of the main_timeline
."},{"location":"overview/timeline/#removing-timeline-nodes-at-runtime","title":"Removing timeline nodes at runtime","text":"You can also remove upcoming timeline nodes from a timeline at runtime. To demonstrate this, we can modify the above example by adding a 4th choice to choice_trial
and another (nested) timeline to the tail of main_timeline
:
const choice_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Press 1 for English. Press 2 for Mandarin. Press 3 for Spanish. Press 4 to exit.',\n choices: ['1','2','3', '4'],\n on_finish: (data) => {\n switch(data.response) {\n case '1':\n main_timeline.push(english_branch);\n break;\n case '2':\n main_timeline.push(mandarin_branch);\n break;\n case '3':\n main_timeline.push(spanish_branch);\n break;\n case '4':\n main_timeline.pop();\n break;\n }\n }\n}\n\nconst part2_timeline = [\n {\n type: JsPsychHtmlKeyboardResponse,\n stimulus: 'Part 2'\n }\n // ...the rest of the part 2 trials\n]\n\nmain_timeline.push(part1_trial, choice_trial, part2_timeline)\n
Now, if 1, 2 or 3 were chosen during runtime, part2_timeline
will run after the dynamically added timeline corresponding to the choice (english_branch
| mandarin_branch
| spanish_branch
) has been run; but if 4 was chosen, part2_timeline
will be removed at runtime, and main_timeline
will terminate."},{"location":"overview/timeline/#exception-cases-for-addingremoving-timeline-nodes-dynamically","title":"Exception cases for adding/removing timeline nodes dynamically","text":"Adding or removing timeline nodes work as expected when the addition/removal occurs at a future point in the timeline relative to the current executing node, but not if it occurs before the current node. The example above works as expected becaues all the node(s) added (english_branch
| mandarin_branch
| spanish_branch
) or removed (part2_timeline
) occur at the end of the timeline via push()
and pop()
. If a node was added at a point in the timeline that has already been executed, it will not be executed:
const choice_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Press 1 for English. Press 2 for Mandarin. Press 3 for Spanish. Press 4 to exit.',\n choices: ['1','2','3', '4'],\n on_finish: (data) => {\n switch(data.response) {\n case '1':\n main_timeline.splice(0,0,english_branch); // Adds english_branch to the start of main_timeline\n break;\n case '2':\n main_timeline.push(mandarin_branch);\n break;\n\n ...\n\nmain_timeline.push(part1_trial, choice_trial);\n
In the above implementation of choice_trial
, choice 1 adds english_branch
at the start of main_timeline
, such that main_timeline = [english_branch, part1_trial, choice_trial]
, but because the execution of main_timeline
is past the first node at this point in runtime, the newly added english_branch
will not be executed. Similarly, modifying case '1'
in choice_trial
to remove part1_trial
will not change any behavior in the timeline. Danger
In the case of a looping timeline, adding a timeline node at a point before the current node will cause the current node to be executed again; and removing a timeline node at a point before the current node will cause the next node to be skipped.
"},{"location":"overview/timeline/#timeline-start-and-finish-functions","title":"Timeline start and finish functions","text":"You can run a custom function at the start and end of a timeline node using the on_timeline_start
and on_timeline_finish
callback function parameters. These are functions that will run when the timeline starts and ends, respectively.
const procedure = {\n timeline: [trial_1, trial_2],\n on_timeline_start: function() {\n console.log('The trial procedure just started.')\n },\n on_timeline_finish: function() {\n console.log('The trial procedure just finished.')\n }\n}\n
This works the same way with timeline variables. The on_timeline_start
and on_timeline_finish
functions will run when timeline variables trials start and end, respectively.
const face_name_procedure = {\n timeline: [...],\n timeline_variables: [\n { face: 'person-1.jpg', name: 'Alex' },\n { face: 'person-2.jpg', name: 'Beth' },\n { face: 'person-3.jpg', name: 'Chad' },\n { face: 'person-4.jpg', name: 'Dave' }\n ],\n randomize_order: true,\n on_timeline_start: function() {\n console.log('First trial is starting.')\n },\n on_timeline_finish: function() {\n console.log('Last trial just finished.')\n }\n}\n
These functions will execute only once if the timeline loops.
"},{"location":"overview/timing-accuracy/","title":"Timing accuracy","text":"Wondering if jsPsych can be used for research that depends on accurate display times or response time measurement? For most purposes, the answer is yes.
Display timing is somewhat less accurate in JavaScript than in standard experimental software that runs on a desktop. Desktop software can have closer integration with the graphics devices of the machine than JavaScript currently permits. If a one or two frame (17-33ms) difference in display timing matters for your experiment, then you'll want to be careful with JavaScript-based experiments. It is possible to achieve this level of control in JavaScript, but it often requires code that is more tailored to your experiment and some restrictions about which browsers can be used to run the experiment.
Tip
If you are hoping to run an experiment with the best timing that jsPsych can offer, we currently recommend using the jspsych-psychophysics plugin developed by Daiichiro Kuroki.
Kuroki, D. (2021). A new jsPsych plugin for psychophysics, providing accurate display duration and stimulus onset asynchrony. Behavior Research Methods, 53, 301\u2013310. https://doi.org/10.3758/s13428-020-01445-w
Response time measurements in jsPsych (and JavaScript in general) are comparable to those taken in standard lab software like Psychophysics Toolbox and E-Prime. Response times measured in JavaScript tend to be a little bit longer (10-40ms), but have similar variance.
"},{"location":"overview/timing-accuracy/#references","title":"References","text":"See the following papers for extensive work on display and response timing in browser-based experiments.
Note that browsers are updating frequently and the JavaScript language specification is also changing. It's possible that the results from these papers do not apply to current versions of web browsers.
Future updates to JavaScript APIs will likely improve the ability of online experiments to provide more accurate display timing and response time measurement.
- Bridges, D., Pitiot, A., MacAskill, M. R., & Peirce, J. W. (2020). The timing mega-study: Comparing a range of experiment generators, both lab-based and online. PeerJ, 8, e9414.
- Anwyl-Irvine, A., Dalmaijer, E. S., Hodges, N., & Evershed, J. K. (2020). Realistic precision and accuracy of online experiment platforms, web browsers, and devices. Behavior Research Methods, 53, 1-19.
- Pronk, T., Wiers, R. W., Molenkamp, B., & Murre, J. (2020). Mental chronometry in the pocket? Timing accuracy of web applications on touchscreen and keyboard devices. Behavior Research Methods, 52(3), 1371-1382.
- Pinet, S., Zielinski, C., Math\u00f4t, S. et al. (2017). Measuring sequences of keystrokes with jsPsych: Reliability of response times and interkeystroke intervals. Behavior Research Methods, 49(3), 1177-1178.
- de Leeuw, J. R., & Motz, B. A. (2016). Psychophysics in a Web browser? Comparing response times collected with JavaScript and Psychophysics Toolbox in a visual search task. Behavior Research Methods, 48(1), 1-12.
- Hilbig, B. E. (2016). Reaction time effects in lab- versus web-based research: Experimental evidence. Behavior Research Methods, 48(4), 1718-1724.
- Reimers, S., & Stewart, N. (2015). Presentation and response time accuracy in Adobe Flash and HTML5/JavaScript Web experiments. Behavior Research Methods, 47(2), 309-327.
"},{"location":"plugins/animation/","title":"animation","text":"Current version: 2.0.1. See version history.
This plugin displays a sequence of images at a fixed frame rate. The sequence can be looped a specified number of times. The participant is free to respond at any point during the animation, and the time of the response is recorded.
"},{"location":"plugins/animation/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimuli array undefined Each element of the array is a path to an image file. frame_time numeric 250 How long to display each image in milliseconds. frame_isi numeric 0 If greater than 0, then a gap will be shown between each image in the sequence. This parameter specifies the length of the gap in milliseconds. sequence_reps numeric 1 How many times to show the entire sequence. There will be no gap (other than the gap specified by frame_isi
) between repetitions. choices array of strings \"ALL_KEYS\"
This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., 'a'
, 'q'
, ' '
, 'Enter'
, 'ArrowDown'
) - see this page and this page (event.key column) for more examples. Any key presses that are not listed in the array will be ignored. The default value of \"ALL_KEYS\"
means that all keys will be accepted as valid responses. Specifying \"NO_KEYS\"
will mean that no responses are allowed. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key(s) to press). render_on_canvas boolean true If true, the images will be drawn onto a canvas element. This prevents a blank screen (white flash) between consecutive images in some browsers, like Firefox and Edge. If false, the image will be shown via an img element, as in previous versions of jsPsych."},{"location":"plugins/animation/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value animation_sequence array An array, where each element is an object that represents a stimulus in the animation sequence. Each object has a stimulus
property, which is the image that was displayed, and a time
property, which is the time in ms, measured from when the sequence began, that the stimulus was displayed. The array will be encoded in JSON format when data is saved using either the .json()
or .csv()
functions. response array An array, where each element is an object representing a response given by the participant. Each object has a stimulus
property, indicating which image was displayed when the key was pressed, an rt
property, indicating the time of the key press relative to the start of the animation, and a key_press
property, indicating which key was pressed. The array will be encoded in JSON format when data is saved using either the .json()
or .csv()
functions."},{"location":"plugins/animation/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-animation@2.0.1\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-animation.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-animation\n
import animation from '@jspsych/plugin-animation';\n
"},{"location":"plugins/animation/#examples","title":"Examples","text":"Displaying a single sequence multiple times CodeDemo var animation_sequence = [\"img/happy_face_1.jpg\", \"img/happy_face_2.jpg\", \"img/happy_face_3.jpg\", \"img/happy_face_4.jpg\"];\n\nvar animation_trial = {\n type: jsPsychAnimation,\n stimuli: animation_sequence,\n sequence_reps: 3,\n frame_time: 300,\n prompt: '<p>Watch the faces.</p>',\n};\n
Open demo in new tab
"},{"location":"plugins/audio-button-response/","title":"audio-button-response","text":"Current version: 2.0.2. See version history.
This plugin plays audio files and records responses generated with a button click.
If the browser supports it, audio files are played using the WebAudio API. This allows for reasonably precise timing of the playback. The timing of responses generated is measured against the WebAudio specific clock, improving the measurement of response times. If the browser does not support the WebAudio API, then the audio file is played with HTML5 audio.
Audio files can be automatically preloaded by jsPsych using the preload
plugin. However, if you are using timeline variables or another dynamic method to specify the audio stimulus, you will need to manually preload the audio.
The trial can end when the participant responds, when the audio file has finished playing, or if the participant has failed to respond within a fixed length of time. You can also prevent a button response from being made before the audio has finished playing.
"},{"location":"plugins/audio-button-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus audio file undefined Path to audio file to be played. choices array of strings undefined Labels for the buttons. Each different string in the array will generate a different button. button_html function (choice: string, choice_index: number)=>`<button class=\"jspsych-btn\">${choice}</button>
; A function that generates the HTML for each button in the choices
array. The function gets the string and index of the item in the choices
array and should return valid HTML. If you want to use different markup for each button, you can do that by using a conditional on either parameter. The default parameter returns a button element with the text label of the choice. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, the trial will wait for a response indefinitely. button_layout string 'grid' Setting to 'grid'
will make the container element have the CSS property display: grid
and enable the use of grid_rows
and grid_columns
. Setting to 'flex'
will make the container element have the CSS property display: flex
. You can customize how the buttons are laid out by adding inline CSS in the button_html
parameter. grid_rows number 1 The number of rows in the button grid. Only applicable when button_layout
is set to 'grid'
. If null, the number of rows will be determined automatically based on the number of buttons and the number of columns. grid_columns number null The number of columns in the button grid. Only applicable when button_layout
is set to 'grid'
. If null, the number of columns will be determined automatically based on the number of buttons and the number of rows. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can set this parameter to false
to force the participant to listen to the stimulus for a fixed amount of time, even if they respond before the time is complete. trial_ends_after_audio boolean false If true, then the trial will end as soon as the audio file finishes playing. response_allowed_while_playing boolean true If true, then responses are allowed while the audio is playing. If false, then the audio must finish playing before the button choices are enabled and a response is accepted. Once the audio has played all the way through, the buttons are enabled and a response is allowed (including while the audio is being re-played via on-screen playback controls). enable_button_after numeric 0 How long the button will delay enabling in milliseconds. If response_allowed_while_playing
is true
, the timer will start immediately. If it is false
, the timer will start at the end of the audio."},{"location":"plugins/audio-button-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first began playing until the participant's response. response numeric Indicates which button the participant pressed. The first button in the choices
array is 0, the second is 1, and so on. stimulus string Path to the audio file that played during the trial."},{"location":"plugins/audio-button-response/#simulation-mode","title":"Simulation Mode","text":"In data-only
simulation mode, the response_allowed_while_playing
parameter does not currently influence the simulated response time. This is because the audio file is not loaded in data-only
mode and therefore the length is unknown. This may change in a future version as we improve the simulation modes.
"},{"location":"plugins/audio-button-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-audio-button-response@2.0.2\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-audio-button-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-audio-button-response\n
import audioButtonResponse from '@jspsych/plugin-audio-button-response';\n
"},{"location":"plugins/audio-button-response/#examples","title":"Examples","text":"Displaying question until participant gives a response CodeDemo var trial = {\n type: jsPsychAudioButtonResponse,\n stimulus: 'sound/tone.mp3',\n choices: ['Low', 'High'],\n prompt: \"<p>Is the pitch high or low?</p>\"\n};\n
Open demo in new tab
Using custom button HTML to use images as buttons Code ``javascript const trial = { type: jsPsychAudioButtonResponse, stimulus: 'sound/roar.mp3', choices: images, prompt: \"<p>Which animal made the sound?</p>\", button_html: (choice)=>
`
}; ```
Demo
Open demo in new tab
Setting up a grid-based layout Code ```javascript const trial = { type: jsPsychAudioButtonResponse,
stimulus: 'sound/telephone.mp3', prompt: '
Which key was pressed first?
', choices: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '0', '#'], button_layout: 'grid', grid_rows: 4, grid_columns: 3 } ``` Demo
Open demo in new tab
"},{"location":"plugins/audio-keyboard-response/","title":"audio-keyboard-response","text":"Current version: 2.0.0. See version history.
This plugin plays audio files and records responses generated with the keyboard.
If the browser supports it, audio files are played using the WebAudio API. This allows for reasonably precise timing of the playback. The timing of responses generated is measured against the WebAudio specific clock, improving the measurement of response times. If the browser does not support the WebAudio API, then the audio file is played with HTML5 audio.
Audio files can be automatically preloaded by jsPsych using the preload
plugin. However, if you are using timeline variables or another dynamic method to specify the audio stimulus, then you will need to manually preload the audio.
The trial can end when the participant responds, when the audio file has finished playing, or if the participant has failed to respond within a fixed length of time. You can also prevent a keyboard response from being recorded before the audio has finished playing.
"},{"location":"plugins/audio-keyboard-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus audio file undefined Path to audio file to be played. choices array of strings \"ALL_KEYS\"
This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., 'a'
, 'q'
, ' '
, 'Enter'
, 'ArrowDown'
) - see this page and this page (event.key column) for more examples. Any key presses that are not listed in the array will be ignored. The default value of \"ALL_KEYS\"
means that all keys will be accepted as valid responses. Specifying \"NO_KEYS\"
will mean that no responses are allowed. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can use set this parameter to false
to force the participant to listen to the stimulus for a fixed amount of time, even if they respond before the time is complete. trial_ends_after_audio boolean false If true, then the trial will end as soon as the audio file finishes playing. response_allowed_while_playing boolean true If true, then responses are allowed while the audio is playing. If false, then the audio must finish playing before a keyboard response is accepted. Once the audio has played all the way through, a valid keyboard response is allowed (including while the audio is being re-played via on-screen playback controls)."},{"location":"plugins/audio-keyboard-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response string Indicates which key the participant pressed. If no key was pressed before the trial ended, then the value will be null
. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first began playing until the participant made a key response. If no key was pressed before the trial ended, then the value will be null
. stimulus string Path to the audio file that played during the trial."},{"location":"plugins/audio-keyboard-response/#simulation-mode","title":"Simulation Mode","text":"In data-only
simulation mode, the response_allowed_while_playing
parameter does not currently influence the simulated response time. This is because the audio file is not loaded in data-only
mode and therefore the length is unknown. This may change in a future version as we improve the simulation modes.
"},{"location":"plugins/audio-keyboard-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-audio-keyboard-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-audio-keyboard-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-audio-keyboard-response\n
import audioKeyboardResponse from '@jspsych/plugin-audio-keyboard-response';\n
"},{"location":"plugins/audio-keyboard-response/#examples","title":"Examples","text":"Trial continues until participant gives a response CodeDemo var trial = {\n type: jsPsychAudioKeyboardResponse,\n stimulus: 'sound/tone.mp3',\n choices: ['e', 'i'],\n prompt: \"<p>Is the pitch high or low? Press 'e' for low and 'i' for high.</p>\",\n response_ends_trial: true\n};\n
Open demo in new tab
Play a sound with no user response; trial ends after sound plays CodeDemo var trial = {\n type: jsPsychAudioKeyboardResponse,\n stimulus: 'sound/tone.mp3',\n choices: \"NO_KEYS\",\n trial_ends_after_audio: true\n};\n
Open demo in new tab
"},{"location":"plugins/audio-slider-response/","title":"audio-slider-response","text":"Current version: 2.0.1. See version history.
This plugin plays an audio file and allows the participant to respond by dragging a slider.
If the browser supports it, audio files are played using the WebAudio API. This allows for reasonably precise timing of the playback. The timing of responses generated is measured against the WebAudio specific clock, improving the measurement of response times. If the browser does not support the WebAudio API, then the audio file is played with HTML5 audio.
Audio files can be automatically preloaded by jsPsych using the preload
plugin. However, if you are using timeline variables or another dynamic method to specify the audio stimulus, then you will need to manually preload the audio.
The trial can end when the participant responds, or if the participant has failed to respond within a fixed length of time. You can also prevent the slider response from being made before the audio has finished playing.
"},{"location":"plugins/audio-slider-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus audio file undefined Audio file to be played labels array of strings [] Labels displayed at equidistant locations on the slider. For example, two labels will be placed at the ends of the slider. Three labels would place two at the ends and one in the middle. Four will place two at the ends, and the other two will be at 33% and 67% of the slider width. button_label string 'Continue' Label of the button to end the trial. min integer 0 Sets the minimum value of the slider max integer 100 Sets the maximum value of the slider slider_start integer 50 Sets the starting value of the slider step integer 1 Sets the step of the slider. This is the smallest amount by which the slider can change. slider_width integer null Set the width of the slider in pixels. If left null, then the width will be equal to the widest element in the display. require_movement boolean false If true, the participant must move the slider before clicking the continue button. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can set this parameter to false
to force the participant to listen to the stimulus for a fixed amount of time, even if they respond before the time is complete. response_allowed_while_playing boolean true If true, then responses are allowed while the audio is playing. If false, then the audio must finish playing before the slider is enabled and the trial can end via the next button click. Once the audio has played all the way through, the slider is enabled and a response is allowed (including while the audio is being re-played via on-screen playback controls)."},{"location":"plugins/audio-slider-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response numeric The numeric value of the slider. rt numeric The time in milliseconds for the participant to make a response. The time is measured from when the stimulus first began playing until the participant's response. stimulus string The path of the audio file that was played. slider_start numeric The starting value of the slider."},{"location":"plugins/audio-slider-response/#simulation-mode","title":"Simulation Mode","text":"In data-only
simulation mode, the response_allowed_while_playing
parameter does not currently influence the simulated response time. This is because the audio file is not loaded in data-only
mode and therefore the length is unknown. This may change in a future version as we improve the simulation modes.
"},{"location":"plugins/audio-slider-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-audio-slider-response@2.0.1\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-audio-slider-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-audio-slider-response\n
import audioSliderResponse from '@jspsych/plugin-audio-slider-response';\n
"},{"location":"plugins/audio-slider-response/#examples","title":"Examples","text":"A simple rating scale CodeDemo var trial = {\n type: jsPsychAudioSliderResponse,\n stimulus: 'sound/speech_joke.mp3',\n labels: ['Not Funny', 'Funny'],\n prompt: '<p>How funny is the joke?</p>'\n}\n
Open demo in new tab
No response allowed until audio finishes; participant must interact with slider to continue CodeDemo var trial = {\n type: jsPsychAudioSliderResponse,\n stimulus: 'sound/speech_joke.mp3',\n labels: ['Not Funny', 'Funny'],\n prompt: '<p>How funny is the joke?</p>',\n response_allowed_while_playing: false,\n require_movement: true\n}\n
Open demo in new tab
"},{"location":"plugins/browser-check/","title":"browser-check","text":"Current version: 2.0.0. See version history.
This plugin measures and records various features of the participant's browser and can end the experiment if defined inclusion criteria are not met.
The plugin currently can record the following features:
- The width and height of the browser window in pixels.
- The type of browser used (e.g., Chrome, Firefox, Edge, etc.) and the version number of the browser.*
- Whether the participant is using a mobile device.*
- The operating system.*
- Support for the WebAudio API.
- Support for the Fullscreen API, e.g., through the fullscreen plugin.
- The display refresh rate in frames per second.
- Whether the device has a webcam and microphone. Note that this only reveals whether a webcam/microphone exists. The participant still needs to grant permission in order for the experiment to use these devices.
Warning
Features with an * are recorded by parsing the user agent string. This method is accurate most of the time, but is not guaranteed to be correct. The plugin uses the detect-browser package to perform user agent parsing. You can find a list of supported browsers and OSes in the source file.
The plugin begins by measuring the set of features requested. An inclusion function is evaluated to see if the paricipant passes the inclusion criteria. If they do, then the trial ends and the experiment continues. If they do not, then the experiment ends immediately. If a minimum width and/or minimum height is desired, the plugin will optionally display a message to participants whose browser windows are too small to give them an opportunity to make the window larger if possible. See the examples below for more guidance.
"},{"location":"plugins/browser-check/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description features array of strings [\"width\", \"height\", \"webaudio\", \"browser\", \"browser_version\", \"mobile\", \"os\", \"fullscreen\", \"vsync_rate\", \"webcam\", \"microphone\"]
The list of browser features to record. The default value includes all of the available options. skip_features array of strings []
Any features listed here will be skipped, even if they appear in features
. Use this when you want to run most of the defaults. vsync_frame_count int 60 The number of frames to sample when measuring the display refresh rate (\"vsync_rate\"
). Increasing the number will potenially improve the stability of the estimate at the cost of increasing the amount of time the plugin takes during this test. On most devices, 60 frames takes about 1 second to measure. allow_window_resize bool true Whether to allow the participant to resize the browser window if the window is smaller than minimum_width
and/or minimum_height
. If false
, then the minimum_width
and minimum_height
parameters are ignored and you can validate the size in the inclusion_function
. minimum_height int 0 If allow_window_resize
is true
, then this is the minimum height of the window (in pixels) that must be met before continuing. minimum_width int 0 If allow_window_resize
is true
, then this is the minimum width of the window (in pixels) that must be met before continuing. window_resize_message string see description The message that will be displayed during the interactive resize when allow_window_resize
is true
and the window is too small. If the message contains HTML elements with the special IDs browser-check-min-width
, browser-check-min-height
, browser-check-actual-height
, and/or browser-check-actual-width
, then the contents of those elements will be dynamically updated to reflect the minimum_width
, minimum_height
and measured width and height of the browser. The default message is: <p>Your browser window is too small to complete this experiment. Please maximize the size of your browser window. If your browser window is already maximized, you will not be able to complete this experiment.</p><p>The minimum window width is <span id=\"browser-check-min-width\"></span> px.</p><p>Your current window width is <span id=\"browser-check-actual-width\"></span> px.</p><p>The minimum window height is <span id=\"browser-check-min-height\"></span> px.</p><p>Your current window height is <span id=\"browser-check-actual-height\"></span> px.</p>
. resize_fail_button_text string \"I cannot make the window any larger\"
During the interactive resize, a button with this text will be displayed below the window_resize_message
for the participant to click if the window cannot meet the minimum size needed. When the button is clicked, the experiment will end and exclusion_message
will be displayed. inclusion_function function () => { return true; }
A function that evaluates to true
if the browser meets all of the inclusion criteria for the experiment, and false
otherwise. The first argument to the function will be an object containing key value pairs with the measured features of the browser. The keys will be the same as those listed in features
. See example below. exclusion_message function () => { return <p>Your browser does not meet the requirements to participate in this experiment.</p> }
A function that returns the message to display if inclusion_function
evaluates to false
or if the participant clicks on the resize fail button during the interactive resize. In order to allow customization of the message, the first argument to the function will be an object containing key value pairs with the measured features of the browser. The keys will be the same as those listed in features
. See example below."},{"location":"plugins/browser-check/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value width int The width of the browser window in pixels. If interactive resizing happens, this is the width after resizing. height int The height of the browser window in pixels. If interactive resizing happens, this is the height after resizing. browser string The browser used. browser_version string The version number of the browser. os string The operating system used. mobile bool Whether the browser is a mobile device. webaudio bool Whether the browser supports the WebAudio API. fullscreen bool Whether the browser supports the Fullscreen API. vsync_rate number An estimate of the refresh rate of the screen, in frames per second. webcam bool Whether there is a webcam device available. Note that the participant still must grant permission to access the device before it can be used. microphone bool Whether there is an audio input device available. Note that the participant still must grant permission to access the device before it can be used. Note that all of these values are only recorded when the corresponding key is included in the features
parameter for the trial.
"},{"location":"plugins/browser-check/#simulation-mode","title":"Simulation Mode","text":"In simulation mode the plugin will report the actual features of the browser, with the exception of vsync_rate
, which is always 60.
In data-only
mode, if allow_window_resize
is true and the browser's width and height are below the maximum value then the reported width and height will be equal to minimum_width
and minimum_height
, as if the participant resized the browser to meet the specifications.
In visual
mode, if allow_window_resize
is true and the browser's width and height are below the maximum value then the experiment will wait for 3 seconds before clicking the resize fail button. During this time, you can adjust the window if you would like to.
As with all simulated plugins, you can override the default (actual) data with fake data using simulation_options
. This allows you to test your exclusion criteria by simulating other configurations.
"},{"location":"plugins/browser-check/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-browser-check@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-browser-check.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-browser-check\n
import browserCheck from '@jspsych/plugin-browser-check';\n
"},{"location":"plugins/browser-check/#examples","title":"Examples","text":"Recording all of the available features, no exclusions CodeDemo var trial = {\n type: jsPsychBrowserCheck\n};\n
Open demo in new tab
Using the inclusion function to mandate the use of Chrome or Firefox as the browser CodeDemo var trial = {\n type: jsPsychBrowserCheck,\n inclusion_function: (data) => {\n return ['chrome', 'firefox'].includes(data.browser);\n },\n exclusion_message: (data) => {\n return `<p>You must use Chrome or Firefox to complete this experiment.</p>`\n },\n};\n
Open demo in new tab
Setting a minimum window height & width, with the option to resize the window CodeDemo var trial = {\n type: jsPsychBrowserCheck,\n minimum_width: 1000,\n minimum_height: 600\n};\n
This demo only works in a resizable window. Please open it in new tab
Open demo in new tab
Custom exclusion message based on measured features CodeDemo var trial = {\n type: jsPsychBrowserCheck,\n inclusion_function: (data) => {\n return data.browser == 'chrome' && data.mobile === false\n },\n exclusion_message: (data) => {\n if(data.mobile){\n return '<p>You must use a desktop/laptop computer to participate in this experiment.</p>';\n } else if(data.browser !== 'chrome'){\n return '<p>You must use Chrome as your browser to complete this experiment.</p>'\n }\n }\n};\n
Open demo in new tab
"},{"location":"plugins/call-function/","title":"call-function","text":"Current version: 2.0.0. See version history.
This plugin executes a specified function. This allows the experimenter to run arbitrary code at any point during the experiment.
The function cannot take any arguments. If arguments are needed, then an anonymous function should be used to wrap the function call (see examples below).
"},{"location":"plugins/call-function/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description func function undefined The function to call. async boolean false
Set to true if func
is an asynchoronous function. If this is true, then the first argument passed to func
will be a callback that you should call when the async operation is complete. You can pass data to the callback. See example below."},{"location":"plugins/call-function/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value value any The return value of the called function."},{"location":"plugins/call-function/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-call-function@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-call-function.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-call-function\n
import callFunction from '@jspsych/plugin-call-function';\n
"},{"location":"plugins/call-function/#examples","title":"Examples","text":"Calling a simple function CodeDemo var myfunc = function() {\n return 'you called?';\n}\n\nvar trial = {\n type: jsPsychCallFunction,\n func: myfunc\n}\n
Open demo in new tab
Using an anonymous function to pass variables CodeDemo var myfunc = function(data){\n // data contains all the experiment data so far,\n // so this function could implement code to write\n // the data to a database.\n console.log(data.values())\n}\n\nvar trial = {\n type: jsPsychCallFunction,\n func: function(){ myfunc(jsPsych.data.get()) }\n}\n
Open demo in new tab
Async function call: wait for data to be saved to a server Code There's no demo for this code, because it requires a server to communicate with.
var trial = {\n type: jsPsychCallFunction,\n async: true,\n func: function(done){\n // can perform async operations here like\n // creating an XMLHttpRequest to communicate\n // with a server\n var xhttp = new XMLHttpRequest();\n xhttp.onreadystatechange = function() {\n if (this.readyState == 4 && this.status == 200) {\n var response_data = xhttp.responseText;\n // line below is what causes jsPsych to \n // continue to next trial. response_data\n // will be stored in jsPsych data object.\n done(response_data);\n }\n };\n xhttp.open(\"GET\", \"path_to_server_script.php\", true);\n xhttp.send();\n }\n}\n
Async function call: simulate waiting for an event to finish CodeDemo var trial = {\n type: jsPsychCallFunction,\n async: true,\n func: function(done){\n // generate a delay between 1500 and 3000 milliseconds to simulate \n // waiting for an event to finish after an unknown duration,\n // then move on with the experiment\n var rand_delay = (Math.floor(Math.random() * (3000 - 1500 + 1) + 1500));\n jsPsych.pluginAPI.setTimeout(function() {\n // end the trial and save the delay duration to the data\n done(rand_delay.toString()+\"ms\");\n }, rand_delay)\n }\n};\n
Open demo in new tab
"},{"location":"plugins/canvas-button-response/","title":"canvas-button-response","text":"Current version: 2.0.0. See version history.
This plugin can be used to draw a stimulus on a HTML canvas element, and record a button click response and response time. The canvas stimulus can be useful for displaying dynamic, parametrically-defined graphics, and for controlling the positioning of multiple graphical elements (shapes, text, images). The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the participant has failed to respond within a fixed length of time. One or more button choices will be displayed under the canvas, and the button style can be customized using HTML formatting.
"},{"location":"plugins/canvas-button-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus function undefined The function to draw on the canvas. This function automatically takes a canvas element as its only argument, e.g. function(c) {...}
or function drawStim(c) {...}
, where c
refers to the canvas element. Note that the stimulus function will still generally need to set the correct context itself, using a line like let ctx = c.getContext(\"2d\")
. canvas_size array [500, 500] Array that defines the size of the canvas element in pixels. First value is height, second value is width. choices array of strings [] Labels for the buttons. Each different string in the array will generate a different button. button_html function (choice: string, choice_index: number)=>`<button class=\"jspsych-btn\">${choice}</button>
; A function that generates the HTML for each button in the choices
array. The function gets the string and index of the item in the choices
array and should return valid HTML. If you want to use different markup for each button, you can do that by using a conditional on either parameter. The default parameter returns a button element with the text label of the choice. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., what question to answer). trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, the trial will wait for a response indefinitely. stimulus_duration numeric null How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to hidden
after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. button_layout string 'grid' Setting to 'grid'
will make the container element have the CSS property display: grid
and enable the use of grid_rows
and grid_columns
. Setting to 'flex'
will make the container element have the CSS property display: flex
. You can customize how the buttons are laid out by adding inline CSS in the button_html
parameter. grid_rows number 1 The number of rows in the button grid. Only applicable when button_layout
is set to 'grid'
. If null, the number of rows will be determined automatically based on the number of buttons and the number of columns. grid_columns number null The number of columns in the button grid. Only applicable when button_layout
is set to 'grid'
. If null, the number of columns will be determined automatically based on the number of buttons and the number of rows. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can use this parameter to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete."},{"location":"plugins/canvas-button-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. response numeric Indicates which button the participant pressed. The first button in the choices
array is 0, the second is 1, and so on. Note: the canvas stimulus is not included in the trial data because it is a function. Any stimulus information that should be saved in the trial data can be added via the data
parameter.
"},{"location":"plugins/canvas-button-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-canvas-button-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-canvas-button-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-canvas-button-response\n
import canvasButtonResponse from '@jspsych/plugin-canvas-button-response';\n
"},{"location":"plugins/canvas-button-response/#examples","title":"Examples","text":"Drawing circles based on parameters CodeDemo function filledCirc(canvas, radius, color) {\n var ctx = canvas.getContext(\"2d\");\n ctx.beginPath();\n ctx.arc(150, 150, radius, 0, 2 * Math.PI);\n ctx.fillStyle = color;\n ctx.fill();\n}\n\nvar circle_1 = {\n type: jsPsychCanvasButtonResponse,\n stimulus: function(c) {\n filledCirc(c, 100, 'blue');\n },\n canvas_size: [300, 300],\n choices: ['Red', 'Green', 'Blue'],\n prompt: '<p>What color is the circle?</p>',\n data: {color: 'blue', radius: 100}\n};\n\nvar circle_2 = {\n type: jsPsychCanvasButtonResponse,\n stimulus: function(c) {\n filledCirc(c, 150, 'green');\n },\n canvas_size: [300, 300],\n choices: ['Larger', 'Smaller'],\n stimulus_duration: 1000,\n prompt: '<p>Is this circle larger or smaller than the last one?</p>'+\n '<p>Stimulus will be hidden after 1 second.</p>',\n data: {color: 'green', radius: 150}\n};\n
Open demo in new tab
Using an anonymous stimulus function CodeDemo var lines = {\n type: jsPsychCanvasButtonResponse,\n stimulus: function(c) {\n var ctx = c.getContext(\"2d\");\n // first line\n ctx.beginPath();\n ctx.moveTo(200, 10);\n ctx.lineTo(200, 250);\n ctx.lineWidth = 10;\n ctx.strokeStyle = 'MediumBlue';\n ctx.stroke();\n // second line\n ctx.beginPath();\n ctx.moveTo(20, 100);\n ctx.lineTo(100, 250);\n ctx.lineWidth = 10;\n ctx.strokeStyle = 'MediumPurple';\n ctx.stroke();\n },\n canvas_size: [300, 300],\n choices: ['Blue line', 'Purple line'],\n prompt: '<p>Which line is longer?</p>',\n data: {line1_color: 'blue', line1_length: 290, line2_color: \"purple\", line2_length: 170}\n};\n
Open demo in new tab
Using the canvas stimulus function with timeline variables, and recording the correctness of responses CodeDemo function filledCirc(canvas, radius, color) {\n var ctx = canvas.getContext(\"2d\");\n ctx.beginPath();\n ctx.arc(150, 150, radius, 0, 2 * Math.PI);\n ctx.fillStyle = color;\n ctx.fill();\n}\n\nvar circle_procedure = {\n timeline: [\n {\n type: jsPsychCanvasButtonResponse,\n stimulus: function(c) {\n filledCirc(c, jsPsych.evaluateTimelineVariable('radius'), jsPsych.evaluateTimelineVariable('color'));\n },\n canvas_size: [300, 300],\n choices: ['Red', 'Green', 'Blue'],\n prompt: '<p>What color is the circle?</p>',\n data: {\n radius: jsPsych.timelineVariable('radius'), \n color: jsPsych.timelineVariable('color'),\n correct_response: jsPsych.timelineVariable('correct_response')\n },\n on_finish: function(data){\n data.correct = data.response == data.correct_response;\n }\n }\n ],\n timeline_variables: [\n {radius: 80, color: 'red', correct_response: 0},\n {radius: 100, color: 'green', correct_response: 1},\n {radius: 50, color: 'blue', correct_response: 2}\n ],\n randomize_order: true\n}; \n
Open demo in new tab
"},{"location":"plugins/canvas-keyboard-response/","title":"canvas-keyboard-response","text":"Current version: 2.0.0. See version history.
This plugin can be used to draw a stimulus on a HTML canvas element and record a keyboard response. The canvas stimulus can be useful for displaying dynamic, parametrically-defined graphics, and for controlling the positioning of multiple graphical elements (shapes, text, images). The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the participant has failed to respond within a fixed length of time.
"},{"location":"plugins/canvas-keyboard-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus function undefined The function to draw on the canvas. This function automatically takes a canvas element as its only argument, e.g. function(c) {...}
or function drawStim(c) {...}
, where c
refers to the canvas element. Note that the stimulus function will still generally need to set the correct context itself, using a line like let ctx = c.getContext(\"2d\")
. canvas_size array [500, 500] Array that defines the size of the canvas element in pixels. First value is height, second value is width. choices array of strings \"ALL_KEYS\"
This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., 'a'
, 'q'
, ' '
, 'Enter'
, 'ArrowDown'
) - see this page and this page (event.key column) for more examples. Any key presses that are not listed in the array will be ignored. The default value of \"ALL_KEYS\"
means that all keys will be accepted as valid responses. Specifying \"NO_KEYS\"
will mean that no responses are allowed. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). stimulus_duration numeric null How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to hidden
after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can use this parameter to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete."},{"location":"plugins/canvas-keyboard-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. Note: the canvas stimulus is not included in the trial data because it is a function. Any stimulus information that should be saved in the trial data can be added via the data
parameter.
"},{"location":"plugins/canvas-keyboard-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-canvas-keyboard-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-canvas-keyboard-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-canvas-keyboard-response\n
import canvasKeyboardResponse from '@jspsych/plugin-canvas-keyboard-response';\n
"},{"location":"plugins/canvas-keyboard-response/#examples","title":"Examples","text":"Draw rectangle and wait for response CodeDemo function drawRect(c){\n var ctx = c.getContext('2d');\n ctx.beginPath();\n ctx.rect(30, 30, 200, 50);\n ctx.stroke();\n}\n\nvar trial = {\n type: jsPsychCanvasKeyboardResponse,\n canvas_size: [300, 300],\n stimulus: drawRect,\n choices: ['e','i'],\n prompt: '<p>Is this a circle or a rectangle? Press \"e\" for circle and \"i\" for rectangle.</p>',\n data: {shape: 'rectangle'}\n}\n
Open demo in new tab
Draw circle, no response allowed CodeDemo function drawCirc(c){\n var ctx = c.getContext('2d');\n ctx.beginPath();\n ctx.arc(100, 75, 50, 0, 2 * Math.PI);\n ctx.stroke();\n}\n\nvar trial = {\n type: jsPsychCanvasKeyboardResponse,\n canvas_size: [300, 300],\n stimulus: drawCirc,\n prompt: '<p>No key response is allowed.</p><p>The stimulus disappears after 3 seconds.</p>',\n choices: \"NO_KEYS\",\n trial_duration: 3000,\n data: {shape: 'circle', radius: 50}\n}\n
Open demo in new tab
"},{"location":"plugins/canvas-slider-response/","title":"canvas-slider-response","text":"Current version: 2.0.0. See version history.
This plugin can be used to draw a stimulus on a HTML canvas element and collect a response within a range of values, which is made by dragging a slider. The canvas stimulus can be useful for displaying dynamic, parametrically-defined graphics, and for controlling the positioning of multiple graphical elements (shapes, text, images). The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the participant has failed to respond within a fixed length of time.
"},{"location":"plugins/canvas-slider-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus function undefined The function to draw on the canvas. This function automatically takes a canvas element as its only argument, e.g. function(c) {...}
or function drawStim(c) {...}
, where c
refers to the canvas element. Note that the stimulus function will still generally need to set the correct context itself, using a line like let ctx = c.getContext(\"2d\")
. canvas_size array [500, 500] Array that defines the size of the canvas element in pixels. First value is height, second value is width. labels array of strings [] Labels displayed at equidistant locations on the slider. For example, two labels will be placed at the ends of the slider. Three labels would place two at the ends and one in the middle. Four will place two at the ends, and the other two will be at 33% and 67% of the slider width. button_label string 'Continue' Label of the button to end the trial. min integer 0 Sets the minimum value of the slider. max integer 100 Sets the maximum value of the slider. slider_start integer 50 Sets the starting value of the slider. step integer 1 Sets the step of the slider. This is the smallest amount by which the slider can change. slider_width integer null Set the width of the slider in pixels. If left null, then the width will be equal to the widest element in the display. require_movement boolean false If true, the participant must click the slider before clicking the continue button. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., what question to answer). stimulus_duration numeric null How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to hidden
after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can use this parameter to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete."},{"location":"plugins/canvas-slider-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response numeric The numeric value of the slider. rt numeric The time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. Note: the canvas stimulus is not included in the trial data because it is a function. Any stimulus information that should be saved in the trial data can be added via the data
parameter.
"},{"location":"plugins/canvas-slider-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-canvas-slider-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-canvas-slider-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-canvas-slider-response\n
import canvasSliderResponse from '@jspsych/plugin-canvas-slider-response';\n
"},{"location":"plugins/canvas-slider-response/#examples","title":"Examples","text":"Draw two squares CodeDemo var colors = ['#FF3333', '#FF6A33'];\n\nfunction twoSquares(c) { \n var ctx = c.getContext('2d');\n ctx.fillStyle = colors[0];\n ctx.fillRect(200, 70, 40, 40);\n ctx.fillStyle = colors[1];\n ctx.fillRect(260, 70, 40, 40);\n}\n\nvar trial = {\n type: jsPsychCanvasSliderResponse,\n stimulus: twoSquares,\n labels: ['0','10'],\n canvas_size: [150, 500],\n prompt: '<p>How different would you say the colors of these two squares are on a scale from 0 (the same) to 10 (completely different)</p>',\n data: {color1: colors[0], color2: colors[1]}\n}\n
Open demo in new tab
Draw two squares with additional parameters CodeDemo var colors;\n\nfunction twoSquares(c, colors) {\n var ctx = c.getContext('2d');\n ctx.fillStyle = colors[0];\n ctx.fillRect(200, 70, 40, 40);\n ctx.fillStyle = colors[1];\n ctx.fillRect(260, 70, 40, 40);\n}\n\nvar trial = {\n type: jsPsychCanvasSliderResponse,\n stimulus: function(c) {\n colors = ['darkred', 'cyan'];\n twoSquares(c, colors);\n },\n labels: ['Exactly<br>the same','Totally<br>different'],\n canvas_size: [200, 500],\n prompt: '<p>How different would you say the colors of these two squares are?</p>',\n on_finish: function(data) {\n data.color1 = colors[0];\n data.color2 = colors[1];\n }\n};\n
Open demo in new tab
"},{"location":"plugins/categorize-animation/","title":"categorize-animation","text":"Current version: 2.0.0. See version history.
The categorize animation plugin shows a sequence of images at a specified frame rate. The participant responds by pressing a key. Feedback indicating the correctness of the response is given.
"},{"location":"plugins/categorize-animation/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimuli array undefined Each element of the array is a path to an image file. choices array of strings \"ALL_KEYS\"
This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., 'a'
, 'q'
, ' '
, 'Enter'
, 'ArrowDown'
) - see this page and this page (event.key column) for more examples. Any key presses that are not listed in the array will be ignored. The default value of \"ALL_KEYS\"
means that all keys will be accepted as valid responses. Specifying \"NO_KEYS\"
will mean that no responses are allowed. key_answer string undefined The key character indicating the correct response. text_answer string \"\" A text label that describes the correct answer. Used in conjunction with the correct_text
and incorrect_text
parameters. correct_text string \"Correct.\" String to show when the correct answer is given. Can contain HTML formatting. The special string %ANS%
can be used within the string. If present, the plugin will put the text_answer
for the trial in place of the %ANS% string (see example below). incorrect_text string \"Wrong.\" String to show when the wrong answer is given. Can contain HTML formatting. The special string %ANS%
can be used within the string. If present, the plugin will put the text_answer
for the trial in place of the %ANS% string (see example below). frame_time numeric 500 How long to display each image (in milliseconds). sequence_reps numeric 1 How many times to show the entire sequence. allow_response_before_complete boolean false If true, the participant can respond before the animation sequence finishes. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus or the end of the animation depending on the allow_response_before_complete parameter. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). feedback_duration numeric 2000 How long to show the feedback (milliseconds). render_on_canvas boolean true If true, the images will be drawn onto a canvas element. This prevents a blank screen (white flash) between consecutive images in some browsers, like Firefox and Edge. If false, the image will be shown via an img element, as in previous versions of jsPsych."},{"location":"plugins/categorize-animation/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value stimulus array Array of stimuli displayed in the trial. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. correct boolean true
if the participant got the correct answer, false
otherwise."},{"location":"plugins/categorize-animation/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-categorize-animation@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-categorize-animation.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-categorize-animation\n
import categorizeAnimation from '@jspsych/plugin-categorize-animation';\n
"},{"location":"plugins/categorize-animation/#examples","title":"Examples","text":"Basic example CodeDemo var animation_trial = {\n type: jsPsychCategorizeAnimation,\n stimuli: [\n 'img/happy_face_1.jpg', \n 'img/happy_face_2.jpg', \n 'img/happy_face_3.jpg', \n 'img/happy_face_4.jpg'\n ],\n prompt: `Press the P or Q key.`,\n choices: ['p', 'q'],\n key_answer: 'q', \n};\n
Open demo in new tab
Giving feedback with %ANS%
string CodeDemo var images = [\n 'img/happy_face_1.jpg', \n 'img/happy_face_2.jpg', \n 'img/happy_face_3.jpg', \n 'img/happy_face_4.jpg'\n];\n\nvar animation_trial = {\n type: jsPsychCategorizeAnimation,\n stimuli: images,\n choices: ['p', 'q'],\n prompt: `Press the P or Q key.`,\n key_answer: 'q', \n text_answer: 'Dax', // the label for the sequence is 'Dax'\n correct_text: 'Correct! This was a %ANS%.',\n incorrect_text: 'Incorrect. This was a %ANS%.'\n};\n
Open demo in new tab
"},{"location":"plugins/categorize-html/","title":"categorize-html","text":"Current version: 2.0.0. See version history.
The categorize html plugin shows an HTML object on the screen. The participant responds by pressing a key. Feedback indicating the correctness of the response is given.
"},{"location":"plugins/categorize-html/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus html string undefined The HTML stimulus to display. choices array of strings \"ALL_KEYS\"
This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., 'a'
, 'q'
, ' '
, 'Enter'
, 'ArrowDown'
) - see this page and this page (event.key column) for more examples. Any key presses that are not listed in the array will be ignored. The default value of \"ALL_KEYS\"
means that all keys will be accepted as valid responses. Specifying \"NO_KEYS\"
will mean that no responses are allowed. key_answer string undefined The key character indicating the correct response. text_answer string \"\" A label that is associated with the correct answer. Used in conjunction with the correct_text
and incorrect_text
parameters. correct_text string \"Correct.\" String to show when the correct answer is given. Can contain HTML formatting. The special string %ANS%
can be used within the string. If present, the plugin will put the text_answer
for the trial in place of the %ANS%
string (see example below). incorrect_text string \"Wrong.\" String to show when the wrong answer is given. Can contain HTML formatting. The special string %ANS%
can be used within the string. If present, the plugin will put the text_answer
for the trial in place of the %ANS%
string (see example below). prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). force_correct_button_press boolean false If set to true, then the participant must press the correct response key after feedback is given in order to advance to the next trial. show_stim_with_feedback boolean true If set to true, then the stimulus will be shown during feedback. If false, then only the text feedback will display during feedback. show_feedback_on_timeout boolean false If true, then category feedback will be displayed for an incorrect response after a timeout (trial_duration is exceeded). If false, then a timeout message will be shown. timeout_message string \"Please respond faster.\" The message to show on a timeout non-response. stimulus_duration numeric null How long to show the stimulus for (milliseconds). If null, then the stimulus is shown until a response is given. feedback_duration numeric 2000 How long to show the feedback for (milliseconds). trial_duration numeric null The maximum time allowed for a response. If null, then the experiment will wait indefinitely for a response."},{"location":"plugins/categorize-html/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value stimulus string Either the path to the image file or the string containing the HTML formatted content that the participant saw on this trial. response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. correct boolean true
if the participant got the correct answer, false
otherwise."},{"location":"plugins/categorize-html/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-categorize-html@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-categorize-html.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-categorize-html\n
import categorizeHtml from '@jspsych/plugin-categorize-html';\n
"},{"location":"plugins/categorize-html/#examples","title":"Examples","text":"Categorizing HTML content CodeDemo var categorization_trial = {\n type: jsPsychCategorizeHtml,\n stimulus: '<p>B</p>',\n key_answer: 'p',\n text_answer: 'letter',\n choices: ['p', 'q'],\n correct_text: \"<p class='prompt'>Correct, this is a %ANS%.</p>\",\n incorrect_text: \"<p class='prompt'>Incorrect, this is a %ANS%.</p>\",\n prompt: \"<p>Press p for letter. Press q for number.</p>\"\n };\n
Open demo in new tab
"},{"location":"plugins/categorize-image/","title":"categorize-image","text":"Current version: 2.0.0. See version history.
The categorize image plugin shows an image object on the screen. The participant responds by pressing a key. Feedback indicating the correctness of the response is given.
"},{"location":"plugins/categorize-image/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus string undefined The path to the image file. key_answer string undefined The key character indicating the correct response. choices array of strings \"ALL_KEYS\"
This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., 'a'
, 'q'
, ' '
, 'Enter'
, 'ArrowDown'
) - see this page and this page (event.key column) for more examples. Any key presses that are not listed in the array will be ignored. The default value of \"ALL_KEYS\"
means that all keys will be accepted as valid responses. Specifying \"NO_KEYS\"
will mean that no responses are allowed. text_answer string \"\" A label that is associated with the correct answer. Used in conjunction with the correct_text
and incorrect_text
parameters. correct_text string \"Correct.\" String to show when the correct answer is given. Can contain HTML formatting. The special string %ANS%
can be used within the string. If present, the plugin will put the text_answer
for the trial in place of the %ANS% string (see example below). incorrect_text string \"Wrong.\" String to show when the wrong answer is given. Can contain HTML formatting. The special string %ANS%
can be used within the string. If present, the plugin will put the text_answer
for the trial in place of the %ANS% string (see example below). prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). force_correct_button_press boolean false If set to true, then the participant must press the correct response key after feedback is given in order to advance to the next trial. show_stim_with_feedback boolean true If set to true, then the stimulus will be shown during feedback. If false, then only the text feedback will display during feedback. show_feedback_on_timeout boolean false If true, then category feedback will be displayed for an incorrect response after a timeout (trial_duration is exceeded). If false, then a timeout message will be shown. timeout_message string \"Please respond faster.\" The message to show on a timeout non-response. stimulus_duration numeric null How long to show the stimulus for (milliseconds). If null, then the stimulus is shown until a response is given. feedback_duration numeric 2000 How long to show the feedback for (milliseconds). trial_duration numeric null The maximum time allowed for a response. If null, then the experiment will wait indefinitely for a response."},{"location":"plugins/categorize-image/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value stimulus string Either the path to the image file or the string containing the HTML formatted content that the participant saw on this trial. response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. correct boolean true
if the participant got the correct answer, false
otherwise."},{"location":"plugins/categorize-image/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-categorize-image@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-categorize-image.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-categorize-image\n
import categorizeImage from '@jspsych/plugin-categorize-image';\n
"},{"location":"plugins/categorize-image/#examples","title":"Examples","text":"Categorizing an image CodeDemo var categorization_trial = {\n type: jsPsychCategorizeImage,\n stimulus: 'img/blue.png',\n key_answer: 'b',\n text_answer: 'Blue',\n choices: ['r', 'g', 'b'],\n correct_text: \"<p class='prompt'>Correct! The color is %ANS%.</p>\",\n incorrect_text: \"<p class='prompt'>Incorrect. The color is %ANS%.</p>\",\n prompt: \"<p>Is the color of this circle (R)ed, (G)reen, or (B)lue?</p>\"\n};\n
Open demo in new tab
"},{"location":"plugins/cloze/","title":"cloze","text":"Current version: 2.0.0. See version history.
This plugin displays a text with certain words omitted. Participants are asked to replace the missing items. Responses are recorded when clicking a button. Responses can be evaluated and a function is called in case of either differences or incomplete answers, making it possible to inform participants about mistakes before proceeding.
"},{"location":"plugins/cloze/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description text string undefined The cloze text to be displayed. Blanks are indicated by %% signs and automatically replaced by input fields. If there is a correct answer you want the system to check against, it must be typed between the two percentage signs (i.e. % correct solution %). To input multiple correct answers, add a / between each answer (i.e. %correct/alsocorrect%). button_text string OK Text of the button participants have to press for finishing the cloze test. check_answers boolean false Boolean value indicating if the answers given by participants should be compared against a correct solution given in the text (between % signs) after the button was clicked. If true
, answers are checked and in case of differences, the mistake_fn
is called. In this case, the trial does not automatically finish. If false
, no checks are performed and the trial automatically ends when clicking the button. allow_blanks boolean true Boolean value indicating if the answers given by participants should be checked for completion after the button was clicked. If true
, answers are not checked for completion and blank answers are allowed. The trial will then automatically finish upon the clicking the button. If false
, answers are checked for completion, and in case there are some fields with missing answers, the mistake_fn
is called. In this case, the trial does not automatically finish. case_sensitivity boolean true Boolean value indicating if the answers given by participants should also be checked to have the right case along with correctness. If set to false
, case is disregarded and participants may type in whatever case they please. mistake_fn function function(){}
Function called if check_answers
is set to true
and there is a difference between the participant's answers and the correct solution provided in the text, or if allow_blanks
is set to false
and there is at least one field with a blank answer. autofocus boolean true Boolean value indicating if the first input field should be focused when the trial starts. Enabled by default, but may be disabled especially if participants are using screen readers."},{"location":"plugins/cloze/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response array of strings Answers the partcipant gave"},{"location":"plugins/cloze/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-cloze@2.1.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-cloze.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-cloze\n
import cloze from '@jspsych/plugin-cloze';\n
"},{"location":"plugins/cloze/#examples","title":"Examples","text":"Simple cloze using default settings (no check against correct solution, no custom button text) CodeDemo var cloze_trial = {\n type: jsPsychCloze,\n text: 'The %% is the largest terrestrial mammal. It lives in both %% and %%.'\n };\n
Open demo in new tab
Cloze example using default settings with completion checking and custom error handling CodeDemo var cloze_trial = {\n type: jsPsychCloze,\n text: 'Science notebooks have a %%-colored front cover. Math notebooks have a %%-colored front cover.',\n allow_blanks: false,\n mistake_fn: function() { alert('Please fill in all blanks.'); }\n };\n
Open demo in new tab
More elaborate example (with check against correct solution, custom error handling and modified button text) CodeDemo var cloze_trial = {\n type: jsPsychCloze,\n text: 'A rectangle has % 4 % corners and a triangle has % 3 %.',\n check_answers: true,\n button_text: 'Next',\n mistake_fn: function (){ alert(\"Wrong answer. Please check again.\") }\n };\n
Open demo in new tab
"},{"location":"plugins/external-html/","title":"external-html","text":"Current version: 2.0.0. See version history.
The HTML plugin displays an external HTML document (often a consent form). Either a keyboard response or a button press can be used to continue to the next trial. It allows the experimenter to check if conditions are met (such as indicating informed consent) before continuing.
"},{"location":"plugins/external-html/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description url string undefined The URL of the page to display. cont_key string null The key character the participant can use to advance to the next trial. If left as null, then the participant will not be able to advance trials using the keyboard. cont_btn string null The ID of a clickable element on the page. When the element is clicked, the trial will advance. check_fn function function(){ return true; }
This function is called with the jsPsych display_element
as the only argument when the participant attempts to advance the trial. The trial will only advance if the function return true
. This can be used to verify that the participant has correctly filled out a form before continuing, for example. force_refresh boolean false If true
, then the plugin will avoid using the cached version of the HTML page to load if one exists. execute_script boolean false If true
, then scripts on the remote page will be executed."},{"location":"plugins/external-html/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value url string The URL of the page. rt numeric The response time in milliseconds for the participant to finish the trial."},{"location":"plugins/external-html/#simulation-mode","title":"Simulation Mode","text":"In visual
simulation mode, the plugin cannot interact with any form elements on the screen other than the cont_btn
specified in the trial parameters. If your check_fn
requires other user interaction, for example, clicking a checkbox, then you'll need to disable simulation for the trial and complete the interaction manually.
"},{"location":"plugins/external-html/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-external-html@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-external-html.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-external-html\n
import externalHtml from '@jspsych/plugin-external-html';\n
"},{"location":"plugins/external-html/#examples","title":"Examples","text":""},{"location":"plugins/external-html/#loading-a-consent-form","title":"Loading a consent form","text":""},{"location":"plugins/external-html/#this-content-would-be-in-a-file-called-external_pagehtml","title":"This content would be in a file called 'external_page.html'","text":"<div id=\"consent\">\n <p>\n This is a demo experiment, with this minimal consent form being loaded\n as an external html document. To continue, click the checkbox below\n and hit \"Start Experiment\".\n </p>\n <p>\n <input type=\"checkbox\" id=\"consent_checkbox\" />\n I agree to take part in this study.\n </p>\n <button type=\"button\" id=\"start\">Start Experiment</button>\n</div>\n
jsPsych code to load above page. CodeDemo // sample function that might be used to check if a participant has given\n// consent to participate.\nvar check_consent = function(elem) {\n if (document.getElementById('consent_checkbox').checked) {\n return true;\n }\n else {\n alert(\"If you wish to participate, you must check the box next to the statement 'I agree to participate in this study.'\");\n return false;\n }\n return false;\n};\n\n// declare the block.\nvar trial = {\n type: jsPsychExternalHtml,\n url: \"external_page.html\",\n cont_btn: \"start\",\n check_fn: check_consent\n};\n
Open demo in new tab
"},{"location":"plugins/free-sort/","title":"free-sort","text":"Current version: 2.0.2. See version history.
The free-sort plugin displays one or more images on the screen that the participant can interact with by clicking and dragging with a mouse, or touching and dragging with a touchscreen device. When the trial starts, the images can be positioned outside or inside the sort area. All images must be moved into the sorting area before the participant can click a button to end the trial. All of the moves that the participant performs are recorded, as well as the final positions of all images. This plugin could be useful when asking participants to position images based on similarity to one another, or to recall image spatial locations.
"},{"location":"plugins/free-sort/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimuli array undefined Each element of this array is an image path. stim_height numeric 100 The height of the images in pixels. stim_width numeric 100 The width of the images in pixels. scale_factor numeric 1.5 How much larger to make the stimulus while moving (1 = no scaling). sort_area_height numeric 800 The height of the container that participants can move the stimuli in. Stimuli will be constrained to this area. sort_area_width numeric 800 The width of the container that participants can move the stimuli in. Stimuli will be constrained to this area. sort_area_shape string \"ellipse\" The shape of the sorting area, can be \"ellipse\" or \"square\". prompt string null This string can contain HTML markup. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). prompt_location string \"above\" Indicates whether to show the prompt \"above\"
or \"below\"
the sorting area. button_label string 'Continue' The text that appears on the button to continue to the next trial. change_border_background_color boolean true If true
, the sort area border color will change while items are being moved in and out of the sort area, and the background color will change once all items have been moved into the sort area. If false
, the border will remain black and the background will remain white throughout the trial. border_color_in string '#a1d99b' If change_border_background_color
is true
, the sort area border will change to this color when an item is being moved into the sort area, and the background will change to this color when all of the items have been moved into the sort area. border_color_out string '#fc9272' If change_border_background_color
is true
, this will be the color of the sort area border when there are one or more items that still need to be moved into the sort area. border_width numeric null The width in pixels of the border around the sort area. If null
, the border width will be 3% of the sort_area_height
. counter_text_unfinished string You still need to place %n% item%s% inside the sort area. Text to display when there are one or more items that still need to be placed in the sort area. If \"%n%\" is included in the string, it will be replaced with the number of items that still need to be moved inside. If \"%s%\" is included in the string, a \"s\" will be included when the number of items remaining is greater than one. counter_text_finished string All items placed. Feel free to reposition items if necessary. Text that will take the place of the counter_text_unfinished text when all items have been moved inside the sort area. stim_starts_inside boolean false If false
, the images will be positioned to the left and right of the sort area when the trial loads. If true
, the images will be positioned at random locations inside the sort area when the trial loads. column_spread_factor numeric 1 When the images appear outside the sort area, this determines the x-axis spread of the image columns. Default value is 1. Values less than 1 will compress the image columns along the x-axis, and values greater than 1 will spread them farther apart."},{"location":"plugins/free-sort/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value init_locations array An array containing objects representing the initial locations of all the stimuli in the sorting area. Each element in the array represents a stimulus, and has a \"src\", \"x\", and \"y\" value. \"src\" is the image path, and \"x\" and \"y\" are the object location. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. moves array An array containing objects representing all of the moves the participant made when sorting. Each object represents a move. Each element in the array has a \"src\", \"x\", and \"y\" value. \"src\" is the image path, and \"x\" and \"y\" are the object location after the move. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. final_locations array An array containing objects representing the final locations of all the stimuli in the sorting area. Each element in the array represents a stimulus, and has a \"src\", \"x\", and \"y\" value. \"src\" is the image path, and \"x\" and \"y\" are the object location. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. rt numeric The response time in milliseconds for the participant to finish all sorting."},{"location":"plugins/free-sort/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/free-sort/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-free-sort@2.0.2\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-free-sort.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-free-sort\n
import freeSort from '@jspsych/plugin-free-sort';\n
"},{"location":"plugins/free-sort/#examples","title":"Examples","text":"Basic example CodeDemo var sort_trial = {\n type: jsPsychFreeSort,\n stimuli: sorting_stimuli,\n stim_width: 80,\n stim_height: 60,\n sort_area_width: 500,\n sort_area_height: 500,\n prompt: \"<p>Click and drag the images below to sort them so that similar items are close together.</p>\"\n};\n
Open demo in new tab
"},{"location":"plugins/fullscreen/","title":"fullscreen","text":"Current version: 2.0.0. See version history.
The fullscreen plugin allows the experiment to enter or exit fullscreen mode. For security reasons, all browsers require that entry into fullscreen mode is triggered by a user action. To enter fullscreen mode, this plugin has the user click a button. Exiting fullscreen mode can be done without user input.
Warning
Safari does not support keyboard input when the browser is in fullscreen mode. Therefore, the function will not launch fullscreen mode on Safari. The experiment will ignore any trials using the fullscreen plugin in Safari.
"},{"location":"plugins/fullscreen/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description fullscreen_mode boolean true
A value of true
causes the experiment to enter fullscreen mode. A value of false
causes the browser to exit fullscreen mode. message string <p>The experiment will switch to full screen mode when you press the button below</p>
The HTML content to display above the button to enter fullscreen mode. button_label string 'Continue' The text that appears on the button to enter fullscreen mode. delay_after numeric 1000 The length of time to delay after entering fullscreen mode before ending the trial. This can be useful because entering fullscreen is jarring and most browsers display some kind of message that the browser has entered fullscreen mode."},{"location":"plugins/fullscreen/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value success boolean true if the browser supports fullscreen mode (i.e., is not Safari) rt number Response time to click the button that launches fullscreen mode"},{"location":"plugins/fullscreen/#simulation-mode","title":"Simulation Mode","text":"Web browsers do not allow fullscreen mode to be triggered by a script to avoid malicious usage of fullscreen behavior when the user is not wanting it. In visual
simulation mode, the trial will run normally and the button will get a simulated click, but the display will not change. If you want the display to actually enter fullscreen mode during the simulation, you should disable simulation for the fullscreen trial and manually click the button.
"},{"location":"plugins/fullscreen/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-fullscreen@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-fullscreen.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-fullscreen\n
import fullscreen from '@jspsych/plugin-fullscreen';\n
"},{"location":"plugins/fullscreen/#examples","title":"Examples","text":"Entering and exiting fullscreen CodeDemo var enter_fullscreen = {\n type: jsPsychFullscreen,\n fullscreen_mode: true\n}\n\nvar trial_in_fullscreen = {\n type: jsPsychHtmlButtonResponse,\n stimulus: 'This trial will be in fullscreen mode.',\n choices: ['Continue']\n}\n\nvar exit_fullscreen = {\n type: jsPsychFullscreen,\n fullscreen_mode: false,\n delay_after: 0\n}\n\nvar trial_after_fullscreen = {\n type: jsPsychHtmlButtonResponse,\n stimulus: 'This trial will NOT be in fullscreen mode.',\n choices: ['Continue']\n}\n
Open demo in new tab
"},{"location":"plugins/html-audio-response/","title":"html-audio-response","text":"Current version: 2.0.0. See version history.
This plugin displays HTML content and records audio from the participant via a microphone.
In order to get access to the microphone, you need to use the initialize-microphone plugin on your timeline prior to using this plugin. Once access is granted for an experiment you do not need to get permission again.
This plugin records audio data in base 64 format. This is a text-based representation of the audio which can be coverted to various audio formats using a variety of online tools as well as in languages like python and R.
This plugin will generate a large amount of data, and you will need to be careful about how you handle this data. Even a few seconds of audio recording will add 10s of kB to jsPsych's data. Multiply this by a handful (or more) of trials, and the data objects will quickly get large. If you need to record a lot of audio, either many trials worth or just a few trials with longer responses, we recommend that you save the data to your server immediately after the trial and delete the data in jsPsych's data object. See below for an example of how to do this.
This plugin also provides the option to store the recorded audio files as Object URLs via save_audio_url: true
. This will generate a URL that is storing a copy of the recorded audio, which can be used for subsequent playback. See below for an example where the recorded audio is used as the stimulus in a subsequent trial. This feature is turned off by default because it uses a relatively large amount of memory compared to most jsPsych features. If you are running an experiment where you need this feature and you are recording lots of audio snippets, you may want to manually revoke the URLs when you no longer need them using URL.revokeObjectURL(objectURL)
.
Warning
When recording from a microphone your experiment will need to be running over https://
protocol. If you try to run the experiment locally using the file://
protocol or over http://
protocol you will not be able to access the microphone because of potential security problems.
"},{"location":"plugins/html-audio-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus HTML string undefined The HTML content to be displayed. recording_duration numeric 2000 The maximum length of the recording, in milliseconds. The default value is intentionally set low because of the potential to accidentally record very large data files if left too high. You can set this to null
to allow the participant to control the length of the recording via the done button, but be careful with this option as it can lead to crashing the browser if the participant waits too long to stop the recording. stimulus_duration numeric null How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to hidden
after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. show_done_button bool true Whether to show a button on the screen that the participant can click to finish the recording. done_button_label string 'Continue' The label for the done button. allow_playback bool false Whether to allow the participant to listen to their recording and decide whether to rerecord or not. If true
, then the participant will be shown an interface to play their recorded audio and click one of two buttons to either accept the recording or rerecord. If rerecord is selected, then stimulus will be shown again, as if the trial is starting again from the beginning. record_again_button_label string 'Record again' The label for the record again button enabled when allow_playback: true
. accept_button_label string 'Continue' The label for the accept button enabled when allow_playback: true
. save_audio_url bool false If true
, then an Object URL will be generated and stored for the recorded audio. Only set this to true
if you plan to reuse the recorded audio later in the experiment, as it is a potentially memory-intensive feature."},{"location":"plugins/html-audio-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value rt numeric The time, since the onset of the stimulus, for the participant to click the done button. If the button is not clicked (or not enabled), then rt
will be null
. response base64 string The base64-encoded audio data. stimulus string The HTML content that was displayed on the screen. estimated_stimulus_onset number This is an estimate of when the stimulus appeared relative to the start of the audio recording. The plugin is configured so that the recording should start prior to the display of the stimulus. We have not yet been able to verify the accuracy of this estimate with external measurement devices. audio_url string A URL to a copy of the audio data."},{"location":"plugins/html-audio-response/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/html-audio-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-html-audio-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-html-audio-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-html-audio-response\n
import htmlAudioResponse from '@jspsych/plugin-html-audio-response';\n
"},{"location":"plugins/html-audio-response/#examples","title":"Examples","text":"Simple spoken response to a stimulus CodeDemo var trial = {\n type: jsPsychHtmlAudioResponse,\n stimulus: `\n <p style=\"font-size:48px; color:red;\">GREEN</p>\n <p>Speak the color of the ink.</p>`,\n recording_duration: 3500\n};\n
Open demo in new tab
Allow playback and rerecording; save data to server immediately CodeDemo var trial = {\n type: jsPsychHtmlAudioResponse,\n stimulus: `\n <p>Please sing the first few seconds of a song and click the button when you are done.</p>\n `,\n recording_duration: 15000,\n allow_playback: true,\n on_finish: function(data){\n fetch('/save-my-data.php', { audio_base64: data.response })\n .then((audio_id){\n data.response = audio_id;\n });\n }\n};\n
This example assumes that there is a script on your experiment server that accepts the data called save-my-data.php
. It also assumes that the script will generate a response with an ID for the stored audio file (audio_id
). In the example, we replace the very long base64 representation of the audio file with the generated ID, which could be just a handful of characters. This would let you link files to responses in data analysis, without having to store long audio files in memory during the experiment.
Open demo in new tab
Use recorded audio as a subsequent stimulus CodeDemo var instruction = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `\n <img src='img/10.gif' style=\"width:100px; padding: 20px;\"></img>\n <p>Make up a name for this shape. When you have one in mind, click the button and then say the name aloud.</p>\n `,\n choices: ['I am ready.']\n}\n\nvar record = {\n type: jsPsychHtmlAudioResponse,\n stimulus: `\n <img src='img/10.gif' style=\"width:100px; padding: 20px;\"></img>\n <p>Recording...</p>\n `,\n recording_duration: 1500,\n save_audio_url: true\n};\n\nvar playback = {\n type: jsPsychAudioButtonResponse,\n stimulus: ()=>{\n return jsPsych.data.get().last(1).values()[0].audio_url;\n },\n prompt: '<p>Click the object the matches the spoken name.</p>',\n choices: ['img/9.gif','img/10.gif','img/11.gif','img/12.gif'],\n button_html: (choice) => `<img src=${choice} style=\"width:100px; padding: 20px;\"></img>`\n}\n
Open demo in new tab
"},{"location":"plugins/html-button-response/","title":"html-button-response","text":"Current version: 2.0.0. See version history.
This plugin displays HTML content and records responses generated by button click. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the participant has failed to respond within a fixed length of time. The button itself can be customized using HTML formatting.
"},{"location":"plugins/html-button-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus HTML string undefined The HTML content to be displayed. choices array of strings [] Labels for the buttons. Each different string in the array will generate a different button. button_html function (choice: string, choice_index: number)=>`<button class=\"jspsych-btn\">${choice}</button>
; A function that generates the HTML for each button in the choices
array. The function gets the string and index of the item in the choices
array and should return valid HTML. If you want to use different markup for each button, you can do that by using a conditional on either parameter. The default parameter returns a button element with the text label of the choice. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, the trial will wait for a response indefinitely. stimulus_duration numeric null How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to hidden
after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. button_layout string 'grid' Setting to 'grid'
will make the container element have the CSS property display: grid
and enable the use of grid_rows
and grid_columns
. Setting to 'flex'
will make the container element have the CSS property display: flex
. You can customize how the buttons are laid out by adding inline CSS in the button_html
parameter. grid_rows number 1 The number of rows in the button grid. Only applicable when button_layout
is set to 'grid'
. If null, the number of rows will be determined automatically based on the number of buttons and the number of columns. grid_columns number null The number of columns in the button grid. Only applicable when button_layout
is set to 'grid'
. If null, the number of columns will be determined automatically based on the number of buttons and the number of rows. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can set this parameter to false
to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete. enable_button_after numeric 0 How long the button will delay enabling in milliseconds."},{"location":"plugins/html-button-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. response numeric Indicates which button the participant pressed. The first button in the choices
array is 0, the second is 1, and so on. stimulus string The HTML content that was displayed on the screen."},{"location":"plugins/html-button-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-html-button-response@2.0.1\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-html-button-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-html-button-response\n
import htmlButtonResponse from '@jspsych/plugin-html-button-response';\n
"},{"location":"plugins/html-button-response/#examples","title":"Examples","text":"Displaying question until participant gives a response CodeDemo var trial = {\n type: jsPsychHtmlButtonResponse,\n stimulus: '<p style=\"font-size:48px; color:red;\">GREEN</p>',\n choices: ['Red', 'Green', 'Blue'],\n prompt: \"<p>What color is the ink?</p>\"\n};\n
Open demo in new tab
Using button_html
to generate custom buttons CodeDemo const trial = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `<div style=\"width: 600px\">\n <div style=\"width: 50px; height: 50px; background-color: red; display: inline-block\"></div>\n <div style=\"width: 50px; height: 50px; background-color: red; display: inline-block\"></div>\n <div style=\"width: 50px; height: 50px; background-color: green; display: inline-block\"></div>\n <div style=\"width: 50px; height: 50px; background-color: blue; display: inline-block\"></div>\n <div style=\"width: 50px; height: 50px; background-color: red; display: inline-block\"></div>\n <div style=\"width: 50px; height: 50px; background-color: red; display: inline-block\"></div>\n <div style=\"width: 50px; height: 50px; background-color: green; display: inline-block\"></div>\n <div style=\"width: 50px; height: 50px; background-color: blue; display: inline-block\"></div>\n <div style=\"width: 50px; height: 50px; background-color: red; display: inline-block\"></div>\n <div style=\"width: 50px; height: 50px; background-color: gray; display: inline-block\"></div>\n </div>`,\n choices: ['red', 'green', 'blue'],\n prompt: \"<p>What color should the gray block be?</p>\",\n button_html: (choice) => `<div style=\"width: 80px; height: 80px; margin: 20px; background-color: ${choice}; cursor: pointer;\"></div>`\n};\n
Open demo in new tab
"},{"location":"plugins/html-keyboard-response/","title":"html-keyboard-response","text":"Current version: 2.0.0. See version history.
This plugin displays HTML content and records responses generated with the keyboard.The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the participant has failed to respond within a fixed length of time.
"},{"location":"plugins/html-keyboard-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus HTML string undefined The string to be displayed. choices array of strings \"ALL_KEYS\"
This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., 'a'
, 'q'
, ' '
, 'Enter'
, 'ArrowDown'
) - see this page and this page (event.key column) for more examples. Any key presses that are not listed in the array will be ignored. The default value of \"ALL_KEYS\"
means that all keys will be accepted as valid responses. Specifying \"NO_KEYS\"
will mean that no responses are allowed. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). stimulus_duration numeric null How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to hidden
after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can set this parameter to false
to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete."},{"location":"plugins/html-keyboard-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. stimulus string The HTML content that was displayed on the screen."},{"location":"plugins/html-keyboard-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-html-keyboard-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-html-keyboard-response\n
import htmlKeyboardResponse from '@jspsych/plugin-html-keyboard-response';\n
"},{"location":"plugins/html-keyboard-response/#examples","title":"Examples","text":"Displaying trial until participant gives a response CodeDemo var trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<p style=\"font-size:48px; color:green;\">BLUE</p>',\n choices: ['r', 'g', 'b'],\n prompt: \"<p>Is the ink color (r)ed, (g)reen, or (b)lue?</p>\"\n};\n
Open demo in new tab
Showing a 1 second fixation cross; no response allowed CodeDemo var trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<p style=\"font-size: 48px;\">+</p>',\n choices: \"NO_KEYS\",\n trial_duration: 1000,\n}; \n
Open demo in new tab
"},{"location":"plugins/html-slider-response/","title":"html-slider-response","text":"Current version: 2.0.0. See version history.
This plugin displays HTML content and allows the participant to respond by dragging a slider.
"},{"location":"plugins/html-slider-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus HTML string undefined The string to be displayed labels array of strings [] Labels displayed at equidistant locations on the slider. For example, two labels will be placed at the ends of the slider. Three labels would place two at the ends and one in the middle. Four will place two at the ends, and the other two will be at 33% and 67% of the slider width. button_label string 'Continue' Label of the button to end the trial. min integer 0 Sets the minimum value of the slider. max integer 100 Sets the maximum value of the slider. slider_start integer 50 Sets the starting value of the slider step integer 1 Sets the step of the slider. This is the smallest amount by which the slider can change. slider_width integer null Set the width of the slider in pixels. If left null, then the width will be equal to the widest element in the display. require_movement boolean false If true, the participant must move the slider before clicking the continue button. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). stimulus_duration numeric null How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to hidden
after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can set this parameter to false
to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete."},{"location":"plugins/html-slider-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response numeric The numeric value of the slider. rt numeric The time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. stimulus string The HTML content that was displayed on the screen. slider_start numeric The starting value of the slider."},{"location":"plugins/html-slider-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-html-slider-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-html-slider-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-html-slider-response\n
import htmlSliderResponse from '@jspsych/plugin-html-slider-response';\n
"},{"location":"plugins/html-slider-response/#examples","title":"Examples","text":"Displaying question until participant moves the slider CodeDemo var trial = {\n type: jsPsychHtmlSliderResponse,\n stimulus: `<div style=\"width:500px;\">\n <p>How likely is it that team A will win this match?</p>\n <div style=\"width:240px; float: left;\">\n <p>TEAM A</p>\n <p>10 wins, 5 losses, 6 draws</p>\n </div>\n <div style=\"width:240px; float: right;\">\n <p>TEAM B</p>\n <p>6 wins, 4 losses, 11 draws</p>\n </div>\n </div>`,\n require_movement: true,\n labels: ['100% chance', '50% chance', '0% chance']\n};\n
Open demo in new tab
"},{"location":"plugins/html-video-response/","title":"html-video-response","text":"Current version: 2.0.0. See version history.
This plugin displays HTML content and records video from the participant via a webcam.
In order to get access to the camera, you need to use the initialize-camera plugin on your timeline prior to using this plugin. Once access is granted for an experiment you do not need to get permission again.
This plugin records video data in base 64 format. This is a text-based representation of the video which can be coverted to various video formats using a variety of online tools as well as in languages like python and R.
This plugin will generate a large amount of data, and you will need to be careful about how you handle this data. Even a few seconds of video recording will add 10s of kB to jsPsych's data. Multiply this by a handful (or more) of trials, and the data objects will quickly get large. If you need to record a lot of video, either many trials worth or just a few trials with longer responses, we recommend that you save the data to your server immediately after the trial and delete the data in jsPsych's data object. See below for an example of how to do this.
This plugin also provides the option to store the recorded video files as Object URLs via save_video_url: true
. This will generate a URL that stores a copy of the recorded video, which can be used for subsequent playback during the experiment. See below for an example where the recorded video is used as the stimulus in a subsequent trial. This feature is turned off by default because it uses a relatively large amount of memory compared to most jsPsych features. If you are running an experiment where you need this feature and you are recording lots of video clips, you may want to manually revoke the URLs when you no longer need them using URL.revokeObjectURL(objectURL)
.
Warning
When recording from a camera your experiment will need to be running over https://
protocol. If you try to run the experiment locally using the file://
protocol or over http://
protocol you will not be able to access the camera because of potential security problems.
"},{"location":"plugins/html-video-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus HTML string undefined The HTML content to be displayed. recording_duration numeric 2000 The maximum length of the recording, in milliseconds. The default value is intentionally set low because of the potential to accidentally record very large data files if left too high. You can set this to null
to allow the participant to control the length of the recording via the done button, but be careful with this option as it can lead to crashing the browser if the participant waits too long to stop the recording. stimulus_duration numeric null How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to hidden
after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. show_done_button bool true Whether to show a button on the screen that the participant can click to finish the recording. done_button_label string 'Continue' The label for the done button. allow_playback bool false Whether to allow the participant to listen to their recording and decide whether to rerecord or not. If true
, then the participant will be shown an interface to play their recorded video and click one of two buttons to either accept the recording or rerecord. If rerecord is selected, then stimulus will be shown again, as if the trial is starting again from the beginning. record_again_button_label string 'Record again' The label for the record again button enabled when allow_playback: true
. accept_button_label string 'Continue' The label for the accept button enabled when allow_playback: true
. save_video_url bool false If true
, then an Object URL will be generated and stored for the recorded video. Only set this to true
if you plan to reuse the recorded video later in the experiment, as it is a potentially memory-intensive feature."},{"location":"plugins/html-video-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value rt numeric The time, since the onset of the stimulus, for the participant to click the done button. If the button is not clicked (or not enabled), then rt
will be null
. response base64 string The base64-encoded video data. stimulus string The HTML content that was displayed on the screen. video_url string A URL to a copy of the video data."},{"location":"plugins/html-video-response/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/html-video-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-html-video-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-html-video-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-html-video-response\n
import htmlVideoResponse from '@jspsych/plugin-html-video-response';\n
"},{"location":"plugins/html-video-response/#examples","title":"Examples","text":"Simple recorded response to a stimulus CodeDemo var init_camera = {\n type: jsPsychInitializeCamera\n}\n\nvar trial = {\n type: jsPsychHtmlVideoResponse,\n stimulus: `\n <p style=\"font-size:48px; color:red;\"> <-- </p>\n <p>Turn your head in the direction of the arrow</p>`,\n recording_duration: 3500,\n show_done_button: false,\n};\n
Open demo in new tab
Allow playback and rerecording CodeDemo var init_camera = {\n type: jsPsychInitializeCamera\n}\n\nvar trial = {\n type: jsPsychHtmlVideoResponse,\n stimulus: `<p>Make a sad face</p>`,\n recording_duration: 3500,\n show_done_button: false,\n allow_playback: true\n};\n
Open demo in new tab
Use recorded video as a subsequent stimulus CodeDemo var init_camera = {\n type: jsPsychInitializeCamera\n}\n\nvar record = {\n type: jsPsychHtmlVideoResponse,\n stimulus: `<p>Make a sad face.</p>`,\n recording_duration: 1500,\n show_done_button: false,\n save_video_url: true\n};\n\nvar classify = {\n type: jsPsychVideoButtonResponse,\n stimulus: () => {\n return [jsPsych.data.get().last(1).values()[0].video_url];\n },\n choices: [\"Happy\", \"Sad\", \"Angry\", \"Surprised\"],\n prompt: \"<p>What emotion is this?</p>\",\n}\n
Open demo in new tab
"},{"location":"plugins/iat-html/","title":"iat-html","text":"Current version: 2.0.0. See version history.
This plugin runs a single trial of the implicit association test (IAT), using HTML content as the stimulus.
"},{"location":"plugins/iat-html/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus string undefined The HTML-formatted stimulus to display. html_when_wrong string <span style=\"color: red; font-size: 80px\">X</span>
The content to display when a user presses the wrong key. bottom_instructions string <p>If you press the wrong key, a red X will appear. Press any key to continue.</p>
Instructions about making a wrong key press and whether another key press is needed to continue. force_correct_key_press boolean false If this is true
and the user presses the wrong key then they have to press the other key to continue. An example would be two keys 'e' and 'i'. If the key associated with the stimulus is 'e' and key 'i' was pressed, then pressing 'e' is needed to continue the trial. When this is true
, then parameter key_to_move_forward
is not used. display_feedback boolean false If true
, then html_when_wrong
and wrong_image_name
is required. If false
, trial_duration
is needed and trial will continue automatically. left_category_key string 'e' Key press that is associated with the left_category_label
. right_category_key string 'i' Key press that is associated with the right_category_label
. left_category_label string ['left'] An array that contains the words/labels associated with a certain stimulus. The labels are aligned to the left side of the page. right_category_label string ['right'] An array that contains the words/labels associated with a certain stimulus. The labels are aligned to the right side of the page. stim_key_association string undefined Either 'left' or 'right'. This indicates whether the stimulus is associated with the key press and category on the left or right side of the page (left_category_key
or right_category_key
). key_to_move_forward array of strings \"ALL_KEYS\" This array contains the characters the participant is allowed to press to move on to the next trial if their key press was incorrect and feedback was displayed. Can also have 'other key' as an option which will only allow the user to select the right key to move forward. trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null
for the trial and the trial will end. If the value of this parameter is null
, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can use this parameter to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete."},{"location":"plugins/iat-html/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value stimulus string Either the path to the image file or the string containing the HTML-formatted content that the participant saw on this trial. response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. correct boolean Boolean indicating whether the user's key press was correct or incorrect for the given stimulus."},{"location":"plugins/iat-html/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-iat-html@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-iat-html.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-iat-html\n
import iatHtml from '@jspsych/plugin-iat-html';\n
"},{"location":"plugins/iat-html/#examples","title":"Examples","text":"Displaying IAT question using html CodeDemo var trial = {\n type: jsPsychIatHtml,\n stimulus: 'Joyous',\n stim_key_association: 'left',\n html_when_wrong: '<span style=\"color: red; font-size: 80px\">X</span>',\n bottom_instructions: '<p>If you press the wrong key, a red X will appear. Press the other key to continue</p>',\n force_correct_key_press: true,\n display_feedback: true,\n trial_duration: 3000, //Only if display_feedback is false\n left_category_key: 'e',\n right_category_key: 'i',\n left_category_label: ['OLD','GOOD'],\n right_category_label: ['YOUNG','BAD'],\n response_ends_trial: true\n}\n
Open demo in new tab
"},{"location":"plugins/iat-image/","title":"iat-image","text":"Current version: 2.0.0. See version history.
This plugin runs a single trial of the implicit association test (IAT), using an image as the stimulus.
"},{"location":"plugins/iat-image/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus string undefined The stimulus to display. The path to an image. html_when_wrong string <span style=\"color: red; font-size: 80px\">X</span>
The HTML to display when a user presses the wrong key. bottom_instructions string <p>If you press the wrong key, a red X will appear. Press any key to continue.</p>
Instructions about making a wrong key press and whether another key press is needed to continue. force_correct_key_press boolean false If this is true
and the user presses the wrong key then they have to press the other key to continue. An example would be two keys 'e' and 'i'. If the key associated with the stimulus is 'e' and key 'i' was pressed, then pressing 'e' is needed to continue the trial. When this is true
, then parameter key_to_move_forward
is not used. display_feedback boolean false If true
, then image_when_wrong
and wrong_image_name
are required. If false
, trial_duration
is needed and trial will continue automatically. left_category_key string 'e' Key press that is associated with the left_category_label
. right_category_key string 'i' Key press that is associated with the right_category_label
. left_category_label string ['left'] An array that contains the words/labels associated with a certain stimulus. The labels are aligned to the left side of the page. right_category_label string ['right'] An array that contains the words/labels associated with a certain stimulus. The labels are aligned to the right side of the page. stim_key_association string 'undefined' Either 'left' or 'right'. This indicates whether the stimulus is associated with the key press and category on the left or right side of the page (left_category_key
or right_category_key
). key_to_move_forward array of characters \"ALL_KEYS\" This array contains the characters the participant is allowed to press to move on to the next trial if their key press was incorrect and feedback was displayed. Can also have 'other key' as an option which will only allow the user to select the right key to move forward. trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null
for the trial and the trial will end. If the value of this parameter is null
, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can use this parameter to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete."},{"location":"plugins/iat-image/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value stimulus string Either the path to the image file or the string containing the HTML-formatted content that the participant saw on this trial. response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. correct boolean Boolean indicating whether the user's key press was correct or incorrect for the given image."},{"location":"plugins/iat-image/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-iat-image@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-iat-image.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-iat-image\n
import iatImage from '@jspsych/plugin-iat-image';\n
"},{"location":"plugins/iat-image/#examples","title":"Examples","text":"Displaying IAT question using image files CodeDemo var trial_block = {\n type: jsPsychIatImage,\n stimulus: 'img/iat_old_face.jpg',\n stim_key_association: 'left',\n html_when_wrong: '<span style=\"color: red; font-size: 80px\">X</span>',\n bottom_instructions: '<p>If you press the wrong key, a red X will appear. Press the other key to continue</p>',\n force_correct_key_press: true,\n display_feedback: true,\n trial_duration: 3000, //Only if display_feedback is false\n left_category_key: 'e',\n right_category_key: 'i',\n left_category_label: ['OLD','GOOD'],\n right_category_label: ['YOUNG','BAD'],\n response_ends_trial: true\n}\n
Open demo in new tab
"},{"location":"plugins/image-button-response/","title":"image-button-response","text":"Current version: 2.0.0. See version history.
This plugin displays an image and records responses generated with a button click. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the participant has failed to respond within a fixed length of time. The button itself can be customized using HTML formatting.
Image files can be automatically preloaded by jsPsych using the preload
plugin. However, if you are using timeline variables or another dynamic method to specify the image stimulus, you will need to manually preload the images.
"},{"location":"plugins/image-button-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus string undefined The path of the image file to be displayed. stimulus_height integer null Set the height of the image in pixels. If left null (no value specified), then the image will display at its natural height. stimulus_width integer null Set the width of the image in pixels. If left null (no value specified), then the image will display at its natural width. maintain_aspect_ratio boolean true If setting only the width or only the height and this parameter is true, then the other dimension will be scaled to maintain the image's aspect ratio. choices array of strings [] Labels for the buttons. Each different string in the array will generate a different button. button_html function (choice: string, choice_index: number)=>`<button class=\"jspsych-btn\">${choice}</button>
; A function that generates the HTML for each button in the choices
array. The function gets the string and index of the item in the choices
array and should return valid HTML. If you want to use different markup for each button, you can do that by using a conditional on either parameter. The default parameter returns a button element with the text label of the choice. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). stimulus_duration numeric null How long to show the stimulus for in milliseconds. If the value is null, then the stimulus will be shown until the participant makes a response. trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, the trial will wait for a response indefinitely. button_layout string 'grid' Setting to 'grid'
will make the container element have the CSS property display: grid
and enable the use of grid_rows
and grid_columns
. Setting to 'flex'
will make the container element have the CSS property display: flex
. You can customize how the buttons are laid out by adding inline CSS in the button_html
parameter. grid_rows number 1 The number of rows in the button grid. Only applicable when button_layout
is set to 'grid'
. If null, the number of rows will be determined automatically based on the number of buttons and the number of columns. grid_columns number null The number of columns in the button grid. Only applicable when button_layout
is set to 'grid'
. If null, the number of columns will be determined automatically based on the number of buttons and the number of rows. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can set this parameter to false
to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete. render_on_canvas boolean true If true, the image will be drawn onto a canvas element. This prevents a blank screen (white flash) between consecutive image trials in some browsers, like Firefox and Edge. If false, the image will be shown via an img element, as in previous versions of jsPsych. If the stimulus is an animated gif, you must set this parameter to false, because the canvas rendering method will only present static images. enable_button_after numeric 0 How long the button will delay enabling in milliseconds."},{"location":"plugins/image-button-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. response numeric Indicates which button the participant pressed. The first button in the choices
array is 0, the second is 1, and so on. stimulus string The path of the image that was displayed."},{"location":"plugins/image-button-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-image-button-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-image-button-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-image-button-response\n
import imageButtonResponse from '@jspsych/plugin-image-button-response';\n
"},{"location":"plugins/image-button-response/#examples","title":"Examples","text":"Displaying question until participant gives a response CodeDemo var trial = {\n type: jsPsychImageButtonResponse,\n stimulus: 'img/happy_face_1.png',\n choices: ['Happy', 'Sad'],\n prompt: \"<p>Is this person happy or sad?</p>\"\n};\n
Open demo in new tab
"},{"location":"plugins/image-keyboard-response/","title":"image-keyboard-response","text":"Current version: 2.0.0. See version history.
This plugin displays an image and records responses generated with the keyboard. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the participant has failed to respond within a fixed length of time.
Image files can be automatically preloaded by jsPsych using the preload
plugin. However, if you are using timeline variables or another dynamic method to specify the image stimulus, you will need to manually preload the images.
"},{"location":"plugins/image-keyboard-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus string undefined The path of the image file to be displayed. stimulus_height integer null Set the height of the image in pixels. If left null (no value specified), then the image will display at its natural height. stimulus_width integer null Set the width of the image in pixels. If left null (no value specified), then the image will display at its natural width. maintain_aspect_ratio boolean true If setting only the width or only the height and this parameter is true, then the other dimension will be scaled to maintain the image's aspect ratio. choices array of strings \"ALL_KEYS\"
This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., 'a'
, 'q'
, ' '
, 'Enter'
, 'ArrowDown'
) - see this page and this page (event.key column) for more examples. Any key presses that are not listed in the array will be ignored. The default value of \"ALL_KEYS\"
means that all keys will be accepted as valid responses. Specifying \"NO_KEYS\"
will mean that no responses are allowed. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). stimulus_duration numeric null How long to show the stimulus for in milliseconds. If the value is null
, then the stimulus will be shown until the participant makes a response. trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null
, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can set this parameter to false
to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete. render_on_canvas boolean true If true
, the image will be drawn onto a canvas element. This prevents a blank screen (white flash) between consecutive image trials in some browsers, like Firefox and Edge. If false
, the image will be shown via an img element, as in previous versions of jsPsych. If the stimulus is an animated gif, you must set this parameter to false, because the canvas rendering method will only present static images."},{"location":"plugins/image-keyboard-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. stimulus string The path of the image that was displayed."},{"location":"plugins/image-keyboard-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-image-keyboard-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-image-keyboard-response\n
import imageKeyboardResponse from '@jspsych/plugin-image-keyboard-response';\n
"},{"location":"plugins/image-keyboard-response/#examples","title":"Examples","text":"Displaying trial until participant gives a response CodeDemo var trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/happy_face_1.png',\n choices: ['e', 'i'],\n prompt: \"<p>Is this person happy or sad? Press 'e' for happy and 'i' for sad.</p>\",\n};\n
Open demo in new tab
Displaying image for a fixed duration; no response allowed CodeDemo var trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/happy_face_1.png',\n choices: \"NO_KEYS\",\n prompt: \"<p>Study this face for 5 seconds.</p>\",\n trial_duration: 5000\n};\n
Open demo in new tab
"},{"location":"plugins/image-slider-response/","title":"image-slider-response","text":"Current version: 2.0.0. See version history.
This plugin displays and image and allows the participant to respond by dragging a slider.
Image files can be automatically preloaded by jsPsych using the preload
plugin. However, if you are using timeline variables or another dynamic method to specify the image stimulus, you will need to manually preload the images.
"},{"location":"plugins/image-slider-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus string undefined The path to the image file to be displayed. stimulus_height integer null Set the height of the image in pixels. If left null (no value specified), then the image will display at its natural height. stimulus_width integer null Set the width of the image in pixels. If left null (no value specified), then the image will display at its natural width. maintain_aspect_ration boolean true If setting only the width or only the height and this parameter is true, then the other dimension will be scaled to maintain the image's aspect ratio. labels array of strings [] Labels displayed at equidistant locations on the slider. For example, two labels will be placed at the ends of the slider. Three labels would place two at the ends and one in the middle. Four will place two at the ends, and the other two will be at 33% and 67% of the slider width. button_label string 'Continue' Label of the button to advance/submit min integer 0 Sets the minimum value of the slider max integer 100 Sets the maximum value of the slider slider_start integer 50 Sets the starting value of the slider step integer 1 Sets the step of the slider slider_width integer null Set the width of the slider in pixels. If left null, then the width will be equal to the widest element in the display. require_movement boolean false If true, the participant must move the slider before clicking the continue button. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). stimulus_duration numeric null How long to show the stimulus for in milliseconds. If the value is null, then the stimulus will be shown until the participant makes a response. trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can set this parameter to false
to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete. render_on_canvas boolean true If true, the image will be drawn onto a canvas element. This prevents a blank screen (white flash) between consecutive image trials in some browsers, like Firefox and Edge. If false, the image will be shown via an img element, as in previous versions of jsPsych. If the stimulus is an animated gif, you must set this parameter to false, because the canvas rendering method will only present static images."},{"location":"plugins/image-slider-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response numeric The numeric value of the slider. rt numeric The time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. stimulus string The path of the image that was displayed. slider_start numeric The starting value of the slider."},{"location":"plugins/image-slider-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-image-slider-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-image-slider-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-image-slider-response\n
import imageSliderResponse from '@jspsych/plugin-image-slider-response';\n
"},{"location":"plugins/image-slider-response/#examples","title":"Examples","text":"Displaying trial until participant gives a response CodeDemo var trial = {\n type: jsPsychImageSliderResponse,\n stimulus: 'img/happy_face_1.png',\n labels: ['happy', 'sad'],\n prompt: \"<p>How happy/sad is this person?</p>\",\n};\n
Open demo in new tab
"},{"location":"plugins/initialize-camera/","title":"initialize-camera","text":"Current version: 1.0.0 See version history.
This plugin asks the participant to grant permission to access a camera. If multiple cameras are connected to the participant's device, then it allows the participant to pick which device to use. Once access is granted for an experiment you do not need to get permission again.
Once the camera is selected with this plugin it can be accessed with jsPsych.pluginAPI.getCameraRecorder()
.
Warning
When recording from a camera your experiment will need to be running over https://
protocol. If you try to run the experiment locally using the file://
protocol or over http://
protocol you will not be able to access the microphone because of potential security problems.
"},{"location":"plugins/initialize-camera/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description device_select_message html string <p>Please select the camera you would like to use.</p>
The message to display when the user is presented with a dropdown list of available devices. button_label sting 'Use this camera.' The label for the select button. include_audio bool false Set to true
to include an audio track in the recordings. width int null Request a specific width for the recording. This is not a guarantee that this width will be used, as it depends on the capabilities of the participant's device. Learn more about MediaRecorder
constraints here. height int null Request a specific height for the recording. This is not a guarantee that this height will be used, as it depends on the capabilities of the participant's device. Learn more about MediaRecorder
constraints here. mime_type string null Set this to use a specific MIME type for the recording. Set the entire type, e.g., 'video/mp4; codecs=\"avc1.424028, mp4a.40.2\"'
."},{"location":"plugins/initialize-camera/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value device_id string The device ID of the selected camera."},{"location":"plugins/initialize-camera/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/initialize-camera/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-initialize-camera@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-initialize-camera.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-initialize-camera\n
import initializeCamera from '@jspsych/plugin-initialize-camera';\n
"},{"location":"plugins/initialize-camera/#examples","title":"Examples","text":"Ask for camera permission CodeDemo var trial = {\n type: jsPsychInitializeCamera\n};\n
Open demo in new tab
"},{"location":"plugins/initialize-microphone/","title":"initialize-microphone","text":"Current version: 2.0.0. See version history.
This plugin asks the participant to grant permission to access a microphone. If multiple microphones are connected to the participant's device, then it allows the participant to pick which device to use. Once access is granted for an experiment you do not need to get permission again.
Once the microphone is selected with this plugin it can be accessed with jsPsych.pluginAPI.getMicrophoneRecorder()
.
Warning
When recording from a microphone your experiment will need to be running over https://
protocol. If you try to run the experiment locally using the file://
protocol or over http://
protocol you will not be able to access the microphone because of potential security problems.
"},{"location":"plugins/initialize-microphone/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description device_select_message html string <p>Please select the microphone you would like to use.</p>
The message to display when the user is presented with a dropdown list of available devices. button_label sting 'Use this microphone.' The label for the select button."},{"location":"plugins/initialize-microphone/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value device_id string The device ID of the selected microphone."},{"location":"plugins/initialize-microphone/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/initialize-microphone/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-initialize-microphone@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-initialize-microphone.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-initialize-microphone\n
import initializeMicrophone from '@jspsych/plugin-initialize-microphone';\n
"},{"location":"plugins/initialize-microphone/#examples","title":"Examples","text":"Ask for microphone permission CodeDemo var trial = {\n type: jsPsychInitializeMicrophone\n};\n
Open demo in new tab
"},{"location":"plugins/instructions/","title":"instructions","text":"Current version: 2.0.1. See version history.
This plugin is for showing instructions to the participant. It allows participants to navigate through multiple pages of instructions at their own pace, recording how long the participant spends on each page. Navigation can be done using the mouse or keyboard. participants can be allowed to navigate forwards and backwards through pages, if desired.
"},{"location":"plugins/instructions/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description pages array undefined Each element of the array is the content for a single page. Each page should be an HTML-formatted string. key_forward string 'ArrowRight' This is the key that the participant can press in order to advance to the next page. This key should be specified as a string (e.g., 'a'
, 'ArrowLeft'
, ' '
, 'Enter'
). key_backward string 'ArrowLeft' This is the key that the participant can press to return to the previous page. This key should be specified as a string (e.g., 'a'
, 'ArrowLeft'
, ' '
, 'Enter'
). allow_backward boolean true If true, the participant can return to previous pages of the instructions. If false, they may only advace to the next page. allow_keys boolean true If true
, the participant can use keyboard keys to navigate the pages. If false
, they may not. show_clickable_nav boolean false If true, then a Previous
and Next
button will be displayed beneath the instructions. Participants can click the buttons to navigate. button_label_previous string 'Previous' The text that appears on the button to go backwards. button_label_next string 'Next' The text that appears on the button to go forwards. show_page_number boolean false If true, and clickable navigation is enabled, then Page x/y will be shown between the nav buttons. page_label string 'Page' The text that appears before x/y pages displayed when show_page_number is true. on_page_change function function (current_page) {}
The function that is called every time the page changes. This function receives a single argument current_page
, which is the index of the current page after page change, and starts at 0
. The function is also called when going forward from the last page, i.e., finishing the trial."},{"location":"plugins/instructions/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value view_history array An array containing the order of pages the participant viewed (including when the participant returned to previous pages) and the time spent viewing each page. Each object in the array represents a single page view, and contains keys called page_index
(the page number, starting with 0) and viewing_time
(duration of the page view). This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. rt numeric The response time in milliseconds for the participant to view all of the pages."},{"location":"plugins/instructions/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-instructions@2.0.1\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-instructions.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-instructions\n
import instructions from '@jspsych/plugin-instructions';\n
"},{"location":"plugins/instructions/#examples","title":"Examples","text":""},{"location":"plugins/instructions/#showing-simple-text-instructions","title":"Showing simple text instructions","text":"Showing simple text instructions CodeDemo var trial = {\n type: jsPsychInstructions,\n pages: [\n 'Welcome to the experiment. Click next to begin.',\n 'This is the second page of instructions.',\n 'This is the final page.'\n ],\n show_clickable_nav: true\n}\n
Open demo in new tab
"},{"location":"plugins/instructions/#including-images","title":"Including images","text":"Including Images CodeDemo var trial = {\n type: jsPsychInstructions,\n pages: [\n 'Welcome to the experiment. Click next to begin.',\n 'You will be looking at images of arrows: ' +\n '<br>' + \n '<img src=\"con2.png\"></img>'\n ],\n show_clickable_nav: true\n}\n
Open demo in new tab
"},{"location":"plugins/instructions/#changing-button-text","title":"Changing Button Text","text":"Changing Button Text CodeDemo var trial = {\n type: jsPsychInstructions,\n pages: [\n 'Welcome to the experiment. Click next to begin.',\n 'This is the second page of instructions.',\n 'This is the final page.'\n ],\n button_label_next: \"Continue\",\n button_label_previous: \"Return to the dark side\",\n show_clickable_nav: true\n}\n
Open demo in new tab
"},{"location":"plugins/list-of-plugins/","title":"List of Plugins","text":"These are the plugins that are included in the jsPsych release.
Additional plugins may be available in the community contributions repository.
For an overview of what plugins are and how they work, see our plugins overview.
Plugin Description animation Shows a sequence of images at a specified frame rate. Records key presses (including timing information) made by the participant while they are viewing the animation. audio\u2011button\u2011response Play an audio file and allow the participant to respond by choosing a button to click. The button can be customized extensively, e.g., using images in place of standard buttons. audio\u2011keyboard\u2011response Play an audio file and allow the participant to respond by pressing a key. audio\u2011slider\u2011response Play an audio file and allow the participant to respond by moving a slider to indicate a value. browser\u2011check Measures various features of the participant's browser and runs an inclusion check to see if the browser meets a custom set of criteria for running the study. call\u2011function Executes an arbitrary function call. Doesn't display anything to the participant, and the participant is usually unaware that this plugin has even executed. It's useful for performing tasks at specified times in the experiment, such as saving data. canvas\u2011button\u2011response Draw a stimulus on a HTML canvas element, and record a button click response. Useful for displaying dynamic, parametrically-defined graphics, and for controlling the positioning of multiple graphical elements (shapes, text, images). canvas\u2011keyboard\u2011response Draw a stimulus on a HTML canvas element, and record a key press response. Useful for displaying dynamic, parametrically-defined graphics, and for controlling the positioning of multiple graphical elements (shapes, text, images). canvas\u2011slider\u2011response Draw a stimulus on a HTML canvas element, and ask the participant to respond by moving a slider to indicate a value. Useful for displaying dynamic, parametrically-defined graphics, and for controlling the positioning of multiple graphical elements (shapes, text, images). categorize\u2011animation The participant responds to an animation and can be given feedback about their response. categorize\u2011html The participant responds to an HTML-formatted stimulus using the keyboard and can be given feedback about the correctness of their response. categorize\u2011image The participant responds to an image using the keyboard and can be given feedback about the correctness of their response. cloze Plugin for displaying a cloze test and checking participants answers against a correct solution. external\u2011html Displays an external HTML page (such as a consent form) and lets the participant respond by clicking a button or pressing a key. Plugin can validate their response, which is useful for making sure that a participant has granted consent before starting the experiment. free\u2011sort Displays a set of images on the screen in random locations. Participants can click and drag the images to move them around the screen. Records all the moves made by the participant, so the sequence of moves can be recovered from the data. fullscreen Toggles the experiment in and out of fullscreen mode. html\u2011audio\u2011response Display an HTML-formatted stimulus and records an audio response via a microphone. html\u2011button\u2011response Display an HTML-formatted stimulus and allow the participant to respond by choosing a button to click. The button can be customized extensively, e.g., using images in place of standard buttons. html\u2011keyboard\u2011response Display an HTML-formatted stimulus and allow the participant to respond by pressing a key. html\u2011slider\u2011response Display an HTML-formatted stimulus and allow the participant to respond by moving a slider to indicate a value. html\u2011video\u2011response Display an HTML-formatted stimulus and records video data via a webcam. iat\u2011html The implicit association task, using HTML-formatted stimuli. iat\u2011image The implicit association task, using images as stimuli. image\u2011button\u2011response Display an image and allow the participant to respond by choosing a button to click. The button can be customized extensively, e.g., using images in place of standard buttons. image\u2011keyboard\u2011response Display an image and allow the participant to respond by pressing a key. image\u2011slider\u2011response Display an image and allow the participant to respond by moving a slider to indicate a value. initialize\u2011camera Request permission to use the participant's camera to record video and allows the participant to choose which camera to use if multiple devices are enabled. Also allows setting the mime type of the recorded video. initialize\u2011microphone Request permission to use the participant's microphone to record audio and allows the participant to choose which microphone to use if multiple devices are enabled. instructions For displaying instructions to the participant. Allows the participant to navigate between pages of instructions using keys or buttons. maxdiff Displays rows of alternatives to be selected for two mutually-exclusive categories, typically as 'most' or 'least' on a particular criteria (e.g. importance, preference, similarity). The participant responds by selecting one radio button corresponding to an alternative in both the left and right response columns. mirror\u2011camera Shows a live feed of the participant's camera on the screen. preload This plugin loads images, audio, and video files into the browser's memory before they are needed in the experiment, in order to improve stimulus and response timing, and to avoid disrupting the flow of the experiment. reconstruction The participant interacts with a stimulus by modifying a parameter of the stimulus and observing the change in the stimulus in real-time. resize Calibrate the display so that materials display with a known physical size. same\u2011different\u2011html A same-different judgment task. An HTML-formatted stimulus is shown, followed by a brief gap, and then another stimulus is shown. The participant indicates whether the stimuli are the same or different. same\u2011different\u2011image A same-different judgment task. An image is shown, followed by a brief gap, and then another stimulus is shown. The participant indicates whether the stimuli are the same or different. serial\u2011reaction\u2011time A set of boxes are displayed on the screen and one of them changes color. The participant presses a key that corresponds to the different color box as fast as possible. serial\u2011reaction\u2011time\u2011mouse A set of boxes are displayed on the screen and one of them changes color. The participants clicks the box that changed color as fast as possible. sketchpad Creates an interactive canvas that the participant can draw on using their mouse or touchscreen. survey\u2011html\u2011form Renders a custom HTML form. Allows for mixing multiple kinds of form input. survey\u2011likert Displays likert-style questions. survey\u2011multi\u2011choice Displays multiple choice questions with one answer allowed per question. survey\u2011multi\u2011select Displays multiple choice questions with multiple answes allowed per question. survey\u2011text Shows a prompt with a text box. The participant writes a response and then submits by clicking a button. video\u2011button\u2011response Displays a video file with many options for customizing playback. participant responds to the video by pressing a button. video\u2011keyboard\u2011response Displays a video file with many options for customizing playback. participant responds to the video by pressing a key. video\u2011slider\u2011response Displays a video file with many options for customizing playback. participant responds to the video by moving a slider. virtual\u2011chinrest An implementation of the \"virutal chinrest\" procedure developed by Li, Joo, Yeatman, and Reinecke (2020). Calibrates the monitor to display items at a known physical size by having participants scale an image to be the same size as a physical credit card. Then uses a blind spot task to estimate the distance between the participant and the display. visual\u2011search\u2011circle A customizable visual-search task modelled after Wang, Cavanagh, & Green (1994). The participant indicates whether or not a target is present among a set of distractors. The stimuli are displayed in a circle, evenly-spaced, equidistant from a fixation point. webgazer\u2011calibrate Calibrates the WebGazer extension for eye tracking. webgazer\u2011init\u2011camera Initializes the camera and helps the participant center their face for eye tracking. webgazer\u2011validate Performs validation to measure precision and accuracy of WebGazer eye tracking predictions."},{"location":"plugins/maxdiff/","title":"maxdiff","text":"Current version: 2.0.2. See version history.
The maxdiff plugin displays a table with rows of alternatives to be selected for two mutually-exclusive categories, typically as 'most' or 'least' on a particular criteria (e.g. importance, preference, similarity). The participant responds by selecting one radio button corresponding to an alternative in both the left and right response columns. The same alternative cannot be endorsed on both the left and right response columns (e.g. 'most' and 'least') simultaneously.
"},{"location":"plugins/maxdiff/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description alternatives array undefined An array of one or more alternatives of string type to fill the rows of the maxdiff table. If required
is true, then the array must contain two or more alternatives, so that at least one can be selected for both the left and right columns. labels array undefined An array with exactly two labels of string type to display as column headings (to the left and right of the alternatives) for responses on the criteria of interest. randomize_alternative_order boolean false
If true, the display order of alternatives
is randomly determined at the start of the trial. preamble string empty string HTML formatted string to display at the top of the page above the maxdiff table. required boolean false
If true, prevents the user from submitting the response and proceeding until a radio button in both the left and right response columns has been selected. button_label string 'Continue' Label of the button."},{"location":"plugins/maxdiff/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the maxdiff table first appears on the screen until the participant's response. labels object An object with two keys, left
and right
, containing the labels (strings) corresponding to the left and right response columns. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. response object An object with two keys, left
and right
, containing the alternatives selected on the left and right columns. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions."},{"location":"plugins/maxdiff/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-maxdiff@2.0.2\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-maxdiff.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-maxdiff\n
import maxdiff from '@jspsych/plugin-maxdiff';\n
"},{"location":"plugins/maxdiff/#examples","title":"Examples","text":"Basic example CodeDemo var maxdiff_page = {\n type: jsPsychMaxdiff,\n alternatives: ['apple', 'orange', 'pear', 'banana'],\n labels: ['Most Preferred', 'Least Preferred'],\n preamble: '<p> Please select your <b>most preferred</b> and <b>least preferred</b> fruits. </p>'\n};\n
Open demo in new tab
"},{"location":"plugins/mirror-camera/","title":"mirror-camera","text":"Current version: 1.0.0 See version history.
This plugin shows a live feed of the participant's camera. It can be useful in experiments that need to record video in order to give the participant a chance to see what is in the view of the camera.
You must initialize the camera using the initialize-camera plugin prior to running this plugin.
Warning
When recording from a camera your experiment will need to be running over https://
protocol. If you try to run the experiment locally using the file://
protocol or over http://
protocol you will not be able to access the camera because of potential security problems.
"},{"location":"plugins/mirror-camera/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description prompt html string null HTML-formatted content to display below the camera feed. width int null The width of the video playback element. If left null
then it will match the size of the recording. height int null The height of the video playback element. If left null
then it will match the size of the recording. button_label string \"Continue\" The label of the button to advance to the next trial. mirror_camera bool true Whether to mirror the video image."},{"location":"plugins/mirror-camera/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value rt int The length of time the participant viewed the video playback."},{"location":"plugins/mirror-camera/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/mirror-camera/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-mirror-camera@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-mirror-camera.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-mirror-camera\n
import mirrorCamera from '@jspsych/plugin-mirror-camera';\n
"},{"location":"plugins/mirror-camera/#examples","title":"Examples","text":"Show the camera feed CodeDemo const init_camera = {\n type: jsPsychInitializeCamera,\n}\n\nconst mirror_camera = {\n type: jsPsychMirrorCamera,\n}\n
Open demo in new tab
"},{"location":"plugins/preload/","title":"preload","text":"Current version: 2.0.0. See version history.
This plugin loads images, audio, and video files. It is used for loading files into the browser's memory before they are needed in the experiment, in order to improve stimulus and response timing, and avoid disruption to the experiment flow. We recommend using this plugin anytime you are loading media files, and especially when your experiment requires large and/or many media files. See the Media Preloading page for more information.
The preload trial will end as soon as all files have loaded successfully. The trial will end or stop with an error message when one of these two scenarios occurs (whichever comes first): (a) all files have not finished loading when the max_load_time
duration is reached, or (b) all file requests have responded with either a load or fail event, and one or more files has failed to load. The continue_after_error
parameter determines whether the trial will stop with an error message or end (allowing the experiment to continue) when preloading is not successful.
"},{"location":"plugins/preload/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. While there are no specific parameters that are required, the plugin expects to be given a set of files to load through one or more of the following parameters: auto_preload
or trials
(for automatic loading), and/or images
, audio
, video
(for manual loading). To automatically load files based on a timeline of trials, either set the auto_preload
parameter is true
(to load files based on the main timeline passed to jsPsych.run
) or use the trials
parameter to load files based on a specific subset of trials. To manually load a set of files, use the images
, audio
, and video
parameters. You can combine automatic and manual loading methods in a single preload trial.
All other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description auto_preload boolean false If true
, the plugin will preload any files that can be automatically preloaded based on the main experiment timeline that is passed to jsPsych.run
. If false
, any file(s) to be preloaded should be specified by passing a timeline array to the trials
parameter and/or an array of file paths to the images
, audio
, and/or video
parameters. Setting this parameter to false
is useful when you plan to preload your files in smaller batches throughout the experiment. trials timeline array [] An array containing one or more jsPsych trial or timeline objects. This parameter is useful when you want to automatically preload stimuli files from a specific subset of the experiment. See Creating an Experiment: The Timeline for information on constructing timelines. images array [] Array containing file paths for one or more image files to preload. This option is typically used for image files that can't be automatically preloaded from the timeline. audio array [] Array containing file paths for one or more audio files to preload. This option is typically used for audio files that can't be automatically preloaded from the timeline. video array [] Array containing file paths for one or more video files to preload. This option is typically used for video files that can't be automatically preloaded from the timeline. message HTML string null HTML-formatted message to show above the progress bar while the files are loading. If null
, then no message is shown. show_progress_bar boolean true If true
, a progress bar will be shown while the files are loading. If false
, no progress bar is shown. continue_after_error boolean false If false
, then the experiment will stop during this trial if either (a) one or more of the files fails to load, and/or (b) all files do not finish loading before the max_load_time
duration is reached. The trial will display the error_message
, as well as the detailed error messages if show_detailed_errors
is true
. If true
, the experiment will continue even if loading fails or times out, and information about loading success/failure will be stored in the trial data (see \"Data Generated\" below). error_message HTML string 'The experiment failed to load.' HTML-formatted message to be shown on the page after loading fails or times out. Only applies when continue_after_error
is false
. show_detailed_errors boolean false If true
, and if continue_after_error
is false
, then a list of detailed errors will be shown below the error_message
. This list will contain the file paths for any files that produced a loading failure, as well as a message indicating that loading timed out, if that was the case. This setting is intended to help the researcher with testing/debugging. If false
, and if continue_after_error
is false
, then only the error_message
will be shown if loading fails or times out. max_load_time numeric null Duration to wait, in milliseconds, for all files to load before loading times out. If one or more files has not finished loading within this time limit, then the trial will stop with an error (if continue_after_error
is false
), or the trial will end with information about the loading time-out in the trial data (see \"Data Generated\" below). If null
, the trial will wait indefinitely for all files to either load or produce an error. on_error function null Function to be called immediately after a file loading request has returned an error. The function receives a single argument, which is the file path that produced the error. This callback is cancelled as soon as the trial ends. See example below. on_success function null Function to be called immediately after a file has successfully loaded. The function receives a single argument, which is the file path that finished loading. This callback is cancelled as soon as the trial ends. See example below."},{"location":"plugins/preload/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value success boolean If true
, then all files loaded successfully within the max_load_time
. If false
, then one or more file requests returned a failure and/or the file loading did not complete within the max_load_time
duration. timeout boolean If true
, then the files did not finish loading within the max_load_time
duration. If false
, then the file loading did not timeout. Note that when the preload trial does not timeout (timeout: false
), it is still possible for loading to fail (success: false
). This happens if one or more files fails to load and all file requests trigger either a success or failure event before the max_load_time
duration. failed_images array One or more image file paths that produced a loading failure before the trial ended. failed_audio array One or more audio file paths that produced a loading failure before the trial ended. failed_video array One or more video file paths that produced a loading failure before the trial ended."},{"location":"plugins/preload/#simulation-mode","title":"Simulation Mode","text":"In visual
simulation mode, the plugin will run the trial as if the experiment was running normally. Specifying simulation_options.data
will not work in visual
mode.
"},{"location":"plugins/preload/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-preload@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-preload.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-preload\n
import preload from '@jspsych/plugin-preload';\n
"},{"location":"plugins/preload/#examples","title":"Examples","text":"Automatically preloading based on other trials CodeDemo var preload = {\n type: jsPsychPreload,\n auto_preload: true\n}\n\nvar trial_1 = {\n type: jsPsychImageButtonResponse,\n stimulus: 'img/happy_face_1.jpg',\n choices: ['Next']\n}\n\nvar trial_2 = {\n type: jsPsychImageButtonResponse,\n stimulus: 'img/happy_face_2.jpg',\n choices: ['Next']\n}\n\nvar trial_3 = {\n type: jsPsychImageButtonResponse,\n stimulus: 'img/happy_face_3.jpg',\n choices: ['Next']\n}\n
The stimulus
parameter from the image-button-response
trials will be automatically preloaded.
Open demo in new tab
Manually preloading an image CodeDemo var preload = {\n type: jsPsychPreload,\n images: ['img/sad_face_1.jpg']\n}\n\nvar trial_1 = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `\n <p>Study this face</p>\n <img src=\"img/sad_face_1.jpg\"></img>\n `,\n choices: ['Next']\n}\n
Because the image is embedded inside HTML from the html-button-response
plugin, it will not be automatically preloaded. Instead we can preload manually.
Open demo in new tab
Loading files in batches CodeDemo var jsPsych = initJsPsych();\n\nvar trial_1 = {\n type: jsPsychImageButtonResponse,\n stimulus: 'img/happy_face_1.jpg',\n choices: ['Next']\n}\n\nvar trial_2 = {\n type: jsPsychImageButtonResponse,\n stimulus: 'img/happy_face_2.jpg',\n choices: ['Next']\n}\n\nvar trial_3 = {\n type: jsPsychImageButtonResponse,\n stimulus: 'img/happy_face_3.jpg',\n choices: ['Next']\n}\n\nvar block_1 = {\n timeline: [trial_1, trial_2, trial_3]\n}\n\nvar trial_4 = {\n type: jsPsychImageButtonResponse,\n stimulus: 'img/sad_face_1.jpg',\n choices: ['Next']\n}\n\nvar trial_5 = {\n type: jsPsychImageButtonResponse,\n stimulus: 'img/sad_face_2.jpg',\n choices: ['Next']\n}\n\nvar trial_6 = {\n type: jsPsychImageButtonResponse,\n stimulus: 'img/sad_face_3.jpg',\n choices: ['Next']\n}\n\nvar block_2 = {\n timeline: [trial_4, trial_5, trial_6]\n}\n\nvar preload_block_1 = {\n type: jsPsychPreload,\n trials: [block_1]\n}\n\nvar preload_block_2 = {\n type: jsPsychPreload,\n trials: [block_2]\n}\n\njsPsych.run([preload_block_1, block_1, preload_block_2, block_2])\n
You can put trials using the preload
plugin throughout your experiment to distribute when files are loaded. In the example above, there are two blocks of trials and the images for each are preloaded just before the corresponding block.
Open demo in new tab
Showing a detailed error message for debugging loading issues CodeDemo var preload = {\n type: jsPsychPreload,\n images: ['img/bad_file_path.png'],\n show_detailed_errors: true\n}\n
Open demo in new tab
For more examples, see the jspsych-preload.html
file in the /examples
folder of the release and the Media Preloading documentation page.
"},{"location":"plugins/reconstruction/","title":"reconstruction","text":"Current version: 2.0.0. See version history.
This plugin allows a participant to interact with a stimulus by modifying a parameter of the stimulus and observing the change in the stimulus in real-time.
The stimulus must be defined through a function that returns an HTML-formatted string. The function should take a single value, which is the parameter that can be modified by the participant. The value can only range from 0 to 1. See the example at the bottom of the page for a sample function.
"},{"location":"plugins/reconstruction/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stim_function function undefined A function with a single parameter that returns an HTML-formatted string representing the stimulus. starting_value numeric 0.5 The starting value of the stimulus parameter. step_size numeric 0.05 The change in the stimulus parameter caused by pressing one of the modification keys. key_increase string 'h' The key to press for increasing the parameter value. key_decrease string 'g' The key to press for decreasing the parameter value. button_label string 'Continue' The text that appears on the button to finish the trial."},{"location":"plugins/reconstruction/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value start_value numeric The starting value of the stimulus parameter. final_value numeric The final value of the stimulus parameter. rt numeric The length of time, in milliseconds, that the trial lasted."},{"location":"plugins/reconstruction/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-reconstruction@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-reconstruction.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-reconstruction\n
import reconstruction from '@jspsych/plugin-reconstruction';\n
"},{"location":"plugins/reconstruction/#examples","title":"Examples","text":"Make a block larger and smaller CodeDemo var sample_function = function(param){\n var size = 50 + Math.floor(param*250);\n var html = '<div style=\"display: block; margin: auto; height: 300px; width: 300px; position: relative;\">'+\n '<div style=\"display: block; position: absolute; top: '+(150 - size/2)+'px; left:'+(150 - size/2)+'px; background-color: #000000; '+\n 'width: '+size+'px; height: '+size+'px;\"></div></div><p>Press \"h\" to make the square larger. Press \"g\" to make the square smaller.</p>'+\n '<p>When the square is the same size as the previous one, click Continue.</p>';\n return html;\n}\n\nvar match_item = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<div style=\"display: block; margin: auto; height: 300px; width: 300px; position: relative;\">'+\n '<div style=\"display: block; position: absolute; top: '+(150 - 210/2)+'px; left:'+(150 - 210/2)+'px; background-color: #000000; '+\n 'width: 210px; height: 210px;\"></div></div>',\n choices: ['c'],\n post_trial_gap: 1250,\n prompt: '<p>Study the size of this square carefully. On the next screen you will have to recreate it. When you are ready, press \"c\".</p>'\n}\n\nvar reconstruction = {\n type: jsPsychReconstruction,\n stim_function: sample_function,\n starting_value: 0.5,\n}\n
Open demo in new tab
"},{"location":"plugins/resize/","title":"resize","text":"Current version: 2.0.0. See version history.
This plugin displays a resizable div container that allows the user to drag until the container is the same size as the item being measured. Once the user measures the item as close as possible, clicking the button sets a scaling factor for the div containing jsPsych content. This causes the stimuli that follow to have a known size, independent of monitor resolution.
"},{"location":"plugins/resize/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description item_height numeric 1 The height of the item to be measured. Any units can be used as long as you are consistent with using the same units for all parameters. item_width numeric 1 The width of the item to be measured. pixels_per_unit numeric 100 After the scaling factor is applied, this many pixels will equal one unit of measurement. prompt string ''
HTML content to display below the resizable box, and above the button. button_label string 'Continue' Label to display on the button to complete calibration. starting_size numeric 100 The initial size of the box, in pixels, along the largest dimension. The aspect ratio will be set automatically to match the item width and height."},{"location":"plugins/resize/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value final_width_px numeric Final width of the resizable div container, in pixels. scale_factor numeric Scaling factor that will be applied to the div containing jsPsych content."},{"location":"plugins/resize/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/resize/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-resize@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-resize.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-resize\n
import resize from '@jspsych/plugin-resize';\n
"},{"location":"plugins/resize/#examples","title":"Examples","text":"Measuring a credit card and resizing the display to have 150 pixels equal an inch. CodeDemo var inputs = {\n type: jsPsychResize,\n item_width: 3 + 3/8,\n item_height: 2 + 1/8,\n prompt: \"<p>Click and drag the lower right corner of the box until the box is the same size as a credit card held up to the screen.</p>\",\n pixels_per_unit: 150\n};\n
Open demo in new tab
"},{"location":"plugins/same-different-html/","title":"same-different-html","text":"Current version: 2.0.0. See version history.
The same-different-html plugin displays two stimuli sequentially. Stimuli are HTML objects. The participant responds using the keyboard, and indicates whether the stimuli were the same or different. Same does not necessarily mean identical; a category judgment could be made, for example.
"},{"location":"plugins/same-different-html/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimuli array undefined A pair of stimuli, represented as an array with two entries, one for each stimulus. A stimulus is a string containing valid HTML markup. Stimuli will be shown in the order that they are defined in the array. answer string undefined Either 'same'
or 'different'
. same_key string 'q' The key that participants should press to indicate that the two stimuli are the same. different_key string 'p' The key that participants should press to indicate that the two stimuli are different. first_stim_duration numeric 1000 How long to show the first stimulus for in milliseconds. If the value of this parameter is null then the stimulus will be shown until the participant presses any key. gap_duration numeric 500 How long to show a blank screen in between the two stimuli. second_stim_duration numeric 1000 How long to show the second stimulus for in milliseconds. If the value of this parameter is null then the stimulus will be shown until the participant responds. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press)."},{"location":"plugins/same-different-html/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value stimulus array An array of length 2 containing the HTML-formatted content that the participant saw for each trial. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the second stimulus first appears on the screen until the participant's response. correct boolean true
if the participant's response matched the answer
for this trial. answer string The correct answer to the trial, either 'same'
or 'different'
. Additionally, if first_stim_duration
is null, then the following data is also collected:
Name Type Value rt_stim1 numeric The response time in milliseconds for the participant to continue after the first stimulus. The time is measured from when the first stimulus appears on the screen until the participant's response. response_stim1 string Indicates which key the participant pressed to continue."},{"location":"plugins/same-different-html/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-same-different-html@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-same-different-html.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-same-different-html\n
import sameDifferentHtml from '@jspsych/plugin-same-different-html';\n
"},{"location":"plugins/same-different-html/#examples","title":"Examples","text":"Two text choices CodeDemo var trial = {\n type: jsPsychSameDifferentHtml,\n stimuli: [\n '<p style=\"font-size:30px;\">Climbing</p>', \n '<p style=\"font-size:30px;\">Walking</p>'\n ],\n prompt: `<p>Press 's' if the activities require the same amount of physical exertion.</p>\n <p>Press 'd' if the activities require different amount of physical exertion.</p>`,\n same_key: 's',\n different_key: 'd',\n first_stim_duration: 800,\n answer: 'different'\n}\n
Open demo in new tab
"},{"location":"plugins/same-different-image/","title":"same-different-image","text":"Current version: 2.0.0. See version history.
The same-different-image plugin displays two stimuli sequentially. Stimuli are images. The participant responds using the keyboard, and indicates whether the stimuli were the same or different. Same does not necessarily mean identical; a category judgment could be made, for example.
"},{"location":"plugins/same-different-image/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimuli array undefined A pair of stimuli, represented as an array with two entries, one for each stimulus. The stimulus is a path to an image file. Stimuli will be shown in the order that they are defined in the array. answer string undefined Either 'same'
or 'different'
. same_key string 'q' The key that participants should press to indicate that the two stimuli are the same. different_key string 'p' The key that participants should press to indicate that the two stimuli are different. first_stim_duration numeric 1000 How long to show the first stimulus for in milliseconds. If the value of this parameter is null then the stimulus will be shown until the participant presses any key. gap_duration numeric 500 How long to show a blank screen in between the two stimuli. second_stim_duration numeric 1000 How long to show the second stimulus for in milliseconds. If the value of this parameter is null then the stimulus will be shown until the participant responds. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press)."},{"location":"plugins/same-different-image/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value stimulus array An array of length 2 containing the paths to the image files that the participant saw for each trial. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the second stimulus first appears on the screen until the participant's response. correct boolean true
if the participant's response matched the answer
for this trial. answer string The correct answer to the trial, either 'same'
or 'different'
. Additionally, if first_stim_duration
is null, then the following data is also collected:
Name Type Value rt_stim1 numeric The response time in milliseconds for the participant to continue after the first stimulus. The time is measured from when the first stimulus appears on the screen until the participant's response. response_stim1 string Indicates which key the participant pressed to continue."},{"location":"plugins/same-different-image/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-same-different-image@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-same-different-image.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-same-different-image\n
import sameDifferentImage from '@jspsych/plugin-same-different-image';\n
"},{"location":"plugins/same-different-image/#examples","title":"Examples","text":"Identifying emotional expressions CodeDemo var trial = {\n type: jsPsychSameDifferentImage,\n stimuli: [\n 'img/happy_face_1.jpg', \n 'img/sad_face_3.jpg'\n ],\n prompt: `<p>Press s if the faces had the same emotional expression.</p>\n <p>Press d if the faces had different emotional expressions.</p>`,\n same_key: 's',\n different_key: 'd',\n first_stim_duration: 800,\n answer: 'different'\n}\n
Open demo in new tab
"},{"location":"plugins/serial-reaction-time-mouse/","title":"serial-reaction-time-mouse","text":"Current version: 2.0.0. See version history.
The serial reaction time mouse plugin implements a generalized version of the SRT task (Nissen & Bullmer, 1987). Squares are displayed in a grid-based system on the screen, and one square changes color. The participant must click on the square that changes color.
"},{"location":"plugins/serial-reaction-time-mouse/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description target array undefined The location of the target. The array should be the [row, column]
of the target. grid array [[1,1,1,1]]
This array represents the grid of boxes shown on the screen. Each inner array represents a single row. The entries in the inner arrays represent the columns. If an entry is 1
then a square will be drawn at that location on the grid. If an entry is 0
then the corresponding location on the grid will be empty. Thus, by mixing 1
s and 0
s it is possible to create many different grid-based arrangements. grid_square_size numeric 100 The width and height in pixels of each square in the grid. target_color hex color code #999
The color of the target square. response_ends_trial boolean true
If true, the trial ends after a mouse click. Feedback is displayed if show_response_feedback
is true. pre_target_duration numeric 0 The number of milliseconds to display the grid before the target changes color. trial_duration numeric null The maximum length of time of the trial, not including feedback. fade_duration numeric null If a positive number, the target will progressively change color at the start of the trial, with the transition lasting this many milliseconds. allow_nontarget_responses boolean false If true, the user can make nontarget response. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which keys to press)."},{"location":"plugins/serial-reaction-time-mouse/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value grid array The grid representation. Each inner array represents a single row. The entries in the inner arrays represent the columns. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. target array The [row, column]
target location on the grid. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the second stimulus first appears on the screen until the participant's response. response array The [row, column]
response location on the grid. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. correct boolean Whether the response location matches the target location (true
) or not (false
)."},{"location":"plugins/serial-reaction-time-mouse/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-serial-reaction-time-mouse@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-serial-reaction-time-mouse.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-serial-reaction-time-mouse\n
import serialReactionTimeMouse from '@jspsych/plugin-serial-reaction-time-mouse';\n
"},{"location":"plugins/serial-reaction-time-mouse/#examples","title":"Examples","text":"A classic version of the SRT CodeDemo var grid = [\n [1,1,1,1]\n]\n\nvar trial_1 = {\n type: jsPsychSerialReactionTimeMouse,\n grid: grid,\n target: [0,0]\n}\nvar trial_2 = {\n type: jsPsychSerialReactionTimeMouse,\n grid: grid,\n target: [0,1]\n}\nvar trial_3 = {\n type: jsPsychSerialReactionTimeMouse,\n grid: grid,\n target: [0,2]\n}\nvar trial_4 = {\n type: jsPsychSerialReactionTimeMouse,\n grid: grid,\n target: [0,3]\n}\n
Open demo in new tab
A 2x2 grid with extra space and different colors CodeDemo var grid = [\n [1,0,1],\n [0,0,0],\n [1,0,1]\n]\n\nvar trial_1 = {\n type: jsPsychSerialReactionTimeMouse,\n grid: grid,\n target: [0,0],\n target_color: '#006738'\n}\nvar trial_2 = {\n type: jsPsychSerialReactionTimeMouse,\n grid: grid,\n target: [0,2],\n target_color: '#F78F1E'\n}\nvar trial_3 = {\n type: jsPsychSerialReactionTimeMouse,\n grid: grid,\n target: [2,2],\n target_color: '#13B24B'\n}\nvar trial_4 = {\n type: jsPsychSerialReactionTimeMouse,\n grid: grid,\n target: [2,0],\n target_color: '#E74921'\n}\n
Open demo in new tab
"},{"location":"plugins/serial-reaction-time/","title":"serial-reaction-time","text":"Current version: 2.0.0. See version history.
The serial reaction time plugin implements a generalized version of the SRT task (Nissen & Bullemer, 1987). Squares are displayed in a grid-based system on the screen, and one square changes color. The participant presses a key that corresponds to the darkened key. Feedback is optionally displayed, showing the participant which square the key they pressed matches.
"},{"location":"plugins/serial-reaction-time/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description target array undefined The location of the target. The array should be the [row, column]
of the target. grid array [[1,1,1,1]]
This array represents the grid of boxes shown on the screen. Each inner array represents a single row. The entries in the inner arrays represent the columns. If an entry is 1
then a square will be drawn at that location on the grid. If an entry is 0
then the corresponding location on the grid will be empty. Thus, by mixing 1
s and 0
s it is possible to create many different grid-based arrangements. choices array of strings [['3','5','7','9']]
The dimensions of this array must match the dimensions of grid
. Each entry in this array is the key that should be pressed for that corresponding location in the grid. Entries can be left blank if there is no key associated with that location of the grid. grid_square_size numeric 100 The width and height in pixels of each square in the grid. target_color hex color code #999
The color of the target square. response_ends_trial boolean true
If true, the trial ends after a key press. Feedback is displayed if show_response_feedback
is true. pre_target_duration numeric 0 The number of milliseconds to display the grid before the target changes color. trial_duration numeric null The maximum length of time of the trial, not including feedback. show_response_feedback boolean false If true, show feedback indicating where the user responded and whether it was correct. feedback_duration numeric 200 The length of time in milliseconds to show the feedback. fade_duration numeric null If a positive number, the target will progressively change color at the start of the trial, with the transition lasting this many milliseconds. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which keys to press)."},{"location":"plugins/serial-reaction-time/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value grid array The representation of the grid. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. target array The representation of the target location on the grid. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the second stimulus first appears on the screen until the participant's response. correct boolean true
if the participant's response matched the target."},{"location":"plugins/serial-reaction-time/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-serial-reaction-time@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-serial-reaction-time.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-serial-reaction-time\n
import serialReactionTime from '@jspsych/plugin-serial-reaction-time';\n
"},{"location":"plugins/serial-reaction-time/#examples","title":"Examples","text":"A classic SRT CodeDemo var instructions = {\n type: jsPsychHtmlButtonResponse,\n stimulus: '<p>Use the S, F, H, and K keys to respond.</p>',\n choices: ['Continue']\n}\n\nvar grid = [\n [1,1,1,1]\n]\n\nvar response_map = [\n ['s','f','h','k']\n]\n\nvar trial_1 = {\n type: jsPsychSerialReactionTime,\n grid: grid,\n choices: response_map,\n target: [0,0]\n}\nvar trial_2 = {\n type: jsPsychSerialReactionTime,\n grid: grid,\n choices: response_map,\n target: [0,1]\n}\nvar trial_3 = {\n type: jsPsychSerialReactionTime,\n grid: grid,\n choices: response_map,\n target: [0,2]\n}\nvar trial_4 = {\n type: jsPsychSerialReactionTime,\n grid: grid,\n choices: response_map,\n target: [0,3]\n}\n
Open demo in new tab
2x2 grid with feedback CodeDemo var instructions = {\n type: jsPsychHtmlButtonResponse,\n stimulus: '<p>Use the R, I, V, and M keys to respond.</p>',\n choices: ['Continue']\n}\n\nvar grid = [\n [1,1],\n [1,1]\n]\n\nvar response_map = [\n ['r','i'],\n ['v','m']\n]\n\nvar trial_1 = {\n type: jsPsychSerialReactionTime,\n grid: grid,\n choices: response_map,\n target: [0,0],\n show_response_feedback: true,\n feedback_duration: 500\n}\nvar trial_2 = {\n type: jsPsychSerialReactionTime,\n grid: grid,\n choices: response_map,\n target: [0,1],\n show_response_feedback: true,\n feedback_duration: 500\n}\nvar trial_3 = {\n type: jsPsychSerialReactionTime,\n grid: grid,\n choices: response_map,\n target: [1,1],\n show_response_feedback: true,\n feedback_duration: 500\n}\nvar trial_4 = {\n type: jsPsychSerialReactionTime,\n grid: grid,\n choices: response_map,\n target: [1,0],\n show_response_feedback: true,\n feedback_duration: 500\n}\n
Open demo in new tab
"},{"location":"plugins/sketchpad/","title":"sketchpad","text":"Current version: 2.0.2. See version history.
This plugin creates an interactive canvas that the participant can draw on using their mouse or touchscreen. It can be used for sketching tasks, like asking the participant to draw a particular object. It can also be used for some image segmentation or annotation tasks by setting the background_image
parameter to render an image on the canvas.
The plugin stores a base 64 data URL representation of the final image. This can be converted to an image file using online tools or short programs in R, python, or another language of your choice. It also records all of the individual strokes that the participant made during the trial.
Warning
This plugin generates a lot of data. Each trial can easily add 500kb+ of data to a final JSON output. You can reduce the amount of data generated by turning off storage of the individual stroke data (save_strokes: false
) or storage of the final image (save_final_image: false
) if your use case doesn't require that information. If you are going to be collecting a lot of data with this plugin you may want to save your data to your server after each trial and not wait until the end of the experiment to perform a single bulk upload. You can do this by putting data saving code inside the on_data_update
event handler.
"},{"location":"plugins/sketchpad/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters.
Parameter Type Default Value Description canvas_shape \"rectangle\"
or \"circle\"
\"rectangle\"
The shape of the canvas element. canvas_width int 500 Width of the canvas in pixels when canvas_shape
is a \"rectangle\"
. canvas_height int 500 Height of the canvas in pixels when canvas_shape
is a \"rectangle\"
. canvas_diameter int 500 Diameter of the canvas in pixels when canvas_shape
is a \"circle\"
. canvas_border_width int 0 Width of the canvas border. canvas_border_color string \"#000\"
Color of the canvas border. background_image image path null
Path to an image to render as the background of the canvas. background_color string \"#fff\"
Color of the canvas background. Note that a background_image
will render on top of the color. stroke_width int 2 Width of the stroke on the canvas. stroke_color string \"#000\"
Color of the stroke on the canvas. stroke_color_palette array of strings []
Array of colors to render as a palette of choices for stroke color. Clicking on the corresponding color button will change the stroke color. prompt string null HTML content to render on the screen. prompt_location \"abovecanvas\"
or \"belowcanvas\"
or \"belowbutton\"
\"abovecanvas\"
The location to render the prompt content. save_final_image bool true Whether to save the final image in the data as a base64 encoded data URL. save_strokes bool true Whether to save the individual stroke data that generated the final image. key_to_draw key string null If this key is held down then it is like the mouse button being held down. The \"ink\" will flow when the button is held and stop when it is lifted. Pass in the string representation of the key, e.g., 'a'
for the A key or ' '
for the spacebar. show_finished_button bool true Whether to show the button that ends the trial. finished_button_label string \"Finished\"
The label for the button that ends the trial. show_clear_button bool true Whether to show the button that clears the entire drawing. clear_button_label string \"Clear\"
The label for the button that clears the entire drawing. show_undo_button bool true Whether to show the button that enables an undo action. undo_button_label string \"Undo\"
The label for the button that enables an undo action. show_redo_button bool true Whether to show the button that enables a redo action. Note that show_undo_button
must be true
for the redo button to show up. redo_button_label string \"Redo\"
The label for the button that enables a redo action. choices array of keys \"NO_KEYS\"
This array contains the key(s) that the participant is allowed to press in order to end the trial. Keys should be specified as characters (e.g., 'a'
, 'q'
, ' '
, 'Enter'
, 'ArrowDown'
) - see this page and this page (event.key column) for more examples. Any key presses that are not listed in the array will be ignored. The default value of \"NO_KEYS\"
means that no keys will be accepted as valid responses. Specifying \"ALL_KEYS\"
will mean that all responses are allowed. trial_duration int null Length of time before the trial ends. If null
the trial will continue indefinitely (until another way of ending the trial occurs). show_countdown_trial_duration bool false Whether to show a timer that counts down until the end of the trial when trial_duration
is not null
. countdown_timer_html string '<span id=\"sketchpad-timer\"></span> remaining'
The HTML to use for rendering the countdown timer. The element with id=\"sketchpad-timer\"
will have its content replaced by a countdown timer in the format MM:SS
."},{"location":"plugins/sketchpad/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value rt int The length of time from the start of the trial to the end of the trial. response string If the trial was ended by clicking the finished button, then \"button\"
. If the trial was ended by pressing a key, then the key that was pressed. If the trial timed out, then null
. png base64 data URL string If save_final_image
is true, then this will contain the base64 encoded data URL for the image, in png format. strokes array of stroke objects If save_strokes
is true, then this will contain an array of stroke objects. Objects have an action
property that is either \"start\"
, \"move\"
, or \"end\"
. If action
is \"start\"
or \"move\"
it will have an x
and y
property that report the coordinates of the action relative to the upper-left corner of the canvas. If action
is \"start\"
then the object will also have a t
and color
property, specifying the time of the action relative to the onset of the trial (ms) and the color of the stroke. If action
is \"end\"
then it will only have a t
property."},{"location":"plugins/sketchpad/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/sketchpad/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-sketchpad@2.0.2\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-sketchpad.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-sketchpad\n
import sketchpad from '@jspsych/plugin-sketchpad';\n
"},{"location":"plugins/sketchpad/#examples","title":"Examples","text":"Basic sketchpad with a prompt CodeDemo var trial = {\n type: jsPsychSketchpad,\n prompt: '<p>Draw an apple!</p>',\n prompt_location: 'abovecanvas',\n canvas_width: 300,\n canvas_height: 300,\n canvas_border_width: 2\n}\n
Open demo in new tab
Image segmentation with different colors CodeDemo var trial = {\n type: jsPsychSketchpad,\n prompt: '<p style=\"width:380px\">Circle the mouth using red. Circle the eyes using blue.</p>',\n prompt_location: 'abovecanvas',\n stroke_color_palette: ['red', 'blue'],\n stroke_color: 'red',\n background_image: 'img/sad_face_4.jpg',\n canvas_width: 380,\n canvas_height: 252\n}\n
Open demo in new tab
Draw an image in a time limit, then display the image and ask for a label. CodeDemo var draw = {\n type: jsPsychSketchpad,\n prompt: '<p>Draw the first animal that comes to mind. You have 30 seconds!</p>',\n prompt_location: 'belowcanvas',\n trial_duration: 30000,\n show_countdown_trial_duration: true,\n}\n\nvar label = {\n type: jsPsychSurveyText,\n preamble: () => {\n var imageData = jsPsych.data.get().last(1).values()[0].png;\n return `<img src=\"${imageData}\"></img>`;\n },\n questions: [\n {prompt: 'What animal did you draw?'}\n ]\n}\n
Open demo in new tab
"},{"location":"plugins/survey-html-form/","title":"survey-html-form","text":"Current version: 2.0.0. See version history.
The survey-html-form plugin displays a set of <inputs>
from a HTML string. The type of input can be freely chosen, for a list of possible input types see the MDN page on inputs. The participant provides answers to the input fields.
"},{"location":"plugins/survey-html-form/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description html string undefined HTML formatted string containing all the input elements to display. Every element has to have its own distinctive name attribute. The <form>
tag must not be included and is generated by the plugin. This string can contain other HTML elements besides the input fields. preamble string empty string HTML formatted string to display at the top of the page above all the questions. button_label string 'Continue' The text that appears on the button to finish the trial. dataAsArray boolean false Retrieve the data as an array e.g. [{name: \"INPUT_NAME\", value: \"INPUT_VALUE\"}, ...] instead of an object e.g. {INPUT_NAME: INPUT_VALUE, ...}. This might be useful if you omit naming your inputs. autofocus string empty string The HTML element ID of a form field to autofocus on. The focused element is the element that will receive keyboard events. For elements like <input type=\"text\">
or <textbox>
, autofocus means that the cursor will appear in the text input area when the trial loads. autocomplete boolean false This determines whether or not all of the input elements on the page should allow autocomplete. Setting this to true will enable autocomplete or auto-fill for the form."},{"location":"plugins/survey-html-form/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response object An object containing the response for each input. The object will have a separate key (variable) for the response to each input, with each variable being named after its corresponding input element. Each response is a string containing whatever the participant answered for this particular input. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. rt numeric The response time in milliseconds for the participant to make a response."},{"location":"plugins/survey-html-form/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/survey-html-form/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-survey-html-form@2.0.1\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-survey-html-form.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-survey-html-form\n
import surveyHtmlForm from '@jspsych/plugin-survey-html-form';\n
"},{"location":"plugins/survey-html-form/#examples","title":"Examples","text":"Fill in the blanks CodeDemo var trial = {\n type: jsPsychSurveyHtmlForm,\n preamble: '<p>How are you feeling <b>right now?</b></p>',\n html: '<p> I am feeling <input name=\"first\" type=\"text\" />, <input name=\"second\" type=\"text\" />, and <input name=\"third\" type=\"text\" />.</p>'\n};\n
Open demo in new tab
Using the autofocus parameter CodeDemo var trial = {\n type: jsPsychSurveyHtmlForm,\n preamble: '<p>What is your favorite bird?</p>',\n html: '<p>My favorite bird is <input type=\"text\" id=\"test-resp-box\" name=\"response\" size=\"10\" /></p>',\n autofocus: 'test-resp-box'\n};\n
In this example, the browser will focus on the element with the ID test-resp-box
when the trial loads. For <input type=\"text\">
elements, this means that the cursor will appear inside the text box.
Open demo in new tab
"},{"location":"plugins/survey-likert/","title":"survey-likert","text":"Current version: 2.0.0. See version history.
The survey-likert plugin displays a set of questions with Likert scale responses. The participant responds by selecting a radio button.
"},{"location":"plugins/survey-likert/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description questions array undefined An array of objects, each object represents a question that appears on the screen. Each object contains a prompt, labels and required parameter that will be applied to the question. See examples below for further clarification.prompt
: Type string, default value is undefined. The strings are the question that will be associated with a slider. labels
: Type array, default value is undefined. Each array element is an array of strings. The innermost arrays contain a set of labels to display for an individual question. If you want to use blank responses and only label the end points or some subset of the options, just insert a blank string for the unlabeled responses.required
: Type boolean, default value is false. Makes answering questions required. name
: Name of the question. Used for storing data. If left undefined then default names (Q0
, Q1
, ...
) will be used for the questions. randomize_question_order boolean false
If true, the display order of questions
is randomly determined at the start of the trial. In the data object, Q0
will still refer to the first question in the array, regardless of where it was presented visually. preamble string empty string HTML formatted string to display at the top of the page above all the questions. scale_width numeric null The width of the likert scale in pixels. If left null
, then the width of the scale will be equal to the width of the widest content on the page. button_label string 'Continue' Label of the button. autocomplete boolean false This determines whether or not all of the input elements on the page should allow autocomplete. Setting this to true will enable autocomplete or auto-fill for the form."},{"location":"plugins/survey-likert/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response object An object containing the response for each question. The object will have a separate key (variable) for each question, with the first question in the trial being recorded in Q0
, the second in Q1
, and so on. The responses are recorded as integers, representing the position selected on the likert scale for that question. If the name
parameter is defined for the question, then the response object will use the value of name
as the key for each question. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the questions first appear on the screen until the participant's response(s) are submitted. question_order array An array with the order of questions. For example [2,0,1]
would indicate that the first question was trial.questions[2]
(the third item in the questions
parameter), the second question was trial.questions[0]
, and the final question was trial.questions[1]
. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions."},{"location":"plugins/survey-likert/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-survey-likert@2.0.1\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-survey-likert.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-survey-likert\n
import surveyLikert from '@jspsych/plugin-survey-likert';\n
"},{"location":"plugins/survey-likert/#examples","title":"Examples","text":"Single Question CodeDemo var trial = {\n type: jsPsychSurveyLikert,\n questions: [\n {\n prompt: \"I like vegetables.\", \n labels: [\n \"Strongly Disagree\", \n \"Disagree\", \n \"Neutral\", \n \"Agree\", \n \"Strongly Agree\"\n ]\n }\n ]\n};\n
Open demo in new tab
Multiple questions in a random order CodeDemo var likert_scale = [\n \"Strongly Disagree\", \n \"Disagree\", \n \"Neutral\", \n \"Agree\", \n \"Strongly Agree\"\n];\n\nvar trial = {\n type: jsPsychSurveyLikert,\n questions: [\n {prompt: \"I like vegetables.\", name: 'Vegetables', labels: likert_scale},\n {prompt: \"I like fruit.\", name: 'Fruit', labels: likert_scale},\n {prompt: \"I like meat.\", name: 'Meat', labels: likert_scale},\n ],\n randomize_question_order: true\n};\n
Open demo in new tab
"},{"location":"plugins/survey-multi-choice/","title":"survey-multi-choice","text":"Current version: 2.0.0. See version history.
The survey-multi-choice plugin displays a set of questions with multiple choice response fields. The participant selects a single answer.
"},{"location":"plugins/survey-multi-choice/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description questions array undefined An array of objects, each object represents a question that appears on the screen. Each object contains a prompt, options, required, and horizontal parameter that will be applied to the question. See examples below for further clarification.prompt
: Type string, default value is undefined. The string is prompt/question that will be associated with a group of options (radio buttons). All questions will get presented on the same page (trial).options
: Type array, defualt value is undefined. An array of strings. The array contains a set of options to display for an individual question.required
: Type boolean, default value is null. The boolean value indicates if a question is required('true') or not ('false'), using the HTML5 required
attribute. If this parameter is undefined, the question will be optional. horizontal
:Type boolean, default value is false. If true, then the question is centered and the options are displayed horizontally. name
: Name of the question. Used for storing data. If left undefined then default names (Q0
, Q1
, ...
) will be used for the questions. randomize_question_order boolean false
If true, the display order of questions
is randomly determined at the start of the trial. In the data object, Q0
will still refer to the first question in the array, regardless of where it was presented visually. preamble string empty string HTML formatted string to display at the top of the page above all the questions. button_label string 'Continue' Label of the button. autocomplete boolean false This determines whether or not all of the input elements on the page should allow autocomplete. Setting this to true will enable autocomplete or auto-fill for the form."},{"location":"plugins/survey-multi-choice/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response object An object containing the response for each question. The object will have a separate key (variable) for each question, with the first question in the trial being recorded in Q0
, the second in Q1
, and so on. The responses are recorded as the name of the option label selected (string). If the name
parameter is defined for the question, then the response object will use the value of name
as the key for each question. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the questions first appear on the screen until the participant's response(s) are submitted. question_order array An array with the order of questions. For example [2,0,1]
would indicate that the first question was trial.questions[2]
(the third item in the questions
parameter), the second question was trial.questions[0]
, and the final question was trial.questions[1]
. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions."},{"location":"plugins/survey-multi-choice/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-survey-multi-choice@2.0.1\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-survey-multi-choice.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-survey-multi-choice\n
import surveyMultiChoice from '@jspsych/plugin-survey-multi-choice';\n
"},{"location":"plugins/survey-multi-choice/#examples","title":"Examples","text":"Vertical Question Alignment CodeDemo var trial = {\n type: jsPsychSurveyMultiChoice,\n questions: [\n {\n prompt: \"Which of the following do you like the most?\", \n name: 'VegetablesLike', \n options: ['Tomato', 'Cucumber', 'Eggplant', 'Corn', 'Peas'], \n required: true\n }, \n {\n prompt: \"Which of the following do you like the least?\", \n name: 'FruitDislike', \n options: ['Apple', 'Banana', 'Orange', 'Grape', 'Strawberry'], \n required: false\n }\n ],\n};\n
Open demo in new tab
Horizontal Question Alignment CodeDemo var trial = {\n type: jsPsychSurveyMultiChoice,\n questions: [\n {\n prompt: \"Which of the following do you like the most?\", \n name: 'VegetablesLike', \n options: ['Tomato', 'Cucumber', 'Eggplant', 'Corn', 'Peas'], \n required: true,\n horizontal: true\n }, \n {\n prompt: \"Which of the following do you like the least?\", \n name: 'FruitDislike', \n options: ['Apple', 'Banana', 'Orange', 'Grape', 'Strawberry'], \n required: false,\n horizontal: true\n }\n ],\n};\n
Open demo in new tab
"},{"location":"plugins/survey-multi-select/","title":"survey-multi-select","text":"Current version: 2.0.0. See version history.
The survey-multi-select plugin displays a set of questions with multiple select response fields. The participant can select multiple answers.
"},{"location":"plugins/survey-multi-select/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description questions array undefined An array of objects, each object represents a question that appears on the screen. Each object contains a prompt, options and horizontal parameter that will be applied to the question. See examples below for further clarification.prompt
: Type string, default value of undefined. The string is the prompt/question that will be associated with a group of options (check boxes). All questions will get presented on the same page (trial).options
: Type array, default value of undefined. The array contains a set of options to display for an individual question.horizontal
: Type boolean, default value of false. If true, the questions are centered and options are displayed horizontally. required
: Type boolean, default value of true. If true, then at least one option must be selected. name
: Name of the question. Used for storing data. If left undefined then default names (Q0
, Q1
, ...
) will be used for the questions. randomize_question_order boolean false
If true, the display order of questions
is randomly determined at the start of the trial. In the data object, Q0
will still refer to the first question in the array, regardless of where it was presented visually. preamble string empty string HTML formatted string to display at the top of the page above all the questions. button_label string 'Continue' Label of the button. required_message string 'You must choose at least one response for this question' Message to display if required response is not given. autocomplete boolean false This determines whether or not all of the input elements on the page should allow autocomplete. Setting this to true will enable autocomplete or auto-fill for the form."},{"location":"plugins/survey-multi-select/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response object An object containing the response for each question. The object will have a separate key (variable) for each question, with the first question in the trial being recorded in Q0
, the second in Q1
, and so on. For each question, the responses are recorded as arrays containing any response options that were selected (strings). If the name
parameter is defined for the question, then the response object will use the value of name
as the key for each question. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the questions first appear on the screen until the participant's response(s) were submitted. question_order array An array with the order of questions. For example [2,0,1]
would indicate that the first question was trial.questions[2]
(the third item in the questions
parameter), the second question was trial.questions[0]
, and the final question was trial.questions[1]
. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions."},{"location":"plugins/survey-multi-select/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-survey-multi-select@2.0.1\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-survey-multi-select.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-survey-multi-select\n
import surveyMultiSelect from '@jspsych/plugin-survey-multi-select';\n
"},{"location":"plugins/survey-multi-select/#examples","title":"Examples","text":"Multiple Questions on a Page CodeDemo var trial = {\n type: jsPsychSurveyMultiSelect,\n questions: [\n {\n prompt: \"Which of these colors do you like?\", \n options: [\"Red\", \"Yellow\", \"Green\", \"Blue\", \"Black\"], \n horizontal: true,\n required: true,\n name: 'Colors'\n }, \n {\n prompt: \"Which of these foods do you like?\", \n options: [\"Apples\", \"Bananas\", \"Carrots\", \"Donuts\", \"Eggplant\"], \n horizontal: true,\n required: true,\n name: 'Foods'\n }\n ], \n randomize_question_order: true\n};\n
Open demo in new tab
"},{"location":"plugins/survey-text/","title":"survey-text","text":"Current version: 2.0.0. See version history.
The survey-text plugin displays a set of questions with free response text fields. The participant types in answers.
"},{"location":"plugins/survey-text/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description questions array undefined An array of objects, each object represents a question that appears on the screen. Each object contains a prompt, placeholder, required, rows, and columns parameter that will be applied to the question. See examples below for further clarification. prompt
: Type string, default value of undefined. The string is the prompt for the participant to respond to. Each question gets its own response field. placeholder
: Type string, default value of \"\"
. The string will create placeholder text in the text field. required
: Boolean; if true
then the user must enter a response to submit. rows
: Type integer, default value of 1. The number of rows for the response text box. columns
: Type integer, default value of 40. The number of columns for the response text box. name
: Name of the question. Used for storing data. If left undefined then default names (Q0
, Q1
, ...
) will be used for the questions. randomize_question_order boolean false
If true, the display order of questions
is randomly determined at the start of the trial. In the data object, Q0
will still refer to the first question in the array, regardless of where it was presented visually. preamble string empty string HTML formatted string to display at the top of the page above all the questions. button_label string 'Continue' The text that appears on the button to finish the trial. autocomplete boolean false This determines whether or not all of the input elements on the page should allow autocomplete. Setting this to true will enable autocomplete or auto-fill for the form."},{"location":"plugins/survey-text/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response object An object containing the response for each question. The object will have a separate key (variable) for each question, with the first question in the trial being recorded in Q0
, the second in Q1
, and so on. For each question, the response is a string containing whatever text was in the response box when the responses were submitted. If the name
parameter is defined for the question, then the response object will use the value of name
as the key for each question. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the questions first appear on the screen until the participant's response(s) were submitted. question_order array An array with the order of questions. For example [2,0,1]
would indicate that the first question was trial.questions[2]
(the third item in the questions
parameter), the second question was trial.questions[0]
, and the final question was trial.questions[1]
. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions."},{"location":"plugins/survey-text/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-survey-text@2.0.1\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-survey-text.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-survey-text\n
import surveyText from '@jspsych/plugin-survey-text';\n
"},{"location":"plugins/survey-text/#examples","title":"Examples","text":"Single question and response CodeDemo var trial = {\n type: jsPsychSurveyText,\n questions: [\n {prompt: 'How old are you?'}\n ]\n}\n
Open demo in new tab
Multiple questions, with an optional placeholder and a required question CodeDemo var trial = {\n type: jsPsychSurveyText,\n questions: [\n {prompt: 'What is your date of birth?', placeholder: 'mm/dd/yyyy', required: true},\n {prompt: 'What country do you currently live in?'}\n ]\n}\n
Open demo in new tab
Naming questions to improve readability of the stored data CodeDemo var trial = {\n type: jsPsychSurveyText,\n questions: [\n {prompt: 'What did you eat for breakfast?', name: 'Breakfast'},\n {prompt: 'What did you eat for lunch?', name: 'Lunch'}\n ]\n}\n
Open demo in new tab
Using the preamble and a longer textbox response CodeDemo var trial = {\n type: jsPsychSurveyText,\n preamble: `<img src=\"img/navarro_burst_03.jpg\" style=\"width:400px;\"></img>`,\n questions: [\n {prompt: 'Describe your reaction to the image above', rows: 5}\n ]\n}\n
The artwork in this demo is by Danielle Navarro
Open demo in new tab
"},{"location":"plugins/survey/","title":"survey","text":"Current version: 2.0.0. See version history.
SurveyJS version: 1.9.138
This plugin is a wrapper for the SurveyJS form library. It displays survey-style questions across one or more pages. You can mix different question types on the same page, and participants can navigate back and forth through multiple survey pages without losing responses. SurveyJS provides a large number of built-in question types, response validation options, conditional display options, special response options (\"None\", \"Select all\", \"Other\"), and other useful features for building complex surveys. See the Building Surveys in jsPsych page for a more detailed list of all options and features.
With SurveyJS, surveys can be defined using a JavaScript/JSON object, a JavaScript function, or a combination of both. The jsPsych survey
plugin provides parameters that accept these methods of constructing a SurveyJS survey, and passes them into SurveyJS. The fact that this plugin just acts as a wrapper means you can take advantage of all of the SurveyJS features, and copy/paste directly from SurveyJS examples into the plugin's survey_json
parameter (for JSON object configuration) or survey_function
parameter (for JavaScript code).
This page contains the plugin's reference information and examples. The Building Surveys in jsPsych page contains a more detailed guide for using this plugin.
For the most comprehensive guides on survey configuration and features, please see the SurveyJS form library documentation and examples.
Limitations
The jsPsych survey
plugin is not compatible with certain jsPsych and SurveyJS features. Specifically:
- It is not always well-suited for use with jsPsych's timeline variables feature. This is because the timeline variables array must store the entire
survey_json
object for each trial, rather than just the parameters that change across trials, which are nested within the survey_json
object. We offer some alternative methods for dynamically constructing questions/trials in this section of the Building Surveys in jsPsych documentation page. - It does not support the SurveyJS \"complete page\" parameter. This is a parameter for HTML formatted content that should appear after the participant clicks the 'submit' button. Instead of using this parameter, you should create another jsPsych trial that comes after the survey trial to serve the same purpose.
- It does not support the SurveyJS question's
correctAnswer
property, which is used for SurveyJS quizzes and automatic response scoring. SurveyJS does not store this value or the response score in the data - instead this is only used to display scores on the survey's 'complete page'. Since the complete page is not supported, this 'correctAnswer' property also does not work as intended in the jsPsych plugin.
"},{"location":"plugins/survey/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
"},{"location":"plugins/survey/#survey-parameters","title":"Survey parameters","text":"Parameter Type Default Value Description survey_json object {}
A SurveyJS-compatible JavaScript object that defines the survey (we refer to this as the survey 'JSON' for consistency with the SurveyJS documentation, but this parameter should be a JSON-compatible JavaScript object rather than a string). If used with the survey_function
parameter, the survey will initially be constructed with this object and then passed to the survey_function
. See the SurveyJS JSON documentation for more information. survey_function function null A function that receives a SurveyJS survey object as an argument. If no survey_json
is specified, then the function receives an empty survey model and must add all pages/elements to it. If a survey_json
object is provided, then this object forms the basis of the survey model that is passed into the survey_function
. See the SurveyJS JavaScript documentation for more information. validation_function function null A function that can be used to validate responses. This function is called whenever the SurveyJS onValidateQuestion
event occurs. (Note: it is also possible to add this function to the survey using the survey_function
parameter - we've just added it as a parameter for convenience)."},{"location":"plugins/survey/#questionelement-types","title":"Question/Element Types","text":"You must add one or more SurveyJS \"element\" to a survey, using the plugin's survey JSON and/or survey function parameter. SurveyJS elements are mostly made up of different question types, but also include non-response content such as HTML and images/video. The Building Surveys in jsPsych page contains more information about how to define survey elements, and you can see some examples in the Examples section on this page.
For reference, the SurveyJS question/element types are listed below, with links to more information and examples in the SurveyJS documentation.
"},{"location":"plugins/survey/#boolean","title":"boolean","text":"The \"boolean\" type is a yes/no (or other two-option) multiple choice question. It differs from the \"radiogroup\" (multiple choice) question type in that it offers different response format options (left/right slider button, yes/no checkbox) in addition to the standard multiple choice format (two separate radio buttons).
- Boolean example
- Boolean API documentation
"},{"location":"plugins/survey/#checkbox","title":"checkbox","text":"This checkbox question type allows participants to select one or more options from the set of choices. You can optionally include special choices, such as \"Select all\", \"None\", and \"Other\" with a text box that appears when selected.
- Checkbox example
- Checkbox API documentation
"},{"location":"plugins/survey/#comment","title":"comment","text":"This is the \"long text\" question type. It's similar to the text input question, but unlike text input, you can make the comment text box larger than a single line. You can also make the box resizeable and limit the number of characters.
- Comment example
- Comment API documentation
"},{"location":"plugins/survey/#dropdown","title":"dropdown","text":"The dropdown question type allows participants to select a single option from a list presented in a drop-down box.
- Dropdown example
- Dropdown API documentation
"},{"location":"plugins/survey/#tagbox","title":"tagbox","text":"This is a multi-select dropdown question type. It is similar to a dropdown question, but allows participants to select more than one response from the drop-down list.
- Tagbox example
- Tagbox API documentation
"},{"location":"plugins/survey/#expression","title":"expression","text":"This is a read-only element that calculates a value based on a specified expression. This question type can be used to dynamically calculate values based on the participant's responses and/or predefined variables and display the calculated value on the page. For example, if you asked participants to estimate the percentage of their day doing various activies, you could have participants enter a percentage value for each activity, and use this 'expression' question to calculate and display the total percentage across all activities (to ensure that it does not exceed 100).
- Expression example
- Expression API documentation
"},{"location":"plugins/survey/#file","title":"file","text":"This question allows participants to upload one or more files (images, documents, etc.). It provides drag-and-drop and browse/select options. Files can be uploaded to a server or stored directly in the survey results JSON object as base64-encoded text.
Note
When using this question type, you will need to choose how to handle the files. One option is to save the file with the rest of the response data as a Base64-encoded text string (storeDataAsText: true
), but keep in mind that this will significantly increase the size of the response data and should only be used for small files. Another option is to upload the participant's file to a server, which you can do using the onUploadFiles
event handler in the jsPsych survey_function
function. You can read more about these options in the SurveyJS file upload documentation, and see an example of the file upload option in the index.js
part of this code example.
- File example
- File API documentation
"},{"location":"plugins/survey/#html","title":"html","text":"Most SurveyJS question types do not support HTML markup in the display fields. The html element allows you to add custom HTML to the survey, so that you can insert images, hyperlinks, etc.
- HTML example
- HTML API documentation
"},{"location":"plugins/survey/#image","title":"image","text":"This element adds an image or video to the survey page.
- Image example
- Image API documentation
"},{"location":"plugins/survey/#imagepicker","title":"imagepicker","text":"This question type displays images/videos and allows the participant to select one or more as their repsonse.
- Imagepicker example
- Imagepicker API documentation
"},{"location":"plugins/survey/#matrix","title":"matrix","text":"The matrix question creates a table of multiple choice questions (rows) that use the same set of response options (columns). This is often used for presenting multiple questions/statements with a Likert or similar rating scale.
- Matrix example
- Matrix API documentation
"},{"location":"plugins/survey/#matrixdropdown","title":"matrixdropdown","text":"This question type allows you to present a matrix (table) of questions, with different types of response options in each cell. Despite the \"dropdown\" part of the question type name, this question type allows not only dropdown questions in the matrix cells, but also checkbox, radiogroup, text, and comment.
- Matrixdropdown example
- Matrixdropdown API documentation
"},{"location":"plugins/survey/#multipletext","title":"multipletext","text":"This question type allows you to present multiple text questions as part of a single 'question', which can be useful if you want to group together related short-answer text input boxes (e.g. separate first/middle/last text boxes for entering full name). Each 'item' within this question type defines a single text question, and supports the text question's input types (email, date, etc.) for built-in formatting and validation. In the results, there will be a single key for this question (either the question name, if specified in the question parameters, otheriwse automatically named questionN
), and the value will be an object with key-value pairs for each text entry 'item' (\"item1Name\": \"item1Response\", \"item2Name\": \"item2Response\"
, etc.).
- Multipletext example
- Multipletext API documentation
"},{"location":"plugins/survey/#panel","title":"panel","text":"This element allows you to group related questions together. This can help with visual organization on the page, and can help participants understand the purpose of a set of questions. Panels appear as a title/description above a box that contains the panel's nested elements/questions. The panel can be initially expanded (show all questions) and collapsed (hide all questions), and users can toggle this state by clicking on the panel title.
- Panel example
- Panel API documentation
"},{"location":"plugins/survey/#paneldynamic","title":"paneldynamic","text":"The paneldyanmic element allows you to set up a group of questions that repeat based on the participant's response(s) to another question. This can be useful when the participant will have an unknown number of responses, and you want to ask the same questions about each response. For instance, you could use this element type to set up a series of questions about the participant's children, employment history, favorite hobbies, etc. The paneldynamic element allows participants to add/delete the 'subpanels' (response and associated question set).
- Paneldynamic example
- Paneldynamic API documentation
"},{"location":"plugins/survey/#radiogroup","title":"radiogroup","text":"This is a multiple choice question type. Participants can select a single option from the set of choices. You can optionally add special choices, such as \"Other\" with a text box that appears when selected.
- Radiogroup example
- Radiogroup API documentation
"},{"location":"plugins/survey/#rating","title":"rating","text":"The rating question type is a type of multiple-choice question that is intended for allowing participants to evaluate something on a scale. The scale can display a range of numbers, graphic symbols (stars, faces), or text labels. The scale options can be presented as a set of horizontal buttons, a drop-down menu, or \"auto\" (displays buttons if there is sufficient page width, otherwise drop-down; see the Rating UI page for more documentation and examples).
- Rating example
- Rating API documentation
"},{"location":"plugins/survey/#ranking","title":"ranking","text":"The ranking question allows participants to arrange a set of choices in order of preference, importance, or other criteria, or assign a numerical value to each choice based on their relative rank. The options are displayed vertically, and participants can drag-and-drop to change their order. This question type can be useful when used with the SurveyJS \"carry forward\" feature. For instance, you can take the participant's responses from a previous checkbox (multi-select) question and use those selections as the options to rank in a ranking question (see the reference_previous_answers.html
example in the jsPsych survey package). It's also possible to combine the selection and ranking steps into a single question using the 'select items to rank' approach, which allows participants to 'select' items by dragging them into a separate ranking area, and re-order the items in the ranking area.
- Ranking example
- Ranking API documentation
"},{"location":"plugins/survey/#signaturepad","title":"signaturepad","text":"The signaturepad question allows participants to add their digital signature to the survey by drawing with the mouse or finger (on a trackpad or touchscreen-enabled device). You can specify the pen color and box size, and save the signature as Base64-encoded text in PNG (default), JPEG, or SVG format. You can also save the image directly to a server rather than encoding it as text with the rest of the response data. See this SurveyJS demo and documentation about uploading the signature as an image file, and the file question for more information and warnings about handling files.
- Signaturepad example
- Signaturepad API documentation
"},{"location":"plugins/survey/#text","title":"text","text":"In addition to a basic text input box, you can select from any of these other input types: color, date, datetime-local, email, month, number, password, range, tel, time, url, week. Setting these input types will change things like (1) the format of the response elements, (2) the characters/values that the participant is allowed to enter, and/or (3) add automatic validation for the response format.
- Text input examples - includes email, password, and URL input types
- Date/time input examples
- Numeric input examples - includes range input (slider) and telephone number input types
- Color input example
- Text API documentation
"},{"location":"plugins/survey/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response object An object containing the response to each question. The object will have a separate key (identifier) for each question. If the name
parameter is defined for the question (recommended), then the response object will use the value of name
as the key for each question. If any questions do not have a name parameter, their keys will named automatically, with the first unnamed question recorded as question1
, the second as question2
, and so on. The response type will depend on the question type. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the questions first appear on the screen until the participant's response(s) are submitted."},{"location":"plugins/survey/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/survey/#css","title":"CSS","text":"This plugin requires an additional stylesheet called survey.css
. You can load it via:
<link rel=\"stylesheet\" href=\"https://unpkg.com/@jspsych/plugin-survey@2.0.1/css/survey.css\">\n
If you are using a bundler such as webpack, you can also import it in JavaScript as follows, depending on your bundler configuration:
import '@jspsych/plugin-survey/css/survey.css'\n
"},{"location":"plugins/survey/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-survey@2.0.1\"></script>\n<link rel=\"stylesheet\" href=\"https://unpkg.com/@jspsych/plugin-survey@2.0.1/css/survey.css\">\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-survey.js\"></script>\n<link rel=\"stylesheet\" href=\"jspsych/plugin-survey.css\">\n
Using NPM:
npm install @jspsych/plugin-survey\n
import survey from '@jspsych/plugin-survey';\nimport '@jspsych/plugin-survey/css/survey.css'\n
"},{"location":"plugins/survey/#examples","title":"Examples","text":"Single page with radiogroup (multiple choice) and checkbox CodeDemo const trial = {\n type: jsPsychSurvey,\n survey_json: {\n showQuestionNumbers: false,\n elements:\n [\n {\n type: 'radiogroup',\n title: \"Which of the following do you like the most?\", \n name: 'vegetablesLike', \n choices: ['Tomato', 'Cucumber', 'Eggplant', 'Corn', 'Peas', 'Broccoli']\n }, \n {\n type: 'checkbox',\n title: \"Which of the following do you like?\", \n name: 'fruitLike', \n description: \"You can select as many as you want.\",\n choices: ['Apple', 'Banana', 'Orange', 'Grape', 'Strawberry', 'Kiwi', 'Mango'], \n showOtherItem: true,\n showSelectAllItem: true,\n showNoneItem: true,\n required: true,\n }\n ]\n }\n};\n
Open demo in new tab
Multiple pages with text and multiple choice questions, and more customization CodeDemo const trial = {\n type: jsPsychSurvey,\n survey_json: {\n showQuestionNumbers: false,\n title: 'My questionnaire',\n completeText: 'Done!',\n pageNextText: 'Continue',\n pagePrevText: 'Previous',\n pages: [\n {\n name: 'page1',\n elements: [\n {\n type: 'text',\n title: 'Where were you born?', \n placeholder: 'City, State/Region, Country',\n name: 'birthplace', \n size: 30,\n isRequired: true,\n }, \n {\n type: 'text',\n title: 'How old are you?', \n name: 'age', \n isRequired: false,\n inputType: 'number',\n min: 0,\n max: 100,\n defaultValue: 0\n }\n ]\n },\n {\n name: 'page2',\n elements: [\n {\n type: 'radiogroup',\n title: \"What's your favorite color?\", \n choices: ['Blue','Yellow','Pink','Teal','Orange','Lime green'],\n showNoneItem: true,\n showOtherItem: true,\n colCount: 0,\n name: 'FavColor',\n }, \n {\n type: 'checkbox',\n title: 'Which of these animals do you like? Select all that apply.', \n choices: ['Lion','Squirrel','Badger','Whale', 'Turtle'],\n choicesOrder: 'random',\n colCount: 0,\n name: 'FavAnimals', \n }\n ]\n }\n ]\n }\n};\n
Open demo in new tab
Rating and matrix questions for Likert-style scales This example shows several different options for presenting a single question/statement with a rating scale (buttons, stars, smileys). It also shows a table of several questions/statements (rows) to be rated on the same scale (columns). Note: This content requires more page width and is best viewed when opened in a new tab.
CodeDemo const trial = {\n type: jsPsychSurvey,\n survey_json: {\n showQuestionNumbers: false,\n title: 'Likert scale examples',\n pages: [\n {\n elements: [\n {\n type: 'rating',\n name: 'like-vegetables',\n title: 'I like to eat vegetables.',\n description: 'Button rating scale with min/max descriptions',\n minRateDescription: 'Strongly Disagree',\n maxRateDescription: 'Strongly Agree',\n displayMode: 'buttons',\n rateValues: [1,2,3,4,5]\n }, \n {\n type: 'rating',\n name: 'like-cake',\n title: 'I like to eat cake.',\n description: 'Star rating scale with min/max descriptions',\n minRateDescription: 'Strongly Disagree',\n maxRateDescription: 'Strongly Agree',\n rateType: 'stars',\n rateCount: 10,\n rateMax: 10,\n },\n {\n type: 'rating',\n name: 'like-cooking',\n title: 'How much do you enjoy cooking?',\n description: 'Smiley rating scale without min/max descriptions',\n rateType: 'smileys',\n rateCount: 10,\n rateMax: 10,\n scaleColorMode: 'colored',\n }\n ]\n }, {\n elements: [\n {\n type: 'matrix',\n name: 'like-food-matrix',\n title: 'Matrix question for rating mutliple statements on the same scale.',\n alternateRows: true,\n isAllRowRequired: true,\n rows: [\n {text: 'I like to eat vegetables.', value: 'VeggiesTable'},\n {text: 'I like to eat fruit.', value: 'FruitTable'},\n {text: 'I like to eat cake.', value: 'CakeTable'},\n {text: 'I like to cook.', value: 'CookTable'},\n ],\n columns: [{\n \"value\": 5,\n \"text\": \"Strongly agree\"\n }, {\n \"value\": 4,\n \"text\": \"Agree\"\n }, {\n \"value\": 3,\n \"text\": \"Neutral\"\n }, {\n \"value\": 2,\n \"text\": \"Disagree\"\n }, {\n \"value\": 1,\n \"text\": \"Strongly disagree\"\n }]\n }\n ]\n }\n ]\n }\n};\n
Open demo in new tab
Conditional question visibility based on response This example demonstrates how you can show/hide questions based on the participant's response. It also shows how you can show/hide the navigation buttons and move on to the next page automatically.
CodeDemo const survey_function = (survey) => {\n // If it's the question page, then hide the buttons and move on automatically.\n // If it's the feedback page, then show the navigation buttons.\n function updateNavButtons(sender, options) {\n if (options.newCurrentPage.getPropertyValue(\"name\") === \"feedback\") {\n survey.showNavigationButtons = \"bottom\";\n } else {\n survey.showNavigationButtons = \"none\";\n }\n }\n survey.onCurrentPageChanging.add(updateNavButtons);\n}\n\nconst trial = {\n type: jsPsychSurvey,\n survey_json: {\n showQuestionNumbers: false,\n title: 'Conditional question visibility.',\n showNavigationButtons: \"none\",\n goNextPageAutomatic: true,\n allowCompleteSurveyAutomatic: true,\n pages: [{\n name: 'question',\n elements: [\n {\n type: 'radiogroup',\n title: 'During the experiment, are you allowed to write things down on paper to help you?',\n choices: [\"Yes\", \"No\"],\n name: \"WriteOK\",\n isRequired: true\n }\n ],\n }, {\n name: 'feedback',\n elements: [\n {\n type: 'html',\n name: 'incorrect',\n visibleIf: '{WriteOK} = \"Yes\"',\n html: '<h4>That response was incorrect.</h4><p>Please return to the previous page and try again.</p>'\n },\n {\n type: 'html',\n name: 'correct',\n visibleIf: '{WriteOK} == \"No\"',\n html: '<h4>Congratulations!</h4>'\n }\n ]\n }]\n },\n survey_function: survey_function\n};\n
Open demo in new tab
Repeating survey trials with different variables The survey plugin is not well-suited for use with the jsPsych timeline variables feature, so an alternative to creating a set of repeating survey trials is to construct them in a loop. When adding any data to a survey trial, you should add it via the data
parameter at the whole-trial level (not inside the question objects), even if it only relates to one question out of multiple questions/pages contained within the trial.
CodeDemo // values that change across survey trials - each object represents a single trial\nconst question_variables = [\n {\n 'fruit': 'apples',\n 'Q1_prompt': 'Do you like apples?', \n 'Q1_type': 'regular',\n 'Q2_word': 'like'\n },\n {\n 'fruit': 'pears',\n 'Q1_prompt': 'Do you like pears?', \n 'Q1_type': 'regular',\n 'Q2_word': 'like'\n },\n {\n 'fruit': 'bananas',\n 'Q1_prompt': 'Do you NOT like bananas?', \n 'Q1_type': 'reverse',\n 'Q2_word': 'hate'\n },\n];\n\n// create an array to store all of our survey trials so that we can easily randomize their order\nsurvey_trials = [];\n\n// construct the survey trials dynamically using an array of question-specific information\nfor (let i=0; i<question_variables.length; i++) {\n\n // set up the survey JSON for this trial\n // any question-specific variables come from the appropriate object in the question_variables array\n let survey_json = {\n showQuestionNumbers: false,\n title: 'Dynamically constructing survey trials.',\n completeText: 'Next >>',\n elements: [\n {\n type: 'radiogroup',\n title: question_variables[i].Q1_prompt,\n choices: ['Yes', 'No'],\n name: 'Q1'\n },\n {\n type: 'text',\n title: 'What do you '+question_variables[i].Q2_word+' most about '+question_variables[i].fruit+'?',\n name: 'Q2'\n }\n ]\n };\n\n // set up a survey trial object using the JSON we've just created for this question, \n // and add the trial object to the survey trials array\n survey_trials.push({\n type: jsPsychSurvey,\n survey_json: survey_json,\n data: {\n 'Q1_prompt': question_variables[i].Q1_prompt,\n 'Q1_type': question_variables[i].Q1_type,\n 'Q2_word': question_variables[i].Q2_word,\n 'fruit': question_variables[i].fruit \n } \n });\n\n}\n\nconst timeline = jsPsych.randomization.shuffle(survey_trials);\n
Open demo in new tab
Adding images, sound and HTML This example shows how to add HTML, image and audio elements to a survey. It also demonstrates some CSS customization and response validation.
CodeDemo /* center the audio player and all image question types in the survey */\ndiv.sd-question--image, div.sd-question[data-name=\"audio-player\"] {\n text-align: center;\n}\n/* use 'data-name' to select any specific question by name */\ndiv[data-name=\"audio-response\"] {\n text-align: center;\n margin-top: 30px;\n}\n
// Embed HTML, images, videos and audio into the survey\nconst image_video_html_trial_info = {\n pages: [{\n elements: [{\n type: \"panel\",\n name: \"html-img-panel\",\n description: \"This panel contains an HTML element and an image element.\",\n elements: [{\n type: \"html\",\n name: \"html\",\n html: \"<div style='text-align: center; align-items: center; align-content: center; justify-content: center;'><p style='text-align: center; color: darkgreen; font-size: 2em;'>This demo shows how you can add <em>HTML</em>, <strong>images</strong>, and <sub>video</sub> to your jsPsych survey trial.</p></div>\"\n }, {\n type: \"image\",\n name: \"monkey\",\n imageLink: \"img/monkey.png\",\n altText: \"Monkey\",\n imageWidth: 300\n }]\n }, {\n type: \"panel\",\n name: \"video-panel\",\n description: \"This panel contains a fun fish video.\",\n elements: [{\n type: \"image\",\n name: \"jspsych-tutorial\",\n imageLink: \"video/fish.mp4\",\n imageWidth: 700,\n imageHeight: 350\n }],\n }]\n }],\n widthMode: \"static\",\n width: 900,\n completeText: 'Next'\n};\n\nconst image_video_html_trial = {\n type: jsPsychSurvey,\n survey_json: image_video_html_trial_info\n};\n\n// Using images as response options\nconst image_choice_trial_info = {\n elements: [{\n type: \"imagepicker\",\n name: \"animals\",\n title: \"Which animals would you like to see in real life?\",\n description: \"Please select all that apply.\",\n choices: [{\n value: \"lion\",\n imageLink: \"img/lion.png\",\n text: \"Lion\"\n }, {\n value: \"monkey\",\n imageLink: \"img/monkey.png\",\n text: \"Monkey\"\n }, {\n value: \"elephant\",\n imageLink: \"img/elephant.png\",\n text: \"Elephant\"\n }],\n showLabel: true,\n multiSelect: true\n }],\n showQuestionNumbers: \"off\",\n completeText: 'Next',\n};\n\nconst image_choice_trial = {\n type: jsPsychSurvey,\n survey_json: image_choice_trial_info\n};\n\n// Add sound to an HTML element\n// This also demonstrates response validation\nconst sound_trial_info = {\n elements: [{\n type: \"html\",\n name: \"audio-player\",\n html: \"<audio controls><source src='sound/speech_red.mp3' type='audio/mp3'></audio>\"\n },\n {\n type: \"text\",\n name: \"audio-response\",\n title: \"Please play the sound above and then type the word that you heard in the box below.\",\n description: \"Try getting it wrong to see the response validation.\",\n required: true,\n validators: [{\n type: \"regex\",\n text: \"Oops, that's not correct. Try again!\",\n regex: \"[rR]{1}[eE]{1}[dD]{1}\"\n }],\n }],\n completeText: \"Check my response\",\n showQuestionNumbers: \"off\"\n};\n\nconst sound_trial = {\n type: jsPsychSurvey,\n survey_json: sound_trial_info\n}\n\nconst timeline = [image_video_html_trial, image_choice_trial, sound_trial];\n
Open demo in new tab
Automatic formating for text input You can add automatic formatting, or input masking, to a text entry question. See the SurveyJS documentation on masked input fields for more information and examples.
CodeDemo const timeline = [];\n\nconst text_masking_json = {\n elements: [\n {\n type: \"html\",\n name: \"intro\",\n html: \"<h3>Input masking examples</h3><p>You can use input masking with text questions to add automatic formatting to the participant's answer. The mask types are: currency, decimal, pattern, and datetime. These masks will also restrict the types of characters that can be entered, e.g. only numbers or letters.\"\n },\n {\n type: \"text\",\n name: \"currency\",\n title: \"Currency:\",\n description: \"This currency mask adds a prefix/suffix to the number to indicate the currency. Enter some numbers to see the result.\",\n maskType: \"currency\",\n maskSettings: {\n prefix: \"$\",\n suffix: \" USD\"\n }\n },\n {\n type: \"text\",\n name: \"decimal\",\n title: \"Decimal:\",\n description: \"This numeric mask will specify the number of decimals allowed. You can enter numbers with up to three decimals (precision: 3).\",\n maskType: \"numeric\",\n maskSettings: {\n precision: 3\n }\n },\n {\n type: \"text\",\n name: \"phone\",\n title: \"Phone:\",\n description: \"This pattern mask will format the numbers as a phone number.\",\n maskType: \"pattern\",\n maskSettings: {\n pattern: \"+9 (999)-999-9999\"\n }\n },\n {\n type: \"text\",\n name: \"creditcard\",\n title: \"Credit card number:\",\n description: \"This pattern mask will format the numbers as a credit card number.\",\n maskType: \"pattern\",\n maskSettings: {\n pattern: \"9999 9999 9999 9999\"\n }\n },\n {\n type: \"text\",\n name: \"licenseplate\",\n title: \"License plate number:\",\n description: \"A pattern mask can also be used with letters. Enter a license plate number in the format ABC-1234.\",\n maskType: \"pattern\",\n maskSettings: {\n pattern: \"aaa-9999\"\n }\n }\n ],\n showQuestionNumbers: false\n};\n\ntimeline.push({\n type: jsPsychSurvey,\n survey_json: text_masking_json\n});\n
Open demo in new tab
"},{"location":"plugins/video-button-response/","title":"video-button-response","text":"Current version: 2.0.0. See version history.
This plugin plays a video and records responses generated by button click. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically when the participant responds, when the video file has finished playing, or if the participant has failed to respond within a fixed length of time. You can also prevent a button response from being made before the video has finished playing. The button itself can be customized using HTML formatting.
Video files can be automatically preloaded by jsPsych using the preload
plugin. However, if you are using timeline variables or another dynamic method to specify the video stimulus, you will need to manually preload the videos. Also note that video preloading is disabled when the experiment is running as a file (i.e. opened directly in the browser, rather than through a server), in order to prevent CORS errors - see the section on Running Experiments for more information.
"},{"location":"plugins/video-button-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus array undefined An array of file paths to the video. You can specify multiple formats of the same video (e.g., .mp4, .ogg, .webm) to maximize the cross-browser compatibility. Usually .mp4 is a safe cross-browser option. The plugin does not reliably support .mov files. The player will use the first source file in the array that is compatible with the browser, so specify the files in order of preference. choices array of strings undefined Labels for the buttons. Each different string in the array will generate a different button. button_html function (choice: string, choice_index: number)=>`<button class=\"jspsych-btn\">${choice}</button>
; A function that generates the HTML for each button in the choices
array. The function gets the string and index of the item in the choices
array and should return valid HTML. If you want to use different markup for each button, you can do that by using a conditional on either parameter. The default parameter returns a button element with the text label of the choice. button_layout string 'grid' Setting to 'grid'
will make the container element have the CSS property display: grid
and enable the use of grid_rows
and grid_columns
. Setting to 'flex'
will make the container element have the CSS property display: flex
. You can customize how the buttons are laid out by adding inline CSS in the button_html
parameter. grid_rows number 1 The number of rows in the button grid. Only applicable when button_layout
is set to 'grid'
. If null, the number of rows will be determined automatically based on the number of buttons and the number of columns. grid_columns number null The number of columns in the button grid. Only applicable when button_layout
is set to 'grid'
. If null, the number of columns will be determined automatically based on the number of buttons and the number of rows. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). width numeric width of the video file The width of the video display in pixels. height numeric heigh of the video file The height of the video display in pixels. autoplay boolean true If true, the video will begin playing as soon as it has loaded. controls boolean false If true, controls for the video player will be available to the participant. They will be able to pause the video or move the playback to any point in the video. start numeric null If given a value, the video will start at this time point in seconds. stop numeric null If given a value, the video will stop at this time point in seconds. rate numeric null The playback rate of the video. 1 is normal, <1 is slower, >1 is faster. trial_ends_after_video bool false If true, then the trial will end as soon as the video file finishes playing. trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can set this parameter to false
to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete. response_allowed_while_playing boolean true If true, then responses are allowed while the video is playing. If false, then the video must finish playing before the button choices are enabled and a response is accepted. Once the video has played all the way through, the buttons are enabled and a response is allowed (including while the video is being re-played via on-screen playback controls). enable_button_after numeric 0 How long the button will delay enabling in milliseconds. If response_allowed_while_playing
is true
, the timer will start immediately. If it is false
, the timer will start at the end of the video."},{"location":"plugins/video-button-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response numeric Indicates which button the participant pressed. The first button in the choices
array is 0, the second is 1, and so on. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. stimulus array The stimulus
array. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions."},{"location":"plugins/video-button-response/#simulation-mode","title":"Simulation Mode","text":"In data-only
simulation mode, the response_allowed_while_playing
parameter does not currently influence the simulated response time. This is because the audio file is not loaded in data-only
mode and therefore the length is unknown. This may change in a future version as we improve the simulation modes.
"},{"location":"plugins/video-button-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-video-button-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-video-button-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-video-button-response\n
import videoButtonResponse from '@jspsych/plugin-video-button-response';\n
"},{"location":"plugins/video-button-response/#example","title":"Example","text":"Responses disabled until the video is complete CodeDemo var trial = {\n type: jsPsychVideoButtonResponse,\n stimulus: [\n 'video/fish.mp4'\n ],\n choices: ['0-5', '6-10','11-15','16-20','21-25','25+'],\n prompt: \"<p>How many different fish are shown in the video?</p>\",\n response_allowed_while_playing: false\n};\n
Stock Footage provided by rjt98, from Pond5
Open demo in new tab
"},{"location":"plugins/video-keyboard-response/","title":"video-keyboard-response","text":"Current version: 2.0.0. See version history.
This plugin plays a video file and records a keyboard response. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically when the participant responds, when the video file has finished playing, or if the participant has failed to respond within a fixed length of time. You can also prevent a keyboard response from being recorded before the video has finished playing.
Video files can be automatically preloaded by jsPsych using the preload
plugin. However, if you are using timeline variables or another dynamic method to specify the video stimulus, you will need to manually preload the videos. Also note that video preloading is disabled when the experiment is running as a file (i.e. opened directly in the browser, rather than through a server), in order to prevent CORS errors - see the section on Running Experiments for more information.
"},{"location":"plugins/video-keyboard-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus array undefined An array of file paths to the video. You can specify multiple formats of the same video (e.g., .mp4, .ogg, .webm) to maximize the cross-browser compatibility. Usually .mp4 is a safe cross-browser option. The plugin does not reliably support .mov files. The player will use the first source file in the array that is compatible with the browser, so specify the files in order of preference. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). width numeric width of the video file The width of the video display in pixels. height numeric heigh of the video file The height of the video display in pixels. autoplay boolean true If true, the video will begin playing as soon as it has loaded. controls boolean false If true, controls for the video player will be available to the participant. They will be able to pause the video or move the playback to any point in the video. start numeric null If given a value, the video will start at this time point in seconds. stop numeric null If given a value, the video will stop at this time point in seconds. rate numeric null The playback rate of the video. 1 is normal, <1 is slower, >1 is faster. choices array of strings \"ALL_KEYS\"
This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., 'a'
, 'q'
, ' '
, 'Enter'
, 'ArrowDown'
) - see this page and this page (event.key column) for more examples. Any key presses that are not listed in the array will be ignored. The default value of \"ALL_KEYS\"
means that all keys will be accepted as valid responses. Specifying \"NO_KEYS\"
will mean that no responses are allowed. trial_ends_after_video bool false If true, then the trial will end as soon as the video file finishes playing. trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can set this parameter to false
to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete. response_allowed_while_playing boolean true If true, then responses are allowed while the video is playing. If false, then the video must finish playing before a keyboard response is accepted. Once the video has played all the way through, a valid keyboard response is allowed (including while the video is being re-played via on-screen playback controls)."},{"location":"plugins/video-keyboard-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. stimulus array The stimulus
array. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions."},{"location":"plugins/video-keyboard-response/#simulation-mode","title":"Simulation Mode","text":"In data-only
simulation mode, the response_allowed_while_playing
parameter does not currently influence the simulated response time. This is because the audio file is not loaded in data-only
mode and therefore the length is unknown. This may change in a future version as we improve the simulation modes.
"},{"location":"plugins/video-keyboard-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-video-keyboard-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-video-keyboard-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-video-keyboard-response\n
import videoKeyboardResponse from '@jspsych/plugin-video-keyboard-response';\n
"},{"location":"plugins/video-keyboard-response/#examples","title":"Examples","text":"Show a video and advance to next trial automatically CodeDemo var trial = {\n type: jsPsychVideoKeyboardResponse,\n stimulus: [\n 'video/fish.mp4'\n ],\n choices: \"NO_KEYS\",\n trial_ends_after_video: true\n};\n
Stock Footage provided by rjt98, from Pond5
Open demo in new tab
"},{"location":"plugins/video-slider-response/","title":"video-slider-response","text":"Current version: 2.0.0. See version history.
This plugin plays a video and allows the participant to respond by dragging a slider. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically when the participant responds, when the video file has finished playing, or if the participant has failed to respond within a fixed length of time. You can also prevent the slider response from being made before the video has finished playing.
Video files can be automatically preloaded by jsPsych using the preload
plugin. However, if you are using timeline variables or another dynamic method to specify the video stimulus, you will need to manually preload the videos. Also note that video preloading is disabled when the experiment is running as a file (i.e. opened directly in the browser, rather than through a server), in order to prevent CORS errors - see the section on Running Experiments for more information.
"},{"location":"plugins/video-slider-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus array undefined An array of file paths to the video. You can specify multiple formats of the same video (e.g., .mp4, .ogg, .webm) to maximize the cross-browser compatibility. Usually .mp4 is a safe cross-browser option. The plugin does not reliably support .mov files. The player will use the first source file in the array that is compatible with the browser, so specify the files in order of preference. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). width numeric width of the video file The width of the video display in pixels. height numeric heigh of the video file The height of the video display in pixels. autoplay boolean true If true, the video will begin playing as soon as it has loaded. controls boolean false If true, controls for the video player will be available to the participant. They will be able to pause the video or move the playback to any point in the video. start numeric null If given a value, the video will start at this time point in seconds. stop numeric null If given a value, the video will stop at this time point in seconds. rate numeric null The playback rate of the video. 1 is normal, <1 is slower, >1 is faster. min integer 0 Sets the minimum value of the slider. max integer 100 Sets the maximum value of the slider. slider_start integer 50 Sets the starting value of the slider step integer 1 Sets the step of the slider. This is the smallest amount by which the slider can change. labels array of strings [] Labels displayed at equidistant locations on the slider. For example, two labels will be placed at the ends of the slider. Three labels would place two at the ends and one in the middle. Four will place two at the ends, and the other two will be at 33% and 67% of the slider width. slider_width integer null Set the width of the slider in pixels. If left null, then the width will be equal to the widest element in the display. require_movement boolean false If true, the participant must move the slider before clicking the continue button. button_label string 'Continue' Label of the button to end the trial. trial_ends_after_video bool false If true, then the trial will end as soon as the video file finishes playing. trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can set this parameter to false
to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete. response_allowed_while_playing boolean true If true, then responses are allowed while the video is playing. If false, then the video must finish playing before the slider is enabled and the trial can end via the next button click. Once the video has played all the way through, the slider is enabled and a response is allowed (including while the video is being re-played via on-screen playback controls)."},{"location":"plugins/video-slider-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response numeric The numeric value of the slider. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. stimulus array The stimulus
array. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. slider_start numeric The starting value of the slider. start numeric The start time of the video clip."},{"location":"plugins/video-slider-response/#simulation-mode","title":"Simulation Mode","text":"In data-only
simulation mode, the response_allowed_while_playing
parameter does not currently influence the simulated response time. This is because the audio file is not loaded in data-only
mode and therefore the length is unknown. This may change in a future version as we improve the simulation modes.
"},{"location":"plugins/video-slider-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-video-slider-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-video-slider-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-video-slider-response\n
import videoSliderResponse from '@jspsych/plugin-video-slider-response';\n
"},{"location":"plugins/video-slider-response/#example","title":"Example","text":"Rate enjoyment of a video clip CodeDemo var trial = {\n type: jsPsychVideoSliderResponse,\n stimulus: [\n 'video/fish.mp4'\n ],\n labels: [\"Hated it\", \"Loved it\"],\n prompt: '<p>Please rate your enjoyment of the video clip.</p>'\n};\n
Stock Footage provided by rjt98, from Pond5
Open demo in new tab
"},{"location":"plugins/virtual-chinrest/","title":"virtual-chinrest","text":"Current version: 3.0.0. See version history.
This plugin provides a \"virtual chinrest\" that can measure the distance between the participant and the screen. It can also standardize the jsPsych page content to a known physical dimension (e.g., ensuring that a 200px wide stimulus is 2.2cm wide on the participant's monitor). This is based on the work of Li, Joo, Yeatman, and Reinecke (2020), and the plugin code is a modified version of their implementation. We recommend citing their work in any paper that makes use of this plugin.
Citation
Li, Q., Joo, S. J., Yeatman, J. D., & Reinecke, K. (2020). Controlling for Participants\u2019 Viewing Distance in Large-Scale, Psychophysical Online Experiments Using a Virtual Chinrest. Scientific Reports, 10(1), 1-11. doi: 10.1038/s41598-019-57204-1
The plugin works in two phases.
Phase 1. To calculate the pixel-to-cm conversion rate for a participant\u2019s display, participants are asked to place a credit card or other item of the same size on the screen and resize an image until it is the same size as the credit card. Since we know the physical dimensions of the card, we can find the conversion rate for the participant's display.
Phase 2. To measure the participant's viewing distance from their screen we use a blind spot task. Participants are asked to focus on a black square on the screen with their right eye closed, while a red dot repeatedly sweeps from right to left. They press the spacebar on their keyboard whenever they perceive that the red dot has disappeared. This part allows the plugin to use the distance between the black square and the red dot when it disappears from eyesight to estimate how far the participant is from the monitor. This estimation assumes that the blind spot is located at 13.5\u00b0 temporally.
"},{"location":"plugins/virtual-chinrest/#parameters","title":"Parameters","text":"Parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Descripton resize_units string \"none\" Units to resize the jsPsych content to after the trial is over: \"none\"
\"cm\"
\"inch\"
or \"deg\"
. If \"none\"
, no resizing will be done to the jsPsych content after the virtual-chinrest trial ends. pixels_per_unit numeric 100 After the scaling factor is applied, this many pixels will equal one unit of measurement, where the units are indicated by resize_units
. This is only used when resizing is done after the trial ends (i.e. the resize_units
parameter is not \"none\"). adjustment_prompt HTML string \"Click and drag the lower right corner of the image until it is the same size as a credit card held up to the screen. You can use any card that is the same size as a credit card, like a membership card or driver's license. If you do not have access to a real card you can use a ruler to measure the image width to 3.37 inches or 85.6 mm.\" This string can contain HTML markup. Any content here will be displayed below the card stimulus during the resizing phase. adjustment_button_prompt HTML string \"Click here when the image is the correct size\" Content of the button displayed below the card stimulus during the resizing phase. item_path string null Path of the item to be presented in the card stimulus during the resizing phase. If null
then no image is shown, and a solid color background is used instead. An example image is available in /examples/img/card.png
item_height_mm numeric 53.98 The known height of the physical item (e.g. credit card) to be measured, in mm. item_width_mm numeric 85.6 The known width of the physical item (e.g. credit card) to be measured, in mm. item_init_size numeric 250 The initial size of the card stimulus, in pixels, along its largest dimension. blindspot_reps numeric 5 How many times to measure the blindspot location. If 0
, blindspot will not be detected, and viewing distance and degree data will not be computed. blindspot_prompt HTML string \"Now we will quickly measure how far away you are sitting. Put your left hand on the space bar. Cover your right eye with your right hand. Using your left eye, focus on the black square. Keep your focus on the black square. The red ball will disappear as it moves from right to left. Press the space bar as soon as the ball disappears. Press the space bar when you are ready to begin. This string can contain HTML markup. Any content here will be displayed above the blindspot task. redo_measurement_button_label HTML string 'No, that is not close. Try again' Text for the button on the viewing distance report page to re-do the viewing distance estimate. If the participant click this button, the blindspot task starts again. blindspot_done_prompt HTML string \"Yes\" Text for the button on the viewing distance report page that can be clicked to accept the viewing distance estimate. blindspot_measurements_prompt HTML string 'Remaining measurements: ' Text accompanying the remaining measurements counter that appears below the blindspot task. viewing_distance_report HTML string \"Based on your responses, you are sitting about <span id='distance-estimate' style='font-weight: bold;'></span>
from the screen. Does that seem about right?\" Estimated viewing distance data displayed after blindspot task. If \"none\"
is given, viewing distance will not be reported to the participant. The HTML span
element with id = distance-estimate
returns the distance."},{"location":"plugins/virtual-chinrest/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Note: The deg data are only returned if viewing distance is estimated with the blindspot method (px2deg, win_height_deg, win_width_deg, item_width_deg).
Name Type Value rt numeric The response time in milliseconds. item_height_mm numeric The height in millimeters of the item to be measured. item_width_mm numeric The width in millimeters of the item to be measured item_height_deg numeric Final height of the resizable div container, in degrees. item_width_deg numeric Final width of the resizable div container, in degrees. item_width_px numeric Final width of the resizable div container, in pixels. px2deg numeric Pixels to degrees conversion factor. px2mm numeric Pixels to millimeters conversion factor. scale_factor numeric Scaling factor that will be applied to the div containing jsPsych content. win_width_deg numeric The interior width of the window in degrees. win_height_deg numeric The interior height of the window in degrees. view_dist_mm numeric Estimated distance to the screen in millimeters."},{"location":"plugins/virtual-chinrest/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/virtual-chinrest/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-virtual-chinrest@3.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-virtual-chinrest.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-virtual-chinrest\n
import virtualChinrest from '@jspsych/plugin-virtual-chinrest';\n
"},{"location":"plugins/virtual-chinrest/#example","title":"Example","text":"Measure distance to screen and pixel ratio; no resizing CodeDemo var trial = {\n type: jsPsychVirtualChinrest,\n blindspot_reps: 3,\n resize_units: \"none\"\n};\n
This demo requires a larger viewing area to complete. Please open the demo in a new tab
Open demo in new tab
Resizing based on centimeters per pixel CodeDemo var trial = {\n type: jsPsychVirtualChinrest,\n blindspot_reps: 3,\n resize_units: \"cm\",\n pixels_per_unit: 50\n};\n\nvar resized_stimulus = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `\n <p>If the measurements were done correctly, the square below should be 10 cm x 10 cm.</p>\n <div style=\"background-color: black; width: 500px; height: 500px; margin: 20px auto;\"></div>\n `,\n choices: ['Continue']\n}\n
This demo requires a larger viewing area to complete. Please open the demo in a new tab
Open demo in new tab
Resizing based on degrees of visual angle per pixel CodeDemo var trial = {\n type: jsPsychVirtualChinrest,\n blindspot_reps: 3,\n resize_units: \"deg\",\n pixels_per_unit: 50\n};\n\nvar resized_stimulus = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `\n <p>If the measurements were done correctly, the square below should take up about 10 degrees of visual angle.</p>\n <div style=\"background-color: black; width: 500px; height: 500px; margin: 20px auto;\"></div>\n `,\n choices: ['Continue']\n}\n
This demo requires a larger viewing area to complete. Please open the demo in a new tab
Open demo in new tab
"},{"location":"plugins/visual-search-circle/","title":"visual-search-circle","text":"Current version: 2.1.0. See version history.
This plugin presents a customizable visual-search task modelled after Wang, Cavanagh, & Green (1994). The participant indicates whether or not a target is present among a set of distractors. The stimuli are displayed in a circle, evenly-spaced, equidistant from a fixation point. Here is an example using normal and backward Ns:
"},{"location":"plugins/visual-search-circle/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. The set of images to display must be defined in one of two ways:
- The
target
, foil
and set_size
parameters: the combination of these parameters can be used to construct a 'classic' visual search task, where there is a single foil/distractor image that makes up all of the images in the set, with the exception of the target image if it is present. OR - The
stimuli
parameter: this array that can be used to present any arbitrary set of image files, with or without the target image, with any number of different foils/distractors, and with any number of repeated images.
The target_present
and fixation_image
parameters must always be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description target string null Path to image file that is the search target. This parameter must specified when the stimuli set is defined using the target
, foil
and set_size
parameters, but should NOT be specified when using the stimuli
parameter. foil string null Path to image file that is the foil/distractor. This image will be repeated for all distractors up to the set_size
value. This parameter must specified when the stimuli set is defined using the target
, foil
and set_size
parameters, but should NOT be specified when using the stimuli
parameter. set_size numeric null How many items should be displayed, including the target when target_present
is true
. The foil image will be repeated up to this value when target_present
is false
, or up to set_size - 1
when target_present
is true
. This parameter must specified when using the target
, foil
and set_size
parameters to define the stimuli set, but should NOT be specified when using the stimuli
parameter. stimuli array of images null Array containing all of the image files to be displayed. This parameter must be specified when NOT using the target
, foil
, and set_size
parameters to define the stimuli set. target_present boolean undefined Is the target present? This parameter must always be specified. When using the target
, foil
and set_size
parameters, false
means that the foil image will be repeated up to the set_size, and true
means that the target will be presented along with the foil image repeated up to set_size - 1. When using the stimuli
parameter, this parameter is only used to determine the response accuracy. fixation_image string undefined Path to image file that is a fixation target. This parameter must always be specified. target_size array [50, 50]
Two element array indicating the height and width of the search array element images. fixation_size array [16, 16]
Two element array indicating the height and width of the fixation image. circle_diameter numeric 250 The diameter of the search array circle in pixels. target_present_key string 'j' The key to press if the target is present in the search array. target_absent_key string 'f' The key to press if the target is not present in the search array. trial_duration numeric null The maximum amount of time the participant is allowed to search before the trial will continue. A value of null will allow the participant to search indefinitely. fixation_duration numeric 1000 How long to show the fixation image for before the search array (in milliseconds). randomize_item_locations bool true Whether to use randomized locations on the circle for the items. If false
, then the first item will always show at the location specified by location_first_item
. location_first_item numeric 0 If randomize_item_locations
is false
, the location of the first item on the circle, in degrees. 0 degrees is above the fixation, and moving clockwise in the positive direction. response_ends_trial boolean true If true, the trial will end when the participant makes a response."},{"location":"plugins/visual-search-circle/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value correct boolean True if the participant gave the correct response. response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. set_size numeric The number of items in the search array target_present boolean True if the target is present in the search array locations array Array where each element is the pixel value of the center of an image in the search array. If the target is present, then the first element will represent the location of the target. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions."},{"location":"plugins/visual-search-circle/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-visual-search-circle@2.1.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-visual-search-circle.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-visual-search-circle\n
import visualSearchCircle from '@jspsych/plugin-visual-search-circle';\n
"},{"location":"plugins/visual-search-circle/#examples","title":"Examples","text":"Identical distractors CodeDemo var instructions = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `<p>Press J if there is a backwards N.</p>\n <p>Press F if all the Ns are in the normal orientation.</p>`,\n choices: ['Continue']\n}\n\nvar trial = {\n type: jsPsychVisualSearchCircle,\n target: 'img/backwardN.gif',\n foil: 'img/normalN.gif',\n fixation_image: 'img/fixation.gif',\n target_present: true,\n set_size: 4\n}\n
Open demo in new tab
Variety of different distractors CodeDemo var instructions = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `<p>Press E if there is an elephant in the group.</p>\n <p>Press N if there is no elephant in the group.</p>`,\n choices: ['Continue']\n}\n\nvar trial = {\n type: jsPsychVisualSearchCircle,\n stimuli: ['img/elephant.png', 'img/lion.png', 'img/monkey.png'],\n fixation_image: 'img/fixation.gif',\n target_present_key: 'e',\n target_absent_key: 'n',\n target_present: true\n}\n
Open demo in new tab
"},{"location":"plugins/webgazer-calibrate/","title":"webgazer-calibrate","text":"Current version: 2.0.0. See version history.
This plugin can be used to calibrate the WebGazer extension. For a narrative description of eye tracking with jsPsych, see the eye tracking overview.
"},{"location":"plugins/webgazer-calibrate/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description calibration_points array [[10,10], [10,50], [10,90], [50,10], [50,50], [50,90], [90,10], [90,50], [90,90]]
Array of points in [x,y]
coordinates. Specified as a percentage of the screen width and height, from the left and top edge. The default grid is 9 points. calibration_mode string 'click'
Can specify click
to have participants click on calibration points or view
to have participants passively watch calibration points. repetitions_per_point numeric 1 The number of times to repeat the sequence of calibration points. point_size numeric 20 Diameter of the calibration points in pixels. randomize_calibration_order bool false
Whether to randomize the order of the calibration points. time_to_saccade numeric 1000 If calibration_mode
is set to view
, then this is the delay before calibrating after showing a point. Gives the participant time to fixate on the new target before assuming that the participant is looking at the target. time_per_point numeric 1000 If calibration_mode
is set to view
, then this is the length of time to show a point while calibrating. Note that if click
calibration is used then the point will remain on the screen until clicked."},{"location":"plugins/webgazer-calibrate/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value No data currently added by this plugin. Use the webgazer-validate plugin to measure the precision and accuracy of calibration.
"},{"location":"plugins/webgazer-calibrate/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/webgazer-calibrate/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-webgazer-calibrate@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-webgazer-calibrate.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-webgazer-calibrate\n
import webgazerCalibrate from '@jspsych/plugin-webgazer-calibrate';\n
"},{"location":"plugins/webgazer-calibrate/#example","title":"Example","text":"Because the eye tracking plugins need to be used in conjunction with each other, please see the example on the eye tracking overview page for an integrated example.
"},{"location":"plugins/webgazer-init-camera/","title":"webgazer-init-camera","text":"Current version: 2.0.0. See version history.
This plugin initializes the camera and helps the participant center their face in the camera view for using the the WebGazer extension. For a narrative description of eye tracking with jsPsych, see the eye tracking overview.
"},{"location":"plugins/webgazer-init-camera/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description instructions string too long to put here Instructions for the participant to follow. button_text string Continue The text for the button that participants click to end the trial."},{"location":"plugins/webgazer-init-camera/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value load_time numeric The time it took for webgazer to initialize. This can be a long time in some situations, so this value is recorded for troubleshooting when participants are reporting difficulty."},{"location":"plugins/webgazer-init-camera/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/webgazer-init-camera/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-webgazer-init-camera@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-webgazer-init-camera.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-webgazer-init-camera\n
import webgazerInitCamera from '@jspsych/plugin-webgazer-init-camera';\n
"},{"location":"plugins/webgazer-init-camera/#example","title":"Example","text":"Because the eye tracking plugins need to be used in conjunction with each other, please see the example on the eye tracking overview page for an integrated example.
"},{"location":"plugins/webgazer-validate/","title":"webgazer-validate","text":"Current version: 2.0.0. See version history.
This plugin can be used to measure the accuracy and precision of gaze predictions made by the WebGazer extension. For a narrative description of eye tracking with jsPsych, see the eye tracking overview.
"},{"location":"plugins/webgazer-validate/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description validation_points array [[10,10], [10,50], [10,90], [50,10], [50,50], [50,90], [90,10], [90,50], [90,90]]
Array of points in [x,y]
coordinates. The default grid is 9 points. Meaning of coordinates controlled by validation_point_coordinates
parameter. validation_point_coordinates string 'percent'
Can specify percent
to have validation point coordinates specified in percentage of screen width and height, or center-offset-pixels
to specify each point as the distance in pixels from the center of the screen. roi_radius numeric 200 Tolerance around the validation point in pixels when calculating the percent of gaze measurements within the acceptable range. randomize_validation_order bool false
Whether to randomize the order of the validation points. time_to_saccade numeric 1000 The delay before validating after showing a point. Gives the participant time to fixate on the new target before assuming that the participant is looking at the target. validation_duration numeric 2000 If calibration_mode
is set to view
, then this is the length of time to show a point while calibrating. Note that if click
calibration is used then the point will remain on the screen until clicked. point_size numeric 20 Diameter of the validation points in pixels. show_validation_data bool false If true
then a visualization of the validation data will be shown on the screen after the validation is complete. This will show each measured gaze location color coded by whether it is within the roi_radius
of the target point. This is mainly intended for testing and debugging."},{"location":"plugins/webgazer-validate/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value raw_gaze array Raw gaze data for the trial. The array will contain a nested array for each validation point. Within each nested array will be a list of {x,y,dx,dy}
values specifying the absolute x and y pixels, as well as the distance from the target for that gaze point. percent_in_roi array The percentage of samples within the roi_radius
for each validation point. average_offset array The average x
and y
distance from each validation point, plus the median distance r
of the points from this average offset. samples_per_sec numeric The average number of samples per second. Calculated by finding samples per second for each point and then averaging these estimates together. validation_points array The list of validation points, in the order that they appeared."},{"location":"plugins/webgazer-validate/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/webgazer-validate/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-webgazer-validate@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-webgazer-validate.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-webgazer-validate\n
import webgazerValidate from '@jspsych/plugin-webgazer-validate';\n
"},{"location":"plugins/webgazer-validate/#example","title":"Example","text":"Because the eye tracking plugins need to be used in conjunction with each other, please see the example on the eye tracking overview page for an integrated example.
"},{"location":"reference/jspsych-data/","title":"jsPsych.data","text":"The jsPsych.data module contains functions for interacting with the data generated by jsPsych plugins.
"},{"location":"reference/jspsych-data/#jspsychdataaddproperties","title":"jsPsych.data.addProperties","text":"jsPsych.data.addProperties(properties)\n
"},{"location":"reference/jspsych-data/#parameters","title":"Parameters","text":"Parameter Type Description properties object Object of key: value pairs to add to the data."},{"location":"reference/jspsych-data/#return-value","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-data/#description","title":"Description","text":"This method appends a set of properties to every trial in the data object, including trials that have already occurred and trials that have yet to occur. You can use this to record things like the subject ID or condition assignment.
"},{"location":"reference/jspsych-data/#examples","title":"Examples","text":""},{"location":"reference/jspsych-data/#assigning-a-subject-id-and-condition-code","title":"Assigning a subject ID and condition code","text":"jsPsych.data.addProperties({subject: 1, condition: 'control'});\n
"},{"location":"reference/jspsych-data/#jspsychdatadisplaydata","title":"jsPsych.data.displayData","text":"jsPsych.data.displayData(format)\n
"},{"location":"reference/jspsych-data/#parameters_1","title":"Parameters","text":"Parameter Type Description format string Specifies whether to display the data in 'csv'
or 'json'
format."},{"location":"reference/jspsych-data/#return-value_1","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-data/#description_1","title":"Description","text":"Outputs all of the data collected in the experiment to the screen in either JSON or CSV format. This is a useful method for quick debugging when developing an experiment.
"},{"location":"reference/jspsych-data/#examples_1","title":"Examples","text":""},{"location":"reference/jspsych-data/#using-the-on_finish-callback-function-to-show-data-at-the-end-of-the-experiment","title":"Using the on_finish callback function to show data at the end of the experiment","text":"var jsPsych = initJsPsych({\n on_finish: function() {\n jsPsych.data.displayData('csv');\n }\n})\n
"},{"location":"reference/jspsych-data/#jspsychdataget","title":"jsPsych.data.get","text":"jsPsych.data.get()\n
"},{"location":"reference/jspsych-data/#parameters_2","title":"Parameters","text":"None.
"},{"location":"reference/jspsych-data/#return-value_2","title":"Return value","text":"Returns the data collection of all data generated by the experiment.
"},{"location":"reference/jspsych-data/#description_2","title":"Description","text":"This function is the standard starting point for accessing the data generated by the experiment. It returns a DataCollection object, which has several methods that can be used to further filter, aggregate, and view the data. These methods are described under the DataCollection section on this page.
"},{"location":"reference/jspsych-data/#example","title":"Example","text":"// select all trials\nvar all_data = jsPsych.data.get();\n\n// get csv representation of data and log to console\nconsole.log(all_data.csv());\n
"},{"location":"reference/jspsych-data/#jspsychdatagetinteractiondata","title":"jsPsych.data.getInteractionData","text":"jsPsych.data.getInteractionData()\n
"},{"location":"reference/jspsych-data/#parameters_3","title":"Parameters","text":"None.
"},{"location":"reference/jspsych-data/#return-value_3","title":"Return value","text":"Returns a DataCollection object with all of the interaction events.
"},{"location":"reference/jspsych-data/#description_3","title":"Description","text":"jsPsych automatically records a few different kinds of user interaction events. blur
events occur when the user clicks on another window or tab during the experiment, indicating that they are no longer interacting with the experiment. focus
events occur when the user clicks on the experiment window after having clicked somewhere else first (i.e., generated a blur
event). fullscreenenter
and fullscreenexit
events are triggered by the browser entering and exiting fullscreen mode. However, fullscreenenter
events only occur when the script switches the browser to fullscreen mode, e.g., with the fullscreen plugin. Manually entering fullscreen mode does not trigger this event. fullscreenexit
events occur whether the user manually exits fullscreen mode or the script exits fullscreen mode. This method returns the DataCollection containing all interaction events. This is useful for tracking whether the participant completed the task without diverting attention to other windows. Events are in the form:
{\n type: 'focus' or 'blur' or 'fullscreenenter' or 'fullscreenexit',\n trial: 10, // the trial number when the event happened\n time: 13042 // total time elapsed since the start of the experiment\n}\n
"},{"location":"reference/jspsych-data/#example_1","title":"Example","text":"var interaction_data = jsPsych.data.getInteractionData();\n// log data to console in json format\nconsole.log(interaction_data.json());\n
"},{"location":"reference/jspsych-data/#jspsychdatagetlasttimelinedata","title":"jsPsych.data.getLastTimelineData","text":"jsPsych.data.getLastTimelineData()\n
"},{"location":"reference/jspsych-data/#return-value_4","title":"Return value","text":"Returns a DataCollection.
"},{"location":"reference/jspsych-data/#description_4","title":"Description","text":"Gets all of the data generated in the same timeline as the last trial.
"},{"location":"reference/jspsych-data/#example_2","title":"Example","text":"var lasttimelinedata = jsPsych.data.getLastTimelineData();\n
"},{"location":"reference/jspsych-data/#jspsychdatagetlasttrialdata","title":"jsPsych.data.getLastTrialData","text":"jsPsych.data.getLastTrialData()\n
"},{"location":"reference/jspsych-data/#return-value_5","title":"Return value","text":"Returns a DataCollection.
"},{"location":"reference/jspsych-data/#description_5","title":"Description","text":"Gets the data collection containing all data generated by the last trial.
"},{"location":"reference/jspsych-data/#example_3","title":"Example","text":"var lasttrialdata = jsPsych.data.getLastTrialData();\n
"},{"location":"reference/jspsych-data/#jspsychdatageturlvariable","title":"jsPsych.data.getURLVariable","text":"jsPsych.data.getURLVariable(var_name)\n
"},{"location":"reference/jspsych-data/#parameters_4","title":"Parameters","text":"Parameter Type Description var_name string Which variable to get the value of."},{"location":"reference/jspsych-data/#return-value_6","title":"Return value","text":"Returns the value of a variable passed in through the query string.
"},{"location":"reference/jspsych-data/#description_6","title":"Description","text":"For extracting a particular variable passed in through a URL query string.
"},{"location":"reference/jspsych-data/#example_4","title":"Example","text":"// if the URL of the page is: experiment.html?subject=1234&condition=test\nconsole.log(jsPsych.data.getURLVariable('subject')) // logs \"1234\"\nconsole.log(jsPsych.data.getURLVariable('condition')) // logs \"test\"\n
"},{"location":"reference/jspsych-data/#jspsychdataurlvariables","title":"jsPsych.data.urlVariables","text":"jsPsych.data.urlVariables()\n
"},{"location":"reference/jspsych-data/#return-value_7","title":"Return value","text":"Returns an object (associative array) of the variables in the URL query string.
"},{"location":"reference/jspsych-data/#description_7","title":"Description","text":"For extracting variables passed in through a URL query string.
"},{"location":"reference/jspsych-data/#example_5","title":"Example","text":"// if the URL of the page is: experiment.html?subject=1234&condition=test\nvar urlvar = jsPsych.data.urlVariables();\nconsole.log(urlvar.subject) // logs \"1234\"\nconsole.log(urlvar.condition) // logs \"test\"\n
"},{"location":"reference/jspsych-data/#jspsychdatawrite","title":"jsPsych.data.write","text":"jsPsych.data.write(data_object)\n
"},{"location":"reference/jspsych-data/#parameters_5","title":"Parameters","text":"Parameter Type Description data_object object Object of key: value
pairs to store in jsPsych's data storage as a trial."},{"location":"reference/jspsych-data/#return-value_8","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-data/#description_8","title":"Description","text":"This method is used by jsPsych.finishTrial
for writing data. You should probably not use it to add data. Instead use jsPsych.data.addProperties.
"},{"location":"reference/jspsych-data/#example_6","title":"Example","text":"// don't use this! data should only be written once per trial. use jsPsych.finishTrial to save data.\n\nvar trial_data = {\n correct: true,\n rt: 487\n}\n\njsPsych.data.write(trial_data);\n
"},{"location":"reference/jspsych-data/#datacollection","title":"DataCollection","text":"All data is stored in the DataCollection object. Using methods like jsPsych.data.get()
and jsPsych.data.getLastTrialData()
return DataCollections containing the experiment data. This is a list of all of the methods that are available to call on a DataCollection object.
"},{"location":"reference/jspsych-data/#addtoall","title":".addToAll()","text":"Adds a set of properties to all items in the DataCollection. Similar to jsPsych.data.addProperties()
, except that it can be applied to a subset of the whole DataCollection by filtering down to a smaller DataCollection first.
jsPsych.data.get().addToAll({subject_id: 123, condition: 'control'});\n
"},{"location":"reference/jspsych-data/#addtolast","title":".addToLast()","text":"Adds a set of properties to the last trial in the DataCollection.
jsPsych.data.get().addToLast({success: true});\n
"},{"location":"reference/jspsych-data/#count","title":".count()","text":"Counts the number of trials in the DataCollection.
jsPsych.data.get().count()\n
"},{"location":"reference/jspsych-data/#csv","title":".csv()","text":"Generates a CSV string representing all of the data in the DataCollection.
console.log(jsPsych.data.get().csv());\n
"},{"location":"reference/jspsych-data/#filter","title":".filter()","text":"Returns a subset of the DataCollection based on the filter. The filter is an object, and trials are only kept in the returned DataCollection if they contain the key: value pair(s) in the filter object. For example, the code below selects all of the trials with a correct response.
var correct_trials = jsPsych.data.get().filter({correct: true});\n
The object can have multiple key: value pairs, and the trials must match all of them in order to be included in the returned collection.
// keep only correct trials from the practice phase\nvar correct_practice_trials = jsPsych.data.get().filter({correct:true, phase: 'practice'});\n
The filter can also be an array of objects. In this case each object in the array acts as an OR filter. As long as the trial has all the key: value pairs of one of the objects in the array, it will appear in the returned collection.
// select trials from block 1 and block 5.\nvar trials = jsPsych.data.get().filter([{block: 1}, {block:5}]);\n
The filter method returns a DataCollection object, so methods can be chained onto a single statement.
// count the number of correct trials in block 1\nvar block_1_correct = jsPsych.data.get().filter({block:1, correct:true}).count();\n
"},{"location":"reference/jspsych-data/#filtercolumns","title":".filterColumns()","text":"Selects the set of columns listed in the array. This is the opposite of the .ignore()
method.
// Get only the subject, rt, and condition entries for each trial.\nconst subset_of_data = jsPsych.data.get().filterColumns(['subject', 'rt', 'condition'])\n
"},{"location":"reference/jspsych-data/#filtercustom","title":".filterCustom()","text":"This method is similar to the .filter()
method, except that it accepts a function as the filter. The function is passed a single argument, containing the data for a trial. If the function returns true
the trial is included in the returned DataCollection.
// count the number of trials with a response time greater than 2000ms.\nvar too_long = jsPsych.data.get().filterCustom(function(trial){\n return trial.rt > 2000;\n}).count()\n
"},{"location":"reference/jspsych-data/#first-last","title":".first() / .last()","text":"Returns a DataCollection containing the first/last n trials. If n is greater than the number of trials in the DataCollection, then these functions will return an array of length equal to the number of trials. If there are no trials in the DataCollection, then these functions will return an empty array. If the n argument is omitted, then the functions will use the default value of 1. If n is zero or a negative number, then these functions will throw an error.
var first_trial = jsPsych.data.get().first(1);\nvar last_trial_with_correct_response = jsPsych.data.get().filter({correct: true}).last(1);\nvar last_10_trials = jsPsych.data.get().last(10);\n
"},{"location":"reference/jspsych-data/#ignore","title":".ignore()","text":"Returns a DataCollection with all instances of a particular key removed from the dataset.
// log a csv file that does not contain the trial_type values for each trial\nconsole.log(jsPsych.data.get().ignore('trial_type').csv());\n
"},{"location":"reference/jspsych-data/#join","title":".join()","text":"Appends one DataCollection onto another and returns the combined collection.
// get a DataCollection with all trials that are either correct or\n// have a response time greater than 200ms.\nvar dc1 = jsPsych.data.get().filter({correct: true});\nvar dc2 = jsPsych.data.get().filterCustom(function(trial){ return trial.rt > 200});\nvar data = dc1.join(dc2);\n
"},{"location":"reference/jspsych-data/#json","title":".json()","text":"Generates a JSON string representing all of the data in the DataCollection.
console.log(jsPsych.data.get().json());\n
"},{"location":"reference/jspsych-data/#localsave","title":".localSave()","text":"Saves a CSV or JSON file on the computer running the experiment. If conducting an online experiment, this will download the file onto the subject's computer, and is therefore not a recommended data storage solution for online data collection.
Warning: This function may not behave correctly in older browsers. Upgrading to the latest version of any major web browser should solve the problem.
// first argument is the format, second is the filename.\n// the format can be either 'csv' or 'json'.\njsPsych.data.get().localSave('csv','mydata.csv');\n
"},{"location":"reference/jspsych-data/#push","title":".push()","text":"Add a new entry to the DataCollection. This method is mostly used internally, and you shouldn't need to call it under normal circumstances.
var data = {correct: true, rt: 500}\njsPsych.data.get().push(data);\n
"},{"location":"reference/jspsych-data/#readonly","title":".readOnly()","text":"Creates a copy of the DataCollection so that any modification of the values in the DataCollection will not affect the original.
// this line edits the rt property of the first trial\njsPsych.data.get().first(1).values()[0].rt = 100;\n\n// readOnly creates a copy that can be modified without affecting the original\n\njsPsych.data.get().first(1).values()[0].rt\n// outputs 100\n\njsPsych.data.get().readOnly().first(1).values()[0].rt = 200\njsPsych.data.get().first(1).values()[0].rt\n// still outputs 100\n
"},{"location":"reference/jspsych-data/#select","title":".select()","text":"Returns a DataColumn object (see documentation below) of a single property from a DataCollection object.
var rt_data = jsPsych.data.get().select('rt');\nrt_data.mean()\n
"},{"location":"reference/jspsych-data/#uniquenames","title":".uniqueNames()","text":"Generates an array of all the unique key names in the set of trials contained in the DataCollection. This is especially useful when setting up a relational database (e.g., MySQL) where the column names need to be specified in advance.
console.log(jsPsych.data.get().uniqueNames());\n
"},{"location":"reference/jspsych-data/#values","title":".values()","text":"Returns the raw data array associated with the DataCollection. This array is modifiable, so changes to the array and values of objects in the array will change the DataCollection.
var raw_data = jsPsych.data.get().values();\n\n// was response in first trial correct?\nif(raw_data[0].correct){\n console.log('correct!');\n} else {\n console.log('incorrect.');\n}\n
"},{"location":"reference/jspsych-data/#datacolumn","title":"DataColumn","text":"DataColumn objects represent all the values of a single property in a DataCollection. They are generated by using the .select()
method on a DataCollection. Once a DataColumn is generated, the following methods can be used.
"},{"location":"reference/jspsych-data/#all","title":".all()","text":"Checks if all values in the DataColumn return true
when passed to a function. The function takes a single argument, which represents one value from the DataColumn.
// check if all the response times in the practice phase were under 1000ms\njsPsych.data.get().filter({phase: 'practice'}).select('correct').all(function(x) { return x < 1000; });\n
"},{"location":"reference/jspsych-data/#count_1","title":".count()","text":"Counts the number of values in the DataColumn.
// count how many response times there are\njsPsych.data.get().select('rt').count();\n
"},{"location":"reference/jspsych-data/#frequencies","title":".frequencies()","text":"Counts the number of occurrences of each unique value in the DataColumn. Returns this value as an object, where each key is a unique value and the value of each key is the number of occurrences of that key.
// get frequencies of correct and incorrect responses\njsPsych.data.get().select('correct').frequencies();\n
"},{"location":"reference/jspsych-data/#max-min","title":".max() / .min()","text":"Returns the maximum or minimum value in a DataColumn.
jsPsych.data.get().select('rt').max();\njsPsych.data.get().select('rt').min();\n
"},{"location":"reference/jspsych-data/#mean","title":".mean()","text":"Returns the average of all the values in a DataColumn.
jsPsych.data.get().select('rt').mean();\n
"},{"location":"reference/jspsych-data/#median","title":".median()","text":"Returns the median of all the values in a DataColumn.
jsPsych.data.get().select('rt').median();\n
"},{"location":"reference/jspsych-data/#sd","title":".sd()","text":"Returns the standard deviation of the values in a DataColumn.
jsPsych.data.get().select('rt').sd();\n
"},{"location":"reference/jspsych-data/#subset","title":".subset()","text":"Filters the DataColumn to include only values that return true
when passed through the specified function.
// below results will be less than 200.\njsPsych.data.get().select('rt').subset(function(x){ return x < 200; }).max();\n
"},{"location":"reference/jspsych-data/#sum","title":".sum()","text":"Returns the sum of the values in a DataColumn.
jsPsych.data.get().select('rt').sum();\n
"},{"location":"reference/jspsych-data/#values_1","title":".values","text":"The raw array of values in the DataColumn.
// note that this is not a function call.\njsPsych.data.get().select('rt').values;\n
"},{"location":"reference/jspsych-data/#variance","title":".variance()","text":"Returns the variance of the values in a DataColumn.
jsPsych.data.get().select('rt').variance();\n
"},{"location":"reference/jspsych-pluginAPI/","title":"jsPsych.pluginAPI","text":"The pluginAPI module contains functions that are useful when developing plugins. All of the functions are accessible through the pluginAPI
object. In this documentation we've divided them up based on different kinds of functionality.
"},{"location":"reference/jspsych-pluginAPI/#keyboard-input","title":"Keyboard Input","text":""},{"location":"reference/jspsych-pluginAPI/#cancelallkeyboardresponses","title":"cancelAllKeyboardResponses","text":"jsPsych.pluginAPI.cancelAllKeyboardResponses()\n
"},{"location":"reference/jspsych-pluginAPI/#parameters","title":"Parameters","text":"None.
"},{"location":"reference/jspsych-pluginAPI/#return-value","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-pluginAPI/#description","title":"Description","text":"Cancels all currently active keyboard listeners created by jsPsych.pluginAPI.getKeyboardResponse
.
"},{"location":"reference/jspsych-pluginAPI/#example","title":"Example","text":"jsPsych.pluginAPI.cancelAllKeyboardResponses();\n
"},{"location":"reference/jspsych-pluginAPI/#cancelkeyboardresponse","title":"cancelKeyboardResponse","text":"jsPsych.pluginAPI.cancelKeyboardResponse(listener_id)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_1","title":"Parameters","text":"Parameter Type Description listener_id object The listener_id object generated by the call to jsPsych.pluginAPI.getKeyboardResponse
."},{"location":"reference/jspsych-pluginAPI/#return-value_1","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-pluginAPI/#description_1","title":"Description","text":"Cancels a specific keyboard listener created by jsPsych.pluginAPI.getKeyboardResponse
.
"},{"location":"reference/jspsych-pluginAPI/#example_1","title":"Example","text":"// create a persistent keyboard listener\nvar listener_id = jsPsych.pluginAPI.getKeyboardResponse({\n callback_function: after_response, \n valid_responses: ['p','q'], \n rt_method: 'performance', \n persist: true,\n allow_held_key: false\n});\n\n// cancel keyboard listener\njsPsych.pluginAPI.cancelKeyboardResponse(listener_id);\n
"},{"location":"reference/jspsych-pluginAPI/#comparekeys","title":"compareKeys","text":"jsPsych.pluginAPI.compareKeys(key1, key2)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_2","title":"Parameters","text":"Parameter Type Description key1 string or numeric The representation of a key, either string or keycode key2 string or numeric The representation of a key, either string or keycode"},{"location":"reference/jspsych-pluginAPI/#return-value_2","title":"Return value","text":"Returns true if keycodes or strings refer to the same key, regardless of type. Returns false if the keycodes or strings do not match.
"},{"location":"reference/jspsych-pluginAPI/#description_2","title":"Description","text":"Compares two keys to see if they are the same, ignoring differences in representational type, and using the appropriate case sensitivity based on the experiment's settings.
If case_sensitive_responses
is set to false
in initJsPsych
(the default), then the string key comparison will not be case-sensitive, e.g., \"a\" and \"A\" will match, and this function will return true
. If case_sensitive_responses
is set to true
in initJsPsych
, then the string key comparison will not be case-sensitive, e.g., \"a\" and \"A\" will not match, and this function will return false
.
We recommend using this function to compare keys in all plugin and experiment code, rather than using something like if (response == 'j')...
. This is because the response key returned by the jsPsych.pluginAPI.getKeyboardResponse
function will be converted to lowercase when case_sensitive_responses
is false
, and it will match the exact key press representation when case_sensitive_responses
is true
. Using this compareKeys
function will ensure that your key comparisons work appropriately based on the experiment's case_sensitive_responses
setting, and that you do not need to remember to check key responses against different case versions of the comparison key (e.g. if (response == 'ArrowLeft' || response == 'arrowleft')...
).
"},{"location":"reference/jspsych-pluginAPI/#examples","title":"Examples","text":""},{"location":"reference/jspsych-pluginAPI/#basic-examples","title":"Basic examples","text":"jsPsych.pluginAPI.compareKeys('a', 'A');\n// returns true when case_sensitive_responses is false in initJsPsych\n\njsPsych.pluginAPI.compareKeys('a', 'A');\n// returns false when case_sensitive_responses is true in initJsPsych\n\n// also works with numeric key codes (but note that numeric keyCode values are now deprecated)\njsPsych.pluginAPI.compareKeys('a', 65);\n// returns true\n\njsPsych.pluginAPI.compareKeys('space', 31);\n// returns false\n
"},{"location":"reference/jspsych-pluginAPI/#comparing-a-key-response-and-key-parameter-value-in-plugins","title":"Comparing a key response and key parameter value in plugins","text":"// this is the callback_function passed to jsPsych.pluginAPI.getKeyboardResponse\nvar after_response = function(info) {\n // score the response by comparing the key that was pressed against the trial's key_answer parameter\n var correct = jsPsych.pluginAPI.compareKeys(trial.key_answer, info.key);\n //...\n}\n
"},{"location":"reference/jspsych-pluginAPI/#scoring-a-key-response-in-experiment-code","title":"Scoring a key response in experiment code","text":"var trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<<<<<',\n choices: ['f','j'],\n prompt: 'Press f for left. Press j for right.',\n on_finish: function(data){\n // score the response by comparing the key that was pressed (data.response) against the \n // correct response for this trial ('f'), and store reponse accuracy in the trial data\n if(jsPsych.pluginAPI.compareKeys(data.response, 'f')){\n data.correct = true;\n } else {\n data.correct = false; \n }\n }\n}\n
"},{"location":"reference/jspsych-pluginAPI/#getkeyboardresponse","title":"getKeyboardResponse","text":"jsPsych.pluginAPI.getKeyboardResponse(parameters)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_3","title":"Parameters","text":"The method accepts an object of parameter values (see example below). The valid keys for this object are listed in the table below.
Parameter Type Description callback_function function The function to execute whenever a valid keyboard response is generated. valid_responses array An array of key codes or character strings representing valid responses. Responses not on the list will be ignored. An empty array indicates that no response is acceptable. rt_method string Indicates which method of recording time to use. The 'performance'
method uses calls to performance.now()
, which is the standard way of measuring timing in jsPsych. It is supported by up-to-date versions of all the major browsers. The audio
method is used in conjuction with an audio_context
(set as an additional parameter). This uses the clock time of the audio_context
when audio stimuli are being played. audio_context AudioContext object The AudioContext of the audio file that is being played. audio_context_start_time numeric The scheduled time of the sound file in the AudioContext. This will be used as the start time. allow_held_key boolean If true
, then responses will be registered from keys that are being held down. If false
, then a held key can only register a response the first time that getKeyboardResponse
is called for that key. For example, if a participant holds down the A
key before the experiment starts, then the first time getKeyboardResponse
is called, the A
will register as a key press. However, any future calls to getKeyboardResponse
will not register the A
until the participant releases the key and presses it again. persist boolean If false, then the keyboard listener will only trigger the first time a valid key is pressed. If true, then it will trigger every time a valid key is pressed until it is explicitly cancelled by jsPsych.pluginAPI.cancelKeyboardResponse
or jsPsych.pluginAPI.cancelAllKeyboardResponses
. minimum_valid_rt number The minimum valid response time for key presses. Any key press response time that is less than this value will be treated as invalid and ignored."},{"location":"reference/jspsych-pluginAPI/#return-value_3","title":"Return value","text":"Return an object that uniquely identifies the keyboard listener. This object can be passed to jsPsych.pluginAPI.cancelKeyboardResponse
to cancel the keyboard listener.
"},{"location":"reference/jspsych-pluginAPI/#description_3","title":"Description","text":"Gets a keyboard response from the participant, recording the response time from when the function is first called until a valid response is generated.
The keyboard event listener will be bound to the display_element
declared in initJsPsych()
(or the <body>
element if no display_element
is specified). This allows jsPsych experiments to be embedded in websites with other content without disrupting the functionality of other UI elements.
A valid response triggers the callback_function
specified in the parameters. A single argument is passed to the callback function. The argument contains an object with the properties key
and rt
. key
contains the string representation of the response key, and rt
contains the response time.
This function uses the .key
value of the keyboard event, which is case sensitive. When case_sensitive_responses
is false
in initJsPsych
(the default), this function will convert both the valid_responses
strings and the response key to lowercase before comparing them, and it will pass the lowercase version of the response key to the callback_function
. For example, if valid_responses
is ['a']
, then both 'A' and 'a' will be considered valid key presses, and 'a' will be returned as the response key. When case_sensitive_responses
is true
in initJsPsych
, this function will not convert the case when comparing the valid_responses
and response key, and it will not convert the case of the response key that is passed to the callback_function
. For example, if valid_responses
is ['a']
, then 'a' will be the only valid key press, and 'A' (i.e. 'a' with CapsLock on or Shift held down) will not be accepted. Also, if valid_responses
includes multiple letter case options (e.g. \"ALL_KEYS\"
), then you may need to check the response key against both letter cases when scoring etc., e.g. if (response == 'ArrowLeft' || response =='arrowleft') ...
.
"},{"location":"reference/jspsych-pluginAPI/#examples_1","title":"Examples","text":""},{"location":"reference/jspsych-pluginAPI/#get-a-single-response-from-any-key","title":"Get a single response from any key","text":"var after_response = function(info){\n alert('You pressed key '+info.key+' after '+info.rt+'ms');\n}\n\njsPsych.pluginAPI.getKeyboardResponse({\n callback_function:after_response,\n valid_responses: \"ALL_KEYS\",\n rt_method: 'performance',\n persist: false\n});\n
"},{"location":"reference/jspsych-pluginAPI/#get-a-responses-from-a-key-until-the-letter-q-is-pressed","title":"Get a responses from a key until the letter q is pressed","text":"var after_response = function(info){\n alert('You pressed key '+info.key+' after '+info.rt+'ms');\n\n if(jsPsych.pluginAPI.compareKeys(info.key,'q')){ /\n jsPsych.pluginAPI.cancelKeyboardResponse(listener);\n }\n}\n\nvar listener = jsPsych.pluginAPI.getKeyboardResponse({\n callback_function:after_response,\n valid_responses: \"ALL_KEYS\",\n rt_method: 'performance',\n persist: true\n});\n
"},{"location":"reference/jspsych-pluginAPI/#audio","title":"Audio","text":"All audio-related functionality is handled by the AudioPlayer class.
"},{"location":"reference/jspsych-pluginAPI/#getaudioplayer","title":"getAudioPlayer","text":"jsPsych.pluginAPI.getAudioPlayer(filepath)\n
"},{"location":"reference/jspsych-pluginAPI/#return-value_4","title":"Return value","text":"Returns a Promise that resolves to an instance of an AudioPlayer class that holds the buffer of the audio file when it finishes loading.
"},{"location":"reference/jspsych-pluginAPI/#description_4","title":"Description","text":"Gets an AudioPlayer class instance which has methods that can be used to play or stop audio that can be played with the WebAudio API or an audio object that can be played as HTML5 Audio.
It is strongly recommended that you preload audio files before calling this method. This method will load the files if they are not preloaded, but this may result in delays during the experiment as audio is downloaded.
"},{"location":"reference/jspsych-pluginAPI/#examples_2","title":"Examples","text":""},{"location":"reference/jspsych-pluginAPI/#html-5-audio-and-webaudio-api","title":"HTML 5 Audio and WebAudio API","text":"const audio = await jsPsych.pluginAPI.getAudioPlayer('my-sound.mp3')\n\naudio.play()\n
See the audio-keyboard-response
plugin for an example in a fuller context.
"},{"location":"reference/jspsych-pluginAPI/#play","title":"play","text":"const audio = jsPsych.pluginAPI.getAudioPlayer(filepath)\n\naudio.play()\n
"},{"location":"reference/jspsych-pluginAPI/#return-value_5","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-pluginAPI/#description_5","title":"Description","text":"Method that belongs to the AudioPlayer class. Plays the audio loaded into the audio buffer of the AudioPlayer instance for a particular file. If the audio is a HTML5 audio object it plays it. If the audio is a Webaudio API object it starts it.
"},{"location":"reference/jspsych-pluginAPI/#example_2","title":"Example","text":""},{"location":"reference/jspsych-pluginAPI/#html-5-audio-and-webaudio-api_1","title":"HTML 5 Audio and WebAudio API","text":"const audio = await jsPsych.pluginAPI.getAudioPlayer('my-sound.mp3');\n\naudio.play();\n
See the audio-keyboard-response
plugin for an example in a fuller context.
"},{"location":"reference/jspsych-pluginAPI/#stop","title":"stop","text":"const audio = jsPsych.pluginAPI.getAudioPlayer(filepath);\n\naudio.play();\n
"},{"location":"reference/jspsych-pluginAPI/#return-value_6","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-pluginAPI/#description_6","title":"Description","text":"Method that belongs to the AudioPlayer class. Stops the audio loaded into the audio buffer of the AudioPlayer instance for a particular file. If the audio is an HTML5 audio object it pauses it. If the audio is a Webaudio API object it stops it.
"},{"location":"reference/jspsych-pluginAPI/#example_3","title":"Example","text":""},{"location":"reference/jspsych-pluginAPI/#html-5-audio-and-webaudio-api_2","title":"HTML 5 Audio and WebAudio API","text":"const audio = await jsPsych.pluginAPI.getAudioPlayer('my-sound.mp3');\n\naudio.play();\n\naudio.stop();\n
See the audio-keyboard-response
plugin for an example in a fuller context.
"},{"location":"reference/jspsych-pluginAPI/#addeventlistener","title":"addEventListener","text":"const audio = jsPsych.pluginAPI.getAudioPlayer(filepath);\n\naudio.addEventListener(eventName, callback);\n
"},{"location":"reference/jspsych-pluginAPI/#return-value_7","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-pluginAPI/#description_7","title":"Description","text":"Method that belongs to the AudioPlayer class. Adds an event listener to the media Element that corresponds to the AudioPlayer class instance.
"},{"location":"reference/jspsych-pluginAPI/#example_4","title":"Example","text":"const audio = await jsPsych.pluginAPI.getAudioPlayer('my-sound.mp3');\n\naudio.play();\n\naudio.addEventListener('ended', end_trial());\n
See the audio-keyboard-response
plugin for an example in a fuller context.
"},{"location":"reference/jspsych-pluginAPI/#removeeventlistener","title":"removeEventListener","text":"const audio = jsPsych.pluginAPI.getAudioPlayer(filepath);\n\naudio.removeEventListener(eventName, callback);\n
"},{"location":"reference/jspsych-pluginAPI/#return-value_8","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-pluginAPI/#description_8","title":"Description","text":"Method that belongs to the AudioPlayer class. Removes an event listener from the media Element that corresponds to the AudioPlayer class instance.
"},{"location":"reference/jspsych-pluginAPI/#example_5","title":"Example","text":"const audio = await jsPsych.pluginAPI.getAudioPlayer('my-sound.mp3');\n\naudio.play();\n\naudio.addEventListener('ended', end_trial());\n\naudio.removeEventListener('ended', end_trial());\n
See the audio-keyboard-response
plugin for an example in a fuller context.
"},{"location":"reference/jspsych-pluginAPI/#other-media","title":"Other Media","text":""},{"location":"reference/jspsych-pluginAPI/#getaudiobuffer","title":"getAudioBuffer","text":"jsPsych.pluginAPI.getAudioBuffer(filepath)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_4","title":"Parameters","text":"Parameter Type Description filepath string The path to the audio file that was preloaded."},{"location":"reference/jspsych-pluginAPI/#return-value_9","title":"Return value","text":"Returns a Promise that resolves when the audio file loads. Success handler's parameter will be the audio buffer. If the experiment is running using the WebAudio API it will be an AudioBuffer object. Otherwise, it will be an HTML5 Audio object. The failure handler's parameter is the error generated by preloadAudio
.
"},{"location":"reference/jspsych-pluginAPI/#description_9","title":"Description","text":"Gets an AudioBuffer that can be played with the WebAudio API or an Audio object that can be played with HTML5 Audio.
It is strongly recommended that you preload audio files before calling this method. This method will load the files if they are not preloaded, but this may result in delays during the experiment as audio is downloaded.
"},{"location":"reference/jspsych-pluginAPI/#examples_3","title":"Examples","text":""},{"location":"reference/jspsych-pluginAPI/#html-5-audio","title":"HTML 5 Audio","text":"jsPsych.pluginAPI.getAudioBuffer('my-sound.mp3')\n .then(function(audio){\n audio.play();\n })\n .catch(function(err){\n console.error('Audio file failed to load')\n })\n
"},{"location":"reference/jspsych-pluginAPI/#webaudio-api","title":"WebAudio API","text":"var context = jsPsych.pluginAPI.audioContext();\n\njsPsych.pluginAPI.getAudioBuffer('my-sound.mp3')\n .then(function(buffer){\n audio = context.createBufferSource();\n audio.buffer = buffer;\n audio.connect(context.destination);\n audio.start(context.currentTime);\n })\n .catch(function(err){\n console.error('Audio file failed to load')\n })\n
See the audio-keyboard-response
plugin for an example in a fuller context.
"},{"location":"reference/jspsych-pluginAPI/#getautopreloadlist","title":"getAutoPreloadList","text":"jsPsych.pluginAPI.getAutoPreloadList(timeline)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_5","title":"Parameters","text":"Parameter Type Description timeline array An array containing the trial object(s) from which a list of media files should be automatically generated. This array can contain the entire experiment timeline, or any individual parts of a larger timeline, such as specific timeline nodes and trial objects."},{"location":"reference/jspsych-pluginAPI/#return-value_10","title":"Return value","text":"An object with properties for each media type: images
, audio
, and video
. Each property contains an array of the unique files of that media type that were automatically extracted from the timeline. If no files are found in the timeline for a particular media type, then the array will be empty for that type.
"},{"location":"reference/jspsych-pluginAPI/#description_10","title":"Description","text":"This method is used to automatically generate lists of unique image, audio, and video files from a timeline. It is used by the preload
plugin to generate a list of to-be-preloaded files based on the trials passed to the trials
parameter and/or the experiment timeline passed to jsPsych.run
(when auto_preload
is true). It can be used in custom plugins and experiment code to generate a list of audio/image/video files, based on a timeline.
This function will only return files from plugin parameters that are marked as parameter type AUDIO
/IMAGE
/VIDEO
, and only when the preload
flag of the corresponding parameter definition has not been set to false
, and the trial's parameter value is not a function. When a file path is returned to the trial parameter from a function (including the jsPsych.timelineVariable
function), or when the file path is embedded in an HTML string, that file will not be detected by the getAutoPreloadList
method. In these cases, the file should be preloaded manually. See Media Preloading for more information.
"},{"location":"reference/jspsych-pluginAPI/#example_6","title":"Example","text":"var audio_trial = {\n type: jsPsychAudioKeyboardResponse\n stimulus: 'file.mp3'\n}\n\nvar image_trial = {\n type: jsPsychImageKeyboardResponse\n stimulus: 'file.png'\n}\n\nvar video_trial = {\n type: jsPsychVideoKeyboardResponse\n stimulus: 'file.mp4'\n}\n\nvar timeline = [audio_trial, image_trial, video_trial];\n\njsPsych.pluginAPI.getAutoPreloadList(timeline);\n
"},{"location":"reference/jspsych-pluginAPI/#getcamerarecorder","title":"getCameraRecorder","text":"jsPsych.pluginAPI.getCameraRecorder()\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_6","title":"Parameters","text":"None
"},{"location":"reference/jspsych-pluginAPI/#return-value_11","title":"Return value","text":"A MediaRecorder
object connected to the MediaStream
for the active camera.
"},{"location":"reference/jspsych-pluginAPI/#description_11","title":"Description","text":"Provides access to the MediaRecorder
created by initializeCameraRecorder(). If no camera recorder exists, it returns null
.
"},{"location":"reference/jspsych-pluginAPI/#example_7","title":"Example","text":"const recorder = jsPsych.pluginAPI.getCameraRecorder();\n
"},{"location":"reference/jspsych-pluginAPI/#getmicrophonerecorder","title":"getMicrophoneRecorder","text":"jsPsych.pluginAPI.getMicrophoneRecorder()\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_7","title":"Parameters","text":"None
"},{"location":"reference/jspsych-pluginAPI/#return-value_12","title":"Return value","text":"A MediaRecorder
object connected to the MediaStream
for the active microphone.
"},{"location":"reference/jspsych-pluginAPI/#description_12","title":"Description","text":"Provides access to the MediaRecorder
created by initializeMicrophoneRecorder(). If no microphone recorder exists, it returns null
.
"},{"location":"reference/jspsych-pluginAPI/#example_8","title":"Example","text":"const recorder = jsPsych.pluginAPI.getMicrophoneRecorder();\n
"},{"location":"reference/jspsych-pluginAPI/#initializecamerarecorder","title":"initializeCameraRecorder","text":"jsPsych.pluginAPI.initializeCameraRecorder(stream)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_8","title":"Parameters","text":"Parameter Type Description stream MediaStream
The MediaStream
object from an active camera device. opts MediaRecorderOptions
The MediaRecorderOptions
for the recorder. See MDN docs for details about these options."},{"location":"reference/jspsych-pluginAPI/#return-value_13","title":"Return value","text":"None.
"},{"location":"reference/jspsych-pluginAPI/#description_13","title":"Description","text":"Generates a MediaRecorder
object from provided MediaStream
and stores this for access via getCameraRecorder().
"},{"location":"reference/jspsych-pluginAPI/#example_9","title":"Example","text":"const stream = await navigator.mediaDevices.getUserMedia({\n audio: true,\n video: { width: 1280, height: 720 }, // request a certain resolution\n});\n\njsPsych.pluginAPI.initializeCameraRecorder(stream);\n
"},{"location":"reference/jspsych-pluginAPI/#initializemicrophonerecorder","title":"initializeMicrophoneRecorder","text":"jsPsych.pluginAPI.initializeMicrophoneRecorder(stream)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_9","title":"Parameters","text":"Parameter Type Description stream MediaStream
The MediaStream
object from an active microphone device."},{"location":"reference/jspsych-pluginAPI/#return-value_14","title":"Return value","text":"None.
"},{"location":"reference/jspsych-pluginAPI/#description_14","title":"Description","text":"Generates a MediaRecorder
object from provided MediaStream
and stores this for access via getMicrophoneRecorder().
"},{"location":"reference/jspsych-pluginAPI/#example_10","title":"Example","text":"const stream = await navigator.mediaDevices.getUserMedia({ audio: { deviceId: mic_id } });\n\njsPsych.pluginAPI.initializeMicrophoneRecorder(stream);\n
"},{"location":"reference/jspsych-pluginAPI/#preloadaudio","title":"preloadAudio","text":"jsPsych.pluginAPI.preloadAudio(files, callback_complete, callback_load, callback_error)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_10","title":"Parameters","text":"Parameter Type Description files array An array of audio file paths to load. The array can be nested (e.g., if images are in multiple arrays to help sort by condition or task). callback_complete function A function to execute when all the files have been loaded. callback_load function A function to execute after a single file has been loaded. A single parameter is passed to this function which is the file source (string) that has loaded. callback_error function A function to execute after a single file has produced an error. A single parameter is passed to this function which is the file source (string) that produced the error."},{"location":"reference/jspsych-pluginAPI/#return-value_15","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-pluginAPI/#description_15","title":"Description","text":"This function is used to preload audio files. It is used by the preload
plugin, and could be called directly to preload audio files in custom plugins or experiment. See Media Preloading for more information.
It is possible to run this function without specifying a callback function. However, in this case the code will continue executing while the files are loaded. Thus, it is possible that an audio file would be required for playing before it is done preloading. The callback_complete
function will only execute after all the audio files are loaded, and can be used to control the flow of the experiment (e.g., by starting the experiment in the callback_complete
function).
The callback_load
and callback_error
functions are called after each file has either loaded or produced an error, so these functions can also be used to monitor loading progress. See example below.
"},{"location":"reference/jspsych-pluginAPI/#examples_4","title":"Examples","text":""},{"location":"reference/jspsych-pluginAPI/#basic-use","title":"Basic use","text":"var sounds = ['file1.mp3', 'file2.mp3', 'file3.mp3'];\n\njsPsych.pluginAPI.preloadAudio(sounds, \n function(){ startExperiment(); },\n function(file){ console.log('file loaded: ', file); }\n function(file){ console.log('error loading file: ', file); }\n);\n\nfunction startExperiment(){\n jsPsych.run(exp);\n}\n
"},{"location":"reference/jspsych-pluginAPI/#show-progress-of-loading","title":"Show progress of loading","text":"var sounds = ['file1.mp3', 'file2.mp3', 'file3.mp3'];\nvar n_loaded = 0;\n\njsPsych.pluginAPI.preloadAudio(sounds, function(){ startExperiment(); }, function(file) { updateLoadedCount(file); });\n\nfunction updateLoadedCount(file){\n n_loaded++;\n var percentcomplete = n_loaded / sounds.length * 100;\n\n // could put something fancier here, like a progress bar\n // or updating text in the DOM.\n console.log('Loaded '+percentcomplete+'% of audio files');\n}\n\nfunction startExperiment(){\n jsPsych.run(exp);\n}\n
"},{"location":"reference/jspsych-pluginAPI/#preloadimages","title":"preloadImages","text":"jsPsych.pluginAPI.preloadImages(images, callback_complete, callback_load, callback_error)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_11","title":"Parameters","text":"Parameter Type Description images array An array of image paths to load. The array can be nested (e.g., if images are in multiple arrays to help sort by condition or task). callback_complete function A function to execute when all the images have been loaded. callback_load function A function to execute after a single file has been loaded. A single parameter is passed to this function which is the file source (string) that has loaded. callback_error function A function to execute after a single file has produced an error. A single parameter is passed to this function which is the file source (string) that produced the error."},{"location":"reference/jspsych-pluginAPI/#return-value_16","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-pluginAPI/#description_16","title":"Description","text":"This function is used to preload image files. It is used by the preload
plugin, and could be called directly to preload image files in custom plugins or experiment code. See Media Preloading for more information.
It is possible to run this function without specifying a callback function. However, in this case the code will continue executing while the images are loaded. Thus, it is possible that an image would be required for display before it is done preloading. The callback_complete
function will only execute after all the images are loaded, and can be used to control the flow of the experiment (e.g., by starting the experiment in the callback_complete
function).
The callback_load
and callback_error
functions are called after each file has either loaded or produced an error, so these functions can also be used to monitor loading progress. See example below.
"},{"location":"reference/jspsych-pluginAPI/#examples_5","title":"Examples","text":""},{"location":"reference/jspsych-pluginAPI/#basic-use_1","title":"Basic use","text":"var images = ['img/file1.png', 'img/file2.png', 'img/file3.png'];\n\njsPsych.pluginAPI.preloadImages(images, \n function(){ startExperiment(); },\n function(file){ console.log('file loaded: ', file); }\n function(file){ console.log('error loading file: ', file); }\n);\n\nfunction startExperiment(){\n jsPsych.run(exp);\n}\n
"},{"location":"reference/jspsych-pluginAPI/#show-progress-of-loading_1","title":"Show progress of loading","text":"var images = ['img/file1.png', 'img/file2.png', 'img/file3.png'];\nvar n_loaded = 0;\n\njsPsych.pluginAPI.preloadImages(images, function(){ startExperiment(); }, function(file) { updateLoadedCount(file); });\n\nfunction updateLoadedCount(file){\n n_loaded++;\n var percentcomplete = n_loaded / images.length * 100;\n\n // could put something fancier here, like a progress bar\n // or updating text in the DOM.\n console.log('Loaded '+percentcomplete+'% of images');\n}\n\nfunction startExperiment(){\n jsPsych.run(exp);\n}\n
"},{"location":"reference/jspsych-pluginAPI/#preloadvideo","title":"preloadVideo","text":"jsPsych.pluginAPI.preloadVideo(video, callback_complete, callback_load, callback_error)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_12","title":"Parameters","text":"Parameter Type Description video array An array of video paths to load. The array can be nested (e.g., if videos are in multiple arrays to help sort by condition or task). callback_complete function A function to execute when all the videos have been loaded. callback_load function A function to execute after a single file has been loaded. A single parameter is passed to this function which is the file source (string) that has loaded. callback_error function A function to execute after a single file has produced an error. A single parameter is passed to this function which is the file source (string) that produced the error."},{"location":"reference/jspsych-pluginAPI/#return-value_17","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-pluginAPI/#description_17","title":"Description","text":"This function is used to preload video files. It is used by the preload
plugin, and could be called directly to preload video files in custom plugins or experiment code. See Media Preloading for more information.
It is possible to run this function without specifying a callback function. However, in this case the code will continue executing while the videos are loaded. Thus, it is possible that a video would be requested before it is done preloading. The callback_complete
function will only execute after all the videos are loaded, and can be used to control the flow of the experiment (e.g., by starting the experiment in the callback_complete
function).
The callback_load
and callback_error
functions are called after each file has either loaded or produced an error, so these functions can also be used to monitor loading progress. See example below.
"},{"location":"reference/jspsych-pluginAPI/#examples_6","title":"Examples","text":""},{"location":"reference/jspsych-pluginAPI/#basic-use_2","title":"Basic use","text":"var videos = ['vid/file1.mp4', 'vid/file2.mp4', 'vid/file3.mp4'];\n\njsPsych.pluginAPI.preloadVideo(videos, \n function(){ startExperiment(); },\n function(file){ console.log('file loaded: ', file); }\n function(file){ console.log('error loading file: ', file); }\n);\n\nfunction startExperiment(){\n jsPsych.run(exp);\n}\n
"},{"location":"reference/jspsych-pluginAPI/#show-progress-of-loading_2","title":"Show progress of loading","text":"var videos = ['vid/file1.mp4', 'vid/file2.mp4', 'vid/file3.mp4'];\nvar n_loaded = 0;\n\njsPsych.pluginAPI.preloadVideo(videos, function(){ startExperiment(); }, function(file) { updateLoadedCount(file); });\n\nfunction updateLoadedCount(file){\n n_loaded++;\n var percentcomplete = n_loaded / videos.length * 100;\n\n // could put something fancier here, like a progress bar\n // or updating text in the DOM.\n console.log('Loaded '+percentcomplete+'% of videos');\n}\n\nfunction startExperiment(){\n jsPsych.run(exp);\n}\n
"},{"location":"reference/jspsych-pluginAPI/#simulation","title":"Simulation","text":""},{"location":"reference/jspsych-pluginAPI/#clicktarget","title":"clickTarget","text":"jsPsych.pluginAPI.clickTarget(target, delay)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_13","title":"Parameters","text":"Parameter Type Description target Element The DOM element to simulate clicking on. delay number Time to wait in milliseconds. The click will be executed after the delay."},{"location":"reference/jspsych-pluginAPI/#return-value_18","title":"Return value","text":"None
"},{"location":"reference/jspsych-pluginAPI/#description_18","title":"Description","text":"Simulates clicking on a DOM element by dispatching three MouseEvents on the target
: 'mousedown'
, then 'mouseup'
, then 'click'
. If delay
is positive, then the events are scheduled to execute after the delay via setTimeout
.
"},{"location":"reference/jspsych-pluginAPI/#example_11","title":"Example","text":"const target = document.querySelector('.jspsych-btn');\n\njsPsych.pluginAPI.clickTarget(target, 500);\n
"},{"location":"reference/jspsych-pluginAPI/#ensuresimulationdataconsistency","title":"ensureSimulationDataConsistency","text":"jsPsych.pluginAPI.ensureSimulationDataConsistency(trial, data)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_14","title":"Parameters","text":"Parameter Type Description trial object Parameters for the trial, e.g., those passed to the plugin's trial()
method. data object An object containing data for the trial."},{"location":"reference/jspsych-pluginAPI/#return-value_19","title":"Return value","text":"None. The data
object is modified in place by this method.
"},{"location":"reference/jspsych-pluginAPI/#description_19","title":"Description","text":"Performs some basic consistency checks on the data
based on the parameters specified in trial
. For example, if trial.choices
is \"NO_KEYS\"
but data.response
is a key string then data.response
and data.rt
are set to null
.
"},{"location":"reference/jspsych-pluginAPI/#example_12","title":"Example","text":"jsPsych.pluginAPI.ensureSimulationDataConsistency(trial, data);\n
"},{"location":"reference/jspsych-pluginAPI/#filltextinput","title":"fillTextInput","text":"jsPsych.pluginAPI.fillTextInput(target, text, delay)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_15","title":"Parameters","text":"Parameter Type Description target HTMLInputElement The input element to fill in with text. text string The text to input. delay number Time to wait in milliseconds. The text will be inserted after the delay."},{"location":"reference/jspsych-pluginAPI/#return-value_20","title":"Return value","text":"None
"},{"location":"reference/jspsych-pluginAPI/#description_20","title":"Description","text":"Sets the value of the target
HTMLInputElement to equal text
.
"},{"location":"reference/jspsych-pluginAPI/#example_13","title":"Example","text":"const target = document.querySelector('input[type=\"text\"]');\n\njsPsych.pluginAPI.fillTextInput(target, \"hello!\", 500);\n
"},{"location":"reference/jspsych-pluginAPI/#getvalidkey","title":"getValidKey","text":"jsPsych.pluginAPI.getValidKey(choices)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_16","title":"Parameters","text":"Parameter Type Description choices \"NO_KEYS\" or \"ALL_KEYS\" or array of strings Representation of the valid keys allowed for a keyboard response used by the getKeyboardResponse
method."},{"location":"reference/jspsych-pluginAPI/#return-value_21","title":"Return value","text":"A valid key given the choices
parameter, chosen at random from the possible keys.
"},{"location":"reference/jspsych-pluginAPI/#description_21","title":"Description","text":"Picks a random key given a set of options. Currently it only picks letters and numbers when choices
is \"ALL_KEYS\"
.
"},{"location":"reference/jspsych-pluginAPI/#example_14","title":"Example","text":"const random_key = jsPsych.pluginAPI.getValidKey(trial.choices);\n
"},{"location":"reference/jspsych-pluginAPI/#keydown","title":"keyDown","text":"jsPsych.pluginAPI.keyDown(key)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_17","title":"Parameters","text":"Parameter Type Description key string The .key
property of the corresponding key on the keyboard."},{"location":"reference/jspsych-pluginAPI/#return-value_22","title":"Return value","text":"None.
"},{"location":"reference/jspsych-pluginAPI/#description_22","title":"Description","text":"Dispatches a 'keydown'
event for the specified key
.
"},{"location":"reference/jspsych-pluginAPI/#example_15","title":"Example","text":"jsPsych.pluginAPI.keyDown('a');\n
"},{"location":"reference/jspsych-pluginAPI/#keyup","title":"keyUp","text":"jsPsych.pluginAPI.keyUp(key)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_18","title":"Parameters","text":"Parameter Type Description key string The .key
property of the corresponding key on the keyboard."},{"location":"reference/jspsych-pluginAPI/#return-value_23","title":"Return value","text":"None.
"},{"location":"reference/jspsych-pluginAPI/#description_23","title":"Description","text":"Dispatches a 'keyup'
event for the specified key
.
"},{"location":"reference/jspsych-pluginAPI/#example_16","title":"Example","text":"jsPsych.pluginAPI.keyUp('a');\n
"},{"location":"reference/jspsych-pluginAPI/#mergesimulationdata","title":"mergeSimulationData","text":"jsPsych.pluginAPI.mergeSimulationData(default_data, simulation_options)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_19","title":"Parameters","text":"Parameter Type Description default_data object An object containing data values for the simulated trial. simulation_options object The simulation_options
specified for the trial."},{"location":"reference/jspsych-pluginAPI/#return-value_24","title":"Return value","text":"An object of data.
"},{"location":"reference/jspsych-pluginAPI/#description_24","title":"Description","text":"This method merges the default_data
with any data specified in simulation_options.data
, giving priority to values specified in simulation_options.data
. It returns the merged data.
"},{"location":"reference/jspsych-pluginAPI/#example_17","title":"Example","text":"const default_data = {\n rt: 500,\n response: 'a'\n}\n\nconst simulation_options = {\n data: {\n rt: 200\n }\n}\n\nconst data = jsPsych.pluginAPI.mergeSimulationData(default_data, simulation_options);\n\ndata.rt === 200; // true\n
"},{"location":"reference/jspsych-pluginAPI/#timeouts","title":"Timeouts","text":""},{"location":"reference/jspsych-pluginAPI/#clearalltimeouts","title":"clearAllTimeouts","text":"jsPsych.pluginAPI.clearAllTimeouts()\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_20","title":"Parameters","text":"None.
"},{"location":"reference/jspsych-pluginAPI/#return-value_25","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-pluginAPI/#description_25","title":"Description","text":"Clears any pending timeouts that were set using jsPsych.pluginAPI.setTimeout().
"},{"location":"reference/jspsych-pluginAPI/#settimeout","title":"setTimeout","text":"jsPsych.pluginAPI.setTimeout(callback, delay)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_21","title":"Parameters","text":"Parameter Type Description callback function A function to execute after waiting for delay. delay integer Time to wait in milliseconds."},{"location":"reference/jspsych-pluginAPI/#return-value_26","title":"Return value","text":"Returns the ID of the setTimeout handle.
"},{"location":"reference/jspsych-pluginAPI/#description_26","title":"Description","text":"This is simply a call to the standard setTimeout function in JavaScript with the added benefit of registering the setTimeout call in a central list. This is useful for scenarios where some other event (the trial ending, aborting the experiment) should stop the execution of queued timeouts.
"},{"location":"reference/jspsych-pluginAPI/#example_18","title":"Example","text":"// print the time\nconsole.log(Date.now())\n\n// print the time 1s later\njsPsych.pluginAPI.setTimeout(function(){\n console.log(Date.now())\n}, 1000);\n
"},{"location":"reference/jspsych-randomization/","title":"jsPsych.randomization","text":"The jsPsych.randomization module contains methods that are useful for generating random lists of trial variables.
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationfactorial","title":"jsPsych.randomization.factorial","text":"jsPsych.randomization.factorial(factors, repetitions, unpack)\n
"},{"location":"reference/jspsych-randomization/#parameters","title":"Parameters","text":"Parameter Type Description factors object The factors
object should contain a property for each different factor. Each property-factor should have a value of an array, with each element of the array corresponding to a level of the factor. repetitions integer The number of times to repeat each unique combination of the factors in the output sample. unpack boolean If true
then the output will be an object with a property for each factor in the original factors
object. The value of each property-factor will be an array containing the levels of the factor in a random order. The order will be consistent across each property-factor (e.g., the first element of each property-factor will specify one unique combination of the factors). If false
, then the return value will be an array of objects where each property-factor contains only a single value."},{"location":"reference/jspsych-randomization/#return-value","title":"Return value","text":"The return value depends on the unpack
parameter. See description of the parameter above, and examples below.
"},{"location":"reference/jspsych-randomization/#description","title":"Description","text":"This method takes a list of factors and their levels, and creates a full factorial design by creating each unique combination of the factors. The returned set of combinations is in a random order.
"},{"location":"reference/jspsych-randomization/#examples","title":"Examples","text":""},{"location":"reference/jspsych-randomization/#create-full-factorial-design","title":"Create full factorial design","text":"var factors = {\n stimulus: ['a.jpg', 'b.jpg'],\n ms_delay: [100, 200]\n}\n\nvar full_design = jsPsych.randomization.factorial(factors, 1);\n\n/*\noutput:\nfull_design = [\n {stimulus: 'a.jpg', ms_delay: 200},\n {stimulus: 'b.jpg', ms_delay: 200},\n {stimulus: 'b.jpg', ms_delay: 100},\n {stimulus: 'a.jpg', ms_delay: 100},\n]\n*/\n
"},{"location":"reference/jspsych-randomization/#create-full-factorial-design-with-repeats","title":"Create full factorial design with repeats","text":"var factors = {\n stimulus: ['a.jpg', 'b.jpg'],\n ms_delay: [100, 200]\n}\n\nvar full_design = jsPsych.randomization.factorial(factors, 2);\n\n/*\noutput:\nfull_design = [\n {stimulus: 'b.jpg', ms_delay: 200},\n {stimulus: 'b.jpg', ms_delay: 100},\n {stimulus: 'b.jpg', ms_delay: 100},\n {stimulus: 'a.jpg', ms_delay: 100},\n {stimulus: 'a.jpg', ms_delay: 200},\n {stimulus: 'b.jpg', ms_delay: 200},\n {stimulus: 'a.jpg', ms_delay: 100},\n {stimulus: 'a.jpg', ms_delay: 200},\n]\n*/\n
"},{"location":"reference/jspsych-randomization/#create-full-factorial-design-unpacked","title":"Create full factorial design, unpacked","text":"var factors = {\n stimulus: ['a.jpg', 'b.jpg'],\n ms_delay: [100, 200]\n}\n\nvar full_design = jsPsych.randomization.factorial(factors, 1, true);\n\n/*\noutput:\nfull_design = {\n stimulus: ['a.jpg','b.jpg','b.jpg','a.jpg'],\n ms_delay: [200, 100, 200, 100]\n]\n*/\n
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationrandomid","title":"jsPsych.randomization.randomID","text":"jsPsych.randomization.randomID(length)\n
"},{"location":"reference/jspsych-randomization/#parameters_1","title":"Parameters","text":"Parameter Type Description length integer The length of the randomly generated ID"},{"location":"reference/jspsych-randomization/#return-value_1","title":"Return value","text":"Returns a string of length length
where each character is randomly selected from the numbers 0-9 and all lowercase English letters a-z.
"},{"location":"reference/jspsych-randomization/#description_1","title":"Description","text":"Generates a random string that is likely to be unique. If length is undefined, then the string length is 32.
"},{"location":"reference/jspsych-randomization/#example","title":"Example","text":"console.log(jsPsych.randomization.randomID());\n// outputs: \"t7dwz0e713pc8juuaayyfvpkdd9un239\"\n\nconsole.log(jsPsych.randomization.randomID(8));\n// outputs: \"3xtpcbck\"\n
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationrandomint","title":"jsPsych.randomization.randomInt","text":"jsPsych.randomization.randomInt(lower, upper)\n
"},{"location":"reference/jspsych-randomization/#parameters_2","title":"Parameters","text":"Parameter Type Description lower integer The smallest value it is possible to generate upper integer The largest value it is possible to generate"},{"location":"reference/jspsych-randomization/#return-value_2","title":"Return value","text":"An integer
"},{"location":"reference/jspsych-randomization/#description_2","title":"Description","text":"Generates a random integer from lower
to upper
"},{"location":"reference/jspsych-randomization/#example_1","title":"Example","text":"console.log(jsPsych.randomization.randomInt(2,4));\n// outputs: 2 or 3 or 4.\n
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationrepeat","title":"jsPsych.randomization.repeat","text":"jsPsych.randomization.repeat(array, repetitions, unpack)\n
"},{"location":"reference/jspsych-randomization/#parameters_3","title":"Parameters","text":"Parameter Type Description array array The array of values to randomize & repeat. repetitions integer or array The number of times to repeat each element of the array
in the final sample. If this parameter is defined as an integer, then each element of array
is repeated the same number of times. This parameter can also be an array of the same length as array
, in which case each element of array
will be repeated the number of times defined in the corresponding position of the repetitions
array. unpack boolean If each element of array
is an object with an equivalent set of properties, then setting unpack
to true
will make the return value an object with a property for each of the unique properties among the elements of the array
. Each property in the output object will be an array containing the values for that property in the randomized order. The order will be consistent across properties. If this is false
then the output is just an array containing a randomized order of the original array
elements."},{"location":"reference/jspsych-randomization/#return-value_3","title":"Return value","text":"The return value depends on the unpack
parameter. See description of the parameter above, and examples below.
"},{"location":"reference/jspsych-randomization/#description_3","title":"Description","text":"This method takes an array of values and generates a new random order of the array, with the option of repeating each element of the array a specified number of times.
If the array elements are objects with the same set of properties, then this method can optionally return a single object where each property is a randomized order of the properties defined in the original set of objects. This is useful for randomizing sets of parameters that are used to define a jsPsych block.
"},{"location":"reference/jspsych-randomization/#examples_1","title":"Examples","text":""},{"location":"reference/jspsych-randomization/#shuffle-an-array-no-repeats","title":"Shuffle an array, no repeats","text":"var myArray = [1,2,3,4,5];\nvar shuffledArray = jsPsych.randomization.repeat(myArray, 1);\n// output: shuffledArray = [3,2,4,1,5]\n
"},{"location":"reference/jspsych-randomization/#shuffle-an-array-with-repeats","title":"Shuffle an array with repeats","text":"var myArray = [1,2,3,4,5];\nvar shuffledArray = jsPsych.randomization.repeat(myArray, 2);\n// output: shuffledArray = [1,3,4,2,2,4,5,1,5,3]\n
"},{"location":"reference/jspsych-randomization/#shuffle-an-array-of-objects","title":"Shuffle an array of objects","text":"var trial1 = {\n stimulus: 'img/faceA.jpg',\n correct_key: 'p',\n person_name: 'Joe'\n}\n\nvar trial2 = {\n stimulus: 'img/faceB.jpg',\n correct_key: 'p',\n person_name: 'Fred'\n}\n\nvar trial3 = {\n stimulus: 'img/faceC.jpg',\n correct_key: 'q',\n person_name: 'Mary'\n}\n\nvar myArray = [ trial1, trial2, trial3 ];\nvar shuffledArray = jsPsych.randomization.repeat(myArray, 2);\n\n// output: shuffledArray = [ trial1, trial3, trial3, trial2, trial1, trial2 ]\n
"},{"location":"reference/jspsych-randomization/#shuffle-an-array-of-objects-with-unpack","title":"Shuffle an array of objects, with unpack","text":"var trial1 = {\n stimulus: 'img/faceA.jpg',\n correct_key: 'p',\n person_name: 'Joe'\n}\n\nvar trial2 = {\n stimulus: 'img/faceB.jpg',\n correct_key: 'p',\n person_name: 'Fred'\n}\n\nvar trial3 = {\n stimulus: 'img/faceC.jpg',\n correct_key: 'q',\n person_name: 'Mary'\n}\n\nvar myArray = [ trial1, trial2, trial3 ];\nvar shuffledArray = jsPsych.randomization.repeat(myArray, 2, true);\n\n/*\noutput: shuffledArray = {\n stimulus: ['img/faceB.jpg','img/faceA.jpg','img/faceC.jpg','img/faceA.jpg','img/faceC.jpg','img/faceB.jpg'],\n correct_key: ['p', 'p', 'q', 'p', 'q', 'p'],\n person_name: ['Fred', 'Joe', 'Mary', 'Joe', 'Mary', 'Fred']\n}\n*/\n
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationsamplebernoulli","title":"jsPsych.randomization.sampleBernoulli","text":"jsPsych.randomization.sampleBernoulli(p)\n
"},{"location":"reference/jspsych-randomization/#parameters_4","title":"Parameters","text":"Parameter Type Description p number Probability of sampling 1"},{"location":"reference/jspsych-randomization/#return-value_4","title":"Return value","text":"Returns 0 with probability 1-p
and 1 with probability p
.
"},{"location":"reference/jspsych-randomization/#description_4","title":"Description","text":"Generates a random sample from a Bernoulli distribution.
"},{"location":"reference/jspsych-randomization/#examples_2","title":"Examples","text":""},{"location":"reference/jspsych-randomization/#sample-a-value","title":"Sample a value","text":"if(jsPsych.randomization.sampleBernoulli(0.8)){\n // this happens 80% of the time\n} else {\n // this happens 20% of the time\n}\n
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationsampleexgaussian","title":"jsPsych.randomization.sampleExGaussian","text":"jsPsych.randomization.sampleExGaussian(mean, standard_deviation, rate, positive=false)\n
"},{"location":"reference/jspsych-randomization/#parameters_5","title":"Parameters","text":"Parameter Type Description mean number Mean of the normal distribution component of the exGaussian standard_deviation number Standard deviation of the normal distribution component of the exGaussian rate number Rate of the exponential distribution component of the exGaussian positive bool If true
sample will be constrained to > 0."},{"location":"reference/jspsych-randomization/#return-value_5","title":"Return value","text":"A random sample from the distribution
"},{"location":"reference/jspsych-randomization/#description_5","title":"Description","text":"Generates a random sample from an exponentially modified Gaussian distribution.
"},{"location":"reference/jspsych-randomization/#examples_3","title":"Examples","text":""},{"location":"reference/jspsych-randomization/#sample-a-value_1","title":"Sample a value","text":"var rand_sample_exg = jsPsych.randomization.sampleExGaussian(500, 100, 0.01);\n
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationsampleexponential","title":"jsPsych.randomization.sampleExponential","text":"jsPsych.randomization.sampleExponential(rate)\n
"},{"location":"reference/jspsych-randomization/#parameters_6","title":"Parameters","text":"Parameter Type Description rate number Rate of the exponential distribution"},{"location":"reference/jspsych-randomization/#return-value_6","title":"Return value","text":"A random sample from the distribution
"},{"location":"reference/jspsych-randomization/#description_6","title":"Description","text":"Generates a random sample from an exponential distribution.
"},{"location":"reference/jspsych-randomization/#examples_4","title":"Examples","text":""},{"location":"reference/jspsych-randomization/#sample-a-value_2","title":"Sample a value","text":"var rand_sample_exg = jsPsych.randomization.sampleExponential(0.01);\n
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationsamplenormal","title":"jsPsych.randomization.sampleNormal","text":"jsPsych.randomization.sampleNormal(mean, standard_deviation)\n
"},{"location":"reference/jspsych-randomization/#parameters_7","title":"Parameters","text":"Parameter Type Description mean number Mean of the normal distribution standard_deviation number Standard deviation of the normal distribution"},{"location":"reference/jspsych-randomization/#return-value_7","title":"Return value","text":"A random sample from the distribution
"},{"location":"reference/jspsych-randomization/#description_7","title":"Description","text":"Generates a random sample from a normal distribution.
"},{"location":"reference/jspsych-randomization/#examples_5","title":"Examples","text":""},{"location":"reference/jspsych-randomization/#sample-a-value_3","title":"Sample a value","text":"var rand_sample_exg = jsPsych.randomization.sampleNormal(500, 250);\n
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationsamplewithreplacement","title":"jsPsych.randomization.sampleWithReplacement","text":"jsPsych.randomization.sampleWithReplacement(array, sampleSize, weights)\n
"},{"location":"reference/jspsych-randomization/#parameters_8","title":"Parameters","text":"Parameter Type Description array array The array of values to sample from sampleSize numeric The number of samples to draw weights array The relative weight of each element in array
. This array is normalized, so the values do not need to sum to 1. The length must match the length of array
."},{"location":"reference/jspsych-randomization/#return-value_8","title":"Return value","text":"An array containing the sample.
"},{"location":"reference/jspsych-randomization/#description_8","title":"Description","text":"This method returns a sample drawn at random from a set of values with replacement. The relative probability of drawing each item can be controlled by specifying the weights
.
"},{"location":"reference/jspsych-randomization/#examples_6","title":"Examples","text":""},{"location":"reference/jspsych-randomization/#sample-with-equal-probability","title":"Sample with equal probability","text":"var myArray = [1,2,3,4,5];\nvar sample = jsPsych.randomization.sampleWithReplacement(myArray, 10);\n// output: sample = [3, 1, 2, 2, 5, 1, 4, 3, 1, 5];\n
"},{"location":"reference/jspsych-randomization/#sample-with-unequal-probability","title":"Sample with unequal probability","text":"var myArray = [1,2,3,4,5];\nvar sample = jsPsych.randomization.sampleWithReplacement(myArray, 10, [6,1,1,1,1]);\n// output: sample = [3, 4, 5, 1, 2, 1, 3, 1, 1, 1];\n
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationsamplewithoutreplacement","title":"jsPsych.randomization.sampleWithoutReplacement","text":"jsPsych.randomization.sampleWithoutReplacement(array, sampleSize)\n
"},{"location":"reference/jspsych-randomization/#parameters_9","title":"Parameters","text":"Parameter Type Description array array The array of values to sample from sampleSize numeric The number of samples to draw"},{"location":"reference/jspsych-randomization/#return-value_9","title":"Return value","text":"An array containing the sample.
"},{"location":"reference/jspsych-randomization/#description_9","title":"Description","text":"This method returns a sample drawn at random from a set of values without replacement. The sample size must be less than or equal to the length of the array.
"},{"location":"reference/jspsych-randomization/#examples_7","title":"Examples","text":""},{"location":"reference/jspsych-randomization/#sample-without-replacement","title":"Sample without replacement","text":"var myArray = [1,2,3,4,5];\nvar sample = jsPsych.randomization.sampleWithoutReplacement(myArray, 2);\n// output: sample = [3,2];\n
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationsetseed","title":"jsPsych.randomization.setSeed","text":"jsPsych.randomization.setSeed(seed)\n
"},{"location":"reference/jspsych-randomization/#parameters_10","title":"Parameters","text":"Parameter Type Description seed string A seed for the random number generator"},{"location":"reference/jspsych-randomization/#return-value_10","title":"Return value","text":"Returns the seed value.
"},{"location":"reference/jspsych-randomization/#description_10","title":"Description","text":"This function will override the behavior of Math.random()
to produce a seedable pseudo random number generator. It uses the seedrandom package. Note that calling setSeed()
will change how Math.random()
behaves for the entire document. If you have non-jsPsych components on the page that use Math.random()
they will be affected.
Using setSeed()
without passing in a seed will generate a random 32-bit seed. The seed value will be returned from the function call, allowing you to save it in the data for the experiment if needed.
"},{"location":"reference/jspsych-randomization/#examples_8","title":"Examples","text":""},{"location":"reference/jspsych-randomization/#use-a-random-32-bit-seed-and-save-to-data","title":"Use a random 32-bit seed and save to data","text":"const seed = jsPsych.randomization.setSeed();\njsPsych.data.addProperties({\n rng_seed: seed\n});\n
"},{"location":"reference/jspsych-randomization/#use-your-own-seed","title":"Use your own seed","text":"jsPsych.randomization.setSeed(\"jspsych\");\n
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationshuffle","title":"jsPsych.randomization.shuffle","text":"jsPsych.randomization.shuffle(array)\n
"},{"location":"reference/jspsych-randomization/#parameters_11","title":"Parameters","text":"Parameter Type Description array array The array of values to shuffle"},{"location":"reference/jspsych-randomization/#return-value_11","title":"Return value","text":"Returns an array with the same elements as the input array in a random order.
"},{"location":"reference/jspsych-randomization/#description_11","title":"Description","text":"A simple method for shuffling the order of an array.
"},{"location":"reference/jspsych-randomization/#examples_9","title":"Examples","text":""},{"location":"reference/jspsych-randomization/#shuffle-an-array","title":"Shuffle an array","text":"var myArray = [1,2,3,4,5];\nvar shuffledArray = jsPsych.randomization.shuffle(myArray);\n// output: shuffledArray = [3,2,4,1,5]\n
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationshufflenorepeats","title":"jsPsych.randomization.shuffleNoRepeats","text":"jsPsych.randomization.shuffleNoRepeats(array, equalityTest)\n
"},{"location":"reference/jspsych-randomization/#parameters_12","title":"Parameters","text":"Parameter Type Description array array The array of values to shuffle equalityTest function A function to use to evaluate the equality of neighbors in the array. The function should accept two parameters, which are the two elements to be tested. It should return true
if they are equal and false
if not. The default function, if none is specified, is to use the ===
operator. This will work for primitive values, but fail for Objects and Arrays. An example function is given below in the examples."},{"location":"reference/jspsych-randomization/#return-value_12","title":"Return value","text":"Returns an array with the same elements as the input array in a random order, with no repeating neighbors.
"},{"location":"reference/jspsych-randomization/#description_12","title":"Description","text":"Shuffle an array, ensuring that neighboring elements in the array are different.
Warning: if you provide an array that has very few valid permutations with no neighboring elements, then this method will fail and cause the browser to hang.
"},{"location":"reference/jspsych-randomization/#examples_10","title":"Examples","text":""},{"location":"reference/jspsych-randomization/#basic-example","title":"Basic example","text":"var myArray = [1,2,3,4,5,1,2,3,4,5,1,2,3,4,5];\nvar shuffledArray = jsPsych.randomization.shuffleNoRepeats(myArray);\n// output: shuffledArray = [2, 3, 5, 1, 2, 4, 1, 5, 4, 1, 3, 5, 4, 3, 2]\n
"},{"location":"reference/jspsych-randomization/#custom-equalitytest","title":"Custom equalityTest","text":"var myObjects = [\n {color:\"blue\"},\n {color:\"red\"},\n {color:\"yellow\"},\n {color:\"orange\"}\n];\n\nvar repeatedSet = jsPsych.randomization.repeat(myObjects,3);\nvar shuffled = jsPsych.randomization.shuffleNoRepeats(repeatedSet, function(a,b) { return a.color === b.color });\n\n// console.log(JSON.stringify(shuffled))\n// \"[{\"color\":\"red\"},{\"color\":\"yellow\"},{\"color\":\"blue\"},{\"color\":\"yellow\"},{\"color\":\"orange\"},{\"color\":\"red\"},{\"color\":\"yellow\"},{\"color\":\"orange\"},{\"color\":\"blue\"},{\"color\":\"orange\"},{\"color\":\"red\"},{\"color\":\"blue\"}]\"\n
"},{"location":"reference/jspsych-turk/","title":"jsPsych.turk","text":"The jsPsych.turk module contains functions for interacting with Mechanical Turk.
"},{"location":"reference/jspsych-turk/#jspsychturksubmittoturk","title":"jsPsych.turk.submitToTurk","text":"jsPsych.turk.submitToTurk(data)\n
"},{"location":"reference/jspsych-turk/#parameters","title":"Parameters","text":"Parameter Type Description data object The data
parameter is an object of key: value
pairs. Any pairs in the data
parameter will be saved by Mechanical Turk, and can be downloaded in a CSV file through the Mechanical Turk interface. Important: the data
parameter must contain at least one key: value
pair, even just a dummy value, or the HIT will not be submitted correctly."},{"location":"reference/jspsych-turk/#return-value","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-turk/#description","title":"Description","text":"This method will submit a HIT to Mechanical Turk, causing the HIT to finish.
This method will only work when called from within the mechanical turk website. If you are using an external HIT to send workers to your own server, this method will not work on an externally hosted page. It will work if your external content is loaded in the iframe on the Mechanical Turk website.
"},{"location":"reference/jspsych-turk/#example","title":"Example","text":"<p>Enter the code you were given:</p>\n<input type=\"text\" id=\"code\"></input>\n<button onclick=\"sendData();\">Submit HIT</button>\n\n<script>\n// this content must be loaded in the iframe on the mechanical turk website.\n// usually, this means that the content is part of your 'recruitment ad', the\n// page the workers can see when they are deciding whether or not to accept a HIT.\n// one option is to include a simple form on this page that workers submit, with a\n// special code that they get at the end of the experiment.\n\nfunction sendData() {\n jsPsych.turk.submitToTurk({\n code: document.getElementById('code').value\n });\n}\n</script>\n
"},{"location":"reference/jspsych-turk/#jspsychturkturkinfo","title":"jsPsych.turk.turkInfo","text":"jsPsych.turk.turkInfo()\n
"},{"location":"reference/jspsych-turk/#parameters_1","title":"Parameters","text":"None.
"},{"location":"reference/jspsych-turk/#return-value_1","title":"Return value","text":"Returns an object with six properties:
.assignmentId
contains the assignment ID string of the HIT. .hitId
contains the HIT ID. .workerId
contains the worker ID of the worker completing the HIT. .turkSubmitTo
contains the URL for submitting the HIT. This parameter is used in the jsPsych.turk.submitToTurk
method, and is probably not useful outside of that context. .previewMode
is a boolean value indicating whether or not the worker has accepted the HIT yet. If the page is viewed inside Mechancial Turk and the worker has not clicked 'Accept HIT' then this will be true. If the page is viewed outside Mechanical Turk or the worker has acccepted the HIT, then it will be false. .outsideTurk
is a boolean value indicating if the page is being viewed within Mechanical Turk, or if it is being viewed from another source (e.g., someone directly going to the page URL instead of going through mturk).
"},{"location":"reference/jspsych-turk/#description_1","title":"Description","text":"This method returns basic information about the current Mechanical Turk session, including the worker ID, assignment ID, and HIT ID.
"},{"location":"reference/jspsych-turk/#example_1","title":"Example","text":"var turkInfo = jsPsych.turk.turkInfo();\n\nalert('Worker ID is: ' + turkInfo.workerId);\n\nalert('Assignment ID is: ' + turkInfo.assignmentId);\n\nalert('HIT ID is: ' + turkInfo.hitId);\n\n// true if the page is viewed within Mechanical Turk, \n// but worker has not accepted the HIT yet.\n// false if the page is viewed outside Mechanical Turk,\n// OR the worker has accepted the HIT.\nalert('Preview mode? ' + turkInfo.previewMode); \n\n// true if the page is viewed outside mechanical turk,\n// false otherwise.\nalert('Outside turk? ' + turkInfo.outsideTurk);\n
"},{"location":"reference/jspsych/","title":"jsPsych","text":""},{"location":"reference/jspsych/#initjspsych","title":"initJsPsych","text":"var jsPsych = initJsPsych(settings);\n
"},{"location":"reference/jspsych/#parameters","title":"Parameters","text":"Parameter Type Description settings object The settings object for initializing jsPsych. See table below. The settings object can contain several parameters. None of the parameters are required.
Parameter Type Description display_element string The ID of an HTML element to display the experiment in. If left blank, jsPsych will use the <body>
element to display content. All keyboard event listeners are bound to this element. In order for a keyboard event to be detected, this element must have focus (be the last thing that the participant clicked on). on_finish function Function to execute when the experiment ends. on_trial_start function Function to execute when a new trial begins. on_trial_finish function Function to execute when a trial ends. on_data_update function Function to execute every time data is stored using the jsPsych.data.write
method. All plugins use this method to save data (via a call to jsPsych.finishTrial
, so this function runs every time a plugin stores new data. on_interaction_data_update function Function to execute every time a new interaction event occurs. Interaction events include clicking on a different window (blur), returning to the experiment window (focus), entering full screen mode (fullscreenenter), and exiting full screen mode (fullscreenexit). on_close function Function to execute when the user leaves the page. Can be used, for example, to save data before the page is closed. show_progress_bar boolean If true
, then a progress bar is shown at the top of the page. Default is false
. message_progress_bar string or function Message to display next to the progress bar or a function that returns that message. The default is 'Completion Progress'. If message_progress_bar
is a function, it receives one single argument which is the current progress, ranging from 0 to 1; the function gets called on every progress bar update automatically. auto_update_progress_bar boolean If true, then the progress bar at the top of the page will automatically update as every top-level timeline or trial is completed. use_webaudio boolean If false, then jsPsych will not attempt to use the WebAudio API for audio playback. Instead, HTML5 Audio objects will be used. The WebAudio API offers more precise control over the timing of audio events, and should be used when possible. The default value is true
. default_iti numeric The default inter-trial interval in ms. The default value if none is specified is 0ms. experiment_width numeric The desired width of the jsPsych container in pixels. If left undefined, the width will be 100% of the display element. Usually this is the <body>
element, and the width will be 100% of the screen size. minimum_valid_rt numeric The minimum valid response time for key presses during the experiment. Any key press response time that is less than this value will be treated as invalid and ignored. Note that this parameter only applies to keyboard responses, and not to other response types such as buttons and sliders. The default value is 0. override_safe_mode boolean Running a jsPsych experiment directly in a web browser (e.g., by double clicking on a local HTML file) will load the page using the file://
protocol. Some features of jsPsych don't work with this protocol. By default, when jsPsych detects that it's running on a page loaded via the file://
protocol, it runs in safe mode, which automatically disables features that don't work in this context. Specifically, the use of Web Audio is disabled (audio will be played using HTML5 audio instead, even if use_webaudio
is true
) and video preloading is disabled. The override_safe_mode
parameter defaults to false
, but you can set it to true
to force these features to operate under the file://
protocol. In order for this to work, you will need to disable web security (CORS) features in your browser - this is safe to do if you know what you are doing. Note that this parameter has no effect when you are running the experiment on a web server, because the page will be loaded via the http://
or https://
protocol. case_sensitive_responses boolean If true
, then jsPsych will make a distinction between uppercase and lowercase keys when evaluating keyboard responses, e.g. \"A\" (uppercase) will not be recognized as a valid response if the trial only accepts \"a\" (lowercase). If false, then jsPsych will not make a distinction between uppercase and lowercase keyboard responses, e.g. both \"a\" and \"A\" responses will be valid when the trial's key choice parameter is \"a\". Setting this parameter to false is useful if you want key responses to be treated the same way when CapsLock is turned on or the Shift key is held down. The default value is false
. extensions array Array containing information about one or more jsPsych extensions that are used during the experiment. Each extension should be specified as an object with type
(required), which is the name of the extension, and params
(optional), which is an object containing any parameter-value pairs to be passed to the extension's initialize
function. Default value is an empty array."},{"location":"reference/jspsych/#return-value","title":"Return value","text":"Returns a jsPsych instance, which all jsPsych methods on this page are called on. Therefore it is not possible to call any of the jsPsych methods listed on this page until this initJsPsych
function is called and a jsPsych instance is created.
"},{"location":"reference/jspsych/#description","title":"Description","text":"This function initializes jsPsych with the specified experiment settings.
"},{"location":"reference/jspsych/#example","title":"Example","text":"var jsPsych = initJsPsych({\n on_finish: function() {\n jsPsych.data.displayData();\n }, \n show_progress_bar: true,\n default_iti: 500\n});\n
For more examples, see the HTML files in the examples folder.
"},{"location":"reference/jspsych/#jspsychabortcurrenttimeline","title":"jsPsych.abortCurrentTimeline","text":"jsPsych.abortCurrentTimeline()\n
"},{"location":"reference/jspsych/#parameters_1","title":"Parameters","text":"None.
"},{"location":"reference/jspsych/#return-value_1","title":"Return value","text":"None.
"},{"location":"reference/jspsych/#description_1","title":"Description","text":"Ends the current timeline. If timelines are nested, then only the timeline that contains the current trial is ended.
"},{"location":"reference/jspsych/#example_1","title":"Example","text":""},{"location":"reference/jspsych/#abort-timeline-if-a-particular-key-is-pressed","title":"Abort timeline if a particular key is pressed","text":"var jsPsych = initJsPsych({\n on_finish: function() {\n jsPsych.data.displayData();\n }\n});\n\nvar images = [\n \"img/1.gif\", \"img/2.gif\", \"img/3.gif\", \"img/4.gif\",\n \"img/5.gif\", \"img/6.gif\", \"img/7.gif\", \"img/8.gif\",\n \"img/9.gif\", \"img/10.gif\"\n];\n\nvar trials = [];\nfor (var i = 0; i < images.length; i++) {\n trials.push({\n stimulus: images[i]\n });\n}\n\nvar block = {\n type: jsPsychImageKeyboardResponse,\n choices: ['y', 'n'], \n prompt: '<p>Press \"y\" to Continue. Press \"n\" to end this node of the experiment.</p>',\n on_finish: function(data) {\n if (jsPsych.pluginAPI.compareKeys(data.response, 'n')) {\n jsPsych.abortCurrentTimeline();\n }\n },\n timeline: trials\n}\n\nvar after_block = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<p>The next node</p>'\n}\n\njsPsych.run([block, after_block]);\n
"},{"location":"reference/jspsych/#jspsychabortexperiment","title":"jsPsych.abortExperiment","text":"jsPsych.abortExperiment(message, data)\n
"},{"location":"reference/jspsych/#parameters_2","title":"Parameters","text":"Parameter Type Description message string A message to display on the screen after the experiment is over. Can include HTML formatting. data object An optional object of key-value pairs to store as data in the final trial of the experiment."},{"location":"reference/jspsych/#return-value_2","title":"Return value","text":"None.
"},{"location":"reference/jspsych/#description_2","title":"Description","text":"Ends the experiment, skipping all remaining trials. If the on_finish
event handler for jsPsych
returns a Promise
then the message
will not be displayed until the promise is resolved.
"},{"location":"reference/jspsych/#example_2","title":"Example","text":""},{"location":"reference/jspsych/#end-the-experiment-if-a-particular-response-is-given","title":"End the experiment if a particular response is given","text":"var trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'image1.jpg',\n choices: ['y', 'n'],\n prompt: '<p>Press \"y\" to Continue. Press \"n\" to end the experiment</p>',\n on_finish: function(data){\n if(jsPsych.pluginAPI.compareKeys(data.response, \"n\")){\n jsPsych.abortExperiment('The experiment was ended by pressing \"n\".');\n }\n }\n}\n
"},{"location":"reference/jspsych/#jspsychaborttimelinebyname","title":"jsPsych.abortTimelineByName","text":"jsPsych.abortTimelineByName()\n
"},{"location":"reference/jspsych/#parameters_3","title":"Parameters","text":"Parameter Type Description name string The name of the timeline to abort."},{"location":"reference/jspsych/#return-value_3","title":"Return value","text":"None.
"},{"location":"reference/jspsych/#description_3","title":"Description","text":"Ends the currently active timeline that matches the name
parameter. This can be used to control which level is aborted in a nested timeline structure.
"},{"location":"reference/jspsych/#example_3","title":"Example","text":""},{"location":"reference/jspsych/#abort-a-procedure-if-an-incorrect-response-is-given","title":"Abort a procedure if an incorrect response is given.","text":"const fixation = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<p>+</p>',\n choices: \"NO_KEYS\",\n trial_duration: 1000\n}\n\nconst test = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n choices: ['y', 'n'],\n on_finish: function(data){\n if(jsPsych.pluginAPI.compareKeys(data.response, \"n\")){\n jsPsych.abortTimelineByName('memory_test');\n }\n }\n}\n\nconst memoryResponseProcedure = {\n timeline: [fixation, test]\n}\n\n// the variable `encode` is not shown, but imagine a trial that displays\n// some stimulus to remember.\nconst memoryEncodeProcedure = {\n timeline: [fixation, encode]\n}\n\nconst memoryTestProcedure = {\n timeline: [memoryEncodeProcedure, memoryResponseProcedure]\n name: 'memory_test',\n timeline_variables: [\n {stimulus: 'image1.png'},\n {stimulus: 'image2.png'},\n {stimulus: 'image3.png'},\n {stimulus: 'image4.png'}\n ]\n}\n
"},{"location":"reference/jspsych/#jspsychaddnodetoendoftimeline","title":"jsPsych.addNodeToEndOfTimeline","text":"jsPsych.addNodeToEndOfTimeline(node_parameters)\n
"},{"location":"reference/jspsych/#parameters_4","title":"Parameters","text":"Parameter Type Description node_parameters object An object defining a timeline. It must have, at a minimum, a timeline
parameter with a valid timeline array as the value for that parameter."},{"location":"reference/jspsych/#return-value_4","title":"Return value","text":"None.
"},{"location":"reference/jspsych/#description_4","title":"Description","text":"Adds the timeline to the end of the experiment.
"},{"location":"reference/jspsych/#example_4","title":"Example","text":"var trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'This is a new trial.'\n}\n\nvar new_timeline = {\n timeline: [trial]\n}\n\njsPsych.addNodeToEndOfTimeline(new_timeline)\n
"},{"location":"reference/jspsych/#jspsychevaluatetimelinevariable","title":"jsPsych.evaluateTimelineVariable","text":"jsPsych.evaluateTimelineVariable(variable_name)\n
"},{"location":"reference/jspsych/#parameters_5","title":"Parameters","text":"Parameter Type Description variable_name string The name of the variable to evaluate."},{"location":"reference/jspsych/#return-value_5","title":"Return value","text":"Returns the current value of the corresponding timeline variable.
"},{"location":"reference/jspsych/#description_5","title":"Description","text":"Unlike jsPsych.timelineVariable()
, evaluateTimelineVariable()
immediately returns the current value of the timeline variable. It should be used whenever you are in a context where immediate evaluation is appropriate. For example, if you referencing a timeline variable within a function, immediate evaluation is usually correct.
"},{"location":"reference/jspsych/#examples","title":"Examples","text":""},{"location":"reference/jspsych/#invoking-timeline-variables-immediately-in-a-function","title":"Invoking timeline variables immediately in a function","text":"const trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: function(){\n return `<img style='width:100px; height:100px;' src='${jsPsych.evaluateTimelineVariable('image')}'></img>`;\n }\n}\n\nconst procedure = {\n timeline: [trial],\n timeline_variables: [\n {image: 'face1.png'},\n {image: 'face2.png'},\n {image: 'face3.png'},\n {image: 'face4.png'}\n ]\n}\n
"},{"location":"reference/jspsych/#jspsychfinishtrial","title":"jsPsych.finishTrial","text":"jsPsych.finishTrial(data)\n
"},{"location":"reference/jspsych/#parameters_6","title":"Parameters","text":"Parameter Type Description data object The data to store for the trial."},{"location":"reference/jspsych/#return-value_6","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych/#description_6","title":"Description","text":"This method tells jsPsych that the current trial is over. It is used in all of the plugins to end the current trial. When the trial ends a few things happen:
- The data is stored using
jsPsych.data.write()
- The on_finish callback function is executed for the trial
- The on_trial_finish callback function is executed
- The progress bar is updated if it is being displayed
- The experiment ends if the trial is the last one (and the on_finish callback function is executed).
- The next trial, if one exists, is started.
"},{"location":"reference/jspsych/#example_5","title":"Example","text":"// this code would be in a plugin\njsPsych.finishTrial({correct_response: true});\n
"},{"location":"reference/jspsych/#jspsychgetcurrenttrial","title":"jsPsych.getCurrentTrial","text":"jsPsych.getCurrentTrial()\n
"},{"location":"reference/jspsych/#parameters_7","title":"Parameters","text":"None.
"},{"location":"reference/jspsych/#return-value_7","title":"Return value","text":"Returns the object describing the current trial. The object will contain all of the parameters associated with the current trial.
"},{"location":"reference/jspsych/#description_7","title":"Description","text":"Get a description of the current trial
"},{"location":"reference/jspsych/#example_6","title":"Example","text":"var trial = jsPsych.getCurrentTrial();\nconsole.log('The current trial is using the '+trial.type+' plugin');\n
"},{"location":"reference/jspsych/#jspsychgetdisplayelement","title":"jsPsych.getDisplayElement","text":"jsPsych.getDisplayElement()\n
"},{"location":"reference/jspsych/#parameters_8","title":"Parameters","text":"None.
"},{"location":"reference/jspsych/#return-value_8","title":"Return value","text":"Returns the HTML DOM element used for displaying the experiment.
"},{"location":"reference/jspsych/#description_8","title":"Description","text":"Get the DOM element that displays the experiment.
"},{"location":"reference/jspsych/#example_7","title":"Example","text":""},{"location":"reference/jspsych/#var-el-jspsychgetdisplayelement-hide-the-jspsych-display-elstylevisibility-hidden","title":"var el = jsPsych.getDisplayElement();\n\n// hide the jsPsych display\nel.style.visibility = 'hidden';\n
","text":""},{"location":"reference/jspsych/#jspsychgetinitsettings","title":"jsPsych.getInitSettings","text":"jsPsych.getInitSettings()\n
"},{"location":"reference/jspsych/#parameters_9","title":"Parameters","text":"None
"},{"location":"reference/jspsych/#return-value_9","title":"Return value","text":"Returns the settings object used to initialize the experiment.
"},{"location":"reference/jspsych/#description_9","title":"Description","text":"Gets the object containing the settings for the current experiment.
"},{"location":"reference/jspsych/#example_8","title":"Example","text":"var settings = jsPsych.getInitSettings();\n\n// check the experiment structure\nconsole.log(JSON.stringify(settings.timeline));\n
"},{"location":"reference/jspsych/#jspsychgetprogress","title":"jsPsych.getProgress","text":"jsPsych.getProgress()\n
"},{"location":"reference/jspsych/#parameters_10","title":"Parameters","text":"None.
"},{"location":"reference/jspsych/#return-value_10","title":"Return value","text":"Returns an object with the following properties:
Property Type Description total_trials numeric Indicates the number of trials in the experiment. Note that this does not count possible loops or skipped trials due to conditional statements. current_trial_global numeric Returns the trial index of the current trial in a global scope. Every trial will increase this count by 1. percent_complete numeric Estimates the percent of the experiment that is complete. Works as expected for experiments without conditional or looping timelines. For complex timelines, the percent is an approximation."},{"location":"reference/jspsych/#description_10","title":"Description","text":"This method returns information about the length of the experiment and the participant's current location in the experiment timeline.
"},{"location":"reference/jspsych/#example_9","title":"Example","text":"var progress = jsPsych.getProgress();\nalert('You have completed approximately '+progress.percent_complete+'% of the experiment');\n
"},{"location":"reference/jspsych/#jspsychgetprogressbarcompleted","title":"jsPsych.getProgressBarCompleted","text":"jsPsych.getProgressBarCompleted()\n
"},{"location":"reference/jspsych/#parameters_11","title":"Parameters","text":"None.
"},{"location":"reference/jspsych/#return-value_11","title":"Return value","text":"Returns a value between 0 and 1 representing how full the progress bar currently is.
"},{"location":"reference/jspsych/#description_11","title":"Description","text":"Used to get the current value of the progress bar. Works for automated and manual control.
"},{"location":"reference/jspsych/#example_10","title":"Example","text":"var progress_bar_amount = jsPsych.getProgressBarCompleted();\n
"},{"location":"reference/jspsych/#jspsychgetstarttime","title":"jsPsych.getStartTime","text":"jsPsych.getStartTime()\n
"},{"location":"reference/jspsych/#parameters_12","title":"Parameters","text":"None.
"},{"location":"reference/jspsych/#return-value_12","title":"Return value","text":"Returns a Date
object indicating when the experiment began.
"},{"location":"reference/jspsych/#description_12","title":"Description","text":"Get the time that the experiment began.
"},{"location":"reference/jspsych/#example_11","title":"Example","text":"var start_time = jsPsych.getStartTime();\n
"},{"location":"reference/jspsych/#jspsychgettotaltime","title":"jsPsych.getTotalTime","text":"jsPsych.getTotalTime()\n
"},{"location":"reference/jspsych/#parameters_13","title":"Parameters","text":"None.
"},{"location":"reference/jspsych/#return-value_13","title":"Return value","text":"Returns a numeric value indicating the number of milliseconds since jsPsych.run
was called.
"},{"location":"reference/jspsych/#description_13","title":"Description","text":"Gets the total time the participant has been in the experiment.
"},{"location":"reference/jspsych/#example_12","title":"Example","text":"var time = jsPsych.getTotalTime();\nconsole.log(time);\n
"},{"location":"reference/jspsych/#jspsychpauseexperiment","title":"jsPsych.pauseExperiment","text":"jsPsych.pauseExperiment()\n
"},{"location":"reference/jspsych/#parameters_14","title":"Parameters","text":"None.
"},{"location":"reference/jspsych/#return-value_14","title":"Return value","text":"None.
"},{"location":"reference/jspsych/#description_14","title":"Description","text":"Pauses the experiment. The experiment will finish the current trial, but will not execute any additional trials until jsPsych.resumeExperiment()
is called.
"},{"location":"reference/jspsych/#example_13","title":"Example","text":"var trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Press p to take a 30 second break. Otherwise, press c to continue immediately.',\n choices: ['p','c'],\n on_finish: function(data){\n if(jsPsych.pluginAPI.compareKeys(data.response, \"p\")) { \n jsPsych.pauseExperiment();\n setTimeout(jsPsych.resumeExperiment, 30000);\n }\n }\n}\n
"},{"location":"reference/jspsych/#jspsychresumeexperiment","title":"jsPsych.resumeExperiment","text":"jsPsych.resumeExperiment()\n
"},{"location":"reference/jspsych/#parameters_15","title":"Parameters","text":"None.
"},{"location":"reference/jspsych/#return-value_15","title":"Return value","text":"None.
"},{"location":"reference/jspsych/#description_15","title":"Description","text":"Resumes the experiment after a call to jsPsych.pauseExperiment()
. If the post trial delay (post_trial_gap
) has not yet been reached, then the experiment will not continue until the delay is finished. For example, if post_trial_gap
was 10,000ms and jsPsych.resumeExperiment()
was called 6,000ms after the previous trial finished, then the experiment would not continue for another 4,000ms.
"},{"location":"reference/jspsych/#example_14","title":"Example","text":"var trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Press p to take a 30 second break. Otherwise, press c to continue immediately.',\n choices: ['p','c'],\n on_finish: function(data){\n if(jsPsych.pluginAPI.compareKeys(data.response, \"p\")) { \n jsPsych.pauseExperiment();\n setTimeout(jsPsych.resumeExperiment, 30000);\n }\n }\n}\n
"},{"location":"reference/jspsych/#jspsychrun","title":"jsPsych.run","text":"jsPsych.run(timeline)\n
"},{"location":"reference/jspsych/#parameters_16","title":"Parameters","text":"Parameter Type Description timeline array An array containing the objects that describe the experiment timeline. See Creating an Experiment: The Timeline."},{"location":"reference/jspsych/#return-value_16","title":"Return value","text":"None.
"},{"location":"reference/jspsych/#description_16","title":"Description","text":"Start the jsPsych experiment with the specified timeline.
"},{"location":"reference/jspsych/#example_15","title":"Example","text":"var timeline = [trial1, trial2, trial3];\n\njsPsych.run(timeline);\n
"},{"location":"reference/jspsych/#jspsychsetprogressbar","title":"jsPsych.setProgressBar","text":"jsPsych.setProgressBar(value)\n
"},{"location":"reference/jspsych/#parameters_17","title":"Parameters","text":"Parameter Type Description value numeric Proprotion (between 0 and 1) to fill the progress bar."},{"location":"reference/jspsych/#return-value_17","title":"Return value","text":"None.
"},{"location":"reference/jspsych/#description_17","title":"Description","text":"Set the progress bar to a custom amount. Proportion must be between 0 and 1. Values larger than 1 are treated as 1.
"},{"location":"reference/jspsych/#example_16","title":"Example","text":"jsPsych.setProgressBar(0.85);\n
"},{"location":"reference/jspsych/#jspsychtimelinevariable","title":"jsPsych.timelineVariable","text":"jsPsych.timelineVariable(variable)\n
"},{"location":"reference/jspsych/#parameters_18","title":"Parameters","text":"Parameter Type Description variable string Name of the timeline variable"},{"location":"reference/jspsych/#return-value_18","title":"Return value","text":"Returns a placeholder object that jsPsych uses to evaluate the timeline variable when the trial runs.
"},{"location":"reference/jspsych/#description_18","title":"Description","text":"Timeline variables are a powerful technique for generating experiments with repetitive procedures but different parameter values. This function fetches the current value of a particular timeline variable. It must be used in conjunction with a timeline that has timeline variables. See the timeline variable section for details.
"},{"location":"reference/jspsych/#examples_1","title":"Examples","text":""},{"location":"reference/jspsych/#use-as-a-parameter-for-a-trial","title":"Use as a parameter for a trial","text":"var trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('image')\n}\n\nvar procedure = {\n timeline: [trial],\n timeline_variables: [\n {image: 'face1.png'},\n {image: 'face2.png'},\n {image: 'face3.png'},\n {image: 'face4.png'}\n ]\n}\n
"},{"location":"reference/jspsych/#jspsychversion","title":"jsPsych.version","text":"jsPsych.version()\n
"},{"location":"reference/jspsych/#parameters_19","title":"Parameters","text":"None.
"},{"location":"reference/jspsych/#return-value_19","title":"Return value","text":"Returns the version number as a string.
"},{"location":"reference/jspsych/#description_19","title":"Description","text":"Gets the version of jsPsych.
"},{"location":"reference/jspsych/#example_17","title":"Example","text":"var version = jsPsych.version();\nconsole.log(version);\n
"},{"location":"support/migration-v7/","title":"Migrating an experiment to v7.x","text":"The release of version 7.0 changes a number of core components of jsPsych. We made these changes to improve jsPsych's compatibility with modern JavaScript tools like package managers and bundlers and to improve the developer experience for people contributing to jsPsych's codebase. We hope these changes will improve the long-term viability of the project and encourage more developers to contribute to jsPsych.
Our aim was to accomplish these goals with minimal changes to the user experience of jsPsych. However, we did have to change a few critical things. This guide is aimed at users who are familiar with v6.x of jsPsych and would like to understand what's changed in v7.x.
"},{"location":"support/migration-v7/#loading-jspsych","title":"Loading jsPsych","text":"There are now three different ways you can load jsPsych into your HTML file. We've updated the hello world tutorial to walk through each of the three options. If you are looking for the option that is most similar to the version 6.x experience, check out option 2. The biggest difference from what you are used to is that the directory structure of the downloaded library is slightly different and plugin files are named a little bit differently.
"},{"location":"support/migration-v7/#initializing-and-running-jspsych","title":"Initializing and running jsPsych","text":"We've removed jsPsych.init()
and split the features into two different functions.
At the start of your experiment script, you'll now call initJsPsych()
to get a new instance of jsPsych and store it in a variable called jsPsych
. This is where you will pass in the variety of parameters that used to go into jsPsych.init()
, with the exception of the timeline
parameter.
var jsPsych = initJsPsych({\n use_webaudio: false,\n on_finish: function(){\n jsPsych.data.displayData();\n }\n});\n
Once you've created your timeline, then you'll launch the experiment by calling jsPsych.run()
, passing in the timeline as the only argument. This is the point in your script where you've used the jsPsych.init
function in jsPsych v6.x. Because the jsPsych.run
function only needs the experiment timeline, this argument should be an array (rather than an object like {timeline: timeline}
in jsPsych v6.x).
var timeline = [...]\n\njsPsych.run(timeline);\n
"},{"location":"support/migration-v7/#the-type-parameter-for-trials","title":"The type
parameter for trials","text":"The type
parameter now expects the value to be a plugin class rather than a string.
For example, if you load the html-keyboard-response
plugin from the CDN...
<script src=\"http://unpkg.com/@jspsych/plugin-html-keyboard-response@1.1.0\"></script>\n
... or from the plugin-html-keyboard-response.js
file in the release archive...
<script src=\"plugin-html-keyboard-response.js\"></script>\n
... then a global variable defining the plugin's class called jsPsychHtmlKeyboardResponse
is available.
To create a trial using the plugin, pass this class as the type
parameter. The plugin classes are named starting with jsPsych
, followed by the plugin name written in camel case (rather than with dashes between words). See the \"Using a plugin\" section of the Plugins overview page for more examples. Note that the value is not a string.
var trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Hello, version 7.0!'\n}\n
"},{"location":"support/migration-v7/#the-choices-parameter-for-keyboard-response-trials","title":"The choices
parameter for keyboard response trials","text":"The choices
parameter for keyboard response trials no longer supports jsPsych.NO_KEYS
and jsPsych.ALL_KEYS
, and they have been replaced by the strings \"NO_KEYS\"
and \"ALL_KEYS\"
respectively.
For example, if you load the audio-keyboard-response
plugin, you can prevent any user input like...
var trial = {\n type: jsPsychAudioKeyboardResponse,\n choices: \"NO_KEYS\",\n stimulus: 'example.ogg',\n trial_ends_after_audio: true\n}\n
"},{"location":"support/migration-v7/#using-extensions","title":"Using extensions","text":"Like plugins, extensions are now also referenced by their class. Extensions are initiliazed in initJsPsych()
instead of jsPsych.init()
. Extension classes are named similarly to plugins, except that they start with jsPsychExtension
.
var jsPsych = initJsPsych({\n extensions: [\n {type: jsPsychExtensionWebgazer}\n ]\n})\n
The class is also used in trials that use the extension.
var trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Hello, version 7.0!',\n extensions: [\n {type: jsPsychExtensionWebgazer}\n ]\n}\n
"},{"location":"support/migration-v7/#custom-plugins","title":"Custom plugins","text":"If you have custom plugins that you would like to upgrade to be compatible with v7.x we recommend using our plugin template.
The new template implements plugins as a class, but the core components are essentially unchanged.
- Anything in
plugin.info
from a v6.x plugin should be moved into the info
object. Note that the type
argument for the parameters follows a slightly different syntax in the v7.x plugins. This object is then assigned as a static property of the class. - Anything in
plugin.trial
from a v6.x plugin should be moved into the trial
method inside the class. - The new template has a
constructor()
function that accepts an instance of jsPsych. You do not need to adjust this portion of the plugin.
There are a few changes to be aware of that may affect your plugin code.
- We removed the
registerPreload
function and we now auto-detect media to preload via the type
argument specified in the info
object. If a parameter is listed as IMAGE
, AUDIO
, or VIDEO
, it will be automatically preloaded. If you wish to disable preloading you can set the preload
flag to false
for the parameter. - If you invoke any functions from jsPsych, like
jsPsych.finishTrial()
, note that jsPsych
is no longer a global variable and you must use the reference to jsPsych that is passed to the constructor. To do this, simply prefix all jsPsych
references with this.
, e.g., jsPsych.finishTrial()
becomes this.jsPsych.finishTrial()
. If your reference to a jsPsych function is inside of another function, then in order for the this
keyword to appropriately reference the jsPsych instance, you must also use a JavaScript arrow function expression for the outer function. For example, this: function end_trial() {\n // ...\n jsPsych.finishTrial(data);\n}\n
Would be re-written as: const end_trial = () => {\n // ...\n this.jsPsych.finishTrial(data);\n}\n
"},{"location":"support/migration-v7/#need-help","title":"Need help?","text":"If you encounter issues migrating code to v7.x, feel free to post in our support thread for migration.
"},{"location":"support/migration-v8/","title":"Migrating an experiment to v8.x","text":"Version 8.x of jsPsych focused on a complete rewrite of the core library to enable new features and make it easier to maintain. Most of the changes in version 8.x are behind the scenes. However, there are some breaking changes that you will need to address in your experiment code in order to upgrade to v8.x.
This guide is aimed at upgrades from version 7.x to 8.x. If you are using version 6.x or earlier, please follow the migration guide for v7.x before trying to upgrade to v8.x.
"},{"location":"support/migration-v8/#timeline-events","title":"Timeline Events","text":"In version 7.x, if a timeline had a conditional_function
it would be checked on every iteration if the timeline also looped. In version 8.x, the conditional_function
is checked only before the first trial on the timeline. We think this is a more intuitive behavior. It allows the conditional_function
to toggle whether a timeline runs at all, and once it starts running we assume that it should continue. If you relied on the old behavior, you can nest the timeline with the conditional_function
inside another timeline that loops.
We've also changed the behavior of on_timeline_start
and on_timeline_finish
to only execute one time each. Previously these events executed on every repetition of a timeline. If you relied on the old behavior, you can nest the timeline with the on_timeline_start
or on_timeline_finish
inside the timeline that repeats.
"},{"location":"support/migration-v8/#timeline-variables","title":"Timeline Variables","text":"We've split the functionality of jsPsych.timelineVariable()
into two different functions to reflect the two different use cases. If you are using jsPsych.timelineVariable()
inside a function you will need to replace the function call with jsPsych.evaluateTimelineVariable()
. Usage as a parameter in a trial doesn't change.
This behavior is still the same:
const trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n}\n
This behavior has changed:
const trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: () => {\n return `<p>The stimulus is ${jsPsych.evaluateTimelineVariable('stimulus')}</p>`\n }\n}\n
We've added some better error support for evaluateTimelineVariable()
so that it will throw an error if there's no corresponding timeline variable to evaluate.
We've removed support for jsPsych.getAllTimelineVariables()
and replaced it with the trial-level property save_timeline_variables
.
If you need to save all the timeline variables of a trial to jsPsych's data, you can set save_timeline_variables: true
in the trial.
"},{"location":"support/migration-v8/#trial-parameters","title":"Trial parameters","text":"We've made some trial parameters more strict to improve the maintainability of the library.
If a plugin has a parameter that is marked as array: true
in the plugin's info
object, then jsPsych will now throw an error if the parameter is not an array. Previously, some plugins allowed some parameters to be either an array or non-array. For the plugins included in jsPsych's main repository, the only affected parameter is the button_html
parameter for the various button response plugins. Previously this parameter could be an array or a string. We've now made it so that it must be a function.
Version 7.x:
const trial = {\n type: jsPsychHtmlButtonResponse,\n stimulus: 'Press a button',\n choices: ['a', 'b', 'c'],\n button_html: '<button class=\"jspsych-btn\" style=\"font-size: 80px;\">%choice%</button>'\n}\n
Version 8.x:
const trial = {\n type: jsPsychHtmlButtonResponse,\n stimulus: 'Press a button',\n choices: ['a', 'b', 'c'],\n button_html: (choice) => {\n return `<button class=\"jspsych-btn\" style=\"font-size: 80px;\">${choice}</button>`\n }\n}\n
The button_html
parameter can also support different HTML for each button. See the plugin documentation for more details.
"},{"location":"support/migration-v8/#plugin-parameter-handling","title":"Plugin parameter handling","text":"In version 7.x, a plugin could omit parameters from the info
object and jsPsych would still evaluate these parameters appropriately in most cases. Version 8.x is more strict about this. Plugins should list all parameters in the info
object. If a parameter is not listed, then timeline variables and function evaluation will not work for that parameter. The save_trial_parameters
parameter will also not work for parameters that are not listed in the info
object.
"},{"location":"support/migration-v8/#plugin-version-and-data-properties","title":"Plugin version
and data
properties","text":"We've added a version
property to the info
object for plugins. This property is a string that should be updated whenever a new version of the plugin is released.
We've also added a data
property to the info
object for plugins. This property is an object that can contain a description of the types of data that the plugin will generate.
Including these properties is not required for a plugin to work, but it is recommended. In version 8.x, jsPsych will throw a warning if a plugin is used that does not have a version
or data
property in the info
object. In version 9.x, we plan to make this a requirement.
"},{"location":"support/migration-v8/#changes-to-finishtrial","title":"Changes to finishTrial()
","text":"When a plugin calls finishTrial()
or ends via a return
statement, jsPsych will now automatically clear the display and clear any timeouts that are still pending. This change should only affect plugin developers. If you are using built-in plugins you should not notice any difference.
"},{"location":"support/migration-v8/#progress-bar","title":"Progress bar","text":"The automatic progress bar now updates after every trial, including trials in nested timelines. If you would like to implement the old behavior of updating only on the top-level timeline, you can manually control the progress bar using the on_finish
callback of the timelines and trials in the top-level timeline.
We've also changed jsPsych.setProgressBar(x)
to jsPsych.progressBar.progress = x
. And we've changed jsPsych.getProgressBarCompleted()
to jsPsych.progressBar.progress
. This simplifies the API for the progress bar.
"},{"location":"support/migration-v8/#data-handling","title":"Data Handling","text":"We've removed internal_node_id
and jsPsych.data.getDataByTimelineNode()
. Timeline node IDs were used internally by jsPsych to keep track of experiment progress in version 7, but this is no longer the case in version 8. Most users didn't need or want to see the internal_node_id
in the data, so we've removed it. If you relied on this parameter, the simplest replacement is probably to use the data
parameter to add the information you need back to the timeline.
"},{"location":"support/migration-v8/#ending-a-timeline-and-ending-the-experiment","title":"Ending a timeline and ending the experiment","text":"We've renamed jsPsych.endExperiment()
to jsPsych.abortExperiment()
.
We've renamed jsPsych.endCurrentTimeline()
to jsPsych.abortCurrentTimeline()
.
"},{"location":"support/migration-v8/#interaction-listeners","title":"Interaction listeners","text":"In version 7.x, interaction events (like exiting fullscreen) would still be listened for even after the experiment ended. These events are no longer reported once the experiment ends.
"},{"location":"support/migration-v8/#need-help","title":"Need help?","text":"If you encounter issues migrating code to v8.x please open a thread on our discussion board.
"},{"location":"support/support/","title":"Support","text":"For questions about jsPsych, the preferred method of support is GitHub Discussions. Questions are most likely to be answered when they include a reproducible example of the problem. If you can make your code available online and link to the experiment, that will make the question easier to answer. Please consider searching through the archive of Q&As before posting a new question.
If you have identified a problem with jsPsych, such as a bug in the code or an error in the documentation, please open a new issue on GitHub.
If you have a suggestion for fixing the problem, feel free to contribute to the project!
Inquiries for paid consultation to develop experiments using jsPsych or to create new custom jsPsych features can be sent to josh.deleeuw@gmail.com.
"},{"location":"tutorials/hello-world/","title":"jsPsych \"Hello world\" experiment","text":"In the long tradition of \"Hello world!\" examples, this tutorial creates an experiment that outputs the phrase \"Hello world!\" to the browser. Though useless as an actual experiment, the process is helpful for learning the basics of using the jsPsych library.
"},{"location":"tutorials/hello-world/#choose-your-own-setup-adventure","title":"Choose your own (setup) adventure","text":"Starting with the release of version 7.0 of jsPsych there are three different ways that you can add jsPsych to your project. Which approach you choose will depend on what your goals are.
-
I want the simplest possible setup. This approach involves using scripts that are hosted on a CDN. You do not need to download or install anything to start using jsPsych. The limitation is that you cannot customize the library. For most experiments, this approach will be sufficient.
-
I want to be able to do some customization, but have a simple setup.. This approach involves downloading a bundle of scripts that make up jsPsych. If you used jsPsych prior to version 7.0, this will feel like the most familiar approach. Having your own copy of the scripts means that you can make modifications to the library such as tweaking plugin behavior.
-
I want to use modern JavaScript tooling, like npm
and import
statements. You can install jsPsych, plugins for jsPsych, and extensions for jsPsych from NPM. This approach allows you to integrate jsPsych into your favorite JavaScript frameworks and get the benefits of TypeScript, bundlers, and more.
"},{"location":"tutorials/hello-world/#option-1-using-cdn-hosted-scripts","title":"Option 1: Using CDN-hosted scripts","text":""},{"location":"tutorials/hello-world/#step-1-create-an-html-file","title":"Step 1: Create an HTML file","text":"Tip
To edit jsPsych code you'll need a programming-friendly text editor. A great free option is Visual Studio Code (Windows, OSX, Linux).
Create a new file called experiment.html
.
There's some basic code that (nearly) all HTML documents have in common. Here's a typical bare-bones HTML document.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n </head>\n <body></body>\n</html>\n
Add the above code to the experiment.html
file and save it. If you open the file in a web browser, you should see a blank page and the title of the page will be 'My experiment'.
"},{"location":"tutorials/hello-world/#step-2-load-the-jspsych-library","title":"Step 2: Load the jsPsych library","text":"To use jsPsych, add a <script>
tag to load the library. We'll load the library from a CDN, which means that the library is hosted on another server and can be loaded without having your own copy.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n </head>\n <body></body>\n</html>\n
Note that the URL for the jsPsych library includes the version number, which ensures that the behavior of your experiment won't change with any future updates to jsPsych.
You may also want to import the jsPsych stylesheet, which applies a basic set of visual styles to the experiment. This requires adding a <link>
tag to the <head>
section of the document.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n</html>\n
"},{"location":"tutorials/hello-world/#step-3-create-a-script-element-and-initialize-jspsych","title":"Step 3: Create a script element and initialize jsPsych","text":"To add JavaScript code directly to the webpage we need to add a pair of <script>
tags after the <body>
tags.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n </script>\n</html>\n
To initialize jsPsych we use the initJsPsych()
function and assign the output to a new variable.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n const jsPsych = initJsPsych();\n </script>\n</html>\n
"},{"location":"tutorials/hello-world/#step-4-use-a-plugin-to-print-a-message","title":"Step 4: Use a plugin to print a message","text":"For this demo we want to show some text on the screen. This is exactly what the html-keyboard-response plugin is designed to do. To use the plugin, we need to load it with a <script>
tag.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n const jsPsych = initJsPsych();\n </script>\n</html>\n
Once the plugin is loaded we can create a trial using the plugin. To declare a trial that uses the html-keyboard-response
plugin, we create an object with the property type
equal to jsPsychHtmlKeyboardResponse
. We can specify the other parameters of the plugin in the same object. Here we use the stimulus
parameter to include a message. You can see the full set of parameters for each plugin on its documentation page.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n const jsPsych = initJsPsych();\n\n const hello_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Hello world!'\n }\n </script>\n</html>\n
"},{"location":"tutorials/hello-world/#step-5-run-the-experiment","title":"Step 5: Run the experiment","text":"Now that we have the trial defined we need to tell jsPsych to run an experiment consisting of this trial. This requires using the jsPsych.run
function and passing in a timeline. For a simple experiment like this one, the timeline is just an array containing the list of trials to run.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n const jsPsych = initJsPsych();\n\n const hello_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Hello world!'\n }\n\n jsPsych.run([hello_trial]);\n </script>\n</html>\n
Once you've saved the file, open it in a browser. You should see \"Hello world!\" printed on the screen, and if you press a key on the keyboard, the text should disappear (ending the trial).
"},{"location":"tutorials/hello-world/#option-2-download-and-host-jspsych","title":"Option 2: Download and host jsPsych","text":""},{"location":"tutorials/hello-world/#step-1-download-jspsych","title":"Step 1: Download jsPsych","text":"Start by downloading the latest release of jsPsych. Here's a direct link (jspsych.zip). The most recent version can always be found at the top of the GitHub releases page. Note that even the releases that are for a particular plugin or extension will contain the full set of files needed to run jsPsych locally in the dist archive (zip)
release asset. You should download the zip file for whatever the most recently released package is. This will ensure that you have the most recent version of all the packages associated with jsPsych.
"},{"location":"tutorials/hello-world/#step-2-create-a-folder-to-store-your-experiment-files","title":"Step 2: Create a folder to store your experiment files","text":"Create a folder on your computer to put the experiment files in. We'll call this \"MyExperiment\" for the tutorial. Add a subfolder called jspsych
. Once you've created the folder, open the downloaded archive from step 1 and copy the contents of the dist
folder into the jspsych
folder. It should look like this:
\ud83d\udcc2 MyExperiment\n-- \ud83d\udcc2 jspsych\n---- \ud83d\udcc4 jspsych.js\n---- \ud83d\udcc4 plugin-animation.js\n---- \ud83d\udcc4 plugin-audio-keyboard-response.js\n---- ...\n
"},{"location":"tutorials/hello-world/#step-3-create-an-html-file","title":"Step 3: Create an HTML file","text":"Tip
To edit jsPsych code you'll need a programming-friendly text editor. A great free option is Visual Studio Code (Windows, OSX, Linux).
Create a new file called experiment.html
in the MyExperiment
folder. The directory structure should look like this:
\ud83d\udcc2 MyExperiment\n-- \ud83d\udcc4 experiment.html\n-- \ud83d\udcc2 jspsych\n
There's some basic code that (nearly) all HTML documents have in common. Here's a typical bare-bones HTML document.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n </head>\n <body></body>\n</html>\n
Add the above code to the experiment.html
file and save it. If you open the file in a web browser, you should see a blank page and the title of the page will be 'My experiment'.
"},{"location":"tutorials/hello-world/#step-4-load-the-jspsych-library","title":"Step 4: Load the jsPsych library","text":"To use jsPsych, add a <script>
tag to load the library. Set the src
attribute to the path to the jspsych.js
file.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"jspsych/jspsych.js\"></script>\n </head>\n <body></body>\n</html>\n
You may also want to import the jsPsych stylesheet, which applies a basic set of visual styles to the experiment. This requires adding a <link>
tag to the <head>
section of the document.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"jspsych/jspsych.js\"></script>\n <link href=\"jspsych/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n</html>\n
"},{"location":"tutorials/hello-world/#step-5-create-a-script-element-and-initialize-jspsych","title":"Step 5: Create a script element and initialize jsPsych","text":"To add JavaScript code directly to the webpage we need to add a pair of <script>
tags after the <body>
tags.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"jspsych/jspsych.js\"></script>\n <link href=\"jspsych/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n </script>\n</html>\n
To initialize jsPsych we use the initJsPsych()
function and assign the output to a new variable.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"jspsych/jspsych.js\"></script>\n <link href=\"jspsych/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n const jsPsych = initJsPsych();\n </script>\n</html>\n
"},{"location":"tutorials/hello-world/#step-6-use-a-plugin-to-print-a-message","title":"Step 6: Use a plugin to print a message","text":"For this demo we want to show some text on the screen. This is exactly what the html-keyboard-response plugin is designed to do. To use the plugin, we need to load it with a <script>
tag.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"jspsych/jspsych.js\"></script>\n <script src=\"jspsych/plugin-html-keyboard-response.js\"></script>\n <link href=\"jspsych/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n const jsPsych = initJsPsych();\n </script>\n</html>\n
Once the plugin is loaded we can create a trial using the plugin. To declare a trial that uses the html-keyboard-response
plugin, we create an object with the property type
equal to jsPsychHtmlKeyboardResponse
. We can specify the other parameters of the plugin in the same object. Here we use the stimulus
parameter to include a message. You can see the full set of parameters for each plugin on its documentation page.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"jspsych/jspsych.js\"></script>\n <script src=\"jspsych/plugin-html-keyboard-response.js\"></script>\n <link href=\"jspsych/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n const jsPsych = initJsPsych();\n\n const hello_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Hello world!'\n }\n </script>\n</html>\n
"},{"location":"tutorials/hello-world/#step-7-run-the-experiment","title":"Step 7: Run the experiment","text":"Now that we have the trial defined we need to tell jsPsych to run an experiment consisting of this trial. This requires using the jsPsych.run
function and passing in a timeline. For a simple experiment like this one, the timeline is just an array containing the list of trials to run.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"jspsych/jspsych.js\"></script>\n <script src=\"jspsych/plugin-html-keyboard-response.js\"></script>\n <link href=\"jspsych/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n const jsPsych = initJsPsych();\n\n const hello_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Hello world!'\n }\n\n jsPsych.run([hello_trial]);\n </script>\n</html>\n
Once you've saved the file, open it in a browser. You should see \"Hello world!\" printed on the screen, and if you press a key on the keyboard, the text should disappear (ending the trial).
"},{"location":"tutorials/hello-world/#option-3-using-npm","title":"Option 3: Using NPM","text":"If you are electing to use npm
to install jsPsych we will assume that you already are familiar with Node.js and generally know what you are doing with web development. We will also assume that you are using a webpack or a similar bundler.
Info
You may want to check out the jsPsych Builder CLI utility. jsPsych Builder allows you to automate the experiment setup, spin up a development server, and transpile and bundle scripts and styles using webpack. Using jsPsych Builder will automate some of the steps in this tutorial, so if you prefer that option, you may want to switch to the getting started instructions on the jsPsych Builder GitHub page.
"},{"location":"tutorials/hello-world/#step-1-install-jspsych","title":"Step 1: Install jspsych","text":"Run npm install jspsych
.
This installs the core jsPsych package. Plugins and extensions are installed separately.
"},{"location":"tutorials/hello-world/#step-2-import-the-initjspsych-function-and-create-a-new-jspsych-instance","title":"Step 2: Import the initJsPsych
function and create a new JsPsych
instance","text":"We create a new instance of the JsPsych
class by calling initJsPsych
. The instance can optionally be configured via a variety of options, passed as an object to initJsPsych
.
import {initJsPsych} from 'jspsych';\n\nconst jsPsych = initJsPsych();\n
"},{"location":"tutorials/hello-world/#step-3-static-markup-and-css","title":"Step 3: Static markup and CSS","text":"jsPsych requires nothing but a body element in your HTML document. For the jsPsych stylesheet, depending on your bundler setup, you can either directly import 'jspsych/css/jspsych.css'
into your JavaScript file or add a link tag (like <link href=\"path/to/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />
) to your HTML document's head.
"},{"location":"tutorials/hello-world/#step-4-install-and-import-a-plugin","title":"Step 4: Install and import a plugin","text":"Install the html-keyboard-response
plugin with:
npm install @jspsych/plugin-html-keyboard-response
Then import the htmlKeyboardResponse
plugin class.
import {initJsPsych} from 'jspsych';\nimport htmlKeyboardResponse from '@jspsych/plugin-html-keyboard-response';\n\nconst jsPsych = initJsPsych();\n
"},{"location":"tutorials/hello-world/#step-5-create-a-trial","title":"Step 5: Create a trial","text":"Once the plugin is imported we can create a trial using the plugin. To declare a trial that uses the html-keyboard-response
plugin, we create an object with the property type
equal to htmlKeyboardResponse
. We can specify the other parameters of the plugin in the same object. Here we use the stimulus
parameter to include a message. You can see the full set of parameters for each plugin on its documentation page.
import {initJsPsych} from 'jspsych';\nimport htmlKeyboardResponse from '@jspsych/plugin-html-keyboard-response';\n\nconst jsPsych = initJsPsych();\n\nconst trial = {\n type: htmlKeyboardResponse,\n stimulus: 'Hello world!',\n}\n
"},{"location":"tutorials/hello-world/#step-6-run","title":"Step 6: Run","text":"Now that we have the trial defined we need to tell jsPsych to run an experiment consisting of this trial. This requires using the jsPsych.run
function and passing in a timeline. For a simple experiment like this one, the timeline is just an array containing the list of trials to run.
import {initJsPsych} from 'jspsych';\nimport htmlKeyboardResponse from '@jspsych/plugin-html-keyboard-response';\n\nconst jsPsych = initJsPsych();\n\nconst trial = {\n type: htmlKeyboardResponse,\n stimulus: 'Hello world!',\n}\n\njsPsych.run([trial]);\n
"},{"location":"tutorials/rt-task/","title":"Summary of Tutorial Content","text":"This tutorial will work through the creation of a simple response time task. The task is to press one key for a blue colored circle and another key for an orange colored circle. Despite this simple task, the tutorial covers many of the key features of jsPsych, including:
- Using a plugin to create a standard trial.
- Combining plugins together to create new kinds of trials.
- Using timeline variables to maximize code reuse.
- Preloading media.
- Randomizing presentation order.
- Manipulating, filtering, and aggregating data.
- Using dynamic content to change the experiment parameters based on the participant's responses.
"},{"location":"tutorials/rt-task/#part-1-creating-a-blank-experiment","title":"Part 1: Creating a blank experiment","text":"Start by setting up a new HTML file with jsPsych, the html-keyboard-response plugin, and the jspsych.css file loaded. If you are unsure how to do this, follow the Hello World tutorial. You should have an HTML document that looks like this:
Info: Loading jsPsych This tutorial assumes that you are using the CDN-based method of loading jsPsych. If you are using another method then everything is the same except for how jsPsych is loaded.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n </script>\n</html>\n
This will be our starting point for building the rest of the experiment.
"},{"location":"tutorials/rt-task/#part-2-display-welcome-message","title":"Part 2: Display welcome message","text":"First we have to initialize jsPsych. We can do this using the initJsPsych()
function, and saving the result to a variable called jsPsych
.
var jsPsych = initJsPsych();\n
All jsPsych experiments are defined by a timeline. The timeline is an array that contains the set of trials we want to run in the experiment. We can start by defining an empty timeline array. We'll add trials to this array as we create them.
var timeline = [];\n
Let's greet the participant with a simple welcome message using the html-keyboard-response plugin.
First, we create a trial that uses the html-keyboard-response
plugin and contains a simple string to show the participant. As explained on the plugins documentation page, the trial object must have a type
parameter that tells jsPsych which plugin to use. The value of type
is similar to the plugin name, but starts with jsPsych
and is written in camel case rather than with dashes. So to use the html-keyboard-response
plugin, we need to write jsPsychHtmlKeyboardResponse
as the trial type.
var welcome = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: \"Welcome to the experiment. Press any key to begin.\"\n};\n
Next, we push the welcome trial to the timeline, which adds it to the end of the array.
timeline.push(welcome);\n
Finally, we tell jsPsych to run the experiment by calling the jsPsych.run() function and passing in the array that defines the experiment timeline.
jsPsych.run(timeline);\n
After each step in the tutorial you can view the complete code up to that point by clicking on the expandable box below. The complete code so far <!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n\n /* initialize jsPsych */\n var jsPsych = initJsPsych();\n\n /* create timeline */\n var timeline = [];\n\n /* define welcome message trial */\n var welcome = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: \"Welcome to the experiment. Press any key to begin.\"\n };\n timeline.push(welcome);\n\n /* start the experiment */\n jsPsych.run(timeline);\n\n </script>\n</html>\n
"},{"location":"tutorials/rt-task/#part-3-show-instructions","title":"Part 3: Show instructions","text":"We can use the same basic structure from part 2 to create a new html-keyboard-response
trial that shows instructions to the participant. The only difference in this trial is that we will use HTML formatting to control how the instructions display and we will add a two second gap after the trial using the post_trial_gap
parameter.
The trial definition looks like this:
var instructions = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `\n <p>In this experiment, a circle will appear in the center \n of the screen.</p><p>If the circle is <strong>blue</strong>, \n press the letter F on the keyboard as fast as you can.</p>\n <p>If the circle is <strong>orange</strong>, press the letter J \n as fast as you can.</p>\n <div style='width: 700px;'>\n <div style='float: left;'><img src='img/blue.png'></img>\n <p class='small'><strong>Press the F key</strong></p></div>\n <div style='float: right;'><img src='img/orange.png'></img>\n <p class='small'><strong>Press the J key</strong></p></div>\n </div>\n <p>Press any key to begin.</p>\n `,\n post_trial_gap: 2000\n};\n
Tip
In JavaScript there are three different ways to define a string
. You can use single quotes '
, double quotes \"
, or backticks `
. Using backticks has two advantages over the other approaches, especially when you are creating long strings with HTML. You can extend the string
across multiple lines and you can use template strings to easily incorporate variables.
Notice that the HTML includes <img>
tags to display the images that the participant will be responding to. You'll need to download these image files. Right-click on each image below and select Save image as.... Put the images in a folder called img
in the experiment folder you created in part 1.
Don't forget to add the trial to the timeline:
timeline.push(instructions);\n
The complete code so far <!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n\n /* initialize jsPsych */\n var jsPsych = initJsPsych();\n\n /* create timeline */\n var timeline = [];\n\n /* define welcome message trial */\n var welcome = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: \"Welcome to the experiment. Press any key to begin.\"\n };\n timeline.push(welcome);\n\n /* define instructions trial */\n var instructions = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `\n <p>In this experiment, a circle will appear in the center \n of the screen.</p><p>If the circle is <strong>blue</strong>, \n press the letter F on the keyboard as fast as you can.</p>\n <p>If the circle is <strong>orange</strong>, press the letter J \n as fast as you can.</p>\n <div style='width: 700px;'>\n <div style='float: left;'><img src='img/blue.png'></img>\n <p class='small'><strong>Press the F key</strong></p></div>\n <div style='float: right;'><img src='img/orange.png'></img>\n <p class='small'><strong>Press the J key</strong></p></div>\n </div>\n <p>Press any key to begin.</p>\n `,\n post_trial_gap: 2000\n };\n timeline.push(instructions);\n\n /* start the experiment */\n jsPsych.run(timeline);\n\n </script>\n</html>\n
"},{"location":"tutorials/rt-task/#part-4-displaying-stimuli-and-getting-responses","title":"Part 4: Displaying stimuli and getting responses","text":"Creating trials to show the stimuli is conceptually the same as creating a trial to show instructions, except that now we are displaying an image instead of text or html. This means we need to use a different plugin: image-keyboard-response
. We need to start by loading this plugin by adding a <script>
tag to the document.
<head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n</head>\n
For now, we will just show each image once. The path to the image file should be set as the stimulus
parameter. We will also set the option for which keys the participant is allowed to use to respond (choices
) so that only the 'f' and 'j' keys are valid responses.
var blue_trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/blue.png',\n choices: ['f', 'j']\n};\n\nvar orange_trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/orange.png',\n choices: ['f', 'j']\n};\n
As usual, we need to add the trials to the timeline.
timeline.push(blue_trial, orange_trial);\n
The complete code so far <!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n\n /* initialize jsPsych */\n var jsPsych = initJsPsych();\n\n /* create timeline */\n var timeline = [];\n\n /* define welcome message trial */\n var welcome = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: \"Welcome to the experiment. Press any key to begin.\"\n };\n timeline.push(welcome);\n\n /* define instructions trial */\n var instructions = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `\n <p>In this experiment, a circle will appear in the center \n of the screen.</p><p>If the circle is <strong>blue</strong>, \n press the letter F on the keyboard as fast as you can.</p>\n <p>If the circle is <strong>orange</strong>, press the letter J \n as fast as you can.</p>\n <div style='width: 700px;'>\n <div style='float: left;'><img src='img/blue.png'></img>\n <p class='small'><strong>Press the F key</strong></p></div>\n <div style='float: right;'><img src='img/orange.png'></img>\n <p class='small'><strong>Press the J key</strong></p></div>\n </div>\n <p>Press any key to begin.</p>\n `,\n post_trial_gap: 2000\n };\n timeline.push(instructions);\n\n /* define test trials */\n var blue_trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/blue.png',\n choices: ['f', 'j']\n };\n\n var orange_trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/orange.png',\n choices: ['f', 'j']\n };\n\n timeline.push(blue_trial, orange_trial);\n\n /* start the experiment */\n jsPsych.run(timeline);\n\n </script>\n</html>\n
"},{"location":"tutorials/rt-task/#part-5-preloading-media","title":"Part 5: Preloading media","text":"Whenever we use media elements (images, audio, or video) in an experiment it is a good idea to preload them prior to needing them for a trial. By preloading media we ask the participant's browser to download the media ahead of needing it, so that when we do need to display or play it there is no lag from needing to download it.
We are going to use the preload plugin to preload the two images. The media preloading section goes into a lot of detail about various options for preloading and different ways that you can use this plugin. Here we are simply going to give the plugin a list of the files that we want to be preloaded.
First we need to add the preload plugin to our <head>
section.
<head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-preload@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n</head>\n
We'll put this trial at the very start of the experiment, so add this code before the welcome
trial.
var preload = {\n type: jsPsychPreload,\n images: ['img/blue.png', 'img/orange.png']\n};\n
As always, add the trial to the timeline.
timeline.push(preload);\n
The complete code so far <!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-preload@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n\n /* initialize jsPsych */\n var jsPsych = initJsPsych();\n\n /* create timeline */\n var timeline = [];\n\n /* preload images */\n var preload = {\n type: jsPsychPreload,\n images: ['img/blue.png', 'img/orange.png']\n };\n timeline.push(preload);\n\n /* define welcome message trial */\n var welcome = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: \"Welcome to the experiment. Press any key to begin.\"\n };\n timeline.push(welcome);\n\n /* define instructions trial */\n var instructions = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `\n <p>In this experiment, a circle will appear in the center \n of the screen.</p><p>If the circle is <strong>blue</strong>, \n press the letter F on the keyboard as fast as you can.</p>\n <p>If the circle is <strong>orange</strong>, press the letter J \n as fast as you can.</p>\n <div style='width: 700px;'>\n <div style='float: left;'><img src='img/blue.png'></img>\n <p class='small'><strong>Press the F key</strong></p></div>\n <div style='float: right;'><img src='img/orange.png'></img>\n <p class='small'><strong>Press the J key</strong></p></div>\n </div>\n <p>Press any key to begin.</p>\n `,\n post_trial_gap: 2000\n };\n timeline.push(instructions);\n\n /* define test trials */\n var blue_trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/blue.png',\n choices: ['f', 'j']\n };\n\n var orange_trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/orange.png',\n choices: ['f', 'j']\n };\n timeline.push(blue_trial, orange_trial);\n\n /* start the experiment */\n jsPsych.run(timeline);\n\n </script>\n</html>\n
"},{"location":"tutorials/rt-task/#part-6-timeline-variables","title":"Part 6: Timeline variables","text":"In the full experiment, we will want more than two trials. One way we could do this is to create many more objects that define trials and push them all onto the timeline, but there is a more efficient way: using timeline variables.
The parameters for showing the blue and orange circle are very similar. The only difference is which image is displayed. Timeline variables allow us to define the procedure for showing the stimulus once, and then repeatedly use it with different variables. We'll see how, even in this relatively simple case, this can save us a lot of lines of code.
To start, let's make an array that contains all the different trials we want to run in the test phase. There are only two for the experiment: blue trials and orange trials.
var test_stimuli = [\n { stimulus: \"img/blue.png\"},\n { stimulus: \"img/orange.png\"}\n];\n
Instead of just showing the blue and orange circles, let's also set up the experiment to show a fixation cross (+) in between trials. We can define a trial to show the fixation cross for a fixed amount of time by using the trial_duration
parameter of the html-keyboard-response plugin and setting the choices
parameter to the special value \"NO_KEYS\"
, which means that no responses will be accepted as a valid response and the trial will last however long the trial_duration
parameter specifies.
var fixation = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<div style=\"font-size:60px;\">+</div>',\n choices: \"NO_KEYS\",\n trial_duration: 1000,\n};\n
To show the circles, we'll set up another trial with the image-keyboard-response plugin, but we'll use the function jsPsych.timelineVariable()
to indicate that we want jsPsych to substitute the value of the parameter in from the timeline variables.
var test = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n choices: ['f', 'j']\n}\n
To link the variables that we declared in the test_stimuli
array with the call to jsPsych.timelineVariable()
we need to create a new timeline and set the timeline_variables
property:
var test_procedure = {\n timeline: [fixation, test],\n timeline_variables: test_stimuli\n}\n
We have to add the test_procedure
to the main timeline
array, but the fixation
and test
trial do not need to be added to timeline
because they already exist on the test_procedure
timeline.
timeline.push(test_procedure);\n
What happens when the experiment reaches the test procedure? jsPsych will run the test_procedure
timeline one time for each entry in the test_stimuli
array (two times total, in this case). The first time through, jsPsych will substitute the timeline variables from the first array entry (blue image), and the second time through the second array entry will be used (orange image). Notice that the fixation trial occurs before both the orange and the blue circles, because the entire timeline of the test_procedure
is repeated for each entry in the timeline_variables
array.
The complete code so far <!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-preload@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n\n /* initialize jsPsych */\n var jsPsych = initJsPsych();\n\n /* create timeline */\n var timeline = [];\n\n /* preload images */\n var preload = {\n type: jsPsychPreload,\n images: ['img/blue.png', 'img/orange.png']\n }\n timeline.push(preload);\n\n /* define welcome message trial */\n var welcome = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: \"Welcome to the experiment. Press any key to begin.\"\n };\n timeline.push(welcome);\n\n /* define instructions trial */\n var instructions = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `\n <p>In this experiment, a circle will appear in the center \n of the screen.</p><p>If the circle is <strong>blue</strong>, \n press the letter F on the keyboard as fast as you can.</p>\n <p>If the circle is <strong>orange</strong>, press the letter J \n as fast as you can.</p>\n <div style='width: 700px;'>\n <div style='float: left;'><img src='img/blue.png'></img>\n <p class='small'><strong>Press the F key</strong></p></div>\n <div style='float: right;'><img src='img/orange.png'></img>\n <p class='small'><strong>Press the J key</strong></p></div>\n </div>\n <p>Press any key to begin.</p>\n `,\n post_trial_gap: 2000\n };\n timeline.push(instructions);\n\n /* define trial stimuli array for timeline variables */\n var test_stimuli = [\n { stimulus: \"img/blue.png\"},\n { stimulus: \"img/orange.png\"}\n ];\n\n /* define fixation and test trials */\n var fixation = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<div style=\"font-size:60px;\">+</div>',\n choices: \"NO_KEYS\",\n trial_duration: 1000,\n };\n\n var test = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n choices: ['f', 'j']\n };\n\n /* define test procedure */\n var test_procedure = {\n timeline: [fixation, test],\n timeline_variables: test_stimuli\n };\n timeline.push(test_procedure);\n\n /* start the experiment */\n jsPsych.run(timeline);\n\n </script>\n</html>\n
"},{"location":"tutorials/rt-task/#part-7-parameters-for-timelines-with-timeline-variables","title":"Part 7: Parameters for timelines with timeline variables","text":"Right now our experiment is a measly two trials long. Even worse is that the order of the stimuli is the same every time! When we use timeline variables, we get access to some methods to randomize the order and repeat the trials. To randomize the order, simply set randomize_order: true
on the object with the timeline_variables
:
var test_procedure = {\n timeline: [fixation, test],\n timeline_variables: test_stimuli,\n randomize_order: true\n};\n
We can also easily make the test phase longer by setting the repetitions
parameter. This parameter controls how many times the experiment will loop through all of the entries in the timeline_variables array. For example, if we set repetitions: 5
, then the experiment will loop through the two entries in the timeline_variables 5 times, for a total of 10 test trials.
var test_procedure = {\n timeline: [fixation, test],\n timeline_variables: test_stimuli,\n randomize_order: true,\n repetitions: 5\n};\n
Info: Randomizing timeline variables In a timeline variables procedure, when randomize_order
is true
and repetitions
is greater than 1, the trial order will be re-randomized on each repetition through the timeline_variables
array. This means that there will be some constraints on the randomization of all trials in the procedure.
For example, if a timeline_variables
array contains one trial per stimulus, then the same stimulus could occur twice in a row (since it could be at the end of one repetition and the start of the next one), but it could not be repeated more than twice in a row, regardless of the number of repetitions
.
If you want to repeat your timeline_variables
array but randomize across all trials, you could use the sample
parameter with the fixed-repetitions
option: this will combine all the repeitions of your timeline_variables
array into one larger array, and then randomize the whole thing. You can read more about the randomization, repetition, and sampling options for timeline variables in the Timeline Variables documentation.
The complete code so far <!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-preload@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n\n /* initialize jsPsych */\n var jsPsych = initJsPsych();\n\n /* create timeline */\n var timeline = [];\n\n /* preload images */\n var preload = {\n type: jsPsychPreload,\n images: ['img/blue.png', 'img/orange.png']\n };\n timeline.push(preload);\n\n /* define welcome message trial */\n var welcome = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: \"Welcome to the experiment. Press any key to begin.\"\n };\n timeline.push(welcome);\n\n /* define instructions trial */\n var instructions = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `\n <p>In this experiment, a circle will appear in the center \n of the screen.</p><p>If the circle is <strong>blue</strong>, \n press the letter F on the keyboard as fast as you can.</p>\n <p>If the circle is <strong>orange</strong>, press the letter J \n as fast as you can.</p>\n <div style='width: 700px;'>\n <div style='float: left;'><img src='img/blue.png'></img>\n <p class='small'><strong>Press the F key</strong></p></div>\n <div style='float: right;'><img src='img/orange.png'></img>\n <p class='small'><strong>Press the J key</strong></p></div>\n </div>\n <p>Press any key to begin.</p>\n `,\n post_trial_gap: 2000\n };\n timeline.push(instructions);\n\n /* define trial stimuli array for timeline variables */\n var test_stimuli = [\n { stimulus: \"img/blue.png\"},\n { stimulus: \"img/orange.png\"}\n ];\n\n /* define fixation and test trials */\n var fixation = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<div style=\"font-size:60px;\">+</div>',\n choices: \"NO_KEYS\",\n trial_duration: 1000,\n };\n\n var test = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n choices: ['f', 'j']\n };\n\n /* define test procedure */\n var test_procedure = {\n timeline: [fixation, test],\n timeline_variables: test_stimuli,\n randomize_order: true,\n repetitions: 5\n };\n timeline.push(test_procedure);\n\n /* start the experiment */\n jsPsych.run(timeline);\n\n </script>\n</html>\n
"},{"location":"tutorials/rt-task/#part-8-using-functions-to-generate-parameters","title":"Part 8: Using functions to generate parameters","text":"One aspect of the experiment that could be improved is the duration of the fixation cross. As the experiment stands right now, the timing of the circles appearing is very predictable. We can change that by using a different value for the trial_duration
parameter in the fixation
trial for each trial. But how can we do that and keep the simple code structure we have now where we only have to define the fixation trial once? One option would be to add another timeline variable, like \"fixation_duration\"
and use that to control the timing. But another option is to specify the trial_duration
parameter as a function. If a parameter is a function, jsPsych will execute the function every time the trial runs. That means that if the function returns different results probabilistically, we can get a different parameter value every time the trial runs.
To do that here, we'll use one of the built-in randomization methods in jsPsych's randomization module. jsPsych.randomization.sampleWithoutReplacement()
takes an array of items to sample from and generates a new array of length N by sampling without replacement.
var fixation = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<div style=\"font-size:60px;\">+</div>',\n choices: \"NO_KEYS\",\n trial_duration: function(){\n return jsPsych.randomization.sampleWithoutReplacement([250, 500, 750, 1000, 1250, 1500, 1750, 2000], 1)[0];\n }\n}\n
In the code above, we replaced the trial_duration: 1000
parameter in fixation
with a function. Inside the function, we take a sample from the array [250, 500, 750, 1000, 1250, 1500, 1750, 2000]
of size 1 (second parameter to jsPsych.randomization.sampleWithoutReplacement
). The return value from calling jsPsych.randomization.sampleWithoutReplacement
is an array of length 1, so we add the [0]
selection at the end to get the value out of the array.
The complete code so far <!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-preload@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n\n /* initialize jsPsych */\n var jsPsych = initJsPsych();\n\n /* create timeline */\n var timeline = [];\n\n /* preload images */\n var preload = {\n type: jsPsychPreload,\n images: ['img/blue.png', 'img/orange.png']\n }\n timeline.push(preload);\n\n /* define welcome message trial */\n var welcome = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: \"Welcome to the experiment. Press any key to begin.\"\n };\n timeline.push(welcome);\n\n /* define instructions trial */\n var instructions = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `\n <p>In this experiment, a circle will appear in the center \n of the screen.</p><p>If the circle is <strong>blue</strong>, \n press the letter F on the keyboard as fast as you can.</p>\n <p>If the circle is <strong>orange</strong>, press the letter J \n as fast as you can.</p>\n <div style='width: 700px;'>\n <div style='float: left;'><img src='img/blue.png'></img>\n <p class='small'><strong>Press the F key</strong></p></div>\n <div style='float: right;'><img src='img/orange.png'></img>\n <p class='small'><strong>Press the J key</strong></p></div>\n </div>\n <p>Press any key to begin.</p>\n `,\n post_trial_gap: 2000\n };\n timeline.push(instructions);\n\n /* define trial stimuli array for timeline variables */\n var test_stimuli = [\n { stimulus: \"img/blue.png\"},\n { stimulus: \"img/orange.png\"}\n ];\n\n /* define fixation and test trials */\n var fixation = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<div style=\"font-size:60px;\">+</div>',\n choices: \"NO_KEYS\",\n trial_duration: function(){\n return jsPsych.randomization.sampleWithoutReplacement([250, 500, 750, 1000, 1250, 1500, 1750, 2000], 1)[0];\n }\n };\n\n var test = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n choices: ['f', 'j']\n };\n\n /* define test procedure */\n var test_procedure = {\n timeline: [fixation, test],\n timeline_variables: test_stimuli,\n randomize_order: true,\n repetitions: 5\n };\n timeline.push(test_procedure);\n\n /* start the experiment */\n jsPsych.run(timeline);\n\n </script>\n</html>\n
"},{"location":"tutorials/rt-task/#part-10-displaying-the-data","title":"Part 10: Displaying the data","text":"We have created a complete, if simple, experiment at this point, so let's take a look at the data being generated. jsPsych has a built-in function called jsPsych.data.displayData()
that is useful for debugging your experiment. It will remove all of the information on the screen and replace it with the raw data collected so far. This isn't terribly useful when you are actually running an experiment, but it's nice for checking the data during development.
We need the displayData
function to execute when the experiment ends. One way to do this is to use the on_finish
callback function. This function will automatically execute once all the trials in the experiment are finished. We can specify this function in the experiment settings when we initialize jsPsych with the initJsPsych
method.
var jsPsych = initJsPsych({\n on_finish: function() {\n jsPsych.data.displayData();\n }\n});\n
The complete code so far <!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-preload@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n\n /* initialize jsPsych */\n var jsPsych = initJsPsych({\n on_finish: function() {\n jsPsych.data.displayData();\n }\n });\n\n /* create timeline */\n var timeline = [];\n\n /* preload images */\n var preload = {\n type: jsPsychPreload,\n images: ['img/blue.png', 'img/orange.png']\n };\n timeline.push(preload);\n\n /* define welcome message trial */\n var welcome = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: \"Welcome to the experiment. Press any key to begin.\"\n };\n timeline.push(welcome);\n\n /* define instructions trial */\n var instructions = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `\n <p>In this experiment, a circle will appear in the center \n of the screen.</p><p>If the circle is <strong>blue</strong>, \n press the letter F on the keyboard as fast as you can.</p>\n <p>If the circle is <strong>orange</strong>, press the letter J \n as fast as you can.</p>\n <div style='width: 700px;'>\n <div style='float: left;'><img src='img/blue.png'></img>\n <p class='small'><strong>Press the F key</strong></p></div>\n <div style='float: right;'><img src='img/orange.png'></img>\n <p class='small'><strong>Press the J key</strong></p></div>\n </div>\n <p>Press any key to begin.</p>\n `,\n post_trial_gap: 2000\n };\n timeline.push(instructions);\n\n /* define trial stimuli array for timeline variables */\n var test_stimuli = [\n { stimulus: \"img/blue.png\"},\n { stimulus: \"img/orange.png\"}\n ];\n\n /* define fixation and test trials */\n var fixation = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<div style=\"font-size:60px;\">+</div>',\n choices: \"NO_KEYS\",\n trial_duration: function(){\n return jsPsych.randomization.sampleWithoutReplacement([250, 500, 750, 1000, 1250, 1500, 1750, 2000], 1)[0];\n }\n };\n\n var test = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n choices: ['f', 'j']\n };\n\n /* define test procedure */\n var test_procedure = {\n timeline: [fixation, test],\n timeline_variables: test_stimuli,\n randomize_order: true,\n repetitions: 5\n };\n timeline.push(test_procedure);\n\n /* start the experiment */\n jsPsych.run(timeline);\n\n </script>\n</html>\n
"},{"location":"tutorials/rt-task/#part-11-tagging-trials-with-additional-data","title":"Part 11: Tagging trials with additional data","text":"All trials in jsPsych can be tagged with additional arbitrary data. This data will get stored alongside the data that the plugin normally generates, which allows experimenters to record properties of a trial along with the data from the trial.
When might you use this feature? In this experiment, it would be nice to tag each trial with a circle as a response
trial, so that the resulting data can be easily filtered to look at only the critical trials. We can do that like this.
var test = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n choices: ['f', 'j'],\n data: {\n task: 'response'\n }\n};\n
We also could tag the test trials with a property that indicates what the correct response should be (F for the blue circles, J for the orange). In our current code, we are using the timeline variables feature of jsPsych to choose which circle gets presented on a trial. Since we want to tag the trials differently based on which circle is presented, we need to add the tagging data to the test_stimuli
array, and then use the jsPsych.timelineVariable()
function to get the value and assign it to a property in the data
of the trial.
We start by adding a \"correct_response\" property and value to each object in the test_stimuli
:
var test_stimuli = [\n { stimulus: \"img/blue.png\", correct_response: 'f'},\n { stimulus: \"img/orange.png\", correct_response: 'j'}\n];\n
Now we can use timelineVariable()
in the data
parameter of the test
trial to get the appropriate \"correct_response\" value for each trial.
var test = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n choices: ['f', 'j'],\n data: {\n task: 'response',\n correct_response: jsPsych.timelineVariable('correct_response')\n }\n};\n
Another kind of tagging that would be useful is to mark each fixation trial as such, to make removing the data from fixation trials easier.
var fixation = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<div style=\"font-size:60px;\">+</div>',\n choices: \"NO_KEYS\",\n trial_duration: function(){\n return jsPsych.randomization.sampleWithoutReplacement([250, 500, 750, 1000, 1250, 1500, 1750, 2000], 1)[0];\n },\n data: {\n task: 'fixation'\n }\n};\n
The complete code so far <!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-preload@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n\n /* initialize jsPsych */\n var jsPsych = initJsPsych({\n on_finish: function() {\n jsPsych.data.displayData();\n }\n });\n\n /* create timeline */\n var timeline = [];\n\n /* preload images */\n var preload = {\n type: jsPsychPreload,\n images: ['img/blue.png', 'img/orange.png']\n };\n timeline.push(preload);\n\n /* define welcome message trial */\n var welcome = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: \"Welcome to the experiment. Press any key to begin.\"\n };\n timeline.push(welcome);\n\n /* define instructions trial */\n var instructions = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `\n <p>In this experiment, a circle will appear in the center \n of the screen.</p><p>If the circle is <strong>blue</strong>, \n press the letter F on the keyboard as fast as you can.</p>\n <p>If the circle is <strong>orange</strong>, press the letter J \n as fast as you can.</p>\n <div style='width: 700px;'>\n <div style='float: left;'><img src='img/blue.png'></img>\n <p class='small'><strong>Press the F key</strong></p></div>\n <div style='float: right;'><img src='img/orange.png'></img>\n <p class='small'><strong>Press the J key</strong></p></div>\n </div>\n <p>Press any key to begin.</p>\n `,\n post_trial_gap: 2000\n };\n timeline.push(instructions);\n\n /* define trial stimuli array for timeline variables */\n var test_stimuli = [\n { stimulus: \"img/blue.png\", correct_response: 'f'},\n { stimulus: \"img/orange.png\", correct_response: 'j'}\n ];\n\n /* define fixation and test trials */\n var fixation = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<div style=\"font-size:60px;\">+</div>',\n choices: \"NO_KEYS\",\n trial_duration: function(){\n return jsPsych.randomization.sampleWithoutReplacement([250, 500, 750, 1000, 1250, 1500, 1750, 2000], 1)[0];\n },\n data: {\n task: 'fixation'\n }\n };\n\n var test = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n choices: ['f', 'j'],\n data: {\n task: 'response',\n correct_response: jsPsych.timelineVariable('correct_response')\n }\n };\n\n /* define test procedure */\n var test_procedure = {\n timeline: [fixation, test],\n timeline_variables: test_stimuli,\n randomize_order: true,\n repetitions: 5\n };\n timeline.push(test_procedure);\n\n /* start the experiment */\n jsPsych.run(timeline);\n\n </script>\n </html>\n
"},{"location":"tutorials/rt-task/#part-12-manipulating-data-during-the-experiment","title":"Part 12: Manipulating data during the experiment","text":"Now that the data from the test trials has a tag that describes the correct response, it would be easy to analyze the data after the fact and calculate whether the participant responded correctly.
But, we can also do this in jsPsych as the experiment runs to save time later and enable a limited set of data analysis directly in the experiment code.
To do this, we'll use the on_finish
event of the test trial. We can assign a function to on_finish
, and that function will receive an object containing the data generated by the trial. This object can be manipulated inside the function, and any changes made to the object will be stored in jsPsych's internal representation of the data.
For this example, we'll determine whether the participant responded correctly, and add a new correct
property to the data object.
var test = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n choices: ['f', 'j'],\n data: {\n task: 'response',\n correct_response: jsPsych.timelineVariable('correct_response')\n },\n on_finish: function(data){\n data.correct = jsPsych.pluginAPI.compareKeys(data.response, data.correct_response);\n }\n};\n
The data.response
value is a string representation of the key the participant pressed. We can compare this with the data.correct_response
value, and assign this computed value to a new property data.correct
.
Info: The compareKeys
function Here we are comparing the values of data.response
and data.correct_response
using a jsPsych function called jsPsych.pluginAPI.compareKeys. We're using this function because it allows us to compare keys in either a case sensitive or case insensitive way, depending on the case_sensitive_responses
parameter in the experiment settings. The participant's key response will be recorded in a case-sensitive way in the data (e.g. 'f' or 'F'), but in most cases, we don't care if their response corresponds to an upper or lower case letter (which is why the case_sensitive_responses
experiment setting is false
by default). Using the jsPsych.pluginAPI.commpareKeys
function here means that the response will be scored correctly, even if the participant holds down Shift or has Caps Lock on.
This function is only relevant for keyboard responses; for other kinds of responses, such as button presses, you can simply compare the response and correct response values directly, e.g.
data.correct = data.response === data.correct_response;\n
The complete code so far <!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-preload@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n\n /* initialize jsPsych */\n var jsPsych = initJsPsych({\n on_finish: function() {\n jsPsych.data.displayData();\n }\n });\n\n /* create timeline */\n var timeline = [];\n\n /* preload images */\n var preload = {\n type: jsPsychPreload,\n images: ['img/blue.png', 'img/orange.png']\n };\n timeline.push(preload);\n\n /* define welcome message trial */\n var welcome = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: \"Welcome to the experiment. Press any key to begin.\"\n };\n timeline.push(welcome);\n\n /* define instructions trial */\n var instructions = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `\n <p>In this experiment, a circle will appear in the center \n of the screen.</p><p>If the circle is <strong>blue</strong>, \n press the letter F on the keyboard as fast as you can.</p>\n <p>If the circle is <strong>orange</strong>, press the letter J \n as fast as you can.</p>\n <div style='width: 700px;'>\n <div style='float: left;'><img src='img/blue.png'></img>\n <p class='small'><strong>Press the F key</strong></p></div>\n <div style='float: right;'><img src='img/orange.png'></img>\n <p class='small'><strong>Press the J key</strong></p></div>\n </div>\n <p>Press any key to begin.</p>\n `,\n post_trial_gap: 2000\n };\n timeline.push(instructions);\n\n /* define trial stimuli array for timeline variables */\n var test_stimuli = [\n { stimulus: \"img/blue.png\", correct_response: 'f'},\n { stimulus: \"img/orange.png\", correct_response: 'j'}\n ];\n\n /* define fixation and test trials */\n var fixation = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<div style=\"font-size:60px;\">+</div>',\n choices: \"NO_KEYS\",\n trial_duration: function(){\n return jsPsych.randomization.sampleWithoutReplacement([250, 500, 750, 1000, 1250, 1500, 1750, 2000], 1)[0];\n },\n data: {\n task: 'fixation'\n }\n };\n\n var test = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n choices: ['f', 'j'],\n data: {\n task: 'response',\n correct_response: jsPsych.timelineVariable('correct_response')\n },\n on_finish: function(data){\n data.correct = jsPsych.pluginAPI.compareKeys(data.response, data.correct_response);\n }\n };\n\n /* define test procedure */\n var test_procedure = {\n timeline: [fixation, test],\n timeline_variables: test_stimuli,\n randomize_order: true,\n repetitions: 5\n };\n timeline.push(test_procedure);\n\n /* start the experiment */\n jsPsych.run(timeline);\n\n </script>\n</html>\n
"},{"location":"tutorials/rt-task/#part-13-data-aggregation","title":"Part 13: Data aggregation","text":"jsPsych provides a limited set of analysis functions to allow you to calculate things like mean response times for a selected set of trials. In this part, we'll use these functions to add a final trial to the experiment that tells the participant their accuracy and their mean response time for correct responses.
We'll use the html-keyboard-response
plugin. Because the text that we want to display changes based on the participant's performance in the experiment, we need to use a function for the stimulus
parameter and return the desired text.
Info: Dynamic parameters Using a function as the value of a 'normal' parameter (i.e. a parameter that isn't usually a function) provides lots of flexibility in jsPsych experiments, because it allows you to dynamically change the parameter's value based on the participant's earlier responses, and any other information that you don't know before the experiment has started. For more information and examples, see the dynamic parameter documentation page.
Here's what the code looks like, and a description follows below.
var debrief_block = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: function() {\n\n var trials = jsPsych.data.get().filter({task: 'response'});\n var correct_trials = trials.filter({correct: true});\n var accuracy = Math.round(correct_trials.count() / trials.count() * 100);\n var rt = Math.round(correct_trials.select('rt').mean());\n\n return `<p>You responded correctly on ${accuracy}% of the trials.</p>\n <p>Your average response time was ${rt}ms.</p>\n <p>Press any key to complete the experiment. Thank you!</p>`;\n\n }\n};\ntimeline.push(debrief_block);\n
To create the variable trials
, we use jsPsych.data.get()
which returns a jsPsych data collection containing all of the data from the experiment. We can then use .filter
to select only the trials where task
is 'response'
(a benefit of tagging the trials in part 11). trials
contains all of the data from the trials where a circle was shown.
To get only the correct trials, we can use .filter()
again to select only the trials from the trials
data collection where the property correct
is true
.
To calculate accuracy, we can use the .count()
method to determine how many trials were correct and how many trials there were total. We also use Math.round()
to avoid extra digits after the decimal.
Finally, to calculate the mean response time on correct trials, we use the .select
method on the correct_trials
data collection to select only the 'rt'
property of those trials. We can then use the .mean()
method to find the mean of all the RT values.
"},{"location":"tutorials/rt-task/#the-final-code","title":"The final code","text":"This code is available in the /examples
folder in the jsPsych release download. It is called demo-simple-rt-task.html
.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-preload@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n\n /* initialize jsPsych */\n var jsPsych = initJsPsych({\n on_finish: function() {\n jsPsych.data.displayData();\n }\n });\n\n /* create timeline */\n var timeline = [];\n\n /* preload images */\n var preload = {\n type: jsPsychPreload,\n images: ['img/blue.png', 'img/orange.png']\n };\n timeline.push(preload);\n\n /* define welcome message trial */\n var welcome = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: \"Welcome to the experiment. Press any key to begin.\"\n };\n timeline.push(welcome);\n\n /* define instructions trial */\n var instructions = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `\n <p>In this experiment, a circle will appear in the center \n of the screen.</p><p>If the circle is <strong>blue</strong>, \n press the letter F on the keyboard as fast as you can.</p>\n <p>If the circle is <strong>orange</strong>, press the letter J \n as fast as you can.</p>\n <div style='width: 700px;'>\n <div style='float: left;'><img src='img/blue.png'></img>\n <p class='small'><strong>Press the F key</strong></p></div>\n <div style='float: right;'><img src='img/orange.png'></img>\n <p class='small'><strong>Press the J key</strong></p></div>\n </div>\n <p>Press any key to begin.</p>\n `,\n post_trial_gap: 2000\n };\n timeline.push(instructions);\n\n /* define trial stimuli array for timeline variables */\n var test_stimuli = [\n { stimulus: \"img/blue.png\", correct_response: 'f'},\n { stimulus: \"img/orange.png\", correct_response: 'j'}\n ];\n\n /* define fixation and test trials */\n var fixation = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<div style=\"font-size:60px;\">+</div>',\n choices: \"NO_KEYS\",\n trial_duration: function(){\n return jsPsych.randomization.sampleWithoutReplacement([250, 500, 750, 1000, 1250, 1500, 1750, 2000], 1)[0];\n },\n data: {\n task: 'fixation'\n }\n };\n\n var test = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n choices: ['f', 'j'],\n data: {\n task: 'response',\n correct_response: jsPsych.timelineVariable('correct_response')\n },\n on_finish: function(data){\n data.correct = jsPsych.pluginAPI.compareKeys(data.response, data.correct_response);\n }\n };\n\n /* define test procedure */\n var test_procedure = {\n timeline: [fixation, test],\n timeline_variables: test_stimuli,\n repetitions: 5,\n randomize_order: true\n };\n timeline.push(test_procedure);\n\n /* define debrief */\n var debrief_block = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: function() {\n\n var trials = jsPsych.data.get().filter({task: 'response'});\n var correct_trials = trials.filter({correct: true});\n var accuracy = Math.round(correct_trials.count() / trials.count() * 100);\n var rt = Math.round(correct_trials.select('rt').mean());\n\n return `<p>You responded correctly on ${accuracy}% of the trials.</p>\n <p>Your average response time was ${rt}ms.</p>\n <p>Press any key to complete the experiment. Thank you!</p>`;\n\n }\n };\n timeline.push(debrief_block);\n\n /* start the experiment */\n jsPsych.run(timeline);\n\n </script>\n</html>\n
"},{"location":"tutorials/video-tutorials/","title":"Video tutorials","text":"Warning
Most of these videos are using version 6.x
of jsPsych. Using version 7.x
requires a few changes that are not covered in these videos. We recommend starting with the tutorials on this website to understand how to work with 7.x
and then watching these videos for additional information. Much of the content covered in the videos still applies to 7.x
, but you'll need a solid understanding of how to use 7.x
in order to make use of the examples in the videos.
"},{"location":"tutorials/video-tutorials/#youtube-channel","title":"YouTube Channel","text":"A variety of video tutorials are available on Josh de Leeuw's YouTube channel. Some tutorials walk through creating a basic version of an entire experiment, like the tutorial on creating a dichotic listening experiment aimed at new users. Others focus on specific features of jsPsych, like how to use functions as parameters to create experiments that change in response to participant input or how to create a new plugin.
"},{"location":"tutorials/video-tutorials/#workshops","title":"Workshops","text":"Moving Research Online (2020). Recordings from a Summer 2020 workshop on conducting online research are available on the workshop's YouTube channel. Session 1 provides an overview of jsPsych suitable for brand new users. Session 3 covers some more advanced features of jsPsych. This workshop was funded by the National Science Foundation.
babySTEP (2021). The Centre for Comparative Psycholinguistics (CCP, University of Alberta Department of Linguistics) hosted a two-part jsPsych workshop in 2021 as part of their annual STEP program. Day 1 covered the basics of creating a jsPsych experiment, with an emphasis on audio stimuli. Day 2 was organized around pre-submitted questions. The video demonstrates how to create a more complex experiment involving reading a sentence and hearing different audio options for completing the sentences, and answers several questions about timing accuracy, recording participant generated audio, embedding jsPsych into course (or other) websites, and some (non-empirical) advice about attention checks.
"}]}
\ No newline at end of file
+{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Introduction","text":"jsPsych is a JavaScript framework for creating behavioral experiments that run in a web browser.
Experiments in jsPsych are created using plugins. Each plugin defines different kinds of events, like showing an image on the screen, and collects different kinds of data, like recording which key was pressed at which time. You can use the plugins that are included with jsPsych, use plugins that are developed by community members in the contrib repository, or create your own plugins. By assembling different plugins together into a timeline, it is possible to create a wide range of experiments.
The page on timelines is a good place to start learning about jsPsych. From there, you might want to complete the hello world tutorial to learn how to set up a jsPsych experiment and the reaction time experiment tutorial to learn the core features of the framework.
"},{"location":"about/about/","title":"About jsPsych","text":"jsPsych is open source project with numerous contributors. The project is currently managed by the core team of Josh de Leeuw (@jodeleeuw), Becky Gilbert (@becky-gilbert), and Bj\u00f6rn Luchterhandt (@bjoluc).
jsPsych was created by Josh de Leeuw.
"},{"location":"about/about/#citation","title":"Citation","text":"If you use this library in academic work, the preferred citation is:
de Leeuw, J.R., Gilbert, R.A., & Luchterhandt, B. (2023). jsPsych: Enabling an open-source collaborative ecosystem of behavioral experiments. Journal of Open Source Software, 8(85), 5351, https://joss.theoj.org/papers/10.21105/joss.05351.
This paper is an updated description of jsPsych and includes all current core team members. It replaces the earlier paper that described jsPsych:
de Leeuw, J.R. (2015). jsPsych: A JavaScript library for creating behavioral experiments in a Web browser. Behavior Research Methods, 47(1), 1-12. doi:10.3758/s13428-014-0458-y
Citations help us demonstrate that this library is used and valued, which allows us to continue working on it.
"},{"location":"about/about/#citation-tool-for-third-party-pluginsextensions","title":"Citation tool for third-party plugins/extensions","text":"jsPsych is an open-source, collaborative ecosystem, and many of the plugins/extensions you end up using may be contributed by third-party developers! We want to make sure they get recognition for their good work, so we made a command-line citation tool that you should use to cite this library and the plugins/extensions used in your experiment. You can see this tool in action by following these steps:
- Launch a jsPsych experiment in your browser
- Open up the browser console using Ctrl + \u21e7 + J (Windows) or \u2318 + \u2325 + J (Mac)
- Type
jsPsych.getCitations()
This should print the APA format citation for the jsPsych library, which you can then copy and paste into your working document. To cite the plugins/extensions in your experiment, you should pass in an array containing the name of each plugin/extension to generate a list of citations, e.g. jsPsych.getCitations([jsPsychHtmlKeyboardResponse, jsPsychMouseTrackingExtension])
. You can also pass in the desired output citation format as the second argument, e.g. jsPsych.getCitations([jsPsychHtmlKeyboardResponse, jsPsychMouseTrackingExtension], \"apa\")
. We currently support APA formatting (\"apa\"
) and BibTex formatting (\"bibtex\"
).
"},{"location":"about/license/","title":"License","text":"jsPsych is licensed under the MIT license.
The MIT License (MIT)\n\nCopyright (c) 2014-2022 Joshua R. de Leeuw\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n
"},{"location":"developers/configuration/","title":"Configuring the jsPsych development environment","text":""},{"location":"developers/configuration/#setup","title":"Setup","text":"JsPsych is written using TypeScript, a superset of JavaScript that adds static typing, but compiles to plain JavaScript. The TypeScript compiler itself is written in JavaScript and can be run by Node.js, a runtime to execute JavaScript code without a web browser. Node.js comes with a package manager called NPM (Node Package Manager) that can install JavaScript libraries to run on your machine, such as TypeScript and other build tools for jsPsych. In order to work on code in the jsPsych or the jspsych-contrib repository, it is recommended that you follow the steps below to set up your development environment.
"},{"location":"developers/configuration/#install-nodejs","title":"Install Node.js","text":"The jsPsych development setup requires a Node.js LTS version to be installed on your machine.
"},{"location":"developers/configuration/#clone-the-repository-and-install-the-dependencies","title":"Clone the repository and install the dependencies","text":"Clone either the jsPsych repository or the jspsych-contrib repository by running
git clone https://github.com/jspsych/jsPsych.git && cd jsPsych\n
or
git clone https://github.com/jspsych/jspsych-contrib.git && cd jspsych-contrib\n
in a terminal.
Then run npm install
. This will create a node_modules
directory and install all the dependencies into it that are required to build and test jsPsych.
Info
The jsPsych (-contrib) repositories depend on the canvas
package which comes with pre-built binaries. On systems for which no pre-built binaries are available, npm install
will try to build the binaries from scratch, sometimes failing with an error message mentioning the canvas
package. If you are facing such installation issues, please follow the installation instructions of the canvas
package and run npm install
again afterwards.
Info
If you are running npm install
in the core jsPsych repository, this will also execute the build chain for all packages in the jsPsych repository. This step may take a few minutes. If you would like to use that time efficiently, consider reading the following two sections to know what's happening.
"},{"location":"developers/configuration/#repository-structure","title":"Repository structure","text":"A Node.js package is a directory that contains a package.json
file describing it. Most importantly, a package.json
file lists other packages that the package depends on. The jsPsych and jspsych-contrib repositories use NPM workspaces. That means, running npm install
in the repository root will install the dependencies for all packages in the packages
directory. The core jsPsych library and every jsPsych plugin or extension is laid out as an individual package. These packages are published to the NPM registry where they can be downloaded by NPM or any CDN (such as unpkg).
"},{"location":"developers/configuration/#build-chain-and-build-artifacts","title":"Build chain and build artifacts","text":"JsPsych comes with a build chain (specified in the @jspsych/config
package) that can be executed by running npm run build
in a package's directory. The build chain will read the package (starting at its src/index.ts
file) and create the following build artifacts in the package's dist
directory:
-
index.js
This file contains everything from index.ts
, but as plain JavaScript and bundled in a single file (i.e. without import
ing files from the same package). It is used by bundlers like webpack.
-
index.cjs
Like index.js
, but using the old CommonJS standard to support tools like the Jest testing framework.
-
index.browser.js
This file, like index.js
, contains the entire package as plain JavaScript, but this time wrapped in a function so that it can be included directly by browsers using the <script>
tag. For plugins or extensions, the default export of a module (i.e. whatever statement comes after export default
in the index.ts
file) is assigned to a global variable. The name of this global variable is specified in the package's rollup.config.mjs
file, as a parameter to the makeRollupConfig()
function. Hence, for instance, including the index.browser.js
file from the plugin-html-keyboard-response
package would assign the HtmlKeyboardResponsePlugin
class to the global jsPsychHtmlKeyboardResponse
variable. Because the code in index.browser.js
looks very similar to the index.ts
code but is fully supported by modern web browsers, all examples in the examples
directory reference the index.browser.js
files so users can also modify the source code directly without running the build chain.
-
index.browser.min.js
There are different versions of the JavaScript language specification and not all web browsers and browser versions support all JavaScript features. That's why the jsPsych build chain uses esbuild to translate the source files into code that a majority of web browsers can understand. The result of this operation is index.browser.min.js
. It behaves just like index.browser.js
, but adds support for older browsers by substituting new JavaScript features using older ones. Because this is the recommended build artifact for production use (and is automatically served by unpkg), the code in index.browser.min.js
is also minified to reduce its size and speed up experiment loading times.
-
*.js.map
When debugging code in a browser (especially index.browser.min.js
, which is minified and hence not easily readable), it is important to be able to read the original source code in the debugger. For every build artifact, there is a .map
file which contains a mapping of the generated code to the original source code. Browsers automatically read these .map
files and display the original code in their debuggers instead of the generated one.
-
index.d.ts
This file contains the TypeScript type definitions that would otherwise be lost during compilation to plain JavaScript. They are read by Typescript and editors when a package is imported into another TypeScript project.
"},{"location":"developers/configuration/#testing","title":"Testing","text":"Automated code testing for jsPsych is implemented with Jest.
To run the tests, install Node and npm. Run npm install
in the root jsPsych directory. Then run npm test
. You can also run npm test
in the directory of the package that you would like to test. For example, if you are developing tests for the html-keyboard-response
plugin you can run npm test
in /packages/plugin-html-keyboard-response
. If you want to run one file from the root directory, using the aforementioned example, you can run npm test -- /packages/plugin-html-keyboard-response/src/index.spec.ts
.
Tests for the core jsPsych library are located in /packages/jspsych/tests
.
Tests for plugins and extensions are located in the /src
folder of the corresponding package. Test files for plugins and extensions are named index.spec.ts
.
There are helper functions for testing in /packages/test-utils
. We recommend looking at other test files to observe conventions for testing.
"},{"location":"developers/contributing/","title":"Contributing to jsPsych","text":"We welcome contributions of all kinds, including changes to the core codebase, the development of new plugins and extensions, and improvements to the documentation.
The project is managed entirely through the GitHub repository. There you can:
- Use discussions to propose ideas for development and seek feedback on contributions, such as a new plugin.
- Use issues to identify anything with an actionable next step. For example, a page in the documentation that needs to be fixed, a bug in the code, or a specific feature that has a clear scope.
- Submit a pull request with modifications to the codebase. Pull requests will be reviewed by one or more members of the core team.
"},{"location":"developers/contributing/#guidelines-for-contibuting","title":"Guidelines for contibuting","text":""},{"location":"developers/contributing/#contributing-to-the-codebase","title":"Contributing to the codebase","text":"We welcome contributions of any scope. Before we can merge changes into the main codebase, we generally require a few things. Note that you are welcome to contribute code without these things in place, but it will help us get to your contribution faster if you take care of whatever components you are comfortable doing.
-
The code must be tested through our automated testing system. We use Jest as the testing framework. If you are fixing a bug, consider adding a test case that shows the bug has been resolved. If you are contributing new features, like a new plugin, a test suite for the plugin is very helpful. See testing jsPsych for more information about configuring the test tools and writing tests.
-
Relevant documentation must be updated. Any pages in /docs
that are affected by the contribution should be updated, and if new pages are needed they should be created. For example, if you are contributing a plugin then adding documentation for the plugin and updating the list of available plugins as well as the mkdocs configuration file is very helpful!
-
An example file should be included if applicable. If you are contributing a new feature, new plugin, or new extension, or contributing a modification that changes the behavior of the library in some important way, consider adding an example file to the /examples
folder in the repository.
-
If you are contributing a plugin/extension, we strongly encourage including a file containing citation information. This file should be named CITATION.cff
and placed at the root of your repository. This allows people who use your plugin/extension in their code to easily cite your work by calling jsPsych.getCitations([<yourPlugin>])
from their command line. More information on .cff
files can be found here.
-
A changeset must be included in the pull request. We use changesets to generate new releases and their corresponding release notes. This is a good overview of changesets that explains how to add one to your pull request. Feel free to ask for help with this!
-
Update the contributors.md file. If you are a first time contributor to jsPsych please add your name to our contributors file. And thanks!
"},{"location":"developers/contributing/#contributing-to-the-documentation","title":"Contributing to the documentation","text":"We are very appreciative of both small and large contributions to the documentation, from fixing a typo to adding a whole new tutorial. All of the documentation that appears on this site is contained in the /docs
folder of the repository. The documentation is built using MkDocs and themed using Material for MkDocs. You can edit any of the markdown files and submit a pull request to modify documentation.
If you'd like to test your changes to the documentation locally you'll need to install MkDocs and Material for MkDocs. Then you can run the command mike serve
in the root folder of the repository to launch a local webserver and view the documentation.
"},{"location":"developers/contributing/#contributing-to-jspsych-vs-jspsych-contrib","title":"Contributing to jspsych
vs. jspsych-contrib
","text":"If you are developing a new plugin or extension there are two different repositories that you can contribute to: jspsych
or jspsych-contrib
.
The main jspsych
repository is open to new plugins and extensions that are likely to be widely used. We require that contributions to main repository are well documented and tested before they are merged. Contributions to the main repository must use TypeScript. We limit contributions to this repository because once a plugin or extension is in the main codebase we are generally committed to providing updates as we develop new versions of jsPsych. Each new plugin and extension potentially increases the amount of development work that we will need to do in the future, so we are somewhat selective about what we will merge. If you have an idea that you'd like to discuss please open a discussion thread and we'd love to chat about it!
The jspsych-contrib
repository is open to any contributions that are complete and working code. There are some minimal guidelines in place about basic documentation that should be provided. Contributors can choose whether to develop their plugin or extension using our TypeScript template or using our JavaScript template. Check our plugin developer documentation for additional guidance.
Contributions to jspsych-contrib
are not evaluated for general usefulness in the same way that contributions to the main repository are. We also periodically consider whether to move contributions into the main repository from jspsych-contrib
based on their popularity and completeness (documentation and testing).
"},{"location":"developers/documentation/","title":"Building the jsPsych documentation","text":"The documentation hosted at https://www.jspsych.org is generated using mkdocs and the mkdocs-material theme. The documentation files are located in the /docs
directory of the GitHub repository. The documentation is written using markdown.
To build a local copy of the docs, you will need to install mkdocs
, mkdocs-material
, and mike
using poetry
.
"},{"location":"developers/documentation/#install-poetry","title":"Install poetry","text":"Poetry is a package manager for python. Follow the install instructions on the poetry
website to get it running.
"},{"location":"developers/documentation/#install-dev-dependencies","title":"Install dev dependencies","text":"Run the command poetry install
in the root directory of jsPsych to install mkdocs
, mkdocs-material
, and their dependencies.
"},{"location":"developers/documentation/#building-a-local-copy-of-the-docs","title":"Building a local copy of the docs","text":"Run poetry run mike deploy [version] -u
to build a new version of the documentation or to override an existing version. For example, if you are testing an edit to version 7.2
of the documentation, run poetry run mike deploy 7.2 -u
.
You can also use jsPsych's custom npm command: npm run docs:deploy [version]
, e.g. npm run docs:deploy 7.2
.
This will build the documentation and commit it directly to the gh-pages
branch.
We use mike
instead of mkdocs
for the build step to support versioning of the documentation. mike
runs the mkdocs
command under the hood.
"},{"location":"developers/documentation/#viewing-the-local-docs","title":"Viewing the local docs","text":"To launch a local webserver, run poetry run mike serve
, or use jsPsych's custom npm command: npm run docs:serve
.
The docs will be viewable at http://localhost:8000
.
"},{"location":"developers/documentation/#updating-the-public-docs-site","title":"Updating the public docs site","text":"For core maintainers only
After the documentation has been built locally (and therefore committed to your local gh-pages
branch), you can update the live documentation site by switching to your gh-pages
branch and pushing to the remote gh-pages
branch.
"},{"location":"developers/extension-development/","title":"Extension development","text":""},{"location":"developers/extension-development/#requirements-for-an-extension","title":"Requirements for an extension","text":"As of version 7.0, extensions are JavaScript Classes. An extension must implement:
- A
constructor()
that accepts an instance of jsPsych. - An
initialize()
function to handle the initialize event of the extension. - An
on_start()
function to handle the on_start event of the extension. - An
on_load()
function to handle the on_load event of the extension. - An
on_finish()
function to handle the on_finish event of the extension and store data that the extension collects. - A static
info
property containing a unique name, version parameter, and data property for the extension.
"},{"location":"developers/extension-development/#templates","title":"Templates","text":"Plugins can be written in either plain JavaScript or in TypeScript. Template files for both JavaScript and TypeScript are available in the jspsych-contrib repository.
"},{"location":"developers/extension-development/#extension-components","title":"Extension components","text":""},{"location":"developers/extension-development/#constructor","title":"constructor()","text":"The extension's constructor()
will be passed a reference to the instance of the JsPsych
class that is running the experiment. The constructor should store this reference so that the plugin can access functionality from the core library and its modules.
class MyAwesomeExtension {\n constructor(jsPsych){\n this.jsPsych = jsPsych;\n }\n}\n
"},{"location":"developers/extension-development/#initialize","title":"initialize()","text":"The initialize()
function is called when an instance of jsPsych is first initialized, either through initJsPsych()
or new JsPsych()
. This is where setup code for the extension should be run. This event will happen once per experiment, unlike the other events which occur with each trial. The params
object can include whatever parameters are necessary to configure the extension. The params
object is passed from the call to initJsPsych()
to initialize()
method. initialize()
must return a Promise
that resolves when the extension is finished initializing.
//... experiment code ...//\nlet jsPsych = initJsPsych({\n extensions: [\n {type: myAwesomeExtension, params: {demo: 'value'}}\n ]\n});\n\n//... extension code ...//\nclass MyAwesomeExtension {\n\n initialize(params){\n return new Promise((resolve, reject)=>{\n console.log(params.demo); // will output 'value'\n\n resolve(); // finish initialzing\n })\n }\n}\n
"},{"location":"developers/extension-development/#on_start","title":"on_start()","text":"on_start()
is called at the start of the plugin execution, prior to calling plugin.trial
. This is where trial-specific initialization can happen, such as creating empty containers to hold data or resetting internal state. The params
object is passed from the declaration of the extension in the trial object. You can use params
to customize the behavior of the extension for each trial.
//... experiment code ...//\nlet trial = {\n type: htmlKeyboardResponse,\n stimulus: \"You're awesome!\",\n extensions: [\n {type: myAwesomeExtension, params: {demo: 'value'}}\n ]\n});\n\n//... extension code ...//\nclass MyAwesomeExtension {\n\n initialize(params){ ... }\n\n on_start(params){\n console.log(params.demo); // outputs 'value' before the trial begins.\n }\n}\n
"},{"location":"developers/extension-development/#on_load","title":"on_load()","text":"on_load()
is called after the on_load
event for the plugin has completed, which is typically when the plugin has finished executing initial DOM-modifying code and has set up various event listeners. This is where the extension can begin actively interacting with the DOM and recording data. The params
object is passed from the declaration of the extension in the trial object. You can use params
to customize the behavior of the extension for each trial.
//... experiment code ...//\nlet trial = {\n type: htmlKeyboardResponse,\n stimulus: \"You're awesome!\",\n extensions: [\n {type: myAwesomeExtension, params: {demo: 'value'}}\n ]\n});\n\n//... extension code ...//\nclass MyAwesomeExtension {\n\n initialize(params){ ... }\n\n on_start(params){ ... }\n\n on_load(params){\n // replaces the contents of the display with 'value';\n this.jsPsych.getDisplayElement().innerHTML = params.demo;\n }\n}\n
"},{"location":"developers/extension-development/#on_finish","title":"on_finish()","text":"on_finish()
is called after the plugin invokes jsPsych.finishTrial()
. This can be used for any teardown at the end of the trial. This method should return an object of data to append to the plugin's data. Note that this event fires before the on_finish
event for the plugin, so data added by the extension is accessible in any trial on_finish
event handlers. The params
object is passed from the declaration of the extension in the trial object. You can use params
to customize the behavior of the extension for each trial.
//... experiment code ...//\nlet trial = {\n type: htmlKeyboardResponse,\n stimulus: \"You're awesome!\",\n extensions: [\n {type: myAwesomeExtension, params: {demo: 'value'}}\n ],\n on_finish: (data) => {\n console.log(data.awesome); // will output 'value'.\n }\n});\n\n//... extension code ...//\nclass MyAwesomeExtension {\n\n initialize(params){ ... }\n\n on_start(params){ ... }\n\n on_load(params){ ... }\n\n on_finish(params){\n return {\n awesome: params.value\n }\n }\n}\n
"},{"location":"developers/extension-development/#static-info","title":"static .info","text":"The info
property for the class must contain an object with a name
property that has a unique name for the extension, a version
property that has the version string, and a data
parameter that includes information about the data
generated by the extension.
import { version } from '../package.json';\n\nclass MyAwesomeExtension {\n\n}\n\nMyAwesomeExtension.info = {\n name: 'awesome',\n version: version, // Should be hardcoded as `version: \"1.0.1\"` if not using build tools.\n data: {\n /** This will be scraped as metadata describing tracking_data and used to create the JsPsych docs */\n tracking_data: {\n type: ParameterType.STRING,\n }\n }\n}\n
The version
field describes the version of the extension used and then durin the experiment will be part of the generated data. This is used generate metadata and help maintain the Psych-DS standard. It should imported from the package.json file by including an import statement in the top of the index.ts file. This allows the version
field be automatically updated with each changeset. If you are not using a build environment and instead writing a plain JS file, you can manually enter the version
as a string as done in the comment.
The data
field is an object containing all of the data
generated for the plugin. Each 'data' object has a type
and default
property. Additionally, this should be only used for data you choose to generate. Any jsdoc (comments included in the /* / tags) you include will be scraped as metadata if you are choosing to generate metadata. This scraped metadata will also be used to create the JsPsych documentation.
"},{"location":"developers/extension-development/#optional-methods","title":"Optional methods","text":"The extension can also include any additional methods that are necessary for interacting with it. See the webgazer extension for an example.
"},{"location":"developers/extension-development/#advice-for-writing-extensions","title":"Advice for writing extensions","text":"If you are developing an extension with the aim of including it in the main jsPsych repository we encourage you to follow the contribution guidelines.
In general, extensions should be able to work with any plugin. They should make very few assumptions about what the DOM will contain beyond the container elements generated by jsPsych. If you are making an extension targeted at one or a small number of specific plugins, consider modifying the plugin code instead.
"},{"location":"developers/plugin-development/","title":"Plugin development","text":""},{"location":"developers/plugin-development/#requirements-for-a-plugin","title":"Requirements for a plugin","text":"As of version 7.0, plugins are JavaScript Classes. A plugin must implement:
- A
constructor()
that accepts an instance of jsPsych. - A
trial()
method that accepts an HTMLElement
as its first argument and an object
of trial parameters as its second argument. There is an optional third argument to handle the on_load
event in certain cirumstances. The trial()
method should either invoke jsPsych.finishTrial()
or should be an async
function that returns a data object to end the trial and save data. - A static
info
property on the class that contains an object describing the plugin's parameters, data generated, and version.
"},{"location":"developers/plugin-development/#plugin-templates","title":"Plugin templates","text":"Templates for plugins are available in the jspsych-contrib repository. Plugins can be written in either plain JavaScript or in TypeScript.
To get started with a template, we recommend using the CLI tool that we have published in jspsych-contrib. This automates the setup of a new plugin in either JavaScript or TypeScript. Additional information about the CLI tool is available in the README
of jspsych-contrib.
"},{"location":"developers/plugin-development/#plugin-components","title":"Plugin components","text":""},{"location":"developers/plugin-development/#constructor","title":"constructor()","text":"The plugin's constructor()
will be passed a reference to the instance of the JsPsych
class that is running the experiment. The constructor should store this reference so that the plugin can access functionality from the core library and its modules.
constructor(jsPsych){\n this.jsPsych = jsPsych;\n}\n
"},{"location":"developers/plugin-development/#trial","title":"trial()","text":"The plugin's trial()
method is responsible for running a single trial. When the jsPsych timeline reaches a trial using the plugin it will invoke the trial()
method for the plugin.
There are three parameters that are passed into the trial method.
display_element
is the DOM element where jsPsych content is being rendered. This parameter will be an HTMLElement
, and you can use it to modify the portion of the document that jsPsych controls. trial
is an object containing all of the parameters specified in the corresponding TimelineNode. on_load
is an optional parameter that contains a callback function to invoke when trial()
has completed its initial loading. See handling the on_load event.
The only requirement for the trial
method is that it calls jsPsych.finishTrial()
when it is done. This is how jsPsych knows to advance to the next trial in the experiment (or end the experiment if it is the last trial). The plugin can do whatever it needs to do before that point.
"},{"location":"developers/plugin-development/#static-info","title":"static info","text":"The plugin's info
property is an object with a name
, version
, parameters
, and data
property.
const info = {\n name: 'my-awesome-plugin',\n version: version,\n parameters: { },\n data: { }\n}\n
The version
field describes the version of the plugin. The version will be automatically included in the data generated by the plugin. In most cases, the version should imported from the package.json
file by including an import statement at the top of the file. This allows the version
field be automatically updated.
import { version } from '../package.json';\n\nconst info = {\n ...\n version: version;\n ...\n}\n
If you are not using a build environment that supports import
and package.json
(such as writing a plain JS file), you can manually enter the version
as a string.
const info = {\n ...\n version: \"1.0.0\";\n ...\n}\n
The parameters
property is an object containing all of the parameters for the plugin. Each parameter has a type
and default
property.
The data
field describes the types of data generated by the plugin. Each parameter has a type
property.
const info = {\n name: 'my-awesome-plugin',\n version: version,\n parameters: { \n image: {\n type: ParameterType.IMAGE,\n default: undefined\n },\n image_duration: {\n type: ParameterType.INT,\n default: 500\n }\n },\n data: {\n response: {\n type: ParameterType.STRING,\n },\n },\n}\n
If the default
value is undefined
then a user must specify a value for this parameter when creating a trial using the plugin on the timeline. If they do not, then an error will be generated and shown in the console. If a default
value is specified in info
then that value will be used by the plugin unless the user overrides it by specifying that property.
jsPsych allows most plugin parameters to be dynamic, which means that the parameter value can be a function that will be evaluated right before the trial starts. However, if you want your plugin to have a parameter that is a function that shouldn't be evaluated before the trial starts, then you should make sure that the parameter type is 'FUNCTION'
. This tells jsPsych not to evaluate the function as it normally does for dynamic parameters. See the canvas-*
plugins for examples.
We strongly encourage using JSDoc comments to document the parameters and data generated by the plugin, as shown below. We use these comments to automatically generate documentation for the plugins and to generate default descriptions of variables for experiment metadata.
const info = {\n name: 'my-awesome-plugin',\n version: version,\n parameters: { \n /** The path to the image file to display. */\n image: {\n type: ParameterType.IMAGE,\n default: undefined\n },\n /** The duration to display the image in milliseconds. */\n image_duration: {\n type: ParameterType.INT,\n default: 500\n }\n },\n data: {\n /** The text of the response generated by the participant. */\n response: {\n type: ParameterType.STRING,\n },\n },\n}\n
The info
object must be a static
member of the class, as shown below.
const info = {\n name: 'my-awesome-plugin',\n version: version,\n parameters: { \n /** The path to the image file to display. */\n image: {\n type: ParameterType.IMAGE,\n default: undefined\n },\n /** The duration to display the image in milliseconds. */\n image_duration: {\n type: ParameterType.INT,\n default: 500\n }\n },\n data: {\n /** The text of the response generated by the participant. */\n response: {\n type: ParameterType.STRING,\n },\n },\n}\n\nclass MyAwesomePlugin {\n constructor(...)\n\n trial(...)\n}\n\nMyAwesomePlugin.info = info;\n
"},{"location":"developers/plugin-development/#plugin-functionality","title":"Plugin functionality","text":"Inside the .trial()
method you can do pretty much anything that you want, including modifying the DOM, setting up event listeners, and making asynchronous requests. In this section we'll highlight a few common things that you might want to do as examples.
"},{"location":"developers/plugin-development/#changing-the-content-of-the-display","title":"Changing the content of the display","text":"There are a few ways to change the content of the display. The display_element
parameter of the trial method contains the HTMLElement
for displaying jsPsych content, so you can use various JavaScript methods for interaction with the display element. A common one is to change the innerHTML
. Here's an example of using innerHTML
to display an image specified in the trial
parameters.
trial(display_element, trial){\n let html_content = `<img src=\"${trial.image}\"></img>`;\n\n display_element.innerHTML = html_content;\n}\n
"},{"location":"developers/plugin-development/#waiting-for-specified-durations","title":"Waiting for specified durations","text":"If you need to delay code execution for a fixed amount of time, we recommend using jsPsych's wrapper of the setTimeout()
function, jsPsych.pluginAPI.setTimeout()
. Any timeouts that are created using jsPsych's setTimeout()
will be automatically cleared when the trial ends, which prevents one plugin from interfering with the timing of another plugin.
In future versions we may replace the implementation of jsPsych.pluginAPI.setTimeout()
with improved timing functionality based on requestAnimationFrame
.
trial(display_element, trial){\n // show image\n display_element.innerHTML = `<img src=\"${trial.image}\"></img>`;\n\n // hide image after trial.image_duration milliseconds\n this.jsPsych.pluginAPI.setTimeout(()=>{\n display_element.innerHTML = '';\n }, trial.image_duration);\n}\n
"},{"location":"developers/plugin-development/#responding-to-keyboard-events","title":"Responding to keyboard events","text":"While the plugin framework allows you to set up any events that you would like to, including normal handling of keyup
or keydown
events, the jsPsych.pluginAPI
module contains the getKeyboardResponse
function, which implements some additional helpful functionality for key responses in an experiment.
Here's a basic example. See the getKeyboardResponse
docs for additional examples.
trial(display_element, trial){\n // show image\n display_element.innerHTML = `<img src=\"${trial.image}\"></img>`;\n\n const after_key_response = (info) => {\n // hide the image\n display_element.innerHTML = '';\n\n // record the response time as data\n let data = {\n rt: info.rt\n }\n\n // end the trial\n this.jsPsych.finishTrial(data);\n }\n\n // set up a keyboard event to respond only to the spacebar\n this.jsPsych.pluginAPI.getKeyboardResponse({\n callback_function: after_key_response,\n valid_responses: [' '],\n persist: false\n });\n}\n
"},{"location":"developers/plugin-development/#asynchronous-loading","title":"Asynchronous loading","text":"One of the trial events is on_load
, which is normally triggered automatically when the .trial()
method returns. In most cases, this return happens after the plugin has done its initial setup of the DOM (e.g., rendering an image, setting up event listeners and timers, etc.). However, in some cases a plugin may implement an asynchronous operation that needs to complete before the initial loading of the plugin is considered done. An example of this is the audio-keyboard-response
plugin, in which the check to see if the audio file is loaded is asynchronous and the .trial()
method returns before the audio file has been initialized and the display updated.
If you would like to manually trigger the on_load
event for a plugin, the .trial()
method accepts an optional third parameter that is a callback function to invoke when loading is complete.
In order to tell jsPsych to not invoke the regular callback when the .trial()
method returns, you need to explicitly return a Promise
. As of version 8.0
, we recommend making the trial
function an async
function to handle this.
Here's a sketch of how the on_load
event can be utilized in a plugin. Note that this example is only a sketch and leaves out all the stuff that happens between loading and finishing the trial. See the source for the audio-keyboard-response
plugin for a complete exampe.
async trial(display_element, trial, on_load){\n let trial_complete;\n\n await do_something_asynchronous()\n\n on_load();\n\n await do_the_rest_of_the_trial();\n\n return data_generated_by_the_trial;\n}\n
"},{"location":"developers/plugin-development/#save-data","title":"Save data","text":"To write data to jsPsych's data collection pass an object of data as the parameter to jsPsych.finishTrial()
.
constructor(jsPsych){\n this.jsPsych = jsPsych;\n}\n\ntrial(display_element, trial){\n let data = {\n correct: true,\n rt: 350\n }\n\n this.jsPsych.finishTrial(data);\n}\n
As of version 8.0
you may also return the data object from the trial()
method when the method is an async
function. This is equivalent to calling jsPsych.finishTrial(data)
.
constructor(jsPsych){\n this.jsPsych = jsPsych;\n}\n\nasync trial(display_element, trial){\n\n let data = {\n correct: true,\n rt: 350\n }\n\n return data;\n}\n
The data recorded will be that correct
is true
and that rt
is 350
. Additional data for the trial will also be collected automatically.
"},{"location":"developers/plugin-development/#when-a-plugin-finishes","title":"When a plugin finishes","text":"When a plugin finishes, it should call jsPsych.finishTrial()
or return a data object if the trial()
method is an async
function. This is how jsPsych knows to advance to the next trial in the experiment (or end the experiment if it is the last trial).
As of version 8.0
, ending the trial will automatically clear the display element and automatically clear any timeouts that are still pending.
"},{"location":"developers/plugin-development/#simulation-mode","title":"Simulation mode","text":"Plugins can optionally support simulation modes.
To add simulation support, a plugin needs a simulate()
function that accepts four arguments
simulate(trial, simulation_mode, simulation_options, load_callback)
trial
: This is the same as the trial
parameter passed to the plugin's trial()
method. It contains an object of the parameters for the trial. simulation_mode
: A string, either \"data-only\"
or \"visual\"
. This specifies which simulation mode is being requested. Plugins can optionally support \"visual\"
mode. If \"visual\"
mode is not supported, the plugin should default to \"data-only\"
mode when \"visual\"
mode is requested. simulation_options
: An object of simulation-specific options. load_callback
: A function handle to invoke when the simulation is ready to trigger the on_load
event for the trial. It is important to invoke this at the correct time during the simulation so that any on_load
events in the experiment execute as expected.
Typically the flow for supporting simulation mode involves:
- Generating artificial data that is consistent with the
trial
parameters. - Merging that data with any data specified by the user in
simulation_options
. - Verifying that the final data object is still consistent with the
trial
parameters. For example, checking that RTs are not longer than the duration of the trial. - In
data-only
mode, call jsPsych.finishTrial()
with the artificial data. - In
visual
mode, invoke the trial()
method of the plugin and then use the artificial data to trigger the appropriate events. There are a variety of methods in the Plugin API module to assist with things like simulating key presses and mouse clicks.
We plan to add a longer guide about simulation development in the future. For now, we recommend browsing the source code of plugins that support simulation mode to see how the flow described above is implemented.
"},{"location":"developers/plugin-development/#advice-for-writing-plugins","title":"Advice for writing plugins","text":"If you are developing a plugin with the aim of including it in the main jsPsych repository we encourage you to follow the contribution guidelines.
We also recommend that you make your plugin as general as possible. Consider using parameters to give the user of the plugin as many options for customization as possible. For example, if you have any text that displays in the plugin including things like button labels, implement the text as a parameter. This allows users running experiments in other languages to replace text values as needed.
"},{"location":"extensions/list-of-extensions/","title":"List of Plugins","text":"These are the extensions that are included in the jsPsych release.
Additional extensions may be available in the community contributions repository.
For an overview of what extensions are and how they work, see our extensions overview.
Extension Description mouse\u2011tracking Enables tracking of mouse events and recording location of objects on screen. record\u2011video Record video data from the participant's webcam during a trial. webgazer Enables eye tracking using the WebGazer library."},{"location":"extensions/mouse-tracking/","title":"mouse-tracking","text":"This extension supports mouse tracking. Specifically, it can record the x
and y
coordinates, along with the time of mousemove events, mousedown events, and mouseup events. It also allows recording of the bounding rectangle of elements on the screen to support the calculation of mouse events relative to different elements.
"},{"location":"extensions/mouse-tracking/#parameters","title":"Parameters","text":""},{"location":"extensions/mouse-tracking/#initialization-parameters","title":"Initialization Parameters","text":"Initialization parameters can be set when calling initJsPsych()
initJsPsych({\n extensions: [\n {type: jsPsychExtensionMouseTracking, params: {...}}\n ]\n})\n
Parameter Type Default Value Description minimum_sample_time number 0 The minimum time between samples for mousemove
events in milliseconds. If mousemove
events occur more rapidly than this limit, they will not be recorded. Use this if you want to keep the data files smaller and don't need high resolution tracking data. The default value of 0 means that all events will be recorded."},{"location":"extensions/mouse-tracking/#trial-parameters","title":"Trial Parameters","text":"Trial parameters can be set when adding the extension to a trial object.
var trial = {\n type: jsPsych...,\n extensions: [\n {type: jsPsychExtensionMouseTracking, params: {...}}\n ]\n}\n
Parameter Type Default Value Description targets array [] A list of elements on the page that you would like to record the coordinates of for comparison with the mouse tracking data. Each entry in the array should be a valid CSS selector string that identifies the element. The selector string should be valid for exactly one element on the page. If the selector is valid for more than one element then only the first matching element will be recorded. events array ['mousemove'] A list of events to track. Can include 'mousemove', 'mousedown', and 'mouseup'."},{"location":"extensions/mouse-tracking/#data-generated","title":"Data Generated","text":"Name Type Value mouse_tracking_data array An array of objects containing mouse movement data for the trial. Each object has an x
, a y
, a t
, and an event
property. The x
and y
properties specify the mouse coordinates in pixels relative to the top left corner of the viewport and t
specifies the time in milliseconds since the start of the trial. The event
will be either 'mousemove', 'mousedown', or 'mouseup' depending on which event was generated. mouse_tracking_targets object An object contain the pixel coordinates of elements on the screen specified by the .targets
parameter. Each key in this object will be a selector
property, containing the CSS selector string used to find the element. The object corresponding to each key will contain x
and y
properties specifying the top-left corner of the object, width
and height
values, plus top
, bottom
, left
, and right
parameters which specify the bounding rectangle of the element."},{"location":"extensions/mouse-tracking/#examples","title":"Examples","text":"Record mouse movement data and play it back CodeDemo var trial = {\n type: jsPsychHtmlButtonResponse,\n stimulus: '<div id=\"target\" style=\"width:250px; height: 250px; background-color: #333; margin: auto;\"></div>',\n choices: ['Done'],\n prompt: \"<p>Move your mouse around inside the square.</p>\",\n extensions: [\n {type: jsPsychExtensionMouseTracking, params: {targets: ['#target']}}\n ],\n data: {\n task: 'draw'\n }\n};\n\nvar replay = {\n type: jsPsychHtmlButtonResponse,\n stimulus: '<div id=\"target\" style=\"width:250px; height: 250px; background-color: #333; margin: auto; position: relative;\"></div>',\n choices: ['Done'],\n prompt: \"<p>Here's the recording of your mouse movements</p>\",\n on_load: function(){\n var mouseMovements = jsPsych.data.get().last(1).values()[0].mouse_tracking_data;\n var targetRect = jsPsych.data.get().last(1).values()[0].mouse_tracking_targets['#target'];\n\n var startTime = performance.now();\n\n function draw_frame() {\n var timeElapsed = performance.now() - startTime;\n var points = mouseMovements.filter((x) => x.t <= timeElapsed);\n var html = ``;\n for(var p of points){\n html += `<div style=\"width: 3px; height: 3px; background-color: blue; position: absolute; top: ${p.y - 1 - targetRect.top}px; left: ${p.x - 1 - targetRect.left}px;\"></div>`\n }\n document.querySelector('#target').innerHTML = html;\n if(points.length < mouseMovements.length) {\n requestAnimationFrame(draw_frame);\n }\n }\n\n requestAnimationFrame(draw_frame);\n\n },\n data: {\n task: 'replay'\n }\n}\n
Open demo in new tab
"},{"location":"extensions/record-video/","title":"record-video","text":"This extension records video from the participant's webcam during a trial.
This extension encodes the video data in base 64 format. This is a text-based representation of the video which can be coverted to various video formats using a variety of online tools as well as in languages like python and R.
"},{"location":"extensions/record-video/#parameters","title":"Parameters","text":""},{"location":"extensions/record-video/#initialization-parameters","title":"Initialization Parameters","text":"Initialization parameters can be set when calling initJsPsych()
initJsPsych({\n extensions: [\n {type: jsPsychExtensionRecordVideo, params: {...}}\n ]\n})\n
Parameter Type Default Value Description None"},{"location":"extensions/record-video/#trial-parameters","title":"Trial Parameters","text":"Trial parameters can be set when adding the extension to a trial object.
var trial = {\n type: jsPsych...,\n extensions: [\n {type: jsPsychExtensionRecordVideo, params: {...}}\n ]\n}\n
Parameter Type Default Value Description None"},{"location":"extensions/record-video/#data-generated","title":"Data Generated","text":"Name Type Value record_video_data base64 string Base 64 encoded representation of the video data."},{"location":"extensions/record-video/#examples","title":"Examples","text":"Record video data during a trial CodeDemo const init_camera = {\n type: jsPsychInitializeCamera\n};\n\nconst trial = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `<div id=\"target\" style=\"width:250px; height: 250px; background-color: #333; position: relative; margin: 2em auto;\">\n <div class=\"orbit\" style=\"width:25px; height:25px; border-radius:25px;background-color: #f00; position: absolute; top:calc(50% - 12px); left:calc(50% - 12px);\"></div>\n </div>\n <style>\n .orbit {\n transform: translateX(100px);\n animation: orbit 4s infinite;\n }\n @keyframes orbit {\n 0% {\n transform: rotate(0deg) translateX(100px);\n }\n 100% {\n transform: rotate(360deg) translateX(100px);\n }\n }\n </style>`,\n choices: ['Done'],\n prompt: \"<p>Video is recording. Click done after a few seconds.</p>\",\n extensions: [\n {type: jsPsychExtensionRecordVideo}\n ]\n};\n
Open demo in new tab
"},{"location":"extensions/webgazer/","title":"webgazer","text":"This extension supports eye tracking through the WebGazer library. For a narrative description of how to use this extension see the eye tracking overview.
"},{"location":"extensions/webgazer/#parameters","title":"Parameters","text":""},{"location":"extensions/webgazer/#initialization-parameters","title":"Initialization Parameters","text":"Initialization parameters can be set when calling initJsPsych()
initJsPsych({\n extensions: [\n {type: jsPsychExtensionWebgazer, params: {...}}\n ]\n})\n
Parameter Type Default Value Description webgazer object undefined
You can explicitly pass a reference to a loaded instance of the webgazer.js library. If no explicit reference is passed then the extension will look for a global webgazer
object. If you are loading webgazer.js via a <script>
tag you do not need to set this parameter in most circumstances. auto_initialize bool false Whether to automatically initialize webgazer when the experiment begins. If set to true
then the experiment will attempt to access the user's webcam immediately upon page load. The default value is false
because it is probably a good idea to explain to the user why camera permission will be needed before asking for it. The webgazer-init-camera
plugin can be used to initialize the camera during the experiment. round_predictions bool true Whether to round the x
,y
coordinates predicted by WebGazer to the nearest whole number. This greatly reduces the size of the data, as WebGazer records data to 15 decimal places by default. Given the noise of the system, there's really no need to record data to this level of precision. sampling_interval numeric 34 Sets the interval between gaze predictions. Because the underlying code is partially asynchronous, this interval is only approximate. The sampling interval will not be faster than this, on average, but the time between samples may fluctuate. Setting the interval too fast will create performance problems and produce redundant data, as the video feed from most webcams only updates about 30 times per second."},{"location":"extensions/webgazer/#trial-parameters","title":"Trial Parameters","text":"Trial parameters can be set when adding the extension to a trial object.
var trial = {\n type: jsPsych...,\n extensions: [\n {type: jsPsychExtensionWebgazer, params: {...}}\n ]\n}\n
Parameter Type Default Value Description targets array [] A list of elements on the page that you would like to record the coordinates of for comparison with the WebGazer data. Each entry in the array should be a valid CSS selector string that identifies the element. The selector string should be valid for exactly one element on the page. If the selector is valid for more than one element then only the first matching element will be recorded."},{"location":"extensions/webgazer/#data-generated","title":"Data Generated","text":"Name Type Value webgazer_data array An array of objects containing gaze data for the trial. Each object has an x
, a y
, and a t
property. The x
and y
properties specify the gaze location in pixels and t
specifies the time in milliseconds since the start of the trial. webgazer_targets object An object contain the pixel coordinates of elements on the screen specified by the .targets
parameter. Each key in this object will be a selector
property, containing the CSS selector string used to find the element. The object corresponding to each key will contain x
and y
properties specifying the top-left corner of the object, width
and height
values, plus top
, bottom
, left
, and right
parameters which specify the bounding rectangle of the element."},{"location":"extensions/webgazer/#functions","title":"Functions","text":"In addition to the jsPsych webgazer-* plugins, the jsPsych webgazer extension provides a set of functions that allow the researcher to interact more directly with WebGazer. These functions can be called at any point during an experiment, and are crucial for building trial plugins that interact with WebGazer. All of the functions below must be prefixed with jsPsych.extensions.webgazer
(e.g. jsPsych.extensions.webgazer.faceDetected()
).
"},{"location":"extensions/webgazer/#start","title":"start()","text":"Performs initialization of webgazer, including requesting permissions from the user to access the camera. Returns a Promise
that resolves when the camera is initialized and fails if the camera cannot be accessed, e.g., because the user denies permission. This is handled automatically if using the webgazer-init-camera
plugin or setting auto_initialize
to true
in the extension parameters.
"},{"location":"extensions/webgazer/#isinitialized","title":"isInitialized()","text":"Returns true
if start()
has been successfully called at some point, and false
otherwise.
"},{"location":"extensions/webgazer/#facedetected","title":"faceDetected()","text":"Returns true
if WebGazer is ready to make predictions (webgazer.getTracker().predictionReady
is true
).
"},{"location":"extensions/webgazer/#showpredictions","title":"showPredictions()","text":"Turns on WebGazer's real-time visualization of predicted gaze location.
"},{"location":"extensions/webgazer/#hidepredictions","title":"hidePredictions()","text":"Turns off WebGazer's real-time visualization of predicted gaze location.
"},{"location":"extensions/webgazer/#showvideo","title":"showVideo()","text":"Turns on a display of the webcam image, guiding box for positioning the face, and WebGazer's estimate of the location of facial landmarks.
"},{"location":"extensions/webgazer/#hidevideo","title":"hideVideo()","text":"Turns off the camera display.
"},{"location":"extensions/webgazer/#resume","title":"resume()","text":"Turns on gaze prediction. The extension will automatically handle this for you in most cases. You probably only need to use this if you are writing your own plugin that interfaces directly with WebGazer.
"},{"location":"extensions/webgazer/#pause","title":"pause()","text":"Turns off gaze prediction. The extension will automatically handle this for you in most cases. You probably only need to use this if you are writing your own plugin that interfaces directly with WebGazer.
"},{"location":"extensions/webgazer/#resetcalibration","title":"resetCalibration()","text":"Clears all calibration data.
"},{"location":"extensions/webgazer/#startmousecalibration","title":"startMouseCalibration()","text":"Turns on mouse movement and mouse clicks as calibration events. While the webgazer-calibration
plugin can also be used to run a parmeterized calibration routine, this calibration function call allows you to continuously calibrate WebGazer to any mouse movements or clicks throughout the experiment. For example, any *-button-response trial would also function as a WebGazer calibration event.
"},{"location":"extensions/webgazer/#stopmousecalibration","title":"stopMouseCalibration()","text":"Stops WebGazer from using mouse movements and mouse clicks as calibration events.
"},{"location":"extensions/webgazer/#calibratepointx-y","title":"calibratePoint(x, y)","text":"Instructs WebGazer to register the location x
, y
(in screen pixel coordinates) as a calibration event. Can be used for passive viewing calibration, i.e., instructing participants to fixate at a particular location.
"},{"location":"extensions/webgazer/#setregressiontyperegression_type","title":"setRegressionType(regression_type)","text":"Change the method that WebGazer is using to perform feature -> location regression. Valid options are ridge
, weightedRidge
, and threadedRidge
. See the WebGazer docs for more information about these options. The extension uses the default mode specified by WebGazer (currently ridge
).
"},{"location":"extensions/webgazer/#getcurrentprediction","title":"getCurrentPrediction()","text":"Get the current predicted gaze location from WebGazer. This returns a Promise that resolves once WebGazer has finished computing the gaze prediction. The Promise has a single parameter with an object with x
, y
, and, t
parameters. t
will be the value of performance.now()
at approximately the time that the video frame was recorded.
"},{"location":"extensions/webgazer/#startsampleintervalinterval","title":"startSampleInterval(interval)","text":"Starts sampling gaze predictions every interval
milliseconds. If interval
is left undefined then the default value at extension initialization is used. Every sample will trigger an onGazeUpdate
callback, as well as side effects that result in data storage within the extension.
"},{"location":"extensions/webgazer/#stopsampleinterval","title":"stopSampleInterval()","text":"Stops the sampling started by startSampleInterval()
.
"},{"location":"extensions/webgazer/#ongazeupdatecallback","title":"onGazeUpdate(callback)","text":"Subscribe to gaze updates. The callback
will be invoked every time a new gaze prediction is generated. The first argument of the callback
will be an object with x
, y
, and, if currently in a trial with the extension turned on, the time t
in ms since the start of the trial. t
will be the value of performance.now()
at approximately the time that the video frame was recorded. If currently in an active trial then t
will be relative to the start of the trial.
This function returns a close handler. When you no longer need to subscribe to gaze updates, call the close handler. Example:
var cancelGazeUpdateHandler = jsPsych.extensions.webgazer.onGazeUpdate(function(prediction){\n console.log(`Currently looking at ${prediction.x}, ${prediction.y}`);\n});\n\ncancelGazeUpdateHandler();\n
You can add multiple handlers. Handlers are not closed automatically, so be sure to cancel them when no longer needed.
"},{"location":"newsletter/subscribe/","title":"Subscribe to our newsletter","text":"Subscribe to our newsletter to stay up to date with the latest news and updates from the jsPsych team. We send out newsletters about once a month. The newsletter includes information about new releases, upcoming events, community spotlights, and other news related to jsPsych. You can unsubscribe at any time.
Subscribe"},{"location":"overview/browser-device-support/","title":"Browser and Device Support","text":""},{"location":"overview/browser-device-support/#desktop-and-laptop-browsers","title":"Desktop and Laptop Browsers","text":"Supported
jsPsych supports recent versions of the four most commonly-used web browsers:
- Chrome
- Firefox
- Safari
- Edge
This means that jsPsych should work on these browsers. If something doesn't work as you expect on one of the browsers above, it might be a bug that should be fixed. You can search for and report bugs on the jsPsych GitHub Issues page. We're very grateful for anyone who takes the time to report bugs - it helps improve the library for everyone!
Unsupported
There are many other web browsers that are available, but that are not commonly used. The most well-known of these are Internet Explorer and Opera. jsPsych is not tested on these and other browsers not listed in the Supported section above. jsPsych experiments might work in these browsers, but they might not. If you want to give participants the option to use unsupported browsers, then we recommend carefully testing your experiment to make sure that everything works as expected. Otherwise, we suggest asking your participants to only use a supported browser, or incorporating browser, device, and/or feature checks at the start of your experiment. jsPsych offers built-in methods for exclusion based on minimum browser size and WebAudio API compatibility. You can incorporate other browser/device/feature checks into your experiment by adding custom JavaScript code.
"},{"location":"overview/browser-device-support/#mobile-devices","title":"Mobile Devices","text":"In general, jsPsych experiments can be run on mobile devices (smartphones and tablets). However, certain plugins will not work on mobile. For instance, any plugin that requires a keyboard response without a text input box, such as the *-keyboard-response plugins, will not work. Even plugins that do work on mobile might work differently than they do on desktop and laptop computers. For instance, on mobile devices, a text input box will cause an on-screen keyboard to pop up, which affects the visible content on the screen.
If you plan to run an experiment that allows people to use mobile devices, we recommend doing some extra testing to make sure that everything works as expected. In particular, you may want to check that: * Font sizes are readable on smaller screens * Stimuli sizes are large enough and appropriate for the task * Page is laid out as intended (e.g. elements are centered and do not overlap) * Response options are touchscreen-friendly (e.g. buttons rather than key presses) * Response options (e.g. buttons, text boxes, radio buttons) are large enough and far enough apart to be easily selected with a finger tap
It's possible to use your browser's developer tools to emulate mobile devices (this page shows how to do it in Chrome), which is useful for getting a sense of how your experiment will look on mobile devices. Just be aware that there are limitations to emulator tools, and there are some aspects of mobile devices/browsers that a desktop browser will not be able to simulate.
"},{"location":"overview/browser-device-support/#mobile-browsers","title":"Mobile Browsers","text":"The browser options for mobile phones and tablets are slightly different than those for desktop and laptop computers. In addition to mobile versions of Chrome, Firefox, Safari, and Edge, other notable mobile browsers include Opera Mobile, Samsung Internet, UC Browser, and Dolphin. Because of the greater diversity of mobile browsers and volatility in their usage statistics, jsPsych does not officially support any particular set of mobile browsers. However, we do anticipate that most experiments should work in most mobile browsers, especially the mobile versions of browsers that we do support in Desktop mode. If you run into a problem using jsPsych in mobile browsers, please report it on the jsPsych GitHub Issues page! We do our best to fix browser incompatibilities that are not specific to a single experiment.
"},{"location":"overview/building-surveys/","title":"Building Surveys in jsPsych","text":""},{"location":"overview/building-surveys/#choosing-which-jspsych-survey-plugin-to-use","title":"Choosing which jsPsych survey plugin to use","text":"jsPsych has several plugins that allow you to present survey questions during your experiment. The one you choose will depend on what exactly you'd like to do, and your preferences for convenience/parameterization versus flexibility.
- Survey-* plugins:
survey-likert
, survey-multi-choice
, survey-multi-select
, survey-text
- Only one question type and one page per trial
- Parameterization makes it easy to define questions
- Work well with timeline variables
- Ideal for adding survey-style questions into repetitive trial procedures
- Limited functionality and customization options
survey-html-form
plugin - Can mix different question types on the same page
- No parameters for defining questions - you write the form HTML
- Maximally flexible, so ideal if you need a lot of control over the survey content and style
survey
plugin - Not well-suited for use with timeline variables
- Large set of built-in question types and parameterized customization options
- Can mix different question types on the same page
- Can present mutliple pages that participants can navigate back and forth through, without losing responses
- Parameters for defining questions, but more config/code than the
survey-*
plugins - Built-in convenience parameters for many survey question types and features (e.g. response validation, conditional question display, 'other'/'none'/'select all' options)
The survey
plugin differs from most other jsPsych plugins in that is a simple wrapper for an external JavaScript library called SurveyJS. This allows jsPsych users to take advantage of all of the SurveyJS features, documentation, and example code, but it also means that the survey
plugin does not follow the same familiar conventions as most other jsPsych plugins. Users will need to familiarize themselves somewhat with the SurveyJS library in order to use the plugin. The remaining documentation on this page provides some guidance for getting started with SurveyJS and the jsPsych survey
plugin.
"},{"location":"overview/building-surveys/#getting-started-with-surveyjs","title":"Getting started with SurveyJS","text":"The SurveyJS form library is a large and powerful survey-building framework with its own helpful documentation, examples, and demos. Here we have tried to orient jsPsych users to the basic steps for constructing surveys and highlight the features that jsPsych users may find most useful. However, it is not possible for us to reproduce the SurveyJS documentation here, so we encourage you to take advantage of their comprehensive documentation and demo/code examples.
SurveyJS allows you to build surveys using a JavaScript/JSON object, a JavaScript function, or a combination of both. You can read more about these options in the SurveyJS documentation:
- Define a survey in JSON
- Define a survey with JavaScript
The jsPsych survey
plugin provides the survey_json
and survey_function
parameters to allow you to construct a SurveyJS survey using these JSON and JavaScript methods. The next two sections on this page explain more about each method: Creating a survey with JSON and Using JavaScript to create or modify the survey.
Here are some other places to start learning about SurveyJS:
- Add multiple pages to a survey
- Configure conditional page visibility
- Page navigation UI (previous, next, and submit buttons)
- Add conditional logic and dynamic texts
- Set default values
SurveyJS has some more specific features that some researchers might find useful, including:
- Automatic question numbering (across the survey, within each page, and using custom values/characters)
- Response validation
- Table of contents and navigation across sections
- Progress bar
- Carry responses forward from a selection question
- Carry responses forward from a dynamic matrix/panel
- Conditional visibility for elements/questions (see also this example)
- Special choices for multi-choice-type questions: None, Other, Select All, Refuse to answer, and Don't know
- Localization (adapting the survey's language based on a country/region value)
- Text piping (dynamically insert text into questions/answers based on previous responses)
You can find realistic examples on the SurveyJS examples/demos page. And to view all of the survey-level options, see the Survey API documentation.
"},{"location":"overview/building-surveys/#creating-a-survey-with-json","title":"Creating a survey with JSON","text":"SurveyJS allows you to define the survey contents using an object with parameters names and values. At a minimum, the survey JSON object should contain a property called 'elements'. The value of 'elements' is an array that contains at least one element/question to be shown on the page.
// Survey with a single text entry question.\nconst survey_json = {\n elements: [{\n name: \"example\",\n title: \"Enter some text in the box below!\",\n type: \"text\"\n }]\n};\n
Each element is an object with a 'type', which is the element/question type (see the survey
plugin's Questions/Elements section for a list of type options). The element objects should also contain any other parameters and configuration options for that question, such as the question name (used to identify the question in the data), title (prompt shown to the participant), whether or not a response is required, and other parameters that might be relevant to that particular question type. The Questions/Elements section in the survey
plugin documentation contains links to the SurveyJS documentation for each question type, where you can find more information about the required and optional parameters.
Once you've created the survey JSON object, as we've done above, it can be used as the survey_json
parameter in a jsPsych survey
trial:
const survey_trial = {\n type: jsPsychSurvey,\n survey_json: survey_json\n};\n\ntimeline.push(survey_trial);\n
That's it! The code above will create a valid survey.
JSON vs JavaScript objects
JSON (JavaScript Object Notation) is a text format for organizing data. It is very similar to a JavaScript object, but not exactly the same. The survey_json
parameter takes a JSON-compatible JavaScript object, rather than a JSON string. We use the 'JSON' term for this parameter to make it clear that this parameter should not contain functions, and for consistency with SurveyJS documentation. To read more about JSON vs JavaScript objects, see e.g. here and here.
"},{"location":"overview/building-surveys/#multiple-pages","title":"Multiple pages","text":"You can specify 'elements' as a top-level property in the survey JSON, and those elements will be shown on a single page. If you'd like the survey to have more than one page, then you can add a 'pages' property to the survey JSON object. The value of 'pages' should be an array of objects, where each object defines a single page. Each page object should contain its own 'elements' array.
The example below defines a survey with two pages. Each page has a set of elements/questions, as well as some optional parameters (page name and title).
const survey_json = {\n pages: [\n {\n name: \"page_1\",\n title: \"Your Name\",\n elements: [{\n type: \"text\",\n name: \"first_name\",\n title: \"Enter your first name:\"\n }, {\n type: \"text\",\n name: \"last_name\",\n title: \"Enter your last name:\"\n }\n }, {\n name: \"page_2\",\n title: \"Personal Information\",\n elements: [{\n type: \"text\",\n name: \"location\",\n title: \"Where do you live?\"\n }, {\n type: \"text\",\n name: \"occupation\",\n title: \"What is your occupation?\"\n }, {\n type: \"text\",\n name: \"age\",\n title: \"How old are you?\",\n inputType: \"number\",\n min: 0,\n max: 120\n }\n }]\n};\n
"},{"location":"overview/building-surveys/#survey-level-options","title":"Survey-level options","text":"Along with either the 'elements' or 'pages' property, you can add optional survey-level properties to the top-level of your survey JSON object. The survey-level properties might include things like: a title (shown at the top of each page), whether to use automatic question numbering, labels for the page navigation buttons, and text to use for marking required questions. These and other survey-level parameters are not required - you only need to set these values if you want to change them from the defaults.
const survey_json = {\n title: \"Survey title\",\n showQuestionNumbers: \"off\",\n completeText: \"Done\",\n pageNextText: \"Next\",\n pagePrevText: \"Back\",\n requiredText: \"[REQUIRED]\",\n pages: [{\n elements: {\n // ... page 1 questions\n }\n }, {\n elements: {\n // ... page 2 questions\n }\n }]\n};\n
Some of the survey-level options can also be set a the page level. See the Page API documentation for more information.
For more survey JSON examples, see the SurveyJS JSON documentation, the Examples section on the survey
plugin documentation page, and the examples folder in the survey
plugin package.
"},{"location":"overview/building-surveys/#using-javascript-to-create-or-modify-the-survey","title":"Using JavaScript to create or modify the survey","text":"SurveyJS allows you to create or modify your survey using JavaScript. The JavaScript approach can do any of the configuration that can be done in JSON, plus it allows you to make your survey more dynamic. For instance, you could use the survey function parameter to change the contents of the survey based on the participant's earlier responses. The survey function parameter also allows you to define any other functions that should run during the survey. For instance, you might want to run custom code in response to a page change or response input event.
In the jsPsych survey
plugin, the survey_function
parameter receives a 'survey' argument, which is a SurveyJS survey model that you can manipulate. If you do not include a value for the survey_json
parameter, then the survey_function
will receive an empty survey. In this case, your survey_function
must add at least one page with at least one element/question to produce a valid survey.
Here's the JavaScript function that would create the same survey that's defined in the first JSON example above:
const survey_function = (survey) => {\n // add page\n const page = survey.addNewPage(\"page1\");\n // add question\n const text_question = page.addNewQuestion(\"text\", \"example\");\n text_question.title = \"Enter some text in the box below!\";\n};\n\nconst survey_trial = {\n type: jsPsychSurvey,\n survey_function: survey_function\n};\n\ntimeline.push(survey_trial);\n
"},{"location":"overview/building-surveys/#combining-json-and-function-parameters","title":"Combining JSON and function parameters","text":"If you specify survey JSON using the survey_json
parameter, then the survey_function
will receive a survey object that was created using your JSON. This means that, in your survey function, you can access all of the survey elements that you have defined in the JSON.
Here's a slightly more realistic case for when you might want to use the survey_function
parameter. In this example, we want to ask the participant to make a color choice at the start of the experiment, and then reference their choice in a later survey
trial question. We can't do this with the JSON configuration because we cannot know the participant's color choice in advance - it only becomes available during the experiment.
However, we can use the survey_function
to dynamically access the participant's color response from the jsPsych data and use that value in the survey question title. We'll use the survey_function
just for this one dynamic part of the survey, and define everything else in JSON.
// Create an array of color choices\nconst color_choices = ['red', 'green', 'blue', 'yellow', 'pink', 'orange', 'purple'];\n\n// Create an html-button-response trial where the participant can choose a color\nconst select_color_trial = {\n type: jsPsychHtmlButtonResponse,\n stimulus: '<p>Which of these is your favorite color?</p>',\n choices: color_choices,\n button_html: '<button class=\"jspsych-btn\" style=\"color:%choice%\";\">%choice%</button>',\n data: {trial_id: 'color_trial'}\n};\n\n// Create the survey JSON \nconst color_survey_json = {\n elements: [{\n type: \"boolean\",\n renderAs: \"radio\",\n name: \"color_confirmation\",\n title: \"\" // This value will be set in the survey function\n }]\n};\n\n// Create a survey function to access the participant's response \n// from an earlier trial and modify the survey accordingly\nconst color_survey_function = (survey) => {\n // Get the earlier color selection response (button index) from the jsPsych data\n const color_choice_index = jsPsych.data.get().filter({trial_id: 'color_trial'}).values()[0].response;\n const color_choice = color_choices[color_choice_index];\n // Get the question that we want to modify\n const color_confirmation_question = survey.getQuestionByName('color_confirmation');\n // Change the question title to include the name of the color that was selected\n color_confirmation_question.title = `\n Earlier you chose ${color_choice.toUpperCase()}. Do you still like that color?\n `;\n}\n\n// Create the jsPsych survey trial using both the survey JSON and survey function\nconst color_survey_trial = {\n type: jsPsychSurvey,\n survey_json: color_survey_json,\n survey_function: color_survey_function\n};\n\njsPsych.run([select_color_trial, color_survey_trial]);\n
For more information about creating/modifying surveys with JavaScript, see the SurveyJS documentation. The SurveyJS API reference contains all of the properties (parameters), methods, and events you can use when working with the survey, page, and question objects.
"},{"location":"overview/building-surveys/#deciding-between-json-and-function-parameters","title":"Deciding between JSON and function parameters","text":"You can create survey
trials entirely with JSON, entirely with a JavaScript function, or using a combination of both. Sometimes this is just a matter of preference. But you must use the JavaScript survey_function
method when you want to:
- Dynamically modify the survey based on a participant's response from an earlier trial, or any other information you don't have access to before the survey trial begins.
- Use custom functions as part of your survey's configuration. For instance, you might want to write a function that is triggered by a particular survey event, such as when response values change or when the survey is completed. You cannot put JavaScript functions into the
survey_json
object, so you will need to add them using the survey_function
parameter.
Custom response validation
There is a special case where you don't need to use the survey_function
parameter for running a custom function, which is for adding custom response validation. The survey
plugin includes a convenience parameter called validation_function
, which allows you to add some custom JavaScript code to validate responses. Of course, you can also use the survey_function
parameter for this, in which case you would set your custom function to run in response to the survey's onValidateQuestion
event.
"},{"location":"overview/building-surveys/#creating-dynamic-surveys-with-json","title":"Creating dynamic surveys with JSON","text":"Although you cannot include JavaScript functions as values in your survey_json
, SurveyJS has implemented some convenience options for setting up certain kinds of dynamic survey behavior from within the JSON configuration. For instance, you can define a condition expression from within the JSON that will dynamically show/hide a question or choice/column/row (see Conditional Visibility and Expressions). As another example, you can use a placeholder value inside a text string to insert the response from a particular question into that string (see Dynamic Texts: Question Values).
In general, you can access information in the survey JSON that exists within that same survey
trial and use it to produce dynamic behavior (e.g. putting placeholder values in text strings, automatically populating choice values, etc.). But if you need to access information that becomes available during the experiment but outside of that particular survey
trial, you will need to use the survey_function
parameter.
"},{"location":"overview/building-surveys/#defining-survey-trialsquestions-programmatically","title":"Defining survey trials/questions programmatically","text":"Sometimes it's useful to be able to create your survey content programmatically. For instance, let's say you want to present a page with questions that all use the exact same format but with different prompts. You could define them one-by-one in a survey_json
object, but doing it this way might produce a very large JSON object with lots of repeated configuration across all questions.
Instead, it's often preferrable to separate the information that changes across questions from the things that stay the same. This can make it easier to make changes and prevent errors, since the things that are common across questions only need to be defined once. Similarly, if you are repeating a trial procedure lots of times, then you might want to define a single survey
trial that repeats with slightly different parameters.
The following section presents some different options for programmatically defining multiple questions in a survey trial, or multiple survey trials, based on an array of values that should change across questions or trials.
The example below shows how to use the survey_function
to loop over a set of question-level variables (titles/prompts and names), and dynamically add each question to a single survey page. You could use this same approach to add questions across multiple pages within the same survey trial.
const survey_function = (survey) => {\n\n // this array stores any information that changes across questions\n const questions = [\n {title: \"Question 1\", name: \"q1\"},\n {title: \"Question 2\", name: \"q2\"},\n // ... more question-level variables ...\n {title: \"Question N\", name: \"qN\"}\n ];\n\n // create a single page\n const page = survey.addNewPage(\"questions\");\n\n for (let i=0; i<questions.length; i++) {\n // for each object in the questions array,\n // create a new question and add it to the same page\n let q = page.addNewQuestion(\"text\", questions[i].name, i);\n q.title = questions[i].title;\n q.inputType = \"range\";\n q.min = 0;\n q.max = 100;\n q.step = 10;\n q.defaultValue = 50;\n q.isRequired = true;\n }\n\n}\n
Use the 'matrix' question type for repeated response options
The example above was used to illustrate how you can loop over information to programmatically construct a series of questions that are shown on the same page. But in cases where you have different question prompts that all use the same multiple choice options, you might prefer to use the the SurveyJS \"matrix\" question type. This question type creates a table where each row is a question and each column is a response option. The table format is often used for Likert scales, satisfaction surveys, etc. You can even create a table that repeats a set of questions with different response types using the SurveyJS multi-select matrix (\"matrixdropdown\") question type.
Rather than repeating a question format within the same trial, perhaps you want to use trial-level variables to generate separate survey
trials, for instance in order to incorporate them into a larger repeating trial procedure. jsPsych's timeline variables feature was designed to address this use case, but the use of timeline variables looks a little different with the survey
plugin. This is because the various individual parameters that you might want to change across survey
trials don't have their own plugin parameters - instead everything is nested within the survey_json
parameter. Below are some examples showing how you can programmatically generate survey trials using a set of trial-level variables.
-
Use the conventional timeline variables approach with the survey_json
parameter. This approach is probably not ideal, because the timeline variables array has to contain the entire survey_json
object for each trial. This kind of defeats the purpose of timeline variables, because you are still defining all of the survey JSON separately for each question/trial. In any case, here's what it looks like:
const word_trials = {\n timeline: [\n {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '+',\n choices: \"NO_KEYS\",\n trial_duration: 500\n },\n {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: jsPsych.timelineVariable('word'),\n choices: \"NO_KEYS\",\n trial_duration: 1000\n },\n {\n type: jsPsychSurvey,\n survey_json: jsPsych.timelineVariable('survey_json'),\n data: { word: jsPsych.timelineVariable('word') }\n }\n ],\n timeline_variables: [\n {\n word: 'cheese',\n survey_json: { elements: [ {type: \"text\", title: \"Enter a word related to CHEESE:\", autocomplete: \"off\" } ], showQuestionNumbers: false, completeText: \"Next\", focusFirstQuestionAutomatic: true } \n },\n {\n word: 'ring',\n survey_json: { elements: [ {type: \"text\", title: \"Enter a word related to RING:\", autocomplete: \"off\" } ], showQuestionNumbers: false, completeText: \"Next\", focusFirstQuestionAutomatic: true } \n },\n {\n word: 'bat',\n survey_json: { elements: [ {type: \"text\", title: \"Enter a word related to BAT:\", autocomplete: \"off\" } ], showQuestionNumbers: false, completeText: \"Next\", focusFirstQuestionAutomatic: true }\n },\n {\n word: 'cow',\n survey_json: { elements: [ {type: \"text\", title: \"Enter a word related to COW:\", autocomplete: \"off\" } ], showQuestionNumbers: false, completeText: \"Next\", focusFirstQuestionAutomatic: true }\n }\n ]\n};\n
Consider using a survey-* plugin for presenting a single question type
The example above was created just to demonstrate how to combine the survey
plugin and timeline variables. But if this were a real experiment, since each survey trial contains just one question, we'd be better off using one of the other survey-* plugins because the parameterization of those plugins works well with timeline variables. Of course, you may have other reasons for wanting to use the survey
plugin in this type of trial procedure, for instance to take advantage of some its convenience features (e.g. different question types on the same page, response validation).
-
Use jsPsych's functions-as-parameters approach for the survey_json
parameter. With this approach, instead of defining a static JSON object for the value of survey_json
, you would write a function that returns the survey JSON object for that specific trial.
This approach allows you to define the survey content using a combination of variable and static values. Also, jsPsych will run this function right before the trial begins, which means that you can change the survey content dynamically based on information that only becomes available during the experiment. Here's an example using timeline variables, though you can use the same approach to dynamically create the survey content without using timeline variables.
const word_trials = {\n timeline: [\n {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '+',\n choices: \"NO_KEYS\",\n trial_duration: 500\n },\n {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: jsPsych.timelineVariable('word'),\n choices: \"NO_KEYS\",\n trial_duration: 1000\n },\n {\n type: jsPsychSurvey,\n survey_json: function() {\n // This is a function that dynamically creates the JSON configuration for each trial.\n // Inside the function, you can access timeline variables, jsPsych data, and other global variables\n // that you define. This function will be called right before the trial starts.\n const this_trial_json = { \n elements: [\n {\n type: \"text\", \n title: `Enter a word related to ${jsPsych.timelineVariable('word').toUpperCase()}:`, \n autocomplete: \"off\" \n }\n ], \n showQuestionNumbers: false, \n completeText: \"Next\", \n focusFirstQuestionAutomatic: true \n }\n return this_trial_json;\n },\n data: { word: jsPsych.timelineVariable('word') }\n }\n ],\n timeline_variables: [\n { word: 'cheese' },\n { word: 'ring' },\n { word: 'bat' },\n { word: 'cow' }\n ]\n};\n
-
Use the survey_function
parameter. You can reference trial-level variables from inside this function, so the general idea here is the same as the example above. The difference is that here you are using SurveyJS's JavaScript API syntax to create the survey content, instead of the JSON configuration. Again, this could be done without timeline variables, but this example uses timeline variables for convenience:
const create_word_survey = (survey) => {\n // Create question using timeline variables\n const page = survey.addNewPage('page1');\n const question = page.addNewQuestion('text'); \n question.title = `Enter a word related to ${jsPsych.timelineVariable('word').toUpperCase()}`;\n question.autocomplete = \"off\";\n // Set survey-level parameters\n survey.showQuestionNumbers = false;\n survey.completeText = \"Next\";\n survey.focusFirstQuestionAutomatic = true;\n}\n\nconst word_trials = {\n timeline: [\n {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '+',\n choices: \"NO_KEYS\",\n trial_duration: 500\n },\n {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: jsPsych.timelineVariable('word'),\n choices: \"NO_KEYS\",\n trial_duration: 1000\n },\n {\n type: jsPsychSurvey,\n survey_function: create_word_survey,\n data: { word: jsPsych.timelineVariable('word') }\n }\n ],\n timeline_variables: [\n { word: 'cheese' },\n { word: 'ring' },\n { word: 'bat' },\n { word: 'cow' }\n ]\n};\n
"},{"location":"overview/data/","title":"Data Storage, Aggregation, and Manipulation","text":""},{"location":"overview/data/#data-in-jspsych-permanent-and-non-permanent-data","title":"Data in jsPsych: permanent and non-permanent data.","text":"There are two very different kinds of data storage: data stored in memory and data stored permanently. Data stored permanently exists even after the browser running jsPsych closes, typically in a database or in a file on a server. Data stored in memory exists only as long the browser window running jsPsych is open.
jsPsych has many features for interacting with data stored in memory, but few for permanent data storage. This is a deliberate choice, as there are dozens of ways that data could be stored permanently. jsPsych does not lock you into one particular solution. However, saving data permanently is obviously a crucial component of any experiment, and the second half of this page contains a few suggestions on how to accomplish permanent data storage.
"},{"location":"overview/data/#storing-data-in-jspsychs-data-structure","title":"Storing data in jsPsych's data structure","text":"jsPsych has a centralized collection of data that is built as the experiment runs. Each trial adds to the collection, and you can access the data with various functions, including jsPsych.data.get()
, which returns the entire set of data.
In most cases, data collection will be automatic and hidden. Plugins save data on their own so it is not uncommon to have the only interaction with the data be at the end of the experiment when it is time to save it in a permanent manner (see sections below about how to do this). However, there are some situations in which you may want to interact with the data; in particular, you may want to store additional data that the plugins are not recording, like a subject identifier or condition assignment. You may also want to add data on a trial by trial basis. For example, in a Stroop paradigm you would want to label which trials are congruent and which are incongruent. These scenarios are explored below.
"},{"location":"overview/data/#adding-data-to-all-trials","title":"Adding data to all trials","text":"Often it is useful to add a piece of data to all of the trials in the experiment. For example, appending the subject ID to each trial. This can be done with the jsPsych.data.addProperties()
function. Here is an example:
// generate a random subject ID with 15 characters\nvar subject_id = jsPsych.randomization.randomID(15);\n\n// pick a random condition for the subject at the start of the experiment\nvar condition_assignment = jsPsych.randomization.sampleWithoutReplacement(['conditionA', 'conditionB', 'conditionC'], 1)[0];\n\n// record the condition assignment in the jsPsych data\n// this adds a property called 'subject' and a property called 'condition' to every trial\njsPsych.data.addProperties({\n subject: subject_id,\n condition: condition_assignment\n});\n
"},{"location":"overview/data/#adding-data-to-a-particular-trial-or-set-of-trials","title":"Adding data to a particular trial or set of trials","text":"Data can be added to a particular trial by setting the data
parameter for the trial. The data
parameter is an object of key-value pairs, and each pair is added to the data for that trial.
var trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'imgA.jpg',\n data: { image_type: 'A' }\n}\n
Data declared in this way is also saved in the trials on any nested timelines:
var block = {\n type: jsPsychImageKeyboardResponse,\n data: { image_type: 'A' },\n timeline: [\n {stimulus: 'imgA1.jpg'},\n {stimulus: 'imgA2.jpg'}\n ]\n}\n
The data object for a trial can also be updated in the on_finish
event handler. You can override properties or add new ones. This is particularly useful for cases where the value depends on something that happened during the trial.
var trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'imgA.jpg',\n on_finish: function(data){\n if(jsPsych.pluginAPI.compareKeys(data.response, 'j')){\n data.correct = true;\n } else {\n data.correct = false;\n }\n }\n}\n
"},{"location":"overview/data/#skipping-data-collection-for-a-particular-trial","title":"Skipping data collection for a particular trial","text":"Sometimes you may want to skip data collection for a particular trial. This can be done by setting the record_data
parameter to false
. This is useful if you want your data output to only contain the trials that collect relevant responses from the participant. For example, you might want to skip data collection for trials that just present a fixation cross for a fixed period of time.
var trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'imgA.jpg',\n record_data: false\n}\n
"},{"location":"overview/data/#aggregating-and-manipulating-jspsych-data","title":"Aggregating and manipulating jsPsych data","text":"When accessing the data with jsPsych.data.get()
the returned object is a special data collection object that exposes a number of methods for aggregating and manipulating the data. The full list of methods is detailed in the data module documentation.
Here are some examples of data collection manipulation.
All data generated by the image-keyboard-response plugin:
var data = jsPsych.data.get().filter({trial_type: 'image-keyboard-response'});\n
All data generated by the categorize-image plugin with a correct response:
var data = jsPsych.data.get().filter({trial_type: 'categorize-image', correct: true});\n
All data with a response time between 100 and 500ms:
var data = jsPsych.data.get().filterCustom(function(x){ return x.rt >= 100 && x.rt <=500 });\n
Applying filters consecutively to get all trials from a particular plugin with a response time above 100ms:
var data = jsPsych.data.get().filter({trial_type: 'image-keyboard-response'}).filterCustom(function(x){ return x.rt > 100; });\n
Getting the data from the last n trials:
var n = 3;\nvar data = jsPsych.data.get().last(n);\n
Getting the data from the last n trials with a correct response:
var n = 3;\nvar data = jsPsych.data.get().filter({correct: true}).last(n);\n
Getting the data from the first n trials:
var n = 3;\nvar data = jsPsych.data.get().first(n);\n
Counting the number of trials with a correct response in a data collection:
var count = jsPsych.data.get().filter({correct: true}).count();\n
Selecting all of the response times from a data collection:
var response_times = jsPsych.data.get().select('rt');\n
Calculating various descriptive statistics on the response times in a data collection:
jsPsych.data.get().select('rt').mean();\njsPsych.data.get().select('rt').sum();\njsPsych.data.get().select('rt').min();\njsPsych.data.get().select('rt').max();\njsPsych.data.get().select('rt').variance();\njsPsych.data.get().select('rt').sd();\njsPsych.data.get().select('rt').median();\njsPsych.data.get().select('rt').count();\n
"},{"location":"overview/data/#storing-data-permanently-as-a-file","title":"Storing data permanently as a file","text":"This is one of the simplest methods for saving jsPsych data on the server that is running the experiment. It involves a short PHP script and a few lines of JavaScript code. This method will save each participant's data as a CSV file on the server. This method will only work if you are running on a web server with PHP installed, or a local server with PHP (e.g., XAMPP).
This method uses a short PHP script to write files to the server:
<?php\n// get the data from the POST message\n$post_data = json_decode(file_get_contents('php://input'), true);\n$data = $post_data['filedata'];\n// generate a unique ID for the file, e.g., session-6feu833950202 \n$file = uniqid(\"session-\");\n// the directory \"data\" must be writable by the server\n$name = \"data/{$file}.csv\"; \n// write the file to disk\nfile_put_contents($name, $data);\n?>\n
The file_put_contents($name, $data)
method requires permission to write new files. An easy way to solve this is to create a directory on the server that will store the data and use the chmod command to give all users write permission to that directory. In the above example, the directory data/
is used to store files.
To use the PHP script, the JavaScript that runs jsPsych needs to send the filedata
information. This is done through an AJAX call.
function saveData(name, data){\n var xhr = new XMLHttpRequest();\n xhr.open('POST', 'write_data.php'); // 'write_data.php' is the path to the php file described above.\n xhr.setRequestHeader('Content-Type', 'application/json');\n xhr.send(JSON.stringify({filedata: data}));\n}\n\n// call the saveData function after the experiment is over\ninitJsPsych({\n on_finish: function(){ saveData(jsPsych.data.get().csv()); }\n});\n
Danger
The example above has minimal security and should probably not be used without additional security measures put in place. The risk is that someone can write arbitrary data using the saveData()
function and store it to a file on your webserver. If they can guess the file name generated by the PHP script, or access a directory listing containing all of the filenames, then they can potentially write executable code to your server and run it.
One fix is to store the CSV files outside the web directory on the server. This requires changing the path in the PHP script above from /data
to a folder that is not accessible on the web. You should only use this solution if you have access to more than just the web directory on your server.
You can also configure your web server to block access to the folder you are storing data in.
The MySQL option below is more secure.
"},{"location":"overview/data/#storing-data-permanently-in-a-mysql-database","title":"Storing data permanently in a MySQL database","text":"Another solution for storing data generated by jsPsych is to write it to a database.
There are dozens of database options. MySQL is one of the most popular relational databases, is free to use, and relatively easy to install. This code will assume that you have a MySQL database installed on your server that is hosting the jsPsych experiment, and that your server is able to execute PHP code. If you are trying to run on a local machine, you'll need to install a local server environment like XAMPP.
You'll need two PHP scripts. The first is a configuration file for your database. Save it as database_config.php
on your server. Within this file are configuration options for the database. You'll need to change these according to how you have configured your MySQL installation.
<?php\n $servername = \"localhost\";\n $port = 3306;\n $username = \"username\";\n $password = \"password\";\n $dbname = \"database\";\n $table = \"tablename\";\n?>\n
The second PHP file will write data to the database. This script reads the database to discover what columns are in the table, and then only allows data to be entered in that matches those columns. This is a security feature. Save this file as write_data.php
on your server.
<?php\n\n// this path should point to your configuration file.\ninclude('database_config.php');\n\n$data_array = json_decode(file_get_contents('php://input'), true);\n\ntry {\n $conn = new PDO(\"mysql:host=$servername;port=$port;dbname=$dbname\", $username, $password);\n $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);\n // First stage is to get all column names from the table and store\n // them in $col_names array.\n $stmt = $conn->prepare(\"SHOW COLUMNS FROM `$table`\");\n $stmt->execute();\n $col_names = array();\n while($row = $stmt->fetchColumn()) {\n $col_names[] = $row;\n }\n // Second stage is to create prepared SQL statement using the column\n // names as a guide to what values might be in the JSON.\n // If a value is missing from a particular trial, then NULL is inserted\n $sql = \"INSERT INTO $table VALUES(\";\n for($i = 0; $i < count($col_names); $i++){\n $name = $col_names[$i];\n $sql .= \":$name\";\n if($i != count($col_names)-1){\n $sql .= \", \";\n }\n }\n $sql .= \");\";\n $insertstmt = $conn->prepare($sql);\n for($i=0; $i < count($data_array); $i++){\n for($j = 0; $j < count($col_names); $j++){\n $colname = $col_names[$j];\n if(!isset($data_array[$i][$colname])){\n $insertstmt->bindValue(\":$colname\", null, PDO::PARAM_NULL);\n } else {\n $insertstmt->bindValue(\":$colname\", $data_array[$i][$colname]);\n }\n }\n $insertstmt->execute();\n }\n echo '{\"success\": true}';\n} catch(PDOException $e) {\n echo '{\"success\": false, \"message\": ' . $e->getMessage();\n}\n$conn = null;\n?>\n
To send the data, we use an XMLHttpRequest
request in JavaScript.
function saveData() {\n var xhr = new XMLHttpRequest();\n xhr.open('POST', 'write_data.php'); // change 'write_data.php' to point to php script.\n xhr.setRequestHeader('Content-Type', 'application/json');\n xhr.onload = function() {\n if(xhr.status == 200){\n var response = JSON.parse(xhr.responseText);\n console.log(response.success);\n }\n };\n xhr.send(jsPsych.data.get().json());\n}\n
It's important that the XMLHttpRequest
is able to complete before the experiment is closed. If you invoke the saveData()
function at the end of your experiment and the participant closes the window before all of the data has been transferred you will lose that data. To mitigate this risk, you can use the call-function
plugin's async
option to prevent the experiment from progressing until the request is complete.
var trial = {\n type: jsPsychCallFunction,\n async: true,\n func: function(done){\n var xhr = new XMLHttpRequest();\n xhr.open('POST', 'write_data.php');\n xhr.setRequestHeader('Content-Type', 'application/json');\n xhr.onload = function() {\n if(xhr.status == 200){\n var response = JSON.parse(xhr.responseText);\n console.log(response.success);\n }\n done(); // invoking done() causes experiment to progress to next trial.\n };\n xhr.send(jsPsych.data.get().json());\n }\n}\n
"},{"location":"overview/dynamic-parameters/","title":"Dynamic parameters","text":"Most trial parameters can also be specified as functions. In a typical declaration of a jsPsych trial, parameters are known at the start of the experiment. This makes it impossible to alter the content of the trial based on the outcome of previous trials. However, when functions are used as the parameter value, the function is evaluated right before the trial starts, and the return value of the function is used as the parameter value for that trial. This enables dynamic updating of the parameter based on data that a participant has generated or any other information that you do not know in advance.
"},{"location":"overview/dynamic-parameters/#examples","title":"Examples","text":""},{"location":"overview/dynamic-parameters/#providing-feedback","title":"Providing Feedback","text":"Here is a sketch of how this functionality could be used to display feedback to a participant in the Flanker Task.
var timeline = [];\n\nvar trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<<<<<',\n choices: ['f','j'],\n data: {\n stimulus_type: 'congruent',\n target_direction: 'left'\n },\n on_finish: function(data){\n // Score the keyboard response as correct or incorrect.\n if(jsPsych.pluginAPI.compareKeys(data.response, \"f\")){\n data.correct = true;\n } else {\n data.correct = false; \n }\n }\n}\n\nvar feedback = {\n type: jsPsychHtmlKeyboardResponse,\n trial_duration: 1000,\n stimulus: function(){\n // The feedback stimulus is a dynamic parameter because we can't know in advance whether\n // the stimulus should be 'correct' or 'incorrect'.\n // Instead, this function will check the accuracy of the last response and use that information to set\n // the stimulus value on each trial.\n var last_trial_correct = jsPsych.data.get().last(1).values()[0].correct;\n if(last_trial_correct){\n return \"<p>Correct!</p>\"; // the parameter value has to be returned from the function\n } else {\n return \"<p>Wrong.</p>\"; // the parameter value has to be returned from the function\n }\n }\n}\n\ntimeline.push(trial, feedback);\n
Note
When scoring a participant's response, the jsPsych.pluginAPI.compareKeys
function is only needed to compare keyboard responses. For other kinds of response types, such as button presses, you can compare the participant's response and correct response values directly, e.g.
if (data.response == 0)){\n data.correct = true;\n} else {\n data.correct = false; \n}\n
Or: data.correct = data.response === data.correct_response;\n
"},{"location":"overview/dynamic-parameters/#randomizing-a-parameter-value","title":"Randomizing a parameter value","text":"Here's an example of using a dynamic parameter to randomize the inter-trial interval (ITI) duration. This time, the dynamic parameter is created using a named function instead of an anonymous function.
var random_duration = function() {\n var rand_dur = jsPsych.randomization.sampleWithoutReplacement([500,600,700,800],1)[0];\n return rand_dur;\n}\n\nvar trial = {\n type: jsPsychHtmlKeyboardResponse\n stimulus: '+',\n post_trial_gap: random_duration // if you use a named function for a dynamic parameter, then just use the function name (without parentheses after it)\n}\n
"},{"location":"overview/dynamic-parameters/#storing-changing-variables-in-the-data","title":"Storing changing variables in the data","text":"The trial's data
parameter can be also function, which is useful for when you want to save information to the data that can change during the experiment. For example, if you have a global variable called current_difficulty
that tracks the difficulty level in an adaptive task, you can save the current value of this variable to the trial data like this:
var current_difficulty; // value changes during the experiment\n\nvar trial = {\n type: jsPsychSurveyText,\n questions: [{prompt: \"Please enter your response.\"}]\n data: function() { \n return {difficulty: current_difficulty}; \n }\n}\n
It's also possible to use a function for any of the individual properties in the trial's data
object, for instance if you want to combine static and dynamic information in the data:
var trial = {\n type: jsPsychSurveyText,\n questions: [{prompt: \"Please enter your response.\"}]\n data: {\n difficulty: function() { \n return current_difficulty; // the difficulty value changes during the experiment\n },\n task_part: 'recall', // this part of the data is always the same\n block_number: 1\n }\n}\n
"},{"location":"overview/dynamic-parameters/#nested-parameters","title":"Nested Parameters","text":"Dyanmic parameters work the same way with nested parameters, which are parameters that contain one or more sets of other parameters. For instance, many survey-* plugins have a questions
parameter that is a nested parameter: it is an array that contains the parameters for one or more questions on the page. To make the questions
parameter dynamic, you can use a function that returns the array with all of the parameters for each question:
var subject_id; // value is set during the experiment\n\nvar trial = {\n type: jsPsychSurveyText,\n questions: function(){\n var questions_array = [ \n {prompt: \"Hi \"+subject_id+\"! What's your favorite city?\", required: true, name: 'fav_city'},\n {prompt: \"What is your favorite fruit?\", required: true, name: 'fav_fruit'},\n ];\n return questions_array;\n }\n}\n
You can also use a function for any of the individual parameters inside of a nested parameter.
var trial = {\n type: jsPsychSurveyText,\n questions: [\n { \n prompt: function() { \n // this question prompt is dynamic - the text that is shown \n // will change based on the participant's earlier response\n var favorite_city = jsPsych.data.getLastTrialData().values()[0].response.fav_city;\n var text = \"Earlier you said your favorite city is \"+favorite_city+\". What do you like most about \"+favorite_city+\"?\"\n return text;\n }, \n required: true,\n rows: 40,\n columns: 10\n },\n { prompt: \"What is your favorite fruit?\", required: true, name: 'fav_fruit' }\n ]\n}\n
"},{"location":"overview/dynamic-parameters/#when-dynamic-parameters-cant-be-used","title":"When dynamic parameters can't be used","text":"Note that if the plugin expects the value of a given parameter to be a function, then this function will not be evaluated at the start of the trial. This is because some plugins allow the researcher to specify functions that should be called at some point during the trial. Some examples of this include the stimulus
parameter in the canvas-* plugins, the mistake_fn
parameter in the cloze plugin, and the stim_function
parameter in the reconstruction plugin. If you want to check whether this is the case for a particular plugin and parameter, then the parameter's type
in the plugin.info
section of the plugin file. If the parameter type is ParameterType.FUNCTION
, then this parameter must be a function and it will not be executed before the trial starts.
Even though function evaluation doesn't work the same way with these parameters, the fact that the parameters are functions means that you can get the same dynamic functionality. These functions are typically evaluated at some point during the trial, so you still get updates to values within the function during the trial.
"},{"location":"overview/events/","title":"Event-related callback functions","text":"jsPsych offers the ability to call arbitrary functions in response to certain events occurring, like the end of a trial or when new data is saved. This page summarizes the different opportunities for callback functions and how to specify them.
"},{"location":"overview/events/#on_close","title":"on_close","text":"The on_close
callback can be declared in the initJsPsych
method. The callback triggers when the user leaves the page, but before any content on the page is removed from the browser's memory. This can be used, for example, to save data as the user is leaving the page.
initJsPsych({\n on_close: function(){\n var data = jsPsych.data.get().json();\n save_data_to_server(data);\n }\n});\n
"},{"location":"overview/events/#on_data_update","title":"on_data_update","text":"The on_data_update
callback can be declared in the initJsPsych
method. The callback triggers at the end of a data update cycle. This happens after every trial, after the on_finish (trial) and on_trial_finish events execute, allowing you to modify the data in those callbacks, and then use this callback to store the data. The function will be passed a single argument, which contains the data that was written.
initJsPsych({\n on_data_update: function(data) {\n console.log('Just added new data. The contents of the data are: '+JSON.stringify(data));\n }\n});\n
"},{"location":"overview/events/#on_finish-trial","title":"on_finish (trial)","text":"The on_finish
callback can be added to any trial. The callback will trigger whenever the trial ends. The callback function will be passed a single argument, containing the data object from the trial. This data object is editable. Any changes made in the on_finish function will be stored in the internal data collection.
var trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'imgA.png',\n on_finish: function(data) {\n if(jsPsych.pluginAPI.compareKeys(data.response, 'j')){\n data.correct = true;\n } else {\n data.correct = false;\n }\n }\n};\n
"},{"location":"overview/events/#on_finish-experiment","title":"on_finish (experiment)","text":"The on_finish
callback can be declared in the initJsPsych
method. The callback will trigger once all trials in the experiment have been run. The method will be passed a single argument, containing all of the data generated in the experiment.
initJsPsych({\n on_finish: function(data) {\n console.log('The experiment is over! Here is all the data: '+JSON.stringify(data));\n }\n});\n
"},{"location":"overview/events/#on_load","title":"on_load","text":"The on_load
callback can be added to any trial. The callback will trigger once the trial has completed loading. For most plugins, this will occur once the display has been initially updated but before any user interactions or timed events (e.g., animations) have occurred.
var trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'imgA.png',\n on_load: function() {\n console.log('The trial just finished loading.');\n }\n};\n
"},{"location":"overview/events/#on_start-trial","title":"on_start (trial)","text":"The on_start
callback can be added to any trial. The callback will trigger right before the trial begins. The callback function will be passed a single argument, containing the trial object. If any of the parameters of the trial are functions or timeline variables, these will be evaluated before on_start
is called, and the trial object will contain the evaluated value. The trial object is modifiable, and any changes made will affect the trial.
var trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'imgA.png',\n on_start: function(trial) {\n console.log('The trial is about to start.');\n trial.stimulus = 'imgB.png'; // this will change what stimulus is displayed in the trial\n }\n};\n
"},{"location":"overview/events/#on_timeline_finish","title":"on_timeline_finish","text":"The on_timeline_finish
callback can be declared in a timeline node. The callback will be triggered when the timeline ends. The event will trigger only once if the timeline loops, after all repetitions are complete.
var procedure = {\n timeline: [trial1, trial2],\n timeline_variables: [\n { stimulus: 'person-1.jpg' },\n { stimulus: 'person-2.jpg' },\n { stimulus: 'person-3.jpg' },\n { stimulus: 'person-4.jpg' }\n ],\n on_timeline_finish: function() {\n console.log('This timeline has finished.');\n }\n}\n
"},{"location":"overview/events/#on_timeline_start","title":"on_timeline_start","text":"The on_timeline_start
callback can be declared in a timeline node. The callback will be triggered when the timeline starts during the experiment. If a conditional_function
is used, then the conditional function will execute first, and the on_timeline_start
function will only execute if the conditional function returns true
. The event is triggered once, even if the timeline has a loop_function
or repetitions
.
var procedure = {\n timeline: [trial1, trial2],\n conditional_function: function() {\n console.log('This conditional function will execute first.')\n return true;\n },\n on_timeline_start: function() {\n console.log('This timeline has started');\n }\n}\n
"},{"location":"overview/events/#on_trial_finish","title":"on_trial_finish","text":"The on_trial_finish
callback can be declared in the initJsPsych
method. The callback will trigger at the end of every trial in the experiment, after the trial object's on_finish
callback has been run. The callback function will be passed a single argument, containing the data object from the trial. If you want a callback to trigger only for the end of certain trials, use the on_finish
callback on the trial object instead.
initJsPsych({\n on_trial_finish: function(data) {\n console.log('A trial just ended.');\n console.log(JSON.stringify(data));\n }\n});\n
"},{"location":"overview/events/#on_trial_start","title":"on_trial_start","text":"The on_trial_start
callback can be declared in the initJsPsych
method. The callback will trigger at the start of every trial in the experiment, before the trial-specific on_start
callback is executed. The function receives a single argument: a modifiable copy of the trial object that will be used to run the next trial. Changes can be made to this object to alter the parameters of the upcoming trial.
var current_score = 0; // a variable that is updated throughout the experiment to keep track of the current score.\n\ninitJsPsych({\n on_trial_start: function(trial) {\n trial.data.score_at_start_of_trial = current_score;\n console.log('A trial just started.');\n }\n});\n
"},{"location":"overview/exclude-browser/","title":"Exclude Participants Based on Browser Features","text":"Changed in 7.1
Online participants will use many different kinds of browsers. Depending on the experiment, it may be important to specify a minimum feature set of the browser.
As of v7.1 of jsPsych, the recommended way to do this is using the browser-check plugin. This plugin can record many features of the participant's browser and exclude participants who do not meet a defined set of inclusion criteria. Please see the browser-check plugin documentation for more details.
The prior approach of using the exclusions
parameter in initJsPsych()
is deprecated. It was removed as of v8.0
. You can find the documentation for it in the 7.0 docs.
"},{"location":"overview/experiment-options/","title":"Experiment-wide settings","text":"There are several options that can be set when calling initJsPsych()
to initialize the jsPsych experiment.
Options are specified in the object passed to initJsPsych
. For example, to specify a default inter-trial interval, a minimum valid response time duration, and a maximum width for all of the experiment's page content, the object would contain:
initJsPsych({\n default_iti: 250, \n minimum_valid_rt: 100, \n experiment_width: 800 \n});\n
"},{"location":"overview/experiment-options/#controlling-where-jspsych-renders-on-the-page","title":"Controlling where jsPsych renders on the page","text":"By default, jsPsych will render the experiment in the <body>
element of a page. It is possible to display the experiment in a different element (e.g., a <div>
) by specifying the display_element
parameter.
<body>\n <div id=\"jspsych-target\"></div>\n</body>\n<script>\n\n initJsPsych({\n display_element: 'jspsych-target'\n });\n\n</script>\n
This option is useful if the experiment needs to be rendered on a page with other content (e.g., a demo version of the experiment with annotation text), or if additional control over the display element is desired. Custom CSS rules can be applied to position, size, scale, etc. the display element.
"},{"location":"overview/experiment-options/#experiment-events","title":"Experiment events","text":"Several experiment-wide events can trigger functions. This is documented in more detail on the event-related callback functions page. The events that trigger functions are:
on_finish
: Called at the end of the experiment. on_trial_start
: Called at the beginning of every trial. on_trial_finish
: Called at the end of every trial. on_data_update
: Called whenever new data is added to the jsPsych data object. on_interaction_data_update
: Called whenever new interaction data (e.g., the participant enters or exits fullscreen mode) is added. on_close
: Called right before the page closes, such as when a participant closes the experiment early.
"},{"location":"overview/experiment-options/#specify-exclusion-criteria","title":"Specify exclusion criteria","text":"Exclusion criteria can be specified based on features of the user's web browser, such as the display size and whether certain features are reported. See the page on excluding participants based on browser features.
"},{"location":"overview/experiment-options/#display-a-progress-bar","title":"Display a progress bar","text":"An automatic or manually updated progress bar can be displayed at the top of the screen. By default, the text next to the progress bar is \"Completion Progress\", but this text can be changed with the message_progress_bar
parameter in initJsPsych
. See the progress bar page for more details.
"},{"location":"overview/experiment-options/#choose-the-method-for-playing-audio-files","title":"Choose the method for playing audio files","text":"Specifying the use_webaudio
parameter in initJsPsych()
allows you to choose whether to use the WebAudio API or HTML5 audio for playing audio files during your experiment. By default, jsPsych uses the WebAudio API to play audio files. Among other features, the WebAudio API allows for more precise measurement of response times relative to the onset of the audio.
However, loading files through the WebAudio API causes errors when running an experiment offline (i.e., by double-clicking on the HTML file, rather than hosting it on a web server). This is due to the cross-origin security policy implemented by web browsers. For this reason, jsPsych switches to a 'safe mode' when it detects that the webpage is running offline, and automatically uses HTML5 audio to prevent errors, even when use_webaudio
has been explicitly set to true
. For more information, see the section Cross-origin requests (CORS) and safe mode on the Running Experiments page.
initJsPsych({\n use_webaudio: false\n});\n
"},{"location":"overview/experiment-options/#set-the-default-intertrial-interval","title":"Set the default intertrial interval","text":"By default the next trial in a timeline will begin immediately after the conclusion of the previous trial. An experiment-wide delay can be specified using the default_iti
parameter to initJsPsych()
.
initJsPsych({\n default_iti: 500\n});\n
This parameter is specified in milliseconds. A blank screen will display between each trial for the duration of the ITI.
"},{"location":"overview/experiment-options/#specify-the-maximum-width-of-the-experiment","title":"Specify the maximum width of the experiment","text":"The experiment will, by default, take up 100% of the display element. Usually the display element is the <body>
, and the experiment is the full width of the screen. (This can be overridden by specifying the display_element
parameter described above).
Specifying the experiment_width
parameter will set a maximum width for the display. The parameter is specified in pixels.
initJsPsych({\n experiment_width: 750\n});\n
"},{"location":"overview/experiment-options/#specify-a-minimum-valid-response-time","title":"Specify a minimum valid response time","text":"By default, jsPsych will treat any keyboard response time as valid. However, it's possible to specify a minimum valid response time (in ms) for key presses. Any key press that is less than this value will be treated as invalid and ignored. Note that this parameter only applies to keyboard responses, and not to other response types such as buttons and sliders. The default value is 0.
// ignore any keyboard responses that are less than 100 ms\ninitJsPsych({\n minimum_valid_rt: 100\n});\n
"},{"location":"overview/experiment-options/#choose-whether-you-want-keyboard-choicesresponses-to-be-case-sensitive","title":"Choose whether you want keyboard choices/responses to be case-sensitive","text":"JavaScript keyboard events make a distinction between uppercase and lowercase key responses (e.g. 'a' and 'A'). Often the researcher just cares about which physical key was pressed, and not whether the key press would result in an uppercase letter (for instance, if CapsLock is on or if the Shift key is held down). For this reason, jsPsych converts all key choice parameters and key responses as lowercase by default. This makes it easier to specify key choices (e.g. choices: ['a']
, instead of choices: ['a','A']
), and it makes it easier to check and score a participant's response.
There may be situations when you want key choices and responses to be case-sensitive. You can change this by setting the case_sensitive_responses
parameter to true
in initJsPsych
.
// use case-sensitive key choices and responses, \n// i.e. uppercase and lower case letters ('a' and 'A') will be treated as different key choices, \n// and will be recorded this way in the data\ninitJsPsych({\n case_sensitive_responses: true\n});\n
Note that this setting only applies to key choices and responses that use jsPsych's keyboard response listener, such as in the *-keyboard-response
plugins. This does NOT apply to responses that are made by typing into a text box, such as in the survey-text
and cloze
plugins.
"},{"location":"overview/experiment-options/#override-safe-mode-when-running-experiments-offline","title":"Override 'safe mode' when running experiments offline","text":"By default, jsPsych switches to a 'safe mode' when it detects that the webpage is running offline (via the file://
protocol) in order to prevent certain errors. Specifically, in safe mode, HTML5 audio is used to play audio files (even when use_webaudio
has been explicitly set to true
) and video preloading is disabled (both automatic and manual preloading). For more information, see the Cross-origin requests (CORS) and safe mode section on the Running Experiments page.
It's possible to override this safe mode feature by setting the override_safe_mode
parameter to true
in initJsPsych
. This is something you might do if you've disabled certain security settings in your browser for testing purposes. This parameter has no effect when your experiment is running online (on a server), because it will be using the http://
or https://
protocol, which does not trigger safe mode.
initJsPsych({\n override_safe_mode: true\n});\n
"},{"location":"overview/experiment-options/#add-extensions","title":"Add extensions","text":"Extensions are jsPsych modules that can run throughout the experiment and interface with any plugin to extend the functionality of the plugin. One example of an extension is eye tracking, which allows you to gather gaze data during any trial and add it to that trial's data object. If you want to use extensions in your experiment, you must specify this when you initialize the experiment with initJsPsych
. The extensions
parameter in initJsPsych
is an array of objects, where each object specifies the extension that you'd like to use in the experiment. Below is an example of adding the webgazer extension.
initJsPsych({\n extensions: [\n {type: jsPsychExtensionWebgazer}\n ]\n});\n
"},{"location":"overview/extensions/","title":"Extensions","text":"Extensions are jsPsych modules that can interface with any plugin to extend the functionality of the plugin. A canonical example of an extension is eye tracking. An eye tracking extension allows a plugin to gather gaze data and add it to the plugin's data object.
"},{"location":"overview/extensions/#using-an-extension","title":"Using an Extension","text":"To use an extension in an experiment, you'll load the extension file via a <script>
tag (just like adding a plugin) and then initialize the extension in the parameters of initJsPsych()
.
<head>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/extension-example@1.0.0\"></script>\n</head>\n
initJsPsych({\n extensions: [\n {type: jsPsychExtensionExample, params: {...} }\n ]\n})\n
To enable an extension during a trial, add the extension to the extensions
list for the trial. Some extensions may also support or require an object of parameters to configure the extension:
var trial = {\n extensions: [\n {type: jsPsychExtensionExample, params: {...} }\n ]\n}\n
"},{"location":"overview/extensions/#list-of-extensions","title":"List of Extensions","text":"Extension Description jspsych\u2011ext\u2011webgazer.js Enables eye tracking using the WebGazer library."},{"location":"overview/extensions/#writing-an-extension","title":"Writing an Extension","text":"See our developer's guide for extensions for information about how to create a new extension.
"},{"location":"overview/eye-tracking/","title":"Eye Tracking","text":"jsPsych supports eye tracking through the WebGazer library. WebGazer uses computer vision techniques to identify features of the participant's eyes via a webcam and predicts gaze location. The system is calibrated by having the participant click on or look at known locations on the screen. These locations are linked to eye features. Gaze location is predicted using regression.
"},{"location":"overview/eye-tracking/#getting-started","title":"Getting Started","text":""},{"location":"overview/eye-tracking/#load-webgazerjs","title":"Load webgazer.js","text":"The official version of WebGazer is currently not supported by jsPsych. Our fork of the library contains some minor improvements aimed at the kind of experiments that jsPsych is typically used for, e.g., situations in which the timing of display screens needs to be accurate.
You must include the webgazer.js
file in your experiment via a <script>
tag. However, the webgazer.js
file is not part of any of the jsPsych NPM packages and is therefore not available via the unpkg.com CDN. Instead, it can be found on the jsdelivr.net CDN at: \"https://cdn.jsdelivr.net/gh/jspsych/jspsych@jspsych@7.0.0/examples/js/webgazer/webgazer.js\".
<head>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://cdn.jsdelivr.net/gh/jspsych/jspsych@jspsych@7.0.0/examples/js/webgazer/webgazer.js\"></script>\n</head>\n
Note
A copy of our forked webgazer.js
file is also included in the jsPsych release, in the /examples/js/webgazer
folder. So if you prefer to download and host all of your jsPsych files (i.e. set-up option 2 in the Hello World tutorial), then another option is to load that file rather than using the jsdelivr link above. Assuming you downloaded the release and copied the webgazer.js
file into a folder called js/webgazer
in your root project directory, then you would load the file like this:
<script src=\"js/webgazer/webgazer.js\"></script>\n
"},{"location":"overview/eye-tracking/#load-the-jspsych-webgazer-extension","title":"Load the jsPsych webgazer extension","text":"The webgazer extension adds functionality to jsPsych for interacting with webgazer. Load it like you would a plugin file.
<head>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://cdn.jsdelivr.net/gh/jspsych/jspsych@jspsych@7.0.0/examples/js/webgazer/webgazer.js\"></script>\n <script src=\"https://unpkg.com/@jspsych/extension-webgazer@1.1.0\"></script>\n</head>\n
To use the WebGazer extension in an experiment, include it in the list of extensions passed to initJsPsych()
initJsPsych({\n extensions: [\n {type: jsPsychExtensionWebgazer}\n ]\n})\n
"},{"location":"overview/eye-tracking/#initialize-the-camera","title":"Initialize the camera","text":"To help the participant position their face correctly for eye tracking you can use the webgazer-init-camera plugin. This will show the participant what the camera sees, including facial feature landmarks, and prevent the participant from continuing until their face is in good position for eye tracking. This plugin will also trigger the experiment to request permission to access the user's webcam if it hasn't already been granted.
var init_camera_trial = {\n type: jsPsychWebgazerInitCamera\n}\n
"},{"location":"overview/eye-tracking/#calibration","title":"Calibration","text":"To calibrate WebGazer, you can use the webgazer-calibrate plugin. This plugin allows you to specify a set of points on the screen for calibration and to choose the method for calibrating -- either clicking on each point or simply fixating on each point. The location of calibration points is specified in percentages, e.g., [25,50]
will result in a point that is 25% of the width of the screen from the left edge and 50% of the height of the screen from the top edge. Options for controlling other details of the calibration are explained in the documentation for the plugin.
Note that instructions are not included in the calibration plugin, so you'll likely want to use a different plugin (e.g., html-button-response
) to display instructions prior to running the calibration.
var calibration_trial = {\n type: jsPsychWebgazerCalibrate,\n calibration_points: [[25,50], [50,50], [75,50], [50,25], [50,75]],\n calibration_mode: 'click'\n}\n
"},{"location":"overview/eye-tracking/#validation","title":"Validation","text":"To measure the accuracy and precision of the calibration, you can use the webgazer-vaidate plugin. Like the calibration plugin, you can specify a list of points to perform validation on. Here you can specify the points as either percentages or in terms of the distance from the center of the screen in pixels. Which mode you use will probably depend on how you are defining your stimuli throughout the experiment. You can also specify the radius of tolerance around each point, and the plugin will calculate the percentage of measured gaze samples within that radius. This is a potentially useful heuristic for deciding whether or not to calibrate again. Options for controlling other details of the validation are explained in the documentation for the plugin.
var validation_trial = {\n type: jsPsychWebgazerValidate,\n validation_points: [[-200,200], [200,200],[-200,-200],[200,-200]],\n validation_point_coordinates: 'center-offset-pixels',\n roi_radius: 100\n}\n
The validation procedure stores the raw gaze data for each validation point, the computed average offset from each validation point, the percentage of samples within the roi_radius
for each validation point, and the number of samples collected per second.
{\n raw_gaze: [...],\n percent_in_roi: [...],\n average_offset: [...],\n samples_per_sec: ...\n}\n
We recommend performing calibration and validation periodically throughout your experiment.
"},{"location":"overview/eye-tracking/#adding-eye-tracking-to-a-trial","title":"Adding eye tracking to a trial","text":"To enable eye tracking for a trial in your experiment, you can simply add the WebGazer extension to the trial.
var trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<img id=\"scene\" src=\"my-scene.png\"></img>',\n extensions: [\n {\n type: jsPsychExtensionWebgazer, \n params: { \n targets: ['#scene']\n }\n }\n ]\n}\n
This will turn on WebGazer at the start of the trial.
The params
property in the extensions
declaration allows you to pass in a list of CSS selector strings. The bounding rectangle of the DOM element that matches each selector will be recorded in the data for that trial. This allows for easy alignment of the gaze data and objects on the screen.
webgazer_targets : {\n 'selector': {x: ..., y: ..., height: ..., width: ..., top: ..., left: ..., right: ..., bottom:...}\n 'selector': {x: ..., y: ..., height: ..., width: ..., top: ..., left: ..., right: ..., bottom:...}\n}\n
Gaze data will be added to the trial's data under the property webgazer_data
. The gaze data is an array of objects. Each object has an x
, a y
, and a t
property. The x
and y
properties specify the gaze location in pixels and t
specifies the time in milliseconds since the start of the trial. Note that establishing the precision and accuracy of these measurements across the variety of web browsers and systems that your experiment participants might be using is quite difficult. For example, different browsers may cause small systematic shifts in the accuracy of t
values.
webgazer_data: [\n {x: ..., y: ..., t: ...},\n {x: ..., y: ..., t: ...},\n {x: ..., y: ..., t: ...},\n {x: ..., y: ..., t: ...}\n]\n
"},{"location":"overview/eye-tracking/#tips-for-improving-data-quality","title":"Tips for Improving Data Quality","text":"These are some anecdotal observations about factors that improve data quality.
- The quality of the camera feed is essential. Good lighting makes a big difference. You may want to encourage participants to perform any eye tracking experiments in a well-lit room.
- Participants need to keep their head relatively still during and after calibration. The calibration is not robust to head movements.
- WebGazer's click-based calibration can be used throughout the experiment. You can turn this on by calling
jsPsych.extensions.webgazer.startMouseCalibration()
at any point in the experiment. If you use a continue button to advance through the experiment and move the location of the continue button around you can be making small adjustments to the calibration throughout. - Computing the gaze predictions consumes more computational resources than most other things that jsPsych is typically used for. The sampling rate that WebGazer is able to achieve will depend on the computing power of the participant's device. You may want to ask the participant to close any non-essential software and browser windows prior to completing the experiment. You may also want to check that the sampling rate is sufficiently high as part of validation.
If you have tips based on your own experience please consider sharing them on our discussion forum and we'll add to this list!
"},{"location":"overview/eye-tracking/#example","title":"Example","text":"Tip
Additional example experiments using WebGazer are available in the /examples folder of the jsPsych release. See webgazer.html
, webgazer_image.html
, and webgazer_audio.html
.
Example
Here's an example of putting all of the pieces above together. This example also shows how to use data from the validation to decide whether or not to recalibrate. You can try this experiment here (opens in new tab).
<!DOCTYPE html>\n<html>\n <head>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-preload@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-button-response@2.0.1\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-webgazer-init-camera@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-webgazer-calibrate@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-webgazer-validate@2.0.0\"></script>\n <script src=\"https://cdn.jsdelivr.net/gh/jspsych/jspsych@jspsych@7.0.0/examples/js/webgazer/webgazer.js\"></script>\n <script src=\"https://unpkg.com/@jspsych/extension-webgazer@1.1.0\"></script>\n <link\n rel=\"stylesheet\"\n href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\"\n />\n <style>\n .jspsych-btn {\n margin-bottom: 10px;\n }\n </style>\n </head>\n <body></body>\n <script>\n\n var jsPsych = initJsPsych({\n extensions: [\n {type: jsPsychExtensionWebgazer}\n ]\n });\n\n var preload = {\n type: jsPsychPreload,\n images: ['img/blue.png']\n }\n\n var camera_instructions = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `\n <p>In order to participate you must allow the experiment to use your camera.</p>\n <p>You will be prompted to do this on the next screen.</p>\n <p>If you do not wish to allow use of your camera, you cannot participate in this experiment.<p>\n <p>It may take up to 30 seconds for the camera to initialize after you give permission.</p>\n `,\n choices: ['Got it'],\n }\n\n var init_camera = {\n type: jsPsychWebgazerInitCamera\n }\n\n var calibration_instructions = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `\n <p>Now you'll calibrate the eye tracking, so that the software can use the image of your eyes to predict where you are looking.</p>\n <p>You'll see a series of dots appear on the screen. Look at each dot and click on it.</p>\n `,\n choices: ['Got it'],\n }\n\n var calibration = {\n type: jsPsychWebgazerCalibrate,\n calibration_points: [\n [25,25],[75,25],[50,50],[25,75],[75,75]\n ],\n repetitions_per_point: 2,\n randomize_calibration_order: true\n }\n\n var validation_instructions = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `\n <p>Now we'll measure the accuracy of the calibration.</p>\n <p>Look at each dot as it appears on the screen.</p>\n <p style=\"font-weight: bold;\">You do not need to click on the dots this time.</p>\n `,\n choices: ['Got it'],\n post_trial_gap: 1000\n }\n\n var validation = {\n type: jsPsychWebgazerValidate,\n validation_points: [\n [25,25],[75,25],[50,50],[25,75],[75,75]\n ],\n roi_radius: 200,\n time_to_saccade: 1000,\n validation_duration: 2000,\n data: {\n task: 'validate'\n }\n }\n\n var recalibrate_instructions = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `\n <p>The accuracy of the calibration is a little lower than we'd like.</p>\n <p>Let's try calibrating one more time.</p>\n <p>On the next screen, look at the dots and click on them.<p>\n `,\n choices: ['OK'],\n }\n\n var recalibrate = {\n timeline: [recalibrate_instructions, calibration, validation_instructions, validation],\n conditional_function: function(){\n var validation_data = jsPsych.data.get().filter({task: 'validate'}).values()[0];\n return validation_data.percent_in_roi.some(function(x){\n var minimum_percent_acceptable = 50;\n return x < minimum_percent_acceptable;\n });\n },\n data: {\n phase: 'recalibration'\n }\n }\n\n var calibration_done = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `\n <p>Great, we're done with calibration!</p>\n `,\n choices: ['OK']\n }\n\n var begin = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `<p>The next screen will show an image to demonstrate adding the webgazer extension to a trial.</p>\n <p>Just look at the image while eye tracking data is collected. The trial will end automatically.</p>\n <p>Press any key to start.</p>\n `\n }\n\n var trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/blue.png',\n choices: \"NO_KEYS\",\n trial_duration: 2000,\n extensions: [\n {\n type: jsPsychExtensionWebgazer, \n params: {targets: ['#jspsych-image-keyboard-response-stimulus']}\n }\n ]\n }\n\n var show_data = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: function() {\n var trial_data = jsPsych.data.getLastTrialData().values();\n var trial_json = JSON.stringify(trial_data, null, 2);\n return `<p style=\"margin-bottom:0px;\"><strong>Trial data:</strong></p>\n <pre style=\"margin-top:0px;text-align:left;\">${trial_json}</pre>`;\n },\n choices: \"NO_KEYS\"\n };\n\n jsPsych.run([\n preload, \n camera_instructions, \n init_camera, \n calibration_instructions, \n calibration, \n validation_instructions, \n validation, \n recalibrate,\n calibration_done,\n begin, \n trial, \n show_data\n ]);\n\n </script>\n</html>\n
Below is example data from the image-keyboard-response trial taken from the experiment above. In addition to the standard data that is collected for this plugin, you can see the additional webgazer_data
and webgazer_targets
arrays. The webgazer_data
shows 21 gaze location estimates during the 1-second image presentation. The webgazer_targets
array shows that there was one target, the image-keyboard-response stimulus, and tells you the x- and y-coordinate boundaries for the target (image) rectangle. By comparing each of the x/y locations from the webgazer_data
locations array with the target boundaries in webgazer_targets
, you can determine if/when the estimated gaze location was inside the target area.
{\n \"rt\": null,\n \"stimulus\": \"img/blue.png\",\n \"response\": null,\n \"trial_type\": \"image-keyboard-response\",\n \"trial_index\": 4,\n \"time_elapsed\": 30701,\n \"webgazer_data\": [\n { \"x\": 1065, \"y\": 437, \"t\": 39},\n { \"x\": 943, \"y\": 377, \"t\": 79},\n { \"x\": 835, \"y\": 332, \"t\": 110},\n { \"x\": 731, \"y\": 299, \"t\": 146},\n { \"x\": 660, \"y\": 271, \"t\": 189},\n { \"x\": 606, \"y\": 251, \"t\": 238},\n { \"x\": 582, \"y\": 213, \"t\": 288},\n { \"x\": 551, \"y\": 200, \"t\": 335},\n { \"x\": 538, \"y\": 183, \"t\": 394},\n { \"x\": 514, \"y\": 177, \"t\": 436},\n { \"x\": 500, \"y\": 171, \"t\": 493},\n { \"x\": 525, \"y\": 178, \"t\": 542},\n { \"x\": 537, \"y\": 182, \"t\": 592},\n { \"x\": 543, \"y\": 178, \"t\": 633},\n { \"x\": 547, \"y\": 177, \"t\": 691},\n { \"x\": 558, \"y\": 174, \"t\": 739},\n { \"x\": 574, \"y\": 183, \"t\": 789},\n { \"x\": 577, \"y\": 197, \"t\": 838},\n { \"x\": 584, \"y\": 214, \"t\": 889},\n { \"x\": 603, \"y\": 218, \"t\": 937},\n { \"x\": 606, \"y\": 221, \"t\": 987}\n ],\n \"webgazer_targets\": [\n \"#jspsych-image-keyboard-response-stimulus\": {\n \"x\": 490,\n \"y\": 135,\n \"height\": 300,\n \"width\": 300,\n \"top\": 135,\n \"bottom\": 435,\n \"left\": 490,\n \"right\": 790\n }\n ]\n}\n
"},{"location":"overview/fullscreen/","title":"Fullscreen Experiments","text":"You can run your experiment in fullscreen mode by using the jspsych-fullscreen plugin.
var jsPsych = initJsPsych();\n\nvar timeline = [];\n\ntimeline.push({\n type: jsPsychFullscreen,\n fullscreen_mode: true\n});\n\ntimeline.push({\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'This trial will be in fullscreen mode.'\n});\n\n// exit fullscreen mode\ntimeline.push({\n type: jsPsychFullscreen,\n fullscreen_mode: false\n});\n\ntimeline.push({\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'This trial will NOT be in fullscreen mode.'\n});\n\njsPsych.run(timeline);\n
For security reasons, web browsers require that users initiate an action to launch fullscreen mode. The fullscreen plugin displays a button that the user must click to change the display to fullscreen.
Safari does not support keyboard input when the browser is in fullscreen mode. Therefore, the function will not launch fullscreen mode on Safari. The experiment will ignore any trials using the fullscreen plugin in Safari.
"},{"location":"overview/media-preloading/","title":"Media Preloading","text":"If an experiment uses image, audio, or video files as stimuli, it is a good idea to preload the files before running the experiment. You can preload files at any point in your experiment using the jsPsych preload
plugin. Preloading files means that the participant's browser will download the files and store them in local memory on the participant's computer. This is important because displaying or playing a media file is much faster if it is already in memory on the participant's computer. Without preloading, there will be noticeable delays in the display of media, which will affect any timing measurements (such as how long an image is displayed, or a participant's response time since first viewing an image). For particularly large files, like video, preloading content avoids lengthy pauses in the middle of the experiment that can be disruptive to the flow of the experiment.
Warning
Note that video preloading will not work when you run your experiment offline (e.g., by double-clicking on the HTML file), but it will work once your experiment is running online (hosted on a server). The [Cross-origin requests (CORS) and safe mode](running-experiments.md#cross-origin-requests-cors-and-safe-mode) section on the Running Experiments page contains more information about this.\n
"},{"location":"overview/media-preloading/#automatic-preloading","title":"Automatic Preloading","text":"jsPsych can automatically preload audio, video, and image files that are used as parameters for the standard set of plugins, based on the timeline that is passed to jsPsych.run
. You must initiate this preloading using a preload
trial. You should add this preload
trial into your timeline when you want the preloading to occur, and set the auto_preload
parameter to true
.
// the \"auto_preload: true\" setting tells the plugin to automatically find \n// stimuli to preload based the main experiment timeline (used in jsPsych.run)\nvar preload = {\n type: jsPsychPreload,\n auto_preload: true \n}\n\n// this image file can be automatically preloaded \nvar image_trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/file1.png'\n}\n\n// the sound file can be automatically preloaded \nvar sound_trial = {\n type: jsPsychAudioKeyboardResponse,\n stimulus: 'audio/hello.mp3'\n}\n\n// the video file can be automatically preloaded (as long as the experiment \n// is running on a server)\nvar video_trial = {\n type: jsPsychVideoKeyboardResponse,\n stimulus: ['video/sample_video.mp4']\n}\n\njsPsych.run([preload, image_trial, sound_trial, video_trial]);\n
"},{"location":"overview/media-preloading/#manual-preloading","title":"Manual preloading","text":"If you are using media files in your experiment but they are not being passed directly as parameters to the trials (e.g., because you are using functions as parameters that return the media files, you are using timeline variables, or you are embedding the media files in an HTML string), then these files will not be detected when you use the auto_preload
option, so you must manually specify them. The preload
plugin allows you to add these files using the images
, audio
and video
parameters.
// this image file cannot be automatically preloaded because it is embedded in \n// an HTML string\nvar image_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<img src=\"img/file1.png\"></img>',\n}\n\n// this audio file cannot be automatically preloaded because it is returned \n// from a function\nvar sound_trial = {\n type: jsPsychAudioKeyboardResponse,\n stimulus: function() { return 'audio/sound1.mp3' }\n}\n\n// these video files cannot be automatically preloaded because they are passed \n// into a trial using the jsPsych.timelineVariable function\nvar video_trials = {\n timeline: [\n {\n type: jsPsychVideoKeyboardResponse,\n stimulus: jsPsych.timelineVariable('video')\n }\n ],\n timeline_variables: [\n {video: ['video/1.mp4']},\n {video: ['video/2.mp4']}\n ]\n}\n\n// to manually preload media files, create an array of file paths for each \n// media type\nvar images = ['img/file1.png'];\nvar audio = ['audio/sound1.mp3'];\nvar video = ['video/1.mp4', 'video/2.mp4'];\n\n// these array can be passed into the preload plugin using the images, audio \n// and video parameters\nvar preload = {\n type: jsPsychPreload,\n images: images,\n audio: audio,\n video: video\n}\n\njsPsych.run([preload, image_trial, sound_trial, video_trials]);\n
"},{"location":"overview/media-preloading/#combining-automatic-and-manual-preloading","title":"Combining automatic and manual preloading","text":"It's possible to combine automatic and manual preloading. For instance, you may want to automatically preload all of the media files based on your experiment timeline, while also manually preloading any files that can't be automatically preloaded. Any duplicate file names across all preloading methods will be removed before preloading starts, so including the same file names in multiple preload
parameters will not affect the preloading duration.
// this file can be preloaded automatically\nvar image_trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/file1.png'\n}\n\n// this file can be preloaded automatically\nvar sound_trial = {\n type: jsPsychAudioKeyboardResponse,\n stimulus: 'audio/hello.mp3'\n}\n\n// these files must be preloaded manually\nvar video_trials = {\n timeline: [\n {\n type: jsPsychVideoKeyboardResponse,\n stimulus: jsPsych.timelineVariable('video')\n }\n ],\n timeline_variables: [\n {video: ['video/1.mp4']},\n {video: ['video/2.mp4']}\n ]\n}\n\nvar video = ['video/1.mp4', 'video/2.mp4'];\n\nvar preload = {\n type: jsPsychPreload,\n auto_preload: true, // automatically preload the image and audio files\n video: video // manually preload the videos used with timeline variables\n}\n\njsPsych.run([preload, image_trial, sound_trial, video_trials]);\n
"},{"location":"overview/media-preloading/#preloading-in-batches","title":"Preloading in batches","text":"Some experiments use many and/or large media files. This can cause problems when participants have slow and/or unreliable internet connections, because it increases the chances of loading errors during preloading. This can also cause problems with file caching, i.e. ensuring that the preloaded files remain in the browser's memory, because loading all stimuli at once may exceed the browser's cache limits. One option for mitigating these problems is to load the media files in smaller batches throughout the experiment. Files should be preloaded as close as possible to when they will be needed. For instance, if you have several blocks of trials, then right before each block, you can preload the stimuli that are needed for that block.
Here is an example with trials where the stimuli files can be preloaded automatically. In this case, the trials
parameter is used to tell the preload
plugin to preload the stimuli from a specific part of the timeline.
// these image files in these trial blocks can be automatically preloaded\nvar block_1 = {\n timeline: [\n {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/file1.png'\n },\n {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/file2.png'\n }\n ]\n}\n\nvar block_2 = {\n timeline: [\n {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/file3.png'\n },\n {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/file4.png'\n }\n ]\n}\n\nvar preload_1 = {\n type: jsPsychPreload,\n trials: block_1 // automatically preload just the images from block_1 trials\n}\n\nvar preload_2 = {\n type: jsPsychPreload,\n trials: block_2 // automatically preload just the images from block_2 trials\n}\n\njsPsych.run(\n // add each preload trial onto the timeline before the appropriate trial block\n [preload_1, block_1, preload_2, block_2]\n);\n
Below is an example with trials where the stimuli files cannot be preloaded automatically, because the stimuli files are passed to the trials via jsPsych.timelineVariable
. In this case, we create separate arrays for each batch of files, and then pass those arrays to the each preload trial.
// these trial blocks cannot be automatically preloaded because \n// the media files are passed to the trial parameters with timeline variables\nvar block_1 = {\n timeline: [...],\n timeline_variables: [\n {stim: 'file1.png'},\n {stim: 'file1.png'}\n ]\n}\n\nvar block_2 = {\n timeline: [...],\n timeline_variables: [\n {stim: 'file3.png'},\n {stim: 'file4.png'}\n ]\n}\n\nvar images_block_1 = ['file1.png', 'file2.png'];\nvar images_block_2 = ['file3.png', 'file4.png'];\n\n// preload trial for preloading the block 1 stimuli\nvar preload_1 = {\n type: jsPsychPreload,\n images: images_block_1\n}\n\n// preload trial for preloading the block 2 stimuli\nvar preload_2 = {\n type: jsPsychPreload,\n images: images_block_2\n}\n\njsPsych.run(\n // add each preload trial to the timeline before the appropriate trial block\n [preload_1, block_1, preload_2, block_2]\n);\n
"},{"location":"overview/media-preloading/#preloading-progress-bar","title":"Preloading progress bar","text":"By default, the preload
plugin will display a progress bar while files are being preloaded. This progress bar represents all files that are being preloaded during the trial, regardless of whether the file is being preloaded automatically via the auto_preload
or trials
parameters, or manually via the audio
, images
, and video
parameters. You may wish to turn the preload progress bar off if you are only loading a small number of files, as it will appear and disappear so quickly that the participant may be confused about what it was. You can control whether the preloading progress bar appears by setting the show_progress_bar
parameter in the preload
trial.
var preload_trial = {\n type: jsPsychPreload,\n auto_preload: true\n show_progress_bar: false // hide progress bar\n}\n
"},{"location":"overview/media-preloading/#loading-time-limits","title":"Loading time limits","text":"It's usually a good idea to set a time limit for file loading, to ensure that participants aren't waiting for an unreasonable amount of time. Time limits can be specified in milliseconds using the max_load_time
parameter. If you set a loading time limit and all files haven't finished loading before this time, then the preload
trial will either stop an error (if continue_after_error
is false, the default) or the trial will end and the experiment will continue (if continue_after_error
is true
). If max_load_time
is null
(the default), then there is no time limit.
var preload_trial = {\n type: jsPsychPreload,\n auto_preload: true\n max_load_time: 60000 // 1 minute\n}\n
"},{"location":"overview/media-preloading/#loading-and-error-messages","title":"Loading and error messages","text":"It's possible to specify custom messages to be shown on the page while the media files are loading, and in case of one or more file loading errors. The message
parameter allows you to customize the loading message using an HML-formatted string. If show_progress_bar
is true
, then this message will be shown above the progress bar.
var preload_trial = {\n type: jsPsychPreload,\n auto_preload: true\n message: 'Please wait while the experiment loads. This may take a few minutes.',\n}\n
A preloading error will occur when either (a) one or more files produces a loading error, and/or (b) all files have not finished loading before the max_load_time
duration. The error_message
parameter allows you to customize the messsage that's shown on the page in these cases. This message will only be shown if continue_after_error
is false
(the default).
var preload_trial = {\n type: jsPsychPreload,\n auto_preload: true,\n error_message: 'The experiment failed to load. Please contact the researcher.'\n}\n
In addition to the error_message
parameter, it's also possible to show more detailed error messages on the page about any files that failed to load. You can control this with the show_detailed_errors
parameter. Detailed error messages will appear below the general error message. This only applies if continue_after_error
is false
(the default).
Detailed error messages can be useful when testing and debugging your experiment. If show_detailed_errors
is true
, then if one or more loading errors occurs before the max_load_time
is reached, then the error page will also contian a list of the file(s) that produced an error, along with error information (if there is any). Note that this may not be a complete list, because it will only report any errors that occurred before the max_load_time
was reached. If there are no file loading errors but preloading hasn't finished before the max_load_time
, then detailed error message will just tell you that loading timed out.
var preload_trial = {\n type: jsPsychPreload,\n auto_preload: true,\n // show details of any file loading errors and/or loading time out\n show_detailed_errors: true \n}\n
"},{"location":"overview/media-preloading/#options-for-handling-errors","title":"Options for handling errors","text":"If continue_after_error
is true
, then the experiment will not stop if one or more files fails to load. Instead, the trial will end and the experiment will continue. However, the preload trial data will contain a property called success
, which is whether or not all files were loaded successfully, timeout
, which is whether or not the files loaded successfully before the max_load_time
. The preload trial data will also contain lists of any image
, audio
, and video
files that failed to load. This gives you the option to continue the experiment after preloading fails and use the preload trial data decide what to do next. For instance, you may decide to skip the trials that use the stimuli files that failed to load, or try loading the failed files again. Another option is to simply end the experiment when preloading fails, but send the data back to your server so that you have more information about the loading failure.
var preload_trial = {\n type: jsPsychPreload,\n auto_preload: true,\n message: 'Please wait while the experiment loads...',\n // don't stop the experiment if there are file loading errors or if loading times out\n continue_after_error: true \n}\n\nvar save_data = {\n type: jsPsychCallFunction,\n async: true,\n func: function(done){\n var data = jsPsych.data.get().json();\n save_data(data, function() {done()})\n }\n}\n\n// the experiment will stop here, since there are no valid key choices or trial duration \nvar fail_message = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'The experiment failed to load. Please contact the researcher.',\n choices: \"NO_KEYS\",\n trial_duration: null \n}\n\nvar if_loading_fails = {\n timeline: [save_data, fail_message],\n conditional_function: function() {\n if (jsPsych.data.getLastTrialData()[0].values().success) {\n // preloading was successful, so skip this conditional timeline\n // and move on with the experiment\n return false;\n } else {\n // preloading failed, so run this conditional timeline:\n // save the data to the server and show the fail message\n return true;\n }\n }\n}\n\n// ... rest of experiment\n\njsPsych.run([preload_trial, if_loading_fails, ... ])\n
The preload
plugin's on_success
and on_error
callback functions provide another way of tracking preloading progress and handling file loading errors. These functions are called after any file either loads successfully or produces an error, respectively. These functions receive a single argument, which is the path of the file (string) that loaded or produced an error.
var file_load_count = 0;\nvar file_error_count = 0;\n\nvar preload_trial = {\n type: jsPsychPreload,\n auto_preload: true,\n on_error: function(file) {\n file_error_count++;\n console.log('Error: ',file);\n },\n on_success: function(file) {\n file_load_count++;\n console.log('Loaded: ',file);\n }\n};\n
Note that there's no guarantee that any/all files will trigger one of these two callback functions, because they are cancelled after the preload
trial ends. For instance, if a file takes longer to load then the max_load_time
, then the preload
trial will end due to timing out, and the on_success
and on_error
callbacks for any in-progress files will be cancelled.
"},{"location":"overview/mturk/","title":"Integrating with Mechanical Turk","text":"A common use of jsPsych is to build an online experiment and find participants using Mechanical Turk. Once an experiment is available through a web server and data is being saved on the server, connecting the experiment with Mechanical Turk takes only a few additional steps. jsPsych has some built-in functionality to assist with this process.
"},{"location":"overview/mturk/#the-jspsychturk-module","title":"The jsPsych.turk module","text":"The jsPsych.turk module contains functions that are relevant for experiments running on Mechanical Turk.
"},{"location":"overview/mturk/#creating-an-advertisement-page","title":"Creating an advertisement page","text":"When potential participants view your experiment on Mechanical Turk, they will be able to see a single webpage before deciding whether or not to accept the HIT (start the experiment). This first page is often used as an advertisement for the experiment, similar to posting a flier in a department hallway. The important thing to remember about this page is that potential participants will be able to interact with it even if they haven't accepted the HIT. Therefore, it can be useful to change the content of the page depending on whether the HIT has been accepted or not. This is relatively easy to do:
<div id=\"experiment_link\">You must accept the HIT to begin the experiment</div>.\n\n<script>\n// jsPsych has a method turkInfo() which can determine whether or not the\n// HIT has been accepted.\nvar turkInfo = jsPsych.turkInfo();\n\n// turkInfo.previewMode is true in two cases: when the HIT has not been\n// accepted yet OR when the page is viewed outside of mechanical turk.\n// The second property, outsideTurk, is true when the page is viewed\n// outside of mechanical turk, so together, the statement will be true\n// only when in Turk and when the HIT is not accepted yet.\nif(!turkInfo.previewMode && !turkInfo.outsideTurk) {\n document.querySelector('#experiment_link').innerHMTL = '<a href=\"link_to_experiment.html\" target=\"_blank\">Click Here to Start Experiment</a>';\n}\n</script>\n
One important issue with advertisement pages is that they must be served using the https protocol, which requires having an SSL certificate on the web server hosting the page. Instructions for how to do this vary depending on what kind of server you are using, so the best advice is to simply Google for instructions on how to acquire and install an SSL certificate on your particular server.
"},{"location":"overview/mturk/#getting-the-worker-id","title":"Getting the worker ID","text":"Every account on Mechanical Turk is given a unique identification string. Recording this ID is a useful way to keep track of who is doing your experiment. In particular, while Turk has built in tools for preventing the same person from doing a HIT more than once, there may be cases where you don't want participants to complete related experiments. If you store the worker ID of every person who starts an experiment in a database, then you can exclude people by running a query on the database to check for the ID. jsPsych can get the workerID, assignmentID, and hitID with the turkInfo method.
var turkInfo = jsPsych.turk.turkInfo();\n\n// workerID\nturkInfo.workerId\n\n// hitID\nturkInfo.hitId\n\n// assignmentID\nturkInfo.assignmentId\n
Recording the workerId at the start of the experiment is also a good way to track dropouts.
"},{"location":"overview/mturk/#submitting-results-to-mechanical-turk","title":"Submitting results to Mechanical Turk","text":"If you are running a HIT on Mechanical Turk using the ExternalQuestion template, then you'll need to provide a way for participants to indicate that they have completed the HIT. (If you are using another template, then the template will provide this code for you). jsPSych makes this a relatively easy task. A common strategy for external HITs is to display an HTML page on the Mechanical Turk website that links to your HIT. Participants click the link, which opens the actual experiment content in a new browser window or tab, allowing the experiment to take up the whole browser window instead of just the iframe that displays content on Mechanical Turk.
On this page, you might include a submit button for workers to indicate that they have finished the experiment. The page would look something like this:
<p>Enter the code you were given:</p>\n<input type=\"text\" id=\"code\"></input>\n<button onclick=\"sendData();\">Submit HIT</button>\n\n<script>\nfunction sendData() {\n jsPsych.turk.submitToTurk({\n code: document.getElementById('code').value\n });\n}\n</script>\n
When workers click the button, the contents of the code
text field will be sent to Mechanical Turk, and you'll be able to view the participants and the codes that they entered in the Mechanical Turk GUI. You can then approve or reject work using the Mechanical Turk website.
"},{"location":"overview/mturk/#limitations","title":"Limitations","text":"jsPsych is not designed to communicate with the Mechanical Turk API in a comprehensive manner. If you are looking for software to help you post and manage HITs, then you may want to look at PsiTurk. jsPsych and PsiTurk complement each other nicely, and there is an example of combining the two platforms on PsiTurk's experiment exchange.
"},{"location":"overview/plugins/","title":"Plugins","text":"In jsPsych, plugins define the kinds of trials or events that should occur during the experiment. Some plugins define very general events, like displaying a set of instructions pages, displaying an image and recording a keyboard response, or playing a sound file and recording a button response. Other plugins are more specific, like those that display particular kinds of stimuli (e.g., a circular visual search array), or run a specific version of particular kind of task (e.g., the Implicit Association Test). Part of creating an experiment with jsPsych involves figuring out which plugins are needed to create the tasks you want your participants to perform.
Plugins provide a structure for a particular trial or task, but often allow for significant customization and flexibility. For example, the image-keyboard-response plugin defines a simple structure for showing an image and collecting a keyboard response. You can specify the what the stimulus is, what keys the participant is allowed to press, how long the stimulus should be on the screen, how long the participant has to respond, and so on. Many of these options have reasonable default values; even though the image plugin has many different parameters, you only need to specify the image stimulus in order to use it. Each plugin has its own documentation page, which describes what the plugin does, what options are available, and what kind of data it collects.
"},{"location":"overview/plugins/#using-a-plugin","title":"Using a plugin","text":"To use a plugin, you'll need to load the plugin's JavaScript file in your experiment's HTML page. All jsPsych experiments also need to load the \"jsPsych.js\" file.
<head>\n <script src=\"https://unpkg.com/jspsych@8.1.0\" type=\"text/javascript\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\" type=\"text/javascript\"></script>\n</head>\n
Once a plugin is loaded, you can use JavaScript to define a trial that uses that plugin. All jsPsych trials need a type
parameter, which tells jsPsych what plugin to use to run the trial. The trial's type
is similar to the plugin name, but it always starts with \"jsPsych\" and is written in camel case rather than with dashes between the words. The trial's type
parameter should NOT be a string (i.e., no quotes around the type
value). Here are some examples of plugin names and types:
Plugin name Type image-keyboard-response jsPsychImageKeyboardResponse fullscreen jsPsychFullscreen webgazer-init-camera jsPsychWebgazerInitCamera The following JavaScript code defines a trial using the image-keyboard-response
plugin to display an image file. This trial uses the default values for valid keys, stimulus duration, trial duration, and other parameters.
var image_trial = {\n type: jsPsychImageKeyboardResponse, \n stimulus: 'images/happy_face.jpg'\n}\n
You can override any default parameter values by adding them into your trial object. Here's an example of overriding the default values for trial_duration
and post_trial_gap
:
var image_trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'images/happy_face.jpg',\n trial_duration: 3000,\n post_trial_gap: 2000\n}\n
"},{"location":"overview/plugins/#parameters-available-in-all-plugins","title":"Parameters available in all plugins","text":"Each plugin specifies its own set of parameters. Check the documentation for a plugin to see what parameters are available and what they do.
There is also a set of parameters that can be specified for any plugin:
Parameter Type Default Value Description data object undefined An object containing additional data to store for the trial. See the Data page for more details. post_trial_gap numeric null Sets the time, in milliseconds, between the current trial and the next trial. If null, there will be no gap. on_start function function(){ return; }
A callback function to execute when the trial begins, before any loading has occurred. See the Event-Related Callbacks page for more details. on_finish function function(){ return; }
A callback function to execute when the trial finishes, and before the next trial begins. See the Event-Related Callbacks page for more details. on_load function function(){ return; }
A callback function to execute when the trial has loaded, which typically happens after the initial display of the plugin has loaded. See the Event-Related Callbacks page for more details. css_classes string null A list of CSS classes to add to the jsPsych display element for the duration of this trial. This allows you to create custom formatting rules (CSS classes) that are only applied to specific trials. For more information and examples, see the Controlling Visual Appearance page and the \"css-classes-parameter.html\" file in the jsPsych examples folder. save_trial_parameters object {}
An object containing any trial parameters that should or should not be saved to the trial data. Each key is the name of a trial parameter, and its value should be true
or false
, depending on whether or not its value should be saved to the data. If the parameter is a function that returns the parameter value, then the value that is returned will be saved to the data. If the parameter is always expected to be a function (e.g., an event-related callback function), then the function itself will be saved as a string. For more examples, see the \"save-trial-parameters.html\" file in the jsPsych examples folder. save_timeline_variables boolean or array false
If set to true
, then all timeline variables will have their current value recorded to the data for this trial. If set to an array, then any variables listed in the array will be saved. record_data boolean true
If set to false
, then the data for this trial will not be recorded."},{"location":"overview/plugins/#the-data-parameter","title":"The data parameter","text":"The data
parameter allows you to add additional properties to the trial data. This can be useful for storing properties of the trial that are not directly apparent from the values that the plugin records. The data
parameter value must be an object that contains key-value pairs.
A simple example is the Flanker Task. In this experiment, participants respond to the direction of a central arrow by pressing a key to the left for a left-pointing arrow (<) and a key to the right for a right-pointing arrow (>). The arrow appears in the center of flankers, or arrows that the participant should ignore. Those flankers can be congruent (>>>>>) or incongruent (<<><<).
A trial for the Flanker Task written with jsPsych might look like this:
var trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<<<<<',\n choices: ['f','j'],\n data: {\n stimulus_type: 'congruent',\n target_direction: 'left'\n }\n}\n
Note the use of the data parameter to add a property stimulus_type
with the value congruent
and a property target_direction
with the value left
. Having these properties recorded directly in the data simplifies data analysis, making it easy to aggregate data by stimulus_type
and/or target_direction
.
"},{"location":"overview/plugins/#the-post_trial_gap-iti-parameter","title":"The post_trial_gap (ITI) parameter","text":"The default inter-trial interval (ITI) in jsPsych is 0 ms. This can be adjusted at the experiment-wide level by changing the default_iti
parameter in initJsPsych()
.
The ITI can also be controlled at the trial level through the post_trial_gap
parameter. Setting this parameter to a positive integer x will cause a blank screen to display after the trial for x milliseconds. Setting this parameter for a trial will override the default_iti
value set in initJsPsych
.
var trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'There will be a 1.5 second blank screen after this trial.',\n post_trial_gap: 1500\n}\n
"},{"location":"overview/plugins/#the-on_start-parameter","title":"The on_start parameter","text":"Immediately before a trial runs, there is an opportunity to run an arbitrary function through the on_start
event handler. This event handler is passed a single argument containing an editable copy of the trial parameters. This function can therefore be used to alter the trial based on the state of the experiment, among other uses.
// when this trial runs, the on_start function will change the trial's stimulus and data parameters,\n// so the trial will display an incongruent Flanker stimulus with a right-facing central arrow\nvar trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<<<<<',\n choices: ['f','j'],\n data: {\n stimulus_type: 'congruent',\n target_direction: 'left'\n },\n on_start: function(trial){\n trial.stimulus = '<<><<';\n trial.data.stimulus_type = 'incongruent';\n trial.data.target_direction = 'right';\n }\n}\n
"},{"location":"overview/plugins/#the-on_finish-parameter","title":"The on_finish parameter","text":"After a trial is completed, there is an opportunity to run an arbitrary function through the on_finish
event handler. This function is passed a single argument containing an editable copy of the data recorded for that trial. This function can therefore be used to update the state of the experiment based on the data collected, or modify the data collected.
The on_finish
function can be useful to calculate new data properties that were unknowable at the start of the trial. For example, with the Flanker Task example above, the on_finish
function could check the response and use to this information to add a new property to the data called correct
, which is either true
or false
.
// in addition to all of the standard data collected for this trial, \n// this on_finish function adds a property called 'correct' \n// which is either 'true' or 'false'\n// depending on the response that was made\nvar trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<<<<<',\n choices: ['f','j'],\n data: {\n stimulus_type: 'congruent',\n target_direction: 'left',\n correct_response: 'f'\n },\n on_finish: function(data){\n if(jsPsych.pluginAPI.compareKeys(data.response, data.correct_response)){\n data.correct = true;\n } else {\n data.correct = false;\n }\n }\n}\n
"},{"location":"overview/plugins/#the-on_load-parameter","title":"The on_load parameter","text":"The on_load
callback function will trigger once the trial has completed loading. For most plugins, this will occur once the display has been initially updated but before any user interactions or timed events (e.g., animations) have occurred. This can be useful for changing various aspects of the page elements and their properties that would otherwise require modifying the plugin file.
var trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'imgA.png',\n on_load: function() {\n // this will change the src attribute of the image after 500ms\n setTimeout(function(){\n document.querySelector('img').src = 'imgB.png'\n }, 500);\n }\n};\n
"},{"location":"overview/plugins/#the-css_classes-parameter","title":"The css_classes parameter","text":"The css_classes
parameter allows you to add an array of CSS class names to the jsPsych display element on that specific trial. This allows you to create custom style and formatting rules that are only applied to specific trials. If you want CSS rules that only apply to specific elements during a trial, you can use additional CSS selectors.
<style>\n .flanker-stimulus {\n font-size: 500%;\n }\n .flanker-stimulus #prompt {\n font-size: 18px;\n }\n .fixation {\n font-size: 80px;\n }\n</style>\n<script>\n var fixation_trial = {\n type: jsPsychHtmlKeyboardResponse,\n choices: \"NO_KEYS\",\n stimulus: '+',\n css_classes: ['fixation']\n };\n var flanker_trial = {\n type: jsPsychHtmlKeyboardResponse,\n choices: [\"ArrowLeft\", \"ArrowRight\"],\n stimulus: '>>>>>',\n prompt: '<span id=\"prompt\">Press the left or right arrow key.</span>',\n css_classes: ['flanker-stimulus']\n };\n</script>\n
"},{"location":"overview/plugins/#the-save_trial_parameters-parameter","title":"The save_trial_parameters parameter","text":"The save_trial_parameters
parameter allows you to tell jsPsych what parameters you want to be saved to the data. This can be used to override the parameter values that the plugin saves by default. You can add more parameter values to the data that are not normally saved, or remove parameter values that normally are saved. This can be especially useful when the parameter value is dynamic (i.e. a function) and you want to record the value that was used during the trial.
var trial = {\n type: jsPsychHtmlButtonResponse,\n stimulus: '<p style=\"color: orange; font-size: 48px; font-weight: bold;\">BLUE</p>',\n choices: function() {\n return jsPsych.randomization.shuffle(['Yes','No']);\n },\n post_trial_gap: function() {\n return jsPsych.randomization.sampleWithoutReplacement([200,300,400,500],1)[0];\n },\n save_trial_parameters: {\n // save the randomly-selected button order and post trial gap duration to the trial data\n choices: true,\n post_trial_gap: true,\n // don't save the stimulus\n stimulus: false\n }\n}\n
Note
You cannot remove the trial_index
value from the trial data.
"},{"location":"overview/plugins/#data-collected-by-all-plugins","title":"Data collected by all plugins","text":"Each plugin defines what data is collected on the trial. The documentation for each plugin specifies what information will be stored in the trial data.
In addition to the data collected by a plugin, there is a default set of data that is collected on every trial.
Name Type Value trial_type string The name of the plugin used to run the trial. trial_index numeric The index of the current trial across the whole experiment. time_elapsed numeric The number of milliseconds between the start of the experiment and when the trial ended."},{"location":"overview/plugins/#creating-a-new-plugin","title":"Creating a new plugin","text":"See our developer's guide for plugins for information about how to create a new plugin.
"},{"location":"overview/progress-bar/","title":"Automatic Progress Bar","text":"jsPsych can show a progress bar at the top of the experiment page indicating the participant's overall completion progress. The progress bar is rendered outside the jsPsych display element, and it requires the jspsych.css
file to be loaded on the page. As of version 6.0, the progress bar looks like this:
To show the progress bar, set the show_progress_bar
option in initJsPsych
to true
:
const jsPsych = initJsPsych({\n show_progress_bar: true\n});\n
The progress bar automatically updates after every trial.
"},{"location":"overview/progress-bar/#manual-control","title":"Manual Control","text":"The progress bar can also be manually controlled by setting jsPsych.progressBar.progress
. The value of jsPsych.progressBar.progress
should be a number between 0 and 1. For example, to set the progress bar to 85% full, you would do this:
const trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Almost done...',\n on_finish: function(){\n jsPsych.progressBar.progress = 0.85; // set progress bar to 85% full.\n }\n}\n
You can also get the current value of the progress bar as jsPsych.progressBar.progress
const proportion_complete = jsPsych.progressBar.progress;\n
If you are going to use manual progress bar control, you may want to disable the automatic progress bar updates by setting the auto_update_progress_bar
property in initJsPsych()
to false
.
const jsPsych = initJsPsych({\n show_progress_bar: true,\n auto_update_progress_bar: false\n});\n
Here's a complete example showing how to use these functions and initJsPsych()
settings to manually update the progress bar:
const jsPsych = initJsPsych({\n show_progress_bar: true,\n auto_update_progress_bar: false\n});\n\nconst n_trials = 5;\n\nconst start = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Press any key to start!',\n on_start: function() {\n // set progress bar to 0 at the start of experiment\n jsPsych.progressBar.progress = 0\n }\n};\n\nconst trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'This is a trial!',\n on_finish: function() {\n // at the end of each trial, update the progress bar\n // based on the current value and the proportion to update for each trial\n var curr_progress_bar_value = jsPsych.progressBar.progress;\n jsPsych.progressBar.progress = curr_progress_bar_value + (1/n_trials)\n }\n};\n\nconst trials = {\n timeline: [trial],\n repetitions: n_trials\n};\n\nconst done = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Done!'\n};\n\njsPsych.run([start, trials, done]);\n
"},{"location":"overview/progress-bar/#custom-text","title":"Custom Text","text":"By default, jsPsych adds the text \"Completion Progress\" to the left of the progress bar. You can specify custom text using the message_progress_bar
parameter in initJsPsych
.
// support for different spoken languages\nconst jsPsych = initJsPsych({\n show_progress_bar: true,\n message_progress_bar: 'Porcentaje completo'\n});\n
// no message\nconst jsPsych = initJsPsych({\n show_progress_bar: true,\n message_progress_bar: ''\n});\n
"},{"location":"overview/prolific/","title":"Integrating with Prolific","text":"Prolific is a participant recruitment service aimed at research. Integrating a jsPsych experiment with Prolific requires capturing the participant's ID and sending the participant to a completion URL at the end of the experiment.
"},{"location":"overview/prolific/#capturing-the-participant-id-study-id-and-session-id","title":"Capturing the Participant ID, Study ID, and Session ID","text":"When creating a study on Prolific you must provide the URL to your study. You can host your jsPsych experiment however you'd like - some options are discussed in the Running Experiments documentation page. Once you've got a URL to your experiment, you can enter that in the study link section of Prolific. Then, click the option to record Prolific IDs via URL parameters.
This will append information about the participant's prolific ID (PROLIFIC_PID
), the study's ID (STUDY_ID
), and the session ID (SESSION_ID
) to the URL that participants use to access your experiment.
We can capture these variables with jsPsych, and add them to jsPsych's data. This can be done anywhere in your code. This code does not need to run as part of your experiment timeline.
<script>\n var jsPsych = initJsPsych();\n\n // capture info from Prolific\n var subject_id = jsPsych.data.getURLVariable('PROLIFIC_PID');\n var study_id = jsPsych.data.getURLVariable('STUDY_ID');\n var session_id = jsPsych.data.getURLVariable('SESSION_ID');\n\n jsPsych.data.addProperties({\n subject_id: subject_id,\n study_id: study_id,\n session_id: session_id\n });\n\n // create the rest of the experiment\n var timeline = [...]\n\n jsPsych.run(timeline)\n</script>\n
"},{"location":"overview/prolific/#completing-the-experiment","title":"Completing the Experiment","text":"When the experiment is complete, Prolific requires that you send the participant to a specific URL that marks the session as complete on Prolific's server. The link is provided to you by Prolific in the study completion section of the setup.
You can accomplish this in a couple different ways.
Warning
It's important that you've saved all the data from your experiment before the participant returns to Prolific. Make sure that any server communication has completed prior to redirecting the participant. One way to do this is by using the async features of the call-function
plugin (example).
"},{"location":"overview/prolific/#participant-clicks-a-link","title":"Participant clicks a link","text":"One option is to create a trial that contains a link that the participant clicks to end the experiment and return to Prolific. For example, the html-keyboard-response
plugin can be used to display text that includes a link. This could go on a debriefing page.
Here's an example trial that could be used. Note that choices
is set to \"NO_KEYS\"
, which will prevent the participant from continuing past this point in the experiment.
var final_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `<p>You've finished the last task. Thanks for participating!</p>\n <p><a href=\"https://app.prolific.co/submissions/complete?cc=XXXXXXX\">Click here to return to Prolific and complete the study</a>.</p>`,\n choices: \"NO_KEYS\"\n}\n
"},{"location":"overview/prolific/#automatically-redirect","title":"Automatically redirect","text":"A second option is to automatically redirect the participant to the completion URL when the experiment is finished. You could do this in a number of places in the jsPsych timeline.
Here's an example using the on_finish
event for the entire experiment.
var jsPsych = initJsPsych({\n on_finish: function(){\n window.location = \"https://app.prolific.co/submissions/complete?cc=XXXXXXX\"\n }\n});\n
"},{"location":"overview/record-browser-interactions/","title":"Record browser interactions","text":"Participants in an online experiment have the freedom to multitask while performing an experiment. jsPsych automatically records information about when the user clicks on a window that is not the experiment, and about when the user exits full screen mode if the experiment is running in full screen mode. This data is stored separately from the main experiment data, and can be accessed with jsPsych.data.getInteractionData().
Each time the user leaves the experiment window, returns to the experiment window, exits full screen mode, or enters full screen mode, the event is recorded in the interaction data. Each event has the following structure.
Event recording stops when the experiment ends.
{\n event: 'focus', // 'focus' or 'blur' or 'fullscreenenter' or 'fullscreenexit'\n trial: 12, // the index of the active trial when the event happened\n time: 1240543 // time in ms since the start of the experiment\n}\n
You can specify a custom function, in the initJsPsych() method, that is called whenever one of these events occurs
initJsPsych({\n on_interaction_data_update: function(data) {\n console.log(JSON.stringify(data))\n }\n});\n
"},{"location":"overview/running-experiments/","title":"Running Experiments","text":"You can run your jsPsych experiment:
Offline, by opening the HTML file directly in the browser using the file://
protocol.
Online, by hosting the files on a web server using the http://
or https://
protocol.
The way that you run your experiment will have consequences for certain aspects about how the experiment works, and what your experiment will be able to do. This page explains what you need to know about both of these options.
Info
If you are looking for a tool to automate deployment-related tasks, check out the jsPsych Builder CLI utility. It automatically bundles scripts and style sheets, configures media preloading, and yields a zip file that contains all files for deployment (online or offline). jsPsych Builder can also directly build JATOS experiment files (.jzip) that you can upload to a JATOS server (see this section below for more info about JATOS and other server options).
"},{"location":"overview/running-experiments/#offline","title":"Offline","text":"You can run your jsPsych experiment offline by opening the HTML file directly in a web browser, for instance by double-clicking on it. This uses the file://
protocol. It's usually the fastest and easiest way to run through an experiment, and is very useful while writing and testing the code.
At some point you will need to move your experiment files onto a server and send the data to a database, since this is how you will ultimately collect the data (unless you're planning to collect data on your local computer). There are some important differences between the way the experiment runs offline compared to online via a web server.
Note that, unless noted, here we're using the word \"server\" to mean either a local server (which runs on your computer and only makes the experiment files available from within that computer, and is often used during development), or a remote server (which does not run on your computer and does share your experiment files over the internet).
"},{"location":"overview/running-experiments/#cross-origin-requests-cors-and-safe-mode","title":"Cross-origin requests (CORS) and safe mode","text":"Web browsers have a security policy called cross-origin resource sharing (CORS) that determines whether the webpage can request files that come from a different origin (i.e. protocol, host/domain, and port). This isn't a problem when your study runs online, because in that case your experiment files all have the same origin. However, when you run your experiment offline, the CORS policy blocks some jsPsych features that require loading local files. If your experiment uses these features, then CORS errors will prevent the experiment from running.
To prevent these errors, jsPsych uses a 'safe mode' when it detects that the HTML page is running via the file://
protocol, and if so, automatically disables the features that don't work in that context. Specifically, when a jsPsych experiment runs offline:
- Web Audio is disabled (even if
use_webaudio
is set to true
in initJsPsych
). The WebAudio API option is used by default because it allows more precise measurement of response times relative to the onset of the audio. But because WebAudio doesn't work offline, audio will be played using HTML5 audio instead. This is equivalent to setting use_webaudio
to false
in initJsPsych
. - Video preloading is disabled (both automatic and manual preloading via the
preload
plugin). Videos will still play when you run your experiment offline, but they will load during the experiment, which might cause noticeable delays before video playback starts.
This safe mode feature is controlled by the override_safe_mode
parameter in initJsPsych
, which defaults to false
. If you leave this setting as the default, then you won't need to worry about CORS errors while running your experiment offline, or remembering to change your initJsPsych
settings when you move the experiment online.
It's possible to override jsPsych's safe mode by setting override_safe_mode
to true
in initJsPsych
. One reason you might do this is if you've disabled web security features in your browser (see here and here for instructions in Chrome), which is safe to do if you know what you're doing. If your experiment does not use Web Audio or preloaded videos, then jsPsych's safe mode feature will not have any effect.
The override_safe_mode
parameter also has no effect when your experiment is running online a web server, because the page will be loaded via the http://
or https://
protocol.
"},{"location":"overview/running-experiments/#media-loading","title":"Media loading","text":"While running your experiment offline, any media files are likely to load very quickly because they are stored on your own computer's disk. Therefore you may not notice problems with file loading delays while running your experiment locally (either offline or on a local server) because the files will load fast enough that they never cause disruption. However, when your experiment is hosted on a remote server, the files will need to be transferred over the internet, which means they will take longer to load - in some cases much longer. Loading delays are most noticeable with media files: images, audio, and video. As explained on the Media Preloading page, loading delays during your experiment can cause problems for stimulus display and response times.
It is important to test your experiment to ensure that any media files are preloading successfully and not being requested again during the experiment. You can use the Network tab in your browser's developer tools to see when files are loaded and to simulate a slow internet connection (see here for Chrome Network tab documentation). If you are preloading many and/or large files, such as videos, you may want to increase the max_load_time
parameter in the preload plugin
so that participants with slow/unreliable internet connections will be able to take part in your experiment.
"},{"location":"overview/running-experiments/#permanent-data-storage","title":"Permanent data storage","text":"As explained in the Data Storage, Aggregation, and Manipulation page, jsPsych stores information in the participant's browser. While running an experiment offline, you won't be able to send the data to a database. However you can still see the data that jsPsych collects by saving it as a local file (using jsPsych.data.get().localSave
), displaying it in the webpage at the end of the experiment (using jsPsych.data.displayData
), or printing it to the browser's console (using console.log
).
Permanent data storage is also necessary when the code that runs the experiment depends on information that can't be known in advance, and that changes throughout data collection. Some common examples of this in cognitive behavioral research are version counterbalancing, where the experiment code needs to access and update the history of version assignment in order to determine which version should be assigned, and multi-session/training studies, where the experiment might need to access and update information about each participant like their current session number, task difficulty level, etc.
Doing these things in an automated way requires the use of a server. While developing and testing your experiment offline, you might choose to simulate some of these things and then implement them properly once you move your experiment online. For instance, you could randomize instead of counterbalancing version assignment:
var versions = [1,2];\nvar random_version = jsPsych.randomization.sampleWithoutReplacement(versions,1)[0];\n
And use URL query parameters to pass in variables like session number and difficulty level:
// add the variables onto the end of the URL that appears in the browser when you open the file \n// e.g., file:///C:/my_experiment.html?id=1&sess=2&diff=3\nvar participant_id = jsPsych.data.getURLVariable('id');\nvar session = jsPsych.data.getURLVariable('sess');\nvar difficulty = jsPsych.data.getURLVariable('diff');\n
"},{"location":"overview/running-experiments/#online","title":"Online","text":""},{"location":"overview/running-experiments/#hosting-the-experiment-and-saving-the-data","title":"Hosting the Experiment and Saving the Data","text":"jsPsych is a front-end JavaScript library that runs entirely on the participant's computer. To run a jsPsych experiment over the internet, the files need to be hosted on a public web server so that participants can access the experiment using a web browser. When the participant completes the experiment in the browser, all of the data that jsPsych collects is stored on the participant's computer in the browser's memory. To get access to this data, it needs to be sent from the participant's browser back to the web server and stored in a database or a file.
To be maximally flexible, jsPsych doesn't provide a single built-in solution for the web server component of your experiment. This makes jsPsych compatible with a wide range of hosting services and tools, allowing researchers to choose the web server option that best suit their needs.
Some options for running your jsPsych experiment online include:
- Cognition.run - A free service designed specifically for hosting jsPsych experiments, with an easy-to-use interface.
- JATOS - A free program that runs on your own server and provides a GUI for setting up experiments and accessing the data. Offers lots of features for creating more complex experiments and managing multiple researchers.
- Pavlovia - A paid hosting service for web-based experiments, run by the PsychoPy team. Experiment files are managed on a GitLab repository. Participants will access the experiment through a link to Pavlovia.
- PsiTurk - Python-based program to help you host your experiment on your own computer and collect data from MTurk (see Recruiting Participants below). Relatively easy for a DIY option.
- Pushkin - A set of tools to help you set up your own virtual laboratory for online experiments. This option differs from the others in that it helps you set up a complete website that may contain many different experiments, information about the laboratory, participant logins, and other features that are targeted at hosting large-scale data collection efforts.
- Full DIY - You can setup your own web server and database and handle the communication yourself. Traditional web server 'stacks' include LAMP/LEMP (Linux operating system, Apache or Nginx server application, MySQL database, and PHP programming language). Other common web server frameworks include Flask (Python) and Node.js (JavaScript).
"},{"location":"overview/running-experiments/#recruiting-participants","title":"Recruiting Participants","text":"Once your experiment is running online, you could recruit participants in the same way that you would for lab-based studies. For instance, if your institution uses SONA, you can advertise your web-based study link on SONA. SONA allows you to automactically embed a unique ID in online study URLs, which you can then save in your data using jsPsych's URL query parameters function. SONA will also generate a completion URL that you can redirect participants to at the end of the study, and this will mark them as having completed the study in SONA.
To take full advantage of hosting an experiment online, many researchers advertise their experiments more widely. Social media and other media outlets provide one option for reaching a large number of potential participants. There are also some commercial platforms that you can use to advertise your study and pay anonymous online participants. These recruitment platforms charge a fee for use. The advantages of these platforms are that they handle the participant payments and allow you to specify pre-screening criteria. The most commonly used recruitment platforms in online behavioral research are:
- Prolific: An online labor market designed specifically for web-based research.
- Amazon Mechanical Turk (MTurk): An online labor market designed for advertising paid 'human intelligence tasks'. This service was designed for use by commercial businesses but has been used by behavioral researchers for many years.
Like SONA, Prolific and MTurk use URL query parameters to get participant information, and redirection to specific URLs to mark participants as having finished the study. jsPsych includes convenience functions for interacting with MTurk participants. Information about integrating with Prolific can be found in the researcher support section of their website.
"},{"location":"overview/simulation/","title":"Simulation Modes","text":"Added in 7.1
Simulation mode allows you run your experiment automatically and generate artificial data.
Info
For a detailed description of the motivation behind simulation mode and a discussion of different use cases of simulation mode, see de Leeuw, J.R., Gilbert, R.A., Petrov, N.B., & Luchterhandt, B. (2022). Simulation behavior to help researchers build experiments. Behavior Research Methods, https://doi.org/10.3758/s13428-022-01899-0.
A pre-print version is available on PsyArXiv.
"},{"location":"overview/simulation/#getting-started","title":"Getting Started","text":"To use simulation mode, replace jsPsych.run()
with jsPsych.simulate()
.
jsPsych.simulate(timeline);\n
This will run jsPsych in the default data-only
simulation mode. To use the visual
simulation mode you can specify the second parameter.
jsPsych.simulate(timeline, \"data-only\");\njsPsych.simulate(timeline, \"visual\");\n
"},{"location":"overview/simulation/#what-happens-in-simulation-mode","title":"What happens in simulation mode","text":"In simulation mode, plugins call their simulate()
method instead of calling their trial()
method. If a plugin doesn't implement a simulate()
method, then the trial will run as usual (using the trial()
method) and any interaction that is needed to advance to the next trial will be required. If a plugin doesn't support visual
mode, then it will run in data-only
mode.
"},{"location":"overview/simulation/#data-only-mode","title":"data-only
mode","text":"In data-only
mode plugins typically generate resonable artificial data given the parameters specified for the trial. For example, if the trial_duration
parameter is set to 2,000 ms, then any response times generated will be capped at this value. Generally the default data generated by the plugin randomly selects any available options (e.g., buttons to click) with equal probability. Response times are usually generated by sampling from an exponentially-modified Gaussian distribution truncated to positive values using jsPsych.randomization.sampleExGaussian()
.
In data-only
mode, the plugin's trial()
method usually does not run. The data are simply calculated based on trial parameters and the finishTrial()
method is called immediately with the simulated data.
"},{"location":"overview/simulation/#visual-mode","title":"visual
mode","text":"In visual
mode a plugin will typically generate simulated data for the trial and then use that data to mimic the kinds of actions that a participant would do. The plugin's trial()
method is called by the simulation, and you'll see the experiment progress in real time. Mouse, keyboard, and touch events are simulated to control the experiment.
In visual
mode each plugin will generate simulated data in the same manner as data-only
mode, but this data will instead be used to generate actions in the experiment and the plugin's trial()
method will ultimately be responsible for generating the data. This can create some subtle differences in data between the two modes. For example, if the simulated data generates a response time of 500 ms, the data.rt
value will be exactly 500
in data-only
mode, but may be 501
or another slightly larger value in visual
mode. This is because the simulated response is triggered at 500
ms and small delays due to JavaScript's event loop might add a few ms to the measure.
"},{"location":"overview/simulation/#controlling-simulation-mode-with-simulation_options","title":"Controlling simulation mode with simulation_options
","text":"The parameters for simulation mode can be set using the simulation_options
parameter in both jsPsych.simulate()
and at the level of individual trials.
"},{"location":"overview/simulation/#trial-level-options","title":"Trial-level options","text":"You can specify simulation options for an individual trial by setting the simulation_options
parameter.
const trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<p>Hello!</p>',\n simulation_options: {\n data: {\n rt: 500\n }\n }\n}\n
Currently the three options that are available are data
, mode
, and simulate
.
"},{"location":"overview/simulation/#data","title":"data
","text":"Setting the data
option will replace the default data generated by the plugin with whatever data you specify. You can specify some or all of the data
parameters. Any parameters you do not specify will be generated by the plugin.
In most cases plugins will try to ensure that the data generated is consistent with the trial parameters. For example, if a trial has a trial_duration
parameter of 2000
but the simulation_options
specify a rt
of 2500
, this creates an impossible situation because the trial would have ended before the response at 2,500ms. In most cases, the plugin will act as if a response was attempted at 2500
, which will mean that no response is generated for the trial. As you might imagine, there are a lot of parameter combinations that can generate peculiar cases where data may be inconsistent with trial parameters. We recommend double checking the simulation output, and please alert us if you discover a situation where the simulation produces inconsistent data.
"},{"location":"overview/simulation/#mode","title":"mode
","text":"You can override the simulation mode specified in jsPsych.simulate()
for any trial. Setting mode: 'data-only'
will run the trial in data-only mode and setting mode: 'visual'
will run the trial in visual mode.
"},{"location":"overview/simulation/#simulate","title":"simulate
","text":"If you want to turn off simulation mode for a trial, set simulate: false
.
"},{"location":"overview/simulation/#functions-and-timeline-variables","title":"Functions and timeline variables","text":"The simulation_options
parameter is compatible with both dynamic parameters and timeline variables. Dynamic parameters can be especially useful if you want to randomize the data for each run of the simulation. For example, you can specify the rt
as a sample from an ExGaussian distribution.
const trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<p>Hello!</p>',\n simulation_options: {\n data: {\n rt: ()=>{\n return jsPsych.randomization.sampleExGaussian(500, 50, 1/100, true)\n }\n }\n }\n}\n
"},{"location":"overview/simulation/#experiment-level-options","title":"Experiment-level options","text":"You can also control the parameters for simulation by passing in an object to the simulation_options
argument of jsPsych.simulate()
.
const simulation_options = {\n default: {\n data: {\n rt: 200\n }\n }\n}\n\njsPsych.simulate(timeline, \"visual\", simulation_options)\n
The above example will set the rt
for any trial that doesn't have its own simulation_options
specified to 200
. This could be useful, for example, to create a very fast preview of the experiment to verify that everything is displaying correctly without having to wait through longer trials.
You can also specify sets of parameters by name using the experiment-level simulation options.
const simulation_options = {\n default: {\n data: {\n rt: 200\n }\n },\n long_response: {\n data: {\n rt: () => {\n return jsPsych.randomization.sampleExGaussian(5000, 500, 1/500, true)\n }\n }\n }\n}\n\nconst trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<p>This is gonna take a bit.</p>',\n simulation_options: 'long_response'\n}\ntimeline.push(trial);\n\njsPsych.simulate(timeline, \"visual\", simulation_options)\n
In the example above, we specified the simulation_options
for trial
using a string ('long_response'
). This will look up the corresponding set of options in the experiment-level simulation_options
.
We had a few use cases in mind with this approach:
- You could group together trials with similar behavior without needing to specify unique options for each trial.
- You could easily swap out different simulation options to test different kinds of behavior. For example, if you want to test that a timeline with a
conditional_function
is working as expected, you could have one set of simulation options where the data will cause the conditional_function
to evaluate to true
and another to false
. By using string-based identifiers, you don't need to change the timeline code at all. You can just change the object being passed to jsPsych.simulate()
. - In an extreme case of the previous example, every trial on the timeline could have its own unique identifier and you could have multiple sets of simulation options to have very precise control over the data output.
"},{"location":"overview/simulation/#current-limitations","title":"Current Limitations","text":"Simulation mode is not yet as comprehensively tested as the rest of jsPsych. While we are confident that the simulation is accurate enough for many use cases, it's very likely that there are circumstances where the simulated behavior will be inconsistent with what is actually possible in the experiment. If you come across any such circumstances, please let us know!
Currently extensions are not supported in simulation mode. Some plugins are also not supported. This will be noted on their documentation page.
"},{"location":"overview/style/","title":"Controlling Visual Appearance","text":"Your experiment's style and formatting comes from the CSS (cascading style sheet) rules that are stored in the jspsych.css file, and the browser's defaults. There are a few ways to change the style and formatting in your experiment. The method that you choose is partly a matter of personal preference. It might also depend on whether you want the style/formatting change(s) to apply to specific trials, to the whole experiment (HTML page), or across different experiments. This section discusses the different ways of incorporating CSS into your jsPsych experiment. You can also see this page about adding CSS to web pages to learn more.
"},{"location":"overview/style/#inline-css","title":"Inline CSS","text":"Whenever you're using a parameter that accepts an HTML-formatted string, you have the option to include inline CSS. Inline CSS is a way of adding style and formatting directly into a specific HTML element using its \"style\" attribute. This is a good option for when you want to make few and/or simple style changes to an HTML trial parameter.
To change an element's style using inline CSS, you can set the element's \"style\" attribute to a string that contains the CSS parameters that you want to change, along with the values that you want to use. The syntax is \" <parameter-name> : <parameter-value> ;\".
In the example below, the stimulus font size is set to 30px and the text color is set to red. These changes will only be applied to this stimulus text in this specific trial.
const trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<p style=\"font-size:30px;color:red;\">hello world!</p>'\n}\n
You can also use a dynamic parameter to combine inline CSS and trial-specific variables. This allows you to easily apply the same inline CSS to multiple trials. Here's an example using a dynamic stimulus parameter and timeline variables:
const trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: function() {\n const stim = `<p style=\"font-size:30px;font-weight:bold;\">${jsPsych.evaluatetimelineVariable('text')}</p>`;\n return stim;\n }\n}\nconst trial_procedure = {\n timeline: [trial],\n timeline_variables: [\n {text: 'Welcome'},\n {text: 'to'},\n {text: 'the'},\n {text: 'experiment!'}\n ]\n}\n
"},{"location":"overview/style/#adding-css-rules","title":"Adding CSS rules","text":"You may want to add a lot of different CSS changes to your experiment, re-use the same change(s) across lots of different trials, and/or separate the style/formatting from the HTML string. In these cases, you might find it useful to create CSS rules rather than using inline CSS.
Creating CSS rules is a lot like using inline CSS, except that you also need to use a CSS selector. This is because your CSS rules aren't attached to any specific HTML element (unlike inline CSS), so you need to tell the browser which element(s) the style rules should apply to. The syntax is \"css-selector { <parameter-name> : <parameter-value> ; }\".
In the example below, the CSS selector \"p\" tells the browser to apply the font size change to any text that is inside of a <p> element.
p {\n font-size: 30px;\n}\n
You can make more specific changes using CSS rules. The specificity will depend on the CSS selectors that are used. In addition to using the tag name (e.g. \"p\"), other common CSS selectors include the element's ID or class. If you are selecting an element using it's ID, then the CSS selector needs to have a # in front of the ID, e.g. \"#stimulus\". If you are selecting elements based on their class, then you need to include a . in front of the class, e.g. \".large-text\".
In the example below, the \"#stimulus\" CSS selector means that the width change will only affect elements with the \"stimulus\" ID, and the \".large-text\" CSS selector means that the font size change will only affect elements that have the \"large-text\" class.
#stimulus \n width: 300px;\n}\n.large-text {\n font-size: 200%;\n}\n
It is possible to create even more specific CSS selectors, for instance by combining tags, IDs, and/or classes. For example, let's say that you are showing feedback text to participants, and that this text is inside of a <p> tag. You could add the ID \"correct\" to the <p> element for correct response feedback, and the ID \"incorrect\" to the <p> element for incorrect response feedback. Then you can define separate styles for correct and incorrect feedback text like this:
p#incorrect {\n color: red;\n}\np#correct {\n color: green;\n}\n
See this page about CSS selectors for a complete reference of CSS selector patterns and their meanings.
"},{"location":"overview/style/#with-style-tags","title":"With style tags","text":"You can add CSS rules to your HTML page by putting them inside of <style> tags. These rules will be applied to your whole experiment. This method can be useful for making general changes to the way that your experiment looks.
In the example below, the default font size is set to 25px throughout the experiment. This will overrule the default font size of 18px that is set in the jspsych.css file.
<head>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <link rel=\"stylesheet\" href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\">\n <style> \n .jspsych-display-element {\n font-size: 25px;\n }\n </style>\n</head>\n
"},{"location":"overview/style/#with-a-stylesheet","title":"With a stylesheet","text":"CSS rules can also be applied to your experiment with a link to an external CSS file. This is the same method that is usually used to apply the style from jspsych.css to an experiment. These rules will be applied to your whole experiment. You may find it useful to use a custom stylesheet when you want to re-use the same CSS rules across multiple experiments (HTML files).
This example shows how to add a custom CSS file in addition to the styles provided in jspsych.css. In this example, the custom CSS file is called \"my_experiment_style.css\" and it is located in the same directory as your HTML file.
<head>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <link rel=\"stylesheet\" href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\">\n <link rel=\"stylesheet\" href=\"my_experiment_style.css\">\n</head>\n
Below are the some example contents of an external CSS file, like the \"my_experiment_style.css\" from the example above. This CSS will (1) change the page background color to black, (2) change the default font to 25px and white, and (3) limit the width of the page content so that it can only take up to 80% of its normal width.
body {\n background-color: black;\n}\n.jspsych-display-element {\n font-size: 25px;\n color: white;\n}\n.jspsych-content {\n max-width: 80%; \n}\n
Note
<style> tags are not used inside of an external CSS file.
"},{"location":"overview/style/#using-the-css_classes-trial-parameter","title":"Using the css_classes trial parameter","text":"CSS rules can also be applied in a trial-specific way using the css_classes
parameter. This parameter will apply one or more class to the <div> element that holds all of the jsPsych page content during that specific trial. This way you can treat CSS styles just like any other trial parameter.
You can use a static css_classes
parameter value if you always want to apply the same CSS rules to the trial. In the 'fixation' example below, separating the style rules from the stimulus
string makes the code a little bit 'cleaner', and this makes it easier to re-use the same style rules in other parts of the experiment.
<head>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <link rel=\"stylesheet\" href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\">\n <style> \n .fixation {font-size: 90px; font-weight: bold; color: gray;}\n </style>\n</head>\n<script>\nconst fixation = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '+',\n choices: \"NO_KEYS\",\n trial_duration: 500,\n css_classes: ['fixation']\n}\n// ...\n</script>\n
You may want the css_classes
parameter to vary across trials. If so, you can turn it into a dynamic parameter or use timeline variables (see examples below).
One thing to note about the css_classes
parameter is that it only adds the class(es) to the jspsych-content <div> element, which is the \"parent\" element that contains all of the experiment content. Often you'll want your CSS rules to be applied to other elements inside of this jspsych-content div. Sometimes your CSS rules will be \"inherited\" by all of the other jsPsych content inside of this parent <div>. For instance, in the fixation
example above, the CSS rules that change the font size, weight and color are applied to the parent <div> and automatically passed on to the stimulus text through inheritance.
There are two reasons why a CSS rule like the one above for fixation
may not work the way you expect:
-
Not all CSS properties are inherited from the parent element.
-
When a CSS property is inherited from the parent element, it will affect all elements in a given trial.
In these cases, you can change your CSS selector to make it more specific: add a space after class name, then add more CSS selectors to select the specific element(s) that you want to change.
Tip
To find out this more specific CSS selector, you can right-click on the element and select Inspect. In the inspector window, right-click on the property corresponding to the element and copy the selector. You might need to increase the trial's trial_duration
to give yourself enough time to inspect the elements on the page. See more tips for working with CSS below.
In the example below, the CSS selector .left-align #stimulus
selects the element with the ID \"stimulus\" that is inside of an element with the class \"left-align\".
<head>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <link rel=\"stylesheet\" href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\">\n <style> \n .left-align #stimulus {text-align: left; width: 600px;}\n .right-align #stimulus {text-align: right; width: 600px;}\n </style>\n</head>\n<script>\nconst trial_procedure = {\n timeline: [{\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<p id=\"stimulus\">This is the stimulus.</p>',\n prompt: '<p>This text will not be affected by the CSS classes '+\n 'because it does not have the \"stimulus\" ID.</p>',\n css_classes: jsPsych.timelineVariable('css_classes')\n }],\n timeline_variables: [\n {css_classes: ['left-align']},\n {css_classes: ['right-align']}\n ]\n}\n// ...\n</script>\n
It's also possible to pass multiple class names to the css_classes
parameter. This can be useful for creating conditions that involve crossing different style-related factors. This example shows you to combine two text alignment and two text color factors to produce four different stimulus conditions:
<head>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <link rel=\"stylesheet\" href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\">\n <style> \n .left-align #stimulus {text-align: left; width: 600px;}\n .right-align #stimulus {text-align: right; width: 600px;}\n .teal #stimulus {color: teal;}\n .purple #stimulus {color: purple;}\n </style>\n</head>\n<script>\nconst trial_procedure = {\n timeline: [{\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<p id=\"stimulus\">This is the stimulus.</p>',\n prompt: '<p>This text will not be affected by the CSS classes '+\n 'because it does not have the \"stimulus\" ID.</p>',\n css_classes: jsPsych.timelineVariable('css_classes'),\n data: {\n condition: jsPsych.timelineVariable('condition')\n }\n }],\n timeline_variables: [\n {css_classes: ['left-align','teal'], condition: 'left-teal'},\n {css_classes: ['right-align','teal'], condition: 'right-teal'},\n {css_classes: ['left-align','purple'], condition: 'left-purple'},\n {css_classes: ['right-align','purple'], condition: 'right-purple'}\n ]\n}\n// ...\n</script>\n
See the \"css-classes-parameter.html\" file in jsPsych's examples subfolder for more explanation and examples.
"},{"location":"overview/style/#tips-for-working-with-css","title":"Tips for working with CSS","text":"Your browser's developer tools contain very useful features for exploring and debugging your experiment's style and formatting. Open your browser's developer tools and click on the Element Inspector button or go to the Elements tab. Once you have selected an element on the page, you can see all of the information that can be used to select it, including:
- tag name, e.g., \"div\", \"p\", \"img\", \"button\"
- ID, if it has one
- class(es), if it has any
You can then use this information to create a CSS selector to modify that element's style.
As you can see, jsPsych adds its own IDs and classes to many elements. You can use the developer tools to determine what IDs and classes already exist for the elements that you want to modify, as you may can often just use these instead of adding your own. For instance, in the \"html-keyboard-response\" plugin, the stimulus will always be shown in a <div> with the ID \"jspsych-html-keyboard-response-stimulus\". So you can create a CSS rule that is applied to all \"html-keyboard-response\" stimuli like this:
#jspsych-html-keyboard-response-stimulus {\n color: white;\n background-color: blue;\n width: 100px;\n border: 4px solid black;\n}\n
As another example, most jsPsych buttons have the class \"jspsych-btn\", so you can use this class to change the default button styling:
.jspsych-btn {\n padding: 20px 20px;\n font-size: 25px;\n border-color: black;\n}\n
You can also use the developer tools to change an element's CSS and immediately see the effect that the changes will have on the page. These changes are just temporary, so you will still need to use one of methods described above to add the CSS changes to your experiment. However, making changes in the developer tools is very useful for figuring out which CSS properties to change and which values to use. This area of the developer tools also shows what styles are currently applied to the element and where those style rules are coming from.
There are a few things to be aware of while debugging problems with CSS.
- When there are conflicting CSS rules, some CSS rules will take precedence over others. For instance, inline CSS usually takes precedence over other CSS rules, and more specific CSS selectors usually take precedence over less specific ones.
- When there are conflicting CSS rules that have the same level of precedence, the last rule will override any earlier rules. For that reason it's important to add your own custom stylesheet after the default jspsych.css stylesheet. See this page about CSS precedence for more information.
If one CSS style rule is overridden by another one, the rule that is overridden will appear in strikethrough text in the element's \"Styles\" section. Also, if you are using an incorrect CSS property name or an invalid value, then that will show up here as an error, indicated by both strikethrough text and a little yellow warning symbol.
"},{"location":"overview/timeline/","title":"Creating an Experiment: The Timeline","text":"To create an experiment using jsPsych, you need to specify a timeline that describes the structure of the experiment. The timeline is an ordered set of trials. You must create the timeline before launching the experiment. Most of the code you will write for an experiment will be code to create the timeline. This page walks through the creation of timelines, including very basic examples and more advanced features.
"},{"location":"overview/timeline/#a-single-trial","title":"A single trial","text":"To create a trial, you need to create an object that describes the trial. The most important feature of this object is the type
parameter. This tells jsPsych which plugin to use to run the trial. For example, if you want to use the html-keyboard-response plugin to display a short message, the trial object would look like this:
const trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Welcome to the experiment.'\n}\n
The parameters for this object (e.g., stimulus
) will depend on the plugin that you choose. Each plugin defines the set of parameters that are needed to run a trial with that plugin. Visit the documentation for a plugin to learn about the parameters that you can use with that plugin.
To create a timeline with the single trial and run the experiment, just embed the trial object in an array. A timeline can simply be an array of trials.
const timeline = [trial];\n\njsPsych.run(timeline);\n
To create and run a simple experiment like this complete the hello world tutorial.
"},{"location":"overview/timeline/#multiple-trials","title":"Multiple trials","text":"Scaling up to multiple trials is straightforward. Create an object for each trial, and add each object to the timeline array.
// with lots of trials, it might be easier to add the trials\n// to the timeline array as they are defined.\nconst timeline = [];\n\nconst trial_1 = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'This is trial 1.'\n}\ntimeline.push(trial_1);\n\nconst trial_2 = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'This is trial 2.'\n}\ntimeline.push(trial_2);\n\nconst trial_3 = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'This is trial 3.'\n}\ntimeline.push(trial_3);\n
"},{"location":"overview/timeline/#nested-timelines","title":"Nested timelines","text":"Each object on the timeline can also have its own timeline. This is useful for many reasons. One is that it allows you to define common parameters across trials once and have them apply to all the trials on the nested timeline. The example below creates a series of trials using the image-keyboard-response plugin, where the only thing that changes from trial-to-trial is the image file being displayed on the screen.
const judgment_trials = {\n type: jsPsychImageKeyboardResponse,\n prompt: '<p>Press a number 1-7 to indicate how unusual the image is.</p>',\n choices: ['1','2','3','4','5','6','7'],\n timeline: [\n {stimulus: 'image1.png'},\n {stimulus: 'image2.png'},\n {stimulus: 'image3.png'}\n ]\n}\n
In the above code, the type
, prompt
, and choices
parameters are automatically applied to all of the objects in the timeline
array. This creates three trials with the same type
, prompt
, and choices
parameters, but different values for the stimulus
parameter.
You can also override the values by declaring a new value in the timeline
array. In the example below, the second trial will display a different prompt message.
const judgment_trials = {\n type: jsPsychImageKeyboardResponse,\n prompt: '<p>Press a number 1-7 to indicate how unusual the image is.</p>',\n choices: ['1','2','3','4','5','6','7'],\n timeline: [\n {stimulus: 'image1.png'},\n {stimulus: 'image2.png', prompt: '<p>Press 1 for this trial.</p>'},\n {stimulus: 'image3.png'}\n ]\n}\n
Timelines can be nested any number of times.
"},{"location":"overview/timeline/#timeline-variables","title":"Timeline variables","text":"A common pattern in behavioral experiments is to repeat the same procedure/task many times with slightly different parameters. A procedure might be a single trial, but it also might be a series of trials. For example, a task might involve a fixation cross appearing, followed by a blank screen, followed by an image for a short duration, followed by a prompt and a text box to report on some aspect of the image.
One shortcut to implement this pattern is with the nested timeline approach described in the previous section, but this only works if all the trials use the same plugin type. Timeline variables are a more general solution. With timeline variables you define the procedure once (as a timeline) and specify a set of parameters and their values for each iteration through the timeline.
What follows is an example of how to use timeline variables. The simple reaction time tutorial also explains how to use timeline variables.
Suppose we want to create an experiment where people see a set of faces. Perhaps this is a memory experiment and this is the phase of the experiment where the faces are being presented for the first time. In between each face, a fixation cross is displayed on the screen. Without timeline variables, we would need to add many trials to the timeline, alternating between trials showing the fixation cross and trials showing the face and name. This could be done efficiently using a loop or function to create the timeline, but timeline variables make it even easier - as well as adding extra features like sampling and randomization.
Here's a basic version of the task with timeline variables.
const face_name_procedure = {\n timeline: [\n {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '+',\n choices: \"NO_KEYS\",\n trial_duration: 500\n },\n {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('face'),\n choices: \"NO_KEYS\",\n trial_duration: 2500\n }\n ],\n timeline_variables: [\n { face: 'person-1.jpg' },\n { face: 'person-2.jpg' },\n { face: 'person-3.jpg' },\n { face: 'person-4.jpg' }\n ]\n}\n
In the above version, there are four separate trials defined in the timeline_variables
parameter. Each trial has a variable face
and a variable name
. The timeline
defines a procedure of showing a fixation cross for 500ms followed by the face and name for 2500ms. This procedure will repeat four times, with the first trial showing 'person-1.jpg'
, the second 'person-2.jpg'
, and so on. The variables are referenced within the procedure by calling the jsPsych.timelineVariable()
method and passing in the name of the variable.
What if we wanted to add an additional step to the task where the name is displayed prior to the face appearing? (Maybe this is one condition of an experiment investigating whether the order of name-face or face-name affects retention.) We can add another variable to our list that gives the name associated with each image. Then we can add another trial to our timeline to show the name.
const face_name_procedure = {\n timeline: [\n {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '+',\n choices: \"NO_KEYS\",\n trial_duration: 500\n },\n {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: jsPsych.timelineVariable('name'),\n trial_duration: 1000,\n choices: \"NO_KEYS\"\n },\n {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('face'), \n choices: \"NO_KEYS\",\n trial_duration: 1000\n }\n ],\n timeline_variables: [\n { face: 'person-1.jpg', name: 'Alex' },\n { face: 'person-2.jpg', name: 'Beth' },\n { face: 'person-3.jpg', name: 'Chad' },\n { face: 'person-4.jpg', name: 'Dave' }\n ]\n}\n
"},{"location":"overview/timeline/#using-timeline-variables-in-a-function","title":"Using timeline variables in a function","text":"Continuing the example from the previous section, what if we wanted to show the name with the face, combining the two variables together? To do this, we can use a dynamic parameter (a function) to create an HTML-string that uses both variables in a single parameter. However, because we are getting the value of a timeline variable in a function, we need to use jsPsych.evaluateTimelineVariable()
instead of jsPsych.timelineVariable()
. Calling .evaluateTimelineVariable()
immediately gets the value of the variable, while .timelineVariable()
creates a placeholder that jsPsych evaluates at the appropriate time during the execution of the experiment. The value of the stimulus
parameter will be a function that returns an HTML string that contains both the image and the name.
const face_name_procedure = {\n timeline: [\n {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '+',\n choices: \"NO_KEYS\",\n trial_duration: 500\n },\n {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: jsPsych.timelineVariable('name'),\n trial_duration: 1000,\n choices: \"NO_KEYS\"\n },\n {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: function(){\n const html = `\n <img src=\"${jsPsych.evaluateTimelineVariable('face')}\">\n <p>${jsPsych.evaluateTimelineVariable('name')}</p>`;\n return html;\n }, \n choices: \"NO_KEYS\",\n trial_duration: 2500\n }\n ],\n timeline_variables: [\n { face: 'person-1.jpg', name: 'Alex' },\n { face: 'person-2.jpg', name: 'Beth' },\n { face: 'person-3.jpg', name: 'Chad' },\n { face: 'person-4.jpg', name: 'Dave' }\n ]\n}\n
"},{"location":"overview/timeline/#random-orders-of-trials","title":"Random orders of trials","text":"If we want to randomize the order of the trials defined with timeline variables, we can set randomize_order
to true
.
const face_name_procedure = {\n timeline: [...],\n timeline_variables: [\n { face: 'person-1.jpg', name: 'Alex' },\n { face: 'person-2.jpg', name: 'Beth' },\n { face: 'person-3.jpg', name: 'Chad' },\n { face: 'person-4.jpg', name: 'Dave' }\n ],\n randomize_order: true\n}\n
"},{"location":"overview/timeline/#sampling-methods","title":"Sampling methods","text":"There are also sampling methods that can be used to select a set of trials from the timeline_variables. Sampling is declared by creating a sample
parameter. The sample
parameter is given an object of arguments. The type
parameter in this object controls the type of sampling that is done. Valid values for type
are:
\"with-replacement\"
: Sample size
items from the timeline variables with the possibility of choosing the same item multiple time. \"without-replacement\"
: Sample size
items from timeline variables, with each item being selected a maximum of 1 time. \"fixed-repetitons\"
: Repeat each item in the timeline variables size
times, in a random order. Unlike using the repetitons
parameter, this method allows for consecutive trials to use the same timeline variable set. \"alternate-groups\"
: Sample in an alternating order based on a declared group membership. Groups are defined by the groups
parameter. This parameter takes an array of arrays, where each inner array is a group and the items in the inner array are the indices of the timeline variables in the timeline_variables
array that belong to that group. \"custom\"
: Write a function that returns a custom order of the timeline variables.
"},{"location":"overview/timeline/#sampling-with-replacement","title":"Sampling with replacement","text":"This sample
parameter will create 10 repetitions, sampling with replacement.
const face_name_procedure = {\n timeline: [...],\n timeline_variables: [\n { face: 'person-1.jpg', name: 'Alex' },\n { face: 'person-2.jpg', name: 'Beth' },\n { face: 'person-3.jpg', name: 'Chad' },\n { face: 'person-4.jpg', name: 'Dave' }\n ],\n sample: {\n type: 'with-replacement',\n size: 10\n }\n}\n
"},{"location":"overview/timeline/#sampling-with-replacement-unequal-probabilities","title":"Sampling with replacement, unequal probabilities","text":"This sample
parameter will make the \"Alex\" trial three times as likely to be sampled as the others.
const face_name_procedure = {\n timeline: [...],\n timeline_variables: [\n { face: 'person-1.jpg', name: 'Alex' },\n { face: 'person-2.jpg', name: 'Beth' },\n { face: 'person-3.jpg', name: 'Chad' },\n { face: 'person-4.jpg', name: 'Dave' }\n ],\n sample: {\n type: 'with-replacement',\n size: 10, \n weights: [3, 1, 1, 1]\n }\n}\n
"},{"location":"overview/timeline/#sampling-without-replacement","title":"Sampling without replacement","text":"This sample
parameter will pick three of the four possible trials to run at random.
const face_name_procedure = {\n timeline: [...],\n timeline_variables: [\n { face: 'person-1.jpg', name: 'Alex' },\n { face: 'person-2.jpg', name: 'Beth' },\n { face: 'person-3.jpg', name: 'Chad' },\n { face: 'person-4.jpg', name: 'Dave' }\n ],\n sample: {\n type: 'without-replacement',\n size: 3 \n }\n}\n
"},{"location":"overview/timeline/#repeating-each-trial-a-fixed-number-of-times-in-a-random-order","title":"Repeating each trial a fixed number of times in a random order","text":"This sample
parameter will create 3 repetitions of each trial, for a total of 12 trials, with a random order.
const face_name_procedure = {\n timeline: [...],\n timeline_variables: [\n { face: 'person-1.jpg', name: 'Alex' },\n { face: 'person-2.jpg', name: 'Beth' },\n { face: 'person-3.jpg', name: 'Chad' },\n { face: 'person-4.jpg', name: 'Dave' }\n ],\n sample: {\n type: 'fixed-repetitions',\n size: 3\n }\n}\n
"},{"location":"overview/timeline/#alternating-groups","title":"Alternating groups","text":"This sample
parameter puts the \"Alex\" and \"Chad\" trials in group 1 and the \"Beth\" and \"Dave\" trials in group 2. The resulting sample of trials will follow the pattern group 1
-> group 2
-> group 1
-> group 2
. Each trial will be selected only one time. If you wanted group 2
to sometimes be first, you could set randomize_group_order: true
.
const face_name_procedure = {\n timeline: [...],\n timeline_variables: [\n { face: 'person-1.jpg', name: 'Alex' },\n { face: 'person-2.jpg', name: 'Beth' },\n { face: 'person-3.jpg', name: 'Chad' },\n { face: 'person-4.jpg', name: 'Dave' }\n ],\n sample: {\n type: 'alternate-groups',\n groups: [[0,2],[1,3]], \n randomize_group_order: false\n }\n}\n
"},{"location":"overview/timeline/#custom-sampling-function","title":"Custom sampling function","text":"Any sampling method can be implemented using the custom
type sampler. The order of trials will be determined by running the function supplied as fn
. The function has a single parameter, t
, which is an array of integers from 0
to n-1
, where n
is the number of trials in the timeline_variables
array. The function must return an array that specifies the order of the trials, e.g., returning [3,3,2,2,1,1,0,0]
would result in the order Dave
-> Dave
-> Chad
-> Chad
-> Beth
-> Beth
-> Alex
-> Alex
.
const face_name_procedure = {\n timeline: [...],\n timeline_variables: [\n { face: 'person-1.jpg', name: 'Alex' },\n { face: 'person-2.jpg', name: 'Beth' },\n { face: 'person-3.jpg', name: 'Chad' },\n { face: 'person-4.jpg', name: 'Dave' }\n ],\n sample: {\n type: 'custom',\n fn: function(t){\n return t.reverse(); // show the trials in the reverse order\n }\n }\n}\n
"},{"location":"overview/timeline/#repeating-a-set-of-trials","title":"Repeating a set of trials","text":"To repeat a timeline multiple times, you can create an object (node) that contains a timeline
, which is the timeline array to repeat, and repetitions
, which is the number of times to repeat that timeline.
const trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'This trial will be repeated twice.'\n}\n\nconst node = {\n timeline: [trial],\n repetitions: 2\n}\n
The repetitions
parameter can be used alongside other node parameters, such as timeline variables, loop functions, and/or conditional functions. If you are using timeline_variables
and randomize_order
is true
, then the order of the timeline variables will re-randomize before every repetition.
const face_name_procedure = {\n timeline: [...],\n timeline_variables: [\n { face: 'person-1.jpg', name: 'Alex' },\n { face: 'person-2.jpg', name: 'Beth' },\n { face: 'person-3.jpg', name: 'Chad' },\n { face: 'person-4.jpg', name: 'Dave' }\n ],\n randomize_order: true,\n repetitions: 3 \n}\n
"},{"location":"overview/timeline/#looping-timelines","title":"Looping timelines","text":"Any timeline can be looped using the loop_function
option. The loop function must be a function that evaluates to true
if the timeline should repeat, and false
if the timeline should end. It receives a single parameter, named data
by convention. This parameter will be the DataCollection object with all of the data from the trials executed in the last iteration of the timeline. The loop function will be evaluated after the timeline is completed.
const trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'This trial is in a loop. Press R to repeat this trial, or C to continue.'\n}\n\nconst loop_node = {\n timeline: [trial],\n loop_function: function(data){\n if(jsPsych.pluginAPI.compareKeys(data.values()[0].response, 'r')){\n return true;\n } else {\n return false;\n }\n }\n}\n
"},{"location":"overview/timeline/#conditional-timelines","title":"Conditional timelines","text":"A timeline can be skipped or not based on the evaluation of the conditional_function
option. If the conditional function evaluates to true
, the timeline will execute normally. If the conditional function evaluates to false
then the timeline will be skipped. The conditional function is evaluated whenever jsPsych is about to run the first trial on the timeline.
If you use a conditional function and a loop function on the same timeline, the conditional function will only evaluate once.
const jsPsych = initJsPsych();\n\nconst pre_if_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'The next trial is in a conditional statement. Press S to skip it, or V to view it.'\n}\n\nconst if_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'You chose to view the trial. Press any key to continue.'\n}\n\nconst if_node = {\n timeline: [if_trial],\n conditional_function: function(){\n // get the data from the previous trial,\n // and check which key was pressed\n const data = jsPsych.data.get().last(1).values()[0];\n if(jsPsych.pluginAPI.compareKeys(data.response, 's')){\n return false;\n } else {\n return true;\n }\n }\n}\n\nconst after_if_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'This is the trial after the conditional.'\n}\n\njsPsych.run([pre_if_trial, if_node, after_if_trial]);\n
"},{"location":"overview/timeline/#modifying-timelines-at-runtime","title":"Modifying timelines at runtime","text":"Although this functionality can also be achieved through a combination of the conditional_function
and the use of dynamic variables in the stimulus
parameter, our timeline implementation allows you to dynamically add or remove trials and nested timelines during runtime.
"},{"location":"overview/timeline/#adding-timeline-nodes-at-runtime","title":"Adding timeline nodes at runtime","text":"For example, you may have a branching point in your experiment where the participant is given 3 choices, each leading to a different timeline:
const jspsych = initJsPsych();\nlet main_timeline = [];\n\nconst part1_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Part 1'\n}\n\nconst choice_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Press 1 if you are a new participant. Press 2 for inquiries about an existing experiment run. Press 3 for Spanish.',\n choices: ['1','2','3']\n}\n
This would be trickier to implement with the conditional_function
since it can only handle 2 branches -- case when True
or case when False
. Instead, you can modify the timeline by modifying choice_trial
to dynamically adding a timeline at the end of the choice trial according to the chosen condition: const english_trial1 = {...};\nconst english_trial2 = {...};\nconst english_trial3 = {...};\n// So on and so forth\nconst spanish_trial3 = {...};\n\nconst english_branch = [b1_t1, b1_t2, b1_t3];\nconst mandarin_branch = [b2_t1, b2_t2, b2_t3];\nconst spanish_branch = [b3_t1, b3_t2, b3_t3];\n\nconst choice_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Press 1 for English. Press 2 for Mandarin. Press 3 for Spanish.',\n choices: ['1','2','3'],\n on_finish: (data) => {\n switch(data.response) {\n case '1':\n main_timeline.push(english_branch);\n break;\n case '2':\n main_timeline.push(mandarin_branch);\n break;\n case '3':\n main_timeline.push(spanish_branch);\n break;\n }\n }\n}\nmain_timeline.push(part1_trial, choice_trial);\n
During runtime, choices 1, 2 and 3 will dynamically add a different (nested) timeline, english_branch
, mandarin_branch
and spanish_branch
respectively, to the end of the main_timeline
."},{"location":"overview/timeline/#removing-timeline-nodes-at-runtime","title":"Removing timeline nodes at runtime","text":"You can also remove upcoming timeline nodes from a timeline at runtime. To demonstrate this, we can modify the above example by adding a 4th choice to choice_trial
and another (nested) timeline to the tail of main_timeline
:
const choice_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Press 1 for English. Press 2 for Mandarin. Press 3 for Spanish. Press 4 to exit.',\n choices: ['1','2','3', '4'],\n on_finish: (data) => {\n switch(data.response) {\n case '1':\n main_timeline.push(english_branch);\n break;\n case '2':\n main_timeline.push(mandarin_branch);\n break;\n case '3':\n main_timeline.push(spanish_branch);\n break;\n case '4':\n main_timeline.pop();\n break;\n }\n }\n}\n\nconst part2_timeline = [\n {\n type: JsPsychHtmlKeyboardResponse,\n stimulus: 'Part 2'\n }\n // ...the rest of the part 2 trials\n]\n\nmain_timeline.push(part1_trial, choice_trial, part2_timeline)\n
Now, if 1, 2 or 3 were chosen during runtime, part2_timeline
will run after the dynamically added timeline corresponding to the choice (english_branch
| mandarin_branch
| spanish_branch
) has been run; but if 4 was chosen, part2_timeline
will be removed at runtime, and main_timeline
will terminate."},{"location":"overview/timeline/#exception-cases-for-addingremoving-timeline-nodes-dynamically","title":"Exception cases for adding/removing timeline nodes dynamically","text":"Adding or removing timeline nodes work as expected when the addition/removal occurs at a future point in the timeline relative to the current executing node, but not if it occurs before the current node. The example above works as expected becaues all the node(s) added (english_branch
| mandarin_branch
| spanish_branch
) or removed (part2_timeline
) occur at the end of the timeline via push()
and pop()
. If a node was added at a point in the timeline that has already been executed, it will not be executed:
const choice_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Press 1 for English. Press 2 for Mandarin. Press 3 for Spanish. Press 4 to exit.',\n choices: ['1','2','3', '4'],\n on_finish: (data) => {\n switch(data.response) {\n case '1':\n main_timeline.splice(0,0,english_branch); // Adds english_branch to the start of main_timeline\n break;\n case '2':\n main_timeline.push(mandarin_branch);\n break;\n\n ...\n\nmain_timeline.push(part1_trial, choice_trial);\n
In the above implementation of choice_trial
, choice 1 adds english_branch
at the start of main_timeline
, such that main_timeline = [english_branch, part1_trial, choice_trial]
, but because the execution of main_timeline
is past the first node at this point in runtime, the newly added english_branch
will not be executed. Similarly, modifying case '1'
in choice_trial
to remove part1_trial
will not change any behavior in the timeline. Danger
In the case of a looping timeline, adding a timeline node at a point before the current node will cause the current node to be executed again; and removing a timeline node at a point before the current node will cause the next node to be skipped.
"},{"location":"overview/timeline/#timeline-start-and-finish-functions","title":"Timeline start and finish functions","text":"You can run a custom function at the start and end of a timeline node using the on_timeline_start
and on_timeline_finish
callback function parameters. These are functions that will run when the timeline starts and ends, respectively.
const procedure = {\n timeline: [trial_1, trial_2],\n on_timeline_start: function() {\n console.log('The trial procedure just started.')\n },\n on_timeline_finish: function() {\n console.log('The trial procedure just finished.')\n }\n}\n
This works the same way with timeline variables. The on_timeline_start
and on_timeline_finish
functions will run when timeline variables trials start and end, respectively.
const face_name_procedure = {\n timeline: [...],\n timeline_variables: [\n { face: 'person-1.jpg', name: 'Alex' },\n { face: 'person-2.jpg', name: 'Beth' },\n { face: 'person-3.jpg', name: 'Chad' },\n { face: 'person-4.jpg', name: 'Dave' }\n ],\n randomize_order: true,\n on_timeline_start: function() {\n console.log('First trial is starting.')\n },\n on_timeline_finish: function() {\n console.log('Last trial just finished.')\n }\n}\n
These functions will execute only once if the timeline loops.
"},{"location":"overview/timing-accuracy/","title":"Timing accuracy","text":"Wondering if jsPsych can be used for research that depends on accurate display times or response time measurement? For most purposes, the answer is yes.
Display timing is somewhat less accurate in JavaScript than in standard experimental software that runs on a desktop. Desktop software can have closer integration with the graphics devices of the machine than JavaScript currently permits. If a one or two frame (17-33ms) difference in display timing matters for your experiment, then you'll want to be careful with JavaScript-based experiments. It is possible to achieve this level of control in JavaScript, but it often requires code that is more tailored to your experiment and some restrictions about which browsers can be used to run the experiment.
Tip
If you are hoping to run an experiment with the best timing that jsPsych can offer, we currently recommend using the jspsych-psychophysics plugin developed by Daiichiro Kuroki.
Kuroki, D. (2021). A new jsPsych plugin for psychophysics, providing accurate display duration and stimulus onset asynchrony. Behavior Research Methods, 53, 301\u2013310. https://doi.org/10.3758/s13428-020-01445-w
Response time measurements in jsPsych (and JavaScript in general) are comparable to those taken in standard lab software like Psychophysics Toolbox and E-Prime. Response times measured in JavaScript tend to be a little bit longer (10-40ms), but have similar variance.
"},{"location":"overview/timing-accuracy/#references","title":"References","text":"See the following papers for extensive work on display and response timing in browser-based experiments.
Note that browsers are updating frequently and the JavaScript language specification is also changing. It's possible that the results from these papers do not apply to current versions of web browsers.
Future updates to JavaScript APIs will likely improve the ability of online experiments to provide more accurate display timing and response time measurement.
- Bridges, D., Pitiot, A., MacAskill, M. R., & Peirce, J. W. (2020). The timing mega-study: Comparing a range of experiment generators, both lab-based and online. PeerJ, 8, e9414.
- Anwyl-Irvine, A., Dalmaijer, E. S., Hodges, N., & Evershed, J. K. (2020). Realistic precision and accuracy of online experiment platforms, web browsers, and devices. Behavior Research Methods, 53, 1-19.
- Pronk, T., Wiers, R. W., Molenkamp, B., & Murre, J. (2020). Mental chronometry in the pocket? Timing accuracy of web applications on touchscreen and keyboard devices. Behavior Research Methods, 52(3), 1371-1382.
- Pinet, S., Zielinski, C., Math\u00f4t, S. et al. (2017). Measuring sequences of keystrokes with jsPsych: Reliability of response times and interkeystroke intervals. Behavior Research Methods, 49(3), 1177-1178.
- de Leeuw, J. R., & Motz, B. A. (2016). Psychophysics in a Web browser? Comparing response times collected with JavaScript and Psychophysics Toolbox in a visual search task. Behavior Research Methods, 48(1), 1-12.
- Hilbig, B. E. (2016). Reaction time effects in lab- versus web-based research: Experimental evidence. Behavior Research Methods, 48(4), 1718-1724.
- Reimers, S., & Stewart, N. (2015). Presentation and response time accuracy in Adobe Flash and HTML5/JavaScript Web experiments. Behavior Research Methods, 47(2), 309-327.
"},{"location":"plugins/animation/","title":"animation","text":"Current version: 2.0.1. See version history.
This plugin displays a sequence of images at a fixed frame rate. The sequence can be looped a specified number of times. The participant is free to respond at any point during the animation, and the time of the response is recorded.
"},{"location":"plugins/animation/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimuli array undefined Each element of the array is a path to an image file. frame_time numeric 250 How long to display each image in milliseconds. frame_isi numeric 0 If greater than 0, then a gap will be shown between each image in the sequence. This parameter specifies the length of the gap in milliseconds. sequence_reps numeric 1 How many times to show the entire sequence. There will be no gap (other than the gap specified by frame_isi
) between repetitions. choices array of strings \"ALL_KEYS\"
This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., 'a'
, 'q'
, ' '
, 'Enter'
, 'ArrowDown'
) - see this page and this page (event.key column) for more examples. Any key presses that are not listed in the array will be ignored. The default value of \"ALL_KEYS\"
means that all keys will be accepted as valid responses. Specifying \"NO_KEYS\"
will mean that no responses are allowed. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key(s) to press). render_on_canvas boolean true If true, the images will be drawn onto a canvas element. This prevents a blank screen (white flash) between consecutive images in some browsers, like Firefox and Edge. If false, the image will be shown via an img element, as in previous versions of jsPsych."},{"location":"plugins/animation/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value animation_sequence array An array, where each element is an object that represents a stimulus in the animation sequence. Each object has a stimulus
property, which is the image that was displayed, and a time
property, which is the time in ms, measured from when the sequence began, that the stimulus was displayed. The array will be encoded in JSON format when data is saved using either the .json()
or .csv()
functions. response array An array, where each element is an object representing a response given by the participant. Each object has a stimulus
property, indicating which image was displayed when the key was pressed, an rt
property, indicating the time of the key press relative to the start of the animation, and a key_press
property, indicating which key was pressed. The array will be encoded in JSON format when data is saved using either the .json()
or .csv()
functions."},{"location":"plugins/animation/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-animation@2.0.1\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-animation.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-animation\n
import animation from '@jspsych/plugin-animation';\n
"},{"location":"plugins/animation/#examples","title":"Examples","text":"Displaying a single sequence multiple times CodeDemo var animation_sequence = [\"img/happy_face_1.jpg\", \"img/happy_face_2.jpg\", \"img/happy_face_3.jpg\", \"img/happy_face_4.jpg\"];\n\nvar animation_trial = {\n type: jsPsychAnimation,\n stimuli: animation_sequence,\n sequence_reps: 3,\n frame_time: 300,\n prompt: '<p>Watch the faces.</p>',\n};\n
Open demo in new tab
"},{"location":"plugins/audio-button-response/","title":"audio-button-response","text":"Current version: 2.0.2. See version history.
This plugin plays audio files and records responses generated with a button click.
If the browser supports it, audio files are played using the WebAudio API. This allows for reasonably precise timing of the playback. The timing of responses generated is measured against the WebAudio specific clock, improving the measurement of response times. If the browser does not support the WebAudio API, then the audio file is played with HTML5 audio.
Audio files can be automatically preloaded by jsPsych using the preload
plugin. However, if you are using timeline variables or another dynamic method to specify the audio stimulus, you will need to manually preload the audio.
The trial can end when the participant responds, when the audio file has finished playing, or if the participant has failed to respond within a fixed length of time. You can also prevent a button response from being made before the audio has finished playing.
"},{"location":"plugins/audio-button-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus audio file undefined Path to audio file to be played. choices array of strings undefined Labels for the buttons. Each different string in the array will generate a different button. button_html function (choice: string, choice_index: number)=>`<button class=\"jspsych-btn\">${choice}</button>
; A function that generates the HTML for each button in the choices
array. The function gets the string and index of the item in the choices
array and should return valid HTML. If you want to use different markup for each button, you can do that by using a conditional on either parameter. The default parameter returns a button element with the text label of the choice. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, the trial will wait for a response indefinitely. button_layout string 'grid' Setting to 'grid'
will make the container element have the CSS property display: grid
and enable the use of grid_rows
and grid_columns
. Setting to 'flex'
will make the container element have the CSS property display: flex
. You can customize how the buttons are laid out by adding inline CSS in the button_html
parameter. grid_rows number 1 The number of rows in the button grid. Only applicable when button_layout
is set to 'grid'
. If null, the number of rows will be determined automatically based on the number of buttons and the number of columns. grid_columns number null The number of columns in the button grid. Only applicable when button_layout
is set to 'grid'
. If null, the number of columns will be determined automatically based on the number of buttons and the number of rows. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can set this parameter to false
to force the participant to listen to the stimulus for a fixed amount of time, even if they respond before the time is complete. trial_ends_after_audio boolean false If true, then the trial will end as soon as the audio file finishes playing. response_allowed_while_playing boolean true If true, then responses are allowed while the audio is playing. If false, then the audio must finish playing before the button choices are enabled and a response is accepted. Once the audio has played all the way through, the buttons are enabled and a response is allowed (including while the audio is being re-played via on-screen playback controls). enable_button_after numeric 0 How long the button will delay enabling in milliseconds. If response_allowed_while_playing
is true
, the timer will start immediately. If it is false
, the timer will start at the end of the audio."},{"location":"plugins/audio-button-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first began playing until the participant's response. response numeric Indicates which button the participant pressed. The first button in the choices
array is 0, the second is 1, and so on. stimulus string Path to the audio file that played during the trial."},{"location":"plugins/audio-button-response/#simulation-mode","title":"Simulation Mode","text":"In data-only
simulation mode, the response_allowed_while_playing
parameter does not currently influence the simulated response time. This is because the audio file is not loaded in data-only
mode and therefore the length is unknown. This may change in a future version as we improve the simulation modes.
"},{"location":"plugins/audio-button-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-audio-button-response@2.0.2\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-audio-button-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-audio-button-response\n
import audioButtonResponse from '@jspsych/plugin-audio-button-response';\n
"},{"location":"plugins/audio-button-response/#examples","title":"Examples","text":"Displaying question until participant gives a response CodeDemo var trial = {\n type: jsPsychAudioButtonResponse,\n stimulus: 'sound/tone.mp3',\n choices: ['Low', 'High'],\n prompt: \"<p>Is the pitch high or low?</p>\"\n};\n
Open demo in new tab
Using custom button HTML to use images as buttons Code ``javascript const trial = { type: jsPsychAudioButtonResponse, stimulus: 'sound/roar.mp3', choices: images, prompt: \"<p>Which animal made the sound?</p>\", button_html: (choice)=>
`
}; ```
Demo
Open demo in new tab
Setting up a grid-based layout Code ```javascript const trial = { type: jsPsychAudioButtonResponse,
stimulus: 'sound/telephone.mp3', prompt: '
Which key was pressed first?
', choices: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '0', '#'], button_layout: 'grid', grid_rows: 4, grid_columns: 3 } ``` Demo
Open demo in new tab
"},{"location":"plugins/audio-keyboard-response/","title":"audio-keyboard-response","text":"Current version: 2.0.0. See version history.
This plugin plays audio files and records responses generated with the keyboard.
If the browser supports it, audio files are played using the WebAudio API. This allows for reasonably precise timing of the playback. The timing of responses generated is measured against the WebAudio specific clock, improving the measurement of response times. If the browser does not support the WebAudio API, then the audio file is played with HTML5 audio.
Audio files can be automatically preloaded by jsPsych using the preload
plugin. However, if you are using timeline variables or another dynamic method to specify the audio stimulus, then you will need to manually preload the audio.
The trial can end when the participant responds, when the audio file has finished playing, or if the participant has failed to respond within a fixed length of time. You can also prevent a keyboard response from being recorded before the audio has finished playing.
"},{"location":"plugins/audio-keyboard-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus audio file undefined Path to audio file to be played. choices array of strings \"ALL_KEYS\"
This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., 'a'
, 'q'
, ' '
, 'Enter'
, 'ArrowDown'
) - see this page and this page (event.key column) for more examples. Any key presses that are not listed in the array will be ignored. The default value of \"ALL_KEYS\"
means that all keys will be accepted as valid responses. Specifying \"NO_KEYS\"
will mean that no responses are allowed. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can use set this parameter to false
to force the participant to listen to the stimulus for a fixed amount of time, even if they respond before the time is complete. trial_ends_after_audio boolean false If true, then the trial will end as soon as the audio file finishes playing. response_allowed_while_playing boolean true If true, then responses are allowed while the audio is playing. If false, then the audio must finish playing before a keyboard response is accepted. Once the audio has played all the way through, a valid keyboard response is allowed (including while the audio is being re-played via on-screen playback controls)."},{"location":"plugins/audio-keyboard-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response string Indicates which key the participant pressed. If no key was pressed before the trial ended, then the value will be null
. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first began playing until the participant made a key response. If no key was pressed before the trial ended, then the value will be null
. stimulus string Path to the audio file that played during the trial."},{"location":"plugins/audio-keyboard-response/#simulation-mode","title":"Simulation Mode","text":"In data-only
simulation mode, the response_allowed_while_playing
parameter does not currently influence the simulated response time. This is because the audio file is not loaded in data-only
mode and therefore the length is unknown. This may change in a future version as we improve the simulation modes.
"},{"location":"plugins/audio-keyboard-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-audio-keyboard-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-audio-keyboard-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-audio-keyboard-response\n
import audioKeyboardResponse from '@jspsych/plugin-audio-keyboard-response';\n
"},{"location":"plugins/audio-keyboard-response/#examples","title":"Examples","text":"Trial continues until participant gives a response CodeDemo var trial = {\n type: jsPsychAudioKeyboardResponse,\n stimulus: 'sound/tone.mp3',\n choices: ['e', 'i'],\n prompt: \"<p>Is the pitch high or low? Press 'e' for low and 'i' for high.</p>\",\n response_ends_trial: true\n};\n
Open demo in new tab
Play a sound with no user response; trial ends after sound plays CodeDemo var trial = {\n type: jsPsychAudioKeyboardResponse,\n stimulus: 'sound/tone.mp3',\n choices: \"NO_KEYS\",\n trial_ends_after_audio: true\n};\n
Open demo in new tab
"},{"location":"plugins/audio-slider-response/","title":"audio-slider-response","text":"Current version: 2.0.1. See version history.
This plugin plays an audio file and allows the participant to respond by dragging a slider.
If the browser supports it, audio files are played using the WebAudio API. This allows for reasonably precise timing of the playback. The timing of responses generated is measured against the WebAudio specific clock, improving the measurement of response times. If the browser does not support the WebAudio API, then the audio file is played with HTML5 audio.
Audio files can be automatically preloaded by jsPsych using the preload
plugin. However, if you are using timeline variables or another dynamic method to specify the audio stimulus, then you will need to manually preload the audio.
The trial can end when the participant responds, or if the participant has failed to respond within a fixed length of time. You can also prevent the slider response from being made before the audio has finished playing.
"},{"location":"plugins/audio-slider-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus audio file undefined Audio file to be played labels array of strings [] Labels displayed at equidistant locations on the slider. For example, two labels will be placed at the ends of the slider. Three labels would place two at the ends and one in the middle. Four will place two at the ends, and the other two will be at 33% and 67% of the slider width. button_label string 'Continue' Label of the button to end the trial. min integer 0 Sets the minimum value of the slider max integer 100 Sets the maximum value of the slider slider_start integer 50 Sets the starting value of the slider step integer 1 Sets the step of the slider. This is the smallest amount by which the slider can change. slider_width integer null Set the width of the slider in pixels. If left null, then the width will be equal to the widest element in the display. require_movement boolean false If true, the participant must move the slider before clicking the continue button. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can set this parameter to false
to force the participant to listen to the stimulus for a fixed amount of time, even if they respond before the time is complete. response_allowed_while_playing boolean true If true, then responses are allowed while the audio is playing. If false, then the audio must finish playing before the slider is enabled and the trial can end via the next button click. Once the audio has played all the way through, the slider is enabled and a response is allowed (including while the audio is being re-played via on-screen playback controls)."},{"location":"plugins/audio-slider-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response numeric The numeric value of the slider. rt numeric The time in milliseconds for the participant to make a response. The time is measured from when the stimulus first began playing until the participant's response. stimulus string The path of the audio file that was played. slider_start numeric The starting value of the slider."},{"location":"plugins/audio-slider-response/#simulation-mode","title":"Simulation Mode","text":"In data-only
simulation mode, the response_allowed_while_playing
parameter does not currently influence the simulated response time. This is because the audio file is not loaded in data-only
mode and therefore the length is unknown. This may change in a future version as we improve the simulation modes.
"},{"location":"plugins/audio-slider-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-audio-slider-response@2.0.1\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-audio-slider-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-audio-slider-response\n
import audioSliderResponse from '@jspsych/plugin-audio-slider-response';\n
"},{"location":"plugins/audio-slider-response/#examples","title":"Examples","text":"A simple rating scale CodeDemo var trial = {\n type: jsPsychAudioSliderResponse,\n stimulus: 'sound/speech_joke.mp3',\n labels: ['Not Funny', 'Funny'],\n prompt: '<p>How funny is the joke?</p>'\n}\n
Open demo in new tab
No response allowed until audio finishes; participant must interact with slider to continue CodeDemo var trial = {\n type: jsPsychAudioSliderResponse,\n stimulus: 'sound/speech_joke.mp3',\n labels: ['Not Funny', 'Funny'],\n prompt: '<p>How funny is the joke?</p>',\n response_allowed_while_playing: false,\n require_movement: true\n}\n
Open demo in new tab
"},{"location":"plugins/browser-check/","title":"browser-check","text":"Current version: 2.0.0. See version history.
This plugin measures and records various features of the participant's browser and can end the experiment if defined inclusion criteria are not met.
The plugin currently can record the following features:
- The width and height of the browser window in pixels.
- The type of browser used (e.g., Chrome, Firefox, Edge, etc.) and the version number of the browser.*
- Whether the participant is using a mobile device.*
- The operating system.*
- Support for the WebAudio API.
- Support for the Fullscreen API, e.g., through the fullscreen plugin.
- The display refresh rate in frames per second.
- Whether the device has a webcam and microphone. Note that this only reveals whether a webcam/microphone exists. The participant still needs to grant permission in order for the experiment to use these devices.
Warning
Features with an * are recorded by parsing the user agent string. This method is accurate most of the time, but is not guaranteed to be correct. The plugin uses the detect-browser package to perform user agent parsing. You can find a list of supported browsers and OSes in the source file.
The plugin begins by measuring the set of features requested. An inclusion function is evaluated to see if the paricipant passes the inclusion criteria. If they do, then the trial ends and the experiment continues. If they do not, then the experiment ends immediately. If a minimum width and/or minimum height is desired, the plugin will optionally display a message to participants whose browser windows are too small to give them an opportunity to make the window larger if possible. See the examples below for more guidance.
"},{"location":"plugins/browser-check/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description features array of strings [\"width\", \"height\", \"webaudio\", \"browser\", \"browser_version\", \"mobile\", \"os\", \"fullscreen\", \"vsync_rate\", \"webcam\", \"microphone\"]
The list of browser features to record. The default value includes all of the available options. skip_features array of strings []
Any features listed here will be skipped, even if they appear in features
. Use this when you want to run most of the defaults. vsync_frame_count int 60 The number of frames to sample when measuring the display refresh rate (\"vsync_rate\"
). Increasing the number will potenially improve the stability of the estimate at the cost of increasing the amount of time the plugin takes during this test. On most devices, 60 frames takes about 1 second to measure. allow_window_resize bool true Whether to allow the participant to resize the browser window if the window is smaller than minimum_width
and/or minimum_height
. If false
, then the minimum_width
and minimum_height
parameters are ignored and you can validate the size in the inclusion_function
. minimum_height int 0 If allow_window_resize
is true
, then this is the minimum height of the window (in pixels) that must be met before continuing. minimum_width int 0 If allow_window_resize
is true
, then this is the minimum width of the window (in pixels) that must be met before continuing. window_resize_message string see description The message that will be displayed during the interactive resize when allow_window_resize
is true
and the window is too small. If the message contains HTML elements with the special IDs browser-check-min-width
, browser-check-min-height
, browser-check-actual-height
, and/or browser-check-actual-width
, then the contents of those elements will be dynamically updated to reflect the minimum_width
, minimum_height
and measured width and height of the browser. The default message is: <p>Your browser window is too small to complete this experiment. Please maximize the size of your browser window. If your browser window is already maximized, you will not be able to complete this experiment.</p><p>The minimum window width is <span id=\"browser-check-min-width\"></span> px.</p><p>Your current window width is <span id=\"browser-check-actual-width\"></span> px.</p><p>The minimum window height is <span id=\"browser-check-min-height\"></span> px.</p><p>Your current window height is <span id=\"browser-check-actual-height\"></span> px.</p>
. resize_fail_button_text string \"I cannot make the window any larger\"
During the interactive resize, a button with this text will be displayed below the window_resize_message
for the participant to click if the window cannot meet the minimum size needed. When the button is clicked, the experiment will end and exclusion_message
will be displayed. inclusion_function function () => { return true; }
A function that evaluates to true
if the browser meets all of the inclusion criteria for the experiment, and false
otherwise. The first argument to the function will be an object containing key value pairs with the measured features of the browser. The keys will be the same as those listed in features
. See example below. exclusion_message function () => { return <p>Your browser does not meet the requirements to participate in this experiment.</p> }
A function that returns the message to display if inclusion_function
evaluates to false
or if the participant clicks on the resize fail button during the interactive resize. In order to allow customization of the message, the first argument to the function will be an object containing key value pairs with the measured features of the browser. The keys will be the same as those listed in features
. See example below."},{"location":"plugins/browser-check/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value width int The width of the browser window in pixels. If interactive resizing happens, this is the width after resizing. height int The height of the browser window in pixels. If interactive resizing happens, this is the height after resizing. browser string The browser used. browser_version string The version number of the browser. os string The operating system used. mobile bool Whether the browser is a mobile device. webaudio bool Whether the browser supports the WebAudio API. fullscreen bool Whether the browser supports the Fullscreen API. vsync_rate number An estimate of the refresh rate of the screen, in frames per second. webcam bool Whether there is a webcam device available. Note that the participant still must grant permission to access the device before it can be used. microphone bool Whether there is an audio input device available. Note that the participant still must grant permission to access the device before it can be used. Note that all of these values are only recorded when the corresponding key is included in the features
parameter for the trial.
"},{"location":"plugins/browser-check/#simulation-mode","title":"Simulation Mode","text":"In simulation mode the plugin will report the actual features of the browser, with the exception of vsync_rate
, which is always 60.
In data-only
mode, if allow_window_resize
is true and the browser's width and height are below the maximum value then the reported width and height will be equal to minimum_width
and minimum_height
, as if the participant resized the browser to meet the specifications.
In visual
mode, if allow_window_resize
is true and the browser's width and height are below the maximum value then the experiment will wait for 3 seconds before clicking the resize fail button. During this time, you can adjust the window if you would like to.
As with all simulated plugins, you can override the default (actual) data with fake data using simulation_options
. This allows you to test your exclusion criteria by simulating other configurations.
"},{"location":"plugins/browser-check/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-browser-check@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-browser-check.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-browser-check\n
import browserCheck from '@jspsych/plugin-browser-check';\n
"},{"location":"plugins/browser-check/#examples","title":"Examples","text":"Recording all of the available features, no exclusions CodeDemo var trial = {\n type: jsPsychBrowserCheck\n};\n
Open demo in new tab
Using the inclusion function to mandate the use of Chrome or Firefox as the browser CodeDemo var trial = {\n type: jsPsychBrowserCheck,\n inclusion_function: (data) => {\n return ['chrome', 'firefox'].includes(data.browser);\n },\n exclusion_message: (data) => {\n return `<p>You must use Chrome or Firefox to complete this experiment.</p>`\n },\n};\n
Open demo in new tab
Setting a minimum window height & width, with the option to resize the window CodeDemo var trial = {\n type: jsPsychBrowserCheck,\n minimum_width: 1000,\n minimum_height: 600\n};\n
This demo only works in a resizable window. Please open it in new tab
Open demo in new tab
Custom exclusion message based on measured features CodeDemo var trial = {\n type: jsPsychBrowserCheck,\n inclusion_function: (data) => {\n return data.browser == 'chrome' && data.mobile === false\n },\n exclusion_message: (data) => {\n if(data.mobile){\n return '<p>You must use a desktop/laptop computer to participate in this experiment.</p>';\n } else if(data.browser !== 'chrome'){\n return '<p>You must use Chrome as your browser to complete this experiment.</p>'\n }\n }\n};\n
Open demo in new tab
"},{"location":"plugins/call-function/","title":"call-function","text":"Current version: 2.0.0. See version history.
This plugin executes a specified function. This allows the experimenter to run arbitrary code at any point during the experiment.
The function cannot take any arguments. If arguments are needed, then an anonymous function should be used to wrap the function call (see examples below).
"},{"location":"plugins/call-function/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description func function undefined The function to call. async boolean false
Set to true if func
is an asynchoronous function. If this is true, then the first argument passed to func
will be a callback that you should call when the async operation is complete. You can pass data to the callback. See example below."},{"location":"plugins/call-function/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value value any The return value of the called function."},{"location":"plugins/call-function/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-call-function@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-call-function.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-call-function\n
import callFunction from '@jspsych/plugin-call-function';\n
"},{"location":"plugins/call-function/#examples","title":"Examples","text":"Calling a simple function CodeDemo var myfunc = function() {\n return 'you called?';\n}\n\nvar trial = {\n type: jsPsychCallFunction,\n func: myfunc\n}\n
Open demo in new tab
Using an anonymous function to pass variables CodeDemo var myfunc = function(data){\n // data contains all the experiment data so far,\n // so this function could implement code to write\n // the data to a database.\n console.log(data.values())\n}\n\nvar trial = {\n type: jsPsychCallFunction,\n func: function(){ myfunc(jsPsych.data.get()) }\n}\n
Open demo in new tab
Async function call: wait for data to be saved to a server Code There's no demo for this code, because it requires a server to communicate with.
var trial = {\n type: jsPsychCallFunction,\n async: true,\n func: function(done){\n // can perform async operations here like\n // creating an XMLHttpRequest to communicate\n // with a server\n var xhttp = new XMLHttpRequest();\n xhttp.onreadystatechange = function() {\n if (this.readyState == 4 && this.status == 200) {\n var response_data = xhttp.responseText;\n // line below is what causes jsPsych to \n // continue to next trial. response_data\n // will be stored in jsPsych data object.\n done(response_data);\n }\n };\n xhttp.open(\"GET\", \"path_to_server_script.php\", true);\n xhttp.send();\n }\n}\n
Async function call: simulate waiting for an event to finish CodeDemo var trial = {\n type: jsPsychCallFunction,\n async: true,\n func: function(done){\n // generate a delay between 1500 and 3000 milliseconds to simulate \n // waiting for an event to finish after an unknown duration,\n // then move on with the experiment\n var rand_delay = (Math.floor(Math.random() * (3000 - 1500 + 1) + 1500));\n jsPsych.pluginAPI.setTimeout(function() {\n // end the trial and save the delay duration to the data\n done(rand_delay.toString()+\"ms\");\n }, rand_delay)\n }\n};\n
Open demo in new tab
"},{"location":"plugins/canvas-button-response/","title":"canvas-button-response","text":"Current version: 2.0.0. See version history.
This plugin can be used to draw a stimulus on a HTML canvas element, and record a button click response and response time. The canvas stimulus can be useful for displaying dynamic, parametrically-defined graphics, and for controlling the positioning of multiple graphical elements (shapes, text, images). The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the participant has failed to respond within a fixed length of time. One or more button choices will be displayed under the canvas, and the button style can be customized using HTML formatting.
"},{"location":"plugins/canvas-button-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus function undefined The function to draw on the canvas. This function automatically takes a canvas element as its only argument, e.g. function(c) {...}
or function drawStim(c) {...}
, where c
refers to the canvas element. Note that the stimulus function will still generally need to set the correct context itself, using a line like let ctx = c.getContext(\"2d\")
. canvas_size array [500, 500] Array that defines the size of the canvas element in pixels. First value is height, second value is width. choices array of strings [] Labels for the buttons. Each different string in the array will generate a different button. button_html function (choice: string, choice_index: number)=>`<button class=\"jspsych-btn\">${choice}</button>
; A function that generates the HTML for each button in the choices
array. The function gets the string and index of the item in the choices
array and should return valid HTML. If you want to use different markup for each button, you can do that by using a conditional on either parameter. The default parameter returns a button element with the text label of the choice. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., what question to answer). trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, the trial will wait for a response indefinitely. stimulus_duration numeric null How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to hidden
after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. button_layout string 'grid' Setting to 'grid'
will make the container element have the CSS property display: grid
and enable the use of grid_rows
and grid_columns
. Setting to 'flex'
will make the container element have the CSS property display: flex
. You can customize how the buttons are laid out by adding inline CSS in the button_html
parameter. grid_rows number 1 The number of rows in the button grid. Only applicable when button_layout
is set to 'grid'
. If null, the number of rows will be determined automatically based on the number of buttons and the number of columns. grid_columns number null The number of columns in the button grid. Only applicable when button_layout
is set to 'grid'
. If null, the number of columns will be determined automatically based on the number of buttons and the number of rows. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can use this parameter to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete."},{"location":"plugins/canvas-button-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. response numeric Indicates which button the participant pressed. The first button in the choices
array is 0, the second is 1, and so on. Note: the canvas stimulus is not included in the trial data because it is a function. Any stimulus information that should be saved in the trial data can be added via the data
parameter.
"},{"location":"plugins/canvas-button-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-canvas-button-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-canvas-button-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-canvas-button-response\n
import canvasButtonResponse from '@jspsych/plugin-canvas-button-response';\n
"},{"location":"plugins/canvas-button-response/#examples","title":"Examples","text":"Drawing circles based on parameters CodeDemo function filledCirc(canvas, radius, color) {\n var ctx = canvas.getContext(\"2d\");\n ctx.beginPath();\n ctx.arc(150, 150, radius, 0, 2 * Math.PI);\n ctx.fillStyle = color;\n ctx.fill();\n}\n\nvar circle_1 = {\n type: jsPsychCanvasButtonResponse,\n stimulus: function(c) {\n filledCirc(c, 100, 'blue');\n },\n canvas_size: [300, 300],\n choices: ['Red', 'Green', 'Blue'],\n prompt: '<p>What color is the circle?</p>',\n data: {color: 'blue', radius: 100}\n};\n\nvar circle_2 = {\n type: jsPsychCanvasButtonResponse,\n stimulus: function(c) {\n filledCirc(c, 150, 'green');\n },\n canvas_size: [300, 300],\n choices: ['Larger', 'Smaller'],\n stimulus_duration: 1000,\n prompt: '<p>Is this circle larger or smaller than the last one?</p>'+\n '<p>Stimulus will be hidden after 1 second.</p>',\n data: {color: 'green', radius: 150}\n};\n
Open demo in new tab
Using an anonymous stimulus function CodeDemo var lines = {\n type: jsPsychCanvasButtonResponse,\n stimulus: function(c) {\n var ctx = c.getContext(\"2d\");\n // first line\n ctx.beginPath();\n ctx.moveTo(200, 10);\n ctx.lineTo(200, 250);\n ctx.lineWidth = 10;\n ctx.strokeStyle = 'MediumBlue';\n ctx.stroke();\n // second line\n ctx.beginPath();\n ctx.moveTo(20, 100);\n ctx.lineTo(100, 250);\n ctx.lineWidth = 10;\n ctx.strokeStyle = 'MediumPurple';\n ctx.stroke();\n },\n canvas_size: [300, 300],\n choices: ['Blue line', 'Purple line'],\n prompt: '<p>Which line is longer?</p>',\n data: {line1_color: 'blue', line1_length: 290, line2_color: \"purple\", line2_length: 170}\n};\n
Open demo in new tab
Using the canvas stimulus function with timeline variables, and recording the correctness of responses CodeDemo function filledCirc(canvas, radius, color) {\n var ctx = canvas.getContext(\"2d\");\n ctx.beginPath();\n ctx.arc(150, 150, radius, 0, 2 * Math.PI);\n ctx.fillStyle = color;\n ctx.fill();\n}\n\nvar circle_procedure = {\n timeline: [\n {\n type: jsPsychCanvasButtonResponse,\n stimulus: function(c) {\n filledCirc(c, jsPsych.evaluateTimelineVariable('radius'), jsPsych.evaluateTimelineVariable('color'));\n },\n canvas_size: [300, 300],\n choices: ['Red', 'Green', 'Blue'],\n prompt: '<p>What color is the circle?</p>',\n data: {\n radius: jsPsych.timelineVariable('radius'), \n color: jsPsych.timelineVariable('color'),\n correct_response: jsPsych.timelineVariable('correct_response')\n },\n on_finish: function(data){\n data.correct = data.response == data.correct_response;\n }\n }\n ],\n timeline_variables: [\n {radius: 80, color: 'red', correct_response: 0},\n {radius: 100, color: 'green', correct_response: 1},\n {radius: 50, color: 'blue', correct_response: 2}\n ],\n randomize_order: true\n}; \n
Open demo in new tab
"},{"location":"plugins/canvas-keyboard-response/","title":"canvas-keyboard-response","text":"Current version: 2.0.0. See version history.
This plugin can be used to draw a stimulus on a HTML canvas element and record a keyboard response. The canvas stimulus can be useful for displaying dynamic, parametrically-defined graphics, and for controlling the positioning of multiple graphical elements (shapes, text, images). The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the participant has failed to respond within a fixed length of time.
"},{"location":"plugins/canvas-keyboard-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus function undefined The function to draw on the canvas. This function automatically takes a canvas element as its only argument, e.g. function(c) {...}
or function drawStim(c) {...}
, where c
refers to the canvas element. Note that the stimulus function will still generally need to set the correct context itself, using a line like let ctx = c.getContext(\"2d\")
. canvas_size array [500, 500] Array that defines the size of the canvas element in pixels. First value is height, second value is width. choices array of strings \"ALL_KEYS\"
This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., 'a'
, 'q'
, ' '
, 'Enter'
, 'ArrowDown'
) - see this page and this page (event.key column) for more examples. Any key presses that are not listed in the array will be ignored. The default value of \"ALL_KEYS\"
means that all keys will be accepted as valid responses. Specifying \"NO_KEYS\"
will mean that no responses are allowed. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). stimulus_duration numeric null How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to hidden
after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can use this parameter to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete."},{"location":"plugins/canvas-keyboard-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. Note: the canvas stimulus is not included in the trial data because it is a function. Any stimulus information that should be saved in the trial data can be added via the data
parameter.
"},{"location":"plugins/canvas-keyboard-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-canvas-keyboard-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-canvas-keyboard-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-canvas-keyboard-response\n
import canvasKeyboardResponse from '@jspsych/plugin-canvas-keyboard-response';\n
"},{"location":"plugins/canvas-keyboard-response/#examples","title":"Examples","text":"Draw rectangle and wait for response CodeDemo function drawRect(c){\n var ctx = c.getContext('2d');\n ctx.beginPath();\n ctx.rect(30, 30, 200, 50);\n ctx.stroke();\n}\n\nvar trial = {\n type: jsPsychCanvasKeyboardResponse,\n canvas_size: [300, 300],\n stimulus: drawRect,\n choices: ['e','i'],\n prompt: '<p>Is this a circle or a rectangle? Press \"e\" for circle and \"i\" for rectangle.</p>',\n data: {shape: 'rectangle'}\n}\n
Open demo in new tab
Draw circle, no response allowed CodeDemo function drawCirc(c){\n var ctx = c.getContext('2d');\n ctx.beginPath();\n ctx.arc(100, 75, 50, 0, 2 * Math.PI);\n ctx.stroke();\n}\n\nvar trial = {\n type: jsPsychCanvasKeyboardResponse,\n canvas_size: [300, 300],\n stimulus: drawCirc,\n prompt: '<p>No key response is allowed.</p><p>The stimulus disappears after 3 seconds.</p>',\n choices: \"NO_KEYS\",\n trial_duration: 3000,\n data: {shape: 'circle', radius: 50}\n}\n
Open demo in new tab
"},{"location":"plugins/canvas-slider-response/","title":"canvas-slider-response","text":"Current version: 2.0.0. See version history.
This plugin can be used to draw a stimulus on a HTML canvas element and collect a response within a range of values, which is made by dragging a slider. The canvas stimulus can be useful for displaying dynamic, parametrically-defined graphics, and for controlling the positioning of multiple graphical elements (shapes, text, images). The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the participant has failed to respond within a fixed length of time.
"},{"location":"plugins/canvas-slider-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus function undefined The function to draw on the canvas. This function automatically takes a canvas element as its only argument, e.g. function(c) {...}
or function drawStim(c) {...}
, where c
refers to the canvas element. Note that the stimulus function will still generally need to set the correct context itself, using a line like let ctx = c.getContext(\"2d\")
. canvas_size array [500, 500] Array that defines the size of the canvas element in pixels. First value is height, second value is width. labels array of strings [] Labels displayed at equidistant locations on the slider. For example, two labels will be placed at the ends of the slider. Three labels would place two at the ends and one in the middle. Four will place two at the ends, and the other two will be at 33% and 67% of the slider width. button_label string 'Continue' Label of the button to end the trial. min integer 0 Sets the minimum value of the slider. max integer 100 Sets the maximum value of the slider. slider_start integer 50 Sets the starting value of the slider. step integer 1 Sets the step of the slider. This is the smallest amount by which the slider can change. slider_width integer null Set the width of the slider in pixels. If left null, then the width will be equal to the widest element in the display. require_movement boolean false If true, the participant must click the slider before clicking the continue button. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., what question to answer). stimulus_duration numeric null How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to hidden
after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can use this parameter to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete."},{"location":"plugins/canvas-slider-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response numeric The numeric value of the slider. rt numeric The time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. Note: the canvas stimulus is not included in the trial data because it is a function. Any stimulus information that should be saved in the trial data can be added via the data
parameter.
"},{"location":"plugins/canvas-slider-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-canvas-slider-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-canvas-slider-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-canvas-slider-response\n
import canvasSliderResponse from '@jspsych/plugin-canvas-slider-response';\n
"},{"location":"plugins/canvas-slider-response/#examples","title":"Examples","text":"Draw two squares CodeDemo var colors = ['#FF3333', '#FF6A33'];\n\nfunction twoSquares(c) { \n var ctx = c.getContext('2d');\n ctx.fillStyle = colors[0];\n ctx.fillRect(200, 70, 40, 40);\n ctx.fillStyle = colors[1];\n ctx.fillRect(260, 70, 40, 40);\n}\n\nvar trial = {\n type: jsPsychCanvasSliderResponse,\n stimulus: twoSquares,\n labels: ['0','10'],\n canvas_size: [150, 500],\n prompt: '<p>How different would you say the colors of these two squares are on a scale from 0 (the same) to 10 (completely different)</p>',\n data: {color1: colors[0], color2: colors[1]}\n}\n
Open demo in new tab
Draw two squares with additional parameters CodeDemo var colors;\n\nfunction twoSquares(c, colors) {\n var ctx = c.getContext('2d');\n ctx.fillStyle = colors[0];\n ctx.fillRect(200, 70, 40, 40);\n ctx.fillStyle = colors[1];\n ctx.fillRect(260, 70, 40, 40);\n}\n\nvar trial = {\n type: jsPsychCanvasSliderResponse,\n stimulus: function(c) {\n colors = ['darkred', 'cyan'];\n twoSquares(c, colors);\n },\n labels: ['Exactly<br>the same','Totally<br>different'],\n canvas_size: [200, 500],\n prompt: '<p>How different would you say the colors of these two squares are?</p>',\n on_finish: function(data) {\n data.color1 = colors[0];\n data.color2 = colors[1];\n }\n};\n
Open demo in new tab
"},{"location":"plugins/categorize-animation/","title":"categorize-animation","text":"Current version: 2.0.0. See version history.
The categorize animation plugin shows a sequence of images at a specified frame rate. The participant responds by pressing a key. Feedback indicating the correctness of the response is given.
"},{"location":"plugins/categorize-animation/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimuli array undefined Each element of the array is a path to an image file. choices array of strings \"ALL_KEYS\"
This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., 'a'
, 'q'
, ' '
, 'Enter'
, 'ArrowDown'
) - see this page and this page (event.key column) for more examples. Any key presses that are not listed in the array will be ignored. The default value of \"ALL_KEYS\"
means that all keys will be accepted as valid responses. Specifying \"NO_KEYS\"
will mean that no responses are allowed. key_answer string undefined The key character indicating the correct response. text_answer string \"\" A text label that describes the correct answer. Used in conjunction with the correct_text
and incorrect_text
parameters. correct_text string \"Correct.\" String to show when the correct answer is given. Can contain HTML formatting. The special string %ANS%
can be used within the string. If present, the plugin will put the text_answer
for the trial in place of the %ANS% string (see example below). incorrect_text string \"Wrong.\" String to show when the wrong answer is given. Can contain HTML formatting. The special string %ANS%
can be used within the string. If present, the plugin will put the text_answer
for the trial in place of the %ANS% string (see example below). frame_time numeric 500 How long to display each image (in milliseconds). sequence_reps numeric 1 How many times to show the entire sequence. allow_response_before_complete boolean false If true, the participant can respond before the animation sequence finishes. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus or the end of the animation depending on the allow_response_before_complete parameter. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). feedback_duration numeric 2000 How long to show the feedback (milliseconds). render_on_canvas boolean true If true, the images will be drawn onto a canvas element. This prevents a blank screen (white flash) between consecutive images in some browsers, like Firefox and Edge. If false, the image will be shown via an img element, as in previous versions of jsPsych."},{"location":"plugins/categorize-animation/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value stimulus array Array of stimuli displayed in the trial. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. correct boolean true
if the participant got the correct answer, false
otherwise."},{"location":"plugins/categorize-animation/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-categorize-animation@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-categorize-animation.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-categorize-animation\n
import categorizeAnimation from '@jspsych/plugin-categorize-animation';\n
"},{"location":"plugins/categorize-animation/#examples","title":"Examples","text":"Basic example CodeDemo var animation_trial = {\n type: jsPsychCategorizeAnimation,\n stimuli: [\n 'img/happy_face_1.jpg', \n 'img/happy_face_2.jpg', \n 'img/happy_face_3.jpg', \n 'img/happy_face_4.jpg'\n ],\n prompt: `Press the P or Q key.`,\n choices: ['p', 'q'],\n key_answer: 'q', \n};\n
Open demo in new tab
Giving feedback with %ANS%
string CodeDemo var images = [\n 'img/happy_face_1.jpg', \n 'img/happy_face_2.jpg', \n 'img/happy_face_3.jpg', \n 'img/happy_face_4.jpg'\n];\n\nvar animation_trial = {\n type: jsPsychCategorizeAnimation,\n stimuli: images,\n choices: ['p', 'q'],\n prompt: `Press the P or Q key.`,\n key_answer: 'q', \n text_answer: 'Dax', // the label for the sequence is 'Dax'\n correct_text: 'Correct! This was a %ANS%.',\n incorrect_text: 'Incorrect. This was a %ANS%.'\n};\n
Open demo in new tab
"},{"location":"plugins/categorize-html/","title":"categorize-html","text":"Current version: 2.0.0. See version history.
The categorize html plugin shows an HTML object on the screen. The participant responds by pressing a key. Feedback indicating the correctness of the response is given.
"},{"location":"plugins/categorize-html/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus html string undefined The HTML stimulus to display. choices array of strings \"ALL_KEYS\"
This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., 'a'
, 'q'
, ' '
, 'Enter'
, 'ArrowDown'
) - see this page and this page (event.key column) for more examples. Any key presses that are not listed in the array will be ignored. The default value of \"ALL_KEYS\"
means that all keys will be accepted as valid responses. Specifying \"NO_KEYS\"
will mean that no responses are allowed. key_answer string undefined The key character indicating the correct response. text_answer string \"\" A label that is associated with the correct answer. Used in conjunction with the correct_text
and incorrect_text
parameters. correct_text string \"Correct.\" String to show when the correct answer is given. Can contain HTML formatting. The special string %ANS%
can be used within the string. If present, the plugin will put the text_answer
for the trial in place of the %ANS%
string (see example below). incorrect_text string \"Wrong.\" String to show when the wrong answer is given. Can contain HTML formatting. The special string %ANS%
can be used within the string. If present, the plugin will put the text_answer
for the trial in place of the %ANS%
string (see example below). prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). force_correct_button_press boolean false If set to true, then the participant must press the correct response key after feedback is given in order to advance to the next trial. show_stim_with_feedback boolean true If set to true, then the stimulus will be shown during feedback. If false, then only the text feedback will display during feedback. show_feedback_on_timeout boolean false If true, then category feedback will be displayed for an incorrect response after a timeout (trial_duration is exceeded). If false, then a timeout message will be shown. timeout_message string \"Please respond faster.\" The message to show on a timeout non-response. stimulus_duration numeric null How long to show the stimulus for (milliseconds). If null, then the stimulus is shown until a response is given. feedback_duration numeric 2000 How long to show the feedback for (milliseconds). trial_duration numeric null The maximum time allowed for a response. If null, then the experiment will wait indefinitely for a response."},{"location":"plugins/categorize-html/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value stimulus string Either the path to the image file or the string containing the HTML formatted content that the participant saw on this trial. response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. correct boolean true
if the participant got the correct answer, false
otherwise."},{"location":"plugins/categorize-html/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-categorize-html@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-categorize-html.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-categorize-html\n
import categorizeHtml from '@jspsych/plugin-categorize-html';\n
"},{"location":"plugins/categorize-html/#examples","title":"Examples","text":"Categorizing HTML content CodeDemo var categorization_trial = {\n type: jsPsychCategorizeHtml,\n stimulus: '<p>B</p>',\n key_answer: 'p',\n text_answer: 'letter',\n choices: ['p', 'q'],\n correct_text: \"<p class='prompt'>Correct, this is a %ANS%.</p>\",\n incorrect_text: \"<p class='prompt'>Incorrect, this is a %ANS%.</p>\",\n prompt: \"<p>Press p for letter. Press q for number.</p>\"\n };\n
Open demo in new tab
"},{"location":"plugins/categorize-image/","title":"categorize-image","text":"Current version: 2.0.0. See version history.
The categorize image plugin shows an image object on the screen. The participant responds by pressing a key. Feedback indicating the correctness of the response is given.
"},{"location":"plugins/categorize-image/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus string undefined The path to the image file. key_answer string undefined The key character indicating the correct response. choices array of strings \"ALL_KEYS\"
This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., 'a'
, 'q'
, ' '
, 'Enter'
, 'ArrowDown'
) - see this page and this page (event.key column) for more examples. Any key presses that are not listed in the array will be ignored. The default value of \"ALL_KEYS\"
means that all keys will be accepted as valid responses. Specifying \"NO_KEYS\"
will mean that no responses are allowed. text_answer string \"\" A label that is associated with the correct answer. Used in conjunction with the correct_text
and incorrect_text
parameters. correct_text string \"Correct.\" String to show when the correct answer is given. Can contain HTML formatting. The special string %ANS%
can be used within the string. If present, the plugin will put the text_answer
for the trial in place of the %ANS% string (see example below). incorrect_text string \"Wrong.\" String to show when the wrong answer is given. Can contain HTML formatting. The special string %ANS%
can be used within the string. If present, the plugin will put the text_answer
for the trial in place of the %ANS% string (see example below). prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). force_correct_button_press boolean false If set to true, then the participant must press the correct response key after feedback is given in order to advance to the next trial. show_stim_with_feedback boolean true If set to true, then the stimulus will be shown during feedback. If false, then only the text feedback will display during feedback. show_feedback_on_timeout boolean false If true, then category feedback will be displayed for an incorrect response after a timeout (trial_duration is exceeded). If false, then a timeout message will be shown. timeout_message string \"Please respond faster.\" The message to show on a timeout non-response. stimulus_duration numeric null How long to show the stimulus for (milliseconds). If null, then the stimulus is shown until a response is given. feedback_duration numeric 2000 How long to show the feedback for (milliseconds). trial_duration numeric null The maximum time allowed for a response. If null, then the experiment will wait indefinitely for a response."},{"location":"plugins/categorize-image/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value stimulus string Either the path to the image file or the string containing the HTML formatted content that the participant saw on this trial. response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. correct boolean true
if the participant got the correct answer, false
otherwise."},{"location":"plugins/categorize-image/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-categorize-image@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-categorize-image.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-categorize-image\n
import categorizeImage from '@jspsych/plugin-categorize-image';\n
"},{"location":"plugins/categorize-image/#examples","title":"Examples","text":"Categorizing an image CodeDemo var categorization_trial = {\n type: jsPsychCategorizeImage,\n stimulus: 'img/blue.png',\n key_answer: 'b',\n text_answer: 'Blue',\n choices: ['r', 'g', 'b'],\n correct_text: \"<p class='prompt'>Correct! The color is %ANS%.</p>\",\n incorrect_text: \"<p class='prompt'>Incorrect. The color is %ANS%.</p>\",\n prompt: \"<p>Is the color of this circle (R)ed, (G)reen, or (B)lue?</p>\"\n};\n
Open demo in new tab
"},{"location":"plugins/cloze/","title":"cloze","text":"Current version: 2.0.0. See version history.
This plugin displays a text with certain words omitted. Participants are asked to replace the missing items. Responses are recorded when clicking a button. Responses can be evaluated and a function is called in case of either differences or incomplete answers, making it possible to inform participants about mistakes before proceeding.
"},{"location":"plugins/cloze/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description text string undefined The cloze text to be displayed. Blanks are indicated by %% signs and automatically replaced by input fields. If there is a correct answer you want the system to check against, it must be typed between the two percentage signs (i.e. % correct solution %). To input multiple correct answers, add a / between each answer (i.e. %correct/alsocorrect%). button_text string OK Text of the button participants have to press for finishing the cloze test. check_answers boolean false Boolean value indicating if the answers given by participants should be compared against a correct solution given in the text (between % signs) after the button was clicked. If true
, answers are checked and in case of differences, the mistake_fn
is called. In this case, the trial does not automatically finish. If false
, no checks are performed and the trial automatically ends when clicking the button. allow_blanks boolean true Boolean value indicating if the answers given by participants should be checked for completion after the button was clicked. If true
, answers are not checked for completion and blank answers are allowed. The trial will then automatically finish upon the clicking the button. If false
, answers are checked for completion, and in case there are some fields with missing answers, the mistake_fn
is called. In this case, the trial does not automatically finish. case_sensitivity boolean true Boolean value indicating if the answers given by participants should also be checked to have the right case along with correctness. If set to false
, case is disregarded and participants may type in whatever case they please. mistake_fn function function(){}
Function called if check_answers
is set to true
and there is a difference between the participant's answers and the correct solution provided in the text, or if allow_blanks
is set to false
and there is at least one field with a blank answer. autofocus boolean true Boolean value indicating if the first input field should be focused when the trial starts. Enabled by default, but may be disabled especially if participants are using screen readers."},{"location":"plugins/cloze/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response array of strings Answers the partcipant gave"},{"location":"plugins/cloze/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-cloze@2.1.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-cloze.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-cloze\n
import cloze from '@jspsych/plugin-cloze';\n
"},{"location":"plugins/cloze/#examples","title":"Examples","text":"Simple cloze using default settings (no check against correct solution, no custom button text) CodeDemo var cloze_trial = {\n type: jsPsychCloze,\n text: 'The %% is the largest terrestrial mammal. It lives in both %% and %%.'\n };\n
Open demo in new tab
Cloze example using default settings with completion checking and custom error handling CodeDemo var cloze_trial = {\n type: jsPsychCloze,\n text: 'Science notebooks have a %%-colored front cover. Math notebooks have a %%-colored front cover.',\n allow_blanks: false,\n mistake_fn: function() { alert('Please fill in all blanks.'); }\n };\n
Open demo in new tab
More elaborate example (with check against correct solution, custom error handling and modified button text) CodeDemo var cloze_trial = {\n type: jsPsychCloze,\n text: 'A rectangle has % 4 % corners and a triangle has % 3 %.',\n check_answers: true,\n button_text: 'Next',\n mistake_fn: function (){ alert(\"Wrong answer. Please check again.\") }\n };\n
Open demo in new tab
"},{"location":"plugins/external-html/","title":"external-html","text":"Current version: 2.0.0. See version history.
The HTML plugin displays an external HTML document (often a consent form). Either a keyboard response or a button press can be used to continue to the next trial. It allows the experimenter to check if conditions are met (such as indicating informed consent) before continuing.
"},{"location":"plugins/external-html/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description url string undefined The URL of the page to display. cont_key string null The key character the participant can use to advance to the next trial. If left as null, then the participant will not be able to advance trials using the keyboard. cont_btn string null The ID of a clickable element on the page. When the element is clicked, the trial will advance. check_fn function function(){ return true; }
This function is called with the jsPsych display_element
as the only argument when the participant attempts to advance the trial. The trial will only advance if the function return true
. This can be used to verify that the participant has correctly filled out a form before continuing, for example. force_refresh boolean false If true
, then the plugin will avoid using the cached version of the HTML page to load if one exists. execute_script boolean false If true
, then scripts on the remote page will be executed."},{"location":"plugins/external-html/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value url string The URL of the page. rt numeric The response time in milliseconds for the participant to finish the trial."},{"location":"plugins/external-html/#simulation-mode","title":"Simulation Mode","text":"In visual
simulation mode, the plugin cannot interact with any form elements on the screen other than the cont_btn
specified in the trial parameters. If your check_fn
requires other user interaction, for example, clicking a checkbox, then you'll need to disable simulation for the trial and complete the interaction manually.
"},{"location":"plugins/external-html/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-external-html@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-external-html.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-external-html\n
import externalHtml from '@jspsych/plugin-external-html';\n
"},{"location":"plugins/external-html/#examples","title":"Examples","text":""},{"location":"plugins/external-html/#loading-a-consent-form","title":"Loading a consent form","text":""},{"location":"plugins/external-html/#this-content-would-be-in-a-file-called-external_pagehtml","title":"This content would be in a file called 'external_page.html'","text":"<div id=\"consent\">\n <p>\n This is a demo experiment, with this minimal consent form being loaded\n as an external html document. To continue, click the checkbox below\n and hit \"Start Experiment\".\n </p>\n <p>\n <input type=\"checkbox\" id=\"consent_checkbox\" />\n I agree to take part in this study.\n </p>\n <button type=\"button\" id=\"start\">Start Experiment</button>\n</div>\n
jsPsych code to load above page. CodeDemo // sample function that might be used to check if a participant has given\n// consent to participate.\nvar check_consent = function(elem) {\n if (document.getElementById('consent_checkbox').checked) {\n return true;\n }\n else {\n alert(\"If you wish to participate, you must check the box next to the statement 'I agree to participate in this study.'\");\n return false;\n }\n return false;\n};\n\n// declare the block.\nvar trial = {\n type: jsPsychExternalHtml,\n url: \"external_page.html\",\n cont_btn: \"start\",\n check_fn: check_consent\n};\n
Open demo in new tab
"},{"location":"plugins/free-sort/","title":"free-sort","text":"Current version: 2.0.2. See version history.
The free-sort plugin displays one or more images on the screen that the participant can interact with by clicking and dragging with a mouse, or touching and dragging with a touchscreen device. When the trial starts, the images can be positioned outside or inside the sort area. All images must be moved into the sorting area before the participant can click a button to end the trial. All of the moves that the participant performs are recorded, as well as the final positions of all images. This plugin could be useful when asking participants to position images based on similarity to one another, or to recall image spatial locations.
"},{"location":"plugins/free-sort/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimuli array undefined Each element of this array is an image path. stim_height numeric 100 The height of the images in pixels. stim_width numeric 100 The width of the images in pixels. scale_factor numeric 1.5 How much larger to make the stimulus while moving (1 = no scaling). sort_area_height numeric 800 The height of the container that participants can move the stimuli in. Stimuli will be constrained to this area. sort_area_width numeric 800 The width of the container that participants can move the stimuli in. Stimuli will be constrained to this area. sort_area_shape string \"ellipse\" The shape of the sorting area, can be \"ellipse\" or \"square\". prompt string null This string can contain HTML markup. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). prompt_location string \"above\" Indicates whether to show the prompt \"above\"
or \"below\"
the sorting area. button_label string 'Continue' The text that appears on the button to continue to the next trial. change_border_background_color boolean true If true
, the sort area border color will change while items are being moved in and out of the sort area, and the background color will change once all items have been moved into the sort area. If false
, the border will remain black and the background will remain white throughout the trial. border_color_in string '#a1d99b' If change_border_background_color
is true
, the sort area border will change to this color when an item is being moved into the sort area, and the background will change to this color when all of the items have been moved into the sort area. border_color_out string '#fc9272' If change_border_background_color
is true
, this will be the color of the sort area border when there are one or more items that still need to be moved into the sort area. border_width numeric null The width in pixels of the border around the sort area. If null
, the border width will be 3% of the sort_area_height
. counter_text_unfinished string You still need to place %n% item%s% inside the sort area. Text to display when there are one or more items that still need to be placed in the sort area. If \"%n%\" is included in the string, it will be replaced with the number of items that still need to be moved inside. If \"%s%\" is included in the string, a \"s\" will be included when the number of items remaining is greater than one. counter_text_finished string All items placed. Feel free to reposition items if necessary. Text that will take the place of the counter_text_unfinished text when all items have been moved inside the sort area. stim_starts_inside boolean false If false
, the images will be positioned to the left and right of the sort area when the trial loads. If true
, the images will be positioned at random locations inside the sort area when the trial loads. column_spread_factor numeric 1 When the images appear outside the sort area, this determines the x-axis spread of the image columns. Default value is 1. Values less than 1 will compress the image columns along the x-axis, and values greater than 1 will spread them farther apart."},{"location":"plugins/free-sort/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value init_locations array An array containing objects representing the initial locations of all the stimuli in the sorting area. Each element in the array represents a stimulus, and has a \"src\", \"x\", and \"y\" value. \"src\" is the image path, and \"x\" and \"y\" are the object location. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. moves array An array containing objects representing all of the moves the participant made when sorting. Each object represents a move. Each element in the array has a \"src\", \"x\", and \"y\" value. \"src\" is the image path, and \"x\" and \"y\" are the object location after the move. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. final_locations array An array containing objects representing the final locations of all the stimuli in the sorting area. Each element in the array represents a stimulus, and has a \"src\", \"x\", and \"y\" value. \"src\" is the image path, and \"x\" and \"y\" are the object location. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. rt numeric The response time in milliseconds for the participant to finish all sorting."},{"location":"plugins/free-sort/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/free-sort/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-free-sort@2.0.2\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-free-sort.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-free-sort\n
import freeSort from '@jspsych/plugin-free-sort';\n
"},{"location":"plugins/free-sort/#examples","title":"Examples","text":"Basic example CodeDemo var sort_trial = {\n type: jsPsychFreeSort,\n stimuli: sorting_stimuli,\n stim_width: 80,\n stim_height: 60,\n sort_area_width: 500,\n sort_area_height: 500,\n prompt: \"<p>Click and drag the images below to sort them so that similar items are close together.</p>\"\n};\n
Open demo in new tab
"},{"location":"plugins/fullscreen/","title":"fullscreen","text":"Current version: 2.0.0. See version history.
The fullscreen plugin allows the experiment to enter or exit fullscreen mode. For security reasons, all browsers require that entry into fullscreen mode is triggered by a user action. To enter fullscreen mode, this plugin has the user click a button. Exiting fullscreen mode can be done without user input.
Warning
Safari does not support keyboard input when the browser is in fullscreen mode. Therefore, the function will not launch fullscreen mode on Safari. The experiment will ignore any trials using the fullscreen plugin in Safari.
"},{"location":"plugins/fullscreen/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description fullscreen_mode boolean true
A value of true
causes the experiment to enter fullscreen mode. A value of false
causes the browser to exit fullscreen mode. message string <p>The experiment will switch to full screen mode when you press the button below</p>
The HTML content to display above the button to enter fullscreen mode. button_label string 'Continue' The text that appears on the button to enter fullscreen mode. delay_after numeric 1000 The length of time to delay after entering fullscreen mode before ending the trial. This can be useful because entering fullscreen is jarring and most browsers display some kind of message that the browser has entered fullscreen mode."},{"location":"plugins/fullscreen/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value success boolean true if the browser supports fullscreen mode (i.e., is not Safari) rt number Response time to click the button that launches fullscreen mode"},{"location":"plugins/fullscreen/#simulation-mode","title":"Simulation Mode","text":"Web browsers do not allow fullscreen mode to be triggered by a script to avoid malicious usage of fullscreen behavior when the user is not wanting it. In visual
simulation mode, the trial will run normally and the button will get a simulated click, but the display will not change. If you want the display to actually enter fullscreen mode during the simulation, you should disable simulation for the fullscreen trial and manually click the button.
"},{"location":"plugins/fullscreen/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-fullscreen@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-fullscreen.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-fullscreen\n
import fullscreen from '@jspsych/plugin-fullscreen';\n
"},{"location":"plugins/fullscreen/#examples","title":"Examples","text":"Entering and exiting fullscreen CodeDemo var enter_fullscreen = {\n type: jsPsychFullscreen,\n fullscreen_mode: true\n}\n\nvar trial_in_fullscreen = {\n type: jsPsychHtmlButtonResponse,\n stimulus: 'This trial will be in fullscreen mode.',\n choices: ['Continue']\n}\n\nvar exit_fullscreen = {\n type: jsPsychFullscreen,\n fullscreen_mode: false,\n delay_after: 0\n}\n\nvar trial_after_fullscreen = {\n type: jsPsychHtmlButtonResponse,\n stimulus: 'This trial will NOT be in fullscreen mode.',\n choices: ['Continue']\n}\n
Open demo in new tab
"},{"location":"plugins/html-audio-response/","title":"html-audio-response","text":"Current version: 2.0.0. See version history.
This plugin displays HTML content and records audio from the participant via a microphone.
In order to get access to the microphone, you need to use the initialize-microphone plugin on your timeline prior to using this plugin. Once access is granted for an experiment you do not need to get permission again.
This plugin records audio data in base 64 format. This is a text-based representation of the audio which can be coverted to various audio formats using a variety of online tools as well as in languages like python and R.
This plugin will generate a large amount of data, and you will need to be careful about how you handle this data. Even a few seconds of audio recording will add 10s of kB to jsPsych's data. Multiply this by a handful (or more) of trials, and the data objects will quickly get large. If you need to record a lot of audio, either many trials worth or just a few trials with longer responses, we recommend that you save the data to your server immediately after the trial and delete the data in jsPsych's data object. See below for an example of how to do this.
This plugin also provides the option to store the recorded audio files as Object URLs via save_audio_url: true
. This will generate a URL that is storing a copy of the recorded audio, which can be used for subsequent playback. See below for an example where the recorded audio is used as the stimulus in a subsequent trial. This feature is turned off by default because it uses a relatively large amount of memory compared to most jsPsych features. If you are running an experiment where you need this feature and you are recording lots of audio snippets, you may want to manually revoke the URLs when you no longer need them using URL.revokeObjectURL(objectURL)
.
Warning
When recording from a microphone your experiment will need to be running over https://
protocol. If you try to run the experiment locally using the file://
protocol or over http://
protocol you will not be able to access the microphone because of potential security problems.
"},{"location":"plugins/html-audio-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus HTML string undefined The HTML content to be displayed. recording_duration numeric 2000 The maximum length of the recording, in milliseconds. The default value is intentionally set low because of the potential to accidentally record very large data files if left too high. You can set this to null
to allow the participant to control the length of the recording via the done button, but be careful with this option as it can lead to crashing the browser if the participant waits too long to stop the recording. stimulus_duration numeric null How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to hidden
after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. show_done_button bool true Whether to show a button on the screen that the participant can click to finish the recording. done_button_label string 'Continue' The label for the done button. allow_playback bool false Whether to allow the participant to listen to their recording and decide whether to rerecord or not. If true
, then the participant will be shown an interface to play their recorded audio and click one of two buttons to either accept the recording or rerecord. If rerecord is selected, then stimulus will be shown again, as if the trial is starting again from the beginning. record_again_button_label string 'Record again' The label for the record again button enabled when allow_playback: true
. accept_button_label string 'Continue' The label for the accept button enabled when allow_playback: true
. save_audio_url bool false If true
, then an Object URL will be generated and stored for the recorded audio. Only set this to true
if you plan to reuse the recorded audio later in the experiment, as it is a potentially memory-intensive feature."},{"location":"plugins/html-audio-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value rt numeric The time, since the onset of the stimulus, for the participant to click the done button. If the button is not clicked (or not enabled), then rt
will be null
. response base64 string The base64-encoded audio data. stimulus string The HTML content that was displayed on the screen. estimated_stimulus_onset number This is an estimate of when the stimulus appeared relative to the start of the audio recording. The plugin is configured so that the recording should start prior to the display of the stimulus. We have not yet been able to verify the accuracy of this estimate with external measurement devices. audio_url string A URL to a copy of the audio data."},{"location":"plugins/html-audio-response/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/html-audio-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-html-audio-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-html-audio-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-html-audio-response\n
import htmlAudioResponse from '@jspsych/plugin-html-audio-response';\n
"},{"location":"plugins/html-audio-response/#examples","title":"Examples","text":"Simple spoken response to a stimulus CodeDemo var trial = {\n type: jsPsychHtmlAudioResponse,\n stimulus: `\n <p style=\"font-size:48px; color:red;\">GREEN</p>\n <p>Speak the color of the ink.</p>`,\n recording_duration: 3500\n};\n
Open demo in new tab
Allow playback and rerecording; save data to server immediately CodeDemo var trial = {\n type: jsPsychHtmlAudioResponse,\n stimulus: `\n <p>Please sing the first few seconds of a song and click the button when you are done.</p>\n `,\n recording_duration: 15000,\n allow_playback: true,\n on_finish: function(data){\n fetch('/save-my-data.php', { audio_base64: data.response })\n .then((audio_id){\n data.response = audio_id;\n });\n }\n};\n
This example assumes that there is a script on your experiment server that accepts the data called save-my-data.php
. It also assumes that the script will generate a response with an ID for the stored audio file (audio_id
). In the example, we replace the very long base64 representation of the audio file with the generated ID, which could be just a handful of characters. This would let you link files to responses in data analysis, without having to store long audio files in memory during the experiment.
Open demo in new tab
Use recorded audio as a subsequent stimulus CodeDemo var instruction = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `\n <img src='img/10.gif' style=\"width:100px; padding: 20px;\"></img>\n <p>Make up a name for this shape. When you have one in mind, click the button and then say the name aloud.</p>\n `,\n choices: ['I am ready.']\n}\n\nvar record = {\n type: jsPsychHtmlAudioResponse,\n stimulus: `\n <img src='img/10.gif' style=\"width:100px; padding: 20px;\"></img>\n <p>Recording...</p>\n `,\n recording_duration: 1500,\n save_audio_url: true\n};\n\nvar playback = {\n type: jsPsychAudioButtonResponse,\n stimulus: ()=>{\n return jsPsych.data.get().last(1).values()[0].audio_url;\n },\n prompt: '<p>Click the object the matches the spoken name.</p>',\n choices: ['img/9.gif','img/10.gif','img/11.gif','img/12.gif'],\n button_html: (choice) => `<img src=${choice} style=\"width:100px; padding: 20px;\"></img>`\n}\n
Open demo in new tab
"},{"location":"plugins/html-button-response/","title":"html-button-response","text":"Current version: 2.0.0. See version history.
This plugin displays HTML content and records responses generated by button click. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the participant has failed to respond within a fixed length of time. The button itself can be customized using HTML formatting.
"},{"location":"plugins/html-button-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus HTML string undefined The HTML content to be displayed. choices array of strings [] Labels for the buttons. Each different string in the array will generate a different button. button_html function (choice: string, choice_index: number)=>`<button class=\"jspsych-btn\">${choice}</button>
; A function that generates the HTML for each button in the choices
array. The function gets the string and index of the item in the choices
array and should return valid HTML. If you want to use different markup for each button, you can do that by using a conditional on either parameter. The default parameter returns a button element with the text label of the choice. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, the trial will wait for a response indefinitely. stimulus_duration numeric null How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to hidden
after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. button_layout string 'grid' Setting to 'grid'
will make the container element have the CSS property display: grid
and enable the use of grid_rows
and grid_columns
. Setting to 'flex'
will make the container element have the CSS property display: flex
. You can customize how the buttons are laid out by adding inline CSS in the button_html
parameter. grid_rows number 1 The number of rows in the button grid. Only applicable when button_layout
is set to 'grid'
. If null, the number of rows will be determined automatically based on the number of buttons and the number of columns. grid_columns number null The number of columns in the button grid. Only applicable when button_layout
is set to 'grid'
. If null, the number of columns will be determined automatically based on the number of buttons and the number of rows. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can set this parameter to false
to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete. enable_button_after numeric 0 How long the button will delay enabling in milliseconds."},{"location":"plugins/html-button-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. response numeric Indicates which button the participant pressed. The first button in the choices
array is 0, the second is 1, and so on. stimulus string The HTML content that was displayed on the screen."},{"location":"plugins/html-button-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-html-button-response@2.0.1\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-html-button-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-html-button-response\n
import htmlButtonResponse from '@jspsych/plugin-html-button-response';\n
"},{"location":"plugins/html-button-response/#examples","title":"Examples","text":"Displaying question until participant gives a response CodeDemo var trial = {\n type: jsPsychHtmlButtonResponse,\n stimulus: '<p style=\"font-size:48px; color:red;\">GREEN</p>',\n choices: ['Red', 'Green', 'Blue'],\n prompt: \"<p>What color is the ink?</p>\"\n};\n
Open demo in new tab
Using button_html
to generate custom buttons CodeDemo const trial = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `<div style=\"width: 600px\">\n <div style=\"width: 50px; height: 50px; background-color: red; display: inline-block\"></div>\n <div style=\"width: 50px; height: 50px; background-color: red; display: inline-block\"></div>\n <div style=\"width: 50px; height: 50px; background-color: green; display: inline-block\"></div>\n <div style=\"width: 50px; height: 50px; background-color: blue; display: inline-block\"></div>\n <div style=\"width: 50px; height: 50px; background-color: red; display: inline-block\"></div>\n <div style=\"width: 50px; height: 50px; background-color: red; display: inline-block\"></div>\n <div style=\"width: 50px; height: 50px; background-color: green; display: inline-block\"></div>\n <div style=\"width: 50px; height: 50px; background-color: blue; display: inline-block\"></div>\n <div style=\"width: 50px; height: 50px; background-color: red; display: inline-block\"></div>\n <div style=\"width: 50px; height: 50px; background-color: gray; display: inline-block\"></div>\n </div>`,\n choices: ['red', 'green', 'blue'],\n prompt: \"<p>What color should the gray block be?</p>\",\n button_html: (choice) => `<div style=\"width: 80px; height: 80px; margin: 20px; background-color: ${choice}; cursor: pointer;\"></div>`\n};\n
Open demo in new tab
"},{"location":"plugins/html-keyboard-response/","title":"html-keyboard-response","text":"Current version: 2.0.0. See version history.
This plugin displays HTML content and records responses generated with the keyboard.The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the participant has failed to respond within a fixed length of time.
"},{"location":"plugins/html-keyboard-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus HTML string undefined The string to be displayed. choices array of strings \"ALL_KEYS\"
This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., 'a'
, 'q'
, ' '
, 'Enter'
, 'ArrowDown'
) - see this page and this page (event.key column) for more examples. Any key presses that are not listed in the array will be ignored. The default value of \"ALL_KEYS\"
means that all keys will be accepted as valid responses. Specifying \"NO_KEYS\"
will mean that no responses are allowed. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). stimulus_duration numeric null How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to hidden
after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can set this parameter to false
to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete."},{"location":"plugins/html-keyboard-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. stimulus string The HTML content that was displayed on the screen."},{"location":"plugins/html-keyboard-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-html-keyboard-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-html-keyboard-response\n
import htmlKeyboardResponse from '@jspsych/plugin-html-keyboard-response';\n
"},{"location":"plugins/html-keyboard-response/#examples","title":"Examples","text":"Displaying trial until participant gives a response CodeDemo var trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<p style=\"font-size:48px; color:green;\">BLUE</p>',\n choices: ['r', 'g', 'b'],\n prompt: \"<p>Is the ink color (r)ed, (g)reen, or (b)lue?</p>\"\n};\n
Open demo in new tab
Showing a 1 second fixation cross; no response allowed CodeDemo var trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<p style=\"font-size: 48px;\">+</p>',\n choices: \"NO_KEYS\",\n trial_duration: 1000,\n}; \n
Open demo in new tab
"},{"location":"plugins/html-slider-response/","title":"html-slider-response","text":"Current version: 2.0.0. See version history.
This plugin displays HTML content and allows the participant to respond by dragging a slider.
"},{"location":"plugins/html-slider-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus HTML string undefined The string to be displayed labels array of strings [] Labels displayed at equidistant locations on the slider. For example, two labels will be placed at the ends of the slider. Three labels would place two at the ends and one in the middle. Four will place two at the ends, and the other two will be at 33% and 67% of the slider width. button_label string 'Continue' Label of the button to end the trial. min integer 0 Sets the minimum value of the slider. max integer 100 Sets the maximum value of the slider. slider_start integer 50 Sets the starting value of the slider step integer 1 Sets the step of the slider. This is the smallest amount by which the slider can change. slider_width integer null Set the width of the slider in pixels. If left null, then the width will be equal to the widest element in the display. require_movement boolean false If true, the participant must move the slider before clicking the continue button. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). stimulus_duration numeric null How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to hidden
after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can set this parameter to false
to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete."},{"location":"plugins/html-slider-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response numeric The numeric value of the slider. rt numeric The time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. stimulus string The HTML content that was displayed on the screen. slider_start numeric The starting value of the slider."},{"location":"plugins/html-slider-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-html-slider-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-html-slider-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-html-slider-response\n
import htmlSliderResponse from '@jspsych/plugin-html-slider-response';\n
"},{"location":"plugins/html-slider-response/#examples","title":"Examples","text":"Displaying question until participant moves the slider CodeDemo var trial = {\n type: jsPsychHtmlSliderResponse,\n stimulus: `<div style=\"width:500px;\">\n <p>How likely is it that team A will win this match?</p>\n <div style=\"width:240px; float: left;\">\n <p>TEAM A</p>\n <p>10 wins, 5 losses, 6 draws</p>\n </div>\n <div style=\"width:240px; float: right;\">\n <p>TEAM B</p>\n <p>6 wins, 4 losses, 11 draws</p>\n </div>\n </div>`,\n require_movement: true,\n labels: ['100% chance', '50% chance', '0% chance']\n};\n
Open demo in new tab
"},{"location":"plugins/html-video-response/","title":"html-video-response","text":"Current version: 2.0.0. See version history.
This plugin displays HTML content and records video from the participant via a webcam.
In order to get access to the camera, you need to use the initialize-camera plugin on your timeline prior to using this plugin. Once access is granted for an experiment you do not need to get permission again.
This plugin records video data in base 64 format. This is a text-based representation of the video which can be coverted to various video formats using a variety of online tools as well as in languages like python and R.
This plugin will generate a large amount of data, and you will need to be careful about how you handle this data. Even a few seconds of video recording will add 10s of kB to jsPsych's data. Multiply this by a handful (or more) of trials, and the data objects will quickly get large. If you need to record a lot of video, either many trials worth or just a few trials with longer responses, we recommend that you save the data to your server immediately after the trial and delete the data in jsPsych's data object. See below for an example of how to do this.
This plugin also provides the option to store the recorded video files as Object URLs via save_video_url: true
. This will generate a URL that stores a copy of the recorded video, which can be used for subsequent playback during the experiment. See below for an example where the recorded video is used as the stimulus in a subsequent trial. This feature is turned off by default because it uses a relatively large amount of memory compared to most jsPsych features. If you are running an experiment where you need this feature and you are recording lots of video clips, you may want to manually revoke the URLs when you no longer need them using URL.revokeObjectURL(objectURL)
.
Warning
When recording from a camera your experiment will need to be running over https://
protocol. If you try to run the experiment locally using the file://
protocol or over http://
protocol you will not be able to access the camera because of potential security problems.
"},{"location":"plugins/html-video-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus HTML string undefined The HTML content to be displayed. recording_duration numeric 2000 The maximum length of the recording, in milliseconds. The default value is intentionally set low because of the potential to accidentally record very large data files if left too high. You can set this to null
to allow the participant to control the length of the recording via the done button, but be careful with this option as it can lead to crashing the browser if the participant waits too long to stop the recording. stimulus_duration numeric null How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to hidden
after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. show_done_button bool true Whether to show a button on the screen that the participant can click to finish the recording. done_button_label string 'Continue' The label for the done button. allow_playback bool false Whether to allow the participant to listen to their recording and decide whether to rerecord or not. If true
, then the participant will be shown an interface to play their recorded video and click one of two buttons to either accept the recording or rerecord. If rerecord is selected, then stimulus will be shown again, as if the trial is starting again from the beginning. record_again_button_label string 'Record again' The label for the record again button enabled when allow_playback: true
. accept_button_label string 'Continue' The label for the accept button enabled when allow_playback: true
. save_video_url bool false If true
, then an Object URL will be generated and stored for the recorded video. Only set this to true
if you plan to reuse the recorded video later in the experiment, as it is a potentially memory-intensive feature."},{"location":"plugins/html-video-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value rt numeric The time, since the onset of the stimulus, for the participant to click the done button. If the button is not clicked (or not enabled), then rt
will be null
. response base64 string The base64-encoded video data. stimulus string The HTML content that was displayed on the screen. video_url string A URL to a copy of the video data."},{"location":"plugins/html-video-response/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/html-video-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-html-video-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-html-video-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-html-video-response\n
import htmlVideoResponse from '@jspsych/plugin-html-video-response';\n
"},{"location":"plugins/html-video-response/#examples","title":"Examples","text":"Simple recorded response to a stimulus CodeDemo var init_camera = {\n type: jsPsychInitializeCamera\n}\n\nvar trial = {\n type: jsPsychHtmlVideoResponse,\n stimulus: `\n <p style=\"font-size:48px; color:red;\"> <-- </p>\n <p>Turn your head in the direction of the arrow</p>`,\n recording_duration: 3500,\n show_done_button: false,\n};\n
Open demo in new tab
Allow playback and rerecording CodeDemo var init_camera = {\n type: jsPsychInitializeCamera\n}\n\nvar trial = {\n type: jsPsychHtmlVideoResponse,\n stimulus: `<p>Make a sad face</p>`,\n recording_duration: 3500,\n show_done_button: false,\n allow_playback: true\n};\n
Open demo in new tab
Use recorded video as a subsequent stimulus CodeDemo var init_camera = {\n type: jsPsychInitializeCamera\n}\n\nvar record = {\n type: jsPsychHtmlVideoResponse,\n stimulus: `<p>Make a sad face.</p>`,\n recording_duration: 1500,\n show_done_button: false,\n save_video_url: true\n};\n\nvar classify = {\n type: jsPsychVideoButtonResponse,\n stimulus: () => {\n return [jsPsych.data.get().last(1).values()[0].video_url];\n },\n choices: [\"Happy\", \"Sad\", \"Angry\", \"Surprised\"],\n prompt: \"<p>What emotion is this?</p>\",\n}\n
Open demo in new tab
"},{"location":"plugins/iat-html/","title":"iat-html","text":"Current version: 2.0.0. See version history.
This plugin runs a single trial of the implicit association test (IAT), using HTML content as the stimulus.
"},{"location":"plugins/iat-html/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus string undefined The HTML-formatted stimulus to display. html_when_wrong string <span style=\"color: red; font-size: 80px\">X</span>
The content to display when a user presses the wrong key. bottom_instructions string <p>If you press the wrong key, a red X will appear. Press any key to continue.</p>
Instructions about making a wrong key press and whether another key press is needed to continue. force_correct_key_press boolean false If this is true
and the user presses the wrong key then they have to press the other key to continue. An example would be two keys 'e' and 'i'. If the key associated with the stimulus is 'e' and key 'i' was pressed, then pressing 'e' is needed to continue the trial. When this is true
, then parameter key_to_move_forward
is not used. display_feedback boolean false If true
, then html_when_wrong
and wrong_image_name
is required. If false
, trial_duration
is needed and trial will continue automatically. left_category_key string 'e' Key press that is associated with the left_category_label
. right_category_key string 'i' Key press that is associated with the right_category_label
. left_category_label string ['left'] An array that contains the words/labels associated with a certain stimulus. The labels are aligned to the left side of the page. right_category_label string ['right'] An array that contains the words/labels associated with a certain stimulus. The labels are aligned to the right side of the page. stim_key_association string undefined Either 'left' or 'right'. This indicates whether the stimulus is associated with the key press and category on the left or right side of the page (left_category_key
or right_category_key
). key_to_move_forward array of strings \"ALL_KEYS\" This array contains the characters the participant is allowed to press to move on to the next trial if their key press was incorrect and feedback was displayed. Can also have 'other key' as an option which will only allow the user to select the right key to move forward. trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null
for the trial and the trial will end. If the value of this parameter is null
, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can use this parameter to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete."},{"location":"plugins/iat-html/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value stimulus string Either the path to the image file or the string containing the HTML-formatted content that the participant saw on this trial. response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. correct boolean Boolean indicating whether the user's key press was correct or incorrect for the given stimulus."},{"location":"plugins/iat-html/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-iat-html@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-iat-html.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-iat-html\n
import iatHtml from '@jspsych/plugin-iat-html';\n
"},{"location":"plugins/iat-html/#examples","title":"Examples","text":"Displaying IAT question using html CodeDemo var trial = {\n type: jsPsychIatHtml,\n stimulus: 'Joyous',\n stim_key_association: 'left',\n html_when_wrong: '<span style=\"color: red; font-size: 80px\">X</span>',\n bottom_instructions: '<p>If you press the wrong key, a red X will appear. Press the other key to continue</p>',\n force_correct_key_press: true,\n display_feedback: true,\n trial_duration: 3000, //Only if display_feedback is false\n left_category_key: 'e',\n right_category_key: 'i',\n left_category_label: ['OLD','GOOD'],\n right_category_label: ['YOUNG','BAD'],\n response_ends_trial: true\n}\n
Open demo in new tab
"},{"location":"plugins/iat-image/","title":"iat-image","text":"Current version: 2.0.0. See version history.
This plugin runs a single trial of the implicit association test (IAT), using an image as the stimulus.
"},{"location":"plugins/iat-image/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus string undefined The stimulus to display. The path to an image. html_when_wrong string <span style=\"color: red; font-size: 80px\">X</span>
The HTML to display when a user presses the wrong key. bottom_instructions string <p>If you press the wrong key, a red X will appear. Press any key to continue.</p>
Instructions about making a wrong key press and whether another key press is needed to continue. force_correct_key_press boolean false If this is true
and the user presses the wrong key then they have to press the other key to continue. An example would be two keys 'e' and 'i'. If the key associated with the stimulus is 'e' and key 'i' was pressed, then pressing 'e' is needed to continue the trial. When this is true
, then parameter key_to_move_forward
is not used. display_feedback boolean false If true
, then image_when_wrong
and wrong_image_name
are required. If false
, trial_duration
is needed and trial will continue automatically. left_category_key string 'e' Key press that is associated with the left_category_label
. right_category_key string 'i' Key press that is associated with the right_category_label
. left_category_label string ['left'] An array that contains the words/labels associated with a certain stimulus. The labels are aligned to the left side of the page. right_category_label string ['right'] An array that contains the words/labels associated with a certain stimulus. The labels are aligned to the right side of the page. stim_key_association string 'undefined' Either 'left' or 'right'. This indicates whether the stimulus is associated with the key press and category on the left or right side of the page (left_category_key
or right_category_key
). key_to_move_forward array of characters \"ALL_KEYS\" This array contains the characters the participant is allowed to press to move on to the next trial if their key press was incorrect and feedback was displayed. Can also have 'other key' as an option which will only allow the user to select the right key to move forward. trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null
for the trial and the trial will end. If the value of this parameter is null
, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can use this parameter to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete."},{"location":"plugins/iat-image/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value stimulus string Either the path to the image file or the string containing the HTML-formatted content that the participant saw on this trial. response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. correct boolean Boolean indicating whether the user's key press was correct or incorrect for the given image."},{"location":"plugins/iat-image/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-iat-image@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-iat-image.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-iat-image\n
import iatImage from '@jspsych/plugin-iat-image';\n
"},{"location":"plugins/iat-image/#examples","title":"Examples","text":"Displaying IAT question using image files CodeDemo var trial_block = {\n type: jsPsychIatImage,\n stimulus: 'img/iat_old_face.jpg',\n stim_key_association: 'left',\n html_when_wrong: '<span style=\"color: red; font-size: 80px\">X</span>',\n bottom_instructions: '<p>If you press the wrong key, a red X will appear. Press the other key to continue</p>',\n force_correct_key_press: true,\n display_feedback: true,\n trial_duration: 3000, //Only if display_feedback is false\n left_category_key: 'e',\n right_category_key: 'i',\n left_category_label: ['OLD','GOOD'],\n right_category_label: ['YOUNG','BAD'],\n response_ends_trial: true\n}\n
Open demo in new tab
"},{"location":"plugins/image-button-response/","title":"image-button-response","text":"Current version: 2.0.0. See version history.
This plugin displays an image and records responses generated with a button click. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the participant has failed to respond within a fixed length of time. The button itself can be customized using HTML formatting.
Image files can be automatically preloaded by jsPsych using the preload
plugin. However, if you are using timeline variables or another dynamic method to specify the image stimulus, you will need to manually preload the images.
"},{"location":"plugins/image-button-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus string undefined The path of the image file to be displayed. stimulus_height integer null Set the height of the image in pixels. If left null (no value specified), then the image will display at its natural height. stimulus_width integer null Set the width of the image in pixels. If left null (no value specified), then the image will display at its natural width. maintain_aspect_ratio boolean true If setting only the width or only the height and this parameter is true, then the other dimension will be scaled to maintain the image's aspect ratio. choices array of strings [] Labels for the buttons. Each different string in the array will generate a different button. button_html function (choice: string, choice_index: number)=>`<button class=\"jspsych-btn\">${choice}</button>
; A function that generates the HTML for each button in the choices
array. The function gets the string and index of the item in the choices
array and should return valid HTML. If you want to use different markup for each button, you can do that by using a conditional on either parameter. The default parameter returns a button element with the text label of the choice. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). stimulus_duration numeric null How long to show the stimulus for in milliseconds. If the value is null, then the stimulus will be shown until the participant makes a response. trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, the trial will wait for a response indefinitely. button_layout string 'grid' Setting to 'grid'
will make the container element have the CSS property display: grid
and enable the use of grid_rows
and grid_columns
. Setting to 'flex'
will make the container element have the CSS property display: flex
. You can customize how the buttons are laid out by adding inline CSS in the button_html
parameter. grid_rows number 1 The number of rows in the button grid. Only applicable when button_layout
is set to 'grid'
. If null, the number of rows will be determined automatically based on the number of buttons and the number of columns. grid_columns number null The number of columns in the button grid. Only applicable when button_layout
is set to 'grid'
. If null, the number of columns will be determined automatically based on the number of buttons and the number of rows. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can set this parameter to false
to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete. render_on_canvas boolean true If true, the image will be drawn onto a canvas element. This prevents a blank screen (white flash) between consecutive image trials in some browsers, like Firefox and Edge. If false, the image will be shown via an img element, as in previous versions of jsPsych. If the stimulus is an animated gif, you must set this parameter to false, because the canvas rendering method will only present static images. enable_button_after numeric 0 How long the button will delay enabling in milliseconds."},{"location":"plugins/image-button-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. response numeric Indicates which button the participant pressed. The first button in the choices
array is 0, the second is 1, and so on. stimulus string The path of the image that was displayed."},{"location":"plugins/image-button-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-image-button-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-image-button-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-image-button-response\n
import imageButtonResponse from '@jspsych/plugin-image-button-response';\n
"},{"location":"plugins/image-button-response/#examples","title":"Examples","text":"Displaying question until participant gives a response CodeDemo var trial = {\n type: jsPsychImageButtonResponse,\n stimulus: 'img/happy_face_1.png',\n choices: ['Happy', 'Sad'],\n prompt: \"<p>Is this person happy or sad?</p>\"\n};\n
Open demo in new tab
"},{"location":"plugins/image-keyboard-response/","title":"image-keyboard-response","text":"Current version: 2.0.0. See version history.
This plugin displays an image and records responses generated with the keyboard. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically if the participant has failed to respond within a fixed length of time.
Image files can be automatically preloaded by jsPsych using the preload
plugin. However, if you are using timeline variables or another dynamic method to specify the image stimulus, you will need to manually preload the images.
"},{"location":"plugins/image-keyboard-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus string undefined The path of the image file to be displayed. stimulus_height integer null Set the height of the image in pixels. If left null (no value specified), then the image will display at its natural height. stimulus_width integer null Set the width of the image in pixels. If left null (no value specified), then the image will display at its natural width. maintain_aspect_ratio boolean true If setting only the width or only the height and this parameter is true, then the other dimension will be scaled to maintain the image's aspect ratio. choices array of strings \"ALL_KEYS\"
This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., 'a'
, 'q'
, ' '
, 'Enter'
, 'ArrowDown'
) - see this page and this page (event.key column) for more examples. Any key presses that are not listed in the array will be ignored. The default value of \"ALL_KEYS\"
means that all keys will be accepted as valid responses. Specifying \"NO_KEYS\"
will mean that no responses are allowed. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). stimulus_duration numeric null How long to show the stimulus for in milliseconds. If the value is null
, then the stimulus will be shown until the participant makes a response. trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null
, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can set this parameter to false
to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete. render_on_canvas boolean true If true
, the image will be drawn onto a canvas element. This prevents a blank screen (white flash) between consecutive image trials in some browsers, like Firefox and Edge. If false
, the image will be shown via an img element, as in previous versions of jsPsych. If the stimulus is an animated gif, you must set this parameter to false, because the canvas rendering method will only present static images."},{"location":"plugins/image-keyboard-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. stimulus string The path of the image that was displayed."},{"location":"plugins/image-keyboard-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-image-keyboard-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-image-keyboard-response\n
import imageKeyboardResponse from '@jspsych/plugin-image-keyboard-response';\n
"},{"location":"plugins/image-keyboard-response/#examples","title":"Examples","text":"Displaying trial until participant gives a response CodeDemo var trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/happy_face_1.png',\n choices: ['e', 'i'],\n prompt: \"<p>Is this person happy or sad? Press 'e' for happy and 'i' for sad.</p>\",\n};\n
Open demo in new tab
Displaying image for a fixed duration; no response allowed CodeDemo var trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/happy_face_1.png',\n choices: \"NO_KEYS\",\n prompt: \"<p>Study this face for 5 seconds.</p>\",\n trial_duration: 5000\n};\n
Open demo in new tab
"},{"location":"plugins/image-slider-response/","title":"image-slider-response","text":"Current version: 2.0.0. See version history.
This plugin displays and image and allows the participant to respond by dragging a slider.
Image files can be automatically preloaded by jsPsych using the preload
plugin. However, if you are using timeline variables or another dynamic method to specify the image stimulus, you will need to manually preload the images.
"},{"location":"plugins/image-slider-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus string undefined The path to the image file to be displayed. stimulus_height integer null Set the height of the image in pixels. If left null (no value specified), then the image will display at its natural height. stimulus_width integer null Set the width of the image in pixels. If left null (no value specified), then the image will display at its natural width. maintain_aspect_ration boolean true If setting only the width or only the height and this parameter is true, then the other dimension will be scaled to maintain the image's aspect ratio. labels array of strings [] Labels displayed at equidistant locations on the slider. For example, two labels will be placed at the ends of the slider. Three labels would place two at the ends and one in the middle. Four will place two at the ends, and the other two will be at 33% and 67% of the slider width. button_label string 'Continue' Label of the button to advance/submit min integer 0 Sets the minimum value of the slider max integer 100 Sets the maximum value of the slider slider_start integer 50 Sets the starting value of the slider step integer 1 Sets the step of the slider slider_width integer null Set the width of the slider in pixels. If left null, then the width will be equal to the widest element in the display. require_movement boolean false If true, the participant must move the slider before clicking the continue button. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). stimulus_duration numeric null How long to show the stimulus for in milliseconds. If the value is null, then the stimulus will be shown until the participant makes a response. trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can set this parameter to false
to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete. render_on_canvas boolean true If true, the image will be drawn onto a canvas element. This prevents a blank screen (white flash) between consecutive image trials in some browsers, like Firefox and Edge. If false, the image will be shown via an img element, as in previous versions of jsPsych. If the stimulus is an animated gif, you must set this parameter to false, because the canvas rendering method will only present static images."},{"location":"plugins/image-slider-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response numeric The numeric value of the slider. rt numeric The time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. stimulus string The path of the image that was displayed. slider_start numeric The starting value of the slider."},{"location":"plugins/image-slider-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-image-slider-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-image-slider-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-image-slider-response\n
import imageSliderResponse from '@jspsych/plugin-image-slider-response';\n
"},{"location":"plugins/image-slider-response/#examples","title":"Examples","text":"Displaying trial until participant gives a response CodeDemo var trial = {\n type: jsPsychImageSliderResponse,\n stimulus: 'img/happy_face_1.png',\n labels: ['happy', 'sad'],\n prompt: \"<p>How happy/sad is this person?</p>\",\n};\n
Open demo in new tab
"},{"location":"plugins/initialize-camera/","title":"initialize-camera","text":"Current version: 1.0.0 See version history.
This plugin asks the participant to grant permission to access a camera. If multiple cameras are connected to the participant's device, then it allows the participant to pick which device to use. Once access is granted for an experiment you do not need to get permission again.
Once the camera is selected with this plugin it can be accessed with jsPsych.pluginAPI.getCameraRecorder()
.
Warning
When recording from a camera your experiment will need to be running over https://
protocol. If you try to run the experiment locally using the file://
protocol or over http://
protocol you will not be able to access the microphone because of potential security problems.
"},{"location":"plugins/initialize-camera/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description device_select_message html string <p>Please select the camera you would like to use.</p>
The message to display when the user is presented with a dropdown list of available devices. button_label sting 'Use this camera.' The label for the select button. include_audio bool false Set to true
to include an audio track in the recordings. width int null Request a specific width for the recording. This is not a guarantee that this width will be used, as it depends on the capabilities of the participant's device. Learn more about MediaRecorder
constraints here. height int null Request a specific height for the recording. This is not a guarantee that this height will be used, as it depends on the capabilities of the participant's device. Learn more about MediaRecorder
constraints here. mime_type string null Set this to use a specific MIME type for the recording. Set the entire type, e.g., 'video/mp4; codecs=\"avc1.424028, mp4a.40.2\"'
."},{"location":"plugins/initialize-camera/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value device_id string The device ID of the selected camera."},{"location":"plugins/initialize-camera/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/initialize-camera/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-initialize-camera@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-initialize-camera.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-initialize-camera\n
import initializeCamera from '@jspsych/plugin-initialize-camera';\n
"},{"location":"plugins/initialize-camera/#examples","title":"Examples","text":"Ask for camera permission CodeDemo var trial = {\n type: jsPsychInitializeCamera\n};\n
Open demo in new tab
"},{"location":"plugins/initialize-microphone/","title":"initialize-microphone","text":"Current version: 2.0.0. See version history.
This plugin asks the participant to grant permission to access a microphone. If multiple microphones are connected to the participant's device, then it allows the participant to pick which device to use. Once access is granted for an experiment you do not need to get permission again.
Once the microphone is selected with this plugin it can be accessed with jsPsych.pluginAPI.getMicrophoneRecorder()
.
Warning
When recording from a microphone your experiment will need to be running over https://
protocol. If you try to run the experiment locally using the file://
protocol or over http://
protocol you will not be able to access the microphone because of potential security problems.
"},{"location":"plugins/initialize-microphone/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description device_select_message html string <p>Please select the microphone you would like to use.</p>
The message to display when the user is presented with a dropdown list of available devices. button_label sting 'Use this microphone.' The label for the select button."},{"location":"plugins/initialize-microphone/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value device_id string The device ID of the selected microphone."},{"location":"plugins/initialize-microphone/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/initialize-microphone/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-initialize-microphone@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-initialize-microphone.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-initialize-microphone\n
import initializeMicrophone from '@jspsych/plugin-initialize-microphone';\n
"},{"location":"plugins/initialize-microphone/#examples","title":"Examples","text":"Ask for microphone permission CodeDemo var trial = {\n type: jsPsychInitializeMicrophone\n};\n
Open demo in new tab
"},{"location":"plugins/instructions/","title":"instructions","text":"Current version: 2.0.1. See version history.
This plugin is for showing instructions to the participant. It allows participants to navigate through multiple pages of instructions at their own pace, recording how long the participant spends on each page. Navigation can be done using the mouse or keyboard. participants can be allowed to navigate forwards and backwards through pages, if desired.
"},{"location":"plugins/instructions/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description pages array undefined Each element of the array is the content for a single page. Each page should be an HTML-formatted string. key_forward string 'ArrowRight' This is the key that the participant can press in order to advance to the next page. This key should be specified as a string (e.g., 'a'
, 'ArrowLeft'
, ' '
, 'Enter'
). key_backward string 'ArrowLeft' This is the key that the participant can press to return to the previous page. This key should be specified as a string (e.g., 'a'
, 'ArrowLeft'
, ' '
, 'Enter'
). allow_backward boolean true If true, the participant can return to previous pages of the instructions. If false, they may only advace to the next page. allow_keys boolean true If true
, the participant can use keyboard keys to navigate the pages. If false
, they may not. show_clickable_nav boolean false If true, then a Previous
and Next
button will be displayed beneath the instructions. Participants can click the buttons to navigate. button_label_previous string 'Previous' The text that appears on the button to go backwards. button_label_next string 'Next' The text that appears on the button to go forwards. show_page_number boolean false If true, and clickable navigation is enabled, then Page x/y will be shown between the nav buttons. page_label string 'Page' The text that appears before x/y pages displayed when show_page_number is true. on_page_change function function (current_page) {}
The function that is called every time the page changes. This function receives a single argument current_page
, which is the index of the current page after page change, and starts at 0
. The function is also called when going forward from the last page, i.e., finishing the trial."},{"location":"plugins/instructions/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value view_history array An array containing the order of pages the participant viewed (including when the participant returned to previous pages) and the time spent viewing each page. Each object in the array represents a single page view, and contains keys called page_index
(the page number, starting with 0) and viewing_time
(duration of the page view). This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. rt numeric The response time in milliseconds for the participant to view all of the pages."},{"location":"plugins/instructions/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-instructions@2.0.1\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-instructions.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-instructions\n
import instructions from '@jspsych/plugin-instructions';\n
"},{"location":"plugins/instructions/#examples","title":"Examples","text":""},{"location":"plugins/instructions/#showing-simple-text-instructions","title":"Showing simple text instructions","text":"Showing simple text instructions CodeDemo var trial = {\n type: jsPsychInstructions,\n pages: [\n 'Welcome to the experiment. Click next to begin.',\n 'This is the second page of instructions.',\n 'This is the final page.'\n ],\n show_clickable_nav: true\n}\n
Open demo in new tab
"},{"location":"plugins/instructions/#including-images","title":"Including images","text":"Including Images CodeDemo var trial = {\n type: jsPsychInstructions,\n pages: [\n 'Welcome to the experiment. Click next to begin.',\n 'You will be looking at images of arrows: ' +\n '<br>' + \n '<img src=\"con2.png\"></img>'\n ],\n show_clickable_nav: true\n}\n
Open demo in new tab
"},{"location":"plugins/instructions/#changing-button-text","title":"Changing Button Text","text":"Changing Button Text CodeDemo var trial = {\n type: jsPsychInstructions,\n pages: [\n 'Welcome to the experiment. Click next to begin.',\n 'This is the second page of instructions.',\n 'This is the final page.'\n ],\n button_label_next: \"Continue\",\n button_label_previous: \"Return to the dark side\",\n show_clickable_nav: true\n}\n
Open demo in new tab
"},{"location":"plugins/list-of-plugins/","title":"List of Plugins","text":"These are the plugins that are included in the jsPsych release.
Additional plugins may be available in the community contributions repository.
For an overview of what plugins are and how they work, see our plugins overview.
Plugin Description animation Shows a sequence of images at a specified frame rate. Records key presses (including timing information) made by the participant while they are viewing the animation. audio\u2011button\u2011response Play an audio file and allow the participant to respond by choosing a button to click. The button can be customized extensively, e.g., using images in place of standard buttons. audio\u2011keyboard\u2011response Play an audio file and allow the participant to respond by pressing a key. audio\u2011slider\u2011response Play an audio file and allow the participant to respond by moving a slider to indicate a value. browser\u2011check Measures various features of the participant's browser and runs an inclusion check to see if the browser meets a custom set of criteria for running the study. call\u2011function Executes an arbitrary function call. Doesn't display anything to the participant, and the participant is usually unaware that this plugin has even executed. It's useful for performing tasks at specified times in the experiment, such as saving data. canvas\u2011button\u2011response Draw a stimulus on a HTML canvas element, and record a button click response. Useful for displaying dynamic, parametrically-defined graphics, and for controlling the positioning of multiple graphical elements (shapes, text, images). canvas\u2011keyboard\u2011response Draw a stimulus on a HTML canvas element, and record a key press response. Useful for displaying dynamic, parametrically-defined graphics, and for controlling the positioning of multiple graphical elements (shapes, text, images). canvas\u2011slider\u2011response Draw a stimulus on a HTML canvas element, and ask the participant to respond by moving a slider to indicate a value. Useful for displaying dynamic, parametrically-defined graphics, and for controlling the positioning of multiple graphical elements (shapes, text, images). categorize\u2011animation The participant responds to an animation and can be given feedback about their response. categorize\u2011html The participant responds to an HTML-formatted stimulus using the keyboard and can be given feedback about the correctness of their response. categorize\u2011image The participant responds to an image using the keyboard and can be given feedback about the correctness of their response. cloze Plugin for displaying a cloze test and checking participants answers against a correct solution. external\u2011html Displays an external HTML page (such as a consent form) and lets the participant respond by clicking a button or pressing a key. Plugin can validate their response, which is useful for making sure that a participant has granted consent before starting the experiment. free\u2011sort Displays a set of images on the screen in random locations. Participants can click and drag the images to move them around the screen. Records all the moves made by the participant, so the sequence of moves can be recovered from the data. fullscreen Toggles the experiment in and out of fullscreen mode. html\u2011audio\u2011response Display an HTML-formatted stimulus and records an audio response via a microphone. html\u2011button\u2011response Display an HTML-formatted stimulus and allow the participant to respond by choosing a button to click. The button can be customized extensively, e.g., using images in place of standard buttons. html\u2011keyboard\u2011response Display an HTML-formatted stimulus and allow the participant to respond by pressing a key. html\u2011slider\u2011response Display an HTML-formatted stimulus and allow the participant to respond by moving a slider to indicate a value. html\u2011video\u2011response Display an HTML-formatted stimulus and records video data via a webcam. iat\u2011html The implicit association task, using HTML-formatted stimuli. iat\u2011image The implicit association task, using images as stimuli. image\u2011button\u2011response Display an image and allow the participant to respond by choosing a button to click. The button can be customized extensively, e.g., using images in place of standard buttons. image\u2011keyboard\u2011response Display an image and allow the participant to respond by pressing a key. image\u2011slider\u2011response Display an image and allow the participant to respond by moving a slider to indicate a value. initialize\u2011camera Request permission to use the participant's camera to record video and allows the participant to choose which camera to use if multiple devices are enabled. Also allows setting the mime type of the recorded video. initialize\u2011microphone Request permission to use the participant's microphone to record audio and allows the participant to choose which microphone to use if multiple devices are enabled. instructions For displaying instructions to the participant. Allows the participant to navigate between pages of instructions using keys or buttons. maxdiff Displays rows of alternatives to be selected for two mutually-exclusive categories, typically as 'most' or 'least' on a particular criteria (e.g. importance, preference, similarity). The participant responds by selecting one radio button corresponding to an alternative in both the left and right response columns. mirror\u2011camera Shows a live feed of the participant's camera on the screen. preload This plugin loads images, audio, and video files into the browser's memory before they are needed in the experiment, in order to improve stimulus and response timing, and to avoid disrupting the flow of the experiment. reconstruction The participant interacts with a stimulus by modifying a parameter of the stimulus and observing the change in the stimulus in real-time. resize Calibrate the display so that materials display with a known physical size. same\u2011different\u2011html A same-different judgment task. An HTML-formatted stimulus is shown, followed by a brief gap, and then another stimulus is shown. The participant indicates whether the stimuli are the same or different. same\u2011different\u2011image A same-different judgment task. An image is shown, followed by a brief gap, and then another stimulus is shown. The participant indicates whether the stimuli are the same or different. serial\u2011reaction\u2011time A set of boxes are displayed on the screen and one of them changes color. The participant presses a key that corresponds to the different color box as fast as possible. serial\u2011reaction\u2011time\u2011mouse A set of boxes are displayed on the screen and one of them changes color. The participants clicks the box that changed color as fast as possible. sketchpad Creates an interactive canvas that the participant can draw on using their mouse or touchscreen. survey\u2011html\u2011form Renders a custom HTML form. Allows for mixing multiple kinds of form input. survey\u2011likert Displays likert-style questions. survey\u2011multi\u2011choice Displays multiple choice questions with one answer allowed per question. survey\u2011multi\u2011select Displays multiple choice questions with multiple answes allowed per question. survey\u2011text Shows a prompt with a text box. The participant writes a response and then submits by clicking a button. video\u2011button\u2011response Displays a video file with many options for customizing playback. participant responds to the video by pressing a button. video\u2011keyboard\u2011response Displays a video file with many options for customizing playback. participant responds to the video by pressing a key. video\u2011slider\u2011response Displays a video file with many options for customizing playback. participant responds to the video by moving a slider. virtual\u2011chinrest An implementation of the \"virutal chinrest\" procedure developed by Li, Joo, Yeatman, and Reinecke (2020). Calibrates the monitor to display items at a known physical size by having participants scale an image to be the same size as a physical credit card. Then uses a blind spot task to estimate the distance between the participant and the display. visual\u2011search\u2011circle A customizable visual-search task modelled after Wang, Cavanagh, & Green (1994). The participant indicates whether or not a target is present among a set of distractors. The stimuli are displayed in a circle, evenly-spaced, equidistant from a fixation point. webgazer\u2011calibrate Calibrates the WebGazer extension for eye tracking. webgazer\u2011init\u2011camera Initializes the camera and helps the participant center their face for eye tracking. webgazer\u2011validate Performs validation to measure precision and accuracy of WebGazer eye tracking predictions."},{"location":"plugins/maxdiff/","title":"maxdiff","text":"Current version: 2.0.2. See version history.
The maxdiff plugin displays a table with rows of alternatives to be selected for two mutually-exclusive categories, typically as 'most' or 'least' on a particular criteria (e.g. importance, preference, similarity). The participant responds by selecting one radio button corresponding to an alternative in both the left and right response columns. The same alternative cannot be endorsed on both the left and right response columns (e.g. 'most' and 'least') simultaneously.
"},{"location":"plugins/maxdiff/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description alternatives array undefined An array of one or more alternatives of string type to fill the rows of the maxdiff table. If required
is true, then the array must contain two or more alternatives, so that at least one can be selected for both the left and right columns. labels array undefined An array with exactly two labels of string type to display as column headings (to the left and right of the alternatives) for responses on the criteria of interest. randomize_alternative_order boolean false
If true, the display order of alternatives
is randomly determined at the start of the trial. preamble string empty string HTML formatted string to display at the top of the page above the maxdiff table. required boolean false
If true, prevents the user from submitting the response and proceeding until a radio button in both the left and right response columns has been selected. button_label string 'Continue' Label of the button."},{"location":"plugins/maxdiff/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the maxdiff table first appears on the screen until the participant's response. labels object An object with two keys, left
and right
, containing the labels (strings) corresponding to the left and right response columns. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. response object An object with two keys, left
and right
, containing the alternatives selected on the left and right columns. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions."},{"location":"plugins/maxdiff/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-maxdiff@2.0.2\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-maxdiff.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-maxdiff\n
import maxdiff from '@jspsych/plugin-maxdiff';\n
"},{"location":"plugins/maxdiff/#examples","title":"Examples","text":"Basic example CodeDemo var maxdiff_page = {\n type: jsPsychMaxdiff,\n alternatives: ['apple', 'orange', 'pear', 'banana'],\n labels: ['Most Preferred', 'Least Preferred'],\n preamble: '<p> Please select your <b>most preferred</b> and <b>least preferred</b> fruits. </p>'\n};\n
Open demo in new tab
"},{"location":"plugins/mirror-camera/","title":"mirror-camera","text":"Current version: 1.0.0 See version history.
This plugin shows a live feed of the participant's camera. It can be useful in experiments that need to record video in order to give the participant a chance to see what is in the view of the camera.
You must initialize the camera using the initialize-camera plugin prior to running this plugin.
Warning
When recording from a camera your experiment will need to be running over https://
protocol. If you try to run the experiment locally using the file://
protocol or over http://
protocol you will not be able to access the camera because of potential security problems.
"},{"location":"plugins/mirror-camera/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description prompt html string null HTML-formatted content to display below the camera feed. width int null The width of the video playback element. If left null
then it will match the size of the recording. height int null The height of the video playback element. If left null
then it will match the size of the recording. button_label string \"Continue\" The label of the button to advance to the next trial. mirror_camera bool true Whether to mirror the video image."},{"location":"plugins/mirror-camera/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value rt int The length of time the participant viewed the video playback."},{"location":"plugins/mirror-camera/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/mirror-camera/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-mirror-camera@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-mirror-camera.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-mirror-camera\n
import mirrorCamera from '@jspsych/plugin-mirror-camera';\n
"},{"location":"plugins/mirror-camera/#examples","title":"Examples","text":"Show the camera feed CodeDemo const init_camera = {\n type: jsPsychInitializeCamera,\n}\n\nconst mirror_camera = {\n type: jsPsychMirrorCamera,\n}\n
Open demo in new tab
"},{"location":"plugins/preload/","title":"preload","text":"Current version: 2.0.0. See version history.
This plugin loads images, audio, and video files. It is used for loading files into the browser's memory before they are needed in the experiment, in order to improve stimulus and response timing, and avoid disruption to the experiment flow. We recommend using this plugin anytime you are loading media files, and especially when your experiment requires large and/or many media files. See the Media Preloading page for more information.
The preload trial will end as soon as all files have loaded successfully. The trial will end or stop with an error message when one of these two scenarios occurs (whichever comes first): (a) all files have not finished loading when the max_load_time
duration is reached, or (b) all file requests have responded with either a load or fail event, and one or more files has failed to load. The continue_after_error
parameter determines whether the trial will stop with an error message or end (allowing the experiment to continue) when preloading is not successful.
"},{"location":"plugins/preload/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. While there are no specific parameters that are required, the plugin expects to be given a set of files to load through one or more of the following parameters: auto_preload
or trials
(for automatic loading), and/or images
, audio
, video
(for manual loading). To automatically load files based on a timeline of trials, either set the auto_preload
parameter is true
(to load files based on the main timeline passed to jsPsych.run
) or use the trials
parameter to load files based on a specific subset of trials. To manually load a set of files, use the images
, audio
, and video
parameters. You can combine automatic and manual loading methods in a single preload trial.
All other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description auto_preload boolean false If true
, the plugin will preload any files that can be automatically preloaded based on the main experiment timeline that is passed to jsPsych.run
. If false
, any file(s) to be preloaded should be specified by passing a timeline array to the trials
parameter and/or an array of file paths to the images
, audio
, and/or video
parameters. Setting this parameter to false
is useful when you plan to preload your files in smaller batches throughout the experiment. trials timeline array [] An array containing one or more jsPsych trial or timeline objects. This parameter is useful when you want to automatically preload stimuli files from a specific subset of the experiment. See Creating an Experiment: The Timeline for information on constructing timelines. images array [] Array containing file paths for one or more image files to preload. This option is typically used for image files that can't be automatically preloaded from the timeline. audio array [] Array containing file paths for one or more audio files to preload. This option is typically used for audio files that can't be automatically preloaded from the timeline. video array [] Array containing file paths for one or more video files to preload. This option is typically used for video files that can't be automatically preloaded from the timeline. message HTML string null HTML-formatted message to show above the progress bar while the files are loading. If null
, then no message is shown. show_progress_bar boolean true If true
, a progress bar will be shown while the files are loading. If false
, no progress bar is shown. continue_after_error boolean false If false
, then the experiment will stop during this trial if either (a) one or more of the files fails to load, and/or (b) all files do not finish loading before the max_load_time
duration is reached. The trial will display the error_message
, as well as the detailed error messages if show_detailed_errors
is true
. If true
, the experiment will continue even if loading fails or times out, and information about loading success/failure will be stored in the trial data (see \"Data Generated\" below). error_message HTML string 'The experiment failed to load.' HTML-formatted message to be shown on the page after loading fails or times out. Only applies when continue_after_error
is false
. show_detailed_errors boolean false If true
, and if continue_after_error
is false
, then a list of detailed errors will be shown below the error_message
. This list will contain the file paths for any files that produced a loading failure, as well as a message indicating that loading timed out, if that was the case. This setting is intended to help the researcher with testing/debugging. If false
, and if continue_after_error
is false
, then only the error_message
will be shown if loading fails or times out. max_load_time numeric null Duration to wait, in milliseconds, for all files to load before loading times out. If one or more files has not finished loading within this time limit, then the trial will stop with an error (if continue_after_error
is false
), or the trial will end with information about the loading time-out in the trial data (see \"Data Generated\" below). If null
, the trial will wait indefinitely for all files to either load or produce an error. on_error function null Function to be called immediately after a file loading request has returned an error. The function receives a single argument, which is the file path that produced the error. This callback is cancelled as soon as the trial ends. See example below. on_success function null Function to be called immediately after a file has successfully loaded. The function receives a single argument, which is the file path that finished loading. This callback is cancelled as soon as the trial ends. See example below."},{"location":"plugins/preload/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value success boolean If true
, then all files loaded successfully within the max_load_time
. If false
, then one or more file requests returned a failure and/or the file loading did not complete within the max_load_time
duration. timeout boolean If true
, then the files did not finish loading within the max_load_time
duration. If false
, then the file loading did not timeout. Note that when the preload trial does not timeout (timeout: false
), it is still possible for loading to fail (success: false
). This happens if one or more files fails to load and all file requests trigger either a success or failure event before the max_load_time
duration. failed_images array One or more image file paths that produced a loading failure before the trial ended. failed_audio array One or more audio file paths that produced a loading failure before the trial ended. failed_video array One or more video file paths that produced a loading failure before the trial ended."},{"location":"plugins/preload/#simulation-mode","title":"Simulation Mode","text":"In visual
simulation mode, the plugin will run the trial as if the experiment was running normally. Specifying simulation_options.data
will not work in visual
mode.
"},{"location":"plugins/preload/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-preload@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-preload.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-preload\n
import preload from '@jspsych/plugin-preload';\n
"},{"location":"plugins/preload/#examples","title":"Examples","text":"Automatically preloading based on other trials CodeDemo var preload = {\n type: jsPsychPreload,\n auto_preload: true\n}\n\nvar trial_1 = {\n type: jsPsychImageButtonResponse,\n stimulus: 'img/happy_face_1.jpg',\n choices: ['Next']\n}\n\nvar trial_2 = {\n type: jsPsychImageButtonResponse,\n stimulus: 'img/happy_face_2.jpg',\n choices: ['Next']\n}\n\nvar trial_3 = {\n type: jsPsychImageButtonResponse,\n stimulus: 'img/happy_face_3.jpg',\n choices: ['Next']\n}\n
The stimulus
parameter from the image-button-response
trials will be automatically preloaded.
Open demo in new tab
Manually preloading an image CodeDemo var preload = {\n type: jsPsychPreload,\n images: ['img/sad_face_1.jpg']\n}\n\nvar trial_1 = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `\n <p>Study this face</p>\n <img src=\"img/sad_face_1.jpg\"></img>\n `,\n choices: ['Next']\n}\n
Because the image is embedded inside HTML from the html-button-response
plugin, it will not be automatically preloaded. Instead we can preload manually.
Open demo in new tab
Loading files in batches CodeDemo var jsPsych = initJsPsych();\n\nvar trial_1 = {\n type: jsPsychImageButtonResponse,\n stimulus: 'img/happy_face_1.jpg',\n choices: ['Next']\n}\n\nvar trial_2 = {\n type: jsPsychImageButtonResponse,\n stimulus: 'img/happy_face_2.jpg',\n choices: ['Next']\n}\n\nvar trial_3 = {\n type: jsPsychImageButtonResponse,\n stimulus: 'img/happy_face_3.jpg',\n choices: ['Next']\n}\n\nvar block_1 = {\n timeline: [trial_1, trial_2, trial_3]\n}\n\nvar trial_4 = {\n type: jsPsychImageButtonResponse,\n stimulus: 'img/sad_face_1.jpg',\n choices: ['Next']\n}\n\nvar trial_5 = {\n type: jsPsychImageButtonResponse,\n stimulus: 'img/sad_face_2.jpg',\n choices: ['Next']\n}\n\nvar trial_6 = {\n type: jsPsychImageButtonResponse,\n stimulus: 'img/sad_face_3.jpg',\n choices: ['Next']\n}\n\nvar block_2 = {\n timeline: [trial_4, trial_5, trial_6]\n}\n\nvar preload_block_1 = {\n type: jsPsychPreload,\n trials: [block_1]\n}\n\nvar preload_block_2 = {\n type: jsPsychPreload,\n trials: [block_2]\n}\n\njsPsych.run([preload_block_1, block_1, preload_block_2, block_2])\n
You can put trials using the preload
plugin throughout your experiment to distribute when files are loaded. In the example above, there are two blocks of trials and the images for each are preloaded just before the corresponding block.
Open demo in new tab
Showing a detailed error message for debugging loading issues CodeDemo var preload = {\n type: jsPsychPreload,\n images: ['img/bad_file_path.png'],\n show_detailed_errors: true\n}\n
Open demo in new tab
For more examples, see the jspsych-preload.html
file in the /examples
folder of the release and the Media Preloading documentation page.
"},{"location":"plugins/reconstruction/","title":"reconstruction","text":"Current version: 2.0.0. See version history.
This plugin allows a participant to interact with a stimulus by modifying a parameter of the stimulus and observing the change in the stimulus in real-time.
The stimulus must be defined through a function that returns an HTML-formatted string. The function should take a single value, which is the parameter that can be modified by the participant. The value can only range from 0 to 1. See the example at the bottom of the page for a sample function.
"},{"location":"plugins/reconstruction/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stim_function function undefined A function with a single parameter that returns an HTML-formatted string representing the stimulus. starting_value numeric 0.5 The starting value of the stimulus parameter. step_size numeric 0.05 The change in the stimulus parameter caused by pressing one of the modification keys. key_increase string 'h' The key to press for increasing the parameter value. key_decrease string 'g' The key to press for decreasing the parameter value. button_label string 'Continue' The text that appears on the button to finish the trial."},{"location":"plugins/reconstruction/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value start_value numeric The starting value of the stimulus parameter. final_value numeric The final value of the stimulus parameter. rt numeric The length of time, in milliseconds, that the trial lasted."},{"location":"plugins/reconstruction/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-reconstruction@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-reconstruction.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-reconstruction\n
import reconstruction from '@jspsych/plugin-reconstruction';\n
"},{"location":"plugins/reconstruction/#examples","title":"Examples","text":"Make a block larger and smaller CodeDemo var sample_function = function(param){\n var size = 50 + Math.floor(param*250);\n var html = '<div style=\"display: block; margin: auto; height: 300px; width: 300px; position: relative;\">'+\n '<div style=\"display: block; position: absolute; top: '+(150 - size/2)+'px; left:'+(150 - size/2)+'px; background-color: #000000; '+\n 'width: '+size+'px; height: '+size+'px;\"></div></div><p>Press \"h\" to make the square larger. Press \"g\" to make the square smaller.</p>'+\n '<p>When the square is the same size as the previous one, click Continue.</p>';\n return html;\n}\n\nvar match_item = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<div style=\"display: block; margin: auto; height: 300px; width: 300px; position: relative;\">'+\n '<div style=\"display: block; position: absolute; top: '+(150 - 210/2)+'px; left:'+(150 - 210/2)+'px; background-color: #000000; '+\n 'width: 210px; height: 210px;\"></div></div>',\n choices: ['c'],\n post_trial_gap: 1250,\n prompt: '<p>Study the size of this square carefully. On the next screen you will have to recreate it. When you are ready, press \"c\".</p>'\n}\n\nvar reconstruction = {\n type: jsPsychReconstruction,\n stim_function: sample_function,\n starting_value: 0.5,\n}\n
Open demo in new tab
"},{"location":"plugins/resize/","title":"resize","text":"Current version: 2.0.0. See version history.
This plugin displays a resizable div container that allows the user to drag until the container is the same size as the item being measured. Once the user measures the item as close as possible, clicking the button sets a scaling factor for the div containing jsPsych content. This causes the stimuli that follow to have a known size, independent of monitor resolution.
"},{"location":"plugins/resize/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description item_height numeric 1 The height of the item to be measured. Any units can be used as long as you are consistent with using the same units for all parameters. item_width numeric 1 The width of the item to be measured. pixels_per_unit numeric 100 After the scaling factor is applied, this many pixels will equal one unit of measurement. prompt string ''
HTML content to display below the resizable box, and above the button. button_label string 'Continue' Label to display on the button to complete calibration. starting_size numeric 100 The initial size of the box, in pixels, along the largest dimension. The aspect ratio will be set automatically to match the item width and height."},{"location":"plugins/resize/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value final_width_px numeric Final width of the resizable div container, in pixels. scale_factor numeric Scaling factor that will be applied to the div containing jsPsych content."},{"location":"plugins/resize/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/resize/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-resize@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-resize.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-resize\n
import resize from '@jspsych/plugin-resize';\n
"},{"location":"plugins/resize/#examples","title":"Examples","text":"Measuring a credit card and resizing the display to have 150 pixels equal an inch. CodeDemo var inputs = {\n type: jsPsychResize,\n item_width: 3 + 3/8,\n item_height: 2 + 1/8,\n prompt: \"<p>Click and drag the lower right corner of the box until the box is the same size as a credit card held up to the screen.</p>\",\n pixels_per_unit: 150\n};\n
Open demo in new tab
"},{"location":"plugins/same-different-html/","title":"same-different-html","text":"Current version: 2.0.0. See version history.
The same-different-html plugin displays two stimuli sequentially. Stimuli are HTML objects. The participant responds using the keyboard, and indicates whether the stimuli were the same or different. Same does not necessarily mean identical; a category judgment could be made, for example.
"},{"location":"plugins/same-different-html/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimuli array undefined A pair of stimuli, represented as an array with two entries, one for each stimulus. A stimulus is a string containing valid HTML markup. Stimuli will be shown in the order that they are defined in the array. answer string undefined Either 'same'
or 'different'
. same_key string 'q' The key that participants should press to indicate that the two stimuli are the same. different_key string 'p' The key that participants should press to indicate that the two stimuli are different. first_stim_duration numeric 1000 How long to show the first stimulus for in milliseconds. If the value of this parameter is null then the stimulus will be shown until the participant presses any key. gap_duration numeric 500 How long to show a blank screen in between the two stimuli. second_stim_duration numeric 1000 How long to show the second stimulus for in milliseconds. If the value of this parameter is null then the stimulus will be shown until the participant responds. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press)."},{"location":"plugins/same-different-html/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value stimulus array An array of length 2 containing the HTML-formatted content that the participant saw for each trial. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the second stimulus first appears on the screen until the participant's response. correct boolean true
if the participant's response matched the answer
for this trial. answer string The correct answer to the trial, either 'same'
or 'different'
. Additionally, if first_stim_duration
is null, then the following data is also collected:
Name Type Value rt_stim1 numeric The response time in milliseconds for the participant to continue after the first stimulus. The time is measured from when the first stimulus appears on the screen until the participant's response. response_stim1 string Indicates which key the participant pressed to continue."},{"location":"plugins/same-different-html/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-same-different-html@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-same-different-html.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-same-different-html\n
import sameDifferentHtml from '@jspsych/plugin-same-different-html';\n
"},{"location":"plugins/same-different-html/#examples","title":"Examples","text":"Two text choices CodeDemo var trial = {\n type: jsPsychSameDifferentHtml,\n stimuli: [\n '<p style=\"font-size:30px;\">Climbing</p>', \n '<p style=\"font-size:30px;\">Walking</p>'\n ],\n prompt: `<p>Press 's' if the activities require the same amount of physical exertion.</p>\n <p>Press 'd' if the activities require different amount of physical exertion.</p>`,\n same_key: 's',\n different_key: 'd',\n first_stim_duration: 800,\n answer: 'different'\n}\n
Open demo in new tab
"},{"location":"plugins/same-different-image/","title":"same-different-image","text":"Current version: 2.0.0. See version history.
The same-different-image plugin displays two stimuli sequentially. Stimuli are images. The participant responds using the keyboard, and indicates whether the stimuli were the same or different. Same does not necessarily mean identical; a category judgment could be made, for example.
"},{"location":"plugins/same-different-image/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimuli array undefined A pair of stimuli, represented as an array with two entries, one for each stimulus. The stimulus is a path to an image file. Stimuli will be shown in the order that they are defined in the array. answer string undefined Either 'same'
or 'different'
. same_key string 'q' The key that participants should press to indicate that the two stimuli are the same. different_key string 'p' The key that participants should press to indicate that the two stimuli are different. first_stim_duration numeric 1000 How long to show the first stimulus for in milliseconds. If the value of this parameter is null then the stimulus will be shown until the participant presses any key. gap_duration numeric 500 How long to show a blank screen in between the two stimuli. second_stim_duration numeric 1000 How long to show the second stimulus for in milliseconds. If the value of this parameter is null then the stimulus will be shown until the participant responds. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press)."},{"location":"plugins/same-different-image/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value stimulus array An array of length 2 containing the paths to the image files that the participant saw for each trial. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the second stimulus first appears on the screen until the participant's response. correct boolean true
if the participant's response matched the answer
for this trial. answer string The correct answer to the trial, either 'same'
or 'different'
. Additionally, if first_stim_duration
is null, then the following data is also collected:
Name Type Value rt_stim1 numeric The response time in milliseconds for the participant to continue after the first stimulus. The time is measured from when the first stimulus appears on the screen until the participant's response. response_stim1 string Indicates which key the participant pressed to continue."},{"location":"plugins/same-different-image/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-same-different-image@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-same-different-image.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-same-different-image\n
import sameDifferentImage from '@jspsych/plugin-same-different-image';\n
"},{"location":"plugins/same-different-image/#examples","title":"Examples","text":"Identifying emotional expressions CodeDemo var trial = {\n type: jsPsychSameDifferentImage,\n stimuli: [\n 'img/happy_face_1.jpg', \n 'img/sad_face_3.jpg'\n ],\n prompt: `<p>Press s if the faces had the same emotional expression.</p>\n <p>Press d if the faces had different emotional expressions.</p>`,\n same_key: 's',\n different_key: 'd',\n first_stim_duration: 800,\n answer: 'different'\n}\n
Open demo in new tab
"},{"location":"plugins/serial-reaction-time-mouse/","title":"serial-reaction-time-mouse","text":"Current version: 2.0.0. See version history.
The serial reaction time mouse plugin implements a generalized version of the SRT task (Nissen & Bullmer, 1987). Squares are displayed in a grid-based system on the screen, and one square changes color. The participant must click on the square that changes color.
"},{"location":"plugins/serial-reaction-time-mouse/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description target array undefined The location of the target. The array should be the [row, column]
of the target. grid array [[1,1,1,1]]
This array represents the grid of boxes shown on the screen. Each inner array represents a single row. The entries in the inner arrays represent the columns. If an entry is 1
then a square will be drawn at that location on the grid. If an entry is 0
then the corresponding location on the grid will be empty. Thus, by mixing 1
s and 0
s it is possible to create many different grid-based arrangements. grid_square_size numeric 100 The width and height in pixels of each square in the grid. target_color hex color code #999
The color of the target square. response_ends_trial boolean true
If true, the trial ends after a mouse click. Feedback is displayed if show_response_feedback
is true. pre_target_duration numeric 0 The number of milliseconds to display the grid before the target changes color. trial_duration numeric null The maximum length of time of the trial, not including feedback. fade_duration numeric null If a positive number, the target will progressively change color at the start of the trial, with the transition lasting this many milliseconds. allow_nontarget_responses boolean false If true, the user can make nontarget response. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which keys to press)."},{"location":"plugins/serial-reaction-time-mouse/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value grid array The grid representation. Each inner array represents a single row. The entries in the inner arrays represent the columns. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. target array The [row, column]
target location on the grid. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the second stimulus first appears on the screen until the participant's response. response array The [row, column]
response location on the grid. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. correct boolean Whether the response location matches the target location (true
) or not (false
)."},{"location":"plugins/serial-reaction-time-mouse/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-serial-reaction-time-mouse@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-serial-reaction-time-mouse.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-serial-reaction-time-mouse\n
import serialReactionTimeMouse from '@jspsych/plugin-serial-reaction-time-mouse';\n
"},{"location":"plugins/serial-reaction-time-mouse/#examples","title":"Examples","text":"A classic version of the SRT CodeDemo var grid = [\n [1,1,1,1]\n]\n\nvar trial_1 = {\n type: jsPsychSerialReactionTimeMouse,\n grid: grid,\n target: [0,0]\n}\nvar trial_2 = {\n type: jsPsychSerialReactionTimeMouse,\n grid: grid,\n target: [0,1]\n}\nvar trial_3 = {\n type: jsPsychSerialReactionTimeMouse,\n grid: grid,\n target: [0,2]\n}\nvar trial_4 = {\n type: jsPsychSerialReactionTimeMouse,\n grid: grid,\n target: [0,3]\n}\n
Open demo in new tab
A 2x2 grid with extra space and different colors CodeDemo var grid = [\n [1,0,1],\n [0,0,0],\n [1,0,1]\n]\n\nvar trial_1 = {\n type: jsPsychSerialReactionTimeMouse,\n grid: grid,\n target: [0,0],\n target_color: '#006738'\n}\nvar trial_2 = {\n type: jsPsychSerialReactionTimeMouse,\n grid: grid,\n target: [0,2],\n target_color: '#F78F1E'\n}\nvar trial_3 = {\n type: jsPsychSerialReactionTimeMouse,\n grid: grid,\n target: [2,2],\n target_color: '#13B24B'\n}\nvar trial_4 = {\n type: jsPsychSerialReactionTimeMouse,\n grid: grid,\n target: [2,0],\n target_color: '#E74921'\n}\n
Open demo in new tab
"},{"location":"plugins/serial-reaction-time/","title":"serial-reaction-time","text":"Current version: 2.0.0. See version history.
The serial reaction time plugin implements a generalized version of the SRT task (Nissen & Bullemer, 1987). Squares are displayed in a grid-based system on the screen, and one square changes color. The participant presses a key that corresponds to the darkened key. Feedback is optionally displayed, showing the participant which square the key they pressed matches.
"},{"location":"plugins/serial-reaction-time/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description target array undefined The location of the target. The array should be the [row, column]
of the target. grid array [[1,1,1,1]]
This array represents the grid of boxes shown on the screen. Each inner array represents a single row. The entries in the inner arrays represent the columns. If an entry is 1
then a square will be drawn at that location on the grid. If an entry is 0
then the corresponding location on the grid will be empty. Thus, by mixing 1
s and 0
s it is possible to create many different grid-based arrangements. choices array of strings [['3','5','7','9']]
The dimensions of this array must match the dimensions of grid
. Each entry in this array is the key that should be pressed for that corresponding location in the grid. Entries can be left blank if there is no key associated with that location of the grid. grid_square_size numeric 100 The width and height in pixels of each square in the grid. target_color hex color code #999
The color of the target square. response_ends_trial boolean true
If true, the trial ends after a key press. Feedback is displayed if show_response_feedback
is true. pre_target_duration numeric 0 The number of milliseconds to display the grid before the target changes color. trial_duration numeric null The maximum length of time of the trial, not including feedback. show_response_feedback boolean false If true, show feedback indicating where the user responded and whether it was correct. feedback_duration numeric 200 The length of time in milliseconds to show the feedback. fade_duration numeric null If a positive number, the target will progressively change color at the start of the trial, with the transition lasting this many milliseconds. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which keys to press)."},{"location":"plugins/serial-reaction-time/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value grid array The representation of the grid. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. target array The representation of the target location on the grid. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the second stimulus first appears on the screen until the participant's response. correct boolean true
if the participant's response matched the target."},{"location":"plugins/serial-reaction-time/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-serial-reaction-time@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-serial-reaction-time.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-serial-reaction-time\n
import serialReactionTime from '@jspsych/plugin-serial-reaction-time';\n
"},{"location":"plugins/serial-reaction-time/#examples","title":"Examples","text":"A classic SRT CodeDemo var instructions = {\n type: jsPsychHtmlButtonResponse,\n stimulus: '<p>Use the S, F, H, and K keys to respond.</p>',\n choices: ['Continue']\n}\n\nvar grid = [\n [1,1,1,1]\n]\n\nvar response_map = [\n ['s','f','h','k']\n]\n\nvar trial_1 = {\n type: jsPsychSerialReactionTime,\n grid: grid,\n choices: response_map,\n target: [0,0]\n}\nvar trial_2 = {\n type: jsPsychSerialReactionTime,\n grid: grid,\n choices: response_map,\n target: [0,1]\n}\nvar trial_3 = {\n type: jsPsychSerialReactionTime,\n grid: grid,\n choices: response_map,\n target: [0,2]\n}\nvar trial_4 = {\n type: jsPsychSerialReactionTime,\n grid: grid,\n choices: response_map,\n target: [0,3]\n}\n
Open demo in new tab
2x2 grid with feedback CodeDemo var instructions = {\n type: jsPsychHtmlButtonResponse,\n stimulus: '<p>Use the R, I, V, and M keys to respond.</p>',\n choices: ['Continue']\n}\n\nvar grid = [\n [1,1],\n [1,1]\n]\n\nvar response_map = [\n ['r','i'],\n ['v','m']\n]\n\nvar trial_1 = {\n type: jsPsychSerialReactionTime,\n grid: grid,\n choices: response_map,\n target: [0,0],\n show_response_feedback: true,\n feedback_duration: 500\n}\nvar trial_2 = {\n type: jsPsychSerialReactionTime,\n grid: grid,\n choices: response_map,\n target: [0,1],\n show_response_feedback: true,\n feedback_duration: 500\n}\nvar trial_3 = {\n type: jsPsychSerialReactionTime,\n grid: grid,\n choices: response_map,\n target: [1,1],\n show_response_feedback: true,\n feedback_duration: 500\n}\nvar trial_4 = {\n type: jsPsychSerialReactionTime,\n grid: grid,\n choices: response_map,\n target: [1,0],\n show_response_feedback: true,\n feedback_duration: 500\n}\n
Open demo in new tab
"},{"location":"plugins/sketchpad/","title":"sketchpad","text":"Current version: 2.0.2. See version history.
This plugin creates an interactive canvas that the participant can draw on using their mouse or touchscreen. It can be used for sketching tasks, like asking the participant to draw a particular object. It can also be used for some image segmentation or annotation tasks by setting the background_image
parameter to render an image on the canvas.
The plugin stores a base 64 data URL representation of the final image. This can be converted to an image file using online tools or short programs in R, python, or another language of your choice. It also records all of the individual strokes that the participant made during the trial.
Warning
This plugin generates a lot of data. Each trial can easily add 500kb+ of data to a final JSON output. You can reduce the amount of data generated by turning off storage of the individual stroke data (save_strokes: false
) or storage of the final image (save_final_image: false
) if your use case doesn't require that information. If you are going to be collecting a lot of data with this plugin you may want to save your data to your server after each trial and not wait until the end of the experiment to perform a single bulk upload. You can do this by putting data saving code inside the on_data_update
event handler.
"},{"location":"plugins/sketchpad/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters.
Parameter Type Default Value Description canvas_shape \"rectangle\"
or \"circle\"
\"rectangle\"
The shape of the canvas element. canvas_width int 500 Width of the canvas in pixels when canvas_shape
is a \"rectangle\"
. canvas_height int 500 Height of the canvas in pixels when canvas_shape
is a \"rectangle\"
. canvas_diameter int 500 Diameter of the canvas in pixels when canvas_shape
is a \"circle\"
. canvas_border_width int 0 Width of the canvas border. canvas_border_color string \"#000\"
Color of the canvas border. background_image image path null
Path to an image to render as the background of the canvas. background_color string \"#fff\"
Color of the canvas background. Note that a background_image
will render on top of the color. stroke_width int 2 Width of the stroke on the canvas. stroke_color string \"#000\"
Color of the stroke on the canvas. stroke_color_palette array of strings []
Array of colors to render as a palette of choices for stroke color. Clicking on the corresponding color button will change the stroke color. prompt string null HTML content to render on the screen. prompt_location \"abovecanvas\"
or \"belowcanvas\"
or \"belowbutton\"
\"abovecanvas\"
The location to render the prompt content. save_final_image bool true Whether to save the final image in the data as a base64 encoded data URL. save_strokes bool true Whether to save the individual stroke data that generated the final image. key_to_draw key string null If this key is held down then it is like the mouse button being held down. The \"ink\" will flow when the button is held and stop when it is lifted. Pass in the string representation of the key, e.g., 'a'
for the A key or ' '
for the spacebar. show_finished_button bool true Whether to show the button that ends the trial. finished_button_label string \"Finished\"
The label for the button that ends the trial. show_clear_button bool true Whether to show the button that clears the entire drawing. clear_button_label string \"Clear\"
The label for the button that clears the entire drawing. show_undo_button bool true Whether to show the button that enables an undo action. undo_button_label string \"Undo\"
The label for the button that enables an undo action. show_redo_button bool true Whether to show the button that enables a redo action. Note that show_undo_button
must be true
for the redo button to show up. redo_button_label string \"Redo\"
The label for the button that enables a redo action. choices array of keys \"NO_KEYS\"
This array contains the key(s) that the participant is allowed to press in order to end the trial. Keys should be specified as characters (e.g., 'a'
, 'q'
, ' '
, 'Enter'
, 'ArrowDown'
) - see this page and this page (event.key column) for more examples. Any key presses that are not listed in the array will be ignored. The default value of \"NO_KEYS\"
means that no keys will be accepted as valid responses. Specifying \"ALL_KEYS\"
will mean that all responses are allowed. trial_duration int null Length of time before the trial ends. If null
the trial will continue indefinitely (until another way of ending the trial occurs). show_countdown_trial_duration bool false Whether to show a timer that counts down until the end of the trial when trial_duration
is not null
. countdown_timer_html string '<span id=\"sketchpad-timer\"></span> remaining'
The HTML to use for rendering the countdown timer. The element with id=\"sketchpad-timer\"
will have its content replaced by a countdown timer in the format MM:SS
."},{"location":"plugins/sketchpad/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value rt int The length of time from the start of the trial to the end of the trial. response string If the trial was ended by clicking the finished button, then \"button\"
. If the trial was ended by pressing a key, then the key that was pressed. If the trial timed out, then null
. png base64 data URL string If save_final_image
is true, then this will contain the base64 encoded data URL for the image, in png format. strokes array of stroke objects If save_strokes
is true, then this will contain an array of stroke objects. Objects have an action
property that is either \"start\"
, \"move\"
, or \"end\"
. If action
is \"start\"
or \"move\"
it will have an x
and y
property that report the coordinates of the action relative to the upper-left corner of the canvas. If action
is \"start\"
then the object will also have a t
and color
property, specifying the time of the action relative to the onset of the trial (ms) and the color of the stroke. If action
is \"end\"
then it will only have a t
property."},{"location":"plugins/sketchpad/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/sketchpad/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-sketchpad@2.0.2\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-sketchpad.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-sketchpad\n
import sketchpad from '@jspsych/plugin-sketchpad';\n
"},{"location":"plugins/sketchpad/#examples","title":"Examples","text":"Basic sketchpad with a prompt CodeDemo var trial = {\n type: jsPsychSketchpad,\n prompt: '<p>Draw an apple!</p>',\n prompt_location: 'abovecanvas',\n canvas_width: 300,\n canvas_height: 300,\n canvas_border_width: 2\n}\n
Open demo in new tab
Image segmentation with different colors CodeDemo var trial = {\n type: jsPsychSketchpad,\n prompt: '<p style=\"width:380px\">Circle the mouth using red. Circle the eyes using blue.</p>',\n prompt_location: 'abovecanvas',\n stroke_color_palette: ['red', 'blue'],\n stroke_color: 'red',\n background_image: 'img/sad_face_4.jpg',\n canvas_width: 380,\n canvas_height: 252\n}\n
Open demo in new tab
Draw an image in a time limit, then display the image and ask for a label. CodeDemo var draw = {\n type: jsPsychSketchpad,\n prompt: '<p>Draw the first animal that comes to mind. You have 30 seconds!</p>',\n prompt_location: 'belowcanvas',\n trial_duration: 30000,\n show_countdown_trial_duration: true,\n}\n\nvar label = {\n type: jsPsychSurveyText,\n preamble: () => {\n var imageData = jsPsych.data.get().last(1).values()[0].png;\n return `<img src=\"${imageData}\"></img>`;\n },\n questions: [\n {prompt: 'What animal did you draw?'}\n ]\n}\n
Open demo in new tab
"},{"location":"plugins/survey-html-form/","title":"survey-html-form","text":"Current version: 2.0.0. See version history.
The survey-html-form plugin displays a set of <inputs>
from a HTML string. The type of input can be freely chosen, for a list of possible input types see the MDN page on inputs. The participant provides answers to the input fields.
"},{"location":"plugins/survey-html-form/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description html string undefined HTML formatted string containing all the input elements to display. Every element has to have its own distinctive name attribute. The <form>
tag must not be included and is generated by the plugin. This string can contain other HTML elements besides the input fields. preamble string empty string HTML formatted string to display at the top of the page above all the questions. button_label string 'Continue' The text that appears on the button to finish the trial. dataAsArray boolean false Retrieve the data as an array e.g. [{name: \"INPUT_NAME\", value: \"INPUT_VALUE\"}, ...] instead of an object e.g. {INPUT_NAME: INPUT_VALUE, ...}. This might be useful if you omit naming your inputs. autofocus string empty string The HTML element ID of a form field to autofocus on. The focused element is the element that will receive keyboard events. For elements like <input type=\"text\">
or <textbox>
, autofocus means that the cursor will appear in the text input area when the trial loads. autocomplete boolean false This determines whether or not all of the input elements on the page should allow autocomplete. Setting this to true will enable autocomplete or auto-fill for the form."},{"location":"plugins/survey-html-form/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response object An object containing the response for each input. The object will have a separate key (variable) for the response to each input, with each variable being named after its corresponding input element. Each response is a string containing whatever the participant answered for this particular input. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. rt numeric The response time in milliseconds for the participant to make a response."},{"location":"plugins/survey-html-form/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/survey-html-form/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-survey-html-form@2.0.1\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-survey-html-form.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-survey-html-form\n
import surveyHtmlForm from '@jspsych/plugin-survey-html-form';\n
"},{"location":"plugins/survey-html-form/#examples","title":"Examples","text":"Fill in the blanks CodeDemo var trial = {\n type: jsPsychSurveyHtmlForm,\n preamble: '<p>How are you feeling <b>right now?</b></p>',\n html: '<p> I am feeling <input name=\"first\" type=\"text\" />, <input name=\"second\" type=\"text\" />, and <input name=\"third\" type=\"text\" />.</p>'\n};\n
Open demo in new tab
Using the autofocus parameter CodeDemo var trial = {\n type: jsPsychSurveyHtmlForm,\n preamble: '<p>What is your favorite bird?</p>',\n html: '<p>My favorite bird is <input type=\"text\" id=\"test-resp-box\" name=\"response\" size=\"10\" /></p>',\n autofocus: 'test-resp-box'\n};\n
In this example, the browser will focus on the element with the ID test-resp-box
when the trial loads. For <input type=\"text\">
elements, this means that the cursor will appear inside the text box.
Open demo in new tab
"},{"location":"plugins/survey-likert/","title":"survey-likert","text":"Current version: 2.0.0. See version history.
The survey-likert plugin displays a set of questions with Likert scale responses. The participant responds by selecting a radio button.
"},{"location":"plugins/survey-likert/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description questions array undefined An array of objects, each object represents a question that appears on the screen. Each object contains a prompt, labels and required parameter that will be applied to the question. See examples below for further clarification.prompt
: Type string, default value is undefined. The strings are the question that will be associated with a slider. labels
: Type array, default value is undefined. Each array element is an array of strings. The innermost arrays contain a set of labels to display for an individual question. If you want to use blank responses and only label the end points or some subset of the options, just insert a blank string for the unlabeled responses.required
: Type boolean, default value is false. Makes answering questions required. name
: Name of the question. Used for storing data. If left undefined then default names (Q0
, Q1
, ...
) will be used for the questions. randomize_question_order boolean false
If true, the display order of questions
is randomly determined at the start of the trial. In the data object, Q0
will still refer to the first question in the array, regardless of where it was presented visually. preamble string empty string HTML formatted string to display at the top of the page above all the questions. scale_width numeric null The width of the likert scale in pixels. If left null
, then the width of the scale will be equal to the width of the widest content on the page. button_label string 'Continue' Label of the button. autocomplete boolean false This determines whether or not all of the input elements on the page should allow autocomplete. Setting this to true will enable autocomplete or auto-fill for the form."},{"location":"plugins/survey-likert/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response object An object containing the response for each question. The object will have a separate key (variable) for each question, with the first question in the trial being recorded in Q0
, the second in Q1
, and so on. The responses are recorded as integers, representing the position selected on the likert scale for that question. If the name
parameter is defined for the question, then the response object will use the value of name
as the key for each question. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the questions first appear on the screen until the participant's response(s) are submitted. question_order array An array with the order of questions. For example [2,0,1]
would indicate that the first question was trial.questions[2]
(the third item in the questions
parameter), the second question was trial.questions[0]
, and the final question was trial.questions[1]
. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions."},{"location":"plugins/survey-likert/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-survey-likert@2.0.1\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-survey-likert.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-survey-likert\n
import surveyLikert from '@jspsych/plugin-survey-likert';\n
"},{"location":"plugins/survey-likert/#examples","title":"Examples","text":"Single Question CodeDemo var trial = {\n type: jsPsychSurveyLikert,\n questions: [\n {\n prompt: \"I like vegetables.\", \n labels: [\n \"Strongly Disagree\", \n \"Disagree\", \n \"Neutral\", \n \"Agree\", \n \"Strongly Agree\"\n ]\n }\n ]\n};\n
Open demo in new tab
Multiple questions in a random order CodeDemo var likert_scale = [\n \"Strongly Disagree\", \n \"Disagree\", \n \"Neutral\", \n \"Agree\", \n \"Strongly Agree\"\n];\n\nvar trial = {\n type: jsPsychSurveyLikert,\n questions: [\n {prompt: \"I like vegetables.\", name: 'Vegetables', labels: likert_scale},\n {prompt: \"I like fruit.\", name: 'Fruit', labels: likert_scale},\n {prompt: \"I like meat.\", name: 'Meat', labels: likert_scale},\n ],\n randomize_question_order: true\n};\n
Open demo in new tab
"},{"location":"plugins/survey-multi-choice/","title":"survey-multi-choice","text":"Current version: 2.0.0. See version history.
The survey-multi-choice plugin displays a set of questions with multiple choice response fields. The participant selects a single answer.
"},{"location":"plugins/survey-multi-choice/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description questions array undefined An array of objects, each object represents a question that appears on the screen. Each object contains a prompt, options, required, and horizontal parameter that will be applied to the question. See examples below for further clarification.prompt
: Type string, default value is undefined. The string is prompt/question that will be associated with a group of options (radio buttons). All questions will get presented on the same page (trial).options
: Type array, defualt value is undefined. An array of strings. The array contains a set of options to display for an individual question.required
: Type boolean, default value is null. The boolean value indicates if a question is required('true') or not ('false'), using the HTML5 required
attribute. If this parameter is undefined, the question will be optional. horizontal
:Type boolean, default value is false. If true, then the question is centered and the options are displayed horizontally. name
: Name of the question. Used for storing data. If left undefined then default names (Q0
, Q1
, ...
) will be used for the questions. randomize_question_order boolean false
If true, the display order of questions
is randomly determined at the start of the trial. In the data object, Q0
will still refer to the first question in the array, regardless of where it was presented visually. preamble string empty string HTML formatted string to display at the top of the page above all the questions. button_label string 'Continue' Label of the button. autocomplete boolean false This determines whether or not all of the input elements on the page should allow autocomplete. Setting this to true will enable autocomplete or auto-fill for the form."},{"location":"plugins/survey-multi-choice/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response object An object containing the response for each question. The object will have a separate key (variable) for each question, with the first question in the trial being recorded in Q0
, the second in Q1
, and so on. The responses are recorded as the name of the option label selected (string). If the name
parameter is defined for the question, then the response object will use the value of name
as the key for each question. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the questions first appear on the screen until the participant's response(s) are submitted. question_order array An array with the order of questions. For example [2,0,1]
would indicate that the first question was trial.questions[2]
(the third item in the questions
parameter), the second question was trial.questions[0]
, and the final question was trial.questions[1]
. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions."},{"location":"plugins/survey-multi-choice/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-survey-multi-choice@2.0.2\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-survey-multi-choice.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-survey-multi-choice\n
import surveyMultiChoice from '@jspsych/plugin-survey-multi-choice';\n
"},{"location":"plugins/survey-multi-choice/#examples","title":"Examples","text":"Vertical Question Alignment CodeDemo var trial = {\n type: jsPsychSurveyMultiChoice,\n questions: [\n {\n prompt: \"Which of the following do you like the most?\", \n name: 'VegetablesLike', \n options: ['Tomato', 'Cucumber', 'Eggplant', 'Corn', 'Peas'], \n required: true\n }, \n {\n prompt: \"Which of the following do you like the least?\", \n name: 'FruitDislike', \n options: ['Apple', 'Banana', 'Orange', 'Grape', 'Strawberry'], \n required: false\n }\n ],\n};\n
Open demo in new tab
Horizontal Question Alignment CodeDemo var trial = {\n type: jsPsychSurveyMultiChoice,\n questions: [\n {\n prompt: \"Which of the following do you like the most?\", \n name: 'VegetablesLike', \n options: ['Tomato', 'Cucumber', 'Eggplant', 'Corn', 'Peas'], \n required: true,\n horizontal: true\n }, \n {\n prompt: \"Which of the following do you like the least?\", \n name: 'FruitDislike', \n options: ['Apple', 'Banana', 'Orange', 'Grape', 'Strawberry'], \n required: false,\n horizontal: true\n }\n ],\n};\n
Open demo in new tab
"},{"location":"plugins/survey-multi-select/","title":"survey-multi-select","text":"Current version: 2.0.0. See version history.
The survey-multi-select plugin displays a set of questions with multiple select response fields. The participant can select multiple answers.
"},{"location":"plugins/survey-multi-select/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description questions array undefined An array of objects, each object represents a question that appears on the screen. Each object contains a prompt, options and horizontal parameter that will be applied to the question. See examples below for further clarification.prompt
: Type string, default value of undefined. The string is the prompt/question that will be associated with a group of options (check boxes). All questions will get presented on the same page (trial).options
: Type array, default value of undefined. The array contains a set of options to display for an individual question.horizontal
: Type boolean, default value of false. If true, the questions are centered and options are displayed horizontally. required
: Type boolean, default value of true. If true, then at least one option must be selected. name
: Name of the question. Used for storing data. If left undefined then default names (Q0
, Q1
, ...
) will be used for the questions. randomize_question_order boolean false
If true, the display order of questions
is randomly determined at the start of the trial. In the data object, Q0
will still refer to the first question in the array, regardless of where it was presented visually. preamble string empty string HTML formatted string to display at the top of the page above all the questions. button_label string 'Continue' Label of the button. required_message string 'You must choose at least one response for this question' Message to display if required response is not given. autocomplete boolean false This determines whether or not all of the input elements on the page should allow autocomplete. Setting this to true will enable autocomplete or auto-fill for the form."},{"location":"plugins/survey-multi-select/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response object An object containing the response for each question. The object will have a separate key (variable) for each question, with the first question in the trial being recorded in Q0
, the second in Q1
, and so on. For each question, the responses are recorded as arrays containing any response options that were selected (strings). If the name
parameter is defined for the question, then the response object will use the value of name
as the key for each question. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the questions first appear on the screen until the participant's response(s) were submitted. question_order array An array with the order of questions. For example [2,0,1]
would indicate that the first question was trial.questions[2]
(the third item in the questions
parameter), the second question was trial.questions[0]
, and the final question was trial.questions[1]
. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions."},{"location":"plugins/survey-multi-select/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-survey-multi-select@2.0.1\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-survey-multi-select.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-survey-multi-select\n
import surveyMultiSelect from '@jspsych/plugin-survey-multi-select';\n
"},{"location":"plugins/survey-multi-select/#examples","title":"Examples","text":"Multiple Questions on a Page CodeDemo var trial = {\n type: jsPsychSurveyMultiSelect,\n questions: [\n {\n prompt: \"Which of these colors do you like?\", \n options: [\"Red\", \"Yellow\", \"Green\", \"Blue\", \"Black\"], \n horizontal: true,\n required: true,\n name: 'Colors'\n }, \n {\n prompt: \"Which of these foods do you like?\", \n options: [\"Apples\", \"Bananas\", \"Carrots\", \"Donuts\", \"Eggplant\"], \n horizontal: true,\n required: true,\n name: 'Foods'\n }\n ], \n randomize_question_order: true\n};\n
Open demo in new tab
"},{"location":"plugins/survey-text/","title":"survey-text","text":"Current version: 2.0.0. See version history.
The survey-text plugin displays a set of questions with free response text fields. The participant types in answers.
"},{"location":"plugins/survey-text/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description questions array undefined An array of objects, each object represents a question that appears on the screen. Each object contains a prompt, placeholder, required, rows, and columns parameter that will be applied to the question. See examples below for further clarification. prompt
: Type string, default value of undefined. The string is the prompt for the participant to respond to. Each question gets its own response field. placeholder
: Type string, default value of \"\"
. The string will create placeholder text in the text field. required
: Boolean; if true
then the user must enter a response to submit. rows
: Type integer, default value of 1. The number of rows for the response text box. columns
: Type integer, default value of 40. The number of columns for the response text box. name
: Name of the question. Used for storing data. If left undefined then default names (Q0
, Q1
, ...
) will be used for the questions. randomize_question_order boolean false
If true, the display order of questions
is randomly determined at the start of the trial. In the data object, Q0
will still refer to the first question in the array, regardless of where it was presented visually. preamble string empty string HTML formatted string to display at the top of the page above all the questions. button_label string 'Continue' The text that appears on the button to finish the trial. autocomplete boolean false This determines whether or not all of the input elements on the page should allow autocomplete. Setting this to true will enable autocomplete or auto-fill for the form."},{"location":"plugins/survey-text/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response object An object containing the response for each question. The object will have a separate key (variable) for each question, with the first question in the trial being recorded in Q0
, the second in Q1
, and so on. For each question, the response is a string containing whatever text was in the response box when the responses were submitted. If the name
parameter is defined for the question, then the response object will use the value of name
as the key for each question. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the questions first appear on the screen until the participant's response(s) were submitted. question_order array An array with the order of questions. For example [2,0,1]
would indicate that the first question was trial.questions[2]
(the third item in the questions
parameter), the second question was trial.questions[0]
, and the final question was trial.questions[1]
. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions."},{"location":"plugins/survey-text/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-survey-text@2.0.1\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-survey-text.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-survey-text\n
import surveyText from '@jspsych/plugin-survey-text';\n
"},{"location":"plugins/survey-text/#examples","title":"Examples","text":"Single question and response CodeDemo var trial = {\n type: jsPsychSurveyText,\n questions: [\n {prompt: 'How old are you?'}\n ]\n}\n
Open demo in new tab
Multiple questions, with an optional placeholder and a required question CodeDemo var trial = {\n type: jsPsychSurveyText,\n questions: [\n {prompt: 'What is your date of birth?', placeholder: 'mm/dd/yyyy', required: true},\n {prompt: 'What country do you currently live in?'}\n ]\n}\n
Open demo in new tab
Naming questions to improve readability of the stored data CodeDemo var trial = {\n type: jsPsychSurveyText,\n questions: [\n {prompt: 'What did you eat for breakfast?', name: 'Breakfast'},\n {prompt: 'What did you eat for lunch?', name: 'Lunch'}\n ]\n}\n
Open demo in new tab
Using the preamble and a longer textbox response CodeDemo var trial = {\n type: jsPsychSurveyText,\n preamble: `<img src=\"img/navarro_burst_03.jpg\" style=\"width:400px;\"></img>`,\n questions: [\n {prompt: 'Describe your reaction to the image above', rows: 5}\n ]\n}\n
The artwork in this demo is by Danielle Navarro
Open demo in new tab
"},{"location":"plugins/survey/","title":"survey","text":"Current version: 2.0.0. See version history.
SurveyJS version: 1.9.138
This plugin is a wrapper for the SurveyJS form library. It displays survey-style questions across one or more pages. You can mix different question types on the same page, and participants can navigate back and forth through multiple survey pages without losing responses. SurveyJS provides a large number of built-in question types, response validation options, conditional display options, special response options (\"None\", \"Select all\", \"Other\"), and other useful features for building complex surveys. See the Building Surveys in jsPsych page for a more detailed list of all options and features.
With SurveyJS, surveys can be defined using a JavaScript/JSON object, a JavaScript function, or a combination of both. The jsPsych survey
plugin provides parameters that accept these methods of constructing a SurveyJS survey, and passes them into SurveyJS. The fact that this plugin just acts as a wrapper means you can take advantage of all of the SurveyJS features, and copy/paste directly from SurveyJS examples into the plugin's survey_json
parameter (for JSON object configuration) or survey_function
parameter (for JavaScript code).
This page contains the plugin's reference information and examples. The Building Surveys in jsPsych page contains a more detailed guide for using this plugin.
For the most comprehensive guides on survey configuration and features, please see the SurveyJS form library documentation and examples.
Limitations
The jsPsych survey
plugin is not compatible with certain jsPsych and SurveyJS features. Specifically:
- It is not always well-suited for use with jsPsych's timeline variables feature. This is because the timeline variables array must store the entire
survey_json
object for each trial, rather than just the parameters that change across trials, which are nested within the survey_json
object. We offer some alternative methods for dynamically constructing questions/trials in this section of the Building Surveys in jsPsych documentation page. - It does not support the SurveyJS \"complete page\" parameter. This is a parameter for HTML formatted content that should appear after the participant clicks the 'submit' button. Instead of using this parameter, you should create another jsPsych trial that comes after the survey trial to serve the same purpose.
- It does not support the SurveyJS question's
correctAnswer
property, which is used for SurveyJS quizzes and automatic response scoring. SurveyJS does not store this value or the response score in the data - instead this is only used to display scores on the survey's 'complete page'. Since the complete page is not supported, this 'correctAnswer' property also does not work as intended in the jsPsych plugin.
"},{"location":"plugins/survey/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
"},{"location":"plugins/survey/#survey-parameters","title":"Survey parameters","text":"Parameter Type Default Value Description survey_json object {}
A SurveyJS-compatible JavaScript object that defines the survey (we refer to this as the survey 'JSON' for consistency with the SurveyJS documentation, but this parameter should be a JSON-compatible JavaScript object rather than a string). If used with the survey_function
parameter, the survey will initially be constructed with this object and then passed to the survey_function
. See the SurveyJS JSON documentation for more information. survey_function function null A function that receives a SurveyJS survey object as an argument. If no survey_json
is specified, then the function receives an empty survey model and must add all pages/elements to it. If a survey_json
object is provided, then this object forms the basis of the survey model that is passed into the survey_function
. See the SurveyJS JavaScript documentation for more information. validation_function function null A function that can be used to validate responses. This function is called whenever the SurveyJS onValidateQuestion
event occurs. (Note: it is also possible to add this function to the survey using the survey_function
parameter - we've just added it as a parameter for convenience)."},{"location":"plugins/survey/#questionelement-types","title":"Question/Element Types","text":"You must add one or more SurveyJS \"element\" to a survey, using the plugin's survey JSON and/or survey function parameter. SurveyJS elements are mostly made up of different question types, but also include non-response content such as HTML and images/video. The Building Surveys in jsPsych page contains more information about how to define survey elements, and you can see some examples in the Examples section on this page.
For reference, the SurveyJS question/element types are listed below, with links to more information and examples in the SurveyJS documentation.
"},{"location":"plugins/survey/#boolean","title":"boolean","text":"The \"boolean\" type is a yes/no (or other two-option) multiple choice question. It differs from the \"radiogroup\" (multiple choice) question type in that it offers different response format options (left/right slider button, yes/no checkbox) in addition to the standard multiple choice format (two separate radio buttons).
- Boolean example
- Boolean API documentation
"},{"location":"plugins/survey/#checkbox","title":"checkbox","text":"This checkbox question type allows participants to select one or more options from the set of choices. You can optionally include special choices, such as \"Select all\", \"None\", and \"Other\" with a text box that appears when selected.
- Checkbox example
- Checkbox API documentation
"},{"location":"plugins/survey/#comment","title":"comment","text":"This is the \"long text\" question type. It's similar to the text input question, but unlike text input, you can make the comment text box larger than a single line. You can also make the box resizeable and limit the number of characters.
- Comment example
- Comment API documentation
"},{"location":"plugins/survey/#dropdown","title":"dropdown","text":"The dropdown question type allows participants to select a single option from a list presented in a drop-down box.
- Dropdown example
- Dropdown API documentation
"},{"location":"plugins/survey/#tagbox","title":"tagbox","text":"This is a multi-select dropdown question type. It is similar to a dropdown question, but allows participants to select more than one response from the drop-down list.
- Tagbox example
- Tagbox API documentation
"},{"location":"plugins/survey/#expression","title":"expression","text":"This is a read-only element that calculates a value based on a specified expression. This question type can be used to dynamically calculate values based on the participant's responses and/or predefined variables and display the calculated value on the page. For example, if you asked participants to estimate the percentage of their day doing various activies, you could have participants enter a percentage value for each activity, and use this 'expression' question to calculate and display the total percentage across all activities (to ensure that it does not exceed 100).
- Expression example
- Expression API documentation
"},{"location":"plugins/survey/#file","title":"file","text":"This question allows participants to upload one or more files (images, documents, etc.). It provides drag-and-drop and browse/select options. Files can be uploaded to a server or stored directly in the survey results JSON object as base64-encoded text.
Note
When using this question type, you will need to choose how to handle the files. One option is to save the file with the rest of the response data as a Base64-encoded text string (storeDataAsText: true
), but keep in mind that this will significantly increase the size of the response data and should only be used for small files. Another option is to upload the participant's file to a server, which you can do using the onUploadFiles
event handler in the jsPsych survey_function
function. You can read more about these options in the SurveyJS file upload documentation, and see an example of the file upload option in the index.js
part of this code example.
- File example
- File API documentation
"},{"location":"plugins/survey/#html","title":"html","text":"Most SurveyJS question types do not support HTML markup in the display fields. The html element allows you to add custom HTML to the survey, so that you can insert images, hyperlinks, etc.
- HTML example
- HTML API documentation
"},{"location":"plugins/survey/#image","title":"image","text":"This element adds an image or video to the survey page.
- Image example
- Image API documentation
"},{"location":"plugins/survey/#imagepicker","title":"imagepicker","text":"This question type displays images/videos and allows the participant to select one or more as their repsonse.
- Imagepicker example
- Imagepicker API documentation
"},{"location":"plugins/survey/#matrix","title":"matrix","text":"The matrix question creates a table of multiple choice questions (rows) that use the same set of response options (columns). This is often used for presenting multiple questions/statements with a Likert or similar rating scale.
- Matrix example
- Matrix API documentation
"},{"location":"plugins/survey/#matrixdropdown","title":"matrixdropdown","text":"This question type allows you to present a matrix (table) of questions, with different types of response options in each cell. Despite the \"dropdown\" part of the question type name, this question type allows not only dropdown questions in the matrix cells, but also checkbox, radiogroup, text, and comment.
- Matrixdropdown example
- Matrixdropdown API documentation
"},{"location":"plugins/survey/#multipletext","title":"multipletext","text":"This question type allows you to present multiple text questions as part of a single 'question', which can be useful if you want to group together related short-answer text input boxes (e.g. separate first/middle/last text boxes for entering full name). Each 'item' within this question type defines a single text question, and supports the text question's input types (email, date, etc.) for built-in formatting and validation. In the results, there will be a single key for this question (either the question name, if specified in the question parameters, otheriwse automatically named questionN
), and the value will be an object with key-value pairs for each text entry 'item' (\"item1Name\": \"item1Response\", \"item2Name\": \"item2Response\"
, etc.).
- Multipletext example
- Multipletext API documentation
"},{"location":"plugins/survey/#panel","title":"panel","text":"This element allows you to group related questions together. This can help with visual organization on the page, and can help participants understand the purpose of a set of questions. Panels appear as a title/description above a box that contains the panel's nested elements/questions. The panel can be initially expanded (show all questions) and collapsed (hide all questions), and users can toggle this state by clicking on the panel title.
- Panel example
- Panel API documentation
"},{"location":"plugins/survey/#paneldynamic","title":"paneldynamic","text":"The paneldyanmic element allows you to set up a group of questions that repeat based on the participant's response(s) to another question. This can be useful when the participant will have an unknown number of responses, and you want to ask the same questions about each response. For instance, you could use this element type to set up a series of questions about the participant's children, employment history, favorite hobbies, etc. The paneldynamic element allows participants to add/delete the 'subpanels' (response and associated question set).
- Paneldynamic example
- Paneldynamic API documentation
"},{"location":"plugins/survey/#radiogroup","title":"radiogroup","text":"This is a multiple choice question type. Participants can select a single option from the set of choices. You can optionally add special choices, such as \"Other\" with a text box that appears when selected.
- Radiogroup example
- Radiogroup API documentation
"},{"location":"plugins/survey/#rating","title":"rating","text":"The rating question type is a type of multiple-choice question that is intended for allowing participants to evaluate something on a scale. The scale can display a range of numbers, graphic symbols (stars, faces), or text labels. The scale options can be presented as a set of horizontal buttons, a drop-down menu, or \"auto\" (displays buttons if there is sufficient page width, otherwise drop-down; see the Rating UI page for more documentation and examples).
- Rating example
- Rating API documentation
"},{"location":"plugins/survey/#ranking","title":"ranking","text":"The ranking question allows participants to arrange a set of choices in order of preference, importance, or other criteria, or assign a numerical value to each choice based on their relative rank. The options are displayed vertically, and participants can drag-and-drop to change their order. This question type can be useful when used with the SurveyJS \"carry forward\" feature. For instance, you can take the participant's responses from a previous checkbox (multi-select) question and use those selections as the options to rank in a ranking question (see the reference_previous_answers.html
example in the jsPsych survey package). It's also possible to combine the selection and ranking steps into a single question using the 'select items to rank' approach, which allows participants to 'select' items by dragging them into a separate ranking area, and re-order the items in the ranking area.
- Ranking example
- Ranking API documentation
"},{"location":"plugins/survey/#signaturepad","title":"signaturepad","text":"The signaturepad question allows participants to add their digital signature to the survey by drawing with the mouse or finger (on a trackpad or touchscreen-enabled device). You can specify the pen color and box size, and save the signature as Base64-encoded text in PNG (default), JPEG, or SVG format. You can also save the image directly to a server rather than encoding it as text with the rest of the response data. See this SurveyJS demo and documentation about uploading the signature as an image file, and the file question for more information and warnings about handling files.
- Signaturepad example
- Signaturepad API documentation
"},{"location":"plugins/survey/#text","title":"text","text":"In addition to a basic text input box, you can select from any of these other input types: color, date, datetime-local, email, month, number, password, range, tel, time, url, week. Setting these input types will change things like (1) the format of the response elements, (2) the characters/values that the participant is allowed to enter, and/or (3) add automatic validation for the response format.
- Text input examples - includes email, password, and URL input types
- Date/time input examples
- Numeric input examples - includes range input (slider) and telephone number input types
- Color input example
- Text API documentation
"},{"location":"plugins/survey/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response object An object containing the response to each question. The object will have a separate key (identifier) for each question. If the name
parameter is defined for the question (recommended), then the response object will use the value of name
as the key for each question. If any questions do not have a name parameter, their keys will named automatically, with the first unnamed question recorded as question1
, the second as question2
, and so on. The response type will depend on the question type. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the questions first appear on the screen until the participant's response(s) are submitted."},{"location":"plugins/survey/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/survey/#css","title":"CSS","text":"This plugin requires an additional stylesheet called survey.css
. You can load it via:
<link rel=\"stylesheet\" href=\"https://unpkg.com/@jspsych/plugin-survey@2.0.1/css/survey.css\">\n
If you are using a bundler such as webpack, you can also import it in JavaScript as follows, depending on your bundler configuration:
import '@jspsych/plugin-survey/css/survey.css'\n
"},{"location":"plugins/survey/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-survey@2.0.1\"></script>\n<link rel=\"stylesheet\" href=\"https://unpkg.com/@jspsych/plugin-survey@2.0.1/css/survey.css\">\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-survey.js\"></script>\n<link rel=\"stylesheet\" href=\"jspsych/plugin-survey.css\">\n
Using NPM:
npm install @jspsych/plugin-survey\n
import survey from '@jspsych/plugin-survey';\nimport '@jspsych/plugin-survey/css/survey.css'\n
"},{"location":"plugins/survey/#examples","title":"Examples","text":"Single page with radiogroup (multiple choice) and checkbox CodeDemo const trial = {\n type: jsPsychSurvey,\n survey_json: {\n showQuestionNumbers: false,\n elements:\n [\n {\n type: 'radiogroup',\n title: \"Which of the following do you like the most?\", \n name: 'vegetablesLike', \n choices: ['Tomato', 'Cucumber', 'Eggplant', 'Corn', 'Peas', 'Broccoli']\n }, \n {\n type: 'checkbox',\n title: \"Which of the following do you like?\", \n name: 'fruitLike', \n description: \"You can select as many as you want.\",\n choices: ['Apple', 'Banana', 'Orange', 'Grape', 'Strawberry', 'Kiwi', 'Mango'], \n showOtherItem: true,\n showSelectAllItem: true,\n showNoneItem: true,\n required: true,\n }\n ]\n }\n};\n
Open demo in new tab
Multiple pages with text and multiple choice questions, and more customization CodeDemo const trial = {\n type: jsPsychSurvey,\n survey_json: {\n showQuestionNumbers: false,\n title: 'My questionnaire',\n completeText: 'Done!',\n pageNextText: 'Continue',\n pagePrevText: 'Previous',\n pages: [\n {\n name: 'page1',\n elements: [\n {\n type: 'text',\n title: 'Where were you born?', \n placeholder: 'City, State/Region, Country',\n name: 'birthplace', \n size: 30,\n isRequired: true,\n }, \n {\n type: 'text',\n title: 'How old are you?', \n name: 'age', \n isRequired: false,\n inputType: 'number',\n min: 0,\n max: 100,\n defaultValue: 0\n }\n ]\n },\n {\n name: 'page2',\n elements: [\n {\n type: 'radiogroup',\n title: \"What's your favorite color?\", \n choices: ['Blue','Yellow','Pink','Teal','Orange','Lime green'],\n showNoneItem: true,\n showOtherItem: true,\n colCount: 0,\n name: 'FavColor',\n }, \n {\n type: 'checkbox',\n title: 'Which of these animals do you like? Select all that apply.', \n choices: ['Lion','Squirrel','Badger','Whale', 'Turtle'],\n choicesOrder: 'random',\n colCount: 0,\n name: 'FavAnimals', \n }\n ]\n }\n ]\n }\n};\n
Open demo in new tab
Rating and matrix questions for Likert-style scales This example shows several different options for presenting a single question/statement with a rating scale (buttons, stars, smileys). It also shows a table of several questions/statements (rows) to be rated on the same scale (columns). Note: This content requires more page width and is best viewed when opened in a new tab.
CodeDemo const trial = {\n type: jsPsychSurvey,\n survey_json: {\n showQuestionNumbers: false,\n title: 'Likert scale examples',\n pages: [\n {\n elements: [\n {\n type: 'rating',\n name: 'like-vegetables',\n title: 'I like to eat vegetables.',\n description: 'Button rating scale with min/max descriptions',\n minRateDescription: 'Strongly Disagree',\n maxRateDescription: 'Strongly Agree',\n displayMode: 'buttons',\n rateValues: [1,2,3,4,5]\n }, \n {\n type: 'rating',\n name: 'like-cake',\n title: 'I like to eat cake.',\n description: 'Star rating scale with min/max descriptions',\n minRateDescription: 'Strongly Disagree',\n maxRateDescription: 'Strongly Agree',\n rateType: 'stars',\n rateCount: 10,\n rateMax: 10,\n },\n {\n type: 'rating',\n name: 'like-cooking',\n title: 'How much do you enjoy cooking?',\n description: 'Smiley rating scale without min/max descriptions',\n rateType: 'smileys',\n rateCount: 10,\n rateMax: 10,\n scaleColorMode: 'colored',\n }\n ]\n }, {\n elements: [\n {\n type: 'matrix',\n name: 'like-food-matrix',\n title: 'Matrix question for rating mutliple statements on the same scale.',\n alternateRows: true,\n isAllRowRequired: true,\n rows: [\n {text: 'I like to eat vegetables.', value: 'VeggiesTable'},\n {text: 'I like to eat fruit.', value: 'FruitTable'},\n {text: 'I like to eat cake.', value: 'CakeTable'},\n {text: 'I like to cook.', value: 'CookTable'},\n ],\n columns: [{\n \"value\": 5,\n \"text\": \"Strongly agree\"\n }, {\n \"value\": 4,\n \"text\": \"Agree\"\n }, {\n \"value\": 3,\n \"text\": \"Neutral\"\n }, {\n \"value\": 2,\n \"text\": \"Disagree\"\n }, {\n \"value\": 1,\n \"text\": \"Strongly disagree\"\n }]\n }\n ]\n }\n ]\n }\n};\n
Open demo in new tab
Conditional question visibility based on response This example demonstrates how you can show/hide questions based on the participant's response. It also shows how you can show/hide the navigation buttons and move on to the next page automatically.
CodeDemo const survey_function = (survey) => {\n // If it's the question page, then hide the buttons and move on automatically.\n // If it's the feedback page, then show the navigation buttons.\n function updateNavButtons(sender, options) {\n if (options.newCurrentPage.getPropertyValue(\"name\") === \"feedback\") {\n survey.showNavigationButtons = \"bottom\";\n } else {\n survey.showNavigationButtons = \"none\";\n }\n }\n survey.onCurrentPageChanging.add(updateNavButtons);\n}\n\nconst trial = {\n type: jsPsychSurvey,\n survey_json: {\n showQuestionNumbers: false,\n title: 'Conditional question visibility.',\n showNavigationButtons: \"none\",\n goNextPageAutomatic: true,\n allowCompleteSurveyAutomatic: true,\n pages: [{\n name: 'question',\n elements: [\n {\n type: 'radiogroup',\n title: 'During the experiment, are you allowed to write things down on paper to help you?',\n choices: [\"Yes\", \"No\"],\n name: \"WriteOK\",\n isRequired: true\n }\n ],\n }, {\n name: 'feedback',\n elements: [\n {\n type: 'html',\n name: 'incorrect',\n visibleIf: '{WriteOK} = \"Yes\"',\n html: '<h4>That response was incorrect.</h4><p>Please return to the previous page and try again.</p>'\n },\n {\n type: 'html',\n name: 'correct',\n visibleIf: '{WriteOK} == \"No\"',\n html: '<h4>Congratulations!</h4>'\n }\n ]\n }]\n },\n survey_function: survey_function\n};\n
Open demo in new tab
Repeating survey trials with different variables The survey plugin is not well-suited for use with the jsPsych timeline variables feature, so an alternative to creating a set of repeating survey trials is to construct them in a loop. When adding any data to a survey trial, you should add it via the data
parameter at the whole-trial level (not inside the question objects), even if it only relates to one question out of multiple questions/pages contained within the trial.
CodeDemo // values that change across survey trials - each object represents a single trial\nconst question_variables = [\n {\n 'fruit': 'apples',\n 'Q1_prompt': 'Do you like apples?', \n 'Q1_type': 'regular',\n 'Q2_word': 'like'\n },\n {\n 'fruit': 'pears',\n 'Q1_prompt': 'Do you like pears?', \n 'Q1_type': 'regular',\n 'Q2_word': 'like'\n },\n {\n 'fruit': 'bananas',\n 'Q1_prompt': 'Do you NOT like bananas?', \n 'Q1_type': 'reverse',\n 'Q2_word': 'hate'\n },\n];\n\n// create an array to store all of our survey trials so that we can easily randomize their order\nsurvey_trials = [];\n\n// construct the survey trials dynamically using an array of question-specific information\nfor (let i=0; i<question_variables.length; i++) {\n\n // set up the survey JSON for this trial\n // any question-specific variables come from the appropriate object in the question_variables array\n let survey_json = {\n showQuestionNumbers: false,\n title: 'Dynamically constructing survey trials.',\n completeText: 'Next >>',\n elements: [\n {\n type: 'radiogroup',\n title: question_variables[i].Q1_prompt,\n choices: ['Yes', 'No'],\n name: 'Q1'\n },\n {\n type: 'text',\n title: 'What do you '+question_variables[i].Q2_word+' most about '+question_variables[i].fruit+'?',\n name: 'Q2'\n }\n ]\n };\n\n // set up a survey trial object using the JSON we've just created for this question, \n // and add the trial object to the survey trials array\n survey_trials.push({\n type: jsPsychSurvey,\n survey_json: survey_json,\n data: {\n 'Q1_prompt': question_variables[i].Q1_prompt,\n 'Q1_type': question_variables[i].Q1_type,\n 'Q2_word': question_variables[i].Q2_word,\n 'fruit': question_variables[i].fruit \n } \n });\n\n}\n\nconst timeline = jsPsych.randomization.shuffle(survey_trials);\n
Open demo in new tab
Adding images, sound and HTML This example shows how to add HTML, image and audio elements to a survey. It also demonstrates some CSS customization and response validation.
CodeDemo /* center the audio player and all image question types in the survey */\ndiv.sd-question--image, div.sd-question[data-name=\"audio-player\"] {\n text-align: center;\n}\n/* use 'data-name' to select any specific question by name */\ndiv[data-name=\"audio-response\"] {\n text-align: center;\n margin-top: 30px;\n}\n
// Embed HTML, images, videos and audio into the survey\nconst image_video_html_trial_info = {\n pages: [{\n elements: [{\n type: \"panel\",\n name: \"html-img-panel\",\n description: \"This panel contains an HTML element and an image element.\",\n elements: [{\n type: \"html\",\n name: \"html\",\n html: \"<div style='text-align: center; align-items: center; align-content: center; justify-content: center;'><p style='text-align: center; color: darkgreen; font-size: 2em;'>This demo shows how you can add <em>HTML</em>, <strong>images</strong>, and <sub>video</sub> to your jsPsych survey trial.</p></div>\"\n }, {\n type: \"image\",\n name: \"monkey\",\n imageLink: \"img/monkey.png\",\n altText: \"Monkey\",\n imageWidth: 300\n }]\n }, {\n type: \"panel\",\n name: \"video-panel\",\n description: \"This panel contains a fun fish video.\",\n elements: [{\n type: \"image\",\n name: \"jspsych-tutorial\",\n imageLink: \"video/fish.mp4\",\n imageWidth: 700,\n imageHeight: 350\n }],\n }]\n }],\n widthMode: \"static\",\n width: 900,\n completeText: 'Next'\n};\n\nconst image_video_html_trial = {\n type: jsPsychSurvey,\n survey_json: image_video_html_trial_info\n};\n\n// Using images as response options\nconst image_choice_trial_info = {\n elements: [{\n type: \"imagepicker\",\n name: \"animals\",\n title: \"Which animals would you like to see in real life?\",\n description: \"Please select all that apply.\",\n choices: [{\n value: \"lion\",\n imageLink: \"img/lion.png\",\n text: \"Lion\"\n }, {\n value: \"monkey\",\n imageLink: \"img/monkey.png\",\n text: \"Monkey\"\n }, {\n value: \"elephant\",\n imageLink: \"img/elephant.png\",\n text: \"Elephant\"\n }],\n showLabel: true,\n multiSelect: true\n }],\n showQuestionNumbers: \"off\",\n completeText: 'Next',\n};\n\nconst image_choice_trial = {\n type: jsPsychSurvey,\n survey_json: image_choice_trial_info\n};\n\n// Add sound to an HTML element\n// This also demonstrates response validation\nconst sound_trial_info = {\n elements: [{\n type: \"html\",\n name: \"audio-player\",\n html: \"<audio controls><source src='sound/speech_red.mp3' type='audio/mp3'></audio>\"\n },\n {\n type: \"text\",\n name: \"audio-response\",\n title: \"Please play the sound above and then type the word that you heard in the box below.\",\n description: \"Try getting it wrong to see the response validation.\",\n required: true,\n validators: [{\n type: \"regex\",\n text: \"Oops, that's not correct. Try again!\",\n regex: \"[rR]{1}[eE]{1}[dD]{1}\"\n }],\n }],\n completeText: \"Check my response\",\n showQuestionNumbers: \"off\"\n};\n\nconst sound_trial = {\n type: jsPsychSurvey,\n survey_json: sound_trial_info\n}\n\nconst timeline = [image_video_html_trial, image_choice_trial, sound_trial];\n
Open demo in new tab
Automatic formating for text input You can add automatic formatting, or input masking, to a text entry question. See the SurveyJS documentation on masked input fields for more information and examples.
CodeDemo const timeline = [];\n\nconst text_masking_json = {\n elements: [\n {\n type: \"html\",\n name: \"intro\",\n html: \"<h3>Input masking examples</h3><p>You can use input masking with text questions to add automatic formatting to the participant's answer. The mask types are: currency, decimal, pattern, and datetime. These masks will also restrict the types of characters that can be entered, e.g. only numbers or letters.\"\n },\n {\n type: \"text\",\n name: \"currency\",\n title: \"Currency:\",\n description: \"This currency mask adds a prefix/suffix to the number to indicate the currency. Enter some numbers to see the result.\",\n maskType: \"currency\",\n maskSettings: {\n prefix: \"$\",\n suffix: \" USD\"\n }\n },\n {\n type: \"text\",\n name: \"decimal\",\n title: \"Decimal:\",\n description: \"This numeric mask will specify the number of decimals allowed. You can enter numbers with up to three decimals (precision: 3).\",\n maskType: \"numeric\",\n maskSettings: {\n precision: 3\n }\n },\n {\n type: \"text\",\n name: \"phone\",\n title: \"Phone:\",\n description: \"This pattern mask will format the numbers as a phone number.\",\n maskType: \"pattern\",\n maskSettings: {\n pattern: \"+9 (999)-999-9999\"\n }\n },\n {\n type: \"text\",\n name: \"creditcard\",\n title: \"Credit card number:\",\n description: \"This pattern mask will format the numbers as a credit card number.\",\n maskType: \"pattern\",\n maskSettings: {\n pattern: \"9999 9999 9999 9999\"\n }\n },\n {\n type: \"text\",\n name: \"licenseplate\",\n title: \"License plate number:\",\n description: \"A pattern mask can also be used with letters. Enter a license plate number in the format ABC-1234.\",\n maskType: \"pattern\",\n maskSettings: {\n pattern: \"aaa-9999\"\n }\n }\n ],\n showQuestionNumbers: false\n};\n\ntimeline.push({\n type: jsPsychSurvey,\n survey_json: text_masking_json\n});\n
Open demo in new tab
"},{"location":"plugins/video-button-response/","title":"video-button-response","text":"Current version: 2.0.0. See version history.
This plugin plays a video and records responses generated by button click. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically when the participant responds, when the video file has finished playing, or if the participant has failed to respond within a fixed length of time. You can also prevent a button response from being made before the video has finished playing. The button itself can be customized using HTML formatting.
Video files can be automatically preloaded by jsPsych using the preload
plugin. However, if you are using timeline variables or another dynamic method to specify the video stimulus, you will need to manually preload the videos. Also note that video preloading is disabled when the experiment is running as a file (i.e. opened directly in the browser, rather than through a server), in order to prevent CORS errors - see the section on Running Experiments for more information.
"},{"location":"plugins/video-button-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus array undefined An array of file paths to the video. You can specify multiple formats of the same video (e.g., .mp4, .ogg, .webm) to maximize the cross-browser compatibility. Usually .mp4 is a safe cross-browser option. The plugin does not reliably support .mov files. The player will use the first source file in the array that is compatible with the browser, so specify the files in order of preference. choices array of strings undefined Labels for the buttons. Each different string in the array will generate a different button. button_html function (choice: string, choice_index: number)=>`<button class=\"jspsych-btn\">${choice}</button>
; A function that generates the HTML for each button in the choices
array. The function gets the string and index of the item in the choices
array and should return valid HTML. If you want to use different markup for each button, you can do that by using a conditional on either parameter. The default parameter returns a button element with the text label of the choice. button_layout string 'grid' Setting to 'grid'
will make the container element have the CSS property display: grid
and enable the use of grid_rows
and grid_columns
. Setting to 'flex'
will make the container element have the CSS property display: flex
. You can customize how the buttons are laid out by adding inline CSS in the button_html
parameter. grid_rows number 1 The number of rows in the button grid. Only applicable when button_layout
is set to 'grid'
. If null, the number of rows will be determined automatically based on the number of buttons and the number of columns. grid_columns number null The number of columns in the button grid. Only applicable when button_layout
is set to 'grid'
. If null, the number of columns will be determined automatically based on the number of buttons and the number of rows. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). width numeric width of the video file The width of the video display in pixels. height numeric heigh of the video file The height of the video display in pixels. autoplay boolean true If true, the video will begin playing as soon as it has loaded. controls boolean false If true, controls for the video player will be available to the participant. They will be able to pause the video or move the playback to any point in the video. start numeric null If given a value, the video will start at this time point in seconds. stop numeric null If given a value, the video will stop at this time point in seconds. rate numeric null The playback rate of the video. 1 is normal, <1 is slower, >1 is faster. trial_ends_after_video bool false If true, then the trial will end as soon as the video file finishes playing. trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can set this parameter to false
to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete. response_allowed_while_playing boolean true If true, then responses are allowed while the video is playing. If false, then the video must finish playing before the button choices are enabled and a response is accepted. Once the video has played all the way through, the buttons are enabled and a response is allowed (including while the video is being re-played via on-screen playback controls). enable_button_after numeric 0 How long the button will delay enabling in milliseconds. If response_allowed_while_playing
is true
, the timer will start immediately. If it is false
, the timer will start at the end of the video."},{"location":"plugins/video-button-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response numeric Indicates which button the participant pressed. The first button in the choices
array is 0, the second is 1, and so on. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. stimulus array The stimulus
array. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions."},{"location":"plugins/video-button-response/#simulation-mode","title":"Simulation Mode","text":"In data-only
simulation mode, the response_allowed_while_playing
parameter does not currently influence the simulated response time. This is because the audio file is not loaded in data-only
mode and therefore the length is unknown. This may change in a future version as we improve the simulation modes.
"},{"location":"plugins/video-button-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-video-button-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-video-button-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-video-button-response\n
import videoButtonResponse from '@jspsych/plugin-video-button-response';\n
"},{"location":"plugins/video-button-response/#example","title":"Example","text":"Responses disabled until the video is complete CodeDemo var trial = {\n type: jsPsychVideoButtonResponse,\n stimulus: [\n 'video/fish.mp4'\n ],\n choices: ['0-5', '6-10','11-15','16-20','21-25','25+'],\n prompt: \"<p>How many different fish are shown in the video?</p>\",\n response_allowed_while_playing: false\n};\n
Stock Footage provided by rjt98, from Pond5
Open demo in new tab
"},{"location":"plugins/video-keyboard-response/","title":"video-keyboard-response","text":"Current version: 2.0.0. See version history.
This plugin plays a video file and records a keyboard response. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically when the participant responds, when the video file has finished playing, or if the participant has failed to respond within a fixed length of time. You can also prevent a keyboard response from being recorded before the video has finished playing.
Video files can be automatically preloaded by jsPsych using the preload
plugin. However, if you are using timeline variables or another dynamic method to specify the video stimulus, you will need to manually preload the videos. Also note that video preloading is disabled when the experiment is running as a file (i.e. opened directly in the browser, rather than through a server), in order to prevent CORS errors - see the section on Running Experiments for more information.
"},{"location":"plugins/video-keyboard-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus array undefined An array of file paths to the video. You can specify multiple formats of the same video (e.g., .mp4, .ogg, .webm) to maximize the cross-browser compatibility. Usually .mp4 is a safe cross-browser option. The plugin does not reliably support .mov files. The player will use the first source file in the array that is compatible with the browser, so specify the files in order of preference. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). width numeric width of the video file The width of the video display in pixels. height numeric heigh of the video file The height of the video display in pixels. autoplay boolean true If true, the video will begin playing as soon as it has loaded. controls boolean false If true, controls for the video player will be available to the participant. They will be able to pause the video or move the playback to any point in the video. start numeric null If given a value, the video will start at this time point in seconds. stop numeric null If given a value, the video will stop at this time point in seconds. rate numeric null The playback rate of the video. 1 is normal, <1 is slower, >1 is faster. choices array of strings \"ALL_KEYS\"
This array contains the key(s) that the participant is allowed to press in order to respond to the stimulus. Keys should be specified as characters (e.g., 'a'
, 'q'
, ' '
, 'Enter'
, 'ArrowDown'
) - see this page and this page (event.key column) for more examples. Any key presses that are not listed in the array will be ignored. The default value of \"ALL_KEYS\"
means that all keys will be accepted as valid responses. Specifying \"NO_KEYS\"
will mean that no responses are allowed. trial_ends_after_video bool false If true, then the trial will end as soon as the video file finishes playing. trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can set this parameter to false
to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete. response_allowed_while_playing boolean true If true, then responses are allowed while the video is playing. If false, then the video must finish playing before a keyboard response is accepted. Once the video has played all the way through, a valid keyboard response is allowed (including while the video is being re-played via on-screen playback controls)."},{"location":"plugins/video-keyboard-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. stimulus array The stimulus
array. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions."},{"location":"plugins/video-keyboard-response/#simulation-mode","title":"Simulation Mode","text":"In data-only
simulation mode, the response_allowed_while_playing
parameter does not currently influence the simulated response time. This is because the audio file is not loaded in data-only
mode and therefore the length is unknown. This may change in a future version as we improve the simulation modes.
"},{"location":"plugins/video-keyboard-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-video-keyboard-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-video-keyboard-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-video-keyboard-response\n
import videoKeyboardResponse from '@jspsych/plugin-video-keyboard-response';\n
"},{"location":"plugins/video-keyboard-response/#examples","title":"Examples","text":"Show a video and advance to next trial automatically CodeDemo var trial = {\n type: jsPsychVideoKeyboardResponse,\n stimulus: [\n 'video/fish.mp4'\n ],\n choices: \"NO_KEYS\",\n trial_ends_after_video: true\n};\n
Stock Footage provided by rjt98, from Pond5
Open demo in new tab
"},{"location":"plugins/video-slider-response/","title":"video-slider-response","text":"Current version: 2.0.0. See version history.
This plugin plays a video and allows the participant to respond by dragging a slider. The stimulus can be displayed until a response is given, or for a pre-determined amount of time. The trial can be ended automatically when the participant responds, when the video file has finished playing, or if the participant has failed to respond within a fixed length of time. You can also prevent the slider response from being made before the video has finished playing.
Video files can be automatically preloaded by jsPsych using the preload
plugin. However, if you are using timeline variables or another dynamic method to specify the video stimulus, you will need to manually preload the videos. Also note that video preloading is disabled when the experiment is running as a file (i.e. opened directly in the browser, rather than through a server), in order to prevent CORS errors - see the section on Running Experiments for more information.
"},{"location":"plugins/video-slider-response/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description stimulus array undefined An array of file paths to the video. You can specify multiple formats of the same video (e.g., .mp4, .ogg, .webm) to maximize the cross-browser compatibility. Usually .mp4 is a safe cross-browser option. The plugin does not reliably support .mov files. The player will use the first source file in the array that is compatible with the browser, so specify the files in order of preference. prompt string null This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). width numeric width of the video file The width of the video display in pixels. height numeric heigh of the video file The height of the video display in pixels. autoplay boolean true If true, the video will begin playing as soon as it has loaded. controls boolean false If true, controls for the video player will be available to the participant. They will be able to pause the video or move the playback to any point in the video. start numeric null If given a value, the video will start at this time point in seconds. stop numeric null If given a value, the video will stop at this time point in seconds. rate numeric null The playback rate of the video. 1 is normal, <1 is slower, >1 is faster. min integer 0 Sets the minimum value of the slider. max integer 100 Sets the maximum value of the slider. slider_start integer 50 Sets the starting value of the slider step integer 1 Sets the step of the slider. This is the smallest amount by which the slider can change. labels array of strings [] Labels displayed at equidistant locations on the slider. For example, two labels will be placed at the ends of the slider. Three labels would place two at the ends and one in the middle. Four will place two at the ends, and the other two will be at 33% and 67% of the slider width. slider_width integer null Set the width of the slider in pixels. If left null, then the width will be equal to the widest element in the display. require_movement boolean false If true, the participant must move the slider before clicking the continue button. button_label string 'Continue' Label of the button to end the trial. trial_ends_after_video bool false If true, then the trial will end as soon as the video file finishes playing. trial_duration numeric null How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, then the trial will wait for a response indefinitely. response_ends_trial boolean true If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the trial_duration
parameter). If false, then the trial will continue until the value for trial_duration
is reached. You can set this parameter to false
to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete. response_allowed_while_playing boolean true If true, then responses are allowed while the video is playing. If false, then the video must finish playing before the slider is enabled and the trial can end via the next button click. Once the video has played all the way through, the slider is enabled and a response is allowed (including while the video is being re-played via on-screen playback controls)."},{"location":"plugins/video-slider-response/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value response numeric The numeric value of the slider. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. stimulus array The stimulus
array. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions. slider_start numeric The starting value of the slider. start numeric The start time of the video clip."},{"location":"plugins/video-slider-response/#simulation-mode","title":"Simulation Mode","text":"In data-only
simulation mode, the response_allowed_while_playing
parameter does not currently influence the simulated response time. This is because the audio file is not loaded in data-only
mode and therefore the length is unknown. This may change in a future version as we improve the simulation modes.
"},{"location":"plugins/video-slider-response/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-video-slider-response@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-video-slider-response.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-video-slider-response\n
import videoSliderResponse from '@jspsych/plugin-video-slider-response';\n
"},{"location":"plugins/video-slider-response/#example","title":"Example","text":"Rate enjoyment of a video clip CodeDemo var trial = {\n type: jsPsychVideoSliderResponse,\n stimulus: [\n 'video/fish.mp4'\n ],\n labels: [\"Hated it\", \"Loved it\"],\n prompt: '<p>Please rate your enjoyment of the video clip.</p>'\n};\n
Stock Footage provided by rjt98, from Pond5
Open demo in new tab
"},{"location":"plugins/virtual-chinrest/","title":"virtual-chinrest","text":"Current version: 3.0.0. See version history.
This plugin provides a \"virtual chinrest\" that can measure the distance between the participant and the screen. It can also standardize the jsPsych page content to a known physical dimension (e.g., ensuring that a 200px wide stimulus is 2.2cm wide on the participant's monitor). This is based on the work of Li, Joo, Yeatman, and Reinecke (2020), and the plugin code is a modified version of their implementation. We recommend citing their work in any paper that makes use of this plugin.
Citation
Li, Q., Joo, S. J., Yeatman, J. D., & Reinecke, K. (2020). Controlling for Participants\u2019 Viewing Distance in Large-Scale, Psychophysical Online Experiments Using a Virtual Chinrest. Scientific Reports, 10(1), 1-11. doi: 10.1038/s41598-019-57204-1
The plugin works in two phases.
Phase 1. To calculate the pixel-to-cm conversion rate for a participant\u2019s display, participants are asked to place a credit card or other item of the same size on the screen and resize an image until it is the same size as the credit card. Since we know the physical dimensions of the card, we can find the conversion rate for the participant's display.
Phase 2. To measure the participant's viewing distance from their screen we use a blind spot task. Participants are asked to focus on a black square on the screen with their right eye closed, while a red dot repeatedly sweeps from right to left. They press the spacebar on their keyboard whenever they perceive that the red dot has disappeared. This part allows the plugin to use the distance between the black square and the red dot when it disappears from eyesight to estimate how far the participant is from the monitor. This estimation assumes that the blind spot is located at 13.5\u00b0 temporally.
"},{"location":"plugins/virtual-chinrest/#parameters","title":"Parameters","text":"Parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Descripton resize_units string \"none\" Units to resize the jsPsych content to after the trial is over: \"none\"
\"cm\"
\"inch\"
or \"deg\"
. If \"none\"
, no resizing will be done to the jsPsych content after the virtual-chinrest trial ends. pixels_per_unit numeric 100 After the scaling factor is applied, this many pixels will equal one unit of measurement, where the units are indicated by resize_units
. This is only used when resizing is done after the trial ends (i.e. the resize_units
parameter is not \"none\"). adjustment_prompt HTML string \"Click and drag the lower right corner of the image until it is the same size as a credit card held up to the screen. You can use any card that is the same size as a credit card, like a membership card or driver's license. If you do not have access to a real card you can use a ruler to measure the image width to 3.37 inches or 85.6 mm.\" This string can contain HTML markup. Any content here will be displayed below the card stimulus during the resizing phase. adjustment_button_prompt HTML string \"Click here when the image is the correct size\" Content of the button displayed below the card stimulus during the resizing phase. item_path string null Path of the item to be presented in the card stimulus during the resizing phase. If null
then no image is shown, and a solid color background is used instead. An example image is available in /examples/img/card.png
item_height_mm numeric 53.98 The known height of the physical item (e.g. credit card) to be measured, in mm. item_width_mm numeric 85.6 The known width of the physical item (e.g. credit card) to be measured, in mm. item_init_size numeric 250 The initial size of the card stimulus, in pixels, along its largest dimension. blindspot_reps numeric 5 How many times to measure the blindspot location. If 0
, blindspot will not be detected, and viewing distance and degree data will not be computed. blindspot_prompt HTML string \"Now we will quickly measure how far away you are sitting. Put your left hand on the space bar. Cover your right eye with your right hand. Using your left eye, focus on the black square. Keep your focus on the black square. The red ball will disappear as it moves from right to left. Press the space bar as soon as the ball disappears. Press the space bar when you are ready to begin. This string can contain HTML markup. Any content here will be displayed above the blindspot task. redo_measurement_button_label HTML string 'No, that is not close. Try again' Text for the button on the viewing distance report page to re-do the viewing distance estimate. If the participant click this button, the blindspot task starts again. blindspot_done_prompt HTML string \"Yes\" Text for the button on the viewing distance report page that can be clicked to accept the viewing distance estimate. blindspot_measurements_prompt HTML string 'Remaining measurements: ' Text accompanying the remaining measurements counter that appears below the blindspot task. viewing_distance_report HTML string \"Based on your responses, you are sitting about <span id='distance-estimate' style='font-weight: bold;'></span>
from the screen. Does that seem about right?\" Estimated viewing distance data displayed after blindspot task. If \"none\"
is given, viewing distance will not be reported to the participant. The HTML span
element with id = distance-estimate
returns the distance."},{"location":"plugins/virtual-chinrest/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Note: The deg data are only returned if viewing distance is estimated with the blindspot method (px2deg, win_height_deg, win_width_deg, item_width_deg).
Name Type Value rt numeric The response time in milliseconds. item_height_mm numeric The height in millimeters of the item to be measured. item_width_mm numeric The width in millimeters of the item to be measured item_height_deg numeric Final height of the resizable div container, in degrees. item_width_deg numeric Final width of the resizable div container, in degrees. item_width_px numeric Final width of the resizable div container, in pixels. px2deg numeric Pixels to degrees conversion factor. px2mm numeric Pixels to millimeters conversion factor. scale_factor numeric Scaling factor that will be applied to the div containing jsPsych content. win_width_deg numeric The interior width of the window in degrees. win_height_deg numeric The interior height of the window in degrees. view_dist_mm numeric Estimated distance to the screen in millimeters."},{"location":"plugins/virtual-chinrest/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/virtual-chinrest/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-virtual-chinrest@3.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-virtual-chinrest.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-virtual-chinrest\n
import virtualChinrest from '@jspsych/plugin-virtual-chinrest';\n
"},{"location":"plugins/virtual-chinrest/#example","title":"Example","text":"Measure distance to screen and pixel ratio; no resizing CodeDemo var trial = {\n type: jsPsychVirtualChinrest,\n blindspot_reps: 3,\n resize_units: \"none\"\n};\n
This demo requires a larger viewing area to complete. Please open the demo in a new tab
Open demo in new tab
Resizing based on centimeters per pixel CodeDemo var trial = {\n type: jsPsychVirtualChinrest,\n blindspot_reps: 3,\n resize_units: \"cm\",\n pixels_per_unit: 50\n};\n\nvar resized_stimulus = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `\n <p>If the measurements were done correctly, the square below should be 10 cm x 10 cm.</p>\n <div style=\"background-color: black; width: 500px; height: 500px; margin: 20px auto;\"></div>\n `,\n choices: ['Continue']\n}\n
This demo requires a larger viewing area to complete. Please open the demo in a new tab
Open demo in new tab
Resizing based on degrees of visual angle per pixel CodeDemo var trial = {\n type: jsPsychVirtualChinrest,\n blindspot_reps: 3,\n resize_units: \"deg\",\n pixels_per_unit: 50\n};\n\nvar resized_stimulus = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `\n <p>If the measurements were done correctly, the square below should take up about 10 degrees of visual angle.</p>\n <div style=\"background-color: black; width: 500px; height: 500px; margin: 20px auto;\"></div>\n `,\n choices: ['Continue']\n}\n
This demo requires a larger viewing area to complete. Please open the demo in a new tab
Open demo in new tab
"},{"location":"plugins/visual-search-circle/","title":"visual-search-circle","text":"Current version: 2.1.0. See version history.
This plugin presents a customizable visual-search task modelled after Wang, Cavanagh, & Green (1994). The participant indicates whether or not a target is present among a set of distractors. The stimuli are displayed in a circle, evenly-spaced, equidistant from a fixation point. Here is an example using normal and backward Ns:
"},{"location":"plugins/visual-search-circle/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. The set of images to display must be defined in one of two ways:
- The
target
, foil
and set_size
parameters: the combination of these parameters can be used to construct a 'classic' visual search task, where there is a single foil/distractor image that makes up all of the images in the set, with the exception of the target image if it is present. OR - The
stimuli
parameter: this array that can be used to present any arbitrary set of image files, with or without the target image, with any number of different foils/distractors, and with any number of repeated images.
The target_present
and fixation_image
parameters must always be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description target string null Path to image file that is the search target. This parameter must specified when the stimuli set is defined using the target
, foil
and set_size
parameters, but should NOT be specified when using the stimuli
parameter. foil string null Path to image file that is the foil/distractor. This image will be repeated for all distractors up to the set_size
value. This parameter must specified when the stimuli set is defined using the target
, foil
and set_size
parameters, but should NOT be specified when using the stimuli
parameter. set_size numeric null How many items should be displayed, including the target when target_present
is true
. The foil image will be repeated up to this value when target_present
is false
, or up to set_size - 1
when target_present
is true
. This parameter must specified when using the target
, foil
and set_size
parameters to define the stimuli set, but should NOT be specified when using the stimuli
parameter. stimuli array of images null Array containing all of the image files to be displayed. This parameter must be specified when NOT using the target
, foil
, and set_size
parameters to define the stimuli set. target_present boolean undefined Is the target present? This parameter must always be specified. When using the target
, foil
and set_size
parameters, false
means that the foil image will be repeated up to the set_size, and true
means that the target will be presented along with the foil image repeated up to set_size - 1. When using the stimuli
parameter, this parameter is only used to determine the response accuracy. fixation_image string undefined Path to image file that is a fixation target. This parameter must always be specified. target_size array [50, 50]
Two element array indicating the height and width of the search array element images. fixation_size array [16, 16]
Two element array indicating the height and width of the fixation image. circle_diameter numeric 250 The diameter of the search array circle in pixels. target_present_key string 'j' The key to press if the target is present in the search array. target_absent_key string 'f' The key to press if the target is not present in the search array. trial_duration numeric null The maximum amount of time the participant is allowed to search before the trial will continue. A value of null will allow the participant to search indefinitely. fixation_duration numeric 1000 How long to show the fixation image for before the search array (in milliseconds). randomize_item_locations bool true Whether to use randomized locations on the circle for the items. If false
, then the first item will always show at the location specified by location_first_item
. location_first_item numeric 0 If randomize_item_locations
is false
, the location of the first item on the circle, in degrees. 0 degrees is above the fixation, and moving clockwise in the positive direction. response_ends_trial boolean true If true, the trial will end when the participant makes a response."},{"location":"plugins/visual-search-circle/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value correct boolean True if the participant gave the correct response. response string Indicates which key the participant pressed. rt numeric The response time in milliseconds for the participant to make a response. The time is measured from when the stimulus first appears on the screen until the participant's response. set_size numeric The number of items in the search array target_present boolean True if the target is present in the search array locations array Array where each element is the pixel value of the center of an image in the search array. If the target is present, then the first element will represent the location of the target. This will be encoded as a JSON string when data is saved using the .json()
or .csv()
functions."},{"location":"plugins/visual-search-circle/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-visual-search-circle@2.1.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-visual-search-circle.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-visual-search-circle\n
import visualSearchCircle from '@jspsych/plugin-visual-search-circle';\n
"},{"location":"plugins/visual-search-circle/#examples","title":"Examples","text":"Identical distractors CodeDemo var instructions = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `<p>Press J if there is a backwards N.</p>\n <p>Press F if all the Ns are in the normal orientation.</p>`,\n choices: ['Continue']\n}\n\nvar trial = {\n type: jsPsychVisualSearchCircle,\n target: 'img/backwardN.gif',\n foil: 'img/normalN.gif',\n fixation_image: 'img/fixation.gif',\n target_present: true,\n set_size: 4\n}\n
Open demo in new tab
Variety of different distractors CodeDemo var instructions = {\n type: jsPsychHtmlButtonResponse,\n stimulus: `<p>Press E if there is an elephant in the group.</p>\n <p>Press N if there is no elephant in the group.</p>`,\n choices: ['Continue']\n}\n\nvar trial = {\n type: jsPsychVisualSearchCircle,\n stimuli: ['img/elephant.png', 'img/lion.png', 'img/monkey.png'],\n fixation_image: 'img/fixation.gif',\n target_present_key: 'e',\n target_absent_key: 'n',\n target_present: true\n}\n
Open demo in new tab
"},{"location":"plugins/webgazer-calibrate/","title":"webgazer-calibrate","text":"Current version: 2.0.0. See version history.
This plugin can be used to calibrate the WebGazer extension. For a narrative description of eye tracking with jsPsych, see the eye tracking overview.
"},{"location":"plugins/webgazer-calibrate/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description calibration_points array [[10,10], [10,50], [10,90], [50,10], [50,50], [50,90], [90,10], [90,50], [90,90]]
Array of points in [x,y]
coordinates. Specified as a percentage of the screen width and height, from the left and top edge. The default grid is 9 points. calibration_mode string 'click'
Can specify click
to have participants click on calibration points or view
to have participants passively watch calibration points. repetitions_per_point numeric 1 The number of times to repeat the sequence of calibration points. point_size numeric 20 Diameter of the calibration points in pixels. randomize_calibration_order bool false
Whether to randomize the order of the calibration points. time_to_saccade numeric 1000 If calibration_mode
is set to view
, then this is the delay before calibrating after showing a point. Gives the participant time to fixate on the new target before assuming that the participant is looking at the target. time_per_point numeric 1000 If calibration_mode
is set to view
, then this is the length of time to show a point while calibrating. Note that if click
calibration is used then the point will remain on the screen until clicked."},{"location":"plugins/webgazer-calibrate/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value No data currently added by this plugin. Use the webgazer-validate plugin to measure the precision and accuracy of calibration.
"},{"location":"plugins/webgazer-calibrate/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/webgazer-calibrate/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-webgazer-calibrate@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-webgazer-calibrate.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-webgazer-calibrate\n
import webgazerCalibrate from '@jspsych/plugin-webgazer-calibrate';\n
"},{"location":"plugins/webgazer-calibrate/#example","title":"Example","text":"Because the eye tracking plugins need to be used in conjunction with each other, please see the example on the eye tracking overview page for an integrated example.
"},{"location":"plugins/webgazer-init-camera/","title":"webgazer-init-camera","text":"Current version: 2.0.0. See version history.
This plugin initializes the camera and helps the participant center their face in the camera view for using the the WebGazer extension. For a narrative description of eye tracking with jsPsych, see the eye tracking overview.
"},{"location":"plugins/webgazer-init-camera/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description instructions string too long to put here Instructions for the participant to follow. button_text string Continue The text for the button that participants click to end the trial."},{"location":"plugins/webgazer-init-camera/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value load_time numeric The time it took for webgazer to initialize. This can be a long time in some situations, so this value is recorded for troubleshooting when participants are reporting difficulty."},{"location":"plugins/webgazer-init-camera/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/webgazer-init-camera/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-webgazer-init-camera@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-webgazer-init-camera.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-webgazer-init-camera\n
import webgazerInitCamera from '@jspsych/plugin-webgazer-init-camera';\n
"},{"location":"plugins/webgazer-init-camera/#example","title":"Example","text":"Because the eye tracking plugins need to be used in conjunction with each other, please see the example on the eye tracking overview page for an integrated example.
"},{"location":"plugins/webgazer-validate/","title":"webgazer-validate","text":"Current version: 2.0.0. See version history.
This plugin can be used to measure the accuracy and precision of gaze predictions made by the WebGazer extension. For a narrative description of eye tracking with jsPsych, see the eye tracking overview.
"},{"location":"plugins/webgazer-validate/#parameters","title":"Parameters","text":"In addition to the parameters available in all plugins, this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable.
Parameter Type Default Value Description validation_points array [[10,10], [10,50], [10,90], [50,10], [50,50], [50,90], [90,10], [90,50], [90,90]]
Array of points in [x,y]
coordinates. The default grid is 9 points. Meaning of coordinates controlled by validation_point_coordinates
parameter. validation_point_coordinates string 'percent'
Can specify percent
to have validation point coordinates specified in percentage of screen width and height, or center-offset-pixels
to specify each point as the distance in pixels from the center of the screen. roi_radius numeric 200 Tolerance around the validation point in pixels when calculating the percent of gaze measurements within the acceptable range. randomize_validation_order bool false
Whether to randomize the order of the validation points. time_to_saccade numeric 1000 The delay before validating after showing a point. Gives the participant time to fixate on the new target before assuming that the participant is looking at the target. validation_duration numeric 2000 If calibration_mode
is set to view
, then this is the length of time to show a point while calibrating. Note that if click
calibration is used then the point will remain on the screen until clicked. point_size numeric 20 Diameter of the validation points in pixels. show_validation_data bool false If true
then a visualization of the validation data will be shown on the screen after the validation is complete. This will show each measured gaze location color coded by whether it is within the roi_radius
of the target point. This is mainly intended for testing and debugging."},{"location":"plugins/webgazer-validate/#data-generated","title":"Data Generated","text":"In addition to the default data collected by all plugins, this plugin collects the following data for each trial.
Name Type Value raw_gaze array Raw gaze data for the trial. The array will contain a nested array for each validation point. Within each nested array will be a list of {x,y,dx,dy}
values specifying the absolute x and y pixels, as well as the distance from the target for that gaze point. percent_in_roi array The percentage of samples within the roi_radius
for each validation point. average_offset array The average x
and y
distance from each validation point, plus the median distance r
of the points from this average offset. samples_per_sec numeric The average number of samples per second. Calculated by finding samples per second for each point and then averaging these estimates together. validation_points array The list of validation points, in the order that they appeared."},{"location":"plugins/webgazer-validate/#simulation-mode","title":"Simulation Mode","text":"This plugin does not yet support simulation mode.
"},{"location":"plugins/webgazer-validate/#install","title":"Install","text":"Using the CDN-hosted JavaScript file:
<script src=\"https://unpkg.com/@jspsych/plugin-webgazer-validate@2.0.0\"></script>\n
Using the JavaScript file downloaded from a GitHub release dist archive:
<script src=\"jspsych/plugin-webgazer-validate.js\"></script>\n
Using NPM:
npm install @jspsych/plugin-webgazer-validate\n
import webgazerValidate from '@jspsych/plugin-webgazer-validate';\n
"},{"location":"plugins/webgazer-validate/#example","title":"Example","text":"Because the eye tracking plugins need to be used in conjunction with each other, please see the example on the eye tracking overview page for an integrated example.
"},{"location":"reference/jspsych-data/","title":"jsPsych.data","text":"The jsPsych.data module contains functions for interacting with the data generated by jsPsych plugins.
"},{"location":"reference/jspsych-data/#jspsychdataaddproperties","title":"jsPsych.data.addProperties","text":"jsPsych.data.addProperties(properties)\n
"},{"location":"reference/jspsych-data/#parameters","title":"Parameters","text":"Parameter Type Description properties object Object of key: value pairs to add to the data."},{"location":"reference/jspsych-data/#return-value","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-data/#description","title":"Description","text":"This method appends a set of properties to every trial in the data object, including trials that have already occurred and trials that have yet to occur. You can use this to record things like the subject ID or condition assignment.
"},{"location":"reference/jspsych-data/#examples","title":"Examples","text":""},{"location":"reference/jspsych-data/#assigning-a-subject-id-and-condition-code","title":"Assigning a subject ID and condition code","text":"jsPsych.data.addProperties({subject: 1, condition: 'control'});\n
"},{"location":"reference/jspsych-data/#jspsychdatadisplaydata","title":"jsPsych.data.displayData","text":"jsPsych.data.displayData(format)\n
"},{"location":"reference/jspsych-data/#parameters_1","title":"Parameters","text":"Parameter Type Description format string Specifies whether to display the data in 'csv'
or 'json'
format."},{"location":"reference/jspsych-data/#return-value_1","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-data/#description_1","title":"Description","text":"Outputs all of the data collected in the experiment to the screen in either JSON or CSV format. This is a useful method for quick debugging when developing an experiment.
"},{"location":"reference/jspsych-data/#examples_1","title":"Examples","text":""},{"location":"reference/jspsych-data/#using-the-on_finish-callback-function-to-show-data-at-the-end-of-the-experiment","title":"Using the on_finish callback function to show data at the end of the experiment","text":"var jsPsych = initJsPsych({\n on_finish: function() {\n jsPsych.data.displayData('csv');\n }\n})\n
"},{"location":"reference/jspsych-data/#jspsychdataget","title":"jsPsych.data.get","text":"jsPsych.data.get()\n
"},{"location":"reference/jspsych-data/#parameters_2","title":"Parameters","text":"None.
"},{"location":"reference/jspsych-data/#return-value_2","title":"Return value","text":"Returns the data collection of all data generated by the experiment.
"},{"location":"reference/jspsych-data/#description_2","title":"Description","text":"This function is the standard starting point for accessing the data generated by the experiment. It returns a DataCollection object, which has several methods that can be used to further filter, aggregate, and view the data. These methods are described under the DataCollection section on this page.
"},{"location":"reference/jspsych-data/#example","title":"Example","text":"// select all trials\nvar all_data = jsPsych.data.get();\n\n// get csv representation of data and log to console\nconsole.log(all_data.csv());\n
"},{"location":"reference/jspsych-data/#jspsychdatagetinteractiondata","title":"jsPsych.data.getInteractionData","text":"jsPsych.data.getInteractionData()\n
"},{"location":"reference/jspsych-data/#parameters_3","title":"Parameters","text":"None.
"},{"location":"reference/jspsych-data/#return-value_3","title":"Return value","text":"Returns a DataCollection object with all of the interaction events.
"},{"location":"reference/jspsych-data/#description_3","title":"Description","text":"jsPsych automatically records a few different kinds of user interaction events. blur
events occur when the user clicks on another window or tab during the experiment, indicating that they are no longer interacting with the experiment. focus
events occur when the user clicks on the experiment window after having clicked somewhere else first (i.e., generated a blur
event). fullscreenenter
and fullscreenexit
events are triggered by the browser entering and exiting fullscreen mode. However, fullscreenenter
events only occur when the script switches the browser to fullscreen mode, e.g., with the fullscreen plugin. Manually entering fullscreen mode does not trigger this event. fullscreenexit
events occur whether the user manually exits fullscreen mode or the script exits fullscreen mode. This method returns the DataCollection containing all interaction events. This is useful for tracking whether the participant completed the task without diverting attention to other windows. Events are in the form:
{\n type: 'focus' or 'blur' or 'fullscreenenter' or 'fullscreenexit',\n trial: 10, // the trial number when the event happened\n time: 13042 // total time elapsed since the start of the experiment\n}\n
"},{"location":"reference/jspsych-data/#example_1","title":"Example","text":"var interaction_data = jsPsych.data.getInteractionData();\n// log data to console in json format\nconsole.log(interaction_data.json());\n
"},{"location":"reference/jspsych-data/#jspsychdatagetlasttimelinedata","title":"jsPsych.data.getLastTimelineData","text":"jsPsych.data.getLastTimelineData()\n
"},{"location":"reference/jspsych-data/#return-value_4","title":"Return value","text":"Returns a DataCollection.
"},{"location":"reference/jspsych-data/#description_4","title":"Description","text":"Gets all of the data generated in the same timeline as the last trial.
"},{"location":"reference/jspsych-data/#example_2","title":"Example","text":"var lasttimelinedata = jsPsych.data.getLastTimelineData();\n
"},{"location":"reference/jspsych-data/#jspsychdatagetlasttrialdata","title":"jsPsych.data.getLastTrialData","text":"jsPsych.data.getLastTrialData()\n
"},{"location":"reference/jspsych-data/#return-value_5","title":"Return value","text":"Returns a DataCollection.
"},{"location":"reference/jspsych-data/#description_5","title":"Description","text":"Gets the data collection containing all data generated by the last trial.
"},{"location":"reference/jspsych-data/#example_3","title":"Example","text":"var lasttrialdata = jsPsych.data.getLastTrialData();\n
"},{"location":"reference/jspsych-data/#jspsychdatageturlvariable","title":"jsPsych.data.getURLVariable","text":"jsPsych.data.getURLVariable(var_name)\n
"},{"location":"reference/jspsych-data/#parameters_4","title":"Parameters","text":"Parameter Type Description var_name string Which variable to get the value of."},{"location":"reference/jspsych-data/#return-value_6","title":"Return value","text":"Returns the value of a variable passed in through the query string.
"},{"location":"reference/jspsych-data/#description_6","title":"Description","text":"For extracting a particular variable passed in through a URL query string.
"},{"location":"reference/jspsych-data/#example_4","title":"Example","text":"// if the URL of the page is: experiment.html?subject=1234&condition=test\nconsole.log(jsPsych.data.getURLVariable('subject')) // logs \"1234\"\nconsole.log(jsPsych.data.getURLVariable('condition')) // logs \"test\"\n
"},{"location":"reference/jspsych-data/#jspsychdataurlvariables","title":"jsPsych.data.urlVariables","text":"jsPsych.data.urlVariables()\n
"},{"location":"reference/jspsych-data/#return-value_7","title":"Return value","text":"Returns an object (associative array) of the variables in the URL query string.
"},{"location":"reference/jspsych-data/#description_7","title":"Description","text":"For extracting variables passed in through a URL query string.
"},{"location":"reference/jspsych-data/#example_5","title":"Example","text":"// if the URL of the page is: experiment.html?subject=1234&condition=test\nvar urlvar = jsPsych.data.urlVariables();\nconsole.log(urlvar.subject) // logs \"1234\"\nconsole.log(urlvar.condition) // logs \"test\"\n
"},{"location":"reference/jspsych-data/#jspsychdatawrite","title":"jsPsych.data.write","text":"jsPsych.data.write(data_object)\n
"},{"location":"reference/jspsych-data/#parameters_5","title":"Parameters","text":"Parameter Type Description data_object object Object of key: value
pairs to store in jsPsych's data storage as a trial."},{"location":"reference/jspsych-data/#return-value_8","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-data/#description_8","title":"Description","text":"This method is used by jsPsych.finishTrial
for writing data. You should probably not use it to add data. Instead use jsPsych.data.addProperties.
"},{"location":"reference/jspsych-data/#example_6","title":"Example","text":"// don't use this! data should only be written once per trial. use jsPsych.finishTrial to save data.\n\nvar trial_data = {\n correct: true,\n rt: 487\n}\n\njsPsych.data.write(trial_data);\n
"},{"location":"reference/jspsych-data/#datacollection","title":"DataCollection","text":"All data is stored in the DataCollection object. Using methods like jsPsych.data.get()
and jsPsych.data.getLastTrialData()
return DataCollections containing the experiment data. This is a list of all of the methods that are available to call on a DataCollection object.
"},{"location":"reference/jspsych-data/#addtoall","title":".addToAll()","text":"Adds a set of properties to all items in the DataCollection. Similar to jsPsych.data.addProperties()
, except that it can be applied to a subset of the whole DataCollection by filtering down to a smaller DataCollection first.
jsPsych.data.get().addToAll({subject_id: 123, condition: 'control'});\n
"},{"location":"reference/jspsych-data/#addtolast","title":".addToLast()","text":"Adds a set of properties to the last trial in the DataCollection.
jsPsych.data.get().addToLast({success: true});\n
"},{"location":"reference/jspsych-data/#count","title":".count()","text":"Counts the number of trials in the DataCollection.
jsPsych.data.get().count()\n
"},{"location":"reference/jspsych-data/#csv","title":".csv()","text":"Generates a CSV string representing all of the data in the DataCollection.
console.log(jsPsych.data.get().csv());\n
"},{"location":"reference/jspsych-data/#filter","title":".filter()","text":"Returns a subset of the DataCollection based on the filter. The filter is an object, and trials are only kept in the returned DataCollection if they contain the key: value pair(s) in the filter object. For example, the code below selects all of the trials with a correct response.
var correct_trials = jsPsych.data.get().filter({correct: true});\n
The object can have multiple key: value pairs, and the trials must match all of them in order to be included in the returned collection.
// keep only correct trials from the practice phase\nvar correct_practice_trials = jsPsych.data.get().filter({correct:true, phase: 'practice'});\n
The filter can also be an array of objects. In this case each object in the array acts as an OR filter. As long as the trial has all the key: value pairs of one of the objects in the array, it will appear in the returned collection.
// select trials from block 1 and block 5.\nvar trials = jsPsych.data.get().filter([{block: 1}, {block:5}]);\n
The filter method returns a DataCollection object, so methods can be chained onto a single statement.
// count the number of correct trials in block 1\nvar block_1_correct = jsPsych.data.get().filter({block:1, correct:true}).count();\n
"},{"location":"reference/jspsych-data/#filtercolumns","title":".filterColumns()","text":"Selects the set of columns listed in the array. This is the opposite of the .ignore()
method.
// Get only the subject, rt, and condition entries for each trial.\nconst subset_of_data = jsPsych.data.get().filterColumns(['subject', 'rt', 'condition'])\n
"},{"location":"reference/jspsych-data/#filtercustom","title":".filterCustom()","text":"This method is similar to the .filter()
method, except that it accepts a function as the filter. The function is passed a single argument, containing the data for a trial. If the function returns true
the trial is included in the returned DataCollection.
// count the number of trials with a response time greater than 2000ms.\nvar too_long = jsPsych.data.get().filterCustom(function(trial){\n return trial.rt > 2000;\n}).count()\n
"},{"location":"reference/jspsych-data/#first-last","title":".first() / .last()","text":"Returns a DataCollection containing the first/last n trials. If n is greater than the number of trials in the DataCollection, then these functions will return an array of length equal to the number of trials. If there are no trials in the DataCollection, then these functions will return an empty array. If the n argument is omitted, then the functions will use the default value of 1. If n is zero or a negative number, then these functions will throw an error.
var first_trial = jsPsych.data.get().first(1);\nvar last_trial_with_correct_response = jsPsych.data.get().filter({correct: true}).last(1);\nvar last_10_trials = jsPsych.data.get().last(10);\n
"},{"location":"reference/jspsych-data/#ignore","title":".ignore()","text":"Returns a DataCollection with all instances of a particular key removed from the dataset.
// log a csv file that does not contain the trial_type values for each trial\nconsole.log(jsPsych.data.get().ignore('trial_type').csv());\n
"},{"location":"reference/jspsych-data/#join","title":".join()","text":"Appends one DataCollection onto another and returns the combined collection.
// get a DataCollection with all trials that are either correct or\n// have a response time greater than 200ms.\nvar dc1 = jsPsych.data.get().filter({correct: true});\nvar dc2 = jsPsych.data.get().filterCustom(function(trial){ return trial.rt > 200});\nvar data = dc1.join(dc2);\n
"},{"location":"reference/jspsych-data/#json","title":".json()","text":"Generates a JSON string representing all of the data in the DataCollection.
console.log(jsPsych.data.get().json());\n
"},{"location":"reference/jspsych-data/#localsave","title":".localSave()","text":"Saves a CSV or JSON file on the computer running the experiment. If conducting an online experiment, this will download the file onto the subject's computer, and is therefore not a recommended data storage solution for online data collection.
Warning: This function may not behave correctly in older browsers. Upgrading to the latest version of any major web browser should solve the problem.
// first argument is the format, second is the filename.\n// the format can be either 'csv' or 'json'.\njsPsych.data.get().localSave('csv','mydata.csv');\n
"},{"location":"reference/jspsych-data/#push","title":".push()","text":"Add a new entry to the DataCollection. This method is mostly used internally, and you shouldn't need to call it under normal circumstances.
var data = {correct: true, rt: 500}\njsPsych.data.get().push(data);\n
"},{"location":"reference/jspsych-data/#readonly","title":".readOnly()","text":"Creates a copy of the DataCollection so that any modification of the values in the DataCollection will not affect the original.
// this line edits the rt property of the first trial\njsPsych.data.get().first(1).values()[0].rt = 100;\n\n// readOnly creates a copy that can be modified without affecting the original\n\njsPsych.data.get().first(1).values()[0].rt\n// outputs 100\n\njsPsych.data.get().readOnly().first(1).values()[0].rt = 200\njsPsych.data.get().first(1).values()[0].rt\n// still outputs 100\n
"},{"location":"reference/jspsych-data/#select","title":".select()","text":"Returns a DataColumn object (see documentation below) of a single property from a DataCollection object.
var rt_data = jsPsych.data.get().select('rt');\nrt_data.mean()\n
"},{"location":"reference/jspsych-data/#uniquenames","title":".uniqueNames()","text":"Generates an array of all the unique key names in the set of trials contained in the DataCollection. This is especially useful when setting up a relational database (e.g., MySQL) where the column names need to be specified in advance.
console.log(jsPsych.data.get().uniqueNames());\n
"},{"location":"reference/jspsych-data/#values","title":".values()","text":"Returns the raw data array associated with the DataCollection. This array is modifiable, so changes to the array and values of objects in the array will change the DataCollection.
var raw_data = jsPsych.data.get().values();\n\n// was response in first trial correct?\nif(raw_data[0].correct){\n console.log('correct!');\n} else {\n console.log('incorrect.');\n}\n
"},{"location":"reference/jspsych-data/#datacolumn","title":"DataColumn","text":"DataColumn objects represent all the values of a single property in a DataCollection. They are generated by using the .select()
method on a DataCollection. Once a DataColumn is generated, the following methods can be used.
"},{"location":"reference/jspsych-data/#all","title":".all()","text":"Checks if all values in the DataColumn return true
when passed to a function. The function takes a single argument, which represents one value from the DataColumn.
// check if all the response times in the practice phase were under 1000ms\njsPsych.data.get().filter({phase: 'practice'}).select('correct').all(function(x) { return x < 1000; });\n
"},{"location":"reference/jspsych-data/#count_1","title":".count()","text":"Counts the number of values in the DataColumn.
// count how many response times there are\njsPsych.data.get().select('rt').count();\n
"},{"location":"reference/jspsych-data/#frequencies","title":".frequencies()","text":"Counts the number of occurrences of each unique value in the DataColumn. Returns this value as an object, where each key is a unique value and the value of each key is the number of occurrences of that key.
// get frequencies of correct and incorrect responses\njsPsych.data.get().select('correct').frequencies();\n
"},{"location":"reference/jspsych-data/#max-min","title":".max() / .min()","text":"Returns the maximum or minimum value in a DataColumn.
jsPsych.data.get().select('rt').max();\njsPsych.data.get().select('rt').min();\n
"},{"location":"reference/jspsych-data/#mean","title":".mean()","text":"Returns the average of all the values in a DataColumn.
jsPsych.data.get().select('rt').mean();\n
"},{"location":"reference/jspsych-data/#median","title":".median()","text":"Returns the median of all the values in a DataColumn.
jsPsych.data.get().select('rt').median();\n
"},{"location":"reference/jspsych-data/#sd","title":".sd()","text":"Returns the standard deviation of the values in a DataColumn.
jsPsych.data.get().select('rt').sd();\n
"},{"location":"reference/jspsych-data/#subset","title":".subset()","text":"Filters the DataColumn to include only values that return true
when passed through the specified function.
// below results will be less than 200.\njsPsych.data.get().select('rt').subset(function(x){ return x < 200; }).max();\n
"},{"location":"reference/jspsych-data/#sum","title":".sum()","text":"Returns the sum of the values in a DataColumn.
jsPsych.data.get().select('rt').sum();\n
"},{"location":"reference/jspsych-data/#values_1","title":".values","text":"The raw array of values in the DataColumn.
// note that this is not a function call.\njsPsych.data.get().select('rt').values;\n
"},{"location":"reference/jspsych-data/#variance","title":".variance()","text":"Returns the variance of the values in a DataColumn.
jsPsych.data.get().select('rt').variance();\n
"},{"location":"reference/jspsych-pluginAPI/","title":"jsPsych.pluginAPI","text":"The pluginAPI module contains functions that are useful when developing plugins. All of the functions are accessible through the pluginAPI
object. In this documentation we've divided them up based on different kinds of functionality.
"},{"location":"reference/jspsych-pluginAPI/#keyboard-input","title":"Keyboard Input","text":""},{"location":"reference/jspsych-pluginAPI/#cancelallkeyboardresponses","title":"cancelAllKeyboardResponses","text":"jsPsych.pluginAPI.cancelAllKeyboardResponses()\n
"},{"location":"reference/jspsych-pluginAPI/#parameters","title":"Parameters","text":"None.
"},{"location":"reference/jspsych-pluginAPI/#return-value","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-pluginAPI/#description","title":"Description","text":"Cancels all currently active keyboard listeners created by jsPsych.pluginAPI.getKeyboardResponse
.
"},{"location":"reference/jspsych-pluginAPI/#example","title":"Example","text":"jsPsych.pluginAPI.cancelAllKeyboardResponses();\n
"},{"location":"reference/jspsych-pluginAPI/#cancelkeyboardresponse","title":"cancelKeyboardResponse","text":"jsPsych.pluginAPI.cancelKeyboardResponse(listener_id)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_1","title":"Parameters","text":"Parameter Type Description listener_id object The listener_id object generated by the call to jsPsych.pluginAPI.getKeyboardResponse
."},{"location":"reference/jspsych-pluginAPI/#return-value_1","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-pluginAPI/#description_1","title":"Description","text":"Cancels a specific keyboard listener created by jsPsych.pluginAPI.getKeyboardResponse
.
"},{"location":"reference/jspsych-pluginAPI/#example_1","title":"Example","text":"// create a persistent keyboard listener\nvar listener_id = jsPsych.pluginAPI.getKeyboardResponse({\n callback_function: after_response, \n valid_responses: ['p','q'], \n rt_method: 'performance', \n persist: true,\n allow_held_key: false\n});\n\n// cancel keyboard listener\njsPsych.pluginAPI.cancelKeyboardResponse(listener_id);\n
"},{"location":"reference/jspsych-pluginAPI/#comparekeys","title":"compareKeys","text":"jsPsych.pluginAPI.compareKeys(key1, key2)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_2","title":"Parameters","text":"Parameter Type Description key1 string or numeric The representation of a key, either string or keycode key2 string or numeric The representation of a key, either string or keycode"},{"location":"reference/jspsych-pluginAPI/#return-value_2","title":"Return value","text":"Returns true if keycodes or strings refer to the same key, regardless of type. Returns false if the keycodes or strings do not match.
"},{"location":"reference/jspsych-pluginAPI/#description_2","title":"Description","text":"Compares two keys to see if they are the same, ignoring differences in representational type, and using the appropriate case sensitivity based on the experiment's settings.
If case_sensitive_responses
is set to false
in initJsPsych
(the default), then the string key comparison will not be case-sensitive, e.g., \"a\" and \"A\" will match, and this function will return true
. If case_sensitive_responses
is set to true
in initJsPsych
, then the string key comparison will not be case-sensitive, e.g., \"a\" and \"A\" will not match, and this function will return false
.
We recommend using this function to compare keys in all plugin and experiment code, rather than using something like if (response == 'j')...
. This is because the response key returned by the jsPsych.pluginAPI.getKeyboardResponse
function will be converted to lowercase when case_sensitive_responses
is false
, and it will match the exact key press representation when case_sensitive_responses
is true
. Using this compareKeys
function will ensure that your key comparisons work appropriately based on the experiment's case_sensitive_responses
setting, and that you do not need to remember to check key responses against different case versions of the comparison key (e.g. if (response == 'ArrowLeft' || response == 'arrowleft')...
).
"},{"location":"reference/jspsych-pluginAPI/#examples","title":"Examples","text":""},{"location":"reference/jspsych-pluginAPI/#basic-examples","title":"Basic examples","text":"jsPsych.pluginAPI.compareKeys('a', 'A');\n// returns true when case_sensitive_responses is false in initJsPsych\n\njsPsych.pluginAPI.compareKeys('a', 'A');\n// returns false when case_sensitive_responses is true in initJsPsych\n\n// also works with numeric key codes (but note that numeric keyCode values are now deprecated)\njsPsych.pluginAPI.compareKeys('a', 65);\n// returns true\n\njsPsych.pluginAPI.compareKeys('space', 31);\n// returns false\n
"},{"location":"reference/jspsych-pluginAPI/#comparing-a-key-response-and-key-parameter-value-in-plugins","title":"Comparing a key response and key parameter value in plugins","text":"// this is the callback_function passed to jsPsych.pluginAPI.getKeyboardResponse\nvar after_response = function(info) {\n // score the response by comparing the key that was pressed against the trial's key_answer parameter\n var correct = jsPsych.pluginAPI.compareKeys(trial.key_answer, info.key);\n //...\n}\n
"},{"location":"reference/jspsych-pluginAPI/#scoring-a-key-response-in-experiment-code","title":"Scoring a key response in experiment code","text":"var trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<<<<<',\n choices: ['f','j'],\n prompt: 'Press f for left. Press j for right.',\n on_finish: function(data){\n // score the response by comparing the key that was pressed (data.response) against the \n // correct response for this trial ('f'), and store reponse accuracy in the trial data\n if(jsPsych.pluginAPI.compareKeys(data.response, 'f')){\n data.correct = true;\n } else {\n data.correct = false; \n }\n }\n}\n
"},{"location":"reference/jspsych-pluginAPI/#getkeyboardresponse","title":"getKeyboardResponse","text":"jsPsych.pluginAPI.getKeyboardResponse(parameters)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_3","title":"Parameters","text":"The method accepts an object of parameter values (see example below). The valid keys for this object are listed in the table below.
Parameter Type Description callback_function function The function to execute whenever a valid keyboard response is generated. valid_responses array An array of key codes or character strings representing valid responses. Responses not on the list will be ignored. An empty array indicates that no response is acceptable. rt_method string Indicates which method of recording time to use. The 'performance'
method uses calls to performance.now()
, which is the standard way of measuring timing in jsPsych. It is supported by up-to-date versions of all the major browsers. The audio
method is used in conjuction with an audio_context
(set as an additional parameter). This uses the clock time of the audio_context
when audio stimuli are being played. audio_context AudioContext object The AudioContext of the audio file that is being played. audio_context_start_time numeric The scheduled time of the sound file in the AudioContext. This will be used as the start time. allow_held_key boolean If true
, then responses will be registered from keys that are being held down. If false
, then a held key can only register a response the first time that getKeyboardResponse
is called for that key. For example, if a participant holds down the A
key before the experiment starts, then the first time getKeyboardResponse
is called, the A
will register as a key press. However, any future calls to getKeyboardResponse
will not register the A
until the participant releases the key and presses it again. persist boolean If false, then the keyboard listener will only trigger the first time a valid key is pressed. If true, then it will trigger every time a valid key is pressed until it is explicitly cancelled by jsPsych.pluginAPI.cancelKeyboardResponse
or jsPsych.pluginAPI.cancelAllKeyboardResponses
. minimum_valid_rt number The minimum valid response time for key presses. Any key press response time that is less than this value will be treated as invalid and ignored."},{"location":"reference/jspsych-pluginAPI/#return-value_3","title":"Return value","text":"Return an object that uniquely identifies the keyboard listener. This object can be passed to jsPsych.pluginAPI.cancelKeyboardResponse
to cancel the keyboard listener.
"},{"location":"reference/jspsych-pluginAPI/#description_3","title":"Description","text":"Gets a keyboard response from the participant, recording the response time from when the function is first called until a valid response is generated.
The keyboard event listener will be bound to the display_element
declared in initJsPsych()
(or the <body>
element if no display_element
is specified). This allows jsPsych experiments to be embedded in websites with other content without disrupting the functionality of other UI elements.
A valid response triggers the callback_function
specified in the parameters. A single argument is passed to the callback function. The argument contains an object with the properties key
and rt
. key
contains the string representation of the response key, and rt
contains the response time.
This function uses the .key
value of the keyboard event, which is case sensitive. When case_sensitive_responses
is false
in initJsPsych
(the default), this function will convert both the valid_responses
strings and the response key to lowercase before comparing them, and it will pass the lowercase version of the response key to the callback_function
. For example, if valid_responses
is ['a']
, then both 'A' and 'a' will be considered valid key presses, and 'a' will be returned as the response key. When case_sensitive_responses
is true
in initJsPsych
, this function will not convert the case when comparing the valid_responses
and response key, and it will not convert the case of the response key that is passed to the callback_function
. For example, if valid_responses
is ['a']
, then 'a' will be the only valid key press, and 'A' (i.e. 'a' with CapsLock on or Shift held down) will not be accepted. Also, if valid_responses
includes multiple letter case options (e.g. \"ALL_KEYS\"
), then you may need to check the response key against both letter cases when scoring etc., e.g. if (response == 'ArrowLeft' || response =='arrowleft') ...
.
"},{"location":"reference/jspsych-pluginAPI/#examples_1","title":"Examples","text":""},{"location":"reference/jspsych-pluginAPI/#get-a-single-response-from-any-key","title":"Get a single response from any key","text":"var after_response = function(info){\n alert('You pressed key '+info.key+' after '+info.rt+'ms');\n}\n\njsPsych.pluginAPI.getKeyboardResponse({\n callback_function:after_response,\n valid_responses: \"ALL_KEYS\",\n rt_method: 'performance',\n persist: false\n});\n
"},{"location":"reference/jspsych-pluginAPI/#get-a-responses-from-a-key-until-the-letter-q-is-pressed","title":"Get a responses from a key until the letter q is pressed","text":"var after_response = function(info){\n alert('You pressed key '+info.key+' after '+info.rt+'ms');\n\n if(jsPsych.pluginAPI.compareKeys(info.key,'q')){ /\n jsPsych.pluginAPI.cancelKeyboardResponse(listener);\n }\n}\n\nvar listener = jsPsych.pluginAPI.getKeyboardResponse({\n callback_function:after_response,\n valid_responses: \"ALL_KEYS\",\n rt_method: 'performance',\n persist: true\n});\n
"},{"location":"reference/jspsych-pluginAPI/#audio","title":"Audio","text":"All audio-related functionality is handled by the AudioPlayer class.
"},{"location":"reference/jspsych-pluginAPI/#getaudioplayer","title":"getAudioPlayer","text":"jsPsych.pluginAPI.getAudioPlayer(filepath)\n
"},{"location":"reference/jspsych-pluginAPI/#return-value_4","title":"Return value","text":"Returns a Promise that resolves to an instance of an AudioPlayer class that holds the buffer of the audio file when it finishes loading.
"},{"location":"reference/jspsych-pluginAPI/#description_4","title":"Description","text":"Gets an AudioPlayer class instance which has methods that can be used to play or stop audio that can be played with the WebAudio API or an audio object that can be played as HTML5 Audio.
It is strongly recommended that you preload audio files before calling this method. This method will load the files if they are not preloaded, but this may result in delays during the experiment as audio is downloaded.
"},{"location":"reference/jspsych-pluginAPI/#examples_2","title":"Examples","text":""},{"location":"reference/jspsych-pluginAPI/#html-5-audio-and-webaudio-api","title":"HTML 5 Audio and WebAudio API","text":"const audio = await jsPsych.pluginAPI.getAudioPlayer('my-sound.mp3')\n\naudio.play()\n
See the audio-keyboard-response
plugin for an example in a fuller context.
"},{"location":"reference/jspsych-pluginAPI/#play","title":"play","text":"const audio = jsPsych.pluginAPI.getAudioPlayer(filepath)\n\naudio.play()\n
"},{"location":"reference/jspsych-pluginAPI/#return-value_5","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-pluginAPI/#description_5","title":"Description","text":"Method that belongs to the AudioPlayer class. Plays the audio loaded into the audio buffer of the AudioPlayer instance for a particular file. If the audio is a HTML5 audio object it plays it. If the audio is a Webaudio API object it starts it.
"},{"location":"reference/jspsych-pluginAPI/#example_2","title":"Example","text":""},{"location":"reference/jspsych-pluginAPI/#html-5-audio-and-webaudio-api_1","title":"HTML 5 Audio and WebAudio API","text":"const audio = await jsPsych.pluginAPI.getAudioPlayer('my-sound.mp3');\n\naudio.play();\n
See the audio-keyboard-response
plugin for an example in a fuller context.
"},{"location":"reference/jspsych-pluginAPI/#stop","title":"stop","text":"const audio = jsPsych.pluginAPI.getAudioPlayer(filepath);\n\naudio.play();\n
"},{"location":"reference/jspsych-pluginAPI/#return-value_6","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-pluginAPI/#description_6","title":"Description","text":"Method that belongs to the AudioPlayer class. Stops the audio loaded into the audio buffer of the AudioPlayer instance for a particular file. If the audio is an HTML5 audio object it pauses it. If the audio is a Webaudio API object it stops it.
"},{"location":"reference/jspsych-pluginAPI/#example_3","title":"Example","text":""},{"location":"reference/jspsych-pluginAPI/#html-5-audio-and-webaudio-api_2","title":"HTML 5 Audio and WebAudio API","text":"const audio = await jsPsych.pluginAPI.getAudioPlayer('my-sound.mp3');\n\naudio.play();\n\naudio.stop();\n
See the audio-keyboard-response
plugin for an example in a fuller context.
"},{"location":"reference/jspsych-pluginAPI/#addeventlistener","title":"addEventListener","text":"const audio = jsPsych.pluginAPI.getAudioPlayer(filepath);\n\naudio.addEventListener(eventName, callback);\n
"},{"location":"reference/jspsych-pluginAPI/#return-value_7","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-pluginAPI/#description_7","title":"Description","text":"Method that belongs to the AudioPlayer class. Adds an event listener to the media Element that corresponds to the AudioPlayer class instance.
"},{"location":"reference/jspsych-pluginAPI/#example_4","title":"Example","text":"const audio = await jsPsych.pluginAPI.getAudioPlayer('my-sound.mp3');\n\naudio.play();\n\naudio.addEventListener('ended', end_trial());\n
See the audio-keyboard-response
plugin for an example in a fuller context.
"},{"location":"reference/jspsych-pluginAPI/#removeeventlistener","title":"removeEventListener","text":"const audio = jsPsych.pluginAPI.getAudioPlayer(filepath);\n\naudio.removeEventListener(eventName, callback);\n
"},{"location":"reference/jspsych-pluginAPI/#return-value_8","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-pluginAPI/#description_8","title":"Description","text":"Method that belongs to the AudioPlayer class. Removes an event listener from the media Element that corresponds to the AudioPlayer class instance.
"},{"location":"reference/jspsych-pluginAPI/#example_5","title":"Example","text":"const audio = await jsPsych.pluginAPI.getAudioPlayer('my-sound.mp3');\n\naudio.play();\n\naudio.addEventListener('ended', end_trial());\n\naudio.removeEventListener('ended', end_trial());\n
See the audio-keyboard-response
plugin for an example in a fuller context.
"},{"location":"reference/jspsych-pluginAPI/#other-media","title":"Other Media","text":""},{"location":"reference/jspsych-pluginAPI/#getaudiobuffer","title":"getAudioBuffer","text":"jsPsych.pluginAPI.getAudioBuffer(filepath)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_4","title":"Parameters","text":"Parameter Type Description filepath string The path to the audio file that was preloaded."},{"location":"reference/jspsych-pluginAPI/#return-value_9","title":"Return value","text":"Returns a Promise that resolves when the audio file loads. Success handler's parameter will be the audio buffer. If the experiment is running using the WebAudio API it will be an AudioBuffer object. Otherwise, it will be an HTML5 Audio object. The failure handler's parameter is the error generated by preloadAudio
.
"},{"location":"reference/jspsych-pluginAPI/#description_9","title":"Description","text":"Gets an AudioBuffer that can be played with the WebAudio API or an Audio object that can be played with HTML5 Audio.
It is strongly recommended that you preload audio files before calling this method. This method will load the files if they are not preloaded, but this may result in delays during the experiment as audio is downloaded.
"},{"location":"reference/jspsych-pluginAPI/#examples_3","title":"Examples","text":""},{"location":"reference/jspsych-pluginAPI/#html-5-audio","title":"HTML 5 Audio","text":"jsPsych.pluginAPI.getAudioBuffer('my-sound.mp3')\n .then(function(audio){\n audio.play();\n })\n .catch(function(err){\n console.error('Audio file failed to load')\n })\n
"},{"location":"reference/jspsych-pluginAPI/#webaudio-api","title":"WebAudio API","text":"var context = jsPsych.pluginAPI.audioContext();\n\njsPsych.pluginAPI.getAudioBuffer('my-sound.mp3')\n .then(function(buffer){\n audio = context.createBufferSource();\n audio.buffer = buffer;\n audio.connect(context.destination);\n audio.start(context.currentTime);\n })\n .catch(function(err){\n console.error('Audio file failed to load')\n })\n
See the audio-keyboard-response
plugin for an example in a fuller context.
"},{"location":"reference/jspsych-pluginAPI/#getautopreloadlist","title":"getAutoPreloadList","text":"jsPsych.pluginAPI.getAutoPreloadList(timeline)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_5","title":"Parameters","text":"Parameter Type Description timeline array An array containing the trial object(s) from which a list of media files should be automatically generated. This array can contain the entire experiment timeline, or any individual parts of a larger timeline, such as specific timeline nodes and trial objects."},{"location":"reference/jspsych-pluginAPI/#return-value_10","title":"Return value","text":"An object with properties for each media type: images
, audio
, and video
. Each property contains an array of the unique files of that media type that were automatically extracted from the timeline. If no files are found in the timeline for a particular media type, then the array will be empty for that type.
"},{"location":"reference/jspsych-pluginAPI/#description_10","title":"Description","text":"This method is used to automatically generate lists of unique image, audio, and video files from a timeline. It is used by the preload
plugin to generate a list of to-be-preloaded files based on the trials passed to the trials
parameter and/or the experiment timeline passed to jsPsych.run
(when auto_preload
is true). It can be used in custom plugins and experiment code to generate a list of audio/image/video files, based on a timeline.
This function will only return files from plugin parameters that are marked as parameter type AUDIO
/IMAGE
/VIDEO
, and only when the preload
flag of the corresponding parameter definition has not been set to false
, and the trial's parameter value is not a function. When a file path is returned to the trial parameter from a function (including the jsPsych.timelineVariable
function), or when the file path is embedded in an HTML string, that file will not be detected by the getAutoPreloadList
method. In these cases, the file should be preloaded manually. See Media Preloading for more information.
"},{"location":"reference/jspsych-pluginAPI/#example_6","title":"Example","text":"var audio_trial = {\n type: jsPsychAudioKeyboardResponse\n stimulus: 'file.mp3'\n}\n\nvar image_trial = {\n type: jsPsychImageKeyboardResponse\n stimulus: 'file.png'\n}\n\nvar video_trial = {\n type: jsPsychVideoKeyboardResponse\n stimulus: 'file.mp4'\n}\n\nvar timeline = [audio_trial, image_trial, video_trial];\n\njsPsych.pluginAPI.getAutoPreloadList(timeline);\n
"},{"location":"reference/jspsych-pluginAPI/#getcamerarecorder","title":"getCameraRecorder","text":"jsPsych.pluginAPI.getCameraRecorder()\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_6","title":"Parameters","text":"None
"},{"location":"reference/jspsych-pluginAPI/#return-value_11","title":"Return value","text":"A MediaRecorder
object connected to the MediaStream
for the active camera.
"},{"location":"reference/jspsych-pluginAPI/#description_11","title":"Description","text":"Provides access to the MediaRecorder
created by initializeCameraRecorder(). If no camera recorder exists, it returns null
.
"},{"location":"reference/jspsych-pluginAPI/#example_7","title":"Example","text":"const recorder = jsPsych.pluginAPI.getCameraRecorder();\n
"},{"location":"reference/jspsych-pluginAPI/#getmicrophonerecorder","title":"getMicrophoneRecorder","text":"jsPsych.pluginAPI.getMicrophoneRecorder()\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_7","title":"Parameters","text":"None
"},{"location":"reference/jspsych-pluginAPI/#return-value_12","title":"Return value","text":"A MediaRecorder
object connected to the MediaStream
for the active microphone.
"},{"location":"reference/jspsych-pluginAPI/#description_12","title":"Description","text":"Provides access to the MediaRecorder
created by initializeMicrophoneRecorder(). If no microphone recorder exists, it returns null
.
"},{"location":"reference/jspsych-pluginAPI/#example_8","title":"Example","text":"const recorder = jsPsych.pluginAPI.getMicrophoneRecorder();\n
"},{"location":"reference/jspsych-pluginAPI/#initializecamerarecorder","title":"initializeCameraRecorder","text":"jsPsych.pluginAPI.initializeCameraRecorder(stream)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_8","title":"Parameters","text":"Parameter Type Description stream MediaStream
The MediaStream
object from an active camera device. opts MediaRecorderOptions
The MediaRecorderOptions
for the recorder. See MDN docs for details about these options."},{"location":"reference/jspsych-pluginAPI/#return-value_13","title":"Return value","text":"None.
"},{"location":"reference/jspsych-pluginAPI/#description_13","title":"Description","text":"Generates a MediaRecorder
object from provided MediaStream
and stores this for access via getCameraRecorder().
"},{"location":"reference/jspsych-pluginAPI/#example_9","title":"Example","text":"const stream = await navigator.mediaDevices.getUserMedia({\n audio: true,\n video: { width: 1280, height: 720 }, // request a certain resolution\n});\n\njsPsych.pluginAPI.initializeCameraRecorder(stream);\n
"},{"location":"reference/jspsych-pluginAPI/#initializemicrophonerecorder","title":"initializeMicrophoneRecorder","text":"jsPsych.pluginAPI.initializeMicrophoneRecorder(stream)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_9","title":"Parameters","text":"Parameter Type Description stream MediaStream
The MediaStream
object from an active microphone device."},{"location":"reference/jspsych-pluginAPI/#return-value_14","title":"Return value","text":"None.
"},{"location":"reference/jspsych-pluginAPI/#description_14","title":"Description","text":"Generates a MediaRecorder
object from provided MediaStream
and stores this for access via getMicrophoneRecorder().
"},{"location":"reference/jspsych-pluginAPI/#example_10","title":"Example","text":"const stream = await navigator.mediaDevices.getUserMedia({ audio: { deviceId: mic_id } });\n\njsPsych.pluginAPI.initializeMicrophoneRecorder(stream);\n
"},{"location":"reference/jspsych-pluginAPI/#preloadaudio","title":"preloadAudio","text":"jsPsych.pluginAPI.preloadAudio(files, callback_complete, callback_load, callback_error)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_10","title":"Parameters","text":"Parameter Type Description files array An array of audio file paths to load. The array can be nested (e.g., if images are in multiple arrays to help sort by condition or task). callback_complete function A function to execute when all the files have been loaded. callback_load function A function to execute after a single file has been loaded. A single parameter is passed to this function which is the file source (string) that has loaded. callback_error function A function to execute after a single file has produced an error. A single parameter is passed to this function which is the file source (string) that produced the error."},{"location":"reference/jspsych-pluginAPI/#return-value_15","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-pluginAPI/#description_15","title":"Description","text":"This function is used to preload audio files. It is used by the preload
plugin, and could be called directly to preload audio files in custom plugins or experiment. See Media Preloading for more information.
It is possible to run this function without specifying a callback function. However, in this case the code will continue executing while the files are loaded. Thus, it is possible that an audio file would be required for playing before it is done preloading. The callback_complete
function will only execute after all the audio files are loaded, and can be used to control the flow of the experiment (e.g., by starting the experiment in the callback_complete
function).
The callback_load
and callback_error
functions are called after each file has either loaded or produced an error, so these functions can also be used to monitor loading progress. See example below.
"},{"location":"reference/jspsych-pluginAPI/#examples_4","title":"Examples","text":""},{"location":"reference/jspsych-pluginAPI/#basic-use","title":"Basic use","text":"var sounds = ['file1.mp3', 'file2.mp3', 'file3.mp3'];\n\njsPsych.pluginAPI.preloadAudio(sounds, \n function(){ startExperiment(); },\n function(file){ console.log('file loaded: ', file); }\n function(file){ console.log('error loading file: ', file); }\n);\n\nfunction startExperiment(){\n jsPsych.run(exp);\n}\n
"},{"location":"reference/jspsych-pluginAPI/#show-progress-of-loading","title":"Show progress of loading","text":"var sounds = ['file1.mp3', 'file2.mp3', 'file3.mp3'];\nvar n_loaded = 0;\n\njsPsych.pluginAPI.preloadAudio(sounds, function(){ startExperiment(); }, function(file) { updateLoadedCount(file); });\n\nfunction updateLoadedCount(file){\n n_loaded++;\n var percentcomplete = n_loaded / sounds.length * 100;\n\n // could put something fancier here, like a progress bar\n // or updating text in the DOM.\n console.log('Loaded '+percentcomplete+'% of audio files');\n}\n\nfunction startExperiment(){\n jsPsych.run(exp);\n}\n
"},{"location":"reference/jspsych-pluginAPI/#preloadimages","title":"preloadImages","text":"jsPsych.pluginAPI.preloadImages(images, callback_complete, callback_load, callback_error)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_11","title":"Parameters","text":"Parameter Type Description images array An array of image paths to load. The array can be nested (e.g., if images are in multiple arrays to help sort by condition or task). callback_complete function A function to execute when all the images have been loaded. callback_load function A function to execute after a single file has been loaded. A single parameter is passed to this function which is the file source (string) that has loaded. callback_error function A function to execute after a single file has produced an error. A single parameter is passed to this function which is the file source (string) that produced the error."},{"location":"reference/jspsych-pluginAPI/#return-value_16","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-pluginAPI/#description_16","title":"Description","text":"This function is used to preload image files. It is used by the preload
plugin, and could be called directly to preload image files in custom plugins or experiment code. See Media Preloading for more information.
It is possible to run this function without specifying a callback function. However, in this case the code will continue executing while the images are loaded. Thus, it is possible that an image would be required for display before it is done preloading. The callback_complete
function will only execute after all the images are loaded, and can be used to control the flow of the experiment (e.g., by starting the experiment in the callback_complete
function).
The callback_load
and callback_error
functions are called after each file has either loaded or produced an error, so these functions can also be used to monitor loading progress. See example below.
"},{"location":"reference/jspsych-pluginAPI/#examples_5","title":"Examples","text":""},{"location":"reference/jspsych-pluginAPI/#basic-use_1","title":"Basic use","text":"var images = ['img/file1.png', 'img/file2.png', 'img/file3.png'];\n\njsPsych.pluginAPI.preloadImages(images, \n function(){ startExperiment(); },\n function(file){ console.log('file loaded: ', file); }\n function(file){ console.log('error loading file: ', file); }\n);\n\nfunction startExperiment(){\n jsPsych.run(exp);\n}\n
"},{"location":"reference/jspsych-pluginAPI/#show-progress-of-loading_1","title":"Show progress of loading","text":"var images = ['img/file1.png', 'img/file2.png', 'img/file3.png'];\nvar n_loaded = 0;\n\njsPsych.pluginAPI.preloadImages(images, function(){ startExperiment(); }, function(file) { updateLoadedCount(file); });\n\nfunction updateLoadedCount(file){\n n_loaded++;\n var percentcomplete = n_loaded / images.length * 100;\n\n // could put something fancier here, like a progress bar\n // or updating text in the DOM.\n console.log('Loaded '+percentcomplete+'% of images');\n}\n\nfunction startExperiment(){\n jsPsych.run(exp);\n}\n
"},{"location":"reference/jspsych-pluginAPI/#preloadvideo","title":"preloadVideo","text":"jsPsych.pluginAPI.preloadVideo(video, callback_complete, callback_load, callback_error)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_12","title":"Parameters","text":"Parameter Type Description video array An array of video paths to load. The array can be nested (e.g., if videos are in multiple arrays to help sort by condition or task). callback_complete function A function to execute when all the videos have been loaded. callback_load function A function to execute after a single file has been loaded. A single parameter is passed to this function which is the file source (string) that has loaded. callback_error function A function to execute after a single file has produced an error. A single parameter is passed to this function which is the file source (string) that produced the error."},{"location":"reference/jspsych-pluginAPI/#return-value_17","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-pluginAPI/#description_17","title":"Description","text":"This function is used to preload video files. It is used by the preload
plugin, and could be called directly to preload video files in custom plugins or experiment code. See Media Preloading for more information.
It is possible to run this function without specifying a callback function. However, in this case the code will continue executing while the videos are loaded. Thus, it is possible that a video would be requested before it is done preloading. The callback_complete
function will only execute after all the videos are loaded, and can be used to control the flow of the experiment (e.g., by starting the experiment in the callback_complete
function).
The callback_load
and callback_error
functions are called after each file has either loaded or produced an error, so these functions can also be used to monitor loading progress. See example below.
"},{"location":"reference/jspsych-pluginAPI/#examples_6","title":"Examples","text":""},{"location":"reference/jspsych-pluginAPI/#basic-use_2","title":"Basic use","text":"var videos = ['vid/file1.mp4', 'vid/file2.mp4', 'vid/file3.mp4'];\n\njsPsych.pluginAPI.preloadVideo(videos, \n function(){ startExperiment(); },\n function(file){ console.log('file loaded: ', file); }\n function(file){ console.log('error loading file: ', file); }\n);\n\nfunction startExperiment(){\n jsPsych.run(exp);\n}\n
"},{"location":"reference/jspsych-pluginAPI/#show-progress-of-loading_2","title":"Show progress of loading","text":"var videos = ['vid/file1.mp4', 'vid/file2.mp4', 'vid/file3.mp4'];\nvar n_loaded = 0;\n\njsPsych.pluginAPI.preloadVideo(videos, function(){ startExperiment(); }, function(file) { updateLoadedCount(file); });\n\nfunction updateLoadedCount(file){\n n_loaded++;\n var percentcomplete = n_loaded / videos.length * 100;\n\n // could put something fancier here, like a progress bar\n // or updating text in the DOM.\n console.log('Loaded '+percentcomplete+'% of videos');\n}\n\nfunction startExperiment(){\n jsPsych.run(exp);\n}\n
"},{"location":"reference/jspsych-pluginAPI/#simulation","title":"Simulation","text":""},{"location":"reference/jspsych-pluginAPI/#clicktarget","title":"clickTarget","text":"jsPsych.pluginAPI.clickTarget(target, delay)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_13","title":"Parameters","text":"Parameter Type Description target Element The DOM element to simulate clicking on. delay number Time to wait in milliseconds. The click will be executed after the delay."},{"location":"reference/jspsych-pluginAPI/#return-value_18","title":"Return value","text":"None
"},{"location":"reference/jspsych-pluginAPI/#description_18","title":"Description","text":"Simulates clicking on a DOM element by dispatching three MouseEvents on the target
: 'mousedown'
, then 'mouseup'
, then 'click'
. If delay
is positive, then the events are scheduled to execute after the delay via setTimeout
.
"},{"location":"reference/jspsych-pluginAPI/#example_11","title":"Example","text":"const target = document.querySelector('.jspsych-btn');\n\njsPsych.pluginAPI.clickTarget(target, 500);\n
"},{"location":"reference/jspsych-pluginAPI/#ensuresimulationdataconsistency","title":"ensureSimulationDataConsistency","text":"jsPsych.pluginAPI.ensureSimulationDataConsistency(trial, data)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_14","title":"Parameters","text":"Parameter Type Description trial object Parameters for the trial, e.g., those passed to the plugin's trial()
method. data object An object containing data for the trial."},{"location":"reference/jspsych-pluginAPI/#return-value_19","title":"Return value","text":"None. The data
object is modified in place by this method.
"},{"location":"reference/jspsych-pluginAPI/#description_19","title":"Description","text":"Performs some basic consistency checks on the data
based on the parameters specified in trial
. For example, if trial.choices
is \"NO_KEYS\"
but data.response
is a key string then data.response
and data.rt
are set to null
.
"},{"location":"reference/jspsych-pluginAPI/#example_12","title":"Example","text":"jsPsych.pluginAPI.ensureSimulationDataConsistency(trial, data);\n
"},{"location":"reference/jspsych-pluginAPI/#filltextinput","title":"fillTextInput","text":"jsPsych.pluginAPI.fillTextInput(target, text, delay)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_15","title":"Parameters","text":"Parameter Type Description target HTMLInputElement The input element to fill in with text. text string The text to input. delay number Time to wait in milliseconds. The text will be inserted after the delay."},{"location":"reference/jspsych-pluginAPI/#return-value_20","title":"Return value","text":"None
"},{"location":"reference/jspsych-pluginAPI/#description_20","title":"Description","text":"Sets the value of the target
HTMLInputElement to equal text
.
"},{"location":"reference/jspsych-pluginAPI/#example_13","title":"Example","text":"const target = document.querySelector('input[type=\"text\"]');\n\njsPsych.pluginAPI.fillTextInput(target, \"hello!\", 500);\n
"},{"location":"reference/jspsych-pluginAPI/#getvalidkey","title":"getValidKey","text":"jsPsych.pluginAPI.getValidKey(choices)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_16","title":"Parameters","text":"Parameter Type Description choices \"NO_KEYS\" or \"ALL_KEYS\" or array of strings Representation of the valid keys allowed for a keyboard response used by the getKeyboardResponse
method."},{"location":"reference/jspsych-pluginAPI/#return-value_21","title":"Return value","text":"A valid key given the choices
parameter, chosen at random from the possible keys.
"},{"location":"reference/jspsych-pluginAPI/#description_21","title":"Description","text":"Picks a random key given a set of options. Currently it only picks letters and numbers when choices
is \"ALL_KEYS\"
.
"},{"location":"reference/jspsych-pluginAPI/#example_14","title":"Example","text":"const random_key = jsPsych.pluginAPI.getValidKey(trial.choices);\n
"},{"location":"reference/jspsych-pluginAPI/#keydown","title":"keyDown","text":"jsPsych.pluginAPI.keyDown(key)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_17","title":"Parameters","text":"Parameter Type Description key string The .key
property of the corresponding key on the keyboard."},{"location":"reference/jspsych-pluginAPI/#return-value_22","title":"Return value","text":"None.
"},{"location":"reference/jspsych-pluginAPI/#description_22","title":"Description","text":"Dispatches a 'keydown'
event for the specified key
.
"},{"location":"reference/jspsych-pluginAPI/#example_15","title":"Example","text":"jsPsych.pluginAPI.keyDown('a');\n
"},{"location":"reference/jspsych-pluginAPI/#keyup","title":"keyUp","text":"jsPsych.pluginAPI.keyUp(key)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_18","title":"Parameters","text":"Parameter Type Description key string The .key
property of the corresponding key on the keyboard."},{"location":"reference/jspsych-pluginAPI/#return-value_23","title":"Return value","text":"None.
"},{"location":"reference/jspsych-pluginAPI/#description_23","title":"Description","text":"Dispatches a 'keyup'
event for the specified key
.
"},{"location":"reference/jspsych-pluginAPI/#example_16","title":"Example","text":"jsPsych.pluginAPI.keyUp('a');\n
"},{"location":"reference/jspsych-pluginAPI/#mergesimulationdata","title":"mergeSimulationData","text":"jsPsych.pluginAPI.mergeSimulationData(default_data, simulation_options)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_19","title":"Parameters","text":"Parameter Type Description default_data object An object containing data values for the simulated trial. simulation_options object The simulation_options
specified for the trial."},{"location":"reference/jspsych-pluginAPI/#return-value_24","title":"Return value","text":"An object of data.
"},{"location":"reference/jspsych-pluginAPI/#description_24","title":"Description","text":"This method merges the default_data
with any data specified in simulation_options.data
, giving priority to values specified in simulation_options.data
. It returns the merged data.
"},{"location":"reference/jspsych-pluginAPI/#example_17","title":"Example","text":"const default_data = {\n rt: 500,\n response: 'a'\n}\n\nconst simulation_options = {\n data: {\n rt: 200\n }\n}\n\nconst data = jsPsych.pluginAPI.mergeSimulationData(default_data, simulation_options);\n\ndata.rt === 200; // true\n
"},{"location":"reference/jspsych-pluginAPI/#timeouts","title":"Timeouts","text":""},{"location":"reference/jspsych-pluginAPI/#clearalltimeouts","title":"clearAllTimeouts","text":"jsPsych.pluginAPI.clearAllTimeouts()\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_20","title":"Parameters","text":"None.
"},{"location":"reference/jspsych-pluginAPI/#return-value_25","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-pluginAPI/#description_25","title":"Description","text":"Clears any pending timeouts that were set using jsPsych.pluginAPI.setTimeout().
"},{"location":"reference/jspsych-pluginAPI/#settimeout","title":"setTimeout","text":"jsPsych.pluginAPI.setTimeout(callback, delay)\n
"},{"location":"reference/jspsych-pluginAPI/#parameters_21","title":"Parameters","text":"Parameter Type Description callback function A function to execute after waiting for delay. delay integer Time to wait in milliseconds."},{"location":"reference/jspsych-pluginAPI/#return-value_26","title":"Return value","text":"Returns the ID of the setTimeout handle.
"},{"location":"reference/jspsych-pluginAPI/#description_26","title":"Description","text":"This is simply a call to the standard setTimeout function in JavaScript with the added benefit of registering the setTimeout call in a central list. This is useful for scenarios where some other event (the trial ending, aborting the experiment) should stop the execution of queued timeouts.
"},{"location":"reference/jspsych-pluginAPI/#example_18","title":"Example","text":"// print the time\nconsole.log(Date.now())\n\n// print the time 1s later\njsPsych.pluginAPI.setTimeout(function(){\n console.log(Date.now())\n}, 1000);\n
"},{"location":"reference/jspsych-randomization/","title":"jsPsych.randomization","text":"The jsPsych.randomization module contains methods that are useful for generating random lists of trial variables.
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationfactorial","title":"jsPsych.randomization.factorial","text":"jsPsych.randomization.factorial(factors, repetitions, unpack)\n
"},{"location":"reference/jspsych-randomization/#parameters","title":"Parameters","text":"Parameter Type Description factors object The factors
object should contain a property for each different factor. Each property-factor should have a value of an array, with each element of the array corresponding to a level of the factor. repetitions integer The number of times to repeat each unique combination of the factors in the output sample. unpack boolean If true
then the output will be an object with a property for each factor in the original factors
object. The value of each property-factor will be an array containing the levels of the factor in a random order. The order will be consistent across each property-factor (e.g., the first element of each property-factor will specify one unique combination of the factors). If false
, then the return value will be an array of objects where each property-factor contains only a single value."},{"location":"reference/jspsych-randomization/#return-value","title":"Return value","text":"The return value depends on the unpack
parameter. See description of the parameter above, and examples below.
"},{"location":"reference/jspsych-randomization/#description","title":"Description","text":"This method takes a list of factors and their levels, and creates a full factorial design by creating each unique combination of the factors. The returned set of combinations is in a random order.
"},{"location":"reference/jspsych-randomization/#examples","title":"Examples","text":""},{"location":"reference/jspsych-randomization/#create-full-factorial-design","title":"Create full factorial design","text":"var factors = {\n stimulus: ['a.jpg', 'b.jpg'],\n ms_delay: [100, 200]\n}\n\nvar full_design = jsPsych.randomization.factorial(factors, 1);\n\n/*\noutput:\nfull_design = [\n {stimulus: 'a.jpg', ms_delay: 200},\n {stimulus: 'b.jpg', ms_delay: 200},\n {stimulus: 'b.jpg', ms_delay: 100},\n {stimulus: 'a.jpg', ms_delay: 100},\n]\n*/\n
"},{"location":"reference/jspsych-randomization/#create-full-factorial-design-with-repeats","title":"Create full factorial design with repeats","text":"var factors = {\n stimulus: ['a.jpg', 'b.jpg'],\n ms_delay: [100, 200]\n}\n\nvar full_design = jsPsych.randomization.factorial(factors, 2);\n\n/*\noutput:\nfull_design = [\n {stimulus: 'b.jpg', ms_delay: 200},\n {stimulus: 'b.jpg', ms_delay: 100},\n {stimulus: 'b.jpg', ms_delay: 100},\n {stimulus: 'a.jpg', ms_delay: 100},\n {stimulus: 'a.jpg', ms_delay: 200},\n {stimulus: 'b.jpg', ms_delay: 200},\n {stimulus: 'a.jpg', ms_delay: 100},\n {stimulus: 'a.jpg', ms_delay: 200},\n]\n*/\n
"},{"location":"reference/jspsych-randomization/#create-full-factorial-design-unpacked","title":"Create full factorial design, unpacked","text":"var factors = {\n stimulus: ['a.jpg', 'b.jpg'],\n ms_delay: [100, 200]\n}\n\nvar full_design = jsPsych.randomization.factorial(factors, 1, true);\n\n/*\noutput:\nfull_design = {\n stimulus: ['a.jpg','b.jpg','b.jpg','a.jpg'],\n ms_delay: [200, 100, 200, 100]\n]\n*/\n
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationrandomid","title":"jsPsych.randomization.randomID","text":"jsPsych.randomization.randomID(length)\n
"},{"location":"reference/jspsych-randomization/#parameters_1","title":"Parameters","text":"Parameter Type Description length integer The length of the randomly generated ID"},{"location":"reference/jspsych-randomization/#return-value_1","title":"Return value","text":"Returns a string of length length
where each character is randomly selected from the numbers 0-9 and all lowercase English letters a-z.
"},{"location":"reference/jspsych-randomization/#description_1","title":"Description","text":"Generates a random string that is likely to be unique. If length is undefined, then the string length is 32.
"},{"location":"reference/jspsych-randomization/#example","title":"Example","text":"console.log(jsPsych.randomization.randomID());\n// outputs: \"t7dwz0e713pc8juuaayyfvpkdd9un239\"\n\nconsole.log(jsPsych.randomization.randomID(8));\n// outputs: \"3xtpcbck\"\n
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationrandomint","title":"jsPsych.randomization.randomInt","text":"jsPsych.randomization.randomInt(lower, upper)\n
"},{"location":"reference/jspsych-randomization/#parameters_2","title":"Parameters","text":"Parameter Type Description lower integer The smallest value it is possible to generate upper integer The largest value it is possible to generate"},{"location":"reference/jspsych-randomization/#return-value_2","title":"Return value","text":"An integer
"},{"location":"reference/jspsych-randomization/#description_2","title":"Description","text":"Generates a random integer from lower
to upper
"},{"location":"reference/jspsych-randomization/#example_1","title":"Example","text":"console.log(jsPsych.randomization.randomInt(2,4));\n// outputs: 2 or 3 or 4.\n
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationrepeat","title":"jsPsych.randomization.repeat","text":"jsPsych.randomization.repeat(array, repetitions, unpack)\n
"},{"location":"reference/jspsych-randomization/#parameters_3","title":"Parameters","text":"Parameter Type Description array array The array of values to randomize & repeat. repetitions integer or array The number of times to repeat each element of the array
in the final sample. If this parameter is defined as an integer, then each element of array
is repeated the same number of times. This parameter can also be an array of the same length as array
, in which case each element of array
will be repeated the number of times defined in the corresponding position of the repetitions
array. unpack boolean If each element of array
is an object with an equivalent set of properties, then setting unpack
to true
will make the return value an object with a property for each of the unique properties among the elements of the array
. Each property in the output object will be an array containing the values for that property in the randomized order. The order will be consistent across properties. If this is false
then the output is just an array containing a randomized order of the original array
elements."},{"location":"reference/jspsych-randomization/#return-value_3","title":"Return value","text":"The return value depends on the unpack
parameter. See description of the parameter above, and examples below.
"},{"location":"reference/jspsych-randomization/#description_3","title":"Description","text":"This method takes an array of values and generates a new random order of the array, with the option of repeating each element of the array a specified number of times.
If the array elements are objects with the same set of properties, then this method can optionally return a single object where each property is a randomized order of the properties defined in the original set of objects. This is useful for randomizing sets of parameters that are used to define a jsPsych block.
"},{"location":"reference/jspsych-randomization/#examples_1","title":"Examples","text":""},{"location":"reference/jspsych-randomization/#shuffle-an-array-no-repeats","title":"Shuffle an array, no repeats","text":"var myArray = [1,2,3,4,5];\nvar shuffledArray = jsPsych.randomization.repeat(myArray, 1);\n// output: shuffledArray = [3,2,4,1,5]\n
"},{"location":"reference/jspsych-randomization/#shuffle-an-array-with-repeats","title":"Shuffle an array with repeats","text":"var myArray = [1,2,3,4,5];\nvar shuffledArray = jsPsych.randomization.repeat(myArray, 2);\n// output: shuffledArray = [1,3,4,2,2,4,5,1,5,3]\n
"},{"location":"reference/jspsych-randomization/#shuffle-an-array-of-objects","title":"Shuffle an array of objects","text":"var trial1 = {\n stimulus: 'img/faceA.jpg',\n correct_key: 'p',\n person_name: 'Joe'\n}\n\nvar trial2 = {\n stimulus: 'img/faceB.jpg',\n correct_key: 'p',\n person_name: 'Fred'\n}\n\nvar trial3 = {\n stimulus: 'img/faceC.jpg',\n correct_key: 'q',\n person_name: 'Mary'\n}\n\nvar myArray = [ trial1, trial2, trial3 ];\nvar shuffledArray = jsPsych.randomization.repeat(myArray, 2);\n\n// output: shuffledArray = [ trial1, trial3, trial3, trial2, trial1, trial2 ]\n
"},{"location":"reference/jspsych-randomization/#shuffle-an-array-of-objects-with-unpack","title":"Shuffle an array of objects, with unpack","text":"var trial1 = {\n stimulus: 'img/faceA.jpg',\n correct_key: 'p',\n person_name: 'Joe'\n}\n\nvar trial2 = {\n stimulus: 'img/faceB.jpg',\n correct_key: 'p',\n person_name: 'Fred'\n}\n\nvar trial3 = {\n stimulus: 'img/faceC.jpg',\n correct_key: 'q',\n person_name: 'Mary'\n}\n\nvar myArray = [ trial1, trial2, trial3 ];\nvar shuffledArray = jsPsych.randomization.repeat(myArray, 2, true);\n\n/*\noutput: shuffledArray = {\n stimulus: ['img/faceB.jpg','img/faceA.jpg','img/faceC.jpg','img/faceA.jpg','img/faceC.jpg','img/faceB.jpg'],\n correct_key: ['p', 'p', 'q', 'p', 'q', 'p'],\n person_name: ['Fred', 'Joe', 'Mary', 'Joe', 'Mary', 'Fred']\n}\n*/\n
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationsamplebernoulli","title":"jsPsych.randomization.sampleBernoulli","text":"jsPsych.randomization.sampleBernoulli(p)\n
"},{"location":"reference/jspsych-randomization/#parameters_4","title":"Parameters","text":"Parameter Type Description p number Probability of sampling 1"},{"location":"reference/jspsych-randomization/#return-value_4","title":"Return value","text":"Returns 0 with probability 1-p
and 1 with probability p
.
"},{"location":"reference/jspsych-randomization/#description_4","title":"Description","text":"Generates a random sample from a Bernoulli distribution.
"},{"location":"reference/jspsych-randomization/#examples_2","title":"Examples","text":""},{"location":"reference/jspsych-randomization/#sample-a-value","title":"Sample a value","text":"if(jsPsych.randomization.sampleBernoulli(0.8)){\n // this happens 80% of the time\n} else {\n // this happens 20% of the time\n}\n
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationsampleexgaussian","title":"jsPsych.randomization.sampleExGaussian","text":"jsPsych.randomization.sampleExGaussian(mean, standard_deviation, rate, positive=false)\n
"},{"location":"reference/jspsych-randomization/#parameters_5","title":"Parameters","text":"Parameter Type Description mean number Mean of the normal distribution component of the exGaussian standard_deviation number Standard deviation of the normal distribution component of the exGaussian rate number Rate of the exponential distribution component of the exGaussian positive bool If true
sample will be constrained to > 0."},{"location":"reference/jspsych-randomization/#return-value_5","title":"Return value","text":"A random sample from the distribution
"},{"location":"reference/jspsych-randomization/#description_5","title":"Description","text":"Generates a random sample from an exponentially modified Gaussian distribution.
"},{"location":"reference/jspsych-randomization/#examples_3","title":"Examples","text":""},{"location":"reference/jspsych-randomization/#sample-a-value_1","title":"Sample a value","text":"var rand_sample_exg = jsPsych.randomization.sampleExGaussian(500, 100, 0.01);\n
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationsampleexponential","title":"jsPsych.randomization.sampleExponential","text":"jsPsych.randomization.sampleExponential(rate)\n
"},{"location":"reference/jspsych-randomization/#parameters_6","title":"Parameters","text":"Parameter Type Description rate number Rate of the exponential distribution"},{"location":"reference/jspsych-randomization/#return-value_6","title":"Return value","text":"A random sample from the distribution
"},{"location":"reference/jspsych-randomization/#description_6","title":"Description","text":"Generates a random sample from an exponential distribution.
"},{"location":"reference/jspsych-randomization/#examples_4","title":"Examples","text":""},{"location":"reference/jspsych-randomization/#sample-a-value_2","title":"Sample a value","text":"var rand_sample_exg = jsPsych.randomization.sampleExponential(0.01);\n
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationsamplenormal","title":"jsPsych.randomization.sampleNormal","text":"jsPsych.randomization.sampleNormal(mean, standard_deviation)\n
"},{"location":"reference/jspsych-randomization/#parameters_7","title":"Parameters","text":"Parameter Type Description mean number Mean of the normal distribution standard_deviation number Standard deviation of the normal distribution"},{"location":"reference/jspsych-randomization/#return-value_7","title":"Return value","text":"A random sample from the distribution
"},{"location":"reference/jspsych-randomization/#description_7","title":"Description","text":"Generates a random sample from a normal distribution.
"},{"location":"reference/jspsych-randomization/#examples_5","title":"Examples","text":""},{"location":"reference/jspsych-randomization/#sample-a-value_3","title":"Sample a value","text":"var rand_sample_exg = jsPsych.randomization.sampleNormal(500, 250);\n
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationsamplewithreplacement","title":"jsPsych.randomization.sampleWithReplacement","text":"jsPsych.randomization.sampleWithReplacement(array, sampleSize, weights)\n
"},{"location":"reference/jspsych-randomization/#parameters_8","title":"Parameters","text":"Parameter Type Description array array The array of values to sample from sampleSize numeric The number of samples to draw weights array The relative weight of each element in array
. This array is normalized, so the values do not need to sum to 1. The length must match the length of array
."},{"location":"reference/jspsych-randomization/#return-value_8","title":"Return value","text":"An array containing the sample.
"},{"location":"reference/jspsych-randomization/#description_8","title":"Description","text":"This method returns a sample drawn at random from a set of values with replacement. The relative probability of drawing each item can be controlled by specifying the weights
.
"},{"location":"reference/jspsych-randomization/#examples_6","title":"Examples","text":""},{"location":"reference/jspsych-randomization/#sample-with-equal-probability","title":"Sample with equal probability","text":"var myArray = [1,2,3,4,5];\nvar sample = jsPsych.randomization.sampleWithReplacement(myArray, 10);\n// output: sample = [3, 1, 2, 2, 5, 1, 4, 3, 1, 5];\n
"},{"location":"reference/jspsych-randomization/#sample-with-unequal-probability","title":"Sample with unequal probability","text":"var myArray = [1,2,3,4,5];\nvar sample = jsPsych.randomization.sampleWithReplacement(myArray, 10, [6,1,1,1,1]);\n// output: sample = [3, 4, 5, 1, 2, 1, 3, 1, 1, 1];\n
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationsamplewithoutreplacement","title":"jsPsych.randomization.sampleWithoutReplacement","text":"jsPsych.randomization.sampleWithoutReplacement(array, sampleSize)\n
"},{"location":"reference/jspsych-randomization/#parameters_9","title":"Parameters","text":"Parameter Type Description array array The array of values to sample from sampleSize numeric The number of samples to draw"},{"location":"reference/jspsych-randomization/#return-value_9","title":"Return value","text":"An array containing the sample.
"},{"location":"reference/jspsych-randomization/#description_9","title":"Description","text":"This method returns a sample drawn at random from a set of values without replacement. The sample size must be less than or equal to the length of the array.
"},{"location":"reference/jspsych-randomization/#examples_7","title":"Examples","text":""},{"location":"reference/jspsych-randomization/#sample-without-replacement","title":"Sample without replacement","text":"var myArray = [1,2,3,4,5];\nvar sample = jsPsych.randomization.sampleWithoutReplacement(myArray, 2);\n// output: sample = [3,2];\n
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationsetseed","title":"jsPsych.randomization.setSeed","text":"jsPsych.randomization.setSeed(seed)\n
"},{"location":"reference/jspsych-randomization/#parameters_10","title":"Parameters","text":"Parameter Type Description seed string A seed for the random number generator"},{"location":"reference/jspsych-randomization/#return-value_10","title":"Return value","text":"Returns the seed value.
"},{"location":"reference/jspsych-randomization/#description_10","title":"Description","text":"This function will override the behavior of Math.random()
to produce a seedable pseudo random number generator. It uses the seedrandom package. Note that calling setSeed()
will change how Math.random()
behaves for the entire document. If you have non-jsPsych components on the page that use Math.random()
they will be affected.
Using setSeed()
without passing in a seed will generate a random 32-bit seed. The seed value will be returned from the function call, allowing you to save it in the data for the experiment if needed.
"},{"location":"reference/jspsych-randomization/#examples_8","title":"Examples","text":""},{"location":"reference/jspsych-randomization/#use-a-random-32-bit-seed-and-save-to-data","title":"Use a random 32-bit seed and save to data","text":"const seed = jsPsych.randomization.setSeed();\njsPsych.data.addProperties({\n rng_seed: seed\n});\n
"},{"location":"reference/jspsych-randomization/#use-your-own-seed","title":"Use your own seed","text":"jsPsych.randomization.setSeed(\"jspsych\");\n
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationshuffle","title":"jsPsych.randomization.shuffle","text":"jsPsych.randomization.shuffle(array)\n
"},{"location":"reference/jspsych-randomization/#parameters_11","title":"Parameters","text":"Parameter Type Description array array The array of values to shuffle"},{"location":"reference/jspsych-randomization/#return-value_11","title":"Return value","text":"Returns an array with the same elements as the input array in a random order.
"},{"location":"reference/jspsych-randomization/#description_11","title":"Description","text":"A simple method for shuffling the order of an array.
"},{"location":"reference/jspsych-randomization/#examples_9","title":"Examples","text":""},{"location":"reference/jspsych-randomization/#shuffle-an-array","title":"Shuffle an array","text":"var myArray = [1,2,3,4,5];\nvar shuffledArray = jsPsych.randomization.shuffle(myArray);\n// output: shuffledArray = [3,2,4,1,5]\n
"},{"location":"reference/jspsych-randomization/#jspsychrandomizationshufflenorepeats","title":"jsPsych.randomization.shuffleNoRepeats","text":"jsPsych.randomization.shuffleNoRepeats(array, equalityTest)\n
"},{"location":"reference/jspsych-randomization/#parameters_12","title":"Parameters","text":"Parameter Type Description array array The array of values to shuffle equalityTest function A function to use to evaluate the equality of neighbors in the array. The function should accept two parameters, which are the two elements to be tested. It should return true
if they are equal and false
if not. The default function, if none is specified, is to use the ===
operator. This will work for primitive values, but fail for Objects and Arrays. An example function is given below in the examples."},{"location":"reference/jspsych-randomization/#return-value_12","title":"Return value","text":"Returns an array with the same elements as the input array in a random order, with no repeating neighbors.
"},{"location":"reference/jspsych-randomization/#description_12","title":"Description","text":"Shuffle an array, ensuring that neighboring elements in the array are different.
Warning: if you provide an array that has very few valid permutations with no neighboring elements, then this method will fail and cause the browser to hang.
"},{"location":"reference/jspsych-randomization/#examples_10","title":"Examples","text":""},{"location":"reference/jspsych-randomization/#basic-example","title":"Basic example","text":"var myArray = [1,2,3,4,5,1,2,3,4,5,1,2,3,4,5];\nvar shuffledArray = jsPsych.randomization.shuffleNoRepeats(myArray);\n// output: shuffledArray = [2, 3, 5, 1, 2, 4, 1, 5, 4, 1, 3, 5, 4, 3, 2]\n
"},{"location":"reference/jspsych-randomization/#custom-equalitytest","title":"Custom equalityTest","text":"var myObjects = [\n {color:\"blue\"},\n {color:\"red\"},\n {color:\"yellow\"},\n {color:\"orange\"}\n];\n\nvar repeatedSet = jsPsych.randomization.repeat(myObjects,3);\nvar shuffled = jsPsych.randomization.shuffleNoRepeats(repeatedSet, function(a,b) { return a.color === b.color });\n\n// console.log(JSON.stringify(shuffled))\n// \"[{\"color\":\"red\"},{\"color\":\"yellow\"},{\"color\":\"blue\"},{\"color\":\"yellow\"},{\"color\":\"orange\"},{\"color\":\"red\"},{\"color\":\"yellow\"},{\"color\":\"orange\"},{\"color\":\"blue\"},{\"color\":\"orange\"},{\"color\":\"red\"},{\"color\":\"blue\"}]\"\n
"},{"location":"reference/jspsych-turk/","title":"jsPsych.turk","text":"The jsPsych.turk module contains functions for interacting with Mechanical Turk.
"},{"location":"reference/jspsych-turk/#jspsychturksubmittoturk","title":"jsPsych.turk.submitToTurk","text":"jsPsych.turk.submitToTurk(data)\n
"},{"location":"reference/jspsych-turk/#parameters","title":"Parameters","text":"Parameter Type Description data object The data
parameter is an object of key: value
pairs. Any pairs in the data
parameter will be saved by Mechanical Turk, and can be downloaded in a CSV file through the Mechanical Turk interface. Important: the data
parameter must contain at least one key: value
pair, even just a dummy value, or the HIT will not be submitted correctly."},{"location":"reference/jspsych-turk/#return-value","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych-turk/#description","title":"Description","text":"This method will submit a HIT to Mechanical Turk, causing the HIT to finish.
This method will only work when called from within the mechanical turk website. If you are using an external HIT to send workers to your own server, this method will not work on an externally hosted page. It will work if your external content is loaded in the iframe on the Mechanical Turk website.
"},{"location":"reference/jspsych-turk/#example","title":"Example","text":"<p>Enter the code you were given:</p>\n<input type=\"text\" id=\"code\"></input>\n<button onclick=\"sendData();\">Submit HIT</button>\n\n<script>\n// this content must be loaded in the iframe on the mechanical turk website.\n// usually, this means that the content is part of your 'recruitment ad', the\n// page the workers can see when they are deciding whether or not to accept a HIT.\n// one option is to include a simple form on this page that workers submit, with a\n// special code that they get at the end of the experiment.\n\nfunction sendData() {\n jsPsych.turk.submitToTurk({\n code: document.getElementById('code').value\n });\n}\n</script>\n
"},{"location":"reference/jspsych-turk/#jspsychturkturkinfo","title":"jsPsych.turk.turkInfo","text":"jsPsych.turk.turkInfo()\n
"},{"location":"reference/jspsych-turk/#parameters_1","title":"Parameters","text":"None.
"},{"location":"reference/jspsych-turk/#return-value_1","title":"Return value","text":"Returns an object with six properties:
.assignmentId
contains the assignment ID string of the HIT. .hitId
contains the HIT ID. .workerId
contains the worker ID of the worker completing the HIT. .turkSubmitTo
contains the URL for submitting the HIT. This parameter is used in the jsPsych.turk.submitToTurk
method, and is probably not useful outside of that context. .previewMode
is a boolean value indicating whether or not the worker has accepted the HIT yet. If the page is viewed inside Mechancial Turk and the worker has not clicked 'Accept HIT' then this will be true. If the page is viewed outside Mechanical Turk or the worker has acccepted the HIT, then it will be false. .outsideTurk
is a boolean value indicating if the page is being viewed within Mechanical Turk, or if it is being viewed from another source (e.g., someone directly going to the page URL instead of going through mturk).
"},{"location":"reference/jspsych-turk/#description_1","title":"Description","text":"This method returns basic information about the current Mechanical Turk session, including the worker ID, assignment ID, and HIT ID.
"},{"location":"reference/jspsych-turk/#example_1","title":"Example","text":"var turkInfo = jsPsych.turk.turkInfo();\n\nalert('Worker ID is: ' + turkInfo.workerId);\n\nalert('Assignment ID is: ' + turkInfo.assignmentId);\n\nalert('HIT ID is: ' + turkInfo.hitId);\n\n// true if the page is viewed within Mechanical Turk, \n// but worker has not accepted the HIT yet.\n// false if the page is viewed outside Mechanical Turk,\n// OR the worker has accepted the HIT.\nalert('Preview mode? ' + turkInfo.previewMode); \n\n// true if the page is viewed outside mechanical turk,\n// false otherwise.\nalert('Outside turk? ' + turkInfo.outsideTurk);\n
"},{"location":"reference/jspsych/","title":"jsPsych","text":""},{"location":"reference/jspsych/#initjspsych","title":"initJsPsych","text":"var jsPsych = initJsPsych(settings);\n
"},{"location":"reference/jspsych/#parameters","title":"Parameters","text":"Parameter Type Description settings object The settings object for initializing jsPsych. See table below. The settings object can contain several parameters. None of the parameters are required.
Parameter Type Description display_element string The ID of an HTML element to display the experiment in. If left blank, jsPsych will use the <body>
element to display content. All keyboard event listeners are bound to this element. In order for a keyboard event to be detected, this element must have focus (be the last thing that the participant clicked on). on_finish function Function to execute when the experiment ends. on_trial_start function Function to execute when a new trial begins. on_trial_finish function Function to execute when a trial ends. on_data_update function Function to execute every time data is stored using the jsPsych.data.write
method. All plugins use this method to save data (via a call to jsPsych.finishTrial
, so this function runs every time a plugin stores new data. on_interaction_data_update function Function to execute every time a new interaction event occurs. Interaction events include clicking on a different window (blur), returning to the experiment window (focus), entering full screen mode (fullscreenenter), and exiting full screen mode (fullscreenexit). on_close function Function to execute when the user leaves the page. Can be used, for example, to save data before the page is closed. show_progress_bar boolean If true
, then a progress bar is shown at the top of the page. Default is false
. message_progress_bar string or function Message to display next to the progress bar or a function that returns that message. The default is 'Completion Progress'. If message_progress_bar
is a function, it receives one single argument which is the current progress, ranging from 0 to 1; the function gets called on every progress bar update automatically. auto_update_progress_bar boolean If true, then the progress bar at the top of the page will automatically update as every top-level timeline or trial is completed. use_webaudio boolean If false, then jsPsych will not attempt to use the WebAudio API for audio playback. Instead, HTML5 Audio objects will be used. The WebAudio API offers more precise control over the timing of audio events, and should be used when possible. The default value is true
. default_iti numeric The default inter-trial interval in ms. The default value if none is specified is 0ms. experiment_width numeric The desired width of the jsPsych container in pixels. If left undefined, the width will be 100% of the display element. Usually this is the <body>
element, and the width will be 100% of the screen size. minimum_valid_rt numeric The minimum valid response time for key presses during the experiment. Any key press response time that is less than this value will be treated as invalid and ignored. Note that this parameter only applies to keyboard responses, and not to other response types such as buttons and sliders. The default value is 0. override_safe_mode boolean Running a jsPsych experiment directly in a web browser (e.g., by double clicking on a local HTML file) will load the page using the file://
protocol. Some features of jsPsych don't work with this protocol. By default, when jsPsych detects that it's running on a page loaded via the file://
protocol, it runs in safe mode, which automatically disables features that don't work in this context. Specifically, the use of Web Audio is disabled (audio will be played using HTML5 audio instead, even if use_webaudio
is true
) and video preloading is disabled. The override_safe_mode
parameter defaults to false
, but you can set it to true
to force these features to operate under the file://
protocol. In order for this to work, you will need to disable web security (CORS) features in your browser - this is safe to do if you know what you are doing. Note that this parameter has no effect when you are running the experiment on a web server, because the page will be loaded via the http://
or https://
protocol. case_sensitive_responses boolean If true
, then jsPsych will make a distinction between uppercase and lowercase keys when evaluating keyboard responses, e.g. \"A\" (uppercase) will not be recognized as a valid response if the trial only accepts \"a\" (lowercase). If false, then jsPsych will not make a distinction between uppercase and lowercase keyboard responses, e.g. both \"a\" and \"A\" responses will be valid when the trial's key choice parameter is \"a\". Setting this parameter to false is useful if you want key responses to be treated the same way when CapsLock is turned on or the Shift key is held down. The default value is false
. extensions array Array containing information about one or more jsPsych extensions that are used during the experiment. Each extension should be specified as an object with type
(required), which is the name of the extension, and params
(optional), which is an object containing any parameter-value pairs to be passed to the extension's initialize
function. Default value is an empty array."},{"location":"reference/jspsych/#return-value","title":"Return value","text":"Returns a jsPsych instance, which all jsPsych methods on this page are called on. Therefore it is not possible to call any of the jsPsych methods listed on this page until this initJsPsych
function is called and a jsPsych instance is created.
"},{"location":"reference/jspsych/#description","title":"Description","text":"This function initializes jsPsych with the specified experiment settings.
"},{"location":"reference/jspsych/#example","title":"Example","text":"var jsPsych = initJsPsych({\n on_finish: function() {\n jsPsych.data.displayData();\n }, \n show_progress_bar: true,\n default_iti: 500\n});\n
For more examples, see the HTML files in the examples folder.
"},{"location":"reference/jspsych/#jspsychabortcurrenttimeline","title":"jsPsych.abortCurrentTimeline","text":"jsPsych.abortCurrentTimeline()\n
"},{"location":"reference/jspsych/#parameters_1","title":"Parameters","text":"None.
"},{"location":"reference/jspsych/#return-value_1","title":"Return value","text":"None.
"},{"location":"reference/jspsych/#description_1","title":"Description","text":"Ends the current timeline. If timelines are nested, then only the timeline that contains the current trial is ended.
"},{"location":"reference/jspsych/#example_1","title":"Example","text":""},{"location":"reference/jspsych/#abort-timeline-if-a-particular-key-is-pressed","title":"Abort timeline if a particular key is pressed","text":"var jsPsych = initJsPsych({\n on_finish: function() {\n jsPsych.data.displayData();\n }\n});\n\nvar images = [\n \"img/1.gif\", \"img/2.gif\", \"img/3.gif\", \"img/4.gif\",\n \"img/5.gif\", \"img/6.gif\", \"img/7.gif\", \"img/8.gif\",\n \"img/9.gif\", \"img/10.gif\"\n];\n\nvar trials = [];\nfor (var i = 0; i < images.length; i++) {\n trials.push({\n stimulus: images[i]\n });\n}\n\nvar block = {\n type: jsPsychImageKeyboardResponse,\n choices: ['y', 'n'], \n prompt: '<p>Press \"y\" to Continue. Press \"n\" to end this node of the experiment.</p>',\n on_finish: function(data) {\n if (jsPsych.pluginAPI.compareKeys(data.response, 'n')) {\n jsPsych.abortCurrentTimeline();\n }\n },\n timeline: trials\n}\n\nvar after_block = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<p>The next node</p>'\n}\n\njsPsych.run([block, after_block]);\n
"},{"location":"reference/jspsych/#jspsychabortexperiment","title":"jsPsych.abortExperiment","text":"jsPsych.abortExperiment(message, data)\n
"},{"location":"reference/jspsych/#parameters_2","title":"Parameters","text":"Parameter Type Description message string A message to display on the screen after the experiment is over. Can include HTML formatting. data object An optional object of key-value pairs to store as data in the final trial of the experiment."},{"location":"reference/jspsych/#return-value_2","title":"Return value","text":"None.
"},{"location":"reference/jspsych/#description_2","title":"Description","text":"Ends the experiment, skipping all remaining trials. If the on_finish
event handler for jsPsych
returns a Promise
then the message
will not be displayed until the promise is resolved.
"},{"location":"reference/jspsych/#example_2","title":"Example","text":""},{"location":"reference/jspsych/#end-the-experiment-if-a-particular-response-is-given","title":"End the experiment if a particular response is given","text":"var trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'image1.jpg',\n choices: ['y', 'n'],\n prompt: '<p>Press \"y\" to Continue. Press \"n\" to end the experiment</p>',\n on_finish: function(data){\n if(jsPsych.pluginAPI.compareKeys(data.response, \"n\")){\n jsPsych.abortExperiment('The experiment was ended by pressing \"n\".');\n }\n }\n}\n
"},{"location":"reference/jspsych/#jspsychaborttimelinebyname","title":"jsPsych.abortTimelineByName","text":"jsPsych.abortTimelineByName()\n
"},{"location":"reference/jspsych/#parameters_3","title":"Parameters","text":"Parameter Type Description name string The name of the timeline to abort."},{"location":"reference/jspsych/#return-value_3","title":"Return value","text":"None.
"},{"location":"reference/jspsych/#description_3","title":"Description","text":"Ends the currently active timeline that matches the name
parameter. This can be used to control which level is aborted in a nested timeline structure.
"},{"location":"reference/jspsych/#example_3","title":"Example","text":""},{"location":"reference/jspsych/#abort-a-procedure-if-an-incorrect-response-is-given","title":"Abort a procedure if an incorrect response is given.","text":"const fixation = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<p>+</p>',\n choices: \"NO_KEYS\",\n trial_duration: 1000\n}\n\nconst test = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n choices: ['y', 'n'],\n on_finish: function(data){\n if(jsPsych.pluginAPI.compareKeys(data.response, \"n\")){\n jsPsych.abortTimelineByName('memory_test');\n }\n }\n}\n\nconst memoryResponseProcedure = {\n timeline: [fixation, test]\n}\n\n// the variable `encode` is not shown, but imagine a trial that displays\n// some stimulus to remember.\nconst memoryEncodeProcedure = {\n timeline: [fixation, encode]\n}\n\nconst memoryTestProcedure = {\n timeline: [memoryEncodeProcedure, memoryResponseProcedure]\n name: 'memory_test',\n timeline_variables: [\n {stimulus: 'image1.png'},\n {stimulus: 'image2.png'},\n {stimulus: 'image3.png'},\n {stimulus: 'image4.png'}\n ]\n}\n
"},{"location":"reference/jspsych/#jspsychaddnodetoendoftimeline","title":"jsPsych.addNodeToEndOfTimeline","text":"jsPsych.addNodeToEndOfTimeline(node_parameters)\n
"},{"location":"reference/jspsych/#parameters_4","title":"Parameters","text":"Parameter Type Description node_parameters object An object defining a timeline. It must have, at a minimum, a timeline
parameter with a valid timeline array as the value for that parameter."},{"location":"reference/jspsych/#return-value_4","title":"Return value","text":"None.
"},{"location":"reference/jspsych/#description_4","title":"Description","text":"Adds the timeline to the end of the experiment.
"},{"location":"reference/jspsych/#example_4","title":"Example","text":"var trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'This is a new trial.'\n}\n\nvar new_timeline = {\n timeline: [trial]\n}\n\njsPsych.addNodeToEndOfTimeline(new_timeline)\n
"},{"location":"reference/jspsych/#jspsychevaluatetimelinevariable","title":"jsPsych.evaluateTimelineVariable","text":"jsPsych.evaluateTimelineVariable(variable_name)\n
"},{"location":"reference/jspsych/#parameters_5","title":"Parameters","text":"Parameter Type Description variable_name string The name of the variable to evaluate."},{"location":"reference/jspsych/#return-value_5","title":"Return value","text":"Returns the current value of the corresponding timeline variable.
"},{"location":"reference/jspsych/#description_5","title":"Description","text":"Unlike jsPsych.timelineVariable()
, evaluateTimelineVariable()
immediately returns the current value of the timeline variable. It should be used whenever you are in a context where immediate evaluation is appropriate. For example, if you referencing a timeline variable within a function, immediate evaluation is usually correct.
"},{"location":"reference/jspsych/#examples","title":"Examples","text":""},{"location":"reference/jspsych/#invoking-timeline-variables-immediately-in-a-function","title":"Invoking timeline variables immediately in a function","text":"const trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: function(){\n return `<img style='width:100px; height:100px;' src='${jsPsych.evaluateTimelineVariable('image')}'></img>`;\n }\n}\n\nconst procedure = {\n timeline: [trial],\n timeline_variables: [\n {image: 'face1.png'},\n {image: 'face2.png'},\n {image: 'face3.png'},\n {image: 'face4.png'}\n ]\n}\n
"},{"location":"reference/jspsych/#jspsychfinishtrial","title":"jsPsych.finishTrial","text":"jsPsych.finishTrial(data)\n
"},{"location":"reference/jspsych/#parameters_6","title":"Parameters","text":"Parameter Type Description data object The data to store for the trial."},{"location":"reference/jspsych/#return-value_6","title":"Return value","text":"Returns nothing.
"},{"location":"reference/jspsych/#description_6","title":"Description","text":"This method tells jsPsych that the current trial is over. It is used in all of the plugins to end the current trial. When the trial ends a few things happen:
- The data is stored using
jsPsych.data.write()
- The on_finish callback function is executed for the trial
- The on_trial_finish callback function is executed
- The progress bar is updated if it is being displayed
- The experiment ends if the trial is the last one (and the on_finish callback function is executed).
- The next trial, if one exists, is started.
"},{"location":"reference/jspsych/#example_5","title":"Example","text":"// this code would be in a plugin\njsPsych.finishTrial({correct_response: true});\n
"},{"location":"reference/jspsych/#jspsychgetcitations","title":"jsPsych.getCitations","text":"jsPsych.getCitations(plugins, format)\n
"},{"location":"reference/jspsych/#parameters_7","title":"Parameters","text":"Parameter Type Description plugins array Array containing list of plugins/extensions by name. format string Output citation format (\"apa\""},{"location":"reference/jspsych/#return-value_7","title":"Return value","text":"String of generated citations in the specified format for the jsPsych library, followed by that for each input plugin/extension, separated with a \"\\n\" character.
"},{"location":"reference/jspsych/#description_7","title":"Description","text":"Get citations in a specified format for the jsPsych library and input list of plugins/extensions, usually those used within an experiment.
"},{"location":"reference/jspsych/#example_6","title":"Example","text":"// in browser console\njsPsych.getCitations() // prints citation for jsPsych library in APA format\njsPsych.getCitations([TestPlugin], \"bibtex\") // prints citation for jsPsych library and TestPlugin (if different) in BibTex format\n
"},{"location":"reference/jspsych/#jspsychgetcurrenttrial","title":"jsPsych.getCurrentTrial","text":"jsPsych.getCurrentTrial()\n
"},{"location":"reference/jspsych/#parameters_8","title":"Parameters","text":"None.
"},{"location":"reference/jspsych/#return-value_8","title":"Return value","text":"Returns the object describing the current trial. The object will contain all of the parameters associated with the current trial.
"},{"location":"reference/jspsych/#description_8","title":"Description","text":"Get a description of the current trial
"},{"location":"reference/jspsych/#example_7","title":"Example","text":"var trial = jsPsych.getCurrentTrial();\nconsole.log('The current trial is using the '+trial.type+' plugin');\n
"},{"location":"reference/jspsych/#jspsychgetdisplayelement","title":"jsPsych.getDisplayElement","text":"jsPsych.getDisplayElement()\n
"},{"location":"reference/jspsych/#parameters_9","title":"Parameters","text":"None.
"},{"location":"reference/jspsych/#return-value_9","title":"Return value","text":"Returns the HTML DOM element used for displaying the experiment.
"},{"location":"reference/jspsych/#description_9","title":"Description","text":"Get the DOM element that displays the experiment.
"},{"location":"reference/jspsych/#example_8","title":"Example","text":""},{"location":"reference/jspsych/#var-el-jspsychgetdisplayelement-hide-the-jspsych-display-elstylevisibility-hidden","title":"var el = jsPsych.getDisplayElement();\n\n// hide the jsPsych display\nel.style.visibility = 'hidden';\n
","text":""},{"location":"reference/jspsych/#jspsychgetinitsettings","title":"jsPsych.getInitSettings","text":"jsPsych.getInitSettings()\n
"},{"location":"reference/jspsych/#parameters_10","title":"Parameters","text":"None
"},{"location":"reference/jspsych/#return-value_10","title":"Return value","text":"Returns the settings object used to initialize the experiment.
"},{"location":"reference/jspsych/#description_10","title":"Description","text":"Gets the object containing the settings for the current experiment.
"},{"location":"reference/jspsych/#example_9","title":"Example","text":"var settings = jsPsych.getInitSettings();\n\n// check the experiment structure\nconsole.log(JSON.stringify(settings.timeline));\n
"},{"location":"reference/jspsych/#jspsychgetprogress","title":"jsPsych.getProgress","text":"jsPsych.getProgress()\n
"},{"location":"reference/jspsych/#parameters_11","title":"Parameters","text":"None.
"},{"location":"reference/jspsych/#return-value_11","title":"Return value","text":"Returns an object with the following properties:
Property Type Description total_trials numeric Indicates the number of trials in the experiment. Note that this does not count possible loops or skipped trials due to conditional statements. current_trial_global numeric Returns the trial index of the current trial in a global scope. Every trial will increase this count by 1. percent_complete numeric Estimates the percent of the experiment that is complete. Works as expected for experiments without conditional or looping timelines. For complex timelines, the percent is an approximation."},{"location":"reference/jspsych/#description_11","title":"Description","text":"This method returns information about the length of the experiment and the participant's current location in the experiment timeline.
"},{"location":"reference/jspsych/#example_10","title":"Example","text":"var progress = jsPsych.getProgress();\nalert('You have completed approximately '+progress.percent_complete+'% of the experiment');\n
"},{"location":"reference/jspsych/#jspsychgetprogressbarcompleted","title":"jsPsych.getProgressBarCompleted","text":"jsPsych.getProgressBarCompleted()\n
"},{"location":"reference/jspsych/#parameters_12","title":"Parameters","text":"None.
"},{"location":"reference/jspsych/#return-value_12","title":"Return value","text":"Returns a value between 0 and 1 representing how full the progress bar currently is.
"},{"location":"reference/jspsych/#description_12","title":"Description","text":"Used to get the current value of the progress bar. Works for automated and manual control.
"},{"location":"reference/jspsych/#example_11","title":"Example","text":"var progress_bar_amount = jsPsych.getProgressBarCompleted();\n
"},{"location":"reference/jspsych/#jspsychgetstarttime","title":"jsPsych.getStartTime","text":"jsPsych.getStartTime()\n
"},{"location":"reference/jspsych/#parameters_13","title":"Parameters","text":"None.
"},{"location":"reference/jspsych/#return-value_13","title":"Return value","text":"Returns a Date
object indicating when the experiment began.
"},{"location":"reference/jspsych/#description_13","title":"Description","text":"Get the time that the experiment began.
"},{"location":"reference/jspsych/#example_12","title":"Example","text":"var start_time = jsPsych.getStartTime();\n
"},{"location":"reference/jspsych/#jspsychgettotaltime","title":"jsPsych.getTotalTime","text":"jsPsych.getTotalTime()\n
"},{"location":"reference/jspsych/#parameters_14","title":"Parameters","text":"None.
"},{"location":"reference/jspsych/#return-value_14","title":"Return value","text":"Returns a numeric value indicating the number of milliseconds since jsPsych.run
was called.
"},{"location":"reference/jspsych/#description_14","title":"Description","text":"Gets the total time the participant has been in the experiment.
"},{"location":"reference/jspsych/#example_13","title":"Example","text":"var time = jsPsych.getTotalTime();\nconsole.log(time);\n
"},{"location":"reference/jspsych/#jspsychpauseexperiment","title":"jsPsych.pauseExperiment","text":"jsPsych.pauseExperiment()\n
"},{"location":"reference/jspsych/#parameters_15","title":"Parameters","text":"None.
"},{"location":"reference/jspsych/#return-value_15","title":"Return value","text":"None.
"},{"location":"reference/jspsych/#description_15","title":"Description","text":"Pauses the experiment. The experiment will finish the current trial, but will not execute any additional trials until jsPsych.resumeExperiment()
is called.
"},{"location":"reference/jspsych/#example_14","title":"Example","text":"var trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Press p to take a 30 second break. Otherwise, press c to continue immediately.',\n choices: ['p','c'],\n on_finish: function(data){\n if(jsPsych.pluginAPI.compareKeys(data.response, \"p\")) { \n jsPsych.pauseExperiment();\n setTimeout(jsPsych.resumeExperiment, 30000);\n }\n }\n}\n
"},{"location":"reference/jspsych/#jspsychresumeexperiment","title":"jsPsych.resumeExperiment","text":"jsPsych.resumeExperiment()\n
"},{"location":"reference/jspsych/#parameters_16","title":"Parameters","text":"None.
"},{"location":"reference/jspsych/#return-value_16","title":"Return value","text":"None.
"},{"location":"reference/jspsych/#description_16","title":"Description","text":"Resumes the experiment after a call to jsPsych.pauseExperiment()
. If the post trial delay (post_trial_gap
) has not yet been reached, then the experiment will not continue until the delay is finished. For example, if post_trial_gap
was 10,000ms and jsPsych.resumeExperiment()
was called 6,000ms after the previous trial finished, then the experiment would not continue for another 4,000ms.
"},{"location":"reference/jspsych/#example_15","title":"Example","text":"var trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Press p to take a 30 second break. Otherwise, press c to continue immediately.',\n choices: ['p','c'],\n on_finish: function(data){\n if(jsPsych.pluginAPI.compareKeys(data.response, \"p\")) { \n jsPsych.pauseExperiment();\n setTimeout(jsPsych.resumeExperiment, 30000);\n }\n }\n}\n
"},{"location":"reference/jspsych/#jspsychrun","title":"jsPsych.run","text":"jsPsych.run(timeline)\n
"},{"location":"reference/jspsych/#parameters_17","title":"Parameters","text":"Parameter Type Description timeline array An array containing the objects that describe the experiment timeline. See Creating an Experiment: The Timeline."},{"location":"reference/jspsych/#return-value_17","title":"Return value","text":"None.
"},{"location":"reference/jspsych/#description_17","title":"Description","text":"Start the jsPsych experiment with the specified timeline.
"},{"location":"reference/jspsych/#example_16","title":"Example","text":"var timeline = [trial1, trial2, trial3];\n\njsPsych.run(timeline);\n
"},{"location":"reference/jspsych/#jspsychsetprogressbar","title":"jsPsych.setProgressBar","text":"jsPsych.setProgressBar(value)\n
"},{"location":"reference/jspsych/#parameters_18","title":"Parameters","text":"Parameter Type Description value numeric Proprotion (between 0 and 1) to fill the progress bar."},{"location":"reference/jspsych/#return-value_18","title":"Return value","text":"None.
"},{"location":"reference/jspsych/#description_18","title":"Description","text":"Set the progress bar to a custom amount. Proportion must be between 0 and 1. Values larger than 1 are treated as 1.
"},{"location":"reference/jspsych/#example_17","title":"Example","text":"jsPsych.setProgressBar(0.85);\n
"},{"location":"reference/jspsych/#jspsychtimelinevariable","title":"jsPsych.timelineVariable","text":"jsPsych.timelineVariable(variable)\n
"},{"location":"reference/jspsych/#parameters_19","title":"Parameters","text":"Parameter Type Description variable string Name of the timeline variable"},{"location":"reference/jspsych/#return-value_19","title":"Return value","text":"Returns a placeholder object that jsPsych uses to evaluate the timeline variable when the trial runs.
"},{"location":"reference/jspsych/#description_19","title":"Description","text":"Timeline variables are a powerful technique for generating experiments with repetitive procedures but different parameter values. This function fetches the current value of a particular timeline variable. It must be used in conjunction with a timeline that has timeline variables. See the timeline variable section for details.
"},{"location":"reference/jspsych/#examples_1","title":"Examples","text":""},{"location":"reference/jspsych/#use-as-a-parameter-for-a-trial","title":"Use as a parameter for a trial","text":"var trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('image')\n}\n\nvar procedure = {\n timeline: [trial],\n timeline_variables: [\n {image: 'face1.png'},\n {image: 'face2.png'},\n {image: 'face3.png'},\n {image: 'face4.png'}\n ]\n}\n
"},{"location":"reference/jspsych/#jspsychversion","title":"jsPsych.version","text":"jsPsych.version()\n
"},{"location":"reference/jspsych/#parameters_20","title":"Parameters","text":"None.
"},{"location":"reference/jspsych/#return-value_20","title":"Return value","text":"Returns the version number as a string.
"},{"location":"reference/jspsych/#description_20","title":"Description","text":"Gets the version of jsPsych.
"},{"location":"reference/jspsych/#example_18","title":"Example","text":"var version = jsPsych.version();\nconsole.log(version);\n
"},{"location":"support/migration-v7/","title":"Migrating an experiment to v7.x","text":"The release of version 7.0 changes a number of core components of jsPsych. We made these changes to improve jsPsych's compatibility with modern JavaScript tools like package managers and bundlers and to improve the developer experience for people contributing to jsPsych's codebase. We hope these changes will improve the long-term viability of the project and encourage more developers to contribute to jsPsych.
Our aim was to accomplish these goals with minimal changes to the user experience of jsPsych. However, we did have to change a few critical things. This guide is aimed at users who are familiar with v6.x of jsPsych and would like to understand what's changed in v7.x.
"},{"location":"support/migration-v7/#loading-jspsych","title":"Loading jsPsych","text":"There are now three different ways you can load jsPsych into your HTML file. We've updated the hello world tutorial to walk through each of the three options. If you are looking for the option that is most similar to the version 6.x experience, check out option 2. The biggest difference from what you are used to is that the directory structure of the downloaded library is slightly different and plugin files are named a little bit differently.
"},{"location":"support/migration-v7/#initializing-and-running-jspsych","title":"Initializing and running jsPsych","text":"We've removed jsPsych.init()
and split the features into two different functions.
At the start of your experiment script, you'll now call initJsPsych()
to get a new instance of jsPsych and store it in a variable called jsPsych
. This is where you will pass in the variety of parameters that used to go into jsPsych.init()
, with the exception of the timeline
parameter.
var jsPsych = initJsPsych({\n use_webaudio: false,\n on_finish: function(){\n jsPsych.data.displayData();\n }\n});\n
Once you've created your timeline, then you'll launch the experiment by calling jsPsych.run()
, passing in the timeline as the only argument. This is the point in your script where you've used the jsPsych.init
function in jsPsych v6.x. Because the jsPsych.run
function only needs the experiment timeline, this argument should be an array (rather than an object like {timeline: timeline}
in jsPsych v6.x).
var timeline = [...]\n\njsPsych.run(timeline);\n
"},{"location":"support/migration-v7/#the-type-parameter-for-trials","title":"The type
parameter for trials","text":"The type
parameter now expects the value to be a plugin class rather than a string.
For example, if you load the html-keyboard-response
plugin from the CDN...
<script src=\"http://unpkg.com/@jspsych/plugin-html-keyboard-response@1.1.0\"></script>\n
... or from the plugin-html-keyboard-response.js
file in the release archive...
<script src=\"plugin-html-keyboard-response.js\"></script>\n
... then a global variable defining the plugin's class called jsPsychHtmlKeyboardResponse
is available.
To create a trial using the plugin, pass this class as the type
parameter. The plugin classes are named starting with jsPsych
, followed by the plugin name written in camel case (rather than with dashes between words). See the \"Using a plugin\" section of the Plugins overview page for more examples. Note that the value is not a string.
var trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Hello, version 7.0!'\n}\n
"},{"location":"support/migration-v7/#the-choices-parameter-for-keyboard-response-trials","title":"The choices
parameter for keyboard response trials","text":"The choices
parameter for keyboard response trials no longer supports jsPsych.NO_KEYS
and jsPsych.ALL_KEYS
, and they have been replaced by the strings \"NO_KEYS\"
and \"ALL_KEYS\"
respectively.
For example, if you load the audio-keyboard-response
plugin, you can prevent any user input like...
var trial = {\n type: jsPsychAudioKeyboardResponse,\n choices: \"NO_KEYS\",\n stimulus: 'example.ogg',\n trial_ends_after_audio: true\n}\n
"},{"location":"support/migration-v7/#using-extensions","title":"Using extensions","text":"Like plugins, extensions are now also referenced by their class. Extensions are initiliazed in initJsPsych()
instead of jsPsych.init()
. Extension classes are named similarly to plugins, except that they start with jsPsychExtension
.
var jsPsych = initJsPsych({\n extensions: [\n {type: jsPsychExtensionWebgazer}\n ]\n})\n
The class is also used in trials that use the extension.
var trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Hello, version 7.0!',\n extensions: [\n {type: jsPsychExtensionWebgazer}\n ]\n}\n
"},{"location":"support/migration-v7/#custom-plugins","title":"Custom plugins","text":"If you have custom plugins that you would like to upgrade to be compatible with v7.x we recommend using our plugin template.
The new template implements plugins as a class, but the core components are essentially unchanged.
- Anything in
plugin.info
from a v6.x plugin should be moved into the info
object. Note that the type
argument for the parameters follows a slightly different syntax in the v7.x plugins. This object is then assigned as a static property of the class. - Anything in
plugin.trial
from a v6.x plugin should be moved into the trial
method inside the class. - The new template has a
constructor()
function that accepts an instance of jsPsych. You do not need to adjust this portion of the plugin.
There are a few changes to be aware of that may affect your plugin code.
- We removed the
registerPreload
function and we now auto-detect media to preload via the type
argument specified in the info
object. If a parameter is listed as IMAGE
, AUDIO
, or VIDEO
, it will be automatically preloaded. If you wish to disable preloading you can set the preload
flag to false
for the parameter. - If you invoke any functions from jsPsych, like
jsPsych.finishTrial()
, note that jsPsych
is no longer a global variable and you must use the reference to jsPsych that is passed to the constructor. To do this, simply prefix all jsPsych
references with this.
, e.g., jsPsych.finishTrial()
becomes this.jsPsych.finishTrial()
. If your reference to a jsPsych function is inside of another function, then in order for the this
keyword to appropriately reference the jsPsych instance, you must also use a JavaScript arrow function expression for the outer function. For example, this: function end_trial() {\n // ...\n jsPsych.finishTrial(data);\n}\n
Would be re-written as: const end_trial = () => {\n // ...\n this.jsPsych.finishTrial(data);\n}\n
"},{"location":"support/migration-v7/#need-help","title":"Need help?","text":"If you encounter issues migrating code to v7.x, feel free to post in our support thread for migration.
"},{"location":"support/migration-v8/","title":"Migrating an experiment to v8.x","text":"Version 8.x of jsPsych focused on a complete rewrite of the core library to enable new features and make it easier to maintain. Most of the changes in version 8.x are behind the scenes. However, there are some breaking changes that you will need to address in your experiment code in order to upgrade to v8.x.
This guide is aimed at upgrades from version 7.x to 8.x. If you are using version 6.x or earlier, please follow the migration guide for v7.x before trying to upgrade to v8.x.
"},{"location":"support/migration-v8/#timeline-events","title":"Timeline Events","text":"In version 7.x, if a timeline had a conditional_function
it would be checked on every iteration if the timeline also looped. In version 8.x, the conditional_function
is checked only before the first trial on the timeline. We think this is a more intuitive behavior. It allows the conditional_function
to toggle whether a timeline runs at all, and once it starts running we assume that it should continue. If you relied on the old behavior, you can nest the timeline with the conditional_function
inside another timeline that loops.
We've also changed the behavior of on_timeline_start
and on_timeline_finish
to only execute one time each. Previously these events executed on every repetition of a timeline. If you relied on the old behavior, you can nest the timeline with the on_timeline_start
or on_timeline_finish
inside the timeline that repeats.
"},{"location":"support/migration-v8/#timeline-variables","title":"Timeline Variables","text":"We've split the functionality of jsPsych.timelineVariable()
into two different functions to reflect the two different use cases. If you are using jsPsych.timelineVariable()
inside a function you will need to replace the function call with jsPsych.evaluateTimelineVariable()
. Usage as a parameter in a trial doesn't change.
This behavior is still the same:
const trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n}\n
This behavior has changed:
const trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: () => {\n return `<p>The stimulus is ${jsPsych.evaluateTimelineVariable('stimulus')}</p>`\n }\n}\n
We've added some better error support for evaluateTimelineVariable()
so that it will throw an error if there's no corresponding timeline variable to evaluate.
We've removed support for jsPsych.getAllTimelineVariables()
and replaced it with the trial-level property save_timeline_variables
.
If you need to save all the timeline variables of a trial to jsPsych's data, you can set save_timeline_variables: true
in the trial.
"},{"location":"support/migration-v8/#trial-parameters","title":"Trial parameters","text":"We've made some trial parameters more strict to improve the maintainability of the library.
If a plugin has a parameter that is marked as array: true
in the plugin's info
object, then jsPsych will now throw an error if the parameter is not an array. Previously, some plugins allowed some parameters to be either an array or non-array. For the plugins included in jsPsych's main repository, the only affected parameter is the button_html
parameter for the various button response plugins. Previously this parameter could be an array or a string. We've now made it so that it must be a function.
Version 7.x:
const trial = {\n type: jsPsychHtmlButtonResponse,\n stimulus: 'Press a button',\n choices: ['a', 'b', 'c'],\n button_html: '<button class=\"jspsych-btn\" style=\"font-size: 80px;\">%choice%</button>'\n}\n
Version 8.x:
const trial = {\n type: jsPsychHtmlButtonResponse,\n stimulus: 'Press a button',\n choices: ['a', 'b', 'c'],\n button_html: (choice) => {\n return `<button class=\"jspsych-btn\" style=\"font-size: 80px;\">${choice}</button>`\n }\n}\n
The button_html
parameter can also support different HTML for each button. See the plugin documentation for more details.
"},{"location":"support/migration-v8/#plugin-parameter-handling","title":"Plugin parameter handling","text":"In version 7.x, a plugin could omit parameters from the info
object and jsPsych would still evaluate these parameters appropriately in most cases. Version 8.x is more strict about this. Plugins should list all parameters in the info
object. If a parameter is not listed, then timeline variables and function evaluation will not work for that parameter. The save_trial_parameters
parameter will also not work for parameters that are not listed in the info
object.
"},{"location":"support/migration-v8/#plugin-version-and-data-properties","title":"Plugin version
and data
properties","text":"We've added a version
property to the info
object for plugins. This property is a string that should be updated whenever a new version of the plugin is released.
We've also added a data
property to the info
object for plugins. This property is an object that can contain a description of the types of data that the plugin will generate.
Including these properties is not required for a plugin to work, but it is recommended. In version 8.x, jsPsych will throw a warning if a plugin is used that does not have a version
or data
property in the info
object. In version 9.x, we plan to make this a requirement.
"},{"location":"support/migration-v8/#changes-to-finishtrial","title":"Changes to finishTrial()
","text":"When a plugin calls finishTrial()
or ends via a return
statement, jsPsych will now automatically clear the display and clear any timeouts that are still pending. This change should only affect plugin developers. If you are using built-in plugins you should not notice any difference.
"},{"location":"support/migration-v8/#progress-bar","title":"Progress bar","text":"The automatic progress bar now updates after every trial, including trials in nested timelines. If you would like to implement the old behavior of updating only on the top-level timeline, you can manually control the progress bar using the on_finish
callback of the timelines and trials in the top-level timeline.
We've also changed jsPsych.setProgressBar(x)
to jsPsych.progressBar.progress = x
. And we've changed jsPsych.getProgressBarCompleted()
to jsPsych.progressBar.progress
. This simplifies the API for the progress bar.
"},{"location":"support/migration-v8/#data-handling","title":"Data Handling","text":"We've removed internal_node_id
and jsPsych.data.getDataByTimelineNode()
. Timeline node IDs were used internally by jsPsych to keep track of experiment progress in version 7, but this is no longer the case in version 8. Most users didn't need or want to see the internal_node_id
in the data, so we've removed it. If you relied on this parameter, the simplest replacement is probably to use the data
parameter to add the information you need back to the timeline.
"},{"location":"support/migration-v8/#ending-a-timeline-and-ending-the-experiment","title":"Ending a timeline and ending the experiment","text":"We've renamed jsPsych.endExperiment()
to jsPsych.abortExperiment()
.
We've renamed jsPsych.endCurrentTimeline()
to jsPsych.abortCurrentTimeline()
.
"},{"location":"support/migration-v8/#interaction-listeners","title":"Interaction listeners","text":"In version 7.x, interaction events (like exiting fullscreen) would still be listened for even after the experiment ended. These events are no longer reported once the experiment ends.
"},{"location":"support/migration-v8/#need-help","title":"Need help?","text":"If you encounter issues migrating code to v8.x please open a thread on our discussion board.
"},{"location":"support/support/","title":"Support","text":"For questions about jsPsych, the preferred method of support is GitHub Discussions. Questions are most likely to be answered when they include a reproducible example of the problem. If you can make your code available online and link to the experiment, that will make the question easier to answer. Please consider searching through the archive of Q&As before posting a new question.
If you have identified a problem with jsPsych, such as a bug in the code or an error in the documentation, please open a new issue on GitHub.
If you have a suggestion for fixing the problem, feel free to contribute to the project!
Inquiries for paid consultation to develop experiments using jsPsych or to create new custom jsPsych features can be sent to josh.deleeuw@gmail.com.
"},{"location":"tutorials/hello-world/","title":"jsPsych \"Hello world\" experiment","text":"In the long tradition of \"Hello world!\" examples, this tutorial creates an experiment that outputs the phrase \"Hello world!\" to the browser. Though useless as an actual experiment, the process is helpful for learning the basics of using the jsPsych library.
"},{"location":"tutorials/hello-world/#choose-your-own-setup-adventure","title":"Choose your own (setup) adventure","text":"Starting with the release of version 7.0 of jsPsych there are three different ways that you can add jsPsych to your project. Which approach you choose will depend on what your goals are.
-
I want the simplest possible setup. This approach involves using scripts that are hosted on a CDN. You do not need to download or install anything to start using jsPsych. The limitation is that you cannot customize the library. For most experiments, this approach will be sufficient.
-
I want to be able to do some customization, but have a simple setup.. This approach involves downloading a bundle of scripts that make up jsPsych. If you used jsPsych prior to version 7.0, this will feel like the most familiar approach. Having your own copy of the scripts means that you can make modifications to the library such as tweaking plugin behavior.
-
I want to use modern JavaScript tooling, like npm
and import
statements. You can install jsPsych, plugins for jsPsych, and extensions for jsPsych from NPM. This approach allows you to integrate jsPsych into your favorite JavaScript frameworks and get the benefits of TypeScript, bundlers, and more.
"},{"location":"tutorials/hello-world/#option-1-using-cdn-hosted-scripts","title":"Option 1: Using CDN-hosted scripts","text":""},{"location":"tutorials/hello-world/#step-1-create-an-html-file","title":"Step 1: Create an HTML file","text":"Tip
To edit jsPsych code you'll need a programming-friendly text editor. A great free option is Visual Studio Code (Windows, OSX, Linux).
Create a new file called experiment.html
.
There's some basic code that (nearly) all HTML documents have in common. Here's a typical bare-bones HTML document.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n </head>\n <body></body>\n</html>\n
Add the above code to the experiment.html
file and save it. If you open the file in a web browser, you should see a blank page and the title of the page will be 'My experiment'.
"},{"location":"tutorials/hello-world/#step-2-load-the-jspsych-library","title":"Step 2: Load the jsPsych library","text":"To use jsPsych, add a <script>
tag to load the library. We'll load the library from a CDN, which means that the library is hosted on another server and can be loaded without having your own copy.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n </head>\n <body></body>\n</html>\n
Note that the URL for the jsPsych library includes the version number, which ensures that the behavior of your experiment won't change with any future updates to jsPsych.
You may also want to import the jsPsych stylesheet, which applies a basic set of visual styles to the experiment. This requires adding a <link>
tag to the <head>
section of the document.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n</html>\n
"},{"location":"tutorials/hello-world/#step-3-create-a-script-element-and-initialize-jspsych","title":"Step 3: Create a script element and initialize jsPsych","text":"To add JavaScript code directly to the webpage we need to add a pair of <script>
tags after the <body>
tags.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n </script>\n</html>\n
To initialize jsPsych we use the initJsPsych()
function and assign the output to a new variable.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n const jsPsych = initJsPsych();\n </script>\n</html>\n
"},{"location":"tutorials/hello-world/#step-4-use-a-plugin-to-print-a-message","title":"Step 4: Use a plugin to print a message","text":"For this demo we want to show some text on the screen. This is exactly what the html-keyboard-response plugin is designed to do. To use the plugin, we need to load it with a <script>
tag.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n const jsPsych = initJsPsych();\n </script>\n</html>\n
Once the plugin is loaded we can create a trial using the plugin. To declare a trial that uses the html-keyboard-response
plugin, we create an object with the property type
equal to jsPsychHtmlKeyboardResponse
. We can specify the other parameters of the plugin in the same object. Here we use the stimulus
parameter to include a message. You can see the full set of parameters for each plugin on its documentation page.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n const jsPsych = initJsPsych();\n\n const hello_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Hello world!'\n }\n </script>\n</html>\n
"},{"location":"tutorials/hello-world/#step-5-run-the-experiment","title":"Step 5: Run the experiment","text":"Now that we have the trial defined we need to tell jsPsych to run an experiment consisting of this trial. This requires using the jsPsych.run
function and passing in a timeline. For a simple experiment like this one, the timeline is just an array containing the list of trials to run.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n const jsPsych = initJsPsych();\n\n const hello_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Hello world!'\n }\n\n jsPsych.run([hello_trial]);\n </script>\n</html>\n
Once you've saved the file, open it in a browser. You should see \"Hello world!\" printed on the screen, and if you press a key on the keyboard, the text should disappear (ending the trial).
"},{"location":"tutorials/hello-world/#option-2-download-and-host-jspsych","title":"Option 2: Download and host jsPsych","text":""},{"location":"tutorials/hello-world/#step-1-download-jspsych","title":"Step 1: Download jsPsych","text":"Start by downloading the latest release of jsPsych. Here's a direct link (jspsych.zip). The most recent version can always be found at the top of the GitHub releases page. Note that even the releases that are for a particular plugin or extension will contain the full set of files needed to run jsPsych locally in the dist archive (zip)
release asset. You should download the zip file for whatever the most recently released package is. This will ensure that you have the most recent version of all the packages associated with jsPsych.
"},{"location":"tutorials/hello-world/#step-2-create-a-folder-to-store-your-experiment-files","title":"Step 2: Create a folder to store your experiment files","text":"Create a folder on your computer to put the experiment files in. We'll call this \"MyExperiment\" for the tutorial. Add a subfolder called jspsych
. Once you've created the folder, open the downloaded archive from step 1 and copy the contents of the dist
folder into the jspsych
folder. It should look like this:
\ud83d\udcc2 MyExperiment\n-- \ud83d\udcc2 jspsych\n---- \ud83d\udcc4 jspsych.js\n---- \ud83d\udcc4 plugin-animation.js\n---- \ud83d\udcc4 plugin-audio-keyboard-response.js\n---- ...\n
"},{"location":"tutorials/hello-world/#step-3-create-an-html-file","title":"Step 3: Create an HTML file","text":"Tip
To edit jsPsych code you'll need a programming-friendly text editor. A great free option is Visual Studio Code (Windows, OSX, Linux).
Create a new file called experiment.html
in the MyExperiment
folder. The directory structure should look like this:
\ud83d\udcc2 MyExperiment\n-- \ud83d\udcc4 experiment.html\n-- \ud83d\udcc2 jspsych\n
There's some basic code that (nearly) all HTML documents have in common. Here's a typical bare-bones HTML document.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n </head>\n <body></body>\n</html>\n
Add the above code to the experiment.html
file and save it. If you open the file in a web browser, you should see a blank page and the title of the page will be 'My experiment'.
"},{"location":"tutorials/hello-world/#step-4-load-the-jspsych-library","title":"Step 4: Load the jsPsych library","text":"To use jsPsych, add a <script>
tag to load the library. Set the src
attribute to the path to the jspsych.js
file.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"jspsych/jspsych.js\"></script>\n </head>\n <body></body>\n</html>\n
You may also want to import the jsPsych stylesheet, which applies a basic set of visual styles to the experiment. This requires adding a <link>
tag to the <head>
section of the document.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"jspsych/jspsych.js\"></script>\n <link href=\"jspsych/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n</html>\n
"},{"location":"tutorials/hello-world/#step-5-create-a-script-element-and-initialize-jspsych","title":"Step 5: Create a script element and initialize jsPsych","text":"To add JavaScript code directly to the webpage we need to add a pair of <script>
tags after the <body>
tags.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"jspsych/jspsych.js\"></script>\n <link href=\"jspsych/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n </script>\n</html>\n
To initialize jsPsych we use the initJsPsych()
function and assign the output to a new variable.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"jspsych/jspsych.js\"></script>\n <link href=\"jspsych/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n const jsPsych = initJsPsych();\n </script>\n</html>\n
"},{"location":"tutorials/hello-world/#step-6-use-a-plugin-to-print-a-message","title":"Step 6: Use a plugin to print a message","text":"For this demo we want to show some text on the screen. This is exactly what the html-keyboard-response plugin is designed to do. To use the plugin, we need to load it with a <script>
tag.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"jspsych/jspsych.js\"></script>\n <script src=\"jspsych/plugin-html-keyboard-response.js\"></script>\n <link href=\"jspsych/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n const jsPsych = initJsPsych();\n </script>\n</html>\n
Once the plugin is loaded we can create a trial using the plugin. To declare a trial that uses the html-keyboard-response
plugin, we create an object with the property type
equal to jsPsychHtmlKeyboardResponse
. We can specify the other parameters of the plugin in the same object. Here we use the stimulus
parameter to include a message. You can see the full set of parameters for each plugin on its documentation page.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"jspsych/jspsych.js\"></script>\n <script src=\"jspsych/plugin-html-keyboard-response.js\"></script>\n <link href=\"jspsych/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n const jsPsych = initJsPsych();\n\n const hello_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Hello world!'\n }\n </script>\n</html>\n
"},{"location":"tutorials/hello-world/#step-7-run-the-experiment","title":"Step 7: Run the experiment","text":"Now that we have the trial defined we need to tell jsPsych to run an experiment consisting of this trial. This requires using the jsPsych.run
function and passing in a timeline. For a simple experiment like this one, the timeline is just an array containing the list of trials to run.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"jspsych/jspsych.js\"></script>\n <script src=\"jspsych/plugin-html-keyboard-response.js\"></script>\n <link href=\"jspsych/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n const jsPsych = initJsPsych();\n\n const hello_trial = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: 'Hello world!'\n }\n\n jsPsych.run([hello_trial]);\n </script>\n</html>\n
Once you've saved the file, open it in a browser. You should see \"Hello world!\" printed on the screen, and if you press a key on the keyboard, the text should disappear (ending the trial).
"},{"location":"tutorials/hello-world/#option-3-using-npm","title":"Option 3: Using NPM","text":"If you are electing to use npm
to install jsPsych we will assume that you already are familiar with Node.js and generally know what you are doing with web development. We will also assume that you are using a webpack or a similar bundler.
Info
You may want to check out the jsPsych Builder CLI utility. jsPsych Builder allows you to automate the experiment setup, spin up a development server, and transpile and bundle scripts and styles using webpack. Using jsPsych Builder will automate some of the steps in this tutorial, so if you prefer that option, you may want to switch to the getting started instructions on the jsPsych Builder GitHub page.
"},{"location":"tutorials/hello-world/#step-1-install-jspsych","title":"Step 1: Install jspsych","text":"Run npm install jspsych
.
This installs the core jsPsych package. Plugins and extensions are installed separately.
"},{"location":"tutorials/hello-world/#step-2-import-the-initjspsych-function-and-create-a-new-jspsych-instance","title":"Step 2: Import the initJsPsych
function and create a new JsPsych
instance","text":"We create a new instance of the JsPsych
class by calling initJsPsych
. The instance can optionally be configured via a variety of options, passed as an object to initJsPsych
.
import {initJsPsych} from 'jspsych';\n\nconst jsPsych = initJsPsych();\n
"},{"location":"tutorials/hello-world/#step-3-static-markup-and-css","title":"Step 3: Static markup and CSS","text":"jsPsych requires nothing but a body element in your HTML document. For the jsPsych stylesheet, depending on your bundler setup, you can either directly import 'jspsych/css/jspsych.css'
into your JavaScript file or add a link tag (like <link href=\"path/to/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />
) to your HTML document's head.
"},{"location":"tutorials/hello-world/#step-4-install-and-import-a-plugin","title":"Step 4: Install and import a plugin","text":"Install the html-keyboard-response
plugin with:
npm install @jspsych/plugin-html-keyboard-response
Then import the htmlKeyboardResponse
plugin class.
import {initJsPsych} from 'jspsych';\nimport htmlKeyboardResponse from '@jspsych/plugin-html-keyboard-response';\n\nconst jsPsych = initJsPsych();\n
"},{"location":"tutorials/hello-world/#step-5-create-a-trial","title":"Step 5: Create a trial","text":"Once the plugin is imported we can create a trial using the plugin. To declare a trial that uses the html-keyboard-response
plugin, we create an object with the property type
equal to htmlKeyboardResponse
. We can specify the other parameters of the plugin in the same object. Here we use the stimulus
parameter to include a message. You can see the full set of parameters for each plugin on its documentation page.
import {initJsPsych} from 'jspsych';\nimport htmlKeyboardResponse from '@jspsych/plugin-html-keyboard-response';\n\nconst jsPsych = initJsPsych();\n\nconst trial = {\n type: htmlKeyboardResponse,\n stimulus: 'Hello world!',\n}\n
"},{"location":"tutorials/hello-world/#step-6-run","title":"Step 6: Run","text":"Now that we have the trial defined we need to tell jsPsych to run an experiment consisting of this trial. This requires using the jsPsych.run
function and passing in a timeline. For a simple experiment like this one, the timeline is just an array containing the list of trials to run.
import {initJsPsych} from 'jspsych';\nimport htmlKeyboardResponse from '@jspsych/plugin-html-keyboard-response';\n\nconst jsPsych = initJsPsych();\n\nconst trial = {\n type: htmlKeyboardResponse,\n stimulus: 'Hello world!',\n}\n\njsPsych.run([trial]);\n
"},{"location":"tutorials/rt-task/","title":"Summary of Tutorial Content","text":"This tutorial will work through the creation of a simple response time task. The task is to press one key for a blue colored circle and another key for an orange colored circle. Despite this simple task, the tutorial covers many of the key features of jsPsych, including:
- Using a plugin to create a standard trial.
- Combining plugins together to create new kinds of trials.
- Using timeline variables to maximize code reuse.
- Preloading media.
- Randomizing presentation order.
- Manipulating, filtering, and aggregating data.
- Using dynamic content to change the experiment parameters based on the participant's responses.
"},{"location":"tutorials/rt-task/#part-1-creating-a-blank-experiment","title":"Part 1: Creating a blank experiment","text":"Start by setting up a new HTML file with jsPsych, the html-keyboard-response plugin, and the jspsych.css file loaded. If you are unsure how to do this, follow the Hello World tutorial. You should have an HTML document that looks like this:
Info: Loading jsPsych This tutorial assumes that you are using the CDN-based method of loading jsPsych. If you are using another method then everything is the same except for how jsPsych is loaded.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n </script>\n</html>\n
This will be our starting point for building the rest of the experiment.
"},{"location":"tutorials/rt-task/#part-2-display-welcome-message","title":"Part 2: Display welcome message","text":"First we have to initialize jsPsych. We can do this using the initJsPsych()
function, and saving the result to a variable called jsPsych
.
var jsPsych = initJsPsych();\n
All jsPsych experiments are defined by a timeline. The timeline is an array that contains the set of trials we want to run in the experiment. We can start by defining an empty timeline array. We'll add trials to this array as we create them.
var timeline = [];\n
Let's greet the participant with a simple welcome message using the html-keyboard-response plugin.
First, we create a trial that uses the html-keyboard-response
plugin and contains a simple string to show the participant. As explained on the plugins documentation page, the trial object must have a type
parameter that tells jsPsych which plugin to use. The value of type
is similar to the plugin name, but starts with jsPsych
and is written in camel case rather than with dashes. So to use the html-keyboard-response
plugin, we need to write jsPsychHtmlKeyboardResponse
as the trial type.
var welcome = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: \"Welcome to the experiment. Press any key to begin.\"\n};\n
Next, we push the welcome trial to the timeline, which adds it to the end of the array.
timeline.push(welcome);\n
Finally, we tell jsPsych to run the experiment by calling the jsPsych.run() function and passing in the array that defines the experiment timeline.
jsPsych.run(timeline);\n
After each step in the tutorial you can view the complete code up to that point by clicking on the expandable box below. The complete code so far <!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n\n /* initialize jsPsych */\n var jsPsych = initJsPsych();\n\n /* create timeline */\n var timeline = [];\n\n /* define welcome message trial */\n var welcome = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: \"Welcome to the experiment. Press any key to begin.\"\n };\n timeline.push(welcome);\n\n /* start the experiment */\n jsPsych.run(timeline);\n\n </script>\n</html>\n
"},{"location":"tutorials/rt-task/#part-3-show-instructions","title":"Part 3: Show instructions","text":"We can use the same basic structure from part 2 to create a new html-keyboard-response
trial that shows instructions to the participant. The only difference in this trial is that we will use HTML formatting to control how the instructions display and we will add a two second gap after the trial using the post_trial_gap
parameter.
The trial definition looks like this:
var instructions = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `\n <p>In this experiment, a circle will appear in the center \n of the screen.</p><p>If the circle is <strong>blue</strong>, \n press the letter F on the keyboard as fast as you can.</p>\n <p>If the circle is <strong>orange</strong>, press the letter J \n as fast as you can.</p>\n <div style='width: 700px;'>\n <div style='float: left;'><img src='img/blue.png'></img>\n <p class='small'><strong>Press the F key</strong></p></div>\n <div style='float: right;'><img src='img/orange.png'></img>\n <p class='small'><strong>Press the J key</strong></p></div>\n </div>\n <p>Press any key to begin.</p>\n `,\n post_trial_gap: 2000\n};\n
Tip
In JavaScript there are three different ways to define a string
. You can use single quotes '
, double quotes \"
, or backticks `
. Using backticks has two advantages over the other approaches, especially when you are creating long strings with HTML. You can extend the string
across multiple lines and you can use template strings to easily incorporate variables.
Notice that the HTML includes <img>
tags to display the images that the participant will be responding to. You'll need to download these image files. Right-click on each image below and select Save image as.... Put the images in a folder called img
in the experiment folder you created in part 1.
Don't forget to add the trial to the timeline:
timeline.push(instructions);\n
The complete code so far <!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n\n /* initialize jsPsych */\n var jsPsych = initJsPsych();\n\n /* create timeline */\n var timeline = [];\n\n /* define welcome message trial */\n var welcome = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: \"Welcome to the experiment. Press any key to begin.\"\n };\n timeline.push(welcome);\n\n /* define instructions trial */\n var instructions = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `\n <p>In this experiment, a circle will appear in the center \n of the screen.</p><p>If the circle is <strong>blue</strong>, \n press the letter F on the keyboard as fast as you can.</p>\n <p>If the circle is <strong>orange</strong>, press the letter J \n as fast as you can.</p>\n <div style='width: 700px;'>\n <div style='float: left;'><img src='img/blue.png'></img>\n <p class='small'><strong>Press the F key</strong></p></div>\n <div style='float: right;'><img src='img/orange.png'></img>\n <p class='small'><strong>Press the J key</strong></p></div>\n </div>\n <p>Press any key to begin.</p>\n `,\n post_trial_gap: 2000\n };\n timeline.push(instructions);\n\n /* start the experiment */\n jsPsych.run(timeline);\n\n </script>\n</html>\n
"},{"location":"tutorials/rt-task/#part-4-displaying-stimuli-and-getting-responses","title":"Part 4: Displaying stimuli and getting responses","text":"Creating trials to show the stimuli is conceptually the same as creating a trial to show instructions, except that now we are displaying an image instead of text or html. This means we need to use a different plugin: image-keyboard-response
. We need to start by loading this plugin by adding a <script>
tag to the document.
<head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n</head>\n
For now, we will just show each image once. The path to the image file should be set as the stimulus
parameter. We will also set the option for which keys the participant is allowed to use to respond (choices
) so that only the 'f' and 'j' keys are valid responses.
var blue_trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/blue.png',\n choices: ['f', 'j']\n};\n\nvar orange_trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/orange.png',\n choices: ['f', 'j']\n};\n
As usual, we need to add the trials to the timeline.
timeline.push(blue_trial, orange_trial);\n
The complete code so far <!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n\n /* initialize jsPsych */\n var jsPsych = initJsPsych();\n\n /* create timeline */\n var timeline = [];\n\n /* define welcome message trial */\n var welcome = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: \"Welcome to the experiment. Press any key to begin.\"\n };\n timeline.push(welcome);\n\n /* define instructions trial */\n var instructions = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `\n <p>In this experiment, a circle will appear in the center \n of the screen.</p><p>If the circle is <strong>blue</strong>, \n press the letter F on the keyboard as fast as you can.</p>\n <p>If the circle is <strong>orange</strong>, press the letter J \n as fast as you can.</p>\n <div style='width: 700px;'>\n <div style='float: left;'><img src='img/blue.png'></img>\n <p class='small'><strong>Press the F key</strong></p></div>\n <div style='float: right;'><img src='img/orange.png'></img>\n <p class='small'><strong>Press the J key</strong></p></div>\n </div>\n <p>Press any key to begin.</p>\n `,\n post_trial_gap: 2000\n };\n timeline.push(instructions);\n\n /* define test trials */\n var blue_trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/blue.png',\n choices: ['f', 'j']\n };\n\n var orange_trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/orange.png',\n choices: ['f', 'j']\n };\n\n timeline.push(blue_trial, orange_trial);\n\n /* start the experiment */\n jsPsych.run(timeline);\n\n </script>\n</html>\n
"},{"location":"tutorials/rt-task/#part-5-preloading-media","title":"Part 5: Preloading media","text":"Whenever we use media elements (images, audio, or video) in an experiment it is a good idea to preload them prior to needing them for a trial. By preloading media we ask the participant's browser to download the media ahead of needing it, so that when we do need to display or play it there is no lag from needing to download it.
We are going to use the preload plugin to preload the two images. The media preloading section goes into a lot of detail about various options for preloading and different ways that you can use this plugin. Here we are simply going to give the plugin a list of the files that we want to be preloaded.
First we need to add the preload plugin to our <head>
section.
<head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-preload@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n</head>\n
We'll put this trial at the very start of the experiment, so add this code before the welcome
trial.
var preload = {\n type: jsPsychPreload,\n images: ['img/blue.png', 'img/orange.png']\n};\n
As always, add the trial to the timeline.
timeline.push(preload);\n
The complete code so far <!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-preload@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n\n /* initialize jsPsych */\n var jsPsych = initJsPsych();\n\n /* create timeline */\n var timeline = [];\n\n /* preload images */\n var preload = {\n type: jsPsychPreload,\n images: ['img/blue.png', 'img/orange.png']\n };\n timeline.push(preload);\n\n /* define welcome message trial */\n var welcome = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: \"Welcome to the experiment. Press any key to begin.\"\n };\n timeline.push(welcome);\n\n /* define instructions trial */\n var instructions = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `\n <p>In this experiment, a circle will appear in the center \n of the screen.</p><p>If the circle is <strong>blue</strong>, \n press the letter F on the keyboard as fast as you can.</p>\n <p>If the circle is <strong>orange</strong>, press the letter J \n as fast as you can.</p>\n <div style='width: 700px;'>\n <div style='float: left;'><img src='img/blue.png'></img>\n <p class='small'><strong>Press the F key</strong></p></div>\n <div style='float: right;'><img src='img/orange.png'></img>\n <p class='small'><strong>Press the J key</strong></p></div>\n </div>\n <p>Press any key to begin.</p>\n `,\n post_trial_gap: 2000\n };\n timeline.push(instructions);\n\n /* define test trials */\n var blue_trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/blue.png',\n choices: ['f', 'j']\n };\n\n var orange_trial = {\n type: jsPsychImageKeyboardResponse,\n stimulus: 'img/orange.png',\n choices: ['f', 'j']\n };\n timeline.push(blue_trial, orange_trial);\n\n /* start the experiment */\n jsPsych.run(timeline);\n\n </script>\n</html>\n
"},{"location":"tutorials/rt-task/#part-6-timeline-variables","title":"Part 6: Timeline variables","text":"In the full experiment, we will want more than two trials. One way we could do this is to create many more objects that define trials and push them all onto the timeline, but there is a more efficient way: using timeline variables.
The parameters for showing the blue and orange circle are very similar. The only difference is which image is displayed. Timeline variables allow us to define the procedure for showing the stimulus once, and then repeatedly use it with different variables. We'll see how, even in this relatively simple case, this can save us a lot of lines of code.
To start, let's make an array that contains all the different trials we want to run in the test phase. There are only two for the experiment: blue trials and orange trials.
var test_stimuli = [\n { stimulus: \"img/blue.png\"},\n { stimulus: \"img/orange.png\"}\n];\n
Instead of just showing the blue and orange circles, let's also set up the experiment to show a fixation cross (+) in between trials. We can define a trial to show the fixation cross for a fixed amount of time by using the trial_duration
parameter of the html-keyboard-response plugin and setting the choices
parameter to the special value \"NO_KEYS\"
, which means that no responses will be accepted as a valid response and the trial will last however long the trial_duration
parameter specifies.
var fixation = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<div style=\"font-size:60px;\">+</div>',\n choices: \"NO_KEYS\",\n trial_duration: 1000,\n};\n
To show the circles, we'll set up another trial with the image-keyboard-response plugin, but we'll use the function jsPsych.timelineVariable()
to indicate that we want jsPsych to substitute the value of the parameter in from the timeline variables.
var test = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n choices: ['f', 'j']\n}\n
To link the variables that we declared in the test_stimuli
array with the call to jsPsych.timelineVariable()
we need to create a new timeline and set the timeline_variables
property:
var test_procedure = {\n timeline: [fixation, test],\n timeline_variables: test_stimuli\n}\n
We have to add the test_procedure
to the main timeline
array, but the fixation
and test
trial do not need to be added to timeline
because they already exist on the test_procedure
timeline.
timeline.push(test_procedure);\n
What happens when the experiment reaches the test procedure? jsPsych will run the test_procedure
timeline one time for each entry in the test_stimuli
array (two times total, in this case). The first time through, jsPsych will substitute the timeline variables from the first array entry (blue image), and the second time through the second array entry will be used (orange image). Notice that the fixation trial occurs before both the orange and the blue circles, because the entire timeline of the test_procedure
is repeated for each entry in the timeline_variables
array.
The complete code so far <!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-preload@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n\n /* initialize jsPsych */\n var jsPsych = initJsPsych();\n\n /* create timeline */\n var timeline = [];\n\n /* preload images */\n var preload = {\n type: jsPsychPreload,\n images: ['img/blue.png', 'img/orange.png']\n }\n timeline.push(preload);\n\n /* define welcome message trial */\n var welcome = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: \"Welcome to the experiment. Press any key to begin.\"\n };\n timeline.push(welcome);\n\n /* define instructions trial */\n var instructions = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `\n <p>In this experiment, a circle will appear in the center \n of the screen.</p><p>If the circle is <strong>blue</strong>, \n press the letter F on the keyboard as fast as you can.</p>\n <p>If the circle is <strong>orange</strong>, press the letter J \n as fast as you can.</p>\n <div style='width: 700px;'>\n <div style='float: left;'><img src='img/blue.png'></img>\n <p class='small'><strong>Press the F key</strong></p></div>\n <div style='float: right;'><img src='img/orange.png'></img>\n <p class='small'><strong>Press the J key</strong></p></div>\n </div>\n <p>Press any key to begin.</p>\n `,\n post_trial_gap: 2000\n };\n timeline.push(instructions);\n\n /* define trial stimuli array for timeline variables */\n var test_stimuli = [\n { stimulus: \"img/blue.png\"},\n { stimulus: \"img/orange.png\"}\n ];\n\n /* define fixation and test trials */\n var fixation = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<div style=\"font-size:60px;\">+</div>',\n choices: \"NO_KEYS\",\n trial_duration: 1000,\n };\n\n var test = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n choices: ['f', 'j']\n };\n\n /* define test procedure */\n var test_procedure = {\n timeline: [fixation, test],\n timeline_variables: test_stimuli\n };\n timeline.push(test_procedure);\n\n /* start the experiment */\n jsPsych.run(timeline);\n\n </script>\n</html>\n
"},{"location":"tutorials/rt-task/#part-7-parameters-for-timelines-with-timeline-variables","title":"Part 7: Parameters for timelines with timeline variables","text":"Right now our experiment is a measly two trials long. Even worse is that the order of the stimuli is the same every time! When we use timeline variables, we get access to some methods to randomize the order and repeat the trials. To randomize the order, simply set randomize_order: true
on the object with the timeline_variables
:
var test_procedure = {\n timeline: [fixation, test],\n timeline_variables: test_stimuli,\n randomize_order: true\n};\n
We can also easily make the test phase longer by setting the repetitions
parameter. This parameter controls how many times the experiment will loop through all of the entries in the timeline_variables array. For example, if we set repetitions: 5
, then the experiment will loop through the two entries in the timeline_variables 5 times, for a total of 10 test trials.
var test_procedure = {\n timeline: [fixation, test],\n timeline_variables: test_stimuli,\n randomize_order: true,\n repetitions: 5\n};\n
Info: Randomizing timeline variables In a timeline variables procedure, when randomize_order
is true
and repetitions
is greater than 1, the trial order will be re-randomized on each repetition through the timeline_variables
array. This means that there will be some constraints on the randomization of all trials in the procedure.
For example, if a timeline_variables
array contains one trial per stimulus, then the same stimulus could occur twice in a row (since it could be at the end of one repetition and the start of the next one), but it could not be repeated more than twice in a row, regardless of the number of repetitions
.
If you want to repeat your timeline_variables
array but randomize across all trials, you could use the sample
parameter with the fixed-repetitions
option: this will combine all the repeitions of your timeline_variables
array into one larger array, and then randomize the whole thing. You can read more about the randomization, repetition, and sampling options for timeline variables in the Timeline Variables documentation.
The complete code so far <!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-preload@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n\n /* initialize jsPsych */\n var jsPsych = initJsPsych();\n\n /* create timeline */\n var timeline = [];\n\n /* preload images */\n var preload = {\n type: jsPsychPreload,\n images: ['img/blue.png', 'img/orange.png']\n };\n timeline.push(preload);\n\n /* define welcome message trial */\n var welcome = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: \"Welcome to the experiment. Press any key to begin.\"\n };\n timeline.push(welcome);\n\n /* define instructions trial */\n var instructions = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `\n <p>In this experiment, a circle will appear in the center \n of the screen.</p><p>If the circle is <strong>blue</strong>, \n press the letter F on the keyboard as fast as you can.</p>\n <p>If the circle is <strong>orange</strong>, press the letter J \n as fast as you can.</p>\n <div style='width: 700px;'>\n <div style='float: left;'><img src='img/blue.png'></img>\n <p class='small'><strong>Press the F key</strong></p></div>\n <div style='float: right;'><img src='img/orange.png'></img>\n <p class='small'><strong>Press the J key</strong></p></div>\n </div>\n <p>Press any key to begin.</p>\n `,\n post_trial_gap: 2000\n };\n timeline.push(instructions);\n\n /* define trial stimuli array for timeline variables */\n var test_stimuli = [\n { stimulus: \"img/blue.png\"},\n { stimulus: \"img/orange.png\"}\n ];\n\n /* define fixation and test trials */\n var fixation = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<div style=\"font-size:60px;\">+</div>',\n choices: \"NO_KEYS\",\n trial_duration: 1000,\n };\n\n var test = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n choices: ['f', 'j']\n };\n\n /* define test procedure */\n var test_procedure = {\n timeline: [fixation, test],\n timeline_variables: test_stimuli,\n randomize_order: true,\n repetitions: 5\n };\n timeline.push(test_procedure);\n\n /* start the experiment */\n jsPsych.run(timeline);\n\n </script>\n</html>\n
"},{"location":"tutorials/rt-task/#part-8-using-functions-to-generate-parameters","title":"Part 8: Using functions to generate parameters","text":"One aspect of the experiment that could be improved is the duration of the fixation cross. As the experiment stands right now, the timing of the circles appearing is very predictable. We can change that by using a different value for the trial_duration
parameter in the fixation
trial for each trial. But how can we do that and keep the simple code structure we have now where we only have to define the fixation trial once? One option would be to add another timeline variable, like \"fixation_duration\"
and use that to control the timing. But another option is to specify the trial_duration
parameter as a function. If a parameter is a function, jsPsych will execute the function every time the trial runs. That means that if the function returns different results probabilistically, we can get a different parameter value every time the trial runs.
To do that here, we'll use one of the built-in randomization methods in jsPsych's randomization module. jsPsych.randomization.sampleWithoutReplacement()
takes an array of items to sample from and generates a new array of length N by sampling without replacement.
var fixation = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<div style=\"font-size:60px;\">+</div>',\n choices: \"NO_KEYS\",\n trial_duration: function(){\n return jsPsych.randomization.sampleWithoutReplacement([250, 500, 750, 1000, 1250, 1500, 1750, 2000], 1)[0];\n }\n}\n
In the code above, we replaced the trial_duration: 1000
parameter in fixation
with a function. Inside the function, we take a sample from the array [250, 500, 750, 1000, 1250, 1500, 1750, 2000]
of size 1 (second parameter to jsPsych.randomization.sampleWithoutReplacement
). The return value from calling jsPsych.randomization.sampleWithoutReplacement
is an array of length 1, so we add the [0]
selection at the end to get the value out of the array.
The complete code so far <!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-preload@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n\n /* initialize jsPsych */\n var jsPsych = initJsPsych();\n\n /* create timeline */\n var timeline = [];\n\n /* preload images */\n var preload = {\n type: jsPsychPreload,\n images: ['img/blue.png', 'img/orange.png']\n }\n timeline.push(preload);\n\n /* define welcome message trial */\n var welcome = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: \"Welcome to the experiment. Press any key to begin.\"\n };\n timeline.push(welcome);\n\n /* define instructions trial */\n var instructions = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `\n <p>In this experiment, a circle will appear in the center \n of the screen.</p><p>If the circle is <strong>blue</strong>, \n press the letter F on the keyboard as fast as you can.</p>\n <p>If the circle is <strong>orange</strong>, press the letter J \n as fast as you can.</p>\n <div style='width: 700px;'>\n <div style='float: left;'><img src='img/blue.png'></img>\n <p class='small'><strong>Press the F key</strong></p></div>\n <div style='float: right;'><img src='img/orange.png'></img>\n <p class='small'><strong>Press the J key</strong></p></div>\n </div>\n <p>Press any key to begin.</p>\n `,\n post_trial_gap: 2000\n };\n timeline.push(instructions);\n\n /* define trial stimuli array for timeline variables */\n var test_stimuli = [\n { stimulus: \"img/blue.png\"},\n { stimulus: \"img/orange.png\"}\n ];\n\n /* define fixation and test trials */\n var fixation = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<div style=\"font-size:60px;\">+</div>',\n choices: \"NO_KEYS\",\n trial_duration: function(){\n return jsPsych.randomization.sampleWithoutReplacement([250, 500, 750, 1000, 1250, 1500, 1750, 2000], 1)[0];\n }\n };\n\n var test = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n choices: ['f', 'j']\n };\n\n /* define test procedure */\n var test_procedure = {\n timeline: [fixation, test],\n timeline_variables: test_stimuli,\n randomize_order: true,\n repetitions: 5\n };\n timeline.push(test_procedure);\n\n /* start the experiment */\n jsPsych.run(timeline);\n\n </script>\n</html>\n
"},{"location":"tutorials/rt-task/#part-10-displaying-the-data","title":"Part 10: Displaying the data","text":"We have created a complete, if simple, experiment at this point, so let's take a look at the data being generated. jsPsych has a built-in function called jsPsych.data.displayData()
that is useful for debugging your experiment. It will remove all of the information on the screen and replace it with the raw data collected so far. This isn't terribly useful when you are actually running an experiment, but it's nice for checking the data during development.
We need the displayData
function to execute when the experiment ends. One way to do this is to use the on_finish
callback function. This function will automatically execute once all the trials in the experiment are finished. We can specify this function in the experiment settings when we initialize jsPsych with the initJsPsych
method.
var jsPsych = initJsPsych({\n on_finish: function() {\n jsPsych.data.displayData();\n }\n});\n
The complete code so far <!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-preload@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n\n /* initialize jsPsych */\n var jsPsych = initJsPsych({\n on_finish: function() {\n jsPsych.data.displayData();\n }\n });\n\n /* create timeline */\n var timeline = [];\n\n /* preload images */\n var preload = {\n type: jsPsychPreload,\n images: ['img/blue.png', 'img/orange.png']\n };\n timeline.push(preload);\n\n /* define welcome message trial */\n var welcome = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: \"Welcome to the experiment. Press any key to begin.\"\n };\n timeline.push(welcome);\n\n /* define instructions trial */\n var instructions = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `\n <p>In this experiment, a circle will appear in the center \n of the screen.</p><p>If the circle is <strong>blue</strong>, \n press the letter F on the keyboard as fast as you can.</p>\n <p>If the circle is <strong>orange</strong>, press the letter J \n as fast as you can.</p>\n <div style='width: 700px;'>\n <div style='float: left;'><img src='img/blue.png'></img>\n <p class='small'><strong>Press the F key</strong></p></div>\n <div style='float: right;'><img src='img/orange.png'></img>\n <p class='small'><strong>Press the J key</strong></p></div>\n </div>\n <p>Press any key to begin.</p>\n `,\n post_trial_gap: 2000\n };\n timeline.push(instructions);\n\n /* define trial stimuli array for timeline variables */\n var test_stimuli = [\n { stimulus: \"img/blue.png\"},\n { stimulus: \"img/orange.png\"}\n ];\n\n /* define fixation and test trials */\n var fixation = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<div style=\"font-size:60px;\">+</div>',\n choices: \"NO_KEYS\",\n trial_duration: function(){\n return jsPsych.randomization.sampleWithoutReplacement([250, 500, 750, 1000, 1250, 1500, 1750, 2000], 1)[0];\n }\n };\n\n var test = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n choices: ['f', 'j']\n };\n\n /* define test procedure */\n var test_procedure = {\n timeline: [fixation, test],\n timeline_variables: test_stimuli,\n randomize_order: true,\n repetitions: 5\n };\n timeline.push(test_procedure);\n\n /* start the experiment */\n jsPsych.run(timeline);\n\n </script>\n</html>\n
"},{"location":"tutorials/rt-task/#part-11-tagging-trials-with-additional-data","title":"Part 11: Tagging trials with additional data","text":"All trials in jsPsych can be tagged with additional arbitrary data. This data will get stored alongside the data that the plugin normally generates, which allows experimenters to record properties of a trial along with the data from the trial.
When might you use this feature? In this experiment, it would be nice to tag each trial with a circle as a response
trial, so that the resulting data can be easily filtered to look at only the critical trials. We can do that like this.
var test = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n choices: ['f', 'j'],\n data: {\n task: 'response'\n }\n};\n
We also could tag the test trials with a property that indicates what the correct response should be (F for the blue circles, J for the orange). In our current code, we are using the timeline variables feature of jsPsych to choose which circle gets presented on a trial. Since we want to tag the trials differently based on which circle is presented, we need to add the tagging data to the test_stimuli
array, and then use the jsPsych.timelineVariable()
function to get the value and assign it to a property in the data
of the trial.
We start by adding a \"correct_response\" property and value to each object in the test_stimuli
:
var test_stimuli = [\n { stimulus: \"img/blue.png\", correct_response: 'f'},\n { stimulus: \"img/orange.png\", correct_response: 'j'}\n];\n
Now we can use timelineVariable()
in the data
parameter of the test
trial to get the appropriate \"correct_response\" value for each trial.
var test = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n choices: ['f', 'j'],\n data: {\n task: 'response',\n correct_response: jsPsych.timelineVariable('correct_response')\n }\n};\n
Another kind of tagging that would be useful is to mark each fixation trial as such, to make removing the data from fixation trials easier.
var fixation = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<div style=\"font-size:60px;\">+</div>',\n choices: \"NO_KEYS\",\n trial_duration: function(){\n return jsPsych.randomization.sampleWithoutReplacement([250, 500, 750, 1000, 1250, 1500, 1750, 2000], 1)[0];\n },\n data: {\n task: 'fixation'\n }\n};\n
The complete code so far <!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-preload@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n\n /* initialize jsPsych */\n var jsPsych = initJsPsych({\n on_finish: function() {\n jsPsych.data.displayData();\n }\n });\n\n /* create timeline */\n var timeline = [];\n\n /* preload images */\n var preload = {\n type: jsPsychPreload,\n images: ['img/blue.png', 'img/orange.png']\n };\n timeline.push(preload);\n\n /* define welcome message trial */\n var welcome = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: \"Welcome to the experiment. Press any key to begin.\"\n };\n timeline.push(welcome);\n\n /* define instructions trial */\n var instructions = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `\n <p>In this experiment, a circle will appear in the center \n of the screen.</p><p>If the circle is <strong>blue</strong>, \n press the letter F on the keyboard as fast as you can.</p>\n <p>If the circle is <strong>orange</strong>, press the letter J \n as fast as you can.</p>\n <div style='width: 700px;'>\n <div style='float: left;'><img src='img/blue.png'></img>\n <p class='small'><strong>Press the F key</strong></p></div>\n <div style='float: right;'><img src='img/orange.png'></img>\n <p class='small'><strong>Press the J key</strong></p></div>\n </div>\n <p>Press any key to begin.</p>\n `,\n post_trial_gap: 2000\n };\n timeline.push(instructions);\n\n /* define trial stimuli array for timeline variables */\n var test_stimuli = [\n { stimulus: \"img/blue.png\", correct_response: 'f'},\n { stimulus: \"img/orange.png\", correct_response: 'j'}\n ];\n\n /* define fixation and test trials */\n var fixation = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<div style=\"font-size:60px;\">+</div>',\n choices: \"NO_KEYS\",\n trial_duration: function(){\n return jsPsych.randomization.sampleWithoutReplacement([250, 500, 750, 1000, 1250, 1500, 1750, 2000], 1)[0];\n },\n data: {\n task: 'fixation'\n }\n };\n\n var test = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n choices: ['f', 'j'],\n data: {\n task: 'response',\n correct_response: jsPsych.timelineVariable('correct_response')\n }\n };\n\n /* define test procedure */\n var test_procedure = {\n timeline: [fixation, test],\n timeline_variables: test_stimuli,\n randomize_order: true,\n repetitions: 5\n };\n timeline.push(test_procedure);\n\n /* start the experiment */\n jsPsych.run(timeline);\n\n </script>\n </html>\n
"},{"location":"tutorials/rt-task/#part-12-manipulating-data-during-the-experiment","title":"Part 12: Manipulating data during the experiment","text":"Now that the data from the test trials has a tag that describes the correct response, it would be easy to analyze the data after the fact and calculate whether the participant responded correctly.
But, we can also do this in jsPsych as the experiment runs to save time later and enable a limited set of data analysis directly in the experiment code.
To do this, we'll use the on_finish
event of the test trial. We can assign a function to on_finish
, and that function will receive an object containing the data generated by the trial. This object can be manipulated inside the function, and any changes made to the object will be stored in jsPsych's internal representation of the data.
For this example, we'll determine whether the participant responded correctly, and add a new correct
property to the data object.
var test = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n choices: ['f', 'j'],\n data: {\n task: 'response',\n correct_response: jsPsych.timelineVariable('correct_response')\n },\n on_finish: function(data){\n data.correct = jsPsych.pluginAPI.compareKeys(data.response, data.correct_response);\n }\n};\n
The data.response
value is a string representation of the key the participant pressed. We can compare this with the data.correct_response
value, and assign this computed value to a new property data.correct
.
Info: The compareKeys
function Here we are comparing the values of data.response
and data.correct_response
using a jsPsych function called jsPsych.pluginAPI.compareKeys. We're using this function because it allows us to compare keys in either a case sensitive or case insensitive way, depending on the case_sensitive_responses
parameter in the experiment settings. The participant's key response will be recorded in a case-sensitive way in the data (e.g. 'f' or 'F'), but in most cases, we don't care if their response corresponds to an upper or lower case letter (which is why the case_sensitive_responses
experiment setting is false
by default). Using the jsPsych.pluginAPI.commpareKeys
function here means that the response will be scored correctly, even if the participant holds down Shift or has Caps Lock on.
This function is only relevant for keyboard responses; for other kinds of responses, such as button presses, you can simply compare the response and correct response values directly, e.g.
data.correct = data.response === data.correct_response;\n
The complete code so far <!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-preload@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n\n /* initialize jsPsych */\n var jsPsych = initJsPsych({\n on_finish: function() {\n jsPsych.data.displayData();\n }\n });\n\n /* create timeline */\n var timeline = [];\n\n /* preload images */\n var preload = {\n type: jsPsychPreload,\n images: ['img/blue.png', 'img/orange.png']\n };\n timeline.push(preload);\n\n /* define welcome message trial */\n var welcome = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: \"Welcome to the experiment. Press any key to begin.\"\n };\n timeline.push(welcome);\n\n /* define instructions trial */\n var instructions = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `\n <p>In this experiment, a circle will appear in the center \n of the screen.</p><p>If the circle is <strong>blue</strong>, \n press the letter F on the keyboard as fast as you can.</p>\n <p>If the circle is <strong>orange</strong>, press the letter J \n as fast as you can.</p>\n <div style='width: 700px;'>\n <div style='float: left;'><img src='img/blue.png'></img>\n <p class='small'><strong>Press the F key</strong></p></div>\n <div style='float: right;'><img src='img/orange.png'></img>\n <p class='small'><strong>Press the J key</strong></p></div>\n </div>\n <p>Press any key to begin.</p>\n `,\n post_trial_gap: 2000\n };\n timeline.push(instructions);\n\n /* define trial stimuli array for timeline variables */\n var test_stimuli = [\n { stimulus: \"img/blue.png\", correct_response: 'f'},\n { stimulus: \"img/orange.png\", correct_response: 'j'}\n ];\n\n /* define fixation and test trials */\n var fixation = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<div style=\"font-size:60px;\">+</div>',\n choices: \"NO_KEYS\",\n trial_duration: function(){\n return jsPsych.randomization.sampleWithoutReplacement([250, 500, 750, 1000, 1250, 1500, 1750, 2000], 1)[0];\n },\n data: {\n task: 'fixation'\n }\n };\n\n var test = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n choices: ['f', 'j'],\n data: {\n task: 'response',\n correct_response: jsPsych.timelineVariable('correct_response')\n },\n on_finish: function(data){\n data.correct = jsPsych.pluginAPI.compareKeys(data.response, data.correct_response);\n }\n };\n\n /* define test procedure */\n var test_procedure = {\n timeline: [fixation, test],\n timeline_variables: test_stimuli,\n randomize_order: true,\n repetitions: 5\n };\n timeline.push(test_procedure);\n\n /* start the experiment */\n jsPsych.run(timeline);\n\n </script>\n</html>\n
"},{"location":"tutorials/rt-task/#part-13-data-aggregation","title":"Part 13: Data aggregation","text":"jsPsych provides a limited set of analysis functions to allow you to calculate things like mean response times for a selected set of trials. In this part, we'll use these functions to add a final trial to the experiment that tells the participant their accuracy and their mean response time for correct responses.
We'll use the html-keyboard-response
plugin. Because the text that we want to display changes based on the participant's performance in the experiment, we need to use a function for the stimulus
parameter and return the desired text.
Info: Dynamic parameters Using a function as the value of a 'normal' parameter (i.e. a parameter that isn't usually a function) provides lots of flexibility in jsPsych experiments, because it allows you to dynamically change the parameter's value based on the participant's earlier responses, and any other information that you don't know before the experiment has started. For more information and examples, see the dynamic parameter documentation page.
Here's what the code looks like, and a description follows below.
var debrief_block = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: function() {\n\n var trials = jsPsych.data.get().filter({task: 'response'});\n var correct_trials = trials.filter({correct: true});\n var accuracy = Math.round(correct_trials.count() / trials.count() * 100);\n var rt = Math.round(correct_trials.select('rt').mean());\n\n return `<p>You responded correctly on ${accuracy}% of the trials.</p>\n <p>Your average response time was ${rt}ms.</p>\n <p>Press any key to complete the experiment. Thank you!</p>`;\n\n }\n};\ntimeline.push(debrief_block);\n
To create the variable trials
, we use jsPsych.data.get()
which returns a jsPsych data collection containing all of the data from the experiment. We can then use .filter
to select only the trials where task
is 'response'
(a benefit of tagging the trials in part 11). trials
contains all of the data from the trials where a circle was shown.
To get only the correct trials, we can use .filter()
again to select only the trials from the trials
data collection where the property correct
is true
.
To calculate accuracy, we can use the .count()
method to determine how many trials were correct and how many trials there were total. We also use Math.round()
to avoid extra digits after the decimal.
Finally, to calculate the mean response time on correct trials, we use the .select
method on the correct_trials
data collection to select only the 'rt'
property of those trials. We can then use the .mean()
method to find the mean of all the RT values.
"},{"location":"tutorials/rt-task/#the-final-code","title":"The final code","text":"This code is available in the /examples
folder in the jsPsych release download. It is called demo-simple-rt-task.html
.
<!DOCTYPE html>\n<html>\n <head>\n <title>My experiment</title>\n <script src=\"https://unpkg.com/jspsych@8.1.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-html-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-image-keyboard-response@2.0.0\"></script>\n <script src=\"https://unpkg.com/@jspsych/plugin-preload@2.0.0\"></script>\n <link href=\"https://unpkg.com/jspsych@8.1.0/css/jspsych.css\" rel=\"stylesheet\" type=\"text/css\" />\n </head>\n <body></body>\n <script>\n\n /* initialize jsPsych */\n var jsPsych = initJsPsych({\n on_finish: function() {\n jsPsych.data.displayData();\n }\n });\n\n /* create timeline */\n var timeline = [];\n\n /* preload images */\n var preload = {\n type: jsPsychPreload,\n images: ['img/blue.png', 'img/orange.png']\n };\n timeline.push(preload);\n\n /* define welcome message trial */\n var welcome = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: \"Welcome to the experiment. Press any key to begin.\"\n };\n timeline.push(welcome);\n\n /* define instructions trial */\n var instructions = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: `\n <p>In this experiment, a circle will appear in the center \n of the screen.</p><p>If the circle is <strong>blue</strong>, \n press the letter F on the keyboard as fast as you can.</p>\n <p>If the circle is <strong>orange</strong>, press the letter J \n as fast as you can.</p>\n <div style='width: 700px;'>\n <div style='float: left;'><img src='img/blue.png'></img>\n <p class='small'><strong>Press the F key</strong></p></div>\n <div style='float: right;'><img src='img/orange.png'></img>\n <p class='small'><strong>Press the J key</strong></p></div>\n </div>\n <p>Press any key to begin.</p>\n `,\n post_trial_gap: 2000\n };\n timeline.push(instructions);\n\n /* define trial stimuli array for timeline variables */\n var test_stimuli = [\n { stimulus: \"img/blue.png\", correct_response: 'f'},\n { stimulus: \"img/orange.png\", correct_response: 'j'}\n ];\n\n /* define fixation and test trials */\n var fixation = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: '<div style=\"font-size:60px;\">+</div>',\n choices: \"NO_KEYS\",\n trial_duration: function(){\n return jsPsych.randomization.sampleWithoutReplacement([250, 500, 750, 1000, 1250, 1500, 1750, 2000], 1)[0];\n },\n data: {\n task: 'fixation'\n }\n };\n\n var test = {\n type: jsPsychImageKeyboardResponse,\n stimulus: jsPsych.timelineVariable('stimulus'),\n choices: ['f', 'j'],\n data: {\n task: 'response',\n correct_response: jsPsych.timelineVariable('correct_response')\n },\n on_finish: function(data){\n data.correct = jsPsych.pluginAPI.compareKeys(data.response, data.correct_response);\n }\n };\n\n /* define test procedure */\n var test_procedure = {\n timeline: [fixation, test],\n timeline_variables: test_stimuli,\n repetitions: 5,\n randomize_order: true\n };\n timeline.push(test_procedure);\n\n /* define debrief */\n var debrief_block = {\n type: jsPsychHtmlKeyboardResponse,\n stimulus: function() {\n\n var trials = jsPsych.data.get().filter({task: 'response'});\n var correct_trials = trials.filter({correct: true});\n var accuracy = Math.round(correct_trials.count() / trials.count() * 100);\n var rt = Math.round(correct_trials.select('rt').mean());\n\n return `<p>You responded correctly on ${accuracy}% of the trials.</p>\n <p>Your average response time was ${rt}ms.</p>\n <p>Press any key to complete the experiment. Thank you!</p>`;\n\n }\n };\n timeline.push(debrief_block);\n\n /* start the experiment */\n jsPsych.run(timeline);\n\n </script>\n</html>\n
"},{"location":"tutorials/video-tutorials/","title":"Video tutorials","text":"Warning
Most of these videos are using version 6.x
of jsPsych. Using version 7.x
requires a few changes that are not covered in these videos. We recommend starting with the tutorials on this website to understand how to work with 7.x
and then watching these videos for additional information. Much of the content covered in the videos still applies to 7.x
, but you'll need a solid understanding of how to use 7.x
in order to make use of the examples in the videos.
"},{"location":"tutorials/video-tutorials/#youtube-channel","title":"YouTube Channel","text":"A variety of video tutorials are available on Josh de Leeuw's YouTube channel. Some tutorials walk through creating a basic version of an entire experiment, like the tutorial on creating a dichotic listening experiment aimed at new users. Others focus on specific features of jsPsych, like how to use functions as parameters to create experiments that change in response to participant input or how to create a new plugin.
"},{"location":"tutorials/video-tutorials/#workshops","title":"Workshops","text":"Moving Research Online (2020). Recordings from a Summer 2020 workshop on conducting online research are available on the workshop's YouTube channel. Session 1 provides an overview of jsPsych suitable for brand new users. Session 3 covers some more advanced features of jsPsych. This workshop was funded by the National Science Foundation.
babySTEP (2021). The Centre for Comparative Psycholinguistics (CCP, University of Alberta Department of Linguistics) hosted a two-part jsPsych workshop in 2021 as part of their annual STEP program. Day 1 covered the basics of creating a jsPsych experiment, with an emphasis on audio stimuli. Day 2 was organized around pre-submitted questions. The video demonstrates how to create a more complex experiment involving reading a sentence and hearing different audio options for completing the sentences, and answers several questions about timing accuracy, recording participant generated audio, embedding jsPsych into course (or other) websites, and some (non-empirical) advice about attention checks.
"}]}
\ No newline at end of file
diff --git a/v8/sitemap.xml b/v8/sitemap.xml
index 5659e95204..2edc19510a 100644
--- a/v8/sitemap.xml
+++ b/v8/sitemap.xml
@@ -2,497 +2,497 @@
https://www.jspsych.org/v8/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/about/about/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/about/license/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/developers/configuration/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/developers/contributing/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/developers/documentation/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/developers/extension-development/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/developers/plugin-development/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/extensions/list-of-extensions/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/extensions/mouse-tracking/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/extensions/record-video/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/extensions/webgazer/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/newsletter/subscribe/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/overview/browser-device-support/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/overview/building-surveys/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/overview/data/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/overview/dynamic-parameters/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/overview/events/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/overview/exclude-browser/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/overview/experiment-options/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/overview/extensions/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/overview/eye-tracking/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/overview/fullscreen/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/overview/media-preloading/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/overview/mturk/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/overview/plugins/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/overview/progress-bar/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/overview/prolific/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/overview/record-browser-interactions/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/overview/running-experiments/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/overview/simulation/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/overview/style/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/overview/timeline/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/overview/timing-accuracy/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/animation/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/audio-button-response/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/audio-keyboard-response/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/audio-slider-response/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/browser-check/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/call-function/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/canvas-button-response/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/canvas-keyboard-response/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/canvas-slider-response/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/categorize-animation/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/categorize-html/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/categorize-image/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/cloze/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/external-html/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/free-sort/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/fullscreen/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/html-audio-response/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/html-button-response/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/html-keyboard-response/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/html-slider-response/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/html-video-response/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/iat-html/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/iat-image/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/image-button-response/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/image-keyboard-response/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/image-slider-response/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/initialize-camera/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/initialize-microphone/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/instructions/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/list-of-plugins/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/maxdiff/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/mirror-camera/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/preload/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/reconstruction/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/resize/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/same-different-html/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/same-different-image/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/serial-reaction-time-mouse/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/serial-reaction-time/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/sketchpad/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/survey-html-form/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/survey-likert/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/survey-multi-choice/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/survey-multi-select/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/survey-text/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/survey/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/video-button-response/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/video-keyboard-response/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/video-slider-response/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/virtual-chinrest/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/visual-search-circle/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/webgazer-calibrate/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/webgazer-init-camera/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/plugins/webgazer-validate/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/reference/jspsych-data/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/reference/jspsych-pluginAPI/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/reference/jspsych-randomization/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/reference/jspsych-turk/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/reference/jspsych/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/support/migration-v7/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/support/migration-v8/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/support/support/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/tutorials/hello-world/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/tutorials/rt-task/
- 2024-12-16
+ 2024-12-24
daily
https://www.jspsych.org/v8/tutorials/video-tutorials/
- 2024-12-16
+ 2024-12-24
daily
\ No newline at end of file
diff --git a/v8/sitemap.xml.gz b/v8/sitemap.xml.gz
index f81ce0b14ee0e4b16b10d891c1e4ef23fac2f2dd..66f624756dee779acfdd50e441ee41561db902ce 100644
GIT binary patch
delta 1002
zcmVgeP%K
z1nJfjw1fTt66y4CiWZnNFQzt{Jm|{IWFc2fGs3B9DV!ou84YscRWVIdAQo;;XiI&U
zwKT&e%GP$8wQ%9ZYllWnnzREhIYP8ICoa#@jb~$12WpEi>DXKtV5xruRG3(7etqzY
zt^@AQi|`uYChe28Ib8vG*-i%?YBf==Ty-bDRUIcf$|kOp0pW2pQ5XnfRIMiQQj0wr
z*~+cnzt(=}bI#YMf`Ols_oeW=CoJLMh%Q;VOBr`3U##$%3g`Q6(aTqs4yuhwIixNk
zvDYzQdvtR9=1rM8461)k%)zUi1*RZ%dHA2=BV5{`^DtYHIa=&;La0J~&0b~%a}+H#
z+FI2oZ^Xx%(SFvks$kp5bw%5Tt|{D%W*7qD2dFyo#shd{XKS(MrX7U$1RFkN3(NWt
zd2Qw2_dx(KTp5LR(rBf@H~X-GhijM|p!&}avwYtcG16s9qF>FpbtlHm34EA;vtl;lmD
ztIg?ihkY;Gh(v*E2&!$zQ?#+{D%~SVI5nd1Ic&_GQk4h-D$iwzFR}jRm0xW|pq!?1
z1+eaXsdZgs&WJQkN{FGGjmk^>`y#
zFjcfK!?^~hXyUr&Qq$~v71uTUUd=VlzGoy(IpdlUeFn2|Y%JCYn#`ySlCiQ|_xd_V
zo`hL!NpmIKvdU4z#PJ56bNhBuo0njjHss=9`-c+y*2G$8>e|#l|MqJoUedk`4nO2>
z;eR%ZeUSPSRiyIzT9?CNePdb8Khy$!6AhL8!W<_KWw9VOBUl^MDUj`iONkZhcoeQ&
YtJwSZ|6RNMiol1z0U$+=Ht<3K0Gd(t+5i9m
delta 1002
zcmVA*@p=zV(@R9=f|hb19%f!^!?lB$M>)5b@OHSX`9GK
z;D>y&k8hiSdHlU;j>qF;L8tr-8
z+#OjU%~kRrO?n>^uRrDbEE@0;L<(D&z=kn*w#EeCVV_8I?spYnnQ)&t2ZeNN8%%QG
zxr&B`6X(vFp=v!?@8Ss7X8Ek|RWWbK>$W-FPxKwV>Acl8()V0hWJCK!uUT=GQx~
z=sMu$JPWS@uF@`9o6{A5m+f@WqE;j2%2l`GTh(!*gKXk584w;vBZZzIMzz-@UTU#J
zBU`!F`mfH{bk
z8f~rWk~iXG&1gUASXHpC*C{i>9`I&@){yRDW&rivkT_STeZXK-Dab|!zrK2_OYQuBXvo7J&pgAc%F7=;gB%cF#In5iz1s{w2A0K!*}R;f#tQJEp2fqJ|V
zESM_Vm*G@{Q#5f|bE#?ey@>0YeJ|#kX5SMMr<`%kfIfp+I5rk*1Wjg82FY02t$TT$
zBTvFC?n!ec+_K71!^H6lo^t!PQk$1xo;Kv-VEu;@`_@{-N9xklfBgBa5-(}r28Zu*
zx9~rj#Xd;=fhtmYd9BM~zr3-mreAA;zKVuQeqoLihq71@n*pp1>KMqj!llHDbvy`H
YE>-O9`~R+;e?{Qk-(R(+8t_5@04K!#7ytkO
diff --git a/versions.json b/versions.json
index 2d225efe5b..8a004f46d2 100644
--- a/versions.json
+++ b/versions.json
@@ -16,9 +16,9 @@
"title": "v7",
"aliases": [
"7.0",
- "7.2",
"7.1",
- "7.3"
+ "7.3",
+ "7.2"
]
}
]