jspsych 6.3.0 → 7.1.1
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 +36 -37
- 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 -734
- package/docs/core_library/jspsych-data.md +0 -589
- package/docs/core_library/jspsych-pluginAPI.md +0 -610
- package/docs/core_library/jspsych-randomization.md +0 -397
- package/docs/core_library/jspsych-turk.md +0 -102
- package/docs/extensions/extensions.md +0 -83
- package/docs/extensions/jspsych-ext-webgazer.md +0 -106
- package/docs/img/blue.png +0 -0
- package/docs/img/devtools-change-css.png +0 -0
- package/docs/img/devtools-css-errors.png +0 -0
- package/docs/img/devtools-inspect-element.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/prolific-study-completion.png +0 -0
- package/docs/img/prolific-study-link.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 -184
- package/docs/overview/data.md +0 -281
- package/docs/overview/dynamic-parameters.md +0 -147
- package/docs/overview/exclude-browser.md +0 -32
- package/docs/overview/experiment-options.md +0 -149
- package/docs/overview/eye-tracking.md +0 -237
- package/docs/overview/fullscreen.md +0 -36
- package/docs/overview/media-preloading.md +0 -369
- package/docs/overview/mturk.md +0 -77
- package/docs/overview/plugins.md +0 -320
- package/docs/overview/progress-bar.md +0 -110
- package/docs/overview/prolific.md +0 -78
- package/docs/overview/record-browser-interactions.md +0 -23
- package/docs/overview/running-experiments.md +0 -95
- package/docs/overview/style.md +0 -293
- package/docs/overview/timeline.md +0 -457
- 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 -53
- 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 -56
- 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 -48
- package/docs/plugins/jspsych-image-keyboard-response.md +0 -58
- package/docs/plugins/jspsych-image-slider-response.md +0 -54
- package/docs/plugins/jspsych-instructions.md +0 -58
- package/docs/plugins/jspsych-maxdiff.md +0 -41
- package/docs/plugins/jspsych-preload.md +0 -128
- 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 -52
- 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 -54
- package/docs/plugins/jspsych-video-keyboard-response.md +0 -50
- package/docs/plugins/jspsych-video-slider-response.md +0 -60
- package/docs/plugins/jspsych-virtual-chinrest.md +0 -105
- 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/jspsych-webgazer-calibrate.md +0 -60
- package/docs/plugins/jspsych-webgazer-init-camera.md +0 -31
- package/docs/plugins/jspsych-webgazer-validate.md +0 -43
- package/docs/plugins/list-of-plugins.md +0 -54
- package/docs/tutorials/hello-world.md +0 -162
- package/docs/tutorials/rt-task.md +0 -1334
- package/docs/tutorials/video-tutorials.md +0 -11
- package/examples/add-to-end-of-timeline.html +0 -38
- package/examples/case-sensitive-responses.html +0 -45
- package/examples/conditional-and-loop-functions.html +0 -64
- package/examples/css/jquery-ui.css +0 -1225
- package/examples/css-classes-parameter.html +0 -145
- package/examples/data-add-properties.html +0 -44
- package/examples/data-as-function.html +0 -39
- package/examples/data-from-timeline.html +0 -52
- package/examples/data-from-url.html +0 -21
- package/examples/demo-flanker.html +0 -117
- package/examples/demo-simple-rt-task.html +0 -120
- package/examples/demos/demo_1.html +0 -35
- package/examples/demos/demo_2.html +0 -50
- package/examples/demos/demo_3.html +0 -63
- package/examples/display-element-to-embed-experiment.html +0 -79
- package/examples/end-active-node.html +0 -52
- package/examples/end-experiment.html +0 -45
- 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/card.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/js/webgazer.js +0 -88886
- package/examples/jspsych-RDK.html +0 -58
- package/examples/jspsych-animation.html +0 -39
- package/examples/jspsych-audio-button-response.html +0 -58
- package/examples/jspsych-audio-keyboard-response.html +0 -68
- package/examples/jspsych-audio-slider-response.html +0 -61
- 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 -49
- package/examples/jspsych-categorize-html.html +0 -33
- package/examples/jspsych-categorize-image.html +0 -44
- package/examples/jspsych-cloze.html +0 -37
- package/examples/jspsych-free-sort.html +0 -109
- package/examples/jspsych-fullscreen.html +0 -45
- package/examples/jspsych-html-button-response.html +0 -43
- package/examples/jspsych-html-keyboard-response.html +0 -42
- package/examples/jspsych-html-slider-response.html +0 -53
- package/examples/jspsych-iat.html +0 -520
- package/examples/jspsych-image-button-response.html +0 -91
- package/examples/jspsych-image-keyboard-response.html +0 -85
- package/examples/jspsych-image-slider-response.html +0 -85
- package/examples/jspsych-instructions.html +0 -37
- package/examples/jspsych-maxdiff.html +0 -33
- package/examples/jspsych-preload.html +0 -140
- 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 -39
- 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 -65
- package/examples/jspsych-video-keyboard-response.html +0 -61
- package/examples/jspsych-video-slider-response.html +0 -63
- package/examples/jspsych-virtual-chinrest.html +0 -69
- package/examples/jspsych-visual-search-circle.html +0 -64
- package/examples/jspsych-vsl-animate-occlusion.html +0 -35
- package/examples/jspsych-vsl-grid-scene.html +0 -47
- package/examples/lexical-decision.html +0 -134
- package/examples/manual-preloading.html +0 -59
- package/examples/pause-unpause.html +0 -33
- package/examples/progress-bar.html +0 -68
- package/examples/save-trial-parameters.html +0 -98
- 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 -64
- package/examples/video/sample_video.mp4 +0 -0
- package/examples/webgazer.html +0 -162
- package/examples/webgazer_image.html +0 -60
- package/extensions/jspsych-ext-webgazer.js +0 -185
- package/jspsych.js +0 -3015
- package/license.txt +0 -21
- package/mkdocs.yml +0 -118
- package/plugins/jspsych-animation.js +0 -189
- package/plugins/jspsych-audio-button-response.js +0 -269
- package/plugins/jspsych-audio-keyboard-response.js +0 -212
- package/plugins/jspsych-audio-slider-response.js +0 -278
- 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 -478
- package/plugins/jspsych-fullscreen.js +0 -106
- 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 -327
- package/plugins/jspsych-image-keyboard-response.js +0 -263
- package/plugins/jspsych-image-slider-response.js +0 -369
- package/plugins/jspsych-instructions.js +0 -237
- package/plugins/jspsych-maxdiff.js +0 -173
- package/plugins/jspsych-preload.js +0 -345
- 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 -212
- 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 -335
- package/plugins/jspsych-video-keyboard-response.js +0 -279
- package/plugins/jspsych-video-slider-response.js +0 -351
- package/plugins/jspsych-virtual-chinrest.js +0 -471
- 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/jspsych-webgazer-calibrate.js +0 -166
- package/plugins/jspsych-webgazer-init-camera.js +0 -95
- package/plugins/jspsych-webgazer-validate.js +0 -304
- package/plugins/template/jspsych-plugin-template.js +0 -35
- package/tests/README.md +0 -7
- package/tests/jsPsych/case-sensitive-responses.test.js +0 -53
- package/tests/jsPsych/css-classes-parameter.test.js +0 -107
- 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 -606
- package/tests/jsPsych/functions-as-parameters.test.js +0 -210
- 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 -531
- package/tests/jsPsych/timelines.test.js +0 -569
- package/tests/jsPsych.data/data-csv-conversion.test.js +0 -85
- package/tests/jsPsych.data/data-json-conversion.test.js +0 -120
- package/tests/jsPsych.data/datacollection.test.js +0 -117
- 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.data/trialparameters.test.js +0 -175
- package/tests/jsPsych.extensions/extensions.test.js +0 -207
- package/tests/jsPsych.extensions/test-extension.js +0 -42
- package/tests/jsPsych.pluginAPI/pluginapi.test.js +0 -341
- package/tests/jsPsych.pluginAPI/preloads.test.js +0 -43
- package/tests/jsPsych.randomization/randomziation.test.js +0 -27
- package/tests/jsPsych.utils/utils.test.js +0 -58
- package/tests/plugins/plugin-animation.test.js +0 -34
- 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 -263
- 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 -157
- package/tests/plugins/plugin-free-sort.test.js +0 -106
- 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 -299
- package/tests/plugins/plugin-iat-image.test.js +0 -298
- package/tests/plugins/plugin-image-button-response.test.js +0 -174
- package/tests/plugins/plugin-image-keyboard-response.test.js +0 -147
- package/tests/plugins/plugin-image-slider-response.test.js +0 -174
- package/tests/plugins/plugin-instructions.test.js +0 -85
- package/tests/plugins/plugin-maxdiff.test.js +0 -39
- package/tests/plugins/plugin-preload.test.js +0 -916
- package/tests/plugins/plugin-rdk.test.js +0 -61
- 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 -109
- 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 -47
- package/tests/plugins/plugin-survey-multi-select.test.js +0 -71
- package/tests/plugins/plugin-survey-text.test.js +0 -115
- package/tests/plugins/plugin-video-button-response.test.js +0 -32
- package/tests/plugins/plugin-video-keyboard-response.test.js +0 -32
- package/tests/plugins/plugin-video-slider-response.test.js +0 -31
- 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,184 +0,0 @@
|
|
|
1
|
-
# Event-related callback functions
|
|
2
|
-
|
|
3
|
-
jsPsych offers the ability to call arbitrary functions in response to certain events occurring, like the end of a trial or when new data is saved. This page summarizes the different opportunities for callback functions and how to specify them.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## on_close
|
|
8
|
-
|
|
9
|
-
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.
|
|
10
|
-
|
|
11
|
-
#### Sample use
|
|
12
|
-
```javascript
|
|
13
|
-
jsPsych.init({
|
|
14
|
-
timeline: exp,
|
|
15
|
-
on_close: function(){
|
|
16
|
-
var data = jsPsych.data.get().json();
|
|
17
|
-
save_data_to_server(data);
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## on_data_update
|
|
25
|
-
|
|
26
|
-
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.
|
|
27
|
-
|
|
28
|
-
#### Sample use
|
|
29
|
-
```javascript
|
|
30
|
-
jsPsych.init({
|
|
31
|
-
timeline: exp,
|
|
32
|
-
on_data_update: function(data) {
|
|
33
|
-
console.log('Just added new data. The contents of the data are: '+JSON.stringify(data));
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
```
|
|
37
|
-
---
|
|
38
|
-
|
|
39
|
-
## on_finish (trial)
|
|
40
|
-
|
|
41
|
-
The `on_finish` callback can be added to any trial. The callback will trigger whenever the trial ends. The callback function will be passed a single argument, containing the data object from the trial. This data object is *editable*. Any changes made in the on_finish function will be stored in the internal data collection.
|
|
42
|
-
|
|
43
|
-
#### Sample use
|
|
44
|
-
```javascript
|
|
45
|
-
var trial = {
|
|
46
|
-
type: 'image-keyboard-response',
|
|
47
|
-
stimulus: 'imgA.png',
|
|
48
|
-
on_finish: function(data) {
|
|
49
|
-
if(jsPsych.pluginAPI.compareKeys(data.response, 'j')){
|
|
50
|
-
data.correct = true;
|
|
51
|
-
} else {
|
|
52
|
-
data.correct = false;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
```
|
|
57
|
-
---
|
|
58
|
-
|
|
59
|
-
## on_finish (experiment)
|
|
60
|
-
|
|
61
|
-
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.
|
|
62
|
-
|
|
63
|
-
#### Sample use
|
|
64
|
-
```javascript
|
|
65
|
-
jsPsych.init({
|
|
66
|
-
timeline: exp,
|
|
67
|
-
on_finish: function(data) {
|
|
68
|
-
console.log('The experiment is over! Here is all the data: '+JSON.stringify(data));
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
```
|
|
72
|
-
---
|
|
73
|
-
|
|
74
|
-
## on_load
|
|
75
|
-
|
|
76
|
-
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.
|
|
77
|
-
|
|
78
|
-
#### Sample use
|
|
79
|
-
```javascript
|
|
80
|
-
var trial = {
|
|
81
|
-
type: 'image-keyboard-response',
|
|
82
|
-
stimulus: 'imgA.png',
|
|
83
|
-
on_load: function() {
|
|
84
|
-
console.log('The trial just finished loading.');
|
|
85
|
-
}
|
|
86
|
-
};
|
|
87
|
-
```
|
|
88
|
-
---
|
|
89
|
-
|
|
90
|
-
## on_start (trial)
|
|
91
|
-
|
|
92
|
-
The `on_start` callback can be added to any trial. The callback will trigger right before the trial begins. The callback function will be passed a single argument, containing the trial object. If any of the parameters of the trial are functions or timeline variables, these will be evaluated before `on_start` is called, and the trial object will contain the evaluated value. The trial object is modifiable, and any changes made will affect the trial.
|
|
93
|
-
|
|
94
|
-
#### Sample use
|
|
95
|
-
```javascript
|
|
96
|
-
var trial = {
|
|
97
|
-
type: 'image-keyboard-response',
|
|
98
|
-
stimulus: 'imgA.png',
|
|
99
|
-
on_start: function(trial) {
|
|
100
|
-
console.log('The trial is about to start.');
|
|
101
|
-
trial.stimulus = 'imgB.png'; // this will change what stimulus is displayed in the trial
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
---
|
|
107
|
-
|
|
108
|
-
## on_timeline_finish
|
|
109
|
-
|
|
110
|
-
The `on_timeline_finish` callback can be declared in a timeline node. The callback will be triggered when the timeline ends during the experiment. If `timeline_variables`, `conditional_function`, `loop_function`, or `sample` options are used, this function will execute when all trials have finished. If a `loop_function` is used, then this `on_timeline_finish` function will be triggered before the loop function. If the `repetitions` option is used, this function will be triggered at the end of every repetition.
|
|
111
|
-
|
|
112
|
-
#### Sample use
|
|
113
|
-
```javascript
|
|
114
|
-
var procedure = {
|
|
115
|
-
timeline: [trial1, trial2],
|
|
116
|
-
timeline_variables: [
|
|
117
|
-
{ stimulus: 'person-1.jpg' },
|
|
118
|
-
{ stimulus: 'person-2.jpg' },
|
|
119
|
-
{ stimulus: 'person-3.jpg' },
|
|
120
|
-
{ stimulus: 'person-4.jpg' }
|
|
121
|
-
],
|
|
122
|
-
on_timeline_finish: function() {
|
|
123
|
-
console.log('This timeline has finished.');
|
|
124
|
-
},
|
|
125
|
-
loop_function: function() {
|
|
126
|
-
console.log('This loop function will execute after on_timeline_finish.');
|
|
127
|
-
return false;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
```
|
|
131
|
-
---
|
|
132
|
-
|
|
133
|
-
## on_timeline_start
|
|
134
|
-
|
|
135
|
-
The `on_timeline_start` callback can be declared in a timeline node. The callback will be triggered when the timeline starts during the experiment, including when `timeline_variables`, `loop_function`, or `sample` options are used. If a `conditional_function` is used, then the conditional function will execute first, and the `on_timeline_start` function will only execute if the conditional function returns `true`. If the `repetitions` option is used, this function will be triggered at the start of every repetition.
|
|
136
|
-
|
|
137
|
-
#### Sample use
|
|
138
|
-
```javascript
|
|
139
|
-
var procedure = {
|
|
140
|
-
timeline: [trial1, trial2],
|
|
141
|
-
conditional_function: function() {
|
|
142
|
-
console.log('This conditional function will execute first.')
|
|
143
|
-
return true;
|
|
144
|
-
},
|
|
145
|
-
on_timeline_start: function() {
|
|
146
|
-
console.log('This timeline has started');
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
```
|
|
150
|
-
---
|
|
151
|
-
|
|
152
|
-
## on_trial_finish
|
|
153
|
-
|
|
154
|
-
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.
|
|
155
|
-
|
|
156
|
-
#### Sample use
|
|
157
|
-
```javascript
|
|
158
|
-
jsPsych.init({
|
|
159
|
-
timeline: exp,
|
|
160
|
-
on_trial_finish: function(data) {
|
|
161
|
-
console.log('A trial just ended.');
|
|
162
|
-
console.log(JSON.stringify(data));
|
|
163
|
-
}
|
|
164
|
-
});
|
|
165
|
-
```
|
|
166
|
-
---
|
|
167
|
-
|
|
168
|
-
## on_trial_start
|
|
169
|
-
|
|
170
|
-
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.
|
|
171
|
-
|
|
172
|
-
#### Sample use
|
|
173
|
-
|
|
174
|
-
```javascript
|
|
175
|
-
var current_score = 0; // a variable that is updated throughout the experiment to keep track of the current score.
|
|
176
|
-
|
|
177
|
-
jsPsych.init({
|
|
178
|
-
timeline: exp,
|
|
179
|
-
on_trial_start: function(trial) {
|
|
180
|
-
trial.data.score_at_start_of_trial = current_score;
|
|
181
|
-
console.log('A trial just started.');
|
|
182
|
-
}
|
|
183
|
-
});
|
|
184
|
-
```
|
package/docs/overview/data.md
DELETED
|
@@ -1,281 +0,0 @@
|
|
|
1
|
-
## Data in jsPsych: permanent and non-permanent data.
|
|
2
|
-
|
|
3
|
-
There are two very different kinds of data storage: data stored in **memory** and data stored **permanently**. Data stored permanently exists even after the browser running jsPsych closes, typically in a database or in a file on a server. Data stored in memory exists only as long the browser window running jsPsych is open.
|
|
4
|
-
|
|
5
|
-
jsPsych has many features for interacting with data stored in memory, but few for permanent data storage. This is a deliberate choice, as there are dozens of ways that data could be stored permanently. jsPsych does not lock you into one particular solution. However, saving data permanently is obviously a crucial component of any experiment, and the second half of this page contains a few suggestions on how to accomplish permanent data storage.
|
|
6
|
-
|
|
7
|
-
## Storing data in jsPsych's data structure
|
|
8
|
-
|
|
9
|
-
jsPsych has a centralized collection of data that is built as the experiment runs. Each trial adds to the collection, and you can access the data with various functions, including `jsPsych.data.get()`, which returns the entire set of data.
|
|
10
|
-
|
|
11
|
-
In most cases, data collection will be automatic and hidden. Plugins save data on their own so it is not uncommon to have the only interaction with the data be at the end of the experiment when it is time to save it in a permanent manner (see sections below about how to do this). However, there are some situations in which you may want to interact with the data; in particular, you may want to store additional data that the plugins are not recording, like a subject identifier or condition assignment. You may also want to add data on a trial by trial basis. For example, in a Stroop paradigm you would want to label which trials are congruent and which are incongruent. These scenarios are explored below.
|
|
12
|
-
|
|
13
|
-
### Adding data to all trials
|
|
14
|
-
|
|
15
|
-
Often it is useful to add a piece of data to *all* of the trials in the experiment. For example, appending the subject ID to each trial. This can be done with the `jsPsych.data.addProperties()` function. Here is an example:
|
|
16
|
-
|
|
17
|
-
```javascript
|
|
18
|
-
// generate a random subject ID with 15 characters
|
|
19
|
-
var subject_id = jsPsych.randomization.randomID(15);
|
|
20
|
-
|
|
21
|
-
// pick a random condition for the subject at the start of the experiment
|
|
22
|
-
var condition_assignment = jsPsych.randomization.sampleWithoutReplacement(['conditionA', 'conditionB', 'conditionC'], 1)[0];
|
|
23
|
-
|
|
24
|
-
// record the condition assignment in the jsPsych data
|
|
25
|
-
// this adds a property called 'subject' and a property called 'condition' to every trial
|
|
26
|
-
jsPsych.data.addProperties({
|
|
27
|
-
subject: subject_id,
|
|
28
|
-
condition: condition_assignment
|
|
29
|
-
});
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
### Adding data to a particular trial or set of trials
|
|
33
|
-
|
|
34
|
-
Data can be added to a particular trial by setting the `data` parameter for the trial. The `data` parameter is an object of key-value pairs, and each pair is added to the data for that trial.
|
|
35
|
-
|
|
36
|
-
```js
|
|
37
|
-
var trial = {
|
|
38
|
-
type: 'image-keyboard-response',
|
|
39
|
-
stimulus: 'imgA.jpg',
|
|
40
|
-
data: { image_type: 'A' }
|
|
41
|
-
}
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
Data declared in this way is also saved in the trials on any nested timelines:
|
|
45
|
-
|
|
46
|
-
```js
|
|
47
|
-
var block = {
|
|
48
|
-
type: 'image-keyboard-response',
|
|
49
|
-
data: { image_type: 'A' },
|
|
50
|
-
timeline: [
|
|
51
|
-
{stimulus: 'imgA1.jpg'},
|
|
52
|
-
{stimulus: 'imgA2.jpg'}
|
|
53
|
-
]
|
|
54
|
-
}
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
The data object for a trial can also be updated in the `on_finish` event handler. You can override properties or add new ones. This is particularly useful for cases where the value depends on something that happened during the trial.
|
|
58
|
-
|
|
59
|
-
```js
|
|
60
|
-
var trial = {
|
|
61
|
-
type: 'image-keyboard-response',
|
|
62
|
-
stimulus: 'imgA.jpg',
|
|
63
|
-
on_finish: function(data){
|
|
64
|
-
if(jsPsych.pluginAPI.compareKeys(data.response, 'j')){
|
|
65
|
-
data.correct = true;
|
|
66
|
-
} else {
|
|
67
|
-
data.correct = false;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
## Aggregating and manipulating jsPsych data
|
|
74
|
-
|
|
75
|
-
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).
|
|
76
|
-
|
|
77
|
-
Here are some examples of data collection manipulation.
|
|
78
|
-
|
|
79
|
-
All data generated by the image-keyboard-response plugin:
|
|
80
|
-
```js
|
|
81
|
-
var data = jsPsych.data.get().filter({trial_type: 'image-keyboard-response'});
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
All data generated by the categorize-image plugin with a correct response:
|
|
85
|
-
```js
|
|
86
|
-
var data = jsPsych.data.get().filter({trial_type: 'categorize-image', correct: true});
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
All data with a response time between 100 and 500ms:
|
|
90
|
-
```js
|
|
91
|
-
var data = jsPsych.data.get().filterCustom(function(x){ return x.rt >= 100 && x.rt <=500 });
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
Applying filters consecutively to get all trials from a particular plugin with a response time above 100ms:
|
|
95
|
-
```js
|
|
96
|
-
var data = jsPsych.data.get().filter({trial_type: 'image-keyboard-response'}).filterCustom(function(x){ return x.rt > 100; });
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
Getting the data from the last n trials:
|
|
100
|
-
```js
|
|
101
|
-
var n = 3;
|
|
102
|
-
var data = jsPsych.data.get().last(n);
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
Getting the data from the last n trials with a correct response:
|
|
106
|
-
```js
|
|
107
|
-
var n = 3;
|
|
108
|
-
var data = jsPsych.data.get().filter({correct: true}).last(n);
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
Getting the data from the first n trials:
|
|
112
|
-
```js
|
|
113
|
-
var n = 3;
|
|
114
|
-
var data = jsPsych.data.get().first(n);
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
Counting the number of trials in a data collection:
|
|
118
|
-
```js
|
|
119
|
-
var count = jsPsych.data.get().filter({correct: true}).count();
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
Selecting all of the response times from a data collection:
|
|
123
|
-
```js
|
|
124
|
-
var response_times = jsPsych.data.get().select('rt');
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
Calculating various descriptive statistics on the response times in a data collection:
|
|
128
|
-
|
|
129
|
-
```js
|
|
130
|
-
jsPsych.data.get().select('rt').mean();
|
|
131
|
-
jsPsych.data.get().select('rt').sum();
|
|
132
|
-
jsPsych.data.get().select('rt').min();
|
|
133
|
-
jsPsych.data.get().select('rt').max();
|
|
134
|
-
jsPsych.data.get().select('rt').variance();
|
|
135
|
-
jsPsych.data.get().select('rt').sd();
|
|
136
|
-
jsPsych.data.get().select('rt').median();
|
|
137
|
-
jsPsych.data.get().select('rt').count();
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
## Storing data permanently as a file
|
|
141
|
-
|
|
142
|
-
This is one of the simplest methods for saving jsPsych data on the server that is running the experiment. It involves a short PHP script and a few lines of JavaScript code. This method will save each participant's data as a CSV file on the server. **This method will only work if you are running on a web server with PHP installed, or a local server with PHP (e.g., [XAMPP](https://www.apachefriends.org/index.html)).**
|
|
143
|
-
|
|
144
|
-
This method uses a simple PHP script to write files to the server:
|
|
145
|
-
|
|
146
|
-
```php
|
|
147
|
-
<?php
|
|
148
|
-
$post_data = json_decode(file_get_contents('php://input'), true);
|
|
149
|
-
// the directory "data" must be writable by the server
|
|
150
|
-
$name = "data/".$post_data['filename'].".csv";
|
|
151
|
-
$data = $post_data['filedata'];
|
|
152
|
-
// write the file to disk
|
|
153
|
-
file_put_contents($name, $data);
|
|
154
|
-
?>
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
The `file_put_contents($filename, $data)` method requires permission to write new files. An easy way to solve this is to create a directory on the server that will store the data and use the chmod command to give all users write permission to that directory. In the above example, the directory `data/` is used to store files.
|
|
158
|
-
|
|
159
|
-
To use the PHP script, the JavaScript that runs jsPsych needs to send the `filename` and `filedata` information. This is done through an [AJAX](http://www.w3schools.com/xml/ajax_intro.asp) call.
|
|
160
|
-
|
|
161
|
-
```javascript
|
|
162
|
-
function saveData(name, data){
|
|
163
|
-
var xhr = new XMLHttpRequest();
|
|
164
|
-
xhr.open('POST', 'write_data.php'); // 'write_data.php' is the path to the php file described above.
|
|
165
|
-
xhr.setRequestHeader('Content-Type', 'application/json');
|
|
166
|
-
xhr.send(JSON.stringify({filename: name, filedata: data}));
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// call the saveData function after the experiment is over
|
|
170
|
-
jsPsych.init({
|
|
171
|
-
// code to define the experiment structure would go here...
|
|
172
|
-
on_finish: function(){ saveData("experiment_data", jsPsych.data.get().csv()); }
|
|
173
|
-
});
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
To use this in an actual experiment, it would be important to tie the filename to some unique identifier like a subject number. Otherwise the file may be overwritten by collecting new data.
|
|
177
|
-
|
|
178
|
-
Note that, depending on file permissions, storing the CSV files this way may make them publicly accessible. One fix is to store the CSV files outside the web directory on the server. This requires changing the path in the PHP script above from `/data` to a non-accessible folder. You should only use this solution if you have access to more than just the web directory on your server.
|
|
179
|
-
|
|
180
|
-
## Storing data permanently in a MySQL database
|
|
181
|
-
|
|
182
|
-
The ideal solution for storing data generated by jsPsych is to write it to a database.
|
|
183
|
-
|
|
184
|
-
There are dozens of database options. MySQL is one of the most popular [relational databases](http://en.wikipedia.org/wiki/Relational_database), is free to use, and relatively easy [to install](https://www.google.com/search?q=how+to+install+mysql). This code will assume that you have a MySQL database installed on your server that is hosting the jsPsych experiment, and that your server is able to execute PHP code. If you are trying to run on a local machine, you'll need to install a local server environment like [XAMPP](https://www.apachefriends.org/index.html).
|
|
185
|
-
|
|
186
|
-
You'll need two PHP scripts. The first is a configuration file for your database. Save it as `database_config.php` on your server. Within this file are configuration options for the database. You'll need to change these according to how you have configured your MySQL installation.
|
|
187
|
-
|
|
188
|
-
```php
|
|
189
|
-
<?php
|
|
190
|
-
$servername = "localhost";
|
|
191
|
-
$port = 3306;
|
|
192
|
-
$username = "username";
|
|
193
|
-
$password = "password";
|
|
194
|
-
$dbname = "database";
|
|
195
|
-
$table = "tablename";
|
|
196
|
-
?>
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
The second PHP file will write data to the database. This script reads the database to discover what columns are in the table, and then only allows data to be entered in that matches those columns. This is a security feature. Save this file as `write_data.php` on your server.
|
|
200
|
-
|
|
201
|
-
```php
|
|
202
|
-
<?php
|
|
203
|
-
|
|
204
|
-
// this path should point to your configuration file.
|
|
205
|
-
include('database_config.php');
|
|
206
|
-
|
|
207
|
-
$data_array = json_decode(file_get_contents('php://input'), true);
|
|
208
|
-
|
|
209
|
-
try {
|
|
210
|
-
$conn = new PDO("mysql:host=$servername;port=$port;dbname=$dbname", $username, $password);
|
|
211
|
-
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
|
212
|
-
// First stage is to get all column names from the table and store
|
|
213
|
-
// them in $col_names array.
|
|
214
|
-
$stmt = $conn->prepare("SHOW COLUMNS FROM `$table`");
|
|
215
|
-
$stmt->execute();
|
|
216
|
-
$col_names = array();
|
|
217
|
-
while($row = $stmt->fetchColumn()) {
|
|
218
|
-
$col_names[] = $row;
|
|
219
|
-
}
|
|
220
|
-
// Second stage is to create prepared SQL statement using the column
|
|
221
|
-
// names as a guide to what values might be in the JSON.
|
|
222
|
-
// If a value is missing from a particular trial, then NULL is inserted
|
|
223
|
-
$sql = "INSERT INTO $table VALUES(";
|
|
224
|
-
for($i = 0; $i < count($col_names); $i++){
|
|
225
|
-
$name = $col_names[$i];
|
|
226
|
-
$sql .= ":$name";
|
|
227
|
-
if($i != count($col_names)-1){
|
|
228
|
-
$sql .= ", ";
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
$sql .= ");";
|
|
232
|
-
$insertstmt = $conn->prepare($sql);
|
|
233
|
-
for($i=0; $i < count($data_array); $i++){
|
|
234
|
-
for($j = 0; $j < count($col_names); $j++){
|
|
235
|
-
$colname = $col_names[$j];
|
|
236
|
-
if(!isset($data_array[$i][$colname])){
|
|
237
|
-
$insertstmt->bindValue(":$colname", null, PDO::PARAM_NULL);
|
|
238
|
-
} else {
|
|
239
|
-
$insertstmt->bindValue(":$colname", $data_array[$i][$colname]);
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
$insertstmt->execute();
|
|
243
|
-
}
|
|
244
|
-
echo '{"success": true}';
|
|
245
|
-
} catch(PDOException $e) {
|
|
246
|
-
echo '{"success": false, "message": ' . $e->getMessage();
|
|
247
|
-
}
|
|
248
|
-
$conn = null;
|
|
249
|
-
?>
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
To send the data, we use an AJAX request in JavaScript.
|
|
253
|
-
```JavaScript
|
|
254
|
-
function saveData() {
|
|
255
|
-
var xhr = new XMLHttpRequest();
|
|
256
|
-
xhr.open('POST', 'write_data.php'); // change 'write_data.php' to point to php script.
|
|
257
|
-
xhr.setRequestHeader('Content-Type', 'application/json');
|
|
258
|
-
xhr.onload = function() {
|
|
259
|
-
if(xhr.status == 200){
|
|
260
|
-
var response = JSON.parse(xhr.responseText);
|
|
261
|
-
console.log(response.success);
|
|
262
|
-
}
|
|
263
|
-
};
|
|
264
|
-
xhr.send(jsPsych.data.get().json());
|
|
265
|
-
}
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
You can call the `saveData()` function using the `on_finish` handler for the experiment, or by using the `call-function` plugin.
|
|
269
|
-
|
|
270
|
-
```javascript
|
|
271
|
-
// with on_finish handler
|
|
272
|
-
jsPsych.init({
|
|
273
|
-
on_finish: saveData
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
// with call-function plugin
|
|
277
|
-
timeline.push({
|
|
278
|
-
type: 'call-function',
|
|
279
|
-
func: saveData
|
|
280
|
-
});
|
|
281
|
-
```
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
# Dynamic parameters
|
|
2
|
-
|
|
3
|
-
Most trial parameters can also be specified as functions. In a typical declaration of a jsPsych trial, parameters are known at the start of the experiment. This makes it impossible to alter the content of the trial based on the outcome of previous trials. However, **when functions are used as the parameter value, the function is evaluated right before the trial starts, and the return value of the function is used as the parameter value for that trial**. This enables dynamic updating of the parameter based on data that a subject has generated or any other information that you do not know in advance.
|
|
4
|
-
|
|
5
|
-
## Examples
|
|
6
|
-
|
|
7
|
-
### Providing Feedback
|
|
8
|
-
|
|
9
|
-
Here is a sketch of how this functionality could be used to display feedback to a subject in the Flanker Task.
|
|
10
|
-
|
|
11
|
-
```javascript
|
|
12
|
-
|
|
13
|
-
var timeline = [];
|
|
14
|
-
|
|
15
|
-
var trial = {
|
|
16
|
-
type: 'html-keyboard-response',
|
|
17
|
-
stimulus: '<<<<<',
|
|
18
|
-
choices: ['f','j'],
|
|
19
|
-
data: {
|
|
20
|
-
stimulus_type: 'congruent',
|
|
21
|
-
target_direction: 'left'
|
|
22
|
-
},
|
|
23
|
-
on_finish: function(data){
|
|
24
|
-
// Score the response as correct or incorrect.
|
|
25
|
-
if(jsPsych.pluginAPI.compareKeys(data.response, "f")){
|
|
26
|
-
data.correct = true;
|
|
27
|
-
} else {
|
|
28
|
-
data.correct = false;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
var feedback = {
|
|
34
|
-
type: 'html-keyboard-response',
|
|
35
|
-
stimulus: function(){
|
|
36
|
-
// The feedback stimulus is a dynamic parameter because we can't know in advance whether
|
|
37
|
-
// the stimulus should be 'correct' or 'incorrect'.
|
|
38
|
-
// Instead, this function will check the accuracy of the last response and use that information to set
|
|
39
|
-
// the stimulus value on each trial.
|
|
40
|
-
var last_trial_correct = jsPsych.data.get().last(1).values()[0].correct;
|
|
41
|
-
if(last_trial_correct){
|
|
42
|
-
return "<p>Correct!</p>"; // the parameter value has to be returned from the function
|
|
43
|
-
} else {
|
|
44
|
-
return "<p>Wrong.</p>"; // the parameter value has to be returned from the function
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
timeline.push(trial, feedback);
|
|
50
|
-
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
### Randomizing a parameter value
|
|
54
|
-
|
|
55
|
-
Here's an example of using a dynamic parameter to randomize the inter-trial interval (ITI) duration. This time, the dynamic parameter is created using a named function instead of an anonymous function.
|
|
56
|
-
|
|
57
|
-
```js
|
|
58
|
-
var random_duration = function() {
|
|
59
|
-
var rand_dur = jsPsych.randomization.sampleWithoutReplacement([500,600,700,800],1)[0];
|
|
60
|
-
return rand_dur;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
var trial = {
|
|
64
|
-
type: 'html-keyboard-response'
|
|
65
|
-
stimulus: '+',
|
|
66
|
-
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)
|
|
67
|
-
}
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
### Storing changing variables in the data
|
|
71
|
-
|
|
72
|
-
The trial's `data` parameter can be also function, which is useful for when you want to save information to the data that can change during the experiment. For example, if you have a global variable called `current_difficulty` that tracks the difficulty level in an adaptive task, you can save the current value of this variable to the trial data like this:
|
|
73
|
-
|
|
74
|
-
```js
|
|
75
|
-
var current_difficulty; // value changes during the experiment
|
|
76
|
-
|
|
77
|
-
var trial = {
|
|
78
|
-
type: 'survey-text',
|
|
79
|
-
questions: [{prompt: "Please enter your response."}]
|
|
80
|
-
data: function() {
|
|
81
|
-
return {difficulty: current_difficulty};
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
It's also possible to use a function for any of the _individual properties_ in the trial's `data` object, for instance if you want to combine static and dynamic information in the data:
|
|
87
|
-
|
|
88
|
-
```js
|
|
89
|
-
var trial = {
|
|
90
|
-
type: 'survey-text',
|
|
91
|
-
questions: [{prompt: "Please enter your response."}]
|
|
92
|
-
data: {
|
|
93
|
-
difficulty: function() {
|
|
94
|
-
return current_difficulty; // the difficulty value changes during the experiment
|
|
95
|
-
},
|
|
96
|
-
task_part: 'recall', // this part of the data is always the same
|
|
97
|
-
block_number: 1
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### Nested Parameters
|
|
103
|
-
|
|
104
|
-
Dyanmic parameters work the same way with nested parameters, which are parameters that contain one or more sets of other parameters. For instance, many survey-* plugins have a `questions` parameter that is a nested parameter: it is an array that contains the parameters for one or more questions on the page. To make the `questions` parameter dynamic, you can use a function that returns the array with all of the parameters for each question:
|
|
105
|
-
|
|
106
|
-
```js
|
|
107
|
-
var subject_id; // value is set during the experiment
|
|
108
|
-
|
|
109
|
-
var trial = {
|
|
110
|
-
type: 'survey-text',
|
|
111
|
-
questions: function(){
|
|
112
|
-
var questions_array = [
|
|
113
|
-
{prompt: "Hi "+subject_id+"! What's your favorite city?", required: true, name: 'fav_city'},
|
|
114
|
-
{prompt: "What is your favorite fruit?", required: true, name: 'fav_fruit'},
|
|
115
|
-
];
|
|
116
|
-
return questions_array;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
You can also use a function for any of the _individual parameters_ inside of a nested parameter.
|
|
122
|
-
|
|
123
|
-
```js
|
|
124
|
-
var trial = {
|
|
125
|
-
type: 'survey-text',
|
|
126
|
-
questions: [
|
|
127
|
-
{
|
|
128
|
-
prompt: function() {
|
|
129
|
-
// this question prompt is dynamic - the text that is shown
|
|
130
|
-
// will change based on the participant's earlier response
|
|
131
|
-
var favorite_city = jsPsych.data.getLastTrialData().values()[0].response.fav_city;
|
|
132
|
-
var text = "Earlier you said your favorite city is "+favorite_city+". What do you like most about "+favorite_city+"?"
|
|
133
|
-
return text;
|
|
134
|
-
},
|
|
135
|
-
required: true,
|
|
136
|
-
rows: 40,
|
|
137
|
-
columns: 10
|
|
138
|
-
},
|
|
139
|
-
{ prompt: "What is your favorite fruit?", required: true, name: 'fav_fruit' }
|
|
140
|
-
]
|
|
141
|
-
}
|
|
142
|
-
```
|
|
143
|
-
## When dynamic parameters can't be used
|
|
144
|
-
|
|
145
|
-
Note that if the plugin *expects* the value of a given parameter to be a function, then this function *will not* be evaluated at the start of the trial. This is because some plugins allow the researcher to specify functions that should be called at some point during the trial. Some examples of this include the `stimulus` parameter in the canvas-* plugins, the `mistake_fn` parameter in the cloze plugin, and the `stim_function` parameter in the reconstruction plugin. If you want to check whether this is the case for a particular plugin and parameter, then the parameter's `type` in the `plugin.info` section of the plugin file. If the parameter type is `jsPsych.plugins.parameterType.FUNCTION`, then this parameter must be a function and it will not be executed before the trial starts.
|
|
146
|
-
|
|
147
|
-
Even though function evaluation doesn't work the same way with these parameters, the fact that the parameters are functions means that you can get the same dynamic functionality. These functions are typically evaluated at some point during the trial, so you still get updates to values within the function during the trial.
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# Exclude Participants Based on Browser Features
|
|
2
|
-
|
|
3
|
-
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.
|
|
4
|
-
|
|
5
|
-
Current exclusion options:
|
|
6
|
-
* Minimum browser width & height
|
|
7
|
-
* Support for the WebAudio API
|
|
8
|
-
|
|
9
|
-
## Examples
|
|
10
|
-
|
|
11
|
-
#### Exclude browsers that are not at least 800x600 pixels
|
|
12
|
-
|
|
13
|
-
```javascript
|
|
14
|
-
jsPsych.init({
|
|
15
|
-
timeline: exp,
|
|
16
|
-
exclusions: {
|
|
17
|
-
min_width: 800,
|
|
18
|
-
min_height: 600
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
#### Exclude browsers that do not have access to the WebAudio API
|
|
24
|
-
|
|
25
|
-
```javascript
|
|
26
|
-
jsPsych.init({
|
|
27
|
-
timeline: exp,
|
|
28
|
-
exclusions: {
|
|
29
|
-
audio: true
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
```
|