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.
Files changed (397) hide show
  1. package/README.md +36 -37
  2. package/css/jspsych.css +39 -39
  3. package/dist/JsPsych.d.ts +112 -0
  4. package/dist/TimelineNode.d.ts +34 -0
  5. package/dist/index.browser.js +3164 -0
  6. package/dist/index.browser.js.map +1 -0
  7. package/dist/index.browser.min.js +2 -0
  8. package/dist/index.browser.min.js.map +1 -0
  9. package/dist/index.cjs +3158 -0
  10. package/dist/index.cjs.map +1 -0
  11. package/dist/index.d.ts +11 -0
  12. package/dist/index.js +3152 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/migration.d.ts +3 -0
  15. package/dist/modules/data/DataCollection.d.ts +45 -0
  16. package/dist/modules/data/DataColumn.d.ts +15 -0
  17. package/dist/modules/data/index.d.ts +25 -0
  18. package/dist/modules/data/utils.d.ts +3 -0
  19. package/dist/modules/extensions.d.ts +22 -0
  20. package/dist/modules/plugin-api/HardwareAPI.d.ts +15 -0
  21. package/dist/modules/plugin-api/KeyboardListenerAPI.d.ts +34 -0
  22. package/dist/modules/plugin-api/MediaAPI.d.ts +27 -0
  23. package/dist/modules/plugin-api/SimulationAPI.d.ts +41 -0
  24. package/dist/modules/plugin-api/TimeoutAPI.d.ts +5 -0
  25. package/dist/modules/plugin-api/index.d.ts +8 -0
  26. package/dist/modules/plugins.d.ts +129 -0
  27. package/dist/modules/randomization.d.ts +35 -0
  28. package/dist/modules/turk.d.ts +40 -0
  29. package/dist/modules/utils.d.ts +7 -0
  30. package/package.json +32 -15
  31. package/src/JsPsych.ts +884 -0
  32. package/src/TimelineNode.ts +536 -0
  33. package/src/index.ts +71 -0
  34. package/src/migration.ts +37 -0
  35. package/src/modules/data/DataCollection.ts +198 -0
  36. package/src/modules/data/DataColumn.ts +86 -0
  37. package/src/modules/data/index.ts +174 -0
  38. package/src/modules/data/utils.ts +75 -0
  39. package/src/modules/extensions.ts +23 -0
  40. package/src/modules/plugin-api/HardwareAPI.ts +32 -0
  41. package/src/modules/plugin-api/KeyboardListenerAPI.ts +165 -0
  42. package/src/modules/plugin-api/MediaAPI.ts +337 -0
  43. package/src/modules/plugin-api/SimulationAPI.ts +181 -0
  44. package/src/modules/plugin-api/TimeoutAPI.ts +16 -0
  45. package/src/modules/plugin-api/index.ts +28 -0
  46. package/src/modules/plugins.ts +158 -0
  47. package/src/modules/randomization.ts +327 -0
  48. package/src/modules/turk.ts +99 -0
  49. package/src/modules/utils.ts +30 -0
  50. package/.github/workflows/jest.yml +0 -20
  51. package/code-of-conduct.md +0 -56
  52. package/contributors.md +0 -61
  53. package/docs/CNAME +0 -1
  54. package/docs/about/about.md +0 -18
  55. package/docs/about/contributing.md +0 -43
  56. package/docs/about/license.md +0 -25
  57. package/docs/about/support.md +0 -7
  58. package/docs/core_library/jspsych-core.md +0 -734
  59. package/docs/core_library/jspsych-data.md +0 -589
  60. package/docs/core_library/jspsych-pluginAPI.md +0 -610
  61. package/docs/core_library/jspsych-randomization.md +0 -397
  62. package/docs/core_library/jspsych-turk.md +0 -102
  63. package/docs/extensions/extensions.md +0 -83
  64. package/docs/extensions/jspsych-ext-webgazer.md +0 -106
  65. package/docs/img/blue.png +0 -0
  66. package/docs/img/devtools-change-css.png +0 -0
  67. package/docs/img/devtools-css-errors.png +0 -0
  68. package/docs/img/devtools-inspect-element.png +0 -0
  69. package/docs/img/folder-setup.png +0 -0
  70. package/docs/img/folder-with-html.png +0 -0
  71. package/docs/img/githubreleases.jpg +0 -0
  72. package/docs/img/jspsych-favicon.png +0 -0
  73. package/docs/img/jspsych-logo-no-text-mono.svg +0 -493
  74. package/docs/img/jspsych-logo.jpg +0 -0
  75. package/docs/img/orange.png +0 -0
  76. package/docs/img/palmer_stim.png +0 -0
  77. package/docs/img/progress_bar.png +0 -0
  78. package/docs/img/prolific-study-completion.png +0 -0
  79. package/docs/img/prolific-study-link.png +0 -0
  80. package/docs/img/visual_search_example.jpg +0 -0
  81. package/docs/index.md +0 -9
  82. package/docs/overview/browser-device-support.md +0 -35
  83. package/docs/overview/callbacks.md +0 -184
  84. package/docs/overview/data.md +0 -281
  85. package/docs/overview/dynamic-parameters.md +0 -147
  86. package/docs/overview/exclude-browser.md +0 -32
  87. package/docs/overview/experiment-options.md +0 -149
  88. package/docs/overview/eye-tracking.md +0 -237
  89. package/docs/overview/fullscreen.md +0 -36
  90. package/docs/overview/media-preloading.md +0 -369
  91. package/docs/overview/mturk.md +0 -77
  92. package/docs/overview/plugins.md +0 -320
  93. package/docs/overview/progress-bar.md +0 -110
  94. package/docs/overview/prolific.md +0 -78
  95. package/docs/overview/record-browser-interactions.md +0 -23
  96. package/docs/overview/running-experiments.md +0 -95
  97. package/docs/overview/style.md +0 -293
  98. package/docs/overview/timeline.md +0 -457
  99. package/docs/plugins/jspsych-animation.md +0 -40
  100. package/docs/plugins/jspsych-audio-button-response.md +0 -60
  101. package/docs/plugins/jspsych-audio-keyboard-response.md +0 -58
  102. package/docs/plugins/jspsych-audio-slider-response.md +0 -53
  103. package/docs/plugins/jspsych-call-function.md +0 -81
  104. package/docs/plugins/jspsych-canvas-button-response.md +0 -66
  105. package/docs/plugins/jspsych-canvas-keyboard-response.md +0 -68
  106. package/docs/plugins/jspsych-canvas-slider-response.md +0 -89
  107. package/docs/plugins/jspsych-categorize-animation.md +0 -60
  108. package/docs/plugins/jspsych-categorize-html.md +0 -53
  109. package/docs/plugins/jspsych-categorize-image.md +0 -53
  110. package/docs/plugins/jspsych-cloze.md +0 -45
  111. package/docs/plugins/jspsych-external-html.md +0 -70
  112. package/docs/plugins/jspsych-free-sort.md +0 -56
  113. package/docs/plugins/jspsych-fullscreen.md +0 -57
  114. package/docs/plugins/jspsych-html-button-response.md +0 -42
  115. package/docs/plugins/jspsych-html-keyboard-response.md +0 -51
  116. package/docs/plugins/jspsych-html-slider-response.md +0 -45
  117. package/docs/plugins/jspsych-iat-html.md +0 -64
  118. package/docs/plugins/jspsych-iat-image.md +0 -64
  119. package/docs/plugins/jspsych-image-button-response.md +0 -48
  120. package/docs/plugins/jspsych-image-keyboard-response.md +0 -58
  121. package/docs/plugins/jspsych-image-slider-response.md +0 -54
  122. package/docs/plugins/jspsych-instructions.md +0 -58
  123. package/docs/plugins/jspsych-maxdiff.md +0 -41
  124. package/docs/plugins/jspsych-preload.md +0 -128
  125. package/docs/plugins/jspsych-rdk.md +0 -119
  126. package/docs/plugins/jspsych-reconstruction.md +0 -48
  127. package/docs/plugins/jspsych-resize.md +0 -39
  128. package/docs/plugins/jspsych-same-different-html.md +0 -53
  129. package/docs/plugins/jspsych-same-different-image.md +0 -66
  130. package/docs/plugins/jspsych-serial-reaction-time-mouse.md +0 -52
  131. package/docs/plugins/jspsych-serial-reaction-time.md +0 -57
  132. package/docs/plugins/jspsych-survey-html-form.md +0 -50
  133. package/docs/plugins/jspsych-survey-likert.md +0 -70
  134. package/docs/plugins/jspsych-survey-multi-choice.md +0 -48
  135. package/docs/plugins/jspsych-survey-multi-select.md +0 -53
  136. package/docs/plugins/jspsych-survey-text.md +0 -63
  137. package/docs/plugins/jspsych-video-button-response.md +0 -54
  138. package/docs/plugins/jspsych-video-keyboard-response.md +0 -50
  139. package/docs/plugins/jspsych-video-slider-response.md +0 -60
  140. package/docs/plugins/jspsych-virtual-chinrest.md +0 -105
  141. package/docs/plugins/jspsych-visual-search-circle.md +0 -52
  142. package/docs/plugins/jspsych-vsl-animate-occlusion.md +0 -55
  143. package/docs/plugins/jspsych-vsl-grid-scene.md +0 -62
  144. package/docs/plugins/jspsych-webgazer-calibrate.md +0 -60
  145. package/docs/plugins/jspsych-webgazer-init-camera.md +0 -31
  146. package/docs/plugins/jspsych-webgazer-validate.md +0 -43
  147. package/docs/plugins/list-of-plugins.md +0 -54
  148. package/docs/tutorials/hello-world.md +0 -162
  149. package/docs/tutorials/rt-task.md +0 -1334
  150. package/docs/tutorials/video-tutorials.md +0 -11
  151. package/examples/add-to-end-of-timeline.html +0 -38
  152. package/examples/case-sensitive-responses.html +0 -45
  153. package/examples/conditional-and-loop-functions.html +0 -64
  154. package/examples/css/jquery-ui.css +0 -1225
  155. package/examples/css-classes-parameter.html +0 -145
  156. package/examples/data-add-properties.html +0 -44
  157. package/examples/data-as-function.html +0 -39
  158. package/examples/data-from-timeline.html +0 -52
  159. package/examples/data-from-url.html +0 -21
  160. package/examples/demo-flanker.html +0 -117
  161. package/examples/demo-simple-rt-task.html +0 -120
  162. package/examples/demos/demo_1.html +0 -35
  163. package/examples/demos/demo_2.html +0 -50
  164. package/examples/demos/demo_3.html +0 -63
  165. package/examples/display-element-to-embed-experiment.html +0 -79
  166. package/examples/end-active-node.html +0 -52
  167. package/examples/end-experiment.html +0 -45
  168. package/examples/exclusions.html +0 -32
  169. package/examples/external_html/simple_consent.html +0 -4
  170. package/examples/img/1.gif +0 -0
  171. package/examples/img/10.gif +0 -0
  172. package/examples/img/11.gif +0 -0
  173. package/examples/img/12.gif +0 -0
  174. package/examples/img/2.gif +0 -0
  175. package/examples/img/3.gif +0 -0
  176. package/examples/img/4.gif +0 -0
  177. package/examples/img/5.gif +0 -0
  178. package/examples/img/6.gif +0 -0
  179. package/examples/img/7.gif +0 -0
  180. package/examples/img/8.gif +0 -0
  181. package/examples/img/9.gif +0 -0
  182. package/examples/img/age/of1.jpg +0 -0
  183. package/examples/img/age/of2.jpg +0 -0
  184. package/examples/img/age/of3.jpg +0 -0
  185. package/examples/img/age/om1.jpg +0 -0
  186. package/examples/img/age/om2.jpg +0 -0
  187. package/examples/img/age/om3.jpg +0 -0
  188. package/examples/img/age/yf1.jpg +0 -0
  189. package/examples/img/age/yf4.jpg +0 -0
  190. package/examples/img/age/yf5.jpg +0 -0
  191. package/examples/img/age/ym2.jpg +0 -0
  192. package/examples/img/age/ym3.jpg +0 -0
  193. package/examples/img/age/ym5.jpg +0 -0
  194. package/examples/img/backwardN.gif +0 -0
  195. package/examples/img/blue.png +0 -0
  196. package/examples/img/card.png +0 -0
  197. package/examples/img/con1.png +0 -0
  198. package/examples/img/con2.png +0 -0
  199. package/examples/img/fixation.gif +0 -0
  200. package/examples/img/happy_face_1.jpg +0 -0
  201. package/examples/img/happy_face_2.jpg +0 -0
  202. package/examples/img/happy_face_3.jpg +0 -0
  203. package/examples/img/happy_face_4.jpg +0 -0
  204. package/examples/img/inc1.png +0 -0
  205. package/examples/img/inc2.png +0 -0
  206. package/examples/img/normalN.gif +0 -0
  207. package/examples/img/orange.png +0 -0
  208. package/examples/img/redX.png +0 -0
  209. package/examples/img/ribbon.jpg +0 -0
  210. package/examples/img/sad_face_1.jpg +0 -0
  211. package/examples/img/sad_face_2.jpg +0 -0
  212. package/examples/img/sad_face_3.jpg +0 -0
  213. package/examples/img/sad_face_4.jpg +0 -0
  214. package/examples/js/snap.svg-min.js +0 -21
  215. package/examples/js/webgazer.js +0 -88886
  216. package/examples/jspsych-RDK.html +0 -58
  217. package/examples/jspsych-animation.html +0 -39
  218. package/examples/jspsych-audio-button-response.html +0 -58
  219. package/examples/jspsych-audio-keyboard-response.html +0 -68
  220. package/examples/jspsych-audio-slider-response.html +0 -61
  221. package/examples/jspsych-call-function.html +0 -32
  222. package/examples/jspsych-canvas-button-response.html +0 -95
  223. package/examples/jspsych-canvas-keyboard-response.html +0 -78
  224. package/examples/jspsych-canvas-slider-response.html +0 -67
  225. package/examples/jspsych-categorize-animation.html +0 -49
  226. package/examples/jspsych-categorize-html.html +0 -33
  227. package/examples/jspsych-categorize-image.html +0 -44
  228. package/examples/jspsych-cloze.html +0 -37
  229. package/examples/jspsych-free-sort.html +0 -109
  230. package/examples/jspsych-fullscreen.html +0 -45
  231. package/examples/jspsych-html-button-response.html +0 -43
  232. package/examples/jspsych-html-keyboard-response.html +0 -42
  233. package/examples/jspsych-html-slider-response.html +0 -53
  234. package/examples/jspsych-iat.html +0 -520
  235. package/examples/jspsych-image-button-response.html +0 -91
  236. package/examples/jspsych-image-keyboard-response.html +0 -85
  237. package/examples/jspsych-image-slider-response.html +0 -85
  238. package/examples/jspsych-instructions.html +0 -37
  239. package/examples/jspsych-maxdiff.html +0 -33
  240. package/examples/jspsych-preload.html +0 -140
  241. package/examples/jspsych-reconstruction.html +0 -43
  242. package/examples/jspsych-resize.html +0 -34
  243. package/examples/jspsych-same-different-html.html +0 -28
  244. package/examples/jspsych-same-different-image.html +0 -39
  245. package/examples/jspsych-serial-reaction-time-mouse.html +0 -98
  246. package/examples/jspsych-serial-reaction-time.html +0 -54
  247. package/examples/jspsych-survey-html-form.html +0 -33
  248. package/examples/jspsych-survey-likert.html +0 -42
  249. package/examples/jspsych-survey-multi-choice.html +0 -40
  250. package/examples/jspsych-survey-multi-select.html +0 -42
  251. package/examples/jspsych-survey-text.html +0 -34
  252. package/examples/jspsych-video-button-response.html +0 -65
  253. package/examples/jspsych-video-keyboard-response.html +0 -61
  254. package/examples/jspsych-video-slider-response.html +0 -63
  255. package/examples/jspsych-virtual-chinrest.html +0 -69
  256. package/examples/jspsych-visual-search-circle.html +0 -64
  257. package/examples/jspsych-vsl-animate-occlusion.html +0 -35
  258. package/examples/jspsych-vsl-grid-scene.html +0 -47
  259. package/examples/lexical-decision.html +0 -134
  260. package/examples/manual-preloading.html +0 -59
  261. package/examples/pause-unpause.html +0 -33
  262. package/examples/progress-bar.html +0 -68
  263. package/examples/save-trial-parameters.html +0 -98
  264. package/examples/sound/hammer.mp3 +0 -0
  265. package/examples/sound/sound.mp3 +0 -0
  266. package/examples/sound/speech_blue.mp3 +0 -0
  267. package/examples/sound/speech_green.mp3 +0 -0
  268. package/examples/sound/speech_joke.mp3 +0 -0
  269. package/examples/sound/speech_red.mp3 +0 -0
  270. package/examples/sound/tone.mp3 +0 -0
  271. package/examples/timeline-variables-sampling.html +0 -50
  272. package/examples/timeline-variables.html +0 -64
  273. package/examples/video/sample_video.mp4 +0 -0
  274. package/examples/webgazer.html +0 -162
  275. package/examples/webgazer_image.html +0 -60
  276. package/extensions/jspsych-ext-webgazer.js +0 -185
  277. package/jspsych.js +0 -3015
  278. package/license.txt +0 -21
  279. package/mkdocs.yml +0 -118
  280. package/plugins/jspsych-animation.js +0 -189
  281. package/plugins/jspsych-audio-button-response.js +0 -269
  282. package/plugins/jspsych-audio-keyboard-response.js +0 -212
  283. package/plugins/jspsych-audio-slider-response.js +0 -278
  284. package/plugins/jspsych-call-function.js +0 -58
  285. package/plugins/jspsych-canvas-button-response.js +0 -199
  286. package/plugins/jspsych-canvas-keyboard-response.js +0 -155
  287. package/plugins/jspsych-canvas-slider-response.js +0 -207
  288. package/plugins/jspsych-categorize-animation.js +0 -266
  289. package/plugins/jspsych-categorize-html.js +0 -220
  290. package/plugins/jspsych-categorize-image.js +0 -222
  291. package/plugins/jspsych-cloze.js +0 -112
  292. package/plugins/jspsych-external-html.js +0 -112
  293. package/plugins/jspsych-free-sort.js +0 -478
  294. package/plugins/jspsych-fullscreen.js +0 -106
  295. package/plugins/jspsych-html-button-response.js +0 -188
  296. package/plugins/jspsych-html-keyboard-response.js +0 -149
  297. package/plugins/jspsych-html-slider-response.js +0 -202
  298. package/plugins/jspsych-iat-html.js +0 -284
  299. package/plugins/jspsych-iat-image.js +0 -286
  300. package/plugins/jspsych-image-button-response.js +0 -327
  301. package/plugins/jspsych-image-keyboard-response.js +0 -263
  302. package/plugins/jspsych-image-slider-response.js +0 -369
  303. package/plugins/jspsych-instructions.js +0 -237
  304. package/plugins/jspsych-maxdiff.js +0 -173
  305. package/plugins/jspsych-preload.js +0 -345
  306. package/plugins/jspsych-rdk.js +0 -1373
  307. package/plugins/jspsych-reconstruction.js +0 -134
  308. package/plugins/jspsych-resize.js +0 -166
  309. package/plugins/jspsych-same-different-html.js +0 -168
  310. package/plugins/jspsych-same-different-image.js +0 -169
  311. package/plugins/jspsych-serial-reaction-time-mouse.js +0 -212
  312. package/plugins/jspsych-serial-reaction-time.js +0 -247
  313. package/plugins/jspsych-survey-html-form.js +0 -171
  314. package/plugins/jspsych-survey-likert.js +0 -195
  315. package/plugins/jspsych-survey-multi-choice.js +0 -208
  316. package/plugins/jspsych-survey-multi-select.js +0 -232
  317. package/plugins/jspsych-survey-text.js +0 -185
  318. package/plugins/jspsych-video-button-response.js +0 -335
  319. package/plugins/jspsych-video-keyboard-response.js +0 -279
  320. package/plugins/jspsych-video-slider-response.js +0 -351
  321. package/plugins/jspsych-virtual-chinrest.js +0 -471
  322. package/plugins/jspsych-visual-search-circle.js +0 -259
  323. package/plugins/jspsych-vsl-animate-occlusion.js +0 -196
  324. package/plugins/jspsych-vsl-grid-scene.js +0 -103
  325. package/plugins/jspsych-webgazer-calibrate.js +0 -166
  326. package/plugins/jspsych-webgazer-init-camera.js +0 -95
  327. package/plugins/jspsych-webgazer-validate.js +0 -304
  328. package/plugins/template/jspsych-plugin-template.js +0 -35
  329. package/tests/README.md +0 -7
  330. package/tests/jsPsych/case-sensitive-responses.test.js +0 -53
  331. package/tests/jsPsych/css-classes-parameter.test.js +0 -107
  332. package/tests/jsPsych/default-iti.test.js +0 -51
  333. package/tests/jsPsych/default-parameters.test.js +0 -58
  334. package/tests/jsPsych/endexperiment.test.js +0 -49
  335. package/tests/jsPsych/events.test.js +0 -606
  336. package/tests/jsPsych/functions-as-parameters.test.js +0 -210
  337. package/tests/jsPsych/init.test.js +0 -48
  338. package/tests/jsPsych/loads.test.js +0 -7
  339. package/tests/jsPsych/min-rt.test.js +0 -58
  340. package/tests/jsPsych/progressbar.test.js +0 -202
  341. package/tests/jsPsych/timeline-variables.test.js +0 -531
  342. package/tests/jsPsych/timelines.test.js +0 -569
  343. package/tests/jsPsych.data/data-csv-conversion.test.js +0 -85
  344. package/tests/jsPsych.data/data-json-conversion.test.js +0 -120
  345. package/tests/jsPsych.data/datacollection.test.js +0 -117
  346. package/tests/jsPsych.data/datacolumn.test.js +0 -50
  347. package/tests/jsPsych.data/datamodule.test.js +0 -152
  348. package/tests/jsPsych.data/dataparameter.test.js +0 -251
  349. package/tests/jsPsych.data/interactions.test.js +0 -109
  350. package/tests/jsPsych.data/trialparameters.test.js +0 -175
  351. package/tests/jsPsych.extensions/extensions.test.js +0 -207
  352. package/tests/jsPsych.extensions/test-extension.js +0 -42
  353. package/tests/jsPsych.pluginAPI/pluginapi.test.js +0 -341
  354. package/tests/jsPsych.pluginAPI/preloads.test.js +0 -43
  355. package/tests/jsPsych.randomization/randomziation.test.js +0 -27
  356. package/tests/jsPsych.utils/utils.test.js +0 -58
  357. package/tests/plugins/plugin-animation.test.js +0 -34
  358. package/tests/plugins/plugin-audio-button-response.test.js +0 -15
  359. package/tests/plugins/plugin-audio-keyboard-response.test.js +0 -15
  360. package/tests/plugins/plugin-audio-slider-response.test.js +0 -15
  361. package/tests/plugins/plugin-call-function.test.js +0 -49
  362. package/tests/plugins/plugin-categorize-animation.test.js +0 -263
  363. package/tests/plugins/plugin-categorize-html.test.js +0 -17
  364. package/tests/plugins/plugin-categorize-image.test.js +0 -17
  365. package/tests/plugins/plugin-cloze.test.js +0 -157
  366. package/tests/plugins/plugin-free-sort.test.js +0 -106
  367. package/tests/plugins/plugin-fullscreen.test.js +0 -41
  368. package/tests/plugins/plugin-html-button-response.test.js +0 -161
  369. package/tests/plugins/plugin-html-keyboard-response.test.js +0 -139
  370. package/tests/plugins/plugin-html-slider-response.test.js +0 -155
  371. package/tests/plugins/plugin-iat-html.test.js +0 -299
  372. package/tests/plugins/plugin-iat-image.test.js +0 -298
  373. package/tests/plugins/plugin-image-button-response.test.js +0 -174
  374. package/tests/plugins/plugin-image-keyboard-response.test.js +0 -147
  375. package/tests/plugins/plugin-image-slider-response.test.js +0 -174
  376. package/tests/plugins/plugin-instructions.test.js +0 -85
  377. package/tests/plugins/plugin-maxdiff.test.js +0 -39
  378. package/tests/plugins/plugin-preload.test.js +0 -916
  379. package/tests/plugins/plugin-rdk.test.js +0 -61
  380. package/tests/plugins/plugin-reconstruction.test.js +0 -16
  381. package/tests/plugins/plugin-resize.test.js +0 -16
  382. package/tests/plugins/plugin-same-different-html.test.js +0 -17
  383. package/tests/plugins/plugin-same-different-image.test.js +0 -17
  384. package/tests/plugins/plugin-serial-reaction-time-mouse.test.js +0 -42
  385. package/tests/plugins/plugin-serial-reaction-time.test.js +0 -109
  386. package/tests/plugins/plugin-survey-html-form.test.js +0 -44
  387. package/tests/plugins/plugin-survey-likert.test.js +0 -48
  388. package/tests/plugins/plugin-survey-multi-choice.test.js +0 -47
  389. package/tests/plugins/plugin-survey-multi-select.test.js +0 -71
  390. package/tests/plugins/plugin-survey-text.test.js +0 -115
  391. package/tests/plugins/plugin-video-button-response.test.js +0 -32
  392. package/tests/plugins/plugin-video-keyboard-response.test.js +0 -32
  393. package/tests/plugins/plugin-video-slider-response.test.js +0 -31
  394. package/tests/plugins/plugin-visual-search-circle.test.js +0 -16
  395. package/tests/plugins/plugin-vsl-animate-occlusion.test.js +0 -16
  396. package/tests/plugins/plugin-vsl-grid-scene.test.js +0 -16
  397. package/tests/testing-utils.js +0 -13
