jspsych 6.2.0 → 7.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -29
- package/css/jspsych.css +39 -39
- package/dist/JsPsych.d.ts +112 -0
- package/dist/TimelineNode.d.ts +34 -0
- package/dist/index.browser.js +3164 -0
- package/dist/index.browser.js.map +1 -0
- package/dist/index.browser.min.js +2 -0
- package/dist/index.browser.min.js.map +1 -0
- package/dist/index.cjs +3158 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +3152 -0
- package/dist/index.js.map +1 -0
- package/dist/migration.d.ts +3 -0
- package/dist/modules/data/DataCollection.d.ts +45 -0
- package/dist/modules/data/DataColumn.d.ts +15 -0
- package/dist/modules/data/index.d.ts +25 -0
- package/dist/modules/data/utils.d.ts +3 -0
- package/dist/modules/extensions.d.ts +22 -0
- package/dist/modules/plugin-api/HardwareAPI.d.ts +15 -0
- package/dist/modules/plugin-api/KeyboardListenerAPI.d.ts +34 -0
- package/dist/modules/plugin-api/MediaAPI.d.ts +27 -0
- package/dist/modules/plugin-api/SimulationAPI.d.ts +41 -0
- package/dist/modules/plugin-api/TimeoutAPI.d.ts +5 -0
- package/dist/modules/plugin-api/index.d.ts +8 -0
- package/dist/modules/plugins.d.ts +129 -0
- package/dist/modules/randomization.d.ts +35 -0
- package/dist/modules/turk.d.ts +40 -0
- package/dist/modules/utils.d.ts +7 -0
- package/package.json +32 -15
- package/src/JsPsych.ts +884 -0
- package/src/TimelineNode.ts +536 -0
- package/src/index.ts +71 -0
- package/src/migration.ts +37 -0
- package/src/modules/data/DataCollection.ts +198 -0
- package/src/modules/data/DataColumn.ts +86 -0
- package/src/modules/data/index.ts +174 -0
- package/src/modules/data/utils.ts +75 -0
- package/src/modules/extensions.ts +23 -0
- package/src/modules/plugin-api/HardwareAPI.ts +32 -0
- package/src/modules/plugin-api/KeyboardListenerAPI.ts +165 -0
- package/src/modules/plugin-api/MediaAPI.ts +337 -0
- package/src/modules/plugin-api/SimulationAPI.ts +181 -0
- package/src/modules/plugin-api/TimeoutAPI.ts +16 -0
- package/src/modules/plugin-api/index.ts +28 -0
- package/src/modules/plugins.ts +158 -0
- package/src/modules/randomization.ts +327 -0
- package/src/modules/turk.ts +99 -0
- package/src/modules/utils.ts +30 -0
- package/.github/workflows/jest.yml +0 -20
- package/code-of-conduct.md +0 -56
- package/contributors.md +0 -61
- package/docs/CNAME +0 -1
- package/docs/about/about.md +0 -18
- package/docs/about/contributing.md +0 -43
- package/docs/about/license.md +0 -25
- package/docs/about/support.md +0 -7
- package/docs/core_library/jspsych-core.md +0 -661
- package/docs/core_library/jspsych-data.md +0 -589
- package/docs/core_library/jspsych-pluginAPI.md +0 -510
- package/docs/core_library/jspsych-randomization.md +0 -397
- package/docs/core_library/jspsych-turk.md +0 -102
- package/docs/img/blue.png +0 -0
- package/docs/img/folder-setup.png +0 -0
- package/docs/img/folder-with-html.png +0 -0
- package/docs/img/githubreleases.jpg +0 -0
- package/docs/img/jspsych-favicon.png +0 -0
- package/docs/img/jspsych-logo-no-text-mono.svg +0 -493
- package/docs/img/jspsych-logo.jpg +0 -0
- package/docs/img/orange.png +0 -0
- package/docs/img/palmer_stim.png +0 -0
- package/docs/img/progress_bar.png +0 -0
- package/docs/img/visual_search_example.jpg +0 -0
- package/docs/index.md +0 -9
- package/docs/overview/browser-device-support.md +0 -35
- package/docs/overview/callbacks.md +0 -140
- package/docs/overview/data.md +0 -281
- package/docs/overview/exclude-browser.md +0 -32
- package/docs/overview/experiment-options.md +0 -121
- package/docs/overview/fullscreen.md +0 -36
- package/docs/overview/media-preloading.md +0 -91
- package/docs/overview/mturk.md +0 -77
- package/docs/overview/progress-bar.md +0 -110
- package/docs/overview/record-browser-interactions.md +0 -23
- package/docs/overview/running-experiments.md +0 -95
- package/docs/overview/timeline.md +0 -387
- package/docs/overview/trial.md +0 -142
- package/docs/plugins/creating-a-plugin.md +0 -79
- package/docs/plugins/jspsych-animation.md +0 -40
- package/docs/plugins/jspsych-audio-button-response.md +0 -60
- package/docs/plugins/jspsych-audio-keyboard-response.md +0 -58
- package/docs/plugins/jspsych-audio-slider-response.md +0 -53
- package/docs/plugins/jspsych-call-function.md +0 -81
- package/docs/plugins/jspsych-canvas-button-response.md +0 -66
- package/docs/plugins/jspsych-canvas-keyboard-response.md +0 -68
- package/docs/plugins/jspsych-canvas-slider-response.md +0 -89
- package/docs/plugins/jspsych-categorize-animation.md +0 -60
- package/docs/plugins/jspsych-categorize-html.md +0 -52
- package/docs/plugins/jspsych-categorize-image.md +0 -53
- package/docs/plugins/jspsych-cloze.md +0 -45
- package/docs/plugins/jspsych-external-html.md +0 -70
- package/docs/plugins/jspsych-free-sort.md +0 -55
- package/docs/plugins/jspsych-fullscreen.md +0 -57
- package/docs/plugins/jspsych-html-button-response.md +0 -42
- package/docs/plugins/jspsych-html-keyboard-response.md +0 -51
- package/docs/plugins/jspsych-html-slider-response.md +0 -45
- package/docs/plugins/jspsych-iat-html.md +0 -64
- package/docs/plugins/jspsych-iat-image.md +0 -64
- package/docs/plugins/jspsych-image-button-response.md +0 -46
- package/docs/plugins/jspsych-image-keyboard-response.md +0 -57
- package/docs/plugins/jspsych-image-slider-response.md +0 -52
- package/docs/plugins/jspsych-instructions.md +0 -58
- package/docs/plugins/jspsych-maxdiff.md +0 -42
- package/docs/plugins/jspsych-rdk.md +0 -119
- package/docs/plugins/jspsych-reconstruction.md +0 -48
- package/docs/plugins/jspsych-resize.md +0 -39
- package/docs/plugins/jspsych-same-different-html.md +0 -53
- package/docs/plugins/jspsych-same-different-image.md +0 -66
- package/docs/plugins/jspsych-serial-reaction-time-mouse.md +0 -50
- package/docs/plugins/jspsych-serial-reaction-time.md +0 -57
- package/docs/plugins/jspsych-survey-html-form.md +0 -50
- package/docs/plugins/jspsych-survey-likert.md +0 -70
- package/docs/plugins/jspsych-survey-multi-choice.md +0 -48
- package/docs/plugins/jspsych-survey-multi-select.md +0 -53
- package/docs/plugins/jspsych-survey-text.md +0 -63
- package/docs/plugins/jspsych-video-button-response.md +0 -52
- package/docs/plugins/jspsych-video-keyboard-response.md +0 -48
- package/docs/plugins/jspsych-video-slider-response.md +0 -58
- package/docs/plugins/jspsych-visual-search-circle.md +0 -52
- package/docs/plugins/jspsych-vsl-animate-occlusion.md +0 -55
- package/docs/plugins/jspsych-vsl-grid-scene.md +0 -62
- package/docs/plugins/overview.md +0 -111
- package/docs/tutorials/hello-world.md +0 -144
- package/docs/tutorials/rt-task.md +0 -1107
- package/examples/add-to-end-of-timeline.html +0 -32
- package/examples/conditional-and-loop-functions.html +0 -63
- package/examples/css/jquery-ui.css +0 -1225
- package/examples/data-add-properties.html +0 -40
- package/examples/data-as-function.html +0 -36
- package/examples/data-from-timeline.html +0 -45
- package/examples/data-from-url.html +0 -21
- package/examples/demo-flanker.html +0 -108
- package/examples/demo-simple-rt-task.html +0 -104
- package/examples/demos/demo_1.html +0 -29
- package/examples/demos/demo_2.html +0 -43
- package/examples/demos/demo_3.html +0 -58
- package/examples/display-element-to-embed-experiment.html +0 -73
- package/examples/end-active-node.html +0 -52
- package/examples/end-experiment.html +0 -43
- package/examples/exclusions.html +0 -32
- package/examples/external_html/simple_consent.html +0 -4
- package/examples/img/1.gif +0 -0
- package/examples/img/10.gif +0 -0
- package/examples/img/11.gif +0 -0
- package/examples/img/12.gif +0 -0
- package/examples/img/2.gif +0 -0
- package/examples/img/3.gif +0 -0
- package/examples/img/4.gif +0 -0
- package/examples/img/5.gif +0 -0
- package/examples/img/6.gif +0 -0
- package/examples/img/7.gif +0 -0
- package/examples/img/8.gif +0 -0
- package/examples/img/9.gif +0 -0
- package/examples/img/age/of1.jpg +0 -0
- package/examples/img/age/of2.jpg +0 -0
- package/examples/img/age/of3.jpg +0 -0
- package/examples/img/age/om1.jpg +0 -0
- package/examples/img/age/om2.jpg +0 -0
- package/examples/img/age/om3.jpg +0 -0
- package/examples/img/age/yf1.jpg +0 -0
- package/examples/img/age/yf4.jpg +0 -0
- package/examples/img/age/yf5.jpg +0 -0
- package/examples/img/age/ym2.jpg +0 -0
- package/examples/img/age/ym3.jpg +0 -0
- package/examples/img/age/ym5.jpg +0 -0
- package/examples/img/backwardN.gif +0 -0
- package/examples/img/blue.png +0 -0
- package/examples/img/con1.png +0 -0
- package/examples/img/con2.png +0 -0
- package/examples/img/fixation.gif +0 -0
- package/examples/img/happy_face_1.jpg +0 -0
- package/examples/img/happy_face_2.jpg +0 -0
- package/examples/img/happy_face_3.jpg +0 -0
- package/examples/img/happy_face_4.jpg +0 -0
- package/examples/img/inc1.png +0 -0
- package/examples/img/inc2.png +0 -0
- package/examples/img/normalN.gif +0 -0
- package/examples/img/orange.png +0 -0
- package/examples/img/redX.png +0 -0
- package/examples/img/ribbon.jpg +0 -0
- package/examples/img/sad_face_1.jpg +0 -0
- package/examples/img/sad_face_2.jpg +0 -0
- package/examples/img/sad_face_3.jpg +0 -0
- package/examples/img/sad_face_4.jpg +0 -0
- package/examples/js/snap.svg-min.js +0 -21
- package/examples/jspsych-RDK.html +0 -58
- package/examples/jspsych-animation.html +0 -33
- package/examples/jspsych-audio-button-response.html +0 -52
- package/examples/jspsych-audio-keyboard-response.html +0 -62
- package/examples/jspsych-audio-slider-response.html +0 -55
- package/examples/jspsych-call-function.html +0 -32
- package/examples/jspsych-canvas-button-response.html +0 -95
- package/examples/jspsych-canvas-keyboard-response.html +0 -78
- package/examples/jspsych-canvas-slider-response.html +0 -67
- package/examples/jspsych-categorize-animation.html +0 -46
- package/examples/jspsych-categorize-html.html +0 -38
- package/examples/jspsych-categorize-image.html +0 -38
- package/examples/jspsych-cloze.html +0 -42
- package/examples/jspsych-free-sort.html +0 -97
- package/examples/jspsych-fullscreen.html +0 -44
- package/examples/jspsych-html-button-response.html +0 -46
- package/examples/jspsych-html-keyboard-response.html +0 -42
- package/examples/jspsych-html-slider-response.html +0 -53
- package/examples/jspsych-iat.html +0 -510
- package/examples/jspsych-image-button-response.html +0 -84
- package/examples/jspsych-image-keyboard-response.html +0 -78
- package/examples/jspsych-image-slider-response.html +0 -76
- package/examples/jspsych-instructions.html +0 -37
- package/examples/jspsych-maxdiff.html +0 -33
- package/examples/jspsych-reconstruction.html +0 -43
- package/examples/jspsych-resize.html +0 -34
- package/examples/jspsych-same-different-html.html +0 -28
- package/examples/jspsych-same-different-image.html +0 -33
- package/examples/jspsych-serial-reaction-time-mouse.html +0 -98
- package/examples/jspsych-serial-reaction-time.html +0 -54
- package/examples/jspsych-survey-html-form.html +0 -33
- package/examples/jspsych-survey-likert.html +0 -42
- package/examples/jspsych-survey-multi-choice.html +0 -40
- package/examples/jspsych-survey-multi-select.html +0 -42
- package/examples/jspsych-survey-text.html +0 -34
- package/examples/jspsych-video-button-response.html +0 -57
- package/examples/jspsych-video-keyboard-response.html +0 -53
- package/examples/jspsych-video-slider-response.html +0 -55
- package/examples/jspsych-visual-search-circle.html +0 -58
- package/examples/jspsych-vsl-animate-occlusion.html +0 -29
- package/examples/jspsych-vsl-grid-scene.html +0 -41
- package/examples/lexical-decision.html +0 -132
- package/examples/manual-preloading.html +0 -53
- package/examples/pause-unpause.html +0 -33
- package/examples/progress-bar.html +0 -62
- package/examples/sound/hammer.mp3 +0 -0
- package/examples/sound/sound.mp3 +0 -0
- package/examples/sound/speech_blue.mp3 +0 -0
- package/examples/sound/speech_green.mp3 +0 -0
- package/examples/sound/speech_joke.mp3 +0 -0
- package/examples/sound/speech_red.mp3 +0 -0
- package/examples/sound/tone.mp3 +0 -0
- package/examples/timeline-variables-sampling.html +0 -50
- package/examples/timeline-variables.html +0 -55
- package/examples/video/sample_video.mp4 +0 -0
- package/jspsych.js +0 -2796
- package/license.txt +0 -21
- package/mkdocs.yml +0 -104
- package/plugins/jspsych-animation.js +0 -189
- package/plugins/jspsych-audio-button-response.js +0 -247
- package/plugins/jspsych-audio-keyboard-response.js +0 -204
- package/plugins/jspsych-audio-slider-response.js +0 -262
- package/plugins/jspsych-call-function.js +0 -58
- package/plugins/jspsych-canvas-button-response.js +0 -199
- package/plugins/jspsych-canvas-keyboard-response.js +0 -155
- package/plugins/jspsych-canvas-slider-response.js +0 -207
- package/plugins/jspsych-categorize-animation.js +0 -266
- package/plugins/jspsych-categorize-html.js +0 -220
- package/plugins/jspsych-categorize-image.js +0 -222
- package/plugins/jspsych-cloze.js +0 -112
- package/plugins/jspsych-external-html.js +0 -112
- package/plugins/jspsych-free-sort.js +0 -444
- package/plugins/jspsych-fullscreen.js +0 -104
- package/plugins/jspsych-html-button-response.js +0 -188
- package/plugins/jspsych-html-keyboard-response.js +0 -149
- package/plugins/jspsych-html-slider-response.js +0 -202
- package/plugins/jspsych-iat-html.js +0 -284
- package/plugins/jspsych-iat-image.js +0 -286
- package/plugins/jspsych-image-button-response.js +0 -311
- package/plugins/jspsych-image-keyboard-response.js +0 -247
- package/plugins/jspsych-image-slider-response.js +0 -353
- package/plugins/jspsych-instructions.js +0 -237
- package/plugins/jspsych-maxdiff.js +0 -174
- package/plugins/jspsych-rdk.js +0 -1373
- package/plugins/jspsych-reconstruction.js +0 -134
- package/plugins/jspsych-resize.js +0 -166
- package/plugins/jspsych-same-different-html.js +0 -168
- package/plugins/jspsych-same-different-image.js +0 -169
- package/plugins/jspsych-serial-reaction-time-mouse.js +0 -213
- package/plugins/jspsych-serial-reaction-time.js +0 -247
- package/plugins/jspsych-survey-html-form.js +0 -171
- package/plugins/jspsych-survey-likert.js +0 -195
- package/plugins/jspsych-survey-multi-choice.js +0 -208
- package/plugins/jspsych-survey-multi-select.js +0 -232
- package/plugins/jspsych-survey-text.js +0 -185
- package/plugins/jspsych-video-button-response.js +0 -320
- package/plugins/jspsych-video-keyboard-response.js +0 -279
- package/plugins/jspsych-video-slider-response.js +0 -351
- package/plugins/jspsych-visual-search-circle.js +0 -259
- package/plugins/jspsych-vsl-animate-occlusion.js +0 -196
- package/plugins/jspsych-vsl-grid-scene.js +0 -103
- package/plugins/template/jspsych-plugin-template.js +0 -35
- package/tests/README.md +0 -7
- package/tests/jsPsych/default-iti.test.js +0 -51
- package/tests/jsPsych/default-parameters.test.js +0 -58
- package/tests/jsPsych/endexperiment.test.js +0 -49
- package/tests/jsPsych/events.test.js +0 -369
- package/tests/jsPsych/init.test.js +0 -48
- package/tests/jsPsych/loads.test.js +0 -7
- package/tests/jsPsych/min-rt.test.js +0 -58
- package/tests/jsPsych/progressbar.test.js +0 -202
- package/tests/jsPsych/timeline-variables.test.js +0 -254
- package/tests/jsPsych/timelines.test.js +0 -498
- package/tests/jsPsych.data/datacollection.test.js +0 -116
- package/tests/jsPsych.data/datacolumn.test.js +0 -50
- package/tests/jsPsych.data/datamodule.test.js +0 -152
- package/tests/jsPsych.data/dataparameter.test.js +0 -251
- package/tests/jsPsych.data/interactions.test.js +0 -109
- package/tests/jsPsych.pluginAPI/pluginapi.test.js +0 -144
- package/tests/jsPsych.randomization/randomziation.test.js +0 -27
- package/tests/jsPsych.utils/utils.test.js +0 -58
- package/tests/media/blue.png +0 -0
- package/tests/media/orange.png +0 -0
- package/tests/media/sample_video.mp4 +0 -0
- package/tests/media/sound.mp3 +0 -0
- package/tests/plugins/plugin-animation.test.js +0 -35
- package/tests/plugins/plugin-audio-button-response.test.js +0 -15
- package/tests/plugins/plugin-audio-keyboard-response.test.js +0 -15
- package/tests/plugins/plugin-audio-slider-response.test.js +0 -15
- package/tests/plugins/plugin-call-function.test.js +0 -49
- package/tests/plugins/plugin-categorize-animation.test.js +0 -274
- package/tests/plugins/plugin-categorize-html.test.js +0 -17
- package/tests/plugins/plugin-categorize-image.test.js +0 -17
- package/tests/plugins/plugin-cloze.test.js +0 -140
- package/tests/plugins/plugin-free-sort.test.js +0 -112
- package/tests/plugins/plugin-fullscreen.test.js +0 -41
- package/tests/plugins/plugin-html-button-response.test.js +0 -161
- package/tests/plugins/plugin-html-keyboard-response.test.js +0 -139
- package/tests/plugins/plugin-html-slider-response.test.js +0 -155
- package/tests/plugins/plugin-iat-html.test.js +0 -328
- package/tests/plugins/plugin-iat-image.test.js +0 -308
- package/tests/plugins/plugin-image-button-response.test.js +0 -183
- package/tests/plugins/plugin-image-keyboard-response.test.js +0 -154
- package/tests/plugins/plugin-image-slider-response.test.js +0 -183
- package/tests/plugins/plugin-instructions.test.js +0 -66
- package/tests/plugins/plugin-maxdiff.test.js +0 -39
- package/tests/plugins/plugin-rdk.test.js +0 -17
- package/tests/plugins/plugin-reconstruction.test.js +0 -16
- package/tests/plugins/plugin-resize.test.js +0 -16
- package/tests/plugins/plugin-same-different-html.test.js +0 -17
- package/tests/plugins/plugin-same-different-image.test.js +0 -17
- package/tests/plugins/plugin-serial-reaction-time-mouse.test.js +0 -42
- package/tests/plugins/plugin-serial-reaction-time.test.js +0 -69
- package/tests/plugins/plugin-survey-html-form.test.js +0 -44
- package/tests/plugins/plugin-survey-likert.test.js +0 -48
- package/tests/plugins/plugin-survey-multi-choice.test.js +0 -48
- package/tests/plugins/plugin-survey-multi-select.test.js +0 -72
- package/tests/plugins/plugin-survey-text.test.js +0 -115
- package/tests/plugins/plugin-video-button-response.test.js +0 -35
- package/tests/plugins/plugin-video-keyboard-response.test.js +0 -35
- package/tests/plugins/plugin-video-slider-response.test.js +0 -34
- package/tests/plugins/plugin-visual-search-circle.test.js +0 -16
- package/tests/plugins/plugin-vsl-animate-occlusion.test.js +0 -16
- package/tests/plugins/plugin-vsl-grid-scene.test.js +0 -16
- package/tests/testing-utils.js +0 -13
|
@@ -1,387 +0,0 @@
|
|
|
1
|
-
# Creating an Experiment: The Timeline
|
|
2
|
-
|
|
3
|
-
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.
|
|
4
|
-
|
|
5
|
-
## A single trial
|
|
6
|
-
|
|
7
|
-
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 file to use to run the trial. For example, if you want to use the text plugin to display a short message, the trial object would look like this:
|
|
8
|
-
|
|
9
|
-
```javascript
|
|
10
|
-
var trial = {
|
|
11
|
-
type: 'html-keyboard-response',
|
|
12
|
-
stimulus: 'hello world!'
|
|
13
|
-
}
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
The parameters for this object 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.
|
|
17
|
-
|
|
18
|
-
To create a timeline with the single trial and run the experiment, just embed the trial object in an array. A timeline is simply an array of trials.
|
|
19
|
-
|
|
20
|
-
```javascript
|
|
21
|
-
var timeline = [trial];
|
|
22
|
-
|
|
23
|
-
jsPsych.init({
|
|
24
|
-
timeline: timeline
|
|
25
|
-
});
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
To actually create and run this simple example, complete the [hello world tutorial](../tutorials/hello-world.md).
|
|
29
|
-
|
|
30
|
-
## Multiple trials
|
|
31
|
-
|
|
32
|
-
Scaling up to multiple trials is straightforward. Just create an object for each trial, and add each object to the timeline array.
|
|
33
|
-
|
|
34
|
-
```javascript
|
|
35
|
-
// with lots of trials, it might be easier to add the trials
|
|
36
|
-
// to the timeline array as they are defined.
|
|
37
|
-
var timeline = [];
|
|
38
|
-
|
|
39
|
-
var trial_1 = {
|
|
40
|
-
type: 'html-keyboard-response',
|
|
41
|
-
stimulus: 'This is trial 1.'
|
|
42
|
-
}
|
|
43
|
-
timeline.push(trial_1);
|
|
44
|
-
|
|
45
|
-
var trial_2 = {
|
|
46
|
-
type: 'html-keyboard-response',
|
|
47
|
-
stimulus: 'This is trial 2.'
|
|
48
|
-
}
|
|
49
|
-
timeline.push(trial_2);
|
|
50
|
-
|
|
51
|
-
var trial_3 = {
|
|
52
|
-
type: 'html-keyboard-response',
|
|
53
|
-
stimulus: 'This is trial 3.'
|
|
54
|
-
}
|
|
55
|
-
timeline.push(trial_3);
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
## Nested timelines
|
|
59
|
-
|
|
60
|
-
Each object on the timeline can also have it's 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.
|
|
61
|
-
|
|
62
|
-
```javascript
|
|
63
|
-
var judgment_trials = {
|
|
64
|
-
type: 'image-keyboard-response',
|
|
65
|
-
prompt: '<p>Press a number 1-7 to indicate how unusual the image is.</p>',
|
|
66
|
-
choices: ['1','2','3','4','5','6','7'],
|
|
67
|
-
timeline: [
|
|
68
|
-
{stimulus: 'image1.png'},
|
|
69
|
-
{stimulus: 'image2.png'},
|
|
70
|
-
{stimulus: 'image3.png'}
|
|
71
|
-
]
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
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.
|
|
76
|
-
|
|
77
|
-
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.
|
|
78
|
-
|
|
79
|
-
```javascript
|
|
80
|
-
var judgment_trials = {
|
|
81
|
-
type: 'image-keyboard-response',
|
|
82
|
-
prompt: '<p>Press a number 1-7 to indicate how unusual the image is.</p>',
|
|
83
|
-
choices: ['1','2','3','4','5','6','7'],
|
|
84
|
-
timeline: [
|
|
85
|
-
{stimulus: 'image1.png'},
|
|
86
|
-
{stimulus: 'image2.png', prompt: '<p>Press 1 for this trial.</p>'},
|
|
87
|
-
{stimulus: 'image3.png'}
|
|
88
|
-
]
|
|
89
|
-
}
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
Timelines can be nested any number of times.
|
|
93
|
-
|
|
94
|
-
## Timeline variables
|
|
95
|
-
|
|
96
|
-
A common pattern in behavioral experiments is to repeat the same procedure many times with slightly different parameters. A procedure might be a single trial, but it also might be a series of trials. One shortcut to implement this pattern is with the 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.
|
|
97
|
-
|
|
98
|
-
What follows is an example of how to use timeline variables. The [simple reaction time tutorial](../tutorials/rt-task.md) also explains how to use timeline variables.
|
|
99
|
-
|
|
100
|
-
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, but timeline variables make it even easier - as well as adding extra features like sampling and randomization.
|
|
101
|
-
|
|
102
|
-
Here's a basic version of the task with timeline variables.
|
|
103
|
-
|
|
104
|
-
```javascript
|
|
105
|
-
var face_name_procedure = {
|
|
106
|
-
timeline: [
|
|
107
|
-
{
|
|
108
|
-
type: 'html-keyboard-response',
|
|
109
|
-
stimulus: '+',
|
|
110
|
-
choices: jsPsych.NO_KEYS,
|
|
111
|
-
trial_duration: 500
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
type: 'image-keyboard-response',
|
|
115
|
-
stimulus: jsPsych.timelineVariable('face'),
|
|
116
|
-
choices: jsPsych.NO_KEYS,
|
|
117
|
-
trial_duration: 2500
|
|
118
|
-
}
|
|
119
|
-
],
|
|
120
|
-
timeline_variables: [
|
|
121
|
-
{ face: 'person-1.jpg' },
|
|
122
|
-
{ face: 'person-2.jpg' },
|
|
123
|
-
{ face: 'person-3.jpg' },
|
|
124
|
-
{ face: 'person-4.jpg' }
|
|
125
|
-
]
|
|
126
|
-
}
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
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 Alex, the second Beth, and so on. The variables are referenced within the procedure by calling the `jsPsych.timelineVariable()` method and passing in the name of the variable.
|
|
130
|
-
|
|
131
|
-
What if we wanted the stimuli to be a little more complex, with a name displayed below each face? And let's add an additional step 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.)
|
|
132
|
-
|
|
133
|
-
To do this, we will need to use the `jsPsych.timelineVariable()` method in a slightly different way. Instead of using it as the parameter, we are going to create a dynamic parameter using a function and place the call to `jsPsych.timelineVariable()` inside this function. This will allow us to create an HTML string that has both the image and the name. Note that there is a subtle syntax difference: there is an extra parameter when `jsPsych.timelineVariable()` is called within a function. This `true` value causes the `jsPsych.timelineVariable()` to immediately return the value of the timeline variable. In a normal context, the function `jsPsych.timelineVariable()` returns a function. This is why `jsPsych.timelineVariable()` can be used directly as a parameter even though the parameter is dynamic.
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
```javascript
|
|
137
|
-
var face_name_procedure = {
|
|
138
|
-
timeline: [
|
|
139
|
-
{
|
|
140
|
-
type: 'html-keyboard-response',
|
|
141
|
-
stimulus: '+',
|
|
142
|
-
choices: jsPsych.NO_KEYS,
|
|
143
|
-
trial_duration: 500
|
|
144
|
-
},
|
|
145
|
-
{
|
|
146
|
-
type: 'html-keyboard-response',
|
|
147
|
-
stimulus: jsPsych.timelineVariable('name'),
|
|
148
|
-
trial_duration: 1000,
|
|
149
|
-
choices: jsPsych.NO_KEYS
|
|
150
|
-
},
|
|
151
|
-
{
|
|
152
|
-
type: 'html-keyboard-response',
|
|
153
|
-
stimulus: function(){
|
|
154
|
-
var html="<img src='"+jsPsych.timelineVariable('face', true)+"'>";
|
|
155
|
-
html += "<p>"+jsPsych.timelineVariable('name', true)+"</p>";
|
|
156
|
-
return html;
|
|
157
|
-
},
|
|
158
|
-
choices: jsPsych.NO_KEYS,
|
|
159
|
-
trial_duration: 2500
|
|
160
|
-
}
|
|
161
|
-
],
|
|
162
|
-
timeline_variables: [
|
|
163
|
-
{ face: 'person-1.jpg', name: 'Alex' },
|
|
164
|
-
{ face: 'person-2.jpg', name: 'Beth' },
|
|
165
|
-
{ face: 'person-3.jpg', name: 'Chad' },
|
|
166
|
-
{ face: 'person-4.jpg', name: 'Dave' }
|
|
167
|
-
]
|
|
168
|
-
}
|
|
169
|
-
```
|
|
170
|
-
### Random orders of trials
|
|
171
|
-
|
|
172
|
-
If we want to randomize the order of the trials, we can set `randomize_order` to `true`.
|
|
173
|
-
|
|
174
|
-
```javascript
|
|
175
|
-
var face_name_procedure = {
|
|
176
|
-
// timeline parameter hidden to save space ...
|
|
177
|
-
timeline_variables: [
|
|
178
|
-
{ face: 'person-1.jpg', name: 'Alex' },
|
|
179
|
-
{ face: 'person-2.jpg', name: 'Beth' },
|
|
180
|
-
{ face: 'person-3.jpg', name: 'Chad' },
|
|
181
|
-
{ face: 'person-4.jpg', name: 'Dave' }
|
|
182
|
-
],
|
|
183
|
-
randomize_order: true
|
|
184
|
-
}
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
### Repeating trials
|
|
188
|
-
|
|
189
|
-
If we want to repeat the set of trials multiple times, then we can set `repetitions` to an integer. If `randomize_order` is also `true`, the order will re-randomize before every repetition.
|
|
190
|
-
|
|
191
|
-
```javascript
|
|
192
|
-
var face_name_procedure = {
|
|
193
|
-
// timeline parameter hidden to save space ...
|
|
194
|
-
timeline_variables: [
|
|
195
|
-
{ face: 'person-1.jpg', name: 'Alex' },
|
|
196
|
-
{ face: 'person-2.jpg', name: 'Beth' },
|
|
197
|
-
{ face: 'person-3.jpg', name: 'Chad' },
|
|
198
|
-
{ face: 'person-4.jpg', name: 'Dave' }
|
|
199
|
-
],
|
|
200
|
-
randomize_order: true,
|
|
201
|
-
repetitions: 3
|
|
202
|
-
}
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
### Sampling methods
|
|
206
|
-
|
|
207
|
-
There are also a set of 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
|
|
208
|
-
|
|
209
|
-
* `"with-replacement"`: Sample `size` items from the timeline variables with the possibility of choosing the same item multiple time.
|
|
210
|
-
* `"without-replacement"`: Sample `size` itesm from timeline variables, with each item being selected a maximum of 1 time.
|
|
211
|
-
* `"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.
|
|
212
|
-
* `"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.
|
|
213
|
-
* `"custom"`: Write a function that returns a custom order of the timeline variables.
|
|
214
|
-
|
|
215
|
-
#### Sampling with replacement
|
|
216
|
-
```javascript
|
|
217
|
-
var face_name_procedure = {
|
|
218
|
-
// timeline parameter hidden to save space ...
|
|
219
|
-
timeline_variables: [
|
|
220
|
-
{ face: 'person-1.jpg', name: 'Alex' },
|
|
221
|
-
{ face: 'person-2.jpg', name: 'Beth' },
|
|
222
|
-
{ face: 'person-3.jpg', name: 'Chad' },
|
|
223
|
-
{ face: 'person-4.jpg', name: 'Dave' }
|
|
224
|
-
],
|
|
225
|
-
sample: {
|
|
226
|
-
type: 'with-replacement',
|
|
227
|
-
size: 10, // 10 trials, with replacement
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
#### Sampling with replacement, unequal probabilities
|
|
233
|
-
```javascript
|
|
234
|
-
var face_name_procedure = {
|
|
235
|
-
// timeline parameter hidden to save space ...
|
|
236
|
-
timeline_variables: [
|
|
237
|
-
{ face: 'person-1.jpg', name: 'Alex' },
|
|
238
|
-
{ face: 'person-2.jpg', name: 'Beth' },
|
|
239
|
-
{ face: 'person-3.jpg', name: 'Chad' },
|
|
240
|
-
{ face: 'person-4.jpg', name: 'Dave' }
|
|
241
|
-
],
|
|
242
|
-
sample: {
|
|
243
|
-
type: 'with-replacement',
|
|
244
|
-
size: 10, // 10 trials, with replacement
|
|
245
|
-
weights: [3, 1, 1, 1], // The Alex trial is three times as likely to be sampled as the others.
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
#### Sampling without replacement
|
|
251
|
-
```javascript
|
|
252
|
-
var face_name_procedure = {
|
|
253
|
-
// timeline parameter hidden to save space ...
|
|
254
|
-
timeline_variables: [
|
|
255
|
-
{ face: 'person-1.jpg', name: 'Alex' },
|
|
256
|
-
{ face: 'person-2.jpg', name: 'Beth' },
|
|
257
|
-
{ face: 'person-3.jpg', name: 'Chad' },
|
|
258
|
-
{ face: 'person-4.jpg', name: 'Dave' }
|
|
259
|
-
],
|
|
260
|
-
sample: {
|
|
261
|
-
type: 'without-replacement',
|
|
262
|
-
size: 3, // 3 trials, without replacement
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
#### Repeating each trial a fixed number of times in a random order
|
|
268
|
-
```javascript
|
|
269
|
-
var face_name_procedure = {
|
|
270
|
-
// timeline parameter hidden to save space ...
|
|
271
|
-
timeline_variables: [
|
|
272
|
-
{ face: 'person-1.jpg', name: 'Alex' },
|
|
273
|
-
{ face: 'person-2.jpg', name: 'Beth' },
|
|
274
|
-
{ face: 'person-3.jpg', name: 'Chad' },
|
|
275
|
-
{ face: 'person-4.jpg', name: 'Dave' }
|
|
276
|
-
],
|
|
277
|
-
sample: {
|
|
278
|
-
type: 'fixed-repetitions',
|
|
279
|
-
size: 3, // 3 repetitions of each trial, 12 total trials, order is randomized.
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
#### Alternating groups
|
|
285
|
-
```javascript
|
|
286
|
-
var face_name_procedure = {
|
|
287
|
-
// timeline parameter hidden to save space ...
|
|
288
|
-
timeline_variables: [
|
|
289
|
-
{ face: 'person-1.jpg', name: 'Alex' },
|
|
290
|
-
{ face: 'person-2.jpg', name: 'Beth' },
|
|
291
|
-
{ face: 'person-3.jpg', name: 'Chad' },
|
|
292
|
-
{ face: 'person-4.jpg', name: 'Dave' }
|
|
293
|
-
],
|
|
294
|
-
sample: {
|
|
295
|
-
type: 'alternate-groups',
|
|
296
|
-
groups: [[0,2],[1,3]], // Alex and Chad are in group 1. Beth and Dave are in group 2.
|
|
297
|
-
randomize_group_order: false // The first trial will be an item from group 1.
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
#### Custom sampling function
|
|
303
|
-
```javascript
|
|
304
|
-
var face_name_procedure = {
|
|
305
|
-
// timeline parameter hidden to save space ...
|
|
306
|
-
timeline_variables: [
|
|
307
|
-
{ face: 'person-1.jpg', name: 'Alex' },
|
|
308
|
-
{ face: 'person-2.jpg', name: 'Beth' },
|
|
309
|
-
{ face: 'person-3.jpg', name: 'Chad' },
|
|
310
|
-
{ face: 'person-4.jpg', name: 'Dave' }
|
|
311
|
-
],
|
|
312
|
-
sample: {
|
|
313
|
-
type: 'custom',
|
|
314
|
-
fn: function(t){
|
|
315
|
-
// the first parameter to this function call is an array of integers
|
|
316
|
-
// from 0 to n-1, where n is the number of trials.
|
|
317
|
-
// the method needs to return an array of integers specifying the order
|
|
318
|
-
// that the trials should be executed. this array does not need to
|
|
319
|
-
// contain all of the integers.
|
|
320
|
-
|
|
321
|
-
return t.reverse(); // show the trials in the reverse order
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
## Looping timelines
|
|
328
|
-
|
|
329
|
-
Any timeline can be looped using the `loop_function` option. The loop function should be a function that evaluates to `true` if the timeline should repeat, and `false` if the timeline should end. It receives a single parameter: 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.
|
|
330
|
-
|
|
331
|
-
```javascript
|
|
332
|
-
var trial = {
|
|
333
|
-
type: 'html-keyboard-response',
|
|
334
|
-
stimulus: 'This trial is in a loop. Press R to repeat this trial, or C to continue.'
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
var loop_node = {
|
|
338
|
-
timeline: [trial],
|
|
339
|
-
loop_function: function(data){
|
|
340
|
-
if(jsPsych.pluginAPI.convertKeyCharacterToKeyCode('r') == data.values()[0].key_press){
|
|
341
|
-
return true;
|
|
342
|
-
} else {
|
|
343
|
-
return false;
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
```
|
|
348
|
-
|
|
349
|
-
## Conditional timelines
|
|
350
|
-
|
|
351
|
-
A timeline can be skipped based on the evaluation of a function using 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 the timeline is about to run the first trial.
|
|
352
|
-
|
|
353
|
-
```javascript
|
|
354
|
-
var pre_if_trial = {
|
|
355
|
-
type: 'html-keyboard-response',
|
|
356
|
-
stimulus: 'The next trial is in a conditional statement. Press S to skip it, or V to view it.'
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
var if_trial = {
|
|
360
|
-
type: 'html-keyboard-response',
|
|
361
|
-
stimulus: 'You chose to view the trial. Press any key to continue.'
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
var if_node = {
|
|
365
|
-
timeline: [if_trial],
|
|
366
|
-
conditional_function: function(){
|
|
367
|
-
// get the data from the previous trial,
|
|
368
|
-
// and check which key was pressed
|
|
369
|
-
var data = jsPsych.data.get().last(1).values()[0];
|
|
370
|
-
if(data.key_press == jsPsych.pluginAPI.convertKeyCharacterToKeyCode('s')){
|
|
371
|
-
return false;
|
|
372
|
-
} else {
|
|
373
|
-
return true;
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
var after_if_trial = {
|
|
379
|
-
type: 'html-keyboard-response',
|
|
380
|
-
stimulus: 'This is the trial after the conditional.'
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
jsPsych.init({
|
|
384
|
-
timeline: [pre_if_trial, if_node, after_if_trial],
|
|
385
|
-
on_finish: function(){jsPsych.data.displayData(); }
|
|
386
|
-
});
|
|
387
|
-
```
|
package/docs/overview/trial.md
DELETED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
# Advanced Options for Trials
|
|
2
|
-
|
|
3
|
-
The parameters available for a trial depend primarily on what plugin is used for the trial. However, there are several options that do not depend on the particular plugin; they are available for all trials.
|
|
4
|
-
|
|
5
|
-
## The data parameter
|
|
6
|
-
|
|
7
|
-
The `data` parameter enables tagging the trial with additional properties. 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 should be an object that contains key-value pairs.
|
|
8
|
-
|
|
9
|
-
A simple example is the [Flanker Task](https://en.wikipedia.org/wiki/Eriksen_flanker_task). In this experiment, participants respond to the direction of an arrow, 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 (<<><<).
|
|
10
|
-
|
|
11
|
-
A trial for the Flanker Task written with jsPsych might look like this:
|
|
12
|
-
|
|
13
|
-
```javascript
|
|
14
|
-
var trial = {
|
|
15
|
-
type: 'html-keyboard-response',
|
|
16
|
-
stimulus: '<<<<<',
|
|
17
|
-
choices: ['f','j'],
|
|
18
|
-
data: {
|
|
19
|
-
stimulus_type: 'congruent',
|
|
20
|
-
target_direction: 'left'
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
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`.
|
|
26
|
-
|
|
27
|
-
## Inter-trial interval
|
|
28
|
-
|
|
29
|
-
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 `jsPsych.init()`.
|
|
30
|
-
|
|
31
|
-
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.
|
|
32
|
-
|
|
33
|
-
```javascript
|
|
34
|
-
var trial = {
|
|
35
|
-
type: 'html-keyboard-response',
|
|
36
|
-
stimulus: 'There will be a 1.5 second blank screen after this trial.',
|
|
37
|
-
post_trial_gap: 1500
|
|
38
|
-
}
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## The on_start event
|
|
42
|
-
|
|
43
|
-
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 event handler can therefore be used to alter the trial based on the state of the experiment, among other uses.
|
|
44
|
-
|
|
45
|
-
```javascript
|
|
46
|
-
var trial = {
|
|
47
|
-
type: 'html-keyboard-response',
|
|
48
|
-
stimulus: '<<<<<',
|
|
49
|
-
choices: ['f','j'],
|
|
50
|
-
data: {
|
|
51
|
-
stimulus_type: 'congruent',
|
|
52
|
-
target_direction: 'left'
|
|
53
|
-
},
|
|
54
|
-
on_start: function(trial){
|
|
55
|
-
trial.stimulus = '<<><<';
|
|
56
|
-
trial.data.stimulus_type = 'incongruent';
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
## The on_finish event
|
|
62
|
-
|
|
63
|
-
After a trial is completed, there is an opportunity to run an arbitrary function through the `on_finish` event handler. This event handler is passed a single argument containing an *editable* copy of the data recorded for that trial. This event handler can therefore be used to update the state of the experiment based on the data collected or modify the data collected.
|
|
64
|
-
|
|
65
|
-
This 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` event could add a new property `correct`.
|
|
66
|
-
|
|
67
|
-
```javascript
|
|
68
|
-
var trial = {
|
|
69
|
-
type: 'html-keyboard-response',
|
|
70
|
-
stimulus: '<<<<<',
|
|
71
|
-
choices: ['f','j'],
|
|
72
|
-
data: {
|
|
73
|
-
stimulus_type: 'congruent',
|
|
74
|
-
target_direction: 'left'
|
|
75
|
-
},
|
|
76
|
-
on_finish: function(data){
|
|
77
|
-
if(data.key_press == 70){// 70 is the numeric code for f
|
|
78
|
-
data.correct = true; // can add property correct by modify data object directly
|
|
79
|
-
} else {
|
|
80
|
-
data.correct = false;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
## The on_load event
|
|
87
|
-
|
|
88
|
-
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.
|
|
89
|
-
|
|
90
|
-
#### Sample use
|
|
91
|
-
```javascript
|
|
92
|
-
var trial = {
|
|
93
|
-
type: 'image-keyboard-response',
|
|
94
|
-
stimulus: 'imgA.png',
|
|
95
|
-
on_load: function() {
|
|
96
|
-
console.log('The trial just finished loading.');
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
## Dynamic parameters
|
|
102
|
-
|
|
103
|
-
Most plugins allow parameters to be functions. In a typical declaration of a jsPsych trial, parameters have to be 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. When functions are used as parameters for a block of trials, the function is evaluated at the start of each trial, and the return value of the function is used as the parameter. This enables dynamic updating of the parameter based on data that a subject has generated.
|
|
104
|
-
|
|
105
|
-
Here is a sketch of how this functionality could be used to display feedback to a subject in the Flanker Task.
|
|
106
|
-
|
|
107
|
-
```javascript
|
|
108
|
-
|
|
109
|
-
var timeline = [];
|
|
110
|
-
|
|
111
|
-
var trial = {
|
|
112
|
-
type: 'html-keyboard-response',
|
|
113
|
-
stimulus: '<<<<<',
|
|
114
|
-
choices: ['f','j'],
|
|
115
|
-
data: {
|
|
116
|
-
stimulus_type: 'congruent',
|
|
117
|
-
target_direction: 'left'
|
|
118
|
-
},
|
|
119
|
-
on_finish: function(data){
|
|
120
|
-
if(data.key_press == 70){// 70 is the numeric code for f
|
|
121
|
-
data.correct = true; // can add property correct by modify data object directly
|
|
122
|
-
} else {
|
|
123
|
-
data.correct = false;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
var feedback = {
|
|
129
|
-
type: 'html-keyboard-response',
|
|
130
|
-
stimulus: function(){
|
|
131
|
-
var last_trial_correct = jsPsych.data.get().last(1).values()[0].correct;
|
|
132
|
-
if(last_trial_correct){
|
|
133
|
-
return "<p>Correct!</p>";
|
|
134
|
-
} else {
|
|
135
|
-
return "<p>Wrong.</p>"
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
timeline.push(trial, feedback);
|
|
141
|
-
|
|
142
|
-
```
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
# Creating a new plugin
|
|
2
|
-
|
|
3
|
-
Creating new plugins is the way to add new kinds of tasks to jsPsych. A task can be virtually any kind of activity. If it can be implemented in JavaScript, then it almost certainly can be turned into a plugin.
|
|
4
|
-
|
|
5
|
-
## What's in a plugin file?
|
|
6
|
-
|
|
7
|
-
Plugin files follow a specific template. Adherence to the template is what allows jsPsych to run a plugin without knowing anything about what the plugin is doing. What makes plugins so flexible is that the template imposes very few requirements on the code. Here's what an empty plugin template looks like:
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
jsPsych.plugins['plugin-name'] = (function(){
|
|
11
|
-
|
|
12
|
-
var plugin = {};
|
|
13
|
-
|
|
14
|
-
plugin.info = {
|
|
15
|
-
name: 'plugin-name',
|
|
16
|
-
parameters: {
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
plugin.trial = function(display_element, trial){
|
|
21
|
-
jsPsych.finishTrial();
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return plugin;
|
|
25
|
-
|
|
26
|
-
})();
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
This plugin will work! It defines a plugin called 'plugin-name', and it does absolutely nothing. However, it won't break the experiment, and jsPsych will understand that this is a valid plugin.
|
|
30
|
-
|
|
31
|
-
Let's examine it in more detail.
|
|
32
|
-
|
|
33
|
-
The overall structure of the plugin is defined using a module JavaScript design pattern. This pattern uses a technique called an anonymous closure. This is why the first line has `(function(){` and the last line is `})();`. The details aren't important, but if you want to learn more about it, [this is a nice overview](http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html). The reason this pattern is useful is because it allows for persistent state and private scope. In other words, the plugin is isolated and can't be altered by other plugins.
|
|
34
|
-
|
|
35
|
-
The module, created by the `(function(){` `})();` expressions, contains an object called `plugin` that has two properties, `info` and `trial`. The `plugin` object is returned at the end of the module, which is what assigns the defined properties of `plugin` to `jsPsych['plugin-name']`.
|
|
36
|
-
|
|
37
|
-
### plugin.trial
|
|
38
|
-
|
|
39
|
-
The `trial` method is responsible for running a single trial. There are two parameters that are passed into the trial method. The first, `display_element`, is the DOM element where jsPsych content is being rendered. This parameter will be an `HTMLElement`. Generally, you don't need to worry about this parameter being in the correct format, and can assume that it is an `HMTLElement` and use methods of that class. The second, `trial`, is an object containing all of the parameters specified in the corresponding TimelineNode.
|
|
40
|
-
|
|
41
|
-
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.
|
|
42
|
-
|
|
43
|
-
Of course, there are other things that you will probably want the plugin to do besides just end. Here are some examples:
|
|
44
|
-
|
|
45
|
-
#### Change the content of the display
|
|
46
|
-
|
|
47
|
-
There are a few ways to change the content of the display. The `display_element` parameter of the trial method contains the DOM element for displaying content, so you can use various JavaScript methods for interaction with the display element. A common one is to change the `innerHTML`.
|
|
48
|
-
|
|
49
|
-
```javascript
|
|
50
|
-
var html_content = '<p>This is the first paragraph</p>';
|
|
51
|
-
html_content += '<p>This is the second paragraph</p>';
|
|
52
|
-
|
|
53
|
-
display_element.innerHTML = html_content;
|
|
54
|
-
```
|
|
55
|
-
It is often appropriate to use `innerHTML` to clear the display at the end of a trial:
|
|
56
|
-
|
|
57
|
-
```javascript
|
|
58
|
-
// clear the display
|
|
59
|
-
display_element.innerHTML = '';
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
#### Write data
|
|
63
|
-
|
|
64
|
-
Plugins exist to collect data, so saving data is obviously a crucial thing to do. You can pass an object of data as the parameter to `jsPsych.finishTrial()`:
|
|
65
|
-
|
|
66
|
-
```javascript
|
|
67
|
-
var data = {
|
|
68
|
-
correct: true,
|
|
69
|
-
rt: 350
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
jsPsych.finishTrial(data)
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
The data recorded will be that `correct` is `true` and that `rt` is `350`. Additional data for the trial will also be collected automatically by the jsPsych library.
|
|
76
|
-
|
|
77
|
-
## The plugin template
|
|
78
|
-
|
|
79
|
-
An empty plugin template is included in the `plugins/template` folder.
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
# jspsych-animation
|
|
2
|
-
|
|
3
|
-
This plugin displays a sequence of images at a fixed frame rate. The sequence can be looped a specified number of times. The subject is free to respond at any point during the animation, and the time of the response is recorded.
|
|
4
|
-
|
|
5
|
-
## Parameters
|
|
6
|
-
|
|
7
|
-
In addition to the [parameters available in all plugins](overview.md#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.
|
|
8
|
-
|
|
9
|
-
Parameter | Type | Default Value | Description
|
|
10
|
-
----------|------|---------------|------------
|
|
11
|
-
stimuli | array | *undefined* | Each element of the array is a path to an image file.
|
|
12
|
-
frame_time | numeric | 250 | How long to display each image (in milliseconds).
|
|
13
|
-
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.
|
|
14
|
-
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.
|
|
15
|
-
choices | array of keycodes | `jsPsych.ALL_KEYS` | This array contains the keys that the subject is allowed to press in order to respond to the stimulus. Keys can be specified as their [numeric key code](http://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes) or as characters (e.g., `'a'`, `'q'`). The default value of `jsPsych.ALL_KEYS` means that all keys will be accepted as valid responses. Specifying `jsPsych.NO_KEYS` will mean that no responses are allowed.
|
|
16
|
-
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 subject is supposed to take (e.g., which key(s) to press).
|
|
17
|
-
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.
|
|
18
|
-
|
|
19
|
-
## Data Generated
|
|
20
|
-
|
|
21
|
-
In addition to the [default data collected by all plugins](overview.md#data-collected-by-plugins), this plugin collects the following data for each trial.
|
|
22
|
-
|
|
23
|
-
Name | Type | Value
|
|
24
|
-
-----|------|------
|
|
25
|
-
animation_sequence | JSON | An array, encoded in JSON format. Each element of the array 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.
|
|
26
|
-
responses | JSON | An array, encoded in JSON format. Each element of the array is an object representing a response given by the subject. 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.
|
|
27
|
-
|
|
28
|
-
## Examples
|
|
29
|
-
|
|
30
|
-
#### Displaying a single sequence multiple times
|
|
31
|
-
|
|
32
|
-
```javascript
|
|
33
|
-
var animation_sequence = ["img/face_1.jpg", "img/face_2.jpg", "img/face_3.jpg", "img/face_4.jpg", "img/face_3.jpg", "img/face_2.jpg"];
|
|
34
|
-
|
|
35
|
-
var animation_trial = {
|
|
36
|
-
type: 'animation',
|
|
37
|
-
stimuli: animation_sequence,
|
|
38
|
-
sequence_reps: 3
|
|
39
|
-
};
|
|
40
|
-
```
|