diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d271eb64..6ff638b5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -39,5 +39,5 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Update README list of plugins and extensions - run: npm run update-readme.js + run: npm run update-readme diff --git a/README.md b/README.md index 0f5e5e08..a1ae1d9b 100644 --- a/README.md +++ b/README.md @@ -19,37 +19,42 @@ The jsPsych plugins that have been contributed by community members can be found The `/packages` directory also contains four template sub-folders that can be used as a starting point for contributing a plugin/extension (see the [Guidelines for contributions](#guidelines-for-contributions) section). + + + + + + ### Plugins Plugin | Contributor | Description ----------- | ----------- | ----------- -[audio-multi-response](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-audio-multi-response/README.md) | [Adam Richie-Halford](https://github.com/richford) | This plugin collects responses to an audio file using both button clicks and key presses. -[audio-swipe-response](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-audio-swipe-response/README.md) | [Adam Richie-Halford](https://github.com/richford) | This plugin collects responses to an audio file using swipe gestures and keyboard responses. -[copying-task](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-copying-task/README.md) | [Andre Sahakian](https://github.com/Andre3582) | foo -[corsi-blocks](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-corsi-blocks/README.md) | [Josh de Leeuw](https://github.com/jodeleeuw) | This plugin displays a configurable Corsi blocks task and records a series of click responses. -[gamepad](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-gamepad/README.md) | [Shaobin Jiang](https://github.com/Shaobin-Jiang) | This plugin allows one to use gamepads in a jsPsych experiment. -[html-choice](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-html-choice/README.md) | [Younes Strittmatter](https://github.com/younesStrittmatter) | This plugin displays clickable html elements that can be used to present a choice. -[html-keyboard-response-raf](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-html-keyboard-response-raf/README.md) | [Josh de Leeuw](https://github.com/jodeleeuw) | This plugin uses the same functionality as the html-keyboard-response plugin, but uses requestAnimationFrame internally for timing -[html-keyboard-slider](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-html-keyboard-slider/README.md) | [Max Lovell](https://github.com/Max-Lovell) | Sliders which allow for keyboard responses. -[html-multi-response](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-html-multi-response/README.md) | [Adam Richie-Halford](https://github.com/richford) | This plugin collects responses to an arbitrary HTML string using both button clicks and key presses. -[html-swipe-response](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-html-swipe-response/README.md) | [Adam Richie-Halford](https://github.com/richford) | This plugin collects responses to an arbitrary HTML string using swipe gestures and keyboard responses. -[html-vas-response](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-html-vas-response/README.md) | [Isaac Kinley](https://github.com/kinleyid) | This plugin collects responses to an arbitrary HTML string using a point-and-click visual analogue scale. -[image-array-keyboard-response](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-image-array-keyboard-response/README.md) | [Younes Strittmatter](https://github.com/younesStrittmatter) | This plugin displays an arbitrary number of images and records responses generated with the keyboard. -[image-multi-response](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-image-multi-response/README.md) | [Adam Richie-Halford](https://github.com/richford) | This plugin collects responses to an image stimulus using both button clicks and key presses. -[image-swipe-response](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-image-swipe-response/README.md) | [Adam Richie-Halford](https://github.com/richford) | This plugin collects responses to an image stimulus using swipe gestures and keyboard responses. -[ios](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-ios/README.md) | [Isaac Kinley](https://github.com/kinleyid) | This plugin implements a continuous version of the Inclusion of Other in the Self (IOS) Scale ([Aron et al., 1992](https://psycnet.apa.org/doiLanding?doi=10.1037%2F0022-3514.63.4.596)). -[libet-intentional-binding](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-libet-intentional-binding/README.md) | [Isaac Kinley](https://github.com/kinleyid) | This plugin measures intentional binding using a Libet clock, and allows the participant to estimate the timing of events by adjusting the clock hand themselves. -[nextcloud-filedrop](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-nextcloud-filedrop/README.md) | [C. Martin Grewe](https://github.com/mgrewe) | This plugin provides permanent storage of data collected during an experiment using a nextcloud instance. -[pipe](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-pipe/README.md) | [Josh de Leeuw](https://github.com/jodeleeuw) | jsPsych plugin to faciliate communication with [DataPipe](https://pipe.jspsych.org) -[rdk](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-rdk/README.md) | [Josh de Leeuw](https://github.com/jodeleeuw) | This plugin displays a Random Dot Kinematogram (RDK) and allows the participant to report the primary direction of motion by pressing a key on the keyboard. -[rok](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-rok/README.md) | [Younes Strittmatter](https://github.com/younesStrittmatter) | This plugin displays a Random Object Kinematogram (ROK) and allows the participant to report the primary direction of motion or the primary orientation by pressing a key on the keyboard. -[self-paced-reading](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-self-paced-reading/README.md) | [igmmgi](https://github.com/igmmgi) | Self-paced reading tasks with different display options. -[survey-number](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-survey-number/README.md) | [Josh de Leeuw](https://github.com/jodeleeuw) | This plugin displays a survey question and collects a numeric response. -[survey-slider](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-survey-slider/README.md) | [Dominique Makowski](https://github.com/DominiqueMakowski) | Add several analogue scales on the same page for use in questionnaires. -[test](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-test/README.md) | cherrie | test -[video-several-keyboard-responses](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-video-several-keyboard-responses/README.md) | [Maria Emine Nylund](https://github.com/marianylund) | jsPsych plugin for playing a video file and getting several keyboard responses -[vsl-animate-occlusion](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-vsl-animate-occlusion/README.md) | [Josh de Leeuw](https://github.com/jodeleeuw) | he VSL (visual statistical learning) animate occlusion plugin displays an animated sequence of shapes that disappear behind an occluding rectangle while they change from one shape to another. -[vsl-grid-scene](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/plugin-vsl-grid-scene/README.md) | [Josh de Leeuw](https://github.com/jodeleeuw) | The VSL (visual statistical learning) grid scene plugin displays images arranged in a grid. +[audio-multi-response](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-audio-multi-response/README.md) | [Adam Richie-Halford](https://github.com/richford) | This plugin collects responses to an audio file using both button clicks and key presses. +[audio-swipe-response](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-audio-swipe-response/README.md) | [Adam Richie-Halford](https://github.com/richford) | This plugin collects responses to an audio file using swipe gestures and keyboard responses. +[copying-task](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-copying-task/README.md) | [Andre Sahakian](https://github.com/Andre3582) | foo +[corsi-blocks](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-corsi-blocks/README.md) | [Josh de Leeuw](https://github.com/jodeleeuw) | This plugin displays a configurable Corsi blocks task and records a series of click responses. +[gamepad](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-gamepad/README.md) | [Shaobin Jiang](https://github.com/Shaobin-Jiang) | This plugin allows one to use gamepads in a jsPsych experiment. +[html-choice](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-html-choice/README.md) | [Younes Strittmatter](https://github.com/younesStrittmatter) | This plugin displays clickable html elements that can be used to present a choice. +[html-keyboard-response-raf](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-html-keyboard-response-raf/README.md) | [Josh de Leeuw](https://github.com/jodeleeuw) | This plugin uses the same functionality as the html-keyboard-response plugin, but uses requestAnimationFrame internally for timing +[html-keyboard-slider](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-html-keyboard-slider/README.md) | [Max Lovell](https://github.com/Max-Lovell) | Sliders which allow for keyboard responses. +[html-multi-response](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-html-multi-response/README.md) | [Adam Richie-Halford](https://github.com/richford) | This plugin collects responses to an arbitrary HTML string using both button clicks and key presses. +[html-swipe-response](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-html-swipe-response/README.md) | [Adam Richie-Halford](https://github.com/richford) | This plugin collects responses to an arbitrary HTML string using swipe gestures and keyboard responses. +[html-vas-response](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-html-vas-response/README.md) | [Isaac Kinley](https://github.com/kinleyid) | This plugin collects responses to an arbitrary HTML string using a point-and-click visual analogue scale. +[image-array-keyboard-response](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-image-array-keyboard-response/README.md) | [Younes Strittmatter](https://github.com/younesStrittmatter) | This plugin displays an arbitrary number of images and records responses generated with the keyboard. +[image-multi-response](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-image-multi-response/README.md) | [Adam Richie-Halford](https://github.com/richford) | This plugin collects responses to an image stimulus using both button clicks and key presses. +[image-swipe-response](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-image-swipe-response/README.md) | [Adam Richie-Halford](https://github.com/richford) | This plugin collects responses to an image stimulus using swipe gestures and keyboard responses. +[ios](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-ios/README.md) | [Isaac Kinley](https://github.com/kinleyid) | This plugin implements a continuous version of the Inclusion of Other in the Self (IOS) Scale ([Aron et al., 1992](https://psycnet.apa.org/doiLanding?doi=10.1037%2F0022-3514.63.4.596)). +[libet-intentional-binding](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-libet-intentional-binding/README.md) | [Isaac Kinley](https://github.com/kinleyid) | This plugin measures intentional binding using a Libet clock, and allows the participant to estimate the timing of events by adjusting the clock hand themselves. +[nextcloud-filedrop](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-nextcloud-filedrop/README.md) | [C. Martin Grewe](https://github.com/mgrewe) | This plugin provides permanent storage of data collected during an experiment using a nextcloud instance. +[pipe](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-pipe/README.md) | [Josh de Leeuw](https://github.com/jodeleeuw) | jsPsych plugin to faciliate communication with [DataPipe](https://pipe.jspsych.org) +[rdk](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-rdk/README.md) | [Josh de Leeuw](https://github.com/jodeleeuw) | This plugin displays a Random Dot Kinematogram (RDK) and allows the subject to report the primary direction of motion by pressing a key on the keyboard. +[rok](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-rok/README.md) | [Younes Strittmatter](https://github.com/younesStrittmatter) | This plugin displays a Random Object Kinematogram (ROK) and allows the subject to report the primary direction of motion or the primary orientation by pressing a key on the keyboard. +[self-paced-reading](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-self-paced-reading/README.md) | [igmmgi](https://github.com/igmmgi) | Self-paced reading tasks with different display options. +[survey-number](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-survey-number/README.md) | [Josh de Leeuw](https://github.com/jodeleeuw) | This plugin displays a survey question and collects a numeric response. +[survey-slider](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-survey-slider/README.md) | [Dominique Makowski](https://github.com/DominiqueMakowski) | Add several analogue scales on the same page for use in questionnaires. +[video-several-keyboard-responses](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-video-several-keyboard-responses/README.md) | [Maria Emine Nylund](https://github.com/marianylund) | jsPsych plugin for playing a video file and getting several keyboard responses +[vsl-animate-occlusion](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-vsl-animate-occlusion/README.md) | [Josh de Leeuw](https://github.com/jodeleeuw) | he VSL (visual statistical learning) animate occlusion plugin displays an animated sequence of shapes that disappear behind an occluding rectangle while they change from one shape to another. +[vsl-grid-scene](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-vsl-grid-scene/README.md) | [Josh de Leeuw](https://github.com/jodeleeuw) | The VSL (visual statistical learning) grid scene plugin displays images arranged in a grid. @@ -58,11 +63,10 @@ The `/packages` directory also contains four template sub-folders that can be us Extension | Contributor | Description ----------- | ----------- | ----------- -[countdown](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/extension-countdown/README.md) | [Shaobin Jiang](https://github.com/Shaobin-Jiang) | This extension adds a countdown during a trial. -[device-motion](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/extension-device-motion/README.md) | [Pedro Neto](https://github.com/pasoneto) | jsPsych extension for tracking device motion -[mediapipe-face-mesh](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/extension-mediapipe-face-mesh/README.md) | [C. Martin Grewe](https://github.com/mgrewe) | This extension provides online tracking of facial posture during trials using the [MediaPipe Face Mesh](https://google.github.io/mediapipe/solutions/face_mesh) library. -[touchscreen-buttons](https://github.com/jspsych/jspsych-contrib/blob/main/packages/@jspsych-contrib/extension-touchscreen-buttons/README.md) | [Younes Strittmatter](https://github.com/younesStrittmatter) | foo - +[countdown](https://github.com/jspsych/jspsych-contrib/blob/main/packages/extension-countdown/README.md) | [Shaobin Jiang](https://github.com/Shaobin-Jiang) | This extension adds a countdown during a trial. +[device-motion](https://github.com/jspsych/jspsych-contrib/blob/main/packages/extension-device-motion/README.md) | [Pedro Neto](https://github.com/pasoneto) | jsPsych extension for tracking device motion +[mediapipe-face-mesh](https://github.com/jspsych/jspsych-contrib/blob/main/packages/extension-mediapipe-face-mesh/README.md) | [C. Martin Grewe](https://github.com/mgrewe) | This extension provides online tracking of facial posture during trials using the [MediaPipe Face Mesh](https://google.github.io/mediapipe/solutions/face_mesh) library. +[touchscreen-buttons](https://github.com/jspsych/jspsych-contrib/blob/main/packages/extension-touchscreen-buttons/README.md) | [Younes Strittmatter](https://github.com/younesStrittmatter) | foo ## Guidelines for contributions @@ -78,6 +82,12 @@ The `/packages` directory also contains four template sub-folders that can be us + + + + + + diff --git a/gulpfile.js b/gulpfile.js index aef3ae4c..7c209df7 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1 +1,3 @@ export { updateUnpkgLinks } from "@jspsych/config/gulp"; + +export { default as updateReadme } from "./update-readme.js"; diff --git a/package-lock.json b/package-lock.json index 50c26a95..e18e66fd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22424,7 +22424,7 @@ }, "packages/plugin-html-swipe-response": { "name": "@jspsych-contrib/plugin-html-swipe-response", - "version": "1.1.2", + "version": "1.1.3", "license": "MIT", "dependencies": { "canvas": "^2.11.2", @@ -22727,7 +22727,7 @@ }, "packages/plugin-rdk": { "name": "@jspsych-contrib/plugin-rdk", - "version": "1.1.0", + "version": "1.2.0", "license": "MIT", "devDependencies": { "@jspsych/config": "^3.2.1", diff --git a/package.json b/package.json index 6db44286..a9a71bb3 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "test:watch": "npm test -- --watch", "build": "npm run build -ws", "update-unpkg-links": "gulp updateUnpkgLinks", - "update-readme": "node ./update-readme.js", + "update-readme": "gulp updateReadme", "prepare": "husky install", "changeset": "changeset", "changeset:version": "changeset version && npm install && npm run update-unpkg-links && npm run update-readme", diff --git a/packages/extension-touchscreen-buttons/examples/example1.html b/packages/extension-touchscreen-buttons/examples/example1.html index c850c46f..e01c2991 100644 --- a/packages/extension-touchscreen-buttons/examples/example1.html +++ b/packages/extension-touchscreen-buttons/examples/example1.html @@ -5,7 +5,7 @@ Experiment - + diff --git a/packages/plugin-html-swipe-response/CHANGELOG.md b/packages/plugin-html-swipe-response/CHANGELOG.md index c87b47a1..f108a147 100644 --- a/packages/plugin-html-swipe-response/CHANGELOG.md +++ b/packages/plugin-html-swipe-response/CHANGELOG.md @@ -1,5 +1,11 @@ # @jspsych-contrib/plugin-html-swipe-response +## 1.1.3 + +### Patch Changes + +- [#136](https://github.com/jspsych/jspsych-contrib/pull/136) [`1e135ea6ccef00a8b8bb9b166ff01a1d8a80bb74`](https://github.com/jspsych/jspsych-contrib/commit/1e135ea6ccef00a8b8bb9b166ff01a1d8a80bb74) Thanks [@Emily-ejag](https://github.com/Emily-ejag)! - the patch ensures that both the container (`#jspsych-html-swipe-response-stimulus-container`) and the stimulus (`#jspsych-html-swipe-response-stimulus`) move together when dragged, providing a unified and seamless interaction. + ## 1.1.2 ### Patch Changes diff --git a/packages/plugin-html-swipe-response/README.md b/packages/plugin-html-swipe-response/README.md index 48ce0659..1447239d 100644 --- a/packages/plugin-html-swipe-response/README.md +++ b/packages/plugin-html-swipe-response/README.md @@ -6,10 +6,12 @@ This plugin displays HTML content and records responses generated by swipe gestu Setting the `stimulus_duration` parameter while using the swipe modality can result in a user experience issue, wherein the user must swipe a stimulus div tag that has been hidden after the stimulus duration has elapsed. To solve this, this plugin wraps the stimulus div tag in another tag with the ID `#jspsych-html-swipe-response-stimulus-container`. This div tag can then be styled so that they user has some visual representation of the stimulus even after the `#jspsych-html-swipe-response-stimulus-container` div has been hidden. +The plugin now ensures that both the container (`#jspsych-html-swipe-response-stimulus-container`) and the stimulus (`#jspsych-html-swipe-response-stimulus`) move together when dragged, providing a unified and seamless interaction. + ## Loading ```js - + ``` ## Compatibility diff --git a/packages/plugin-html-swipe-response/docs/jspsych-html-swipe-response.md b/packages/plugin-html-swipe-response/docs/jspsych-html-swipe-response.md index 00c60ce8..b18e8434 100644 --- a/packages/plugin-html-swipe-response/docs/jspsych-html-swipe-response.md +++ b/packages/plugin-html-swipe-response/docs/jspsych-html-swipe-response.md @@ -4,6 +4,8 @@ This plugin displays HTML content and records responses generated by swipe gestu Setting the `stimulus_duration` parameter while using the swipe modality can result in a user experience issue, wherein the user must swipe a stimulus div tag that has been hidden after the stimulus duration has elapsed. To solve this, this plugin wraps the stimulus div tag in another tag with the ID `#jspsych-html-swipe-response-stimulus-container`. This div tag can then be styled so that they user has some visual representation of the stimulus even after the `#jspsych-html-swipe-response-stimulus-container` div has been hidden. +The plugin now ensures that both the container (`#jspsych-html-swipe-response-stimulus-container`) and the stimulus (`#jspsych-html-swipe-response-stimulus`) move together when dragged, providing a unified and seamless interaction. + ## Parameters In addition to the [parameters available in all plugins](https://www.jspsych.org/latest/overview/plugins/#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of *undefined* must be specified. Parameters can be left unspecified if the default value is acceptable. diff --git a/packages/plugin-html-swipe-response/package.json b/packages/plugin-html-swipe-response/package.json index 3eaa562a..104c5346 100644 --- a/packages/plugin-html-swipe-response/package.json +++ b/packages/plugin-html-swipe-response/package.json @@ -1,6 +1,6 @@ { "name": "@jspsych-contrib/plugin-html-swipe-response", - "version": "1.1.2", + "version": "1.1.3", "description": "This plugin collects responses to an arbitrary HTML string using swipe gestures and keyboard responses.", "type": "module", "main": "dist/index.cjs", diff --git a/packages/plugin-html-swipe-response/src/index.spec.ts b/packages/plugin-html-swipe-response/src/index.spec.ts index fc5af222..cbc4a328 100644 --- a/packages/plugin-html-swipe-response/src/index.spec.ts +++ b/packages/plugin-html-swipe-response/src/index.spec.ts @@ -1,4 +1,5 @@ import { clickTarget, pressKey, simulateTimeline, startTimeline } from "@jspsych/test-utils"; +import interact from "interactjs"; import htmlSwipeResponse from "."; @@ -292,6 +293,34 @@ describe("plugin-html-swipe-response", () => { expect(element.getAttribute("disabled")).toBe("disabled"); }); }); + + test("should move container and stimulus together during drag", async () => { + const { displayElement } = await startTimeline([ + { + type: htmlSwipeResponse, + stimulus: "this is html", + swipe_animation_duration: 0, + }, + ]); + + const container = displayElement.querySelector( + "#jspsych-html-swipe-response-stimulus-container" + ); + const stimulus = displayElement.querySelector( + "#jspsych-html-swipe-response-stimulus" + ); + + // Simulate drag event manually using interact.js drag events + interact(container).fire({ + type: "dragmove", + target: container, + delta: { x: 100, y: 50 }, + }); + + // Now test if the transforms are applied correctly + expect(container.style.transform).toBe("translate3D(100px, 50px, 0)"); + expect(stimulus.style.transform).toBe("translate3D(100px, 50px, 0) rotate(20deg)"); + }); }); describe("html-swipe-response simulation", () => { @@ -347,6 +376,7 @@ describe("html-swipe-response simulation", () => { const buttonResponse = getData().values()[0].button_response; const keyboardResponse = getData().values()[0].keyboard_response; const responseSource = getData().values()[0].response_source; + expect(getData().values()[0].rt).toBeGreaterThan(0); if (responseSource == "keyboard") { expect(typeof keyboardResponse).toBe("string"); diff --git a/packages/plugin-html-swipe-response/src/index.ts b/packages/plugin-html-swipe-response/src/index.ts index f7d49748..df9cce32 100644 --- a/packages/plugin-html-swipe-response/src/index.ts +++ b/packages/plugin-html-swipe-response/src/index.ts @@ -200,6 +200,8 @@ class HtmlSwipeResponsePlugin implements JsPsychPlugin { source: null, }; + // References to container and stimulus + const container_div = document.getElementById("jspsych-html-swipe-response-stimulus-container"); const stimulus_div = document.getElementById("jspsych-html-swipe-response-stimulus"); let position = { @@ -211,26 +213,35 @@ class HtmlSwipeResponsePlugin implements JsPsychPlugin { const setPosition = (coordinates) => { const { x = 0, y = 0, rotation = 0 } = coordinates; position = { x, y, rotation }; + container_div.style.transform = `translate3D(${x}px, ${y}px, 0)`; stimulus_div.style.transform = `translate3D(${x}px, ${y}px, 0) rotate(${rotation}deg)`; }; + // Reset the position of the stimulus and container const resetPosition = async () => { - stimulus_div.style.transition = `${trial.swipe_animation_duration / 1000}s ease-in-out, ${ - trial.swipe_animation_duration / 1000 - }s ease-in`; + for (const div of [container_div, stimulus_div]) { + div.style.transition = `${trial.swipe_animation_duration / 1000}s ease-in-out, ${ + trial.swipe_animation_duration / 1000 + }s ease-in`; + } setPosition({ x: 0, y: 0, rotation: 0 }); - stimulus_div.style.transition = null; + for (const div of [container_div, stimulus_div]) { + div.style.transition = null; + } }; + // Handle drag movement of the stimulus and container together const dragMoveListener = (event) => { const x = position.x + event.delta.x; const y = position.y + event.delta.y; let rotation = 0; - if (position.x > 0) { - rotation = Math.min(trial.swipe_animation_max_rotation, position.x / 4); + + if (x > 0) { + rotation = Math.min(trial.swipe_animation_max_rotation, x / 4); } else { - rotation = Math.max(-trial.swipe_animation_max_rotation, position.x / 4); + rotation = Math.max(-trial.swipe_animation_max_rotation, x / 4); } + setPosition({ x: x, y: y, rotation }); }; @@ -249,9 +260,11 @@ class HtmlSwipeResponsePlugin implements JsPsychPlugin { } const sendCardToLeft = async () => { - stimulus_div.style.transition = `${trial.swipe_animation_duration / 1000}s ease-in-out, ${ - trial.swipe_animation_duration / 1000 - }s ease-in`; + for (const div of [container_div, stimulus_div]) { + div.style.transition = `${trial.swipe_animation_duration / 1000}s ease-in-out, ${ + trial.swipe_animation_duration / 1000 + }s ease-in`; + } setPosition({ x: -trial.swipe_offscreen_coordinate, y: position.y, @@ -260,9 +273,11 @@ class HtmlSwipeResponsePlugin implements JsPsychPlugin { }; const sendCardToRight = async () => { - stimulus_div.style.transition = `${trial.swipe_animation_duration / 1000}s ease-in-out, ${ - trial.swipe_animation_duration / 1000 - }s ease-in`; + for (const div of [container_div, stimulus_div]) { + div.style.transition = `${trial.swipe_animation_duration / 1000}s ease-in-out, ${ + trial.swipe_animation_duration / 1000 + }s ease-in`; + } setPosition({ x: trial.swipe_offscreen_coordinate, y: position.y, @@ -321,29 +336,31 @@ class HtmlSwipeResponsePlugin implements JsPsychPlugin { } }; - interact(stimulus_div).draggable({ - inertia: false, - autoScroll: true, - modifiers: [ - interact.modifiers.restrictRect({ - endOnly: true, - }), - ], - listeners: { - move: dragMoveListener, - end: () => { - if (position.x < -trial.swipe_threshold) { - sendCardToLeft(); - after_swipe_response("left"); - } else if (position.x > trial.swipe_threshold) { - sendCardToRight(); - after_swipe_response("right"); - } else { - resetPosition(); - } + for (const div of [stimulus_div, container_div]) { + interact(div).draggable({ + inertia: false, + autoScroll: true, + modifiers: [ + interact.modifiers.restrictRect({ + endOnly: true, + }), + ], + listeners: { + move: dragMoveListener, + end: () => { + if (position.x < -trial.swipe_threshold) { + sendCardToLeft(); + after_swipe_response("left"); + } else if (position.x > trial.swipe_threshold) { + sendCardToRight(); + after_swipe_response("right"); + } else { + resetPosition(); + } + }, }, - }, - }); + }); + } // function to handle responses by the participant const after_keyboard_response = (info) => { @@ -422,7 +439,9 @@ class HtmlSwipeResponsePlugin implements JsPsychPlugin { this.jsPsych.pluginAPI.cancelKeyboardResponse(keyboardListener); } - interact(stimulus_div).unset(); + for (const div of [stimulus_div, container_div]) { + interact(div).unset(); + } // gather the data to store for the trial const trial_data = { diff --git a/packages/plugin-rdk/CHANGELOG.md b/packages/plugin-rdk/CHANGELOG.md index 4d446d96..2300fac1 100644 --- a/packages/plugin-rdk/CHANGELOG.md +++ b/packages/plugin-rdk/CHANGELOG.md @@ -1,5 +1,11 @@ # @jspsych-contrib/plugin-rdk +## 1.2.0 + +### Minor Changes + +- [#147](https://github.com/jspsych/jspsych-contrib/pull/147) [`7c775983b5852b5c44949f4bcd5bd7d45b048b3b`](https://github.com/jspsych/jspsych-contrib/commit/7c775983b5852b5c44949f4bcd5bd7d45b048b3b) Thanks [@Hoboki](https://github.com/Hoboki)! - If you want coherent dots to change their directions during a trial, you can set `flip_timestamps` and flip their directions as much as you want. + ## 1.1.0 ### Minor Changes diff --git a/packages/plugin-rdk/docs/jspsych-rdk.md b/packages/plugin-rdk/docs/jspsych-rdk.md index 57d95902..168dd9c8 100644 --- a/packages/plugin-rdk/docs/jspsych-rdk.md +++ b/packages/plugin-rdk/docs/jspsych-rdk.md @@ -18,6 +18,7 @@ In addition to the [parameters available in all plugins](https://www.jspsych.org | choices | array of strings | jsPsych.ALL_KEYS | The valid keys that the participant can press as a response. Must be an array of strings. If left unspecified, any key is a valid key. | | correct_choice | array of strings | *undefined* | Array containing the key(s) that are considered the correct response for that particular trial. This needs to be linked with the `coherent_direction` parameter (see Examples section below for an illustration). This is used to determine whether the participant chose the correct response. The boolean indicating whether or not the participant chose the correct response is returned in the `correct` key of the data object. | | trial_duration | numeric | 500 | The amount of time that the stimulus is displayed on the screen in ms. If -1, the stimulus will be displayed until the participant keys in a valid response. (`choices` parameter must contain valid keys or else the stimuli will run indefinitely). | +| flip_timestamps | array of numerics | [] | Timestamps to flip the direction of coherent dots. | | response_ends_trial | boolean | true | If `true`, then the participant's response will end the trial. If `false`, the stimuli will be presented for the full `trial_duration` (the response will be recorded as long as the participant responds within the trial duration). | | number_of_apertures | numeric | 1 | The number of apertures or RDKs on the screen. If set to more than one, remember to set the location (i.e., aperture_center_x and aperture_center_y) parameters to separate them.
In addition, each aperture can be customized individually by passing in an array of values as the parameter (see example below). If a single value (not an array) is passed as the parameter, then all apertures will have the same parameter. | | number_of_dots | numeric | 300 | Number of dots per set. Equivalent to number of dots per frame. | @@ -82,19 +83,19 @@ In addition to the [default data collected by all plugins](https://www.jspsych.o ```javascript var trial = { - type: jsPsychRdk, + type: jsPsychRdk, coherent_direction: 0, correct_choice: ["p"] }; -``` +``` See `examples/example2.html` for a demo. - + ### "Displaying a trial with 2 choices and 1 correct choice" ```javascript var trial = { - type: jsPsychRdk, + type: jsPsychRdk, post_trial_gap: 0, number_of_dots: 200, RDK_type: 3, @@ -103,7 +104,7 @@ var trial = { coherent_direction: 180, trial_duration: 1000 }; -``` +``` See `examples/example3.html` for a demo. @@ -112,7 +113,7 @@ See `examples/example3.html` for a demo. ```javascript var trial = { - type: jsPsychRdk, + type: jsPsychRdk, number_of_apertures: 3, //This needs to be set if more than one aperture trial_duration: 10000, correct_choice: ["a"], @@ -121,7 +122,7 @@ var trial = { number_of_dots: [50, 200, 100], //Different parameter for each aperture. Array length must equal number_of_apertures aperture_center_x: [(window.innerWidth/2)-300,window.innerWidth/2,(window.innerWidth/2)+300] //Separate the apertures on the screen (window.innerWidth/2 is the middle of the screen) }; -``` +``` See `examples/example4.html` for a demo. diff --git a/packages/plugin-rdk/examples/example1.html b/packages/plugin-rdk/examples/example1.html index 794c6bf8..3c061443 100644 --- a/packages/plugin-rdk/examples/example1.html +++ b/packages/plugin-rdk/examples/example1.html @@ -14,13 +14,13 @@ } }); - /* - We would appreciate it if you cited this paper when you use the RDK: + /* + We would appreciate it if you cited this paper when you use the RDK: Rajananda, S., Lau, H. & Odegaard, B., (2018). A Random-Dot Kinematogram for Web-Based Vision Research. Journal of Open Research Software. 6(1), p.6. DOI: [http://doi.org/10.5334/jors.194] */ //---------Create trials--------- - + // Create an array of 2 different trials (different conditions) var RDK_trials = [ { // Condition 1 @@ -29,11 +29,12 @@ }, { // Condition 2 correct_choice: ['l'], // The correct answer for Condition 2 - coherent_direction: 0 // The coherent direction for Condition 2 (dots move right) + coherent_direction: 0, // The coherent direction for Condition 2 (dots move right) + flip_timestamps: [300, 600], }, ]; - - // The test block where all the trials are nested. The properties here will trickle down to all trials in the timeline unless they have their own properties defined + + // The test block where all the trials are nested. The properties here will trickle down to all trials in the timeline unless they have their own properties defined var test_block = { type: jsPsychRdk, post_trial_gap: 500, // The Inter Trial Interval. You can either have no ITI, or have an ITI but change the display element to be the same color as the stimuli background to prevent flashing between trials @@ -45,9 +46,9 @@ background_color: "white", dot_color: "black" }; - + //---------Run the experiment--------- - + jsPsych.run([test_block]); diff --git a/packages/plugin-rdk/package.json b/packages/plugin-rdk/package.json index f200a034..503b5903 100644 --- a/packages/plugin-rdk/package.json +++ b/packages/plugin-rdk/package.json @@ -1,7 +1,7 @@ { "name": "@jspsych-contrib/plugin-rdk", - "version": "1.1.0", - "description": "This plugin displays a Random Dot Kinematogram (RDK) and allows the participant to report the primary direction of motion by pressing a key on the keyboard.", + "version": "1.2.0", + "description": "This plugin displays a Random Dot Kinematogram (RDK) and allows the subject to report the primary direction of motion by pressing a key on the keyboard.", "type": "module", "main": "dist/index.cjs", "exports": { diff --git a/packages/plugin-rdk/readme.md b/packages/plugin-rdk/readme.md index 6f7db427..05207bf1 100644 --- a/packages/plugin-rdk/readme.md +++ b/packages/plugin-rdk/readme.md @@ -9,7 +9,7 @@ This plugin displays a Random Dot Kinematogram (RDK) and allows the participant ### In browser ```js - + ``` ### Via NPM diff --git a/packages/plugin-rdk/src/index.ts b/packages/plugin-rdk/src/index.ts index 53b9ac71..6b380719 100644 --- a/packages/plugin-rdk/src/index.ts +++ b/packages/plugin-rdk/src/index.ts @@ -24,6 +24,13 @@ const info = { pretty_name: "Trial duration", default: 500, }, + /** Flip timestamp array of coherent dots' direction. */ + flip_timestamps: { + type: ParameterType.INT, + pretty_name: "Flip timestamps", + default: [], + array: true, + }, /** If true, then any valid key will end the trial. */ response_ends_trial: { type: ParameterType.BOOL, @@ -423,6 +430,7 @@ class RdkPlugin implements JsPsychPlugin { var choices = assignParameterValue(trial.choices, []); var correct_choice = assignParameterValue(trial.correct_choice, undefined); var trial_duration = assignParameterValue(trial.trial_duration, 500); + var flip_timestamps = assignParameterValue(trial.flip_timestamps, []); var response_ends_trial = assignParameterValue(trial.response_ends_trial, true); var number_of_apertures = assignParameterValue(trial.number_of_apertures, 1); var number_of_dots = assignParameterValue(trial.number_of_dots, 300); @@ -503,7 +511,7 @@ class RdkPlugin implements JsPsychPlugin { var RDK = RDK_type; - /** + /** Shape of aperture 1 - Circle 2 - Ellipse @@ -703,6 +711,12 @@ class RdkPlugin implements JsPsychPlugin { //Declare global variable to be defined in startKeyboardListener function and to be used in end_trial function var keyboardListener; + //Flip status {1, -1} + var flipStatus = 1; + + //Timeout IDs for flipping. + var timeoutIDsFlip = []; + //Declare global variable to store the frame rate of the trial var frameRate: number | number[] = []; //How often the monitor refreshes, in ms. Currently an array to store all the intervals. Will be converted into a single number (the average) in end_trial function. @@ -767,6 +781,7 @@ class RdkPlugin implements JsPsychPlugin { choices: choices, //The set of valid keys correct_choice: correct_choice, //The correct choice(s) trial_duration: trial_duration, //The trial duration + flip_timestamps: flip_timestamps, response_ends_trial: response_ends_trial, //If the response ends the trial number_of_apertures: number_of_apertures, number_of_dots: number_of_dots, @@ -833,6 +848,7 @@ class RdkPlugin implements JsPsychPlugin { //If the parameter is set such that the response ends the trial, then kill the timeout and end the trial if (response_ends_trial) { window.clearTimeout(timeoutID); + timeoutIDsFlip.forEach(window.clearTimeout); end_trial(); } } //End of after_response @@ -1127,6 +1143,17 @@ class RdkPlugin implements JsPsychPlugin { } } + //Start updating flip status + function startFlip() { + flip_timestamps.forEach((timestamp: number) => + timeoutIDsFlip.push( + setTimeout(() => { + flipStatus *= -1; + }, timestamp) + ) + ); + } + //Draw the dots on the canvas after they're updated function draw() { //Load in the current set of dot array for easy handling @@ -1338,10 +1365,10 @@ class RdkPlugin implements JsPsychPlugin { //Updates the x and y coordinates by moving it in the x and y coherent directions function constantDirectionUpdate(dot) { - dot.x += dot.vx; - dot.y += dot.vy; - dot.latestXMove = dot.vx; - dot.latestYMove = dot.vy; + dot.x += dot.vx * flipStatus; + dot.y += dot.vy * flipStatus; + dot.latestXMove = dot.vx * flipStatus; + dot.latestYMove = dot.vy * flipStatus; return dot; } @@ -1400,12 +1427,12 @@ class RdkPlugin implements JsPsychPlugin { //If it is a square or rectangle, re-insert on one of the opposite edges if (apertureType == 3 || apertureType == 4) { /** The formula for calculating whether a dot appears from the vertical edge (left or right edges) is dependent on the direction of the dot and the ratio of the vertical and horizontal edge lengths. - E.g. + E.g. Aperture is 100 px high and 200px wide Dot is moving 3 px in x direction and 4px in y direction Weight on vertical edge (sides) = (100/(100+200)) * (|3| / (|3| + |4|)) = 1/7 Weight on horizontal edge (top or bottom) = (200/(100+200)) * (|4| / (|3| + |4|)) = 8/21 - + The weights above are the ratios to one another. E.g. (cont.) Ratio (vertical edge : horizontal edge) == (1/7 : 8/21) @@ -1543,6 +1570,7 @@ class RdkPlugin implements JsPsychPlugin { //Start to listen to participant's key responses startKeyboardListener(); + startFlip(); //Delare a timestamp var previousTimestamp; diff --git a/update-readme.js b/update-readme.js index fb41e964..506863ce 100644 --- a/update-readme.js +++ b/update-readme.js @@ -28,7 +28,7 @@ function getPackageInfo(packageDir) { }; } -function updateRootReadme() { +async function updateRootReadme() { const packageInfos = fs .readdirSync(packagesDir) .map((dir) => path.join(packagesDir, dir)) @@ -52,21 +52,23 @@ function updateRootReadme() { let extensionList = ""; packageInfos.map((info) => { - const packageReadmeLink = `https://github.com/jspsych/jspsych-contrib/blob/main/packages/${info.name}/README.md`; + const packageName = info.name.replace(/^\@jspsych-contrib\//g, ""); + const packageReadmeLink = `https://github.com/jspsych/jspsych-contrib/blob/main/packages/${packageName}/README.md`; + + const authorRender = info.authorUrl != "" ? `[${info.author}](${info.authorUrl})` : info.author; if (info.name.match(/^\@jspsych-contrib\/plugin-/g)) { - const pluginName = info.name.replace(/^\@jspsych-contrib\/plugin-/g, ""); - const authorRender = - info.authorUrl != "" ? `[${info.author}](${info.authorUrl})` : info.author; + const pluginName = packageName.replace(/^plugin-/g, ""); pluginList = pluginList.concat( `[${pluginName}](${packageReadmeLink}) | ${authorRender} | ${ info.description ? info.description : "foo" } \n` ); } else { + const extensionName = packageName.replace(/^extension-/g, ""); extensionList = extensionList.concat( - `[${info.name.replace(/^\@jspsych-contrib\/extension-/g, "")}](${packageReadmeLink}) | [${ - info.author - }](${info.authorUrl}) | ${info.description ? info.description : "foo"} \n` + `[${extensionName}](${packageReadmeLink}) | ${authorRender} | ${ + info.description ? info.description : "foo" + } \n` ); } }); @@ -90,4 +92,4 @@ function updateRootReadme() { series(generatePluginTable, generateExtensionTable)(); } -export { updateRootReadme }; +export default updateRootReadme;