@@ -0,0 +1,536 @@
1
+ import { JsPsych } from "./JsPsych";
2
+ import {
3
+ repeat,
4
+ sampleWithReplacement,
5
+ sampleWithoutReplacement,
6
+ shuffle,
7
+ shuffleAlternateGroups,
8
+ } from "./modules/randomization";
9
+ import { deepCopy } from "./modules/utils";
10
+
11
+ export class TimelineNode {
12
+ // a unique ID for this node, relative to the parent
13
+ relative_id;
14
+
15
+ // store the parent for this node
16
+ parent_node;
17
+
18
+ // parameters for the trial if the node contains a trial
19
+ trial_parameters;
20
+
21
+ // parameters for nodes that contain timelines
22
+ timeline_parameters;
23
+
24
+ // stores trial information on a node that contains a timeline
25
+ // used for adding new trials
26
+ node_trial_data;
27
+
28
+ // track progress through the node
29
+ progress = <any>{
30
+ current_location: -1, // where on the timeline (which timelinenode)
31
+ current_variable_set: 0, // which set of variables to use from timeline_variables
32
+ current_repetition: 0, // how many times through the variable set on this run of the node
33
+ current_iteration: 0, // how many times this node has been revisited
34
+ done: false,
35
+ };
36
+
37
+ end_message?: string;
38
+
39
+ // constructor
40
+ constructor(private jsPsych: JsPsych, parameters, parent?, relativeID?) {
41
+ // store a link to the parent of this node
42
+ this.parent_node = parent;
43
+
44
+ // create the ID for this node
45
+ this.relative_id = typeof parent === "undefined" ? 0 : relativeID;
46
+
47
+ // check if there is a timeline parameter
48
+ // if there is, then this node has its own timeline
49
+ if (typeof parameters.timeline !== "undefined") {
50
+ // create timeline properties
51
+ this.timeline_parameters = {
52
+ timeline: [],
53
+ loop_function: parameters.loop_function,
54
+ conditional_function: parameters.conditional_function,
55
+ sample: parameters.sample,
56
+ randomize_order:
57
+ typeof parameters.randomize_order == "undefined" ? false : parameters.randomize_order,
58
+ repetitions: typeof parameters.repetitions == "undefined" ? 1 : parameters.repetitions,
59
+ timeline_variables:
60
+ typeof parameters.timeline_variables == "undefined"
61
+ ? [{}]
62
+ : parameters.timeline_variables,
63
+ on_timeline_finish: parameters.on_timeline_finish,
64
+ on_timeline_start: parameters.on_timeline_start,
65
+ };
66
+
67
+ this.setTimelineVariablesOrder();
68
+
69
+ // extract all of the node level data and parameters
70
+ // but remove all of the timeline-level specific information
71
+ // since this will be used to copy things down hierarchically
72
+ var node_data = Object.assign({}, parameters);
73
+ delete node_data.timeline;
74
+ delete node_data.conditional_function;
75
+ delete node_data.loop_function;
76
+ delete node_data.randomize_order;
77
+ delete node_data.repetitions;
78
+ delete node_data.timeline_variables;
79
+ delete node_data.sample;
80
+ delete node_data.on_timeline_start;
81
+ delete node_data.on_timeline_finish;
82
+ this.node_trial_data = node_data; // store for later...
83
+
84
+ // create a TimelineNode for each element in the timeline
85
+ for (var i = 0; i < parameters.timeline.length; i++) {
86
+ // merge parameters
87
+ var merged_parameters = Object.assign({}, node_data, parameters.timeline[i]);
88
+ // merge any data from the parent node into child nodes
89
+ if (typeof node_data.data == "object" && typeof parameters.timeline[i].data == "object") {
90
+ var merged_data = Object.assign({}, node_data.data, parameters.timeline[i].data);
91
+ merged_parameters.data = merged_data;
92
+ }
93
+ this.timeline_parameters.timeline.push(
94
+ new TimelineNode(this.jsPsych, merged_parameters, this, i)
95
+ );
96
+ }
97
+ }
98
+ // if there is no timeline parameter, then this node is a trial node
99
+ else {
100
+ // check to see if a valid trial type is defined
101
+ if (typeof parameters.type === "undefined") {
102
+ console.error(
103
+ 'Trial level node is missing the "type" parameter. The parameters for the node are: ' +
104
+ JSON.stringify(parameters)
105
+ );
106
+ }
107
+ // create a deep copy of the parameters for the trial
108
+ this.trial_parameters = { ...parameters };
109
+ }
110
+ }
111
+
112
+ // recursively get the next trial to run.
113
+ // if this node is a leaf (trial), then return the trial.
114
+ // otherwise, recursively find the next trial in the child timeline.
115
+ trial() {
116
+ if (typeof this.timeline_parameters == "undefined") {
117
+ // returns a clone of the trial_parameters to
118
+ // protect functions.
119
+ return deepCopy(this.trial_parameters);
120
+ } else {
121
+ if (this.progress.current_location >= this.timeline_parameters.timeline.length) {
122
+ return null;
123
+ } else {
124
+ return this.timeline_parameters.timeline[this.progress.current_location].trial();
125
+ }
126
+ }
127
+ }
128
+
129
+ markCurrentTrialComplete() {
130
+ if (typeof this.timeline_parameters === "undefined") {
131
+ this.progress.done = true;
132
+ } else {
133
+ this.timeline_parameters.timeline[this.progress.current_location].markCurrentTrialComplete();
134
+ }
135
+ }
136
+
137
+ nextRepetiton() {
138
+ this.setTimelineVariablesOrder();
139
+ this.progress.current_location = -1;
140
+ this.progress.current_variable_set = 0;
141
+ this.progress.current_repetition++;
142
+ for (var i = 0; i < this.timeline_parameters.timeline.length; i++) {
143
+ this.timeline_parameters.timeline[i].reset();
144
+ }
145
+ }
146
+
147
+ // set the order for going through the timeline variables array
148
+ setTimelineVariablesOrder() {
149
+ const timeline_parameters = this.timeline_parameters;
150
+
151
+ // check to make sure this node has variables
152
+ if (
153
+ typeof timeline_parameters === "undefined" ||
154
+ typeof timeline_parameters.timeline_variables === "undefined"
155
+ ) {
156
+ return;
157
+ }
158
+
159
+ var order = [];
160
+ for (var i = 0; i < timeline_parameters.timeline_variables.length; i++) {
161
+ order.push(i);
162
+ }
163
+
164
+ if (typeof timeline_parameters.sample !== "undefined") {
165
+ if (timeline_parameters.sample.type == "custom") {
166
+ order = timeline_parameters.sample.fn(order);
167
+ } else if (timeline_parameters.sample.type == "with-replacement") {
168
+ order = sampleWithReplacement(
169
+ order,
170
+ timeline_parameters.sample.size,
171
+ timeline_parameters.sample.weights
172
+ );
173
+ } else if (timeline_parameters.sample.type == "without-replacement") {
174
+ order = sampleWithoutReplacement(order, timeline_parameters.sample.size);
175
+ } else if (timeline_parameters.sample.type == "fixed-repetitions") {
176
+ order = repeat(order, timeline_parameters.sample.size, false);
177
+ } else if (timeline_parameters.sample.type == "alternate-groups") {
178
+ order = shuffleAlternateGroups(
179
+ timeline_parameters.sample.groups,
180
+ timeline_parameters.sample.randomize_group_order
181
+ );
182
+ } else {
183
+ console.error(
184
+ 'Invalid type in timeline sample parameters. Valid options for type are "custom", "with-replacement", "without-replacement", "fixed-repetitions", and "alternate-groups"'
185
+ );
186
+ }
187
+ }
188
+
189
+ if (timeline_parameters.randomize_order) {
190
+ order = shuffle(order);
191
+ }
192
+
193
+ this.progress.order = order;
194
+ }
195
+
196
+ // next variable set
197
+ nextSet() {
198
+ this.progress.current_location = -1;
199
+ this.progress.current_variable_set++;
200
+ for (var i = 0; i < this.timeline_parameters.timeline.length; i++) {
201
+ this.timeline_parameters.timeline[i].reset();
202
+ }
203
+ }
204
+
205
+ // update the current trial node to be completed
206
+ // returns true if the node is complete after advance (all subnodes are also complete)
207
+ // returns false otherwise
208
+ advance() {
209
+ const progress = this.progress;
210
+ const timeline_parameters = this.timeline_parameters;
211
+ const internal = this.jsPsych.internal;
212
+
213
+ // first check to see if done
214
+ if (progress.done) {
215
+ return true;
216
+ }
217
+
218
+ // if node has not started yet (progress.current_location == -1),
219
+ // then try to start the node.
220
+ if (progress.current_location == -1) {
221
+ // check for on_timeline_start and conditonal function on nodes with timelines
222
+ if (typeof timeline_parameters !== "undefined") {
223
+ // only run the conditional function if this is the first repetition of the timeline when
224
+ // repetitions > 1, and only when on the first variable set
225
+ if (
226
+ typeof timeline_parameters.conditional_function !== "undefined" &&
227
+ progress.current_repetition == 0 &&
228
+ progress.current_variable_set == 0
229
+ ) {
230
+ internal.call_immediate = true;
231
+ var conditional_result = timeline_parameters.conditional_function();
232
+ internal.call_immediate = false;
233
+ // if the conditional_function() returns false, then the timeline
234
+ // doesn't run and is marked as complete.
235
+ if (conditional_result == false) {
236
+ progress.done = true;
237
+ return true;
238
+ }
239
+ }
240
+
241
+ // if we reach this point then the node has its own timeline and will start
242
+ // so we need to check if there is an on_timeline_start function if we are on the first variable set
243
+ if (
244
+ typeof timeline_parameters.on_timeline_start !== "undefined" &&
245
+ progress.current_variable_set == 0
246
+ ) {
247
+ timeline_parameters.on_timeline_start();
248
+ }
249
+ }
250
+ // if we reach this point, then either the node doesn't have a timeline of the
251
+ // conditional function returned true and it can start
252
+ progress.current_location = 0;
253
+ // call advance again on this node now that it is pointing to a new location
254
+ return this.advance();
255
+ }
256
+
257
+ // if this node has a timeline, propogate down to the current trial.
258
+ if (typeof timeline_parameters !== "undefined") {
259
+ var have_node_to_run = false;
260
+ // keep incrementing the location in the timeline until one of the nodes reached is incomplete
261
+ while (
262
+ progress.current_location < timeline_parameters.timeline.length &&
263
+ have_node_to_run == false
264
+ ) {
265
+ // check to see if the node currently pointed at is done
266
+ var target_complete = timeline_parameters.timeline[progress.current_location].advance();
267
+ if (!target_complete) {
268
+ have_node_to_run = true;
269
+ return false;
270
+ } else {
271
+ progress.current_location++;
272
+ }
273
+ }
274
+
275
+ // if we've reached the end of the timeline (which, if the code is here, we have)
276
+
277
+ // there are a few steps to see what to do next...
278
+
279
+ // first, check the timeline_variables to see if we need to loop through again
280
+ // with a new set of variables
281
+ if (progress.current_variable_set < progress.order.length - 1) {
282
+ // reset the progress of the node to be with the new set
283
+ this.nextSet();
284
+ // then try to advance this node again.
285
+ return this.advance();
286
+ }
287
+
288
+ // if we're all done with the timeline_variables, then check to see if there are more repetitions
289
+ else if (progress.current_repetition < timeline_parameters.repetitions - 1) {
290
+ this.nextRepetiton();
291
+ // check to see if there is an on_timeline_finish function
292
+ if (typeof timeline_parameters.on_timeline_finish !== "undefined") {
293
+ timeline_parameters.on_timeline_finish();
294
+ }
295
+ return this.advance();
296
+ }
297
+
298
+ // if we're all done with the repetitions...
299
+ else {
300
+ // check to see if there is an on_timeline_finish function
301
+ if (typeof timeline_parameters.on_timeline_finish !== "undefined") {
302
+ timeline_parameters.on_timeline_finish();
303
+ }
304
+
305
+ // if we're all done with the repetitions, check if there is a loop function.
306
+ if (typeof timeline_parameters.loop_function !== "undefined") {
307
+ internal.call_immediate = true;
308
+ if (timeline_parameters.loop_function(this.generatedData())) {
309
+ this.reset();
310
+ internal.call_immediate = false;
311
+ return this.parent_node.advance();
312
+ } else {
313
+ progress.done = true;
314
+ internal.call_immediate = false;
315
+ return true;
316
+ }
317
+ }
318
+ }
319
+
320
+ // no more loops on this timeline, we're done!
321
+ progress.done = true;
322
+ return true;
323
+ }
324
+ }
325
+
326
+ // check the status of the done flag
327
+ isComplete() {
328
+ return this.progress.done;
329
+ }
330
+
331
+ // getter method for timeline variables
332
+ getTimelineVariableValue(variable_name: string) {
333
+ if (typeof this.timeline_parameters == "undefined") {
334
+ return undefined;
335
+ }
336
+ var v =
337
+ this.timeline_parameters.timeline_variables[
338
+ this.progress.order[this.progress.current_variable_set]
339
+ ][variable_name];
340
+ return v;
341
+ }
342
+
343
+ // recursive upward search for timeline variables
344
+ findTimelineVariable(variable_name) {
345
+ var v = this.getTimelineVariableValue(variable_name);
346
+ if (typeof v == "undefined") {
347
+ if (typeof this.parent_node !== "undefined") {
348
+ return this.parent_node.findTimelineVariable(variable_name);
349
+ } else {
350
+ return undefined;
351
+ }
352
+ } else {
353
+ return v;
354
+ }
355
+ }
356
+
357
+ // recursive downward search for active trial to extract timeline variable
358
+ timelineVariable(variable_name: string) {
359
+ if (typeof this.timeline_parameters == "undefined") {
360
+ return this.findTimelineVariable(variable_name);
361
+ } else {
362
+ // if progress.current_location is -1, then the timeline variable is being evaluated
363
+ // in a function that runs prior to the trial starting, so we should treat that trial
364
+ // as being the active trial for purposes of finding the value of the timeline variable
365
+ var loc = Math.max(0, this.progress.current_location);
366
+ // if loc is greater than the number of elements on this timeline, then the timeline
367
+ // variable is being evaluated in a function that runs after the trial on the timeline
368
+ // are complete but before advancing to the next (like a loop_function).
369
+ // treat the last active trial as the active trial for this purpose.
370
+ if (loc == this.timeline_parameters.timeline.length) {
371
+ loc = loc - 1;
372
+ }
373
+ // now find the variable
374
+ return this.timeline_parameters.timeline[loc].timelineVariable(variable_name);
375
+ }
376
+ }
377
+
378
+ // recursively get all the timeline variables for this trial
379
+ allTimelineVariables() {
380
+ var all_tvs = this.allTimelineVariablesNames();
381
+ var all_tvs_vals = <any>{};
382
+ for (var i = 0; i < all_tvs.length; i++) {
383
+ all_tvs_vals[all_tvs[i]] = this.timelineVariable(all_tvs[i]);
384
+ }
385
+ return all_tvs_vals;
386
+ }
387
+
388
+ // helper to get all the names at this stage.
389
+ allTimelineVariablesNames(so_far = []) {
390
+ if (typeof this.timeline_parameters !== "undefined") {
391
+ so_far = so_far.concat(
392
+ Object.keys(
393
+ this.timeline_parameters.timeline_variables[
394
+ this.progress.order[this.progress.current_variable_set]
395
+ ]
396
+ )
397
+ );
398
+ // if progress.current_location is -1, then the timeline variable is being evaluated
399
+ // in a function that runs prior to the trial starting, so we should treat that trial
400
+ // as being the active trial for purposes of finding the value of the timeline variable
401
+ var loc = Math.max(0, this.progress.current_location);
402
+ // if loc is greater than the number of elements on this timeline, then the timeline
403
+ // variable is being evaluated in a function that runs after the trial on the timeline
404
+ // are complete but before advancing to the next (like a loop_function).
405
+ // treat the last active trial as the active trial for this purpose.
406
+ if (loc == this.timeline_parameters.timeline.length) {
407
+ loc = loc - 1;
408
+ }
409
+ // now find the variable
410
+ return this.timeline_parameters.timeline[loc].allTimelineVariablesNames(so_far);
411
+ }
412
+ if (typeof this.timeline_parameters == "undefined") {
413
+ return so_far;
414
+ }
415
+ }
416
+
417
+ // recursively get the number of **trials** contained in the timeline
418
+ // assuming that while loops execute exactly once and if conditionals
419
+ // always run
420
+ length() {
421
+ var length = 0;
422
+ if (typeof this.timeline_parameters !== "undefined") {
423
+ for (var i = 0; i < this.timeline_parameters.timeline.length; i++) {
424
+ length += this.timeline_parameters.timeline[i].length();
425
+ }
426
+ } else {
427
+ return 1;
428
+ }
429
+ return length;
430
+ }
431
+
432
+ // return the percentage of trials completed, grouped at the first child level
433
+ // counts a set of trials as complete when the child node is done
434
+ percentComplete() {
435
+ var total_trials = this.length();
436
+ var completed_trials = 0;
437
+ for (var i = 0; i < this.timeline_parameters.timeline.length; i++) {
438
+ if (this.timeline_parameters.timeline[i].isComplete()) {
439
+ completed_trials += this.timeline_parameters.timeline[i].length();
440
+ }
441
+ }
442
+ return (completed_trials / total_trials) * 100;
443
+ }
444
+
445
+ // resets the node and all subnodes to original state
446
+ // but increments the current_iteration counter
447
+ reset() {
448
+ this.progress.current_location = -1;
449
+ this.progress.current_repetition = 0;
450
+ this.progress.current_variable_set = 0;
451
+ this.progress.current_iteration++;
452
+ this.progress.done = false;
453
+ this.setTimelineVariablesOrder();
454
+ if (typeof this.timeline_parameters != "undefined") {
455
+ for (var i = 0; i < this.timeline_parameters.timeline.length; i++) {
456
+ this.timeline_parameters.timeline[i].reset();
457
+ }
458
+ }
459
+ }
460
+
461
+ // mark this node as finished
462
+ end() {
463
+ this.progress.done = true;
464
+ }
465
+
466
+ // recursively end whatever sub-node is running the current trial
467
+ endActiveNode() {
468
+ if (typeof this.timeline_parameters == "undefined") {
469
+ this.end();
470
+ this.parent_node.end();
471
+ } else {
472
+ this.timeline_parameters.timeline[this.progress.current_location].endActiveNode();
473
+ }
474
+ }
475
+
476
+ // get a unique ID associated with this node
477
+ // the ID reflects the current iteration through this node.
478
+ ID() {
479
+ var id = "";
480
+ if (typeof this.parent_node == "undefined") {
481
+ return "0." + this.progress.current_iteration;
482
+ } else {
483
+ id += this.parent_node.ID() + "-";
484
+ id += this.relative_id + "." + this.progress.current_iteration;
485
+ return id;
486
+ }
487
+ }
488
+
489
+ // get the ID of the active trial
490
+ activeID() {
491
+ if (typeof this.timeline_parameters == "undefined") {
492
+ return this.ID();
493
+ } else {
494
+ return this.timeline_parameters.timeline[this.progress.current_location].activeID();
495
+ }
496
+ }
497
+
498
+ // get all the data generated within this node
499
+ generatedData() {
500
+ return this.jsPsych.data.getDataByTimelineNode(this.ID());
501
+ }
502
+
503
+ // get all the trials of a particular type
504
+ trialsOfType(type) {
505
+ if (typeof this.timeline_parameters == "undefined") {
506
+ if (this.trial_parameters.type == type) {
507
+ return this.trial_parameters;
508
+ } else {
509
+ return [];
510
+ }
511
+ } else {
512
+ var trials = [];
513
+ for (var i = 0; i < this.timeline_parameters.timeline.length; i++) {
514
+ var t = this.timeline_parameters.timeline[i].trialsOfType(type);
515
+ trials = trials.concat(t);
516
+ }
517
+ return trials;
518
+ }
519
+ }
520
+
521
+ // add new trials to end of this timeline
522
+ insert(parameters) {
523
+ if (typeof this.timeline_parameters === "undefined") {
524
+ console.error("Cannot add new trials to a trial-level node.");
525
+ } else {
526
+ this.timeline_parameters.timeline.push(
527
+ new TimelineNode(
528
+ this.jsPsych,
529
+ { ...this.node_trial_data, ...parameters },
530
+ this,
531
+ this.timeline_parameters.timeline.length
532
+ )
533
+ );
534
+ }
535
+ }
536
+ }
package/src/index.ts ADDED
@@ -0,0 +1,71 @@
1
+ import { JsPsych } from "./JsPsych";
2
+ import { MigrationError } from "./migration";
3
+
4
+ // temporary patch for Safari
5
+ if (
6
+ typeof window !== "undefined" &&
7
+ window.hasOwnProperty("webkitAudioContext") &&
8
+ !window.hasOwnProperty("AudioContext")
9
+ ) {
10
+ // @ts-expect-error
11
+ window.AudioContext = webkitAudioContext;
12
+ }
13
+ // end patch
14
+
15
+ // The following function provides a uniform interface to initialize jsPsych, no matter whether a
16
+ // browser supports ES6 classes or not (and whether the ES6 build or the Babel build is used).
17
+ /**
18
+ * Creates a new JsPsych instance using the provided options.
19
+ *
20
+ * @param options The options to pass to the JsPsych constructor
21
+ * @returns A new JsPsych instance
22
+ */
23
+ export function initJsPsych(options?) {
24
+ const jsPsych = new JsPsych(options);
25
+
26
+ // Handle invocations of non-existent v6 methods with migration errors
27
+ const migrationMessages = {
28
+ init: "`jsPsych.init()` was replaced by `initJsPsych()` in jsPsych v7.",
29
+
30
+ ALL_KEYS: 'jsPsych.ALL_KEYS was replaced by the "ALL_KEYS" string in jsPsych v7.',
31
+ NO_KEYS: 'jsPsych.NO_KEYS was replaced by the "NO_KEYS" string in jsPsych v7.',
32
+
33
+ // Getter functions that were renamed
34
+ currentTimelineNodeID:
35
+ "`currentTimelineNodeID()` was renamed to `getCurrentTimelineNodeID()` in jsPsych v7.",
36
+ progress: "`progress()` was renamed to `getProgress()` in jsPsych v7.",
37
+ startTime: "`startTime()` was renamed to `getStartTime()` in jsPsych v7.",
38
+ totalTime: "`totalTime()` was renamed to `getTotalTime()` in jsPsych v7.",
39
+ currentTrial: "`currentTrial()` was renamed to `getCurrentTrial()` in jsPsych v7.",
40
+ initSettings: "`initSettings()` was renamed to `getInitSettings()` in jsPsych v7.",
41
+ allTimelineVariables:
42
+ "`allTimelineVariables()` was renamed to `getAllTimelineVariables()` in jsPsych v7.",
43
+ };
44
+
45
+ Object.defineProperties(
46
+ jsPsych,
47
+ Object.fromEntries(
48
+ Object.entries(migrationMessages).map(([key, message]) => [
49
+ key,
50
+ {
51
+ get() {
52
+ throw new MigrationError(message);
53
+ },
54
+ },
55
+ ])
56
+ )
57
+ );
58
+
59
+ return jsPsych;
60
+ }
61
+
62
+ export { JsPsych } from "./JsPsych";
63
+ export {
64
+ JsPsychPlugin,
65
+ PluginInfo,
66
+ TrialType,
67
+ ParameterType,
68
+ universalPluginParameters,
69
+ UniversalPluginParameters,
70
+ } from "./modules/plugins";
71
+ export { JsPsychExtension, JsPsychExtensionInfo } from "./modules/extensions";
@@ -0,0 +1,37 @@
1
+ export class MigrationError extends Error {
2
+ constructor(message = "The global `jsPsych` variable is no longer available in jsPsych v7.") {
3
+ super(
4
+ `${message} Please follow the migration guide at https://www.jspsych.org/7.0/support/migration-v7/ to update your experiment.`
5
+ );
6
+ this.name = "MigrationError";
7
+ }
8
+ }
9
+
10
+ // Define a global jsPsych object to handle invocations on it with migration errors
11
+ (window as any).jsPsych = {
12
+ get init() {
13
+ throw new MigrationError("`jsPsych.init()` was replaced by `initJsPsych()` in jsPsych v7.");
14
+ },
15
+
16
+ get data() {
17
+ throw new MigrationError();
18
+ },
19
+ get randomization() {
20
+ throw new MigrationError();
21
+ },
22
+ get turk() {
23
+ throw new MigrationError();
24
+ },
25
+ get pluginAPI() {
26
+ throw new MigrationError();
27
+ },
28
+
29
+ get ALL_KEYS() {
30
+ throw new MigrationError(
31
+ 'jsPsych.ALL_KEYS was replaced by the "ALL_KEYS" string in jsPsych v7.'
32
+ );
33
+ },
34
+ get NO_KEYS() {
35
+ throw new MigrationError('jsPsych.NO_KEYS was replaced by the "NO_KEYS" string in jsPsych v7.');
36
+ },
37
+ };