diff --git a/README.md b/README.md index 7989832c..ca613021 100644 --- a/README.md +++ b/README.md @@ -1,63 +1,62 @@ -![logo](http://www.jspsych.org/img/jspsych-logo.jpg) +![jspsych logo](http://www.jspsych.org/img/jspsych-logo.jpg) -jsPsych is a JavaScript library for creating behavioral experiments that run in a web browser. It provides a framework for defining experiments using a set of flexible plugins that create different kinds of events, and collect different kinds of data. By assembling these plugins together, it is possible to create a wide range of online experiments. +jsPsych is a JavaScript framework for creating behavioral experiments that run in a web browser. -jsPsych experiments are created using the languages of the Web: HTML, CSS, and JavaScript. JavaScript is the programming language used by web browsers. It provides the most control and flexibility for creating web-based experiments, and allows for easy integration with other JavaScript libraries and server-side tools. Don't have JavaScript experience? Don't worry! jsPsych was designed to make creating online experiments as easy as possible for people without web development experience. +Experiments in jsPsych are created using [plugins](https://www.jspsych.org/overview/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. +By assembling different plugins together into [a timeline](https://www.jspsych.org/overview/timeline), it is possible to create a wide range of online experiments. ## What can I do with jsPsych? -jsPsych comes with a number of plugins that you can use create tasks and collect data. Some plugins do general things, like present a stimulus (text, image, audio, video) and record a key press or button response along with a response time. Other plugins do more specific things, like show a set of instructions pages, run a drag-and-drop image sorting task, present a Random-Dot Kinematogram, or calibrate the WebGazer eye-tracking extension. See the documentation website for a [list of all plugins](https://www.jspsych.org/plugins/list-of-plugins/), and to see what each plugin can do. +jsPsych comes with a number of plugins that you can use create tasks and collect data. +Some plugins do general things, like present a stimulus (text, image, audio, video) and record a key press or button response along with a response time. +Other plugins do more specific things, like show a set of instructions pages, run a drag-and-drop image sorting task, or calibrate the WebGazer eye-tracking extension. +See the [list of all plugins](https://www.jspsych.org/plugins/list-of-plugins/) to see what each plugin can do. -Often people can create their experiment by combining these plugins together. But if that's not possible for your experiment, you can also modify a plugin file or [create your own plugin](https://www.jspsych.org/overview/plugins/#creating-a-new-plugin). This gives you the flexibility to do exactly what you want, while still taking advantage of jsPsych's general experiment-building framework. +Often people can create their experiment by combining these plugins together. +But if that's not possible for your experiment, you can also modify a plugin file or [create your own plugin](https://www.jspsych.org/developers/plugin-development). +This gives you the flexibility to do exactly what you want, while still taking advantage of jsPsych's general experiment-building framework. +The plugin template is *extremely* flexible. If a task is possible to do in a web browser, you can almost certainly implement it as a plugin. -Getting started ---------------- +## Getting started -New to jsPsych? A good place to start is the basic [Hello World tutorial](https://www.jspsych.org/tutorials/hello-world/) on the jsPsych website. The [Reaction Time Task tutorial](https://www.jspsych.org/tutorials/rt-task/) is a great next step, since it covers many core topics and features. +jsPsych can be loaded into a project in a variety of ways, including via CDNs and through NPM. +You can learn more about setting up a project by following the [hello world tutorial](https://www.jspsych.org/tutorials/hello-world/) on the jsPsych website. -There are also a number of [video tutorials](https://www.jspsych.org/tutorials/video-tutorials), including [Session 1 of the Moving Online Workshop](https://www.youtube.com/watch?v=BuhfsIFRFe8), which provides an overview of jsPsych suitable for brand new users. +Once you've got a project set up, the [reaction time task tutorial](https://www.jspsych.org/tutorials/rt-task/) is a great next step, since it covers many core topics and features. -Examples ----------- +There are also a number of [video tutorials](https://www.jspsych.org/tutorials/video-tutorials) available on the website. -Several example experiments and plugin demonstrations are available in the `/examples` folder. After you've downloaded the [latest release](https://github.com/jspsych/jsPsych/releases), double-click on an example HTML file to run it in your web browser, and open it with a programming-friendly text editor to see how it works. +## Examples -Documentation -------------- +Several example experiments and plugin demonstrations are available in the `/examples` folder. +After you've downloaded the [latest release](https://github.com/jspsych/jsPsych/releases), double-click on an example HTML file to run it in your web browser, and open it with a programming-friendly text editor to see how it works. -Documentation is available at [jspsych.org](https://www.jspsych.org/). +## Documentation -Need help? ----------- +Documentation is available at [https://www.jspsych.org](https://www.jspsych.org/). -For questions about using the library, please use the GitHub [Discussions forum](https://github.com/jspsych/jsPsych/discussions). +## Getting help -Contributing ------------- +For questions about using the library, please use the GitHub [discussions forum](https://github.com/jspsych/jsPsych/discussions). +You can also browse through the history of Q&A on the forum to find related questions. -Contributions to the code are welcome. Please use the [Issue tracker system](https://github.com/jspsych/jsPsych/issues) to report bugs or discuss suggestions for new features and improvements. If you would like to contribute code, [submit a Pull request](https://help.github.com/articles/using-pull-requests). See the [Contributing to jsPsych](https://www.jspsych.org/about/contributing/) documentation page for more information. +## Contributing -Citation --------- +We :heart: contributions! +See the [contributing to jsPsych](https://www.jspsych.org/developers/contributing/) documentation page for more information about how you can help. + +## Citation If you use this library in academic work, please cite the [paper that describes jsPsych](http://link.springer.com/article/10.3758%2Fs13428-014-0458-y): 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 -Response times --------------- +## Contributors -Wondering if jsPsych can be used for research that depends on accurate response time measurement? For most purposes, the answer is yes. 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. See the following references for extensive work on this topic. +jsPsych is open source project with [numerous contributors](https://github.com/jspsych/jsPsych/graphs/contributors). +The project is currently managed by the core team of Josh de Leeuw ([@jodeleeuw](https://github.com/jodeleeuw)), Becky Gilbert ([@becky-gilbert](https://github.com/becky-gilbert)), and Björn Luchterhandt ([@bjoluc](https://github.com/bjoluc)). -* [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.](http://link.springer.com/article/10.3758%2Fs13428-015-0567-2) -* [Hilbig, B. E. (2016). Reaction time effects in lab- versus web-based research: Experimental evidence. *Behavior Research Methods*, *48*(4), 1718-1724.](http://dx.doi.org/10.3758/s13428-015-0678-9) -* [Pinet, S., Zielinski, C., Mathôt, S. et al. (2017). Measuring sequences of keystrokes with jsPsych: Reliability of response times and interkeystroke intervals. *Behavior Research Methods*, *49*(3), 1163-1176.](http://link.springer.com/article/10.3758/s13428-016-0776-3) -* [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.](http://link.springer.com/article/10.3758%2Fs13428-014-0471-1) +jsPsych was created by [Josh de Leeuw](http://www.twitter.com/joshdeleeuw). - -Credits -------- - -jsPsych was created by Josh de Leeuw ([@jodeleeuw](https://github.com/jodeleeuw)). - -We're grateful for the many [contributors](https://github.com/jspsych/jsPsych/blob/master/contributors.md) to the library, and for the generous support from a [Mozilla Open Source Support (MOSS)](https://www.mozilla.org/en-US/moss/) award. Thank you! \ No newline at end of file +We're also grateful for the generous support from a [Mozilla Open Source Support award](https://www.mozilla.org/en-US/moss/), which funded development of the library from 2020-2021. \ No newline at end of file diff --git a/code-of-conduct.md b/code-of-conduct.md index 5d95e686..76a4d6c7 100644 --- a/code-of-conduct.md +++ b/code-of-conduct.md @@ -33,7 +33,7 @@ Although we strive to make jsPsych as open and collaborative as possible, it’s Such leadership occasionally requires decisions that are in the best interest of the project but may not be understood by or beneficial to everyone. These decisions are important because they keep the project on track, and enable it to move forward faster than if we required complete consensus. Any major decisions taken by the project leader should be mindful of the challenges they may present for others. We expect the project leader to communicate major decisions/changes early on, and to provide their reasoning. ### Contributions -We invite anyone to contribute to any aspect of the project. You can find more information about contributing here: https://www.jspsych.org/about/contributing/ +We invite anyone to contribute to any aspect of the project. You can find more information about contributing here: https://www.jspsych.org/developers/contributing.md/ Because changes to the jsPsych library can have a huge potential for impact on all users, any proposed changes to the library have to be considered very carefully. For this reason, it is always a good idea to check with the project leader about whether your proposed contribution would likely be merged into the jsPsych library. Keep in mind that, even if your work isn’t suitable for merging into the jsPsych library, you can still use it in your own projects and share it publicly with others, e.g. via a separate GitHub repository. diff --git a/docs/about/about.md b/docs/about/about.md index 61bf260b..d72bf25d 100644 --- a/docs/about/about.md +++ b/docs/about/about.md @@ -1,18 +1,11 @@ # About jsPsych -jsPsych was created by [Josh de Leeuw](http://www.twitter.com/joshdeleeuw). There have been [many other contributors](https://github.com/jodeleeuw/jsPsych/blob/master/contributors.md) to the library; thanks to all of them! +jsPsych is open source project with [numerous contributors](https://github.com/jspsych/jsPsych/graphs/contributors). The project is currently managed by the core team of Josh de Leeuw ([@jodeleeuw](https://github.com/jodeleeuw)), Becky Gilbert ([@becky-gilbert](https://github.com/becky-gilbert)), and Björn Luchterhandt ([@bjoluc](https://github.com/bjoluc)). + +jsPsych was created by [Josh de Leeuw :fontawesome-brands-twitter:](http://www.twitter.com/joshdeleeuw). ### Citation -If you use jsPsych for academic work please cite the following paper. +If you use jsPsych please cite the following paper. -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. - -### Response times - -Wondering if jsPsych can be used for research that depends on accurate response time measurement? For most purposes, the answer is yes. 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. See the following references for extensive work on this topic. - -* [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.](http://link.springer.com/article/10.3758%2Fs13428-015-0567-2) -* [Hilbig, B. E. (2016). Reaction time effects in lab- versus web-based research: Experimental evidence. *Behavior Research Methods*, *48*(4), 1718-1724.](http://dx.doi.org/10.3758/s13428-015-0678-9) -* [Pinet, S., Zielinski, C., Mathôt, S. et al. (in press). Measuring sequences of keystrokes with jsPsych: Reliability of response times and interkeystroke intervals. *Behavior Research Methods*.](http://link.springer.com/article/10.3758/s13428-016-0776-3) -* [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.](http://link.springer.com/article/10.3758%2Fs13428-014-0471-1) +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](https://doi.org/10.3758/s13428-014-0458-y). diff --git a/docs/about/contributing.md b/docs/about/contributing.md deleted file mode 100644 index bb1e8307..00000000 --- a/docs/about/contributing.md +++ /dev/null @@ -1,43 +0,0 @@ -# Contributing to jsPsych - -Contributions to jsPsych are welcome! All of the code is managed through the GitHub repository. - -## Steps for modifying the code - -#### Discuss the proposed change - -If you have a specific modification in mind -- for instance, a new feature or bug fix -- please open a [new issue via GitHub](https://github.com/jspsych/jsPsych/issues/new). Describe the proposed change and what functionality it adds to the library and/or what problem it solves. If you are interested in adding a new plugin to the library, it helps if you post an example of the plugin in use and describe the different use cases of the plugin (for more guidance, see the "Writing new plugins" section below). - -If you are thinking about proposing a change but not at the point where you have a specific modification to the code base in mind, then it might be helpful to discuss the issue first on [GitHub Discussions](https://github.com/jspsych/jsPsych/discussions). Discussion posts can be useful for sharing code and getting feedback before requesting a change to the library. - -#### Fork the library and modify the code - -To make changes to the code, you should fork the jsPsych library via GitHub and make modifications on your fork. You may find it useful to make modifications on branches, so that you can keep your proposed changes separate from any other unrelated changes you might want to make on your fork. - -#### Submit a pull request - -Once your modification is complete, submit a pull request to merge your changes into the `master` branch of the main repository. Pull requests will be reviewed by the project team. - -## Writing new plugins - -New plugins are welcome additions to the library. Plugins can be distributed independently of the main library or added to the GitHub repository via a pull request, following the process described above. If you want to add your plugin to the main library then there are a few guidelines to follow. - -#### Make the plugin as general as possible - -Plugins are most useful when they are flexible. Avoid fixing the value of parameters that could be variables. This is especially important for any text that displays on the screen in order to facilitate use in multiple languages. - -#### Use the jsPsych.pluginAPI module when appropriate - -The [pluginAPI module](../core_library/jspsych-pluginAPI.md) contains functions relevant to plugin development. Avoid duplicating the functions defined within the library in your plugin, and instead use the pluginAPI whenever possible. If you have a suggestion for improving pluginAPI methods, then go ahead and submit a pull request to modify it directly. - -#### Document your plugin - -When submitting a pull request to add your plugin, make sure to include a documentation page in the same style as the other docs pages. Documentation files exist in the `docs` directory. - -#### Include an example file - -Write a short example HTML file to include in the `examples` directory. This should demonstrate the basic use cases of the plugin as clearly as possible. - -#### Include a testing file - -Automated code testing for jsPsych is implemented with [Jest](https://facebook.github.io/jest/). To run the tests, install Node and npm. Run `npm install` in the root jsPsych directory. Then run `npm test`. Plugins should have a testing file that validates the behavior of all the plugin parameters. See the `/tests/plugins` directory for examples. diff --git a/docs/about/license.md b/docs/about/license.md index 3db30785..cc2d1022 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,25 +1,7 @@ # License -jsPsych is licensed under the MIT license. +jsPsych is [licensed](https://github.com/jspsych/jsPsych/blob/main/license.txt) under the MIT license. ->The MIT License (MIT) -> ->Copyright (c) 2019 Joshua R. de Leeuw -> ->Permission is hereby granted, free of charge, to any person obtaining a copy ->of this software and associated documentation files (the "Software"), to deal ->in the Software without restriction, including without limitation the rights ->to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ->copies of the Software, and to permit persons to whom the Software is ->furnished to do so, subject to the following conditions: -> ->The above copyright notice and this permission notice shall be included in all ->copies or substantial portions of the Software. -> ->THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ->IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ->FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ->AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ->LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ->OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ->SOFTWARE. +``` +--8<-- "license.txt" +``` \ No newline at end of file diff --git a/docs/about/support.md b/docs/about/support.md deleted file mode 100644 index 9a284e51..00000000 --- a/docs/about/support.md +++ /dev/null @@ -1,7 +0,0 @@ -# Support - -For questions about jsPsych the preferred method of support is via [GitHub Discussions](https://github.com/jspsych/jsPsych/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. - -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](https://github.com/jspsych/jsPsych/issues/new) on the GitHub site. And if you have a suggestion for fixing the problem, feel free to propose a modification by following the steps in the [Contribuitng to jsPsych](contributing.md) page. - -Inquiries for paid consultation to develop experiments using jsPsych or to create new custom jsPsych features can be sent to [josh.deleeuw@gmail.com](mailto:josh.deleeuw@gmail.com). diff --git a/docs/demos/eye-tracking-with-webgazer.html b/docs/demos/eye-tracking-with-webgazer.html index e6e8b294..682b21e7 100644 --- a/docs/demos/eye-tracking-with-webgazer.html +++ b/docs/demos/eye-tracking-with-webgazer.html @@ -1,19 +1,19 @@ - - - - - - - - - - + + + + + + + + + + @@ -12,14 +12,16 @@ - - - + + + + @@ -12,14 +12,16 @@ - - - + + + + @@ -12,14 +12,16 @@ - - - + + + + @@ -12,14 +12,16 @@ - - - + + + + @@ -12,14 +12,16 @@ - - - + + + + @@ -12,14 +12,16 @@ - - - + + + + @@ -12,14 +12,16 @@ - - - + + + + @@ -12,14 +12,16 @@ - - - + + + + @@ -12,14 +12,16 @@ - - - + + + + @@ -12,14 +12,16 @@ - - - - + + + + + @@ -13,14 +12,16 @@ - - - - + + + + + @@ -13,14 +13,16 @@ - - - - + + + + @@ -13,14 +12,16 @@ - - - - + + + + @@ -13,14 +12,16 @@ - - - - + + + + @@ -13,14 +12,16 @@ - - - - + + + + + @@ -13,14 +13,16 @@ - - - + + + @@ -12,14 +11,16 @@ - - - - + + + + @@ -13,14 +12,16 @@ - - - - + + + + @@ -13,14 +12,16 @@ - - - - + + + + @@ -13,14 +12,16 @@ - - - - + + + + @@ -13,14 +12,16 @@ - - - - + + + + + @@ -13,19 +13,21 @@ - - - - + + + + + @@ -13,19 +13,21 @@ - - - - + + + + + @@ -13,19 +13,21 @@ - - - - + + + + + @@ -13,19 +13,21 @@ - - - - + + + + + @@ -13,19 +13,21 @@ - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + @@ -13,14 +12,16 @@ - - - + + + + @@ -14,14 +13,16 @@ - - - - + + + + @@ -13,14 +12,16 @@ - - - + + + @@ -13,19 +13,21 @@ - - - - + + + + + @@ -13,19 +13,21 @@ - - - - + + + + + @@ -13,19 +13,21 @@ - - - - - + + + + + + @@ -14,14 +14,21 @@ - - - + + + + - + @@ -14,19 +14,21 @@ - - - + + + + - + @@ -14,19 +14,21 @@ - - - + + + + - - - - diff --git a/docs/demos/jspsych-vsl-grid-scene-demo1.html b/docs/demos/jspsych-vsl-grid-scene-demo1.html deleted file mode 100644 index 5143edb9..00000000 --- a/docs/demos/jspsych-vsl-grid-scene-demo1.html +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - diff --git a/docs/developers/configuration.md b/docs/developers/configuration.md new file mode 100644 index 00000000..6b4cf2d3 --- /dev/null +++ b/docs/developers/configuration.md @@ -0,0 +1,98 @@ +# Configuring the jsPsych development environment + +## Setup + +JsPsych is written using [TypeScript](https://www.typescriptlang.org/), 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](https://nodejs.org/en/), 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. + +### Install Node.js + +The jsPsych development setup requires Node.js >= v14 to be installed on your machine. +We recommend that you [install version 16](https://nodejs.org/en/) since it includes version 7 of NPM (required for the workspaces feature that the jsPsych repositories use). +If you are bound to Node.js v14, make sure to install NPM v7 manually (via `npm install -g npm@7`). + +### Clone the repository and install the dependencies + +Clone either the jsPsych repository or the jspsych-contrib repository by running + +```sh +git clone https://github.com/jspsych/jsPsych.git && cd jsPsych +``` + +or + +```sh +git clone https://github.com/jspsych/jspsych-contrib.git && cd jspsych-contrib +``` +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. + +!!! attention + It is important that `npm install` is only run in the root directory of the repository (due to the NPM workspaces feature). + If you accidentally ran `npm install` anywhere else, remove the `node_modules` directory and the `package-lock.json` file that were created at that location and run `npm install` in the root directory again. + +!!! 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. + +## Repository structure + +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](https://www.npmjs.com/) where they can be downloaded by NPM or any CDN (such as [unpkg](https://unpkg.com/)). + +## Build chain and build artifacts + +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](https://webpack.js.org/). + +* **`index.cjs`** + Like `index.js`, but using the old CommonJS standard to support backwards-compatible tools like the [Jest](https://jestjs.io/) 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 ` - - -``` - -```js -jsPsych.init({ - timeline: [...], - extensions: [ - {type: 'some-extension', params: {...} } - ] -}) -``` - -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: - -```js -var trial = { - extensions: [ - {type: 'some-extension', params: {...} } - ] -} -``` - -## List of Extensions - -Extension | Description ------- | ----------- -[jspsych‑ext‑webgazer.js](../extensions/jspsych-ext-webgazer.md) | Enables eye tracking using the [WebGazer](https://webgazer.cs.brown.edu/) library. - -## Writing an Extension - -To create a new extension you must create an object that supports a few event callbacks. A barebones extension file looks like this: - -```js -jsPsych.extensions['new-extension'] = (function () { - - var extension = {}; - - extension.initialize = function(params){ - // params are passed from the extensions parameter in jsPsych.init - } - - extension.on_start = function(params){ - // params are passed from the extensions parameter in the trial object - } - - extension.on_load = function(params){ - // params are passed from the extensions parameter in the trial object - } - - extension.on_finish = function(params){ - // params are passed from the extensions parameter in the trial object - return { - // any data that the extension returns here will be added to the trial data - } - } - - return extension; -}); -``` - -The four events that an extension must support are shown in the sample code. - -`extension.initialize` is called with `jsPsych.init()`. This is where setup code for the extension can happen. 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 `jsPsych.init()` to the `extension.initialize` method. `extension.initialize` must return a `Promise` that resolves when the extension is finished initializing. - -`extension.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. - -`extension.on_load` is called after `plugin.trial` has executed, 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. - -`extension.on_finish` is called after the plugin completes. 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. - -The extension can also include any additional methods that are necessary for interacting with it. See the [webgazer extension](../extensions/jspsych-ext-webgazer.md) for an example. \ No newline at end of file diff --git a/docs/extensions/list-of-extensions.md b/docs/extensions/list-of-extensions.md new file mode 100644 index 00000000..92cae8e9 --- /dev/null +++ b/docs/extensions/list-of-extensions.md @@ -0,0 +1,12 @@ +# List of Plugins + +These are the extensions that are included in the jsPsych release. + +Additional extensions may be available in the [community contributions repository](https://github.com/jspsych/jspsych-contrib). + +For an overview of what extensions are and how they work, see our [extensions overview](../overview/extensions.md). + + +Extension | Description +------ | ----------- +[jspsych‑ext‑webgazer](../extensions/webgazer.md) | Enables eye tracking using the [WebGazer](https://webgazer.cs.brown.edu/) library. \ No newline at end of file diff --git a/docs/extensions/jspsych-ext-webgazer.md b/docs/extensions/webgazer.md similarity index 97% rename from docs/extensions/jspsych-ext-webgazer.md rename to docs/extensions/webgazer.md index 095fae4a..3d25fecc 100644 --- a/docs/extensions/jspsych-ext-webgazer.md +++ b/docs/extensions/webgazer.md @@ -1,4 +1,4 @@ -# jspsych-ext-webgazer +# webgazer This extension supports eye tracking through the [WebGazer](https://webgazer.cs.brown.edu/) library. For a narrative description of how to use this extension see the [eye tracking overview](../overview/eye-tracking.md). @@ -6,12 +6,12 @@ This extension supports eye tracking through the [WebGazer](https://webgazer.cs. ### Initialization Parameters -Initialization parameters can be set when calling `jsPsych.init()` +Initialization parameters can be set when calling `initJsPsych()` ```js -jsPsych.init({ +initJsPsych({ extensions: [ - {type: 'webgazer', params: {...}} + {type: jsPsychExtensionWebgazer, params: {...}} ] }) ``` @@ -29,9 +29,9 @@ Trial parameters can be set when adding the extension to a trial object. ```js var trial = { - type: '...', + type: jsPsych..., extensions: [ - {type: 'webgazer', params: {...}} + {type: jsPsychExtensionWebgazer, params: {...}} ] } ``` diff --git a/docs/index.md b/docs/index.md index ce2f66cc..23f7a80c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -2,8 +2,12 @@ ![jsPsych](img/jspsych-logo.jpg) -jsPsych is a JavaScript library for running behavioral experiments in a web browser. The library provides a flexible framework for building a wide range of laboratory-like experiments that can be run online. +jsPsych is a JavaScript framework for creating behavioral experiments that run in a web browser. -To use jsPsych, you provide a description of the experiment in the form of [a timeline](overview/timeline.md). jsPsych handles things like determining which trial to run next, storing data, and randomization. jsPsych uses *plugins* to define what to do at each point on the timeline. Plugins are ready-made templates for simple experimental tasks like displaying instructions or displaying a stimulus and collecting a keyboard response. Plugins are very flexible to support a wide variety of experiments. It is easy to create your own plugin if you have experience with JavaScript programming. +Experiments in jsPsych are created using [plugins](overview/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](plugins/list-of-plugins), use plugins that are developed by community members in the [contrib repository](https://github.com/jspsych/jspsych-contrib), or [create your own plugins](developers/plugin-development/). +By assembling different plugins together into [a timeline](overview/timeline), it is possible to create a wide range of experiments. -[The page on timelines](overview/timeline.md) is a good place to start learning about jsPsych. From there, you might want to complete the [Hello World! tutorial](tutorials/hello-world.md) and the [reaction time experiment tutorial](tutorials/rt-task.md). +[The page on timelines](overview/timeline.md) is a good place to start learning about jsPsych. +From there, you might want to complete the [hello world tutorial](tutorials/hello-world.md) to learn how to set up a jsPsych experiment and the [reaction time experiment tutorial](tutorials/rt-task.md) to learn the core features of the framework. diff --git a/docs/overview/data.md b/docs/overview/data.md index 378f19c0..0d96bd59 100644 --- a/docs/overview/data.md +++ b/docs/overview/data.md @@ -35,7 +35,7 @@ Data can be added to a particular trial by setting the `data` parameter for the ```js var trial = { - type: 'image-keyboard-response', + type: jsPsychImageKeyboardResponse, stimulus: 'imgA.jpg', data: { image_type: 'A' } } @@ -45,7 +45,7 @@ Data declared in this way is also saved in the trials on any nested timelines: ```js var block = { - type: 'image-keyboard-response', + type: jsPsychImageKeyboardResponse, data: { image_type: 'A' }, timeline: [ {stimulus: 'imgA1.jpg'}, @@ -58,7 +58,7 @@ The data object for a trial can also be updated in the `on_finish` event handler ```js var trial = { - type: 'image-keyboard-response', + type: jsPsychImageKeyboardResponse, stimulus: 'imgA.jpg', on_finish: function(data){ if(jsPsych.pluginAPI.compareKeys(data.response, 'j')){ @@ -72,7 +72,7 @@ var trial = { ## Aggregating and manipulating jsPsych data -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](../core_library/jspsych-data.md). +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](../reference/jspsych-data.md). Here are some examples of data collection manipulation. @@ -170,8 +170,7 @@ function saveData(name, data){ } // call the saveData function after the experiment is over -jsPsych.init({ - // code to define the experiment structure would go here... +initJsPsych({ on_finish: function(){ saveData(jsPsych.data.get().csv()); } }); ``` @@ -277,7 +276,7 @@ It's important that the `XMLHttpRequest` is able to complete before the experime ```javascript var trial = { - type: 'call-function', + type: jsPsychCallFunction, async: true, func: function(done){ var xhr = new XMLHttpRequest(); diff --git a/docs/overview/dynamic-parameters.md b/docs/overview/dynamic-parameters.md index 5ba86df5..6aa1d0cf 100644 --- a/docs/overview/dynamic-parameters.md +++ b/docs/overview/dynamic-parameters.md @@ -13,7 +13,7 @@ Here is a sketch of how this functionality could be used to display feedback to var timeline = []; var trial = { - type: 'html-keyboard-response', + type: jsPsychHtmlKeyboardResponse, stimulus: '<<<<<', choices: ['f','j'], data: { @@ -31,7 +31,7 @@ var trial = { } var feedback = { - type: 'html-keyboard-response', + type: jsPsychHtmlKeyboardResponse, stimulus: function(){ // The feedback stimulus is a dynamic parameter because we can't know in advance whether // the stimulus should be 'correct' or 'incorrect'. @@ -61,7 +61,7 @@ var random_duration = function() { } var trial = { - type: 'html-keyboard-response' + type: jsPsychHtmlKeyboardResponse stimulus: '+', 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) } @@ -75,7 +75,7 @@ The trial's `data` parameter can be also function, which is useful for when you var current_difficulty; // value changes during the experiment var trial = { - type: 'survey-text', + type: jsPsychSurveyText, questions: [{prompt: "Please enter your response."}] data: function() { return {difficulty: current_difficulty}; @@ -87,7 +87,7 @@ It's also possible to use a function for any of the _individual properties_ in t ```js var trial = { - type: 'survey-text', + type: jsPsychSurveyText, questions: [{prompt: "Please enter your response."}] data: { difficulty: function() { @@ -107,7 +107,7 @@ Dyanmic parameters work the same way with nested parameters, which are parameter var subject_id; // value is set during the experiment var trial = { - type: 'survey-text', + type: jsPsychSurveyText, questions: function(){ var questions_array = [ {prompt: "Hi "+subject_id+"! What's your favorite city?", required: true, name: 'fav_city'}, @@ -122,7 +122,7 @@ You can also use a function for any of the _individual parameters_ inside of a n ```js var trial = { - type: 'survey-text', + type: jsPsychSurveyText, questions: [ { prompt: function() { diff --git a/docs/overview/callbacks.md b/docs/overview/events.md similarity index 71% rename from docs/overview/callbacks.md rename to docs/overview/events.md index 73248cc2..f8be2c58 100644 --- a/docs/overview/callbacks.md +++ b/docs/overview/events.md @@ -6,11 +6,10 @@ jsPsych offers the ability to call arbitrary functions in response to certain ev ## on_close -The `on_close` callback can be declared in the `jsPsych.init` 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. +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. ```javascript -jsPsych.init({ - timeline: exp, +initJsPsych({ on_close: function(){ var data = jsPsych.data.get().json(); save_data_to_server(data); @@ -22,11 +21,10 @@ jsPsych.init({ ## on_data_update -The `on_data_update` callback can be declared in the `jsPsych.init` 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. +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. ```javascript -jsPsych.init({ - timeline: exp, +initJsPsych({ on_data_update: function(data) { console.log('Just added new data. The contents of the data are: '+JSON.stringify(data)); } @@ -41,7 +39,7 @@ The `on_finish` callback can be added to any trial. The callback will trigger wh ```javascript var trial = { - type: 'image-keyboard-response', + type: jsPsychImageKeyboardResponse, stimulus: 'imgA.png', on_finish: function(data) { if(jsPsych.pluginAPI.compareKeys(data.response, 'j')){ @@ -57,11 +55,10 @@ var trial = { ## on_finish (experiment) -The `on_finish` callback can be declared in the `jsPsych.init` 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. +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. ```javascript -jsPsych.init({ - timeline: exp, +initJsPsych({ on_finish: function(data) { console.log('The experiment is over! Here is all the data: '+JSON.stringify(data)); } @@ -76,7 +73,7 @@ The `on_load` callback can be added to any trial. The callback will trigger once ```javascript var trial = { - type: 'image-keyboard-response', + type: jsPsychImageKeyboardResponse, stimulus: 'imgA.png', on_load: function() { console.log('The trial just finished loading.'); @@ -92,7 +89,7 @@ The `on_start` callback can be added to any trial. The callback will trigger rig ```javascript var trial = { - type: 'image-keyboard-response', + type: jsPsychImageKeyboardResponse, stimulus: 'imgA.png', on_start: function(trial) { console.log('The trial is about to start.'); @@ -149,11 +146,10 @@ var procedure = { ## on_trial_finish -The `on_trial_finish` callback can be declared in the `jsPsych.init` method. The callback will trigger at the end of every trial in the experiment. If you want a callback to trigger only for the end of certain trials, use the [`on_finish`](#onfinishtrial) callback on the trial object. The callback function will be passed a single argument, containing the data object from the trial. +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. If you want a callback to trigger only for the end of certain trials, use the [`on_finish`](#onfinishtrial) callback on the trial object. The callback function will be passed a single argument, containing the data object from the trial. ```javascript -jsPsych.init({ - timeline: exp, +initJsPsych({ on_trial_finish: function(data) { console.log('A trial just ended.'); console.log(JSON.stringify(data)); @@ -165,13 +161,12 @@ jsPsych.init({ ## on_trial_start -The `on_trial_start` callback can be declared in the `jsPsych.init` method. The callback will trigger at the start of every trial in the experiment. 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. +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. 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. ```javascript var current_score = 0; // a variable that is updated throughout the experiment to keep track of the current score. -jsPsych.init({ - timeline: exp, +initJsPsych({ on_trial_start: function(trial) { trial.data.score_at_start_of_trial = current_score; console.log('A trial just started.'); diff --git a/docs/overview/exclude-browser.md b/docs/overview/exclude-browser.md index 0a84396a..7526d169 100644 --- a/docs/overview/exclude-browser.md +++ b/docs/overview/exclude-browser.md @@ -1,6 +1,6 @@ # Exclude Participants Based on Browser Features -Online subjects will use many different kinds of browsers. Depending on the experiment, it may be important to specify a minimum feature set of the browser. jsPsych makes this straightforward. Simply specify certain exclusion criteria in the `jsPsych.init` method call. If a subject's browser doesn't meet the criteria the experiment will not start and the subject will see a message explaining the problem. For size restrictions the subject will see a message that displays the current size of their browser window and the minimum size needed to start the experiment, giving the subject an opportunity to enlarge the browser window to continue. +Online subjects will use many different kinds of browsers. Depending on the experiment, it may be important to specify a minimum feature set of the browser. jsPsych makes this straightforward. Simply specify certain exclusion criteria in the `initJsPsych` method call. If a subject's browser doesn't meet the criteria the experiment will not start and the subject will see a message explaining the problem. For size restrictions the subject will see a message that displays the current size of their browser window and the minimum size needed to start the experiment, giving the subject an opportunity to enlarge the browser window to continue. Current exclusion options: * Minimum browser width & height @@ -11,8 +11,7 @@ Current exclusion options: #### Exclude browsers that are not at least 800x600 pixels ```javascript -jsPsych.init({ - timeline: exp, +initJsPsych({ exclusions: { min_width: 800, min_height: 600 @@ -23,8 +22,7 @@ jsPsych.init({ #### Exclude browsers that do not have access to the WebAudio API ```javascript -jsPsych.init({ - timeline: exp, +initJsPsych({ exclusions: { audio: true } diff --git a/docs/overview/experiment-options.md b/docs/overview/experiment-options.md index 468ba7a3..11f3c4c5 100644 --- a/docs/overview/experiment-options.md +++ b/docs/overview/experiment-options.md @@ -1,12 +1,11 @@ # Experiment-wide settings -There are several options that can be set when calling `jsPsych.init()` to launch the experiment. +There are several options that can be set when calling `initJsPsych()` to initialize the jsPsych experiment. -Options are specified in the object passed to `jsPsych.init`. 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: +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: ```js -jsPsych.init({ - timeline: [...], +initJsPsych({ default_iti: 250, minimum_valid_rt: 100, experiment_width: 800 @@ -22,13 +21,11 @@ By default, jsPsych will render the experiment in the `` element of a page
``` @@ -36,7 +33,7 @@ This option is useful if the experiment needs to be rendered on a page with othe ## Experiment events -Several experiment-wide events can trigger functions. This is documented in more detail on the [event-related callback functions page](callbacks.md). The events that trigger functions are: +Several experiment-wide events can trigger functions. This is documented in more detail on the [event-related callback functions page](events.md). 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. @@ -51,28 +48,26 @@ Exclusion criteria can be specified based on features of the user's web browser, ## Display a progress bar -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 `jsPsych.init`. See the [progress bar page](progress-bar.md) for more details. +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](progress-bar.md) for more details. ## Choose the method for playing audio files -Specifying the `use_webaudio` parameter in `jsPsych.init()` 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. +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](https://security.stackexchange.com/a/190321) 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](running-experiments.md#cross-origin-requests-cors-and-safe-mode) on the Running Experiments page. ```js -jsPsych.init({ - timeline: [...], +initJsPsych({ use_webaudio: false }); ``` ## Set the default intertrial interval -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 `jsPsych.init()`. +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()`. ```js -jsPsych.init({ - timeline: [...], +initJsPsych({ default_iti: 500 }); ``` @@ -86,8 +81,7 @@ The experiment will, by default, take up 100% of the display element. Usually th Specifying the `experiment_width` parameter will set a maximum width for the display. The parameter is specified in pixels. ```js -jsPsych.init({ - timeline: [...], +initJsPsych({ experiment_width: 750 }); ``` @@ -98,8 +92,7 @@ By default, jsPsych will treat any keyboard response time as valid. However, it' ```js // ignore any keyboard responses that are less than 100 ms -jsPsych.init({ - timeline: [...], +initJsPsych({ minimum_valid_rt: 100 }); ``` @@ -108,14 +101,13 @@ jsPsych.init({ 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 `jsPsych.init`. +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`. ```js // use case-sensitive key choices and responses, // i.e. uppercase and lower case letters ('a' and 'A') will be treated as different key choices, // and will be recorded this way in the data -jsPsych.init({ - timeline: [...], +initJsPsych({ case_sensitive_responses: true }); ``` @@ -126,24 +118,22 @@ Note that this setting only applies to key choices and responses that use jsPsyc 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](running-experiments.md#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 `jsPsych.init`. 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. +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. ```js -jsPsych.init({ - timeline: [...], +initJsPsych({ override_safe_mode: true }); ``` ## Add extensions -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 `jsPsych.init`. The `extensions` parameter in `jsPsych.init` 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. +[Extensions](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. ```js -jsPsych.init({ - timeline: [...], +initJsPsych({ extensions: [ - {type: 'webgazer'} + {type: jsPsychExtensionWebgazer} ] }); ``` diff --git a/docs/overview/extensions.md b/docs/overview/extensions.md new file mode 100644 index 00000000..09fb3c01 --- /dev/null +++ b/docs/overview/extensions.md @@ -0,0 +1,42 @@ +# Extensions + +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. + +## Using an Extension + +To use an extension in an experiment, you'll load the extension file via a ` + + +``` + +```js +initJsPsych({ + extensions: [ + {type: jsPsychExtensionExample, params: {...} } + ] +}) +``` + +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: + +```js +var trial = { + extensions: [ + {type: jsPsychExtensionExample, params: {...} } + ] +} +``` + +## List of Extensions + +Extension | Description +------ | ----------- +[jspsych‑ext‑webgazer.js](../extensions/webgazer.md) | Enables eye tracking using the [WebGazer](https://webgazer.cs.brown.edu/) library. + +## Writing an Extension + +See our [developer's guide for extensions](../developers/extension-development.md) for information about how to create a new extension. \ No newline at end of file diff --git a/docs/overview/eye-tracking.md b/docs/overview/eye-tracking.md index 3ace0477..a119e9dd 100644 --- a/docs/overview/eye-tracking.md +++ b/docs/overview/eye-tracking.md @@ -8,62 +8,68 @@ jsPsych supports eye tracking through the [WebGazer](https://webgazer.cs.brown.e The [official version of WebGazer](https://webgazer.cs.brown.edu/#download) is currently **not** supported by jsPsych. Our [fork of the library](https://github.com/jspsych/WebGazer) 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. -A copy of our fork is included in the jsPsych release, in the `/examples/js/webgazer` folder. You will need to copy this folder into your project directory. This guide will assume that the folder is located at `/js/webgazer`, but you can change the path as you'd like. - -Include the `webgazer.js` file in your experiment via a ` - + + ``` +!!! 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](../tutorials/hello-world.md#option-2-download-and-host-jspsych) 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: + ```html + + ``` + ### Load the jsPsych webgazer extension -The [webgazer extension](/extensions/jspsych-ext-webgazer.md) adds functionality to jsPsych for interacting with webgazer. Load it like you would a plugin file. - +The [webgazer extension](../extensions/webgazer.md) adds functionality to jsPsych for interacting with webgazer. Load it like you would a plugin file. ```html - - - + + + ``` -To use the WebGazer extension in an experiment, include it in the list of extensions passed to `jsPsych.init()` +To use the WebGazer extension in an experiment, include it in the list of extensions passed to `initJsPsych()` ```js -jsPsych.init({ - timeline: [...], +initJsPsych({ extensions: [ - {type: 'webgazer'} + {type: jsPsychExtensionWebgazer} ] }) ``` ### Initialize the camera -To help the participant position their face correctly for eye tracking you can use the [jspsych-webgazer-init-camera plugin](/plugins/jspsych-webgazer-init-camera.ms). 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. +To help the participant position their face correctly for eye tracking you can use the [webgazer-init-camera plugin](../plugins/webgazer-init-camera.md). 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. ```js var init_camera_trial = { - type: 'webgazer-init-camera' + type: jsPsychWebgazerInitCamera } ``` ### Calibration -To calibrate WebGazer, you can use the [jspsych-webgazer-calibrate plugin](/plugins/jspsych-webgazer-calibrate.md). 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](/plugins/jspsych-webgazer-calibrate.md). +To calibrate WebGazer, you can use the [webgazer-calibrate plugin](../plugins/webgazer-calibrate.md). 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](../plugins/webgazer-calibrate.md). 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. ```js var calibration_trial = { - type: 'webgazer-calibrate', + type: jsPsychWebgazerCalibrate, calibration_points: [[25,50], [50,50], [75,50], [50,25], [50,75]], calibration_mode: 'click' } @@ -72,12 +78,12 @@ var calibration_trial = { ### Validation -To measure the accuracy and precision of the calibration, you can use the [jspsych-webgazer-vaidate plugin](/plugins/jspsych-webgazer-validate.md). 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](/plugins/jspsych-webgazer-validate.md). +To measure the accuracy and precision of the calibration, you can use the [webgazer-vaidate plugin](../plugins/webgazer-validate.md). 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](../plugins/webgazer-validate.md). ```js var validation_trial = { - type: 'webgazer-validate', + type: jsPsychWebgazerValidate, validation_points: [[-200,200], [200,200],[-200,-200],[200,-200]], validation_point_coordinates: 'center-offset-pixels', roi_radius: 100 @@ -103,11 +109,11 @@ To enable eye tracking for a trial in your experiment, you can simply add the We ```js var trial = { - type: 'html-keyboard-response', + type: jsPsychHtmlKeyboardResponse, stimulus: '', extensions: [ { - type: 'webgazer', + type: jsPsychExtensionWebgazer, params: { targets: ['#scene'] } @@ -161,19 +167,19 @@ If you have tips based on your own experience please consider sharing them on ou - - - - - - - - - - + + + + + + + + + + ``` @@ -38,12 +38,12 @@ We can capture these variables with jsPsych, and add them to jsPsych's data. Thi 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. -![Prolific Study Completion Screenshot](/img/prolific-study-completion.png) +![Prolific Study Completion Screenshot](../img/prolific-study-completion.png) 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](/plugins/jspsych-call-function/#async-function-call)). + 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](../plugins/call-function.md#async-function-call)). ### Participant clicks a link @@ -53,7 +53,7 @@ Here's an example trial that could be used. Note that `choices` is set to `jsPsy ```js var final_trial = { - type: 'html-keyboard-response', + type: jsPsychHtmlKeyboardResponse, stimulus: `

You've finished the last task. Thanks for participating!

Click here to return to Prolific and complete the study.

`, choices: jsPsych.NO_KEYS @@ -67,8 +67,7 @@ A second option is to automatically redirect the participant to the completion U Here's an example using the `on_finish` event for the entire experiment. ```js -jsPsych.init({ - timeline: [...], +var jsPsych = initJsPsych({ on_finish: function(){ window.location = "https://app.prolific.co/submissions/complete?cc=XXXXXXX" } diff --git a/docs/overview/record-browser-interactions.md b/docs/overview/record-browser-interactions.md index 6aa2cf1b..2dd7f66c 100644 --- a/docs/overview/record-browser-interactions.md +++ b/docs/overview/record-browser-interactions.md @@ -1,6 +1,6 @@ # Record browser interactions -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()](../core_library/jspsych-data.md#jspsychdatagetinteractiondata). +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()](../reference/jspsych-data.md#jspsychdatagetinteractiondata). 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. @@ -12,10 +12,10 @@ Each time the user leaves the experiment window, returns to the experiment windo } ``` -You can specify a custom function, in the jsPsych.init() method, that is called whenever one of these events occurs +You can specify a custom function, in the initJsPsych() method, that is called whenever one of these events occurs ```javascript -jsPsych.init({ +initJsPsych({ on_interaction_data_update: function(data) { console.log(JSON.stringify(data)) } diff --git a/docs/overview/running-experiments.md b/docs/overview/running-experiments.md index 49586f73..92c0ecbf 100644 --- a/docs/overview/running-experiments.md +++ b/docs/overview/running-experiments.md @@ -27,12 +27,12 @@ Web browsers have a security policy called [cross-origin resource sharing (CORS) 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 `jsPsych.init`). 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 `jsPsych.init`. +* **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 [`jsPsych.init`](../core_library/jspsych-core.md#jspsychinit), 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 `jsPsych.init` settings when you move the experiment online. +This safe mode feature is controlled by the `override_safe_mode` parameter in [`initJsPsych`](../reference/jspsych.md#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 `jsPsych.init`. One reason you might do this is if you've disabled web security features in your browser (see [here](https://alfilatov.com/posts/run-chrome-without-cors/) and [here](https://stackoverflow.com/questions/4819060/allow-google-chrome-to-use-xmlhttprequest-to-load-a-url-from-a-local-file) 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. +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](https://alfilatov.com/posts/run-chrome-without-cors/) and [here](https://stackoverflow.com/questions/4819060/allow-google-chrome-to-use-xmlhttprequest-to-load-a-url-from-a-local-file) 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. @@ -40,22 +40,22 @@ The `override_safe_mode` parameter also has no effect when your experiment is ru 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](media-preloading.md) 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](https://developers.google.com/web/tools/chrome-devtools/network) 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`](../plugins/jspsych-preload.md) so that participants with slow/unreliable internet connections will be able to take part in your experiment. +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](https://developers.google.com/web/tools/chrome-devtools/network) 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`](../plugins/preload.md) so that participants with slow/unreliable internet connections will be able to take part in your experiment. ### Permanent data storage -As explained in the [Data Storage, Aggregation, and Manipulation](data.md#data-in-jspsych-permanent-and-non-permanent-data) 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`](../core_library/jspsych-data.md#localsave)), displaying it in the webpage at the end of the experiment (using [`jsPsych.data.displayData`](../core_library/jspsych-data.md#jspsychdatadisplaydata)), or printing it to the browser's console (using [`console.log`](https://www.w3schools.com/jsref/met_console_log.asp)). +As explained in the [Data Storage, Aggregation, and Manipulation](data.md#data-in-jspsych-permanent-and-non-permanent-data) 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`](../reference/jspsych-data.md#localsave)), displaying it in the webpage at the end of the experiment (using [`jsPsych.data.displayData`](../reference/jspsych-data.md#jspsychdatadisplaydata)), or printing it to the browser's console (using [`console.log`](https://www.w3schools.com/jsref/met_console_log.asp)). 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](../core_library/jspsych-randomization.md#jspsychrandomizationsamplewithoutreplacement) instead of counterbalancing version assignment: +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](../reference/jspsych-randomization.md#jspsychrandomizationsamplewithoutreplacement) instead of counterbalancing version assignment: ```js var versions = [1,2]; var random_version = jsPsych.randomization.sampleWithoutReplacement(versions,1)[0]; ``` -And use [URL query parameters](../core_library/jspsych-data.md#jspsychdatageturlvariable) to pass in variables like session number and difficulty level: +And use [URL query parameters](../reference/jspsych-data.md#jspsychdatageturlvariable) to pass in variables like session number and difficulty level: ```js // add the variables onto the end of the URL that appears in the browser when you open the file @@ -88,11 +88,11 @@ Some options for running your jsPsych experiment online include: ### Recruiting Participants -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](../core_library/jspsych-data.md#jspsychdatageturlvariable). 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. +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](../reference/jspsych-data.md#jspsychdatageturlvariable). 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](https://www.prolific.co/): An online labor market designed specifically for web-based research. * [Amazon Mechanical Turk (MTurk)](https://www.mturk.com/): 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](../core_library/jspsych-turk.md). Information about integrating with Prolific can be found in the researcher support section of their website. +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](../reference/jspsych-turk.md). Information about integrating with Prolific can be found in the researcher support section of their website. diff --git a/docs/overview/style.md b/docs/overview/style.md index 9c432825..eb621676 100644 --- a/docs/overview/style.md +++ b/docs/overview/style.md @@ -12,16 +12,16 @@ In the example below, the stimulus font size is set to 30px and the text color i ```javascript var trial = { - type: 'html-keyboard-response', + type: jsPsychHtmlKeyboardResponse, stimulus: '

hello world!

' } ``` -You can also use a [dynamic parameter](/overview/dynamic-parameters) 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](/overview/timeline/#timeline-variables): +You can also use a [dynamic parameter](dynamic-parameters) 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](timeline.md#timeline-variables): ```javascript var trial = { - type: 'html-keyboard-response', + type: jsPsychHtmlKeyboardResponse, stimulus: function() { var stim = '

'+jsPsych.timelineVariable('text')+'

'; return stim; @@ -86,9 +86,9 @@ In the example below, the default font size is set to 25px throughout the experi ```html - - - + + + ``` -You may want the `css_classes` parameter to vary across trials. If so, you can turn it into a [dynamic parameter](/overview/dynamic-parameters) or use [timeline variables](/overview/timeline/#timeline-variables) (see examples below). +You may want the `css_classes` parameter to vary across trials. If so, you can turn it into a [dynamic parameter](dynamic-parameters) or use [timeline variables](timeline.md#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. @@ -176,9 +176,9 @@ In the example below, the CSS selector `.left-align #stimulus` selects the eleme ```html - - - + + +