diff --git a/.changeset/afraid-badgers-lie.md b/.changeset/afraid-badgers-lie.md new file mode 100644 index 0000000000..0039503371 --- /dev/null +++ b/.changeset/afraid-badgers-lie.md @@ -0,0 +1,5 @@ +--- +"jspsych": minor +--- + +Added `jsPsych.abortTimelineByName()`. This allows for aborting a specific active timeline by its `name` property. The `name` can be set in the description of the timline. diff --git a/.changeset/bright-apples-hope.md b/.changeset/bright-apples-hope.md new file mode 100644 index 0000000000..9af2958eb6 --- /dev/null +++ b/.changeset/bright-apples-hope.md @@ -0,0 +1,5 @@ +--- +"jspsych": patch +--- + +`getKeyboardResponse` now returns the `key` in the original case (e.g., "Enter" instead of "enter") for easier matching to standard key event documentation. diff --git a/.changeset/button-layouts.md b/.changeset/button-layouts.md new file mode 100644 index 0000000000..0ba3717c1c --- /dev/null +++ b/.changeset/button-layouts.md @@ -0,0 +1,8 @@ +--- +"@jspsych/plugin-html-button-response": major +"jspsych": patch +--- + +Button plugins now support either `display: grid` or `display: flex` on the container element that hold the buttons. If the layout is `grid`, the number of rows and/or columns can be specified. The `margin_horizontal` and `margin_vertical` parameters have been removed from the button plugins. If you need control over the button CSS, you can add inline style to the button element using the `button_html` parameter. + +jspsych.css has new layout classes to support this feature. diff --git a/.changeset/button-response-plugins.md b/.changeset/button-response-plugins.md new file mode 100644 index 0000000000..4588392f34 --- /dev/null +++ b/.changeset/button-response-plugins.md @@ -0,0 +1,31 @@ +--- +"@jspsych/plugin-audio-button-response": major +"@jspsych/plugin-canvas-button-response": major +"@jspsych/plugin-html-button-response": major +"@jspsych/plugin-image-button-response": major +"@jspsych/plugin-video-button-response": major +--- + +- Make `button_html` a function parameter which, given a choice's text and its index, returns the HTML string of the choice's button. If you were previously passing a string to `button_html`, like ``, you can now pass the function + ```js + function (choice) { + return '"; + } + ``` + Similarly, if you were using the array syntax, like + ```js + ['', '', ''] + ``` + an easy way to migrate your trial definition is to pass a function which accesses your array and replaces the `%choice%` placeholder: + ```js + function (choice, choice_index) { + return ['', '', ''][choice_index].replace("%choice%", choice); + } + ``` + From there on, you can further simplify your function. For instance, if the intention of the above example is to have alternating button classes, the `button_html` function might be rewritten as + ```js + function (choice, choice_index) { + return '"; + } + ``` +- Simplify the button DOM structure and styling: Buttons are no longer wrapped in individual container `div`s for spacing and `data-choice` attributes. Instead, each button is assigned its `data-choice` attribute and all buttons are direct children of the button group container `div`. The container `div`, in turn, utilizes a flexbox layout to position the buttons. diff --git a/.changeset/chilled-papayas-admire.md b/.changeset/chilled-papayas-admire.md new file mode 100644 index 0000000000..830e20d443 --- /dev/null +++ b/.changeset/chilled-papayas-admire.md @@ -0,0 +1,58 @@ +--- +"jspsych": minor +"@jspsych/plugin-animation": minor +"@jspsych/plugin-audio-button-response": minor +"@jspsych/plugin-audio-keyboard-response": minor +"@jspsych/plugin-audio-slider-response": minor +"@jspsych/plugin-browser-check": minor +"@jspsych/plugin-call-function": minor +"@jspsych/plugin-canvas-button-response": minor +"@jspsych/plugin-canvas-keyboard-response": minor +"@jspsych/plugin-canvas-slider-response": minor +"@jspsych/plugin-categorize-animation": minor +"@jspsych/plugin-categorize-html": minor +"@jspsych/plugin-categorize-image": minor +"@jspsych/plugin-cloze": minor +"@jspsych/plugin-external-html": minor +"@jspsych/plugin-free-sort": minor +"@jspsych/plugin-fullscreen": minor +"@jspsych/plugin-html-audio-response": minor +"@jspsych/plugin-html-button-response": minor +"@jspsych/plugin-html-keyboard-response": minor +"@jspsych/plugin-html-slider-response": minor +"@jspsych/plugin-html-video-response": minor +"@jspsych/plugin-iat-html": minor +"@jspsych/plugin-iat-image": minor +"@jspsych/plugin-image-button-response": minor +"@jspsych/plugin-image-keyboard-response": minor +"@jspsych/plugin-image-slider-response": minor +"@jspsych/plugin-initialize-camera": minor +"@jspsych/plugin-initialize-microphone": minor +"@jspsych/plugin-instructions": minor +"@jspsych/plugin-maxdiff": minor +"@jspsych/plugin-mirror-camera": minor +"@jspsych/plugin-preload": minor +"@jspsych/plugin-reconstruction": minor +"@jspsych/plugin-resize": minor +"@jspsych/plugin-same-different-html": minor +"@jspsych/plugin-same-different-image": minor +"@jspsych/plugin-serial-reaction-time": minor +"@jspsych/plugin-serial-reaction-time-mouse": minor +"@jspsych/plugin-sketchpad": minor +"@jspsych/plugin-survey": minor +"@jspsych/plugin-survey-html-form": minor +"@jspsych/plugin-survey-likert": minor +"@jspsych/plugin-survey-multi-choice": minor +"@jspsych/plugin-survey-multi-select": minor +"@jspsych/plugin-survey-text": minor +"@jspsych/plugin-video-button-response": minor +"@jspsych/plugin-video-keyboard-response": minor +"@jspsych/plugin-video-slider-response": minor +"@jspsych/plugin-virtual-chinrest": minor +"@jspsych/plugin-visual-search-circle": minor +"@jspsych/plugin-webgazer-calibrate": minor +"@jspsych/plugin-webgazer-init-camera": minor +"@jspsych/plugin-webgazer-validate": minor +--- + +Updated all plugins to implement new pluginInfo standard that contains version, data generated and new documentation style to match migration of docs to be integrated with the code and packages themselves" diff --git a/.changeset/chilly-pans-sin.md b/.changeset/chilly-pans-sin.md new file mode 100644 index 0000000000..f6173d2ad9 --- /dev/null +++ b/.changeset/chilly-pans-sin.md @@ -0,0 +1,5 @@ +--- +"@jspsych/config": major +--- + +Activate TypeScript's `isolatedModules` flag in the root `tsconfig.json` file. If you are facing any TypeScript errors due to `isolatedModules`, please update your code according to the error messages. diff --git a/.changeset/core-rewrite.md b/.changeset/core-rewrite.md new file mode 100644 index 0000000000..1e5503dc97 --- /dev/null +++ b/.changeset/core-rewrite.md @@ -0,0 +1,39 @@ +--- +"jspsych": major +--- + +Rewrite jsPsych's core logic. The following breaking changes have been made: + +**Timeline Events** + +- `conditional_function` is no longer executed on every iteration of a looping timeline, but only once before running the first trial of the timeline. If you rely on the old behavior, move your `conditional_function` into a nested timeline instead. +- `on_timeline_start` and `on_timeline_finish` are no longer invoked in every repetition of a timeline, but only at the beginning or at the end of the timeline, respectively. If you rely on the old behavior, move the `on_timeline_start` and `on_timeline_finish` callbacks into a nested timeline. + +**Timeline Variables** + +- The functionality of `jsPsych.timelineVariable()` has been explicitly split into two functions, `jsPsych.timelineVariable()` and `jsPsych.evaluateTimelineVariable()`. Use `jsPsych.timelineVariable()` to create a timeline variable placeholder and `jsPsych.evaluateTimelineVariable()` to retrieve a given timeline variable's current value. +- `jsPsych.evaluateTimelineVariable()` now throws an error if a variable is not found. +- `jsPsych.getAllTimelineVariables()` has been replaced by a trial-level `save_timeline_variables` parameter that can be used to include all or some timeline variables in a trial's result data. + +**Parameter Handling** + +- JsPsych will now throw an error when a non-array value is used for a trial parameter marked as `array: true` in the plugin's info object. +- Parameter functions and timeline variables are no longer automatically evaluated recursively throughout the whole trial object, but only for the parameters that a plugin specifies in its `info` object. Parameter functions and timeline variables in nested objects are only evaluated if the nested object's parameters are explicitly specified using the `nested` property in the parameter description. + +**Progress Bar** + +- `jsPsych.setProgressBar(x)` has been replaced by `jsPsych.progressBar.progress = x` +- `jsPsych.getProgressBarCompleted()` has been replaced by `jsPsych.progressBar.progress` +- The automatic progress bar updates after every trial now, including trials in nested timelines. + +**Data Handling** + +- Timeline nodes no longer have IDs. As a consequence, the `internal_node_id` trial result property and `jsPsych.data.getDataByTimelineNode()` have been removed. +- Unlike previously, the `save_trial_parameters` parameter can only be used to remove parameters that are specified in the plugin's info object. Other result properties will be left untouched. + +**Miscellaneous Changes** + +- `jsPsych.endExperiment()` and `jsPsych.endCurrentTimeline()` have been renamed to `jsPsych.abortExperiment()` and `jsPsych.abortCurrentTimeline()`, respectively. +- JsPsych now internally relies on the JavaScript event loop. This means automated tests have to `await` utility functions like `pressKey()` to process the event loop. +- The `jspsych` package no longer exports `universalPluginParameters` and the `UniversalPluginParameters` type. +- Interaction listeners are now removed when the experiment ends. diff --git a/.changeset/esbuild.md b/.changeset/esbuild.md new file mode 100644 index 0000000000..591ffff498 --- /dev/null +++ b/.changeset/esbuild.md @@ -0,0 +1,5 @@ +--- +"@jspsych/config": major +--- + +Migrate the build chain from TypeScript, Babel, and Terser to [esbuild](https://esbuild.github.io/). Babel and Terser are no longer included as dependencies and the Babel configuration at `@jspsych/config/babel` has been removed. The minified browser builds are only transpiled down to [ES2015](https://caniuse.com/es6) now. diff --git a/.changeset/flat-tables-repair.md b/.changeset/flat-tables-repair.md new file mode 100644 index 0000000000..1e912fbbf7 --- /dev/null +++ b/.changeset/flat-tables-repair.md @@ -0,0 +1,7 @@ +--- +"jspsych": major +--- + +Removed the `exclusions` option from `initJsPsych()`. The recommended replacement for this functionality is the browser-check plugin. + +Removed the `hardwareAPI` module from the pluginAPI. This was no longer being updated and the features were out of date. diff --git a/.changeset/forty-weeks-walk.md b/.changeset/forty-weeks-walk.md new file mode 100644 index 0000000000..b0133a1e01 --- /dev/null +++ b/.changeset/forty-weeks-walk.md @@ -0,0 +1,5 @@ +--- +"jspsych": major +--- + +Changed the behavior of `DataColumn.mean()` to exclude `null` and `undefined` values from the calculation, as suggested in #2905 diff --git a/.changeset/fresh-doors-watch.md b/.changeset/fresh-doors-watch.md new file mode 100644 index 0000000000..865938e424 --- /dev/null +++ b/.changeset/fresh-doors-watch.md @@ -0,0 +1,8 @@ +--- +"jspsych": major +"@jspsych/plugin-audio-button-response": minor +"@jspsych/plugin-audio-keyboard-response": minor +"@jspsych/plugin-audio-slider-response": minor +--- + +Changed plugins to use AudioPlayer class; added tests using AudioPlayer mock; plugins now use AudioPlayerInterface. diff --git a/.changeset/lucky-glasses-crash.md b/.changeset/lucky-glasses-crash.md new file mode 100644 index 0000000000..54522df1e0 --- /dev/null +++ b/.changeset/lucky-glasses-crash.md @@ -0,0 +1,6 @@ +--- +"jspsych": minor +--- + +Added `record_data` as a parameter available for any trial. Setting `record_data: false` will prevent data from being stored in the jsPsych data object for that trial. + diff --git a/.changeset/old-moons-lay.md b/.changeset/old-moons-lay.md new file mode 100644 index 0000000000..5b3ffc70a9 --- /dev/null +++ b/.changeset/old-moons-lay.md @@ -0,0 +1,5 @@ +--- +"jspsych": minor +--- + +Allow trial `on_finish` methods to be asynchronous, i.e. return a `Promise`. Prior to this, promises returned by `on_finish` were not awaited before proceeding with the next trial. diff --git a/.changeset/pretty-lions-float.md b/.changeset/pretty-lions-float.md new file mode 100644 index 0000000000..be0b864dde --- /dev/null +++ b/.changeset/pretty-lions-float.md @@ -0,0 +1,5 @@ +--- +"jspsych": patch +--- + +Fix typo in randomInt error message diff --git a/.changeset/proud-stingrays-wonder.md b/.changeset/proud-stingrays-wonder.md new file mode 100644 index 0000000000..8c4173342b --- /dev/null +++ b/.changeset/proud-stingrays-wonder.md @@ -0,0 +1,5 @@ +--- +"jspsych": major +--- + +Removed `max-width: 95%` CSS rule on the `.jspsych-content` `
Which animal made the sound?
", - button_html: '' + button_html: (choice)=>`` }; timeline.push(trial); diff --git a/docs/demos/jspsych-audio-button-response-demo-3.html b/docs/demos/jspsych-audio-button-response-demo-3.html new file mode 100644 index 0000000000..e4f95ac8a8 --- /dev/null +++ b/docs/demos/jspsych-audio-button-response-demo-3.html @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + diff --git a/docs/demos/jspsych-canvas-button-response-demo3.html b/docs/demos/jspsych-canvas-button-response-demo3.html index c309044566..c7cd92d7f0 100644 --- a/docs/demos/jspsych-canvas-button-response-demo3.html +++ b/docs/demos/jspsych-canvas-button-response-demo3.html @@ -22,13 +22,13 @@ } // To use the canvas stimulus function with timeline variables, - // the jsPsych.timelineVariable() function can be used inside your stimulus function. + // the jsPsych.evaluateTimelineVariable() function can be used inside your stimulus function. // In addition, this code demonstrates how to check whether participants' answers were correct or not. const circle_procedure = { timeline: [{ type: jsPsychCanvasButtonResponse, stimulus: function(c) { - filledCirc(c, jsPsych.timelineVariable('radius'), jsPsych.timelineVariable('color')); + filledCirc(c, jsPsych.evaluateTimelineVariable('radius'), jsPsych.evaluateTimelineVariable('color')); }, canvas_size: [300, 300], choices: ['Red', 'Green', 'Blue'], diff --git a/docs/demos/jspsych-html-audio-response-demo3.html b/docs/demos/jspsych-html-audio-response-demo3.html index 9e80904f6e..8010c7c916 100644 --- a/docs/demos/jspsych-html-audio-response-demo3.html +++ b/docs/demos/jspsych-html-audio-response-demo3.html @@ -61,7 +61,7 @@ }, prompt: 'Click the object the matches the spoken name.
', choices: ['img/9.gif','img/10.gif','img/11.gif','img/12.gif'], - button_html: '' + button_html: (choice) => `` } var trial_loop = { diff --git a/docs/demos/jspsych-html-button-response-demo2.html b/docs/demos/jspsych-html-button-response-demo2.html new file mode 100644 index 0000000000..66af48b512 --- /dev/null +++ b/docs/demos/jspsych-html-button-response-demo2.html @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + diff --git a/docs/demos/sound/telephone.mp3 b/docs/demos/sound/telephone.mp3 new file mode 100644 index 0000000000..5fc6954cfe Binary files /dev/null and b/docs/demos/sound/telephone.mp3 differ diff --git a/docs/developers/configuration.md b/docs/developers/configuration.md index 73cc9ea97b..27f39a4db7 100644 --- a/docs/developers/configuration.md +++ b/docs/developers/configuration.md @@ -24,26 +24,27 @@ or ```sh git clone https://github.com/jspsych/jspsych-contrib.git && cd jspsych-contrib ``` + in a terminal. Then run `npm install`. This will create a `node_modules` directory and install all the dependencies into it that are required to build and test jsPsych. !!! info - The jsPsych (-contrib) repositories depend on the `canvas` package which comes with pre-built binaries. - On systems for which no pre-built binaries are available, `npm install` will try to build the binaries from scratch, sometimes failing with an error message mentioning the `canvas` package. - If you are facing such installation issues, please follow the [installation instructions](https://github.com/Automattic/node-canvas/wiki#installation-guides) of the `canvas` package and run `npm install` again afterwards. +The jsPsych (-contrib) repositories depend on the `canvas` package which comes with pre-built binaries. +On systems for which no pre-built binaries are available, `npm install` will try to build the binaries from scratch, sometimes failing with an error message mentioning the `canvas` package. +If you are facing such installation issues, please follow the [installation instructions](https://github.com/Automattic/node-canvas/wiki#installation-guides) of the `canvas` package and run `npm install` again afterwards. !!! info - If you are running `npm install` in the core jsPsych repository, this will also execute the build chain for all packages in the jsPsych repository. - This step may take a few minutes. - If you would like to use that time efficiently, consider reading the following two sections to know what's happening. +If you are running `npm install` in the core jsPsych repository, this will also execute the build chain for all packages in the jsPsych repository. +This step may take a few minutes. +If you would like to use that time efficiently, consider reading the following two sections to know what's happening. ## Repository structure A Node.js package is a directory that contains a `package.json` file describing it. Most importantly, a `package.json` file lists other packages that the package depends on. -The jsPsych and jspsych-contrib repositories use NPM *workspaces*. +The jsPsych and jspsych-contrib repositories use NPM _workspaces_. That means, running `npm install` in the repository root will install the dependencies for all packages in the `packages` directory. The core jsPsych library and every jsPsych plugin or extension is laid out as an individual package. These packages are published to the [NPM registry](https://www.npmjs.com/) where they can be downloaded by NPM or any CDN (such as [unpkg](https://unpkg.com/)). @@ -53,40 +54,39 @@ These packages are published to the [NPM registry](https://www.npmjs.com/) where JsPsych comes with a build chain (specified in the `@jspsych/config` package) that can be executed by running `npm run build` in a package's directory. The build chain will read the package (starting at its `src/index.ts` file) and create the following build artifacts in the package's `dist` directory: -* **`index.js`** +- **`index.js`** This file contains everything from `index.ts`, but as plain JavaScript and bundled in a single file (i.e. without `import`ing files from the same package). It is used by bundlers like [webpack](https://webpack.js.org/). -* **`index.cjs`** - Like `index.js`, but using the old CommonJS standard to support backwards-compatible tools like the [Jest](https://jestjs.io/) testing framework. +- **`index.cjs`** + Like `index.js`, but using the old CommonJS standard to support tools like the [Jest](https://jestjs.io/) testing framework. -* **`index.browser.js`** +- **`index.browser.js`** This file, like `index.js`, contains the entire package as plain JavaScript, but this time wrapped in a function so that it can be included directly by browsers using the ` - +