Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Making stimulus-swipe-container drag with stimulus div #136

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/cold-jobs-begin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@jspsych-contrib/plugin-html-swipe-response": patch
---

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.
2 changes: 2 additions & 0 deletions packages/plugin-html-swipe-response/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,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.

## Loading

```js
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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/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.
Expand Down
29 changes: 29 additions & 0 deletions packages/plugin-html-swipe-response/src/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { clickTarget, pressKey, simulateTimeline, startTimeline } from "@jspsych/test-utils";
import interact from "interactjs";

import htmlSwipeResponse from ".";

Expand Down Expand Up @@ -289,6 +290,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<HTMLElement>(
"#jspsych-html-swipe-response-stimulus-container"
);
const stimulus = displayElement.querySelector<HTMLElement>(
"#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", () => {
Expand Down
26 changes: 22 additions & 4 deletions packages/plugin-html-swipe-response/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ class HtmlSwipeResponsePlugin implements JsPsychPlugin<Info> {
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 = {
Expand All @@ -178,26 +180,35 @@ class HtmlSwipeResponsePlugin implements JsPsychPlugin<Info> {
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`;
container_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;
container_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 });
};

Expand All @@ -219,6 +230,9 @@ class HtmlSwipeResponsePlugin implements JsPsychPlugin<Info> {
stimulus_div.style.transition = `${trial.swipe_animation_duration / 1000}s ease-in-out, ${
trial.swipe_animation_duration / 1000
}s ease-in`;
container_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,
Expand All @@ -230,6 +244,9 @@ class HtmlSwipeResponsePlugin implements JsPsychPlugin<Info> {
stimulus_div.style.transition = `${trial.swipe_animation_duration / 1000}s ease-in-out, ${
trial.swipe_animation_duration / 1000
}s ease-in`;
container_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,
Expand Down Expand Up @@ -288,7 +305,7 @@ class HtmlSwipeResponsePlugin implements JsPsychPlugin<Info> {
}
};

interact(stimulus_div).draggable({
interact(container_div).draggable({
inertia: false,
autoScroll: true,
modifiers: [
Expand Down Expand Up @@ -393,6 +410,7 @@ class HtmlSwipeResponsePlugin implements JsPsychPlugin<Info> {
}

interact(stimulus_div).unset();
interact(container_div).unset();

// gather the data to store for the trial
const trial_data = {
Expand Down
Loading