jspsych 6.3.1 → 7.1.2

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 (401) 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 +3171 -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 +3165 -0
  10. package/dist/index.cjs.map +1 -0
  11. package/dist/index.d.ts +11 -0
  12. package/dist/index.js +3159 -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 +136 -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 +165 -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 -719
  59. package/docs/core_library/jspsych-data.md +0 -587
  60. package/docs/core_library/jspsych-pluginAPI.md +0 -624
  61. package/docs/core_library/jspsych-randomization.md +0 -389
  62. package/docs/core_library/jspsych-turk.md +0 -98
  63. package/docs/extensions/extensions.md +0 -83
  64. package/docs/extensions/jspsych-ext-webgazer.md +0 -137
  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 -180
  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 -271
  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 -61
  145. package/docs/plugins/jspsych-webgazer-init-camera.md +0 -30
  146. package/docs/plugins/jspsych-webgazer-validate.md +0 -44
  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/ridgeWorker.mjs +0 -135
  216. package/examples/js/webgazer/webgazer.js +0 -88909
  217. package/examples/js/webgazer/worker_scripts/mat.js +0 -306
  218. package/examples/js/webgazer/worker_scripts/util.js +0 -398
  219. package/examples/jspsych-RDK.html +0 -58
  220. package/examples/jspsych-animation.html +0 -39
  221. package/examples/jspsych-audio-button-response.html +0 -58
  222. package/examples/jspsych-audio-keyboard-response.html +0 -68
  223. package/examples/jspsych-audio-slider-response.html +0 -61
  224. package/examples/jspsych-call-function.html +0 -32
  225. package/examples/jspsych-canvas-button-response.html +0 -95
  226. package/examples/jspsych-canvas-keyboard-response.html +0 -78
  227. package/examples/jspsych-canvas-slider-response.html +0 -67
  228. package/examples/jspsych-categorize-animation.html +0 -49
  229. package/examples/jspsych-categorize-html.html +0 -33
  230. package/examples/jspsych-categorize-image.html +0 -44
  231. package/examples/jspsych-cloze.html +0 -37
  232. package/examples/jspsych-free-sort.html +0 -109
  233. package/examples/jspsych-fullscreen.html +0 -45
  234. package/examples/jspsych-html-button-response.html +0 -43
  235. package/examples/jspsych-html-keyboard-response.html +0 -42
  236. package/examples/jspsych-html-slider-response.html +0 -53
  237. package/examples/jspsych-iat.html +0 -520
  238. package/examples/jspsych-image-button-response.html +0 -91
  239. package/examples/jspsych-image-keyboard-response.html +0 -85
  240. package/examples/jspsych-image-slider-response.html +0 -85
  241. package/examples/jspsych-instructions.html +0 -37
  242. package/examples/jspsych-maxdiff.html +0 -33
  243. package/examples/jspsych-preload.html +0 -140
  244. package/examples/jspsych-reconstruction.html +0 -43
  245. package/examples/jspsych-resize.html +0 -34
  246. package/examples/jspsych-same-different-html.html +0 -28
  247. package/examples/jspsych-same-different-image.html +0 -39
  248. package/examples/jspsych-serial-reaction-time-mouse.html +0 -98
  249. package/examples/jspsych-serial-reaction-time.html +0 -54
  250. package/examples/jspsych-survey-html-form.html +0 -33
  251. package/examples/jspsych-survey-likert.html +0 -42
  252. package/examples/jspsych-survey-multi-choice.html +0 -40
  253. package/examples/jspsych-survey-multi-select.html +0 -42
  254. package/examples/jspsych-survey-text.html +0 -34
  255. package/examples/jspsych-video-button-response.html +0 -65
  256. package/examples/jspsych-video-keyboard-response.html +0 -61
  257. package/examples/jspsych-video-slider-response.html +0 -63
  258. package/examples/jspsych-virtual-chinrest.html +0 -69
  259. package/examples/jspsych-visual-search-circle.html +0 -64
  260. package/examples/jspsych-vsl-animate-occlusion.html +0 -35
  261. package/examples/jspsych-vsl-grid-scene.html +0 -47
  262. package/examples/lexical-decision.html +0 -134
  263. package/examples/manual-preloading.html +0 -59
  264. package/examples/pause-unpause.html +0 -33
  265. package/examples/progress-bar.html +0 -68
  266. package/examples/save-trial-parameters.html +0 -98
  267. package/examples/sound/hammer.mp3 +0 -0
  268. package/examples/sound/sound.mp3 +0 -0
  269. package/examples/sound/speech_blue.mp3 +0 -0
  270. package/examples/sound/speech_green.mp3 +0 -0
  271. package/examples/sound/speech_joke.mp3 +0 -0
  272. package/examples/sound/speech_red.mp3 +0 -0
  273. package/examples/sound/tone.mp3 +0 -0
  274. package/examples/timeline-variables-sampling.html +0 -50
  275. package/examples/timeline-variables.html +0 -64
  276. package/examples/video/sample_video.mp4 +0 -0
  277. package/examples/webgazer.html +0 -174
  278. package/examples/webgazer_audio.html +0 -90
  279. package/examples/webgazer_image.html +0 -60
  280. package/extensions/jspsych-ext-webgazer.js +0 -265
  281. package/jspsych.js +0 -3023
  282. package/license.txt +0 -21
  283. package/mkdocs.yml +0 -118
  284. package/plugins/jspsych-animation.js +0 -189
  285. package/plugins/jspsych-audio-button-response.js +0 -269
  286. package/plugins/jspsych-audio-keyboard-response.js +0 -209
  287. package/plugins/jspsych-audio-slider-response.js +0 -278
  288. package/plugins/jspsych-call-function.js +0 -58
  289. package/plugins/jspsych-canvas-button-response.js +0 -199
  290. package/plugins/jspsych-canvas-keyboard-response.js +0 -155
  291. package/plugins/jspsych-canvas-slider-response.js +0 -207
  292. package/plugins/jspsych-categorize-animation.js +0 -266
  293. package/plugins/jspsych-categorize-html.js +0 -220
  294. package/plugins/jspsych-categorize-image.js +0 -222
  295. package/plugins/jspsych-cloze.js +0 -112
  296. package/plugins/jspsych-external-html.js +0 -112
  297. package/plugins/jspsych-free-sort.js +0 -478
  298. package/plugins/jspsych-fullscreen.js +0 -106
  299. package/plugins/jspsych-html-button-response.js +0 -188
  300. package/plugins/jspsych-html-keyboard-response.js +0 -149
  301. package/plugins/jspsych-html-slider-response.js +0 -202
  302. package/plugins/jspsych-iat-html.js +0 -284
  303. package/plugins/jspsych-iat-image.js +0 -286
  304. package/plugins/jspsych-image-button-response.js +0 -327
  305. package/plugins/jspsych-image-keyboard-response.js +0 -263
  306. package/plugins/jspsych-image-slider-response.js +0 -369
  307. package/plugins/jspsych-instructions.js +0 -237
  308. package/plugins/jspsych-maxdiff.js +0 -173
  309. package/plugins/jspsych-preload.js +0 -345
  310. package/plugins/jspsych-rdk.js +0 -1373
  311. package/plugins/jspsych-reconstruction.js +0 -134
  312. package/plugins/jspsych-resize.js +0 -166
  313. package/plugins/jspsych-same-different-html.js +0 -168
  314. package/plugins/jspsych-same-different-image.js +0 -169
  315. package/plugins/jspsych-serial-reaction-time-mouse.js +0 -212
  316. package/plugins/jspsych-serial-reaction-time.js +0 -247
  317. package/plugins/jspsych-survey-html-form.js +0 -171
  318. package/plugins/jspsych-survey-likert.js +0 -195
  319. package/plugins/jspsych-survey-multi-choice.js +0 -208
  320. package/plugins/jspsych-survey-multi-select.js +0 -232
  321. package/plugins/jspsych-survey-text.js +0 -185
  322. package/plugins/jspsych-video-button-response.js +0 -335
  323. package/plugins/jspsych-video-keyboard-response.js +0 -279
  324. package/plugins/jspsych-video-slider-response.js +0 -351
  325. package/plugins/jspsych-virtual-chinrest.js +0 -471
  326. package/plugins/jspsych-visual-search-circle.js +0 -259
  327. package/plugins/jspsych-vsl-animate-occlusion.js +0 -196
  328. package/plugins/jspsych-vsl-grid-scene.js +0 -103
  329. package/plugins/jspsych-webgazer-calibrate.js +0 -161
  330. package/plugins/jspsych-webgazer-init-camera.js +0 -139
  331. package/plugins/jspsych-webgazer-validate.js +0 -314
  332. package/plugins/template/jspsych-plugin-template.js +0 -35
  333. package/tests/README.md +0 -7
  334. package/tests/jsPsych/case-sensitive-responses.test.js +0 -53
  335. package/tests/jsPsych/css-classes-parameter.test.js +0 -107
  336. package/tests/jsPsych/default-iti.test.js +0 -51
  337. package/tests/jsPsych/default-parameters.test.js +0 -58
  338. package/tests/jsPsych/endexperiment.test.js +0 -49
  339. package/tests/jsPsych/events.test.js +0 -606
  340. package/tests/jsPsych/functions-as-parameters.test.js +0 -210
  341. package/tests/jsPsych/init.test.js +0 -48
  342. package/tests/jsPsych/loads.test.js +0 -7
  343. package/tests/jsPsych/min-rt.test.js +0 -58
  344. package/tests/jsPsych/progressbar.test.js +0 -202
  345. package/tests/jsPsych/timeline-variables.test.js +0 -531
  346. package/tests/jsPsych/timelines.test.js +0 -569
  347. package/tests/jsPsych.data/data-csv-conversion.test.js +0 -85
  348. package/tests/jsPsych.data/data-json-conversion.test.js +0 -120
  349. package/tests/jsPsych.data/datacollection.test.js +0 -117
  350. package/tests/jsPsych.data/datacolumn.test.js +0 -50
  351. package/tests/jsPsych.data/datamodule.test.js +0 -152
  352. package/tests/jsPsych.data/dataparameter.test.js +0 -251
  353. package/tests/jsPsych.data/interactions.test.js +0 -109
  354. package/tests/jsPsych.data/trialparameters.test.js +0 -175
  355. package/tests/jsPsych.extensions/extensions.test.js +0 -207
  356. package/tests/jsPsych.extensions/test-extension.js +0 -42
  357. package/tests/jsPsych.pluginAPI/pluginapi.test.js +0 -365
  358. package/tests/jsPsych.pluginAPI/preloads.test.js +0 -43
  359. package/tests/jsPsych.randomization/randomziation.test.js +0 -27
  360. package/tests/jsPsych.utils/utils.test.js +0 -58
  361. package/tests/plugins/plugin-animation.test.js +0 -34
  362. package/tests/plugins/plugin-audio-button-response.test.js +0 -15
  363. package/tests/plugins/plugin-audio-keyboard-response.test.js +0 -15
  364. package/tests/plugins/plugin-audio-slider-response.test.js +0 -15
  365. package/tests/plugins/plugin-call-function.test.js +0 -49
  366. package/tests/plugins/plugin-categorize-animation.test.js +0 -263
  367. package/tests/plugins/plugin-categorize-html.test.js +0 -17
  368. package/tests/plugins/plugin-categorize-image.test.js +0 -17
  369. package/tests/plugins/plugin-cloze.test.js +0 -157
  370. package/tests/plugins/plugin-free-sort.test.js +0 -106
  371. package/tests/plugins/plugin-fullscreen.test.js +0 -41
  372. package/tests/plugins/plugin-html-button-response.test.js +0 -161
  373. package/tests/plugins/plugin-html-keyboard-response.test.js +0 -139
  374. package/tests/plugins/plugin-html-slider-response.test.js +0 -155
  375. package/tests/plugins/plugin-iat-html.test.js +0 -299
  376. package/tests/plugins/plugin-iat-image.test.js +0 -298
  377. package/tests/plugins/plugin-image-button-response.test.js +0 -174
  378. package/tests/plugins/plugin-image-keyboard-response.test.js +0 -147
  379. package/tests/plugins/plugin-image-slider-response.test.js +0 -174
  380. package/tests/plugins/plugin-instructions.test.js +0 -85
  381. package/tests/plugins/plugin-maxdiff.test.js +0 -39
  382. package/tests/plugins/plugin-preload.test.js +0 -916
  383. package/tests/plugins/plugin-rdk.test.js +0 -61
  384. package/tests/plugins/plugin-reconstruction.test.js +0 -16
  385. package/tests/plugins/plugin-resize.test.js +0 -16
  386. package/tests/plugins/plugin-same-different-html.test.js +0 -17
  387. package/tests/plugins/plugin-same-different-image.test.js +0 -17
  388. package/tests/plugins/plugin-serial-reaction-time-mouse.test.js +0 -42
  389. package/tests/plugins/plugin-serial-reaction-time.test.js +0 -109
  390. package/tests/plugins/plugin-survey-html-form.test.js +0 -44
  391. package/tests/plugins/plugin-survey-likert.test.js +0 -48
  392. package/tests/plugins/plugin-survey-multi-choice.test.js +0 -47
  393. package/tests/plugins/plugin-survey-multi-select.test.js +0 -71
  394. package/tests/plugins/plugin-survey-text.test.js +0 -115
  395. package/tests/plugins/plugin-video-button-response.test.js +0 -32
  396. package/tests/plugins/plugin-video-keyboard-response.test.js +0 -32
  397. package/tests/plugins/plugin-video-slider-response.test.js +0 -31
  398. package/tests/plugins/plugin-visual-search-circle.test.js +0 -16
  399. package/tests/plugins/plugin-vsl-animate-occlusion.test.js +0 -16
  400. package/tests/plugins/plugin-vsl-grid-scene.test.js +0 -16
  401. 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
+ };