mirror of
https://github.com/jspsych/jsPsych.git
synced 2025-05-13 00:58:12 +00:00

* modularize plugins: edit index.ts and example files (WIP)
* continue modularizing plugins: edit index.ts and example files (WIP)
* continue modularizing plugins: edit index.ts and example files (WIP)
* continue modularizing plugins and example files, make info static in plugin classes
* add preload flag to plugin info, fix a few parameterType values
* change preload flags in plugin info from audio/image/video strings to boolean
* convert more plugins and example files
* convert more plugins/examples, sync with webgazer branch plugins/examples (not working on this branch)
* remove preload flag from info, change to ParameterType, change to "ALL_KEYS"/"NO_KEYS", change KEY type to KEYS for array params
* remove descriptions from plugin info, fix some ALL_KEYS/NO_KEYS errors
* remove descriptions and add pretty names to plugin info
* remove/edit comments re ALL_KEYS/NO_KEYS and TS errors
* fix some preload plugin errors and convert example file (plugin still not working due to getAutoPreloadList)
* convert RDK plugin and example file
* convert preload plugin and example, add JsPsych getTimelineDescription method for auto-preloading (still not working for audio due to getAudioBuffer
* fix jsPsych getTimelineDescription method so that it does recursive search
* add image and video preloading to plugin examples
* Merge branch 'modularization' into modularization-plugins
* add tests for reconstruction
* fix timeline array getter method: add private timelineDescription var, set to timeline array in run(), rename getTimelineDescription to getTimeline
* changes in response to PR review: fix JsDoc comments, fix array: true in param info, change HTML string param types, add JsDoc author/file/see docs for all plugin classes, switch to @ts-expect-error. Thanks @bjoluc!
* fix JsDoc comments for plugin classes and preload trials parameter
* change preload type to boolean in ParameterInfo interface, and add `preload: false` to virtual-chinrest item_path image parameter
* All my tests except for preload plugin (will do that tomorrow)
* minor fixes to reconstruction tests
* Update preload plugin tests
* Finish test conversion
* switch to arrow functions to fix this keyword errors in plugins, add audio preloading into plugin example files, fix typos
* convert non-plugin example files (WIP, not tested)
* Fix allow_held_keys -> allow_held_key parameter in virtual-chinrest plugin
* Fix `keyboardListener` type in serial-reaction-time plugin
* type fixes for RDK, simplifying `correctOrNot()` function
* fixed ["ALL_KEYS"] => "ALL_KEYS" for iat plugins and tests
* Build jspsych packages before everything else
Dependent builds were previously failing due to missing type definitions
* Remove console.log from html-keyboard-response tests
I think I accidentially committed it.
* fix the delayed start to animation bug (#1885)
* round all RTs to nearest int (#2108)
* fixes and tests #1900 - IAT parameter problems
* finish converting/testing example files, add init settings, add audio preloading, fix errors
* fix progress-bar timeline to demo an example where auto-updating the progress bar works well
* Revert "round all RTs to nearest int (#2108)"
This reverts commit f53145d2e3
.
* change how delayed timeline variables are implemented
* use static for generate_stimulus method so that it can be called on the vsl-grid-scene class
* fix external-html plugin and example (switch to arrow function for proper this context, fix incorrect parameter name)
* remove outdated TO DO comments
Co-authored-by: bjoluc <mail@bjoluc.de>
Co-authored-by: Josh de Leeuw <josh.deleeuw@gmail.com>
169 lines
5.1 KiB
TypeScript
169 lines
5.1 KiB
TypeScript
import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from "jspsych";
|
|
|
|
const info = <const>{
|
|
name: "same-different-image",
|
|
parameters: {
|
|
/** Array containing the images to be displayed. */
|
|
stimuli: {
|
|
type: ParameterType.IMAGE,
|
|
pretty_name: "Stimuli",
|
|
default: undefined,
|
|
array: true,
|
|
},
|
|
/** Correct answer: either "same" or "different". */
|
|
answer: {
|
|
type: ParameterType.SELECT,
|
|
pretty_name: "Answer",
|
|
options: ["same", "different"],
|
|
default: undefined,
|
|
},
|
|
/** The key that subjects should press to indicate that the two stimuli are the same. */
|
|
same_key: {
|
|
type: ParameterType.KEY,
|
|
pretty_name: "Same key",
|
|
default: "q",
|
|
},
|
|
/** The key that subjects should press to indicate that the two stimuli are different. */
|
|
different_key: {
|
|
type: ParameterType.KEY,
|
|
pretty_name: "Different key",
|
|
default: "p",
|
|
},
|
|
/** How long to show the first stimulus for in milliseconds. If null, then the stimulus will remain on the screen until any keypress is made. */
|
|
first_stim_duration: {
|
|
type: ParameterType.INT,
|
|
pretty_name: "First stimulus duration",
|
|
default: 1000,
|
|
},
|
|
/** How long to show a blank screen in between the two stimuli */
|
|
gap_duration: {
|
|
type: ParameterType.INT,
|
|
pretty_name: "Gap duration",
|
|
default: 500,
|
|
},
|
|
/** How long to show the second stimulus for in milliseconds. If null, then the stimulus will remain on the screen until a valid response is made. */
|
|
second_stim_duration: {
|
|
type: ParameterType.INT,
|
|
pretty_name: "Second stimulus duration",
|
|
default: 1000,
|
|
},
|
|
/** Any content here will be displayed below the stimulus. */
|
|
prompt: {
|
|
type: ParameterType.HTML_STRING,
|
|
pretty_name: "Prompt",
|
|
default: null,
|
|
},
|
|
},
|
|
};
|
|
|
|
type Info = typeof info;
|
|
|
|
/**
|
|
* **same-different-image**
|
|
*
|
|
* jsPsych plugin for showing two image stimuli sequentially and getting a same / different judgment via keypress
|
|
*
|
|
* @author Josh de Leeuw
|
|
* @see {@link https://www.jspsych.org/plugins/jspsych-same-different-image/ same-different-image plugin documentation on jspsych.org}
|
|
*/
|
|
class SameDifferentImagePlugin implements JsPsychPlugin<Info> {
|
|
static info = info;
|
|
|
|
constructor(private jsPsych: JsPsych) {}
|
|
|
|
trial(display_element: HTMLElement, trial: TrialType<Info>) {
|
|
display_element.innerHTML =
|
|
'<img class="jspsych-same-different-stimulus" src="' + trial.stimuli[0] + '"></img>';
|
|
|
|
var first_stim_info: { key: string; rt: number };
|
|
if (trial.first_stim_duration > 0) {
|
|
this.jsPsych.pluginAPI.setTimeout(function () {
|
|
showBlankScreen();
|
|
}, trial.first_stim_duration);
|
|
} else {
|
|
const afterKeyboardResponse = (info: { key: string; rt: number }) => {
|
|
first_stim_info = info;
|
|
showBlankScreen();
|
|
};
|
|
this.jsPsych.pluginAPI.getKeyboardResponse({
|
|
callback_function: afterKeyboardResponse,
|
|
valid_responses: "ALL_KEYS",
|
|
rt_method: "performance",
|
|
persist: false,
|
|
allow_held_key: false,
|
|
});
|
|
}
|
|
|
|
const showBlankScreen = () => {
|
|
display_element.innerHTML = "";
|
|
|
|
this.jsPsych.pluginAPI.setTimeout(function () {
|
|
showSecondStim();
|
|
}, trial.gap_duration);
|
|
};
|
|
|
|
const showSecondStim = () => {
|
|
var html =
|
|
'<img class="jspsych-same-different-stimulus" src="' + trial.stimuli[1] + '"></img>';
|
|
//show prompt
|
|
if (trial.prompt !== null) {
|
|
html += trial.prompt;
|
|
}
|
|
|
|
display_element.innerHTML = html;
|
|
|
|
if (trial.second_stim_duration > 0) {
|
|
this.jsPsych.pluginAPI.setTimeout(function () {
|
|
display_element.querySelector<HTMLElement>(
|
|
".jspsych-same-different-stimulus"
|
|
).style.visibility = "hidden";
|
|
}, trial.second_stim_duration);
|
|
}
|
|
|
|
const after_response = (info: { key: string; rt: number }) => {
|
|
// kill any remaining setTimeout handlers
|
|
this.jsPsych.pluginAPI.clearAllTimeouts();
|
|
|
|
var correct = false;
|
|
|
|
var skey = trial.same_key;
|
|
var dkey = trial.different_key;
|
|
|
|
if (this.jsPsych.pluginAPI.compareKeys(info.key, skey) && trial.answer == "same") {
|
|
correct = true;
|
|
}
|
|
|
|
if (this.jsPsych.pluginAPI.compareKeys(info.key, dkey) && trial.answer == "different") {
|
|
correct = true;
|
|
}
|
|
|
|
var trial_data = {
|
|
rt: info.rt,
|
|
answer: trial.answer,
|
|
correct: correct,
|
|
stimulus: [trial.stimuli[0], trial.stimuli[1]],
|
|
response: info.key,
|
|
};
|
|
if (first_stim_info) {
|
|
trial_data["rt_stim1"] = first_stim_info.rt;
|
|
trial_data["response_stim1"] = first_stim_info.key;
|
|
}
|
|
|
|
display_element.innerHTML = "";
|
|
|
|
this.jsPsych.finishTrial(trial_data);
|
|
};
|
|
|
|
this.jsPsych.pluginAPI.getKeyboardResponse({
|
|
callback_function: after_response,
|
|
valid_responses: [trial.same_key, trial.different_key],
|
|
rt_method: "performance",
|
|
persist: false,
|
|
allow_held_key: false,
|
|
});
|
|
};
|
|
}
|
|
}
|
|
|
|
export default SameDifferentImagePlugin;
|