@jspsych/plugin-canvas-keyboard-response 1.0.0 → 1.1.0
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.
- package/dist/index.browser.js +34 -3
- package/dist/index.browser.js.map +1 -1
- package/dist/index.browser.min.js +1 -1
- package/dist/index.browser.min.js.map +1 -1
- package/dist/index.cjs +34 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +34 -3
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/index.spec.ts +61 -0
- package/src/index.ts +50 -3
package/dist/index.browser.js
CHANGED
|
@@ -101,7 +101,7 @@ var jsPsychCanvasKeyboardResponse = (function (jspsych) {
|
|
|
101
101
|
this.jsPsych.finishTrial(trial_data);
|
|
102
102
|
};
|
|
103
103
|
// function to handle responses by the subject
|
|
104
|
-
var after_response =
|
|
104
|
+
var after_response = (info) => {
|
|
105
105
|
// after a valid response, the stimulus will have the CSS class 'responded'
|
|
106
106
|
// which can be used to provide visual feedback that a response was recorded
|
|
107
107
|
display_element.querySelector("#jspsych-canvas-keyboard-response-stimulus").className +=
|
|
@@ -126,17 +126,48 @@ var jsPsychCanvasKeyboardResponse = (function (jspsych) {
|
|
|
126
126
|
}
|
|
127
127
|
// hide stimulus if stimulus_duration is set
|
|
128
128
|
if (trial.stimulus_duration !== null) {
|
|
129
|
-
this.jsPsych.pluginAPI.setTimeout(
|
|
129
|
+
this.jsPsych.pluginAPI.setTimeout(() => {
|
|
130
130
|
display_element.querySelector("#jspsych-canvas-keyboard-response-stimulus").style.visibility = "hidden";
|
|
131
131
|
}, trial.stimulus_duration);
|
|
132
132
|
}
|
|
133
133
|
// end trial if trial_duration is set
|
|
134
134
|
if (trial.trial_duration !== null) {
|
|
135
|
-
this.jsPsych.pluginAPI.setTimeout(
|
|
135
|
+
this.jsPsych.pluginAPI.setTimeout(() => {
|
|
136
136
|
end_trial();
|
|
137
137
|
}, trial.trial_duration);
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
|
+
simulate(trial, simulation_mode, simulation_options, load_callback) {
|
|
141
|
+
if (simulation_mode == "data-only") {
|
|
142
|
+
load_callback();
|
|
143
|
+
this.simulate_data_only(trial, simulation_options);
|
|
144
|
+
}
|
|
145
|
+
if (simulation_mode == "visual") {
|
|
146
|
+
this.simulate_visual(trial, simulation_options, load_callback);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
simulate_data_only(trial, simulation_options) {
|
|
150
|
+
const data = this.create_simulation_data(trial, simulation_options);
|
|
151
|
+
this.jsPsych.finishTrial(data);
|
|
152
|
+
}
|
|
153
|
+
simulate_visual(trial, simulation_options, load_callback) {
|
|
154
|
+
const data = this.create_simulation_data(trial, simulation_options);
|
|
155
|
+
const display_element = this.jsPsych.getDisplayElement();
|
|
156
|
+
this.trial(display_element, trial);
|
|
157
|
+
load_callback();
|
|
158
|
+
if (data.rt !== null) {
|
|
159
|
+
this.jsPsych.pluginAPI.pressKey(data.response, data.rt);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
create_simulation_data(trial, simulation_options) {
|
|
163
|
+
const default_data = {
|
|
164
|
+
rt: this.jsPsych.randomization.sampleExGaussian(500, 50, 1 / 150, true),
|
|
165
|
+
response: this.jsPsych.pluginAPI.getValidKey(trial.choices),
|
|
166
|
+
};
|
|
167
|
+
const data = this.jsPsych.pluginAPI.mergeSimulationData(default_data, simulation_options);
|
|
168
|
+
this.jsPsych.pluginAPI.ensureSimulationDataConsistency(trial, data);
|
|
169
|
+
return data;
|
|
170
|
+
}
|
|
140
171
|
}
|
|
141
172
|
CanvasKeyboardResponsePlugin.info = info;
|
|
142
173
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.browser.js","sources":["../src/index.ts"],"sourcesContent":["import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from \"jspsych\";\n\nconst info = <const>{\n name: \"canvas-keyboard-response\",\n parameters: {\n /** The drawing function to apply to the canvas. Should take the canvas object as argument. */\n stimulus: {\n type: ParameterType.FUNCTION,\n pretty_name: \"Stimulus\",\n default: undefined,\n },\n /** Array containing the key(s) the subject is allowed to press to respond to the stimulus. */\n choices: {\n type: ParameterType.KEYS,\n pretty_name: \"Choices\",\n default: \"ALL_KEYS\",\n },\n /** Any content here will be displayed below the stimulus. */\n prompt: {\n type: ParameterType.HTML_STRING,\n pretty_name: \"Prompt\",\n default: null,\n },\n /** How long to show the stimulus. */\n stimulus_duration: {\n type: ParameterType.INT,\n pretty_name: \"Stimulus duration\",\n default: null,\n },\n /** How long to show trial before it ends. */\n trial_duration: {\n type: ParameterType.INT,\n pretty_name: \"Trial duration\",\n default: null,\n },\n /** If true, trial will end when subject makes a response. */\n response_ends_trial: {\n type: ParameterType.BOOL,\n pretty_name: \"Response ends trial\",\n default: true,\n },\n /** Array containing the height (first value) and width (second value) of the canvas element. */\n canvas_size: {\n type: ParameterType.INT,\n array: true,\n pretty_name: \"Canvas size\",\n default: [500, 500],\n },\n },\n};\n\ntype Info = typeof info;\n\n/**\n * **canvas-keyboard-response**\n *\n * jsPsych plugin for displaying a canvas stimulus and getting a keyboard response\n *\n * @author Chris Jungerius (modified from Josh de Leeuw)\n * @see {@link https://www.jspsych.org/plugins/jspsych-canvas-keyboard-response/ canvas-keyboard-response plugin documentation on jspsych.org}\n */\nclass CanvasKeyboardResponsePlugin implements JsPsychPlugin<Info> {\n static info = info;\n\n constructor(private jsPsych: JsPsych) {}\n\n trial(display_element: HTMLElement, trial: TrialType<Info>) {\n var new_html =\n '<div id=\"jspsych-canvas-keyboard-response-stimulus\">' +\n '<canvas id=\"jspsych-canvas-stimulus\" height=\"' +\n trial.canvas_size[0] +\n '\" width=\"' +\n trial.canvas_size[1] +\n '\"></canvas>' +\n \"</div>\";\n // add prompt\n if (trial.prompt !== null) {\n new_html += trial.prompt;\n }\n\n // draw\n display_element.innerHTML = new_html;\n let c = document.getElementById(\"jspsych-canvas-stimulus\");\n trial.stimulus(c);\n // store response\n var response = {\n rt: null,\n key: null,\n };\n\n // function to end trial when it is time\n const end_trial = () => {\n // kill any remaining setTimeout handlers\n this.jsPsych.pluginAPI.clearAllTimeouts();\n\n // kill keyboard listeners\n if (typeof keyboardListener !== \"undefined\") {\n this.jsPsych.pluginAPI.cancelKeyboardResponse(keyboardListener);\n }\n\n // gather the data to store for the trial\n var trial_data = {\n rt: response.rt,\n response: response.key,\n };\n\n // clear the display\n display_element.innerHTML = \"\";\n\n // move on to the next trial\n this.jsPsych.finishTrial(trial_data);\n };\n\n // function to handle responses by the subject\n var after_response = function (info) {\n // after a valid response, the stimulus will have the CSS class 'responded'\n // which can be used to provide visual feedback that a response was recorded\n display_element.querySelector(\"#jspsych-canvas-keyboard-response-stimulus\").className +=\n \" responded\";\n\n // only record the first response\n if (response.key == null) {\n response = info;\n }\n\n if (trial.response_ends_trial) {\n end_trial();\n }\n };\n\n // start the response listener\n if (trial.choices != \"NO_KEYS\") {\n var keyboardListener = this.jsPsych.pluginAPI.getKeyboardResponse({\n callback_function: after_response,\n valid_responses: trial.choices,\n rt_method: \"performance\",\n persist: false,\n allow_held_key: false,\n });\n }\n\n // hide stimulus if stimulus_duration is set\n if (trial.stimulus_duration !== null) {\n this.jsPsych.pluginAPI.setTimeout(function () {\n display_element.querySelector<HTMLElement>(\n \"#jspsych-canvas-keyboard-response-stimulus\"\n ).style.visibility = \"hidden\";\n }, trial.stimulus_duration);\n }\n\n // end trial if trial_duration is set\n if (trial.trial_duration !== null) {\n this.jsPsych.pluginAPI.setTimeout(function () {\n end_trial();\n }, trial.trial_duration);\n }\n }\n}\n\nexport default CanvasKeyboardResponsePlugin;\n"],"names":["ParameterType"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.browser.js","sources":["../src/index.ts"],"sourcesContent":["import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from \"jspsych\";\n\nconst info = <const>{\n name: \"canvas-keyboard-response\",\n parameters: {\n /** The drawing function to apply to the canvas. Should take the canvas object as argument. */\n stimulus: {\n type: ParameterType.FUNCTION,\n pretty_name: \"Stimulus\",\n default: undefined,\n },\n /** Array containing the key(s) the subject is allowed to press to respond to the stimulus. */\n choices: {\n type: ParameterType.KEYS,\n pretty_name: \"Choices\",\n default: \"ALL_KEYS\",\n },\n /** Any content here will be displayed below the stimulus. */\n prompt: {\n type: ParameterType.HTML_STRING,\n pretty_name: \"Prompt\",\n default: null,\n },\n /** How long to show the stimulus. */\n stimulus_duration: {\n type: ParameterType.INT,\n pretty_name: \"Stimulus duration\",\n default: null,\n },\n /** How long to show trial before it ends. */\n trial_duration: {\n type: ParameterType.INT,\n pretty_name: \"Trial duration\",\n default: null,\n },\n /** If true, trial will end when subject makes a response. */\n response_ends_trial: {\n type: ParameterType.BOOL,\n pretty_name: \"Response ends trial\",\n default: true,\n },\n /** Array containing the height (first value) and width (second value) of the canvas element. */\n canvas_size: {\n type: ParameterType.INT,\n array: true,\n pretty_name: \"Canvas size\",\n default: [500, 500],\n },\n },\n};\n\ntype Info = typeof info;\n\n/**\n * **canvas-keyboard-response**\n *\n * jsPsych plugin for displaying a canvas stimulus and getting a keyboard response\n *\n * @author Chris Jungerius (modified from Josh de Leeuw)\n * @see {@link https://www.jspsych.org/plugins/jspsych-canvas-keyboard-response/ canvas-keyboard-response plugin documentation on jspsych.org}\n */\nclass CanvasKeyboardResponsePlugin implements JsPsychPlugin<Info> {\n static info = info;\n\n constructor(private jsPsych: JsPsych) {}\n\n trial(display_element: HTMLElement, trial: TrialType<Info>) {\n var new_html =\n '<div id=\"jspsych-canvas-keyboard-response-stimulus\">' +\n '<canvas id=\"jspsych-canvas-stimulus\" height=\"' +\n trial.canvas_size[0] +\n '\" width=\"' +\n trial.canvas_size[1] +\n '\"></canvas>' +\n \"</div>\";\n // add prompt\n if (trial.prompt !== null) {\n new_html += trial.prompt;\n }\n\n // draw\n display_element.innerHTML = new_html;\n let c = document.getElementById(\"jspsych-canvas-stimulus\");\n trial.stimulus(c);\n // store response\n var response = {\n rt: null,\n key: null,\n };\n\n // function to end trial when it is time\n const end_trial = () => {\n // kill any remaining setTimeout handlers\n this.jsPsych.pluginAPI.clearAllTimeouts();\n\n // kill keyboard listeners\n if (typeof keyboardListener !== \"undefined\") {\n this.jsPsych.pluginAPI.cancelKeyboardResponse(keyboardListener);\n }\n\n // gather the data to store for the trial\n var trial_data = {\n rt: response.rt,\n response: response.key,\n };\n\n // clear the display\n display_element.innerHTML = \"\";\n\n // move on to the next trial\n this.jsPsych.finishTrial(trial_data);\n };\n\n // function to handle responses by the subject\n var after_response = (info) => {\n // after a valid response, the stimulus will have the CSS class 'responded'\n // which can be used to provide visual feedback that a response was recorded\n display_element.querySelector(\"#jspsych-canvas-keyboard-response-stimulus\").className +=\n \" responded\";\n\n // only record the first response\n if (response.key == null) {\n response = info;\n }\n\n if (trial.response_ends_trial) {\n end_trial();\n }\n };\n\n // start the response listener\n if (trial.choices != \"NO_KEYS\") {\n var keyboardListener = this.jsPsych.pluginAPI.getKeyboardResponse({\n callback_function: after_response,\n valid_responses: trial.choices,\n rt_method: \"performance\",\n persist: false,\n allow_held_key: false,\n });\n }\n\n // hide stimulus if stimulus_duration is set\n if (trial.stimulus_duration !== null) {\n this.jsPsych.pluginAPI.setTimeout(() => {\n display_element.querySelector<HTMLElement>(\n \"#jspsych-canvas-keyboard-response-stimulus\"\n ).style.visibility = \"hidden\";\n }, trial.stimulus_duration);\n }\n\n // end trial if trial_duration is set\n if (trial.trial_duration !== null) {\n this.jsPsych.pluginAPI.setTimeout(() => {\n end_trial();\n }, trial.trial_duration);\n }\n }\n\n simulate(\n trial: TrialType<Info>,\n simulation_mode,\n simulation_options: any,\n load_callback: () => void\n ) {\n if (simulation_mode == \"data-only\") {\n load_callback();\n this.simulate_data_only(trial, simulation_options);\n }\n if (simulation_mode == \"visual\") {\n this.simulate_visual(trial, simulation_options, load_callback);\n }\n }\n\n private simulate_data_only(trial: TrialType<Info>, simulation_options) {\n const data = this.create_simulation_data(trial, simulation_options);\n\n this.jsPsych.finishTrial(data);\n }\n\n private simulate_visual(trial: TrialType<Info>, simulation_options, load_callback: () => void) {\n const data = this.create_simulation_data(trial, simulation_options);\n\n const display_element = this.jsPsych.getDisplayElement();\n\n this.trial(display_element, trial);\n load_callback();\n\n if (data.rt !== null) {\n this.jsPsych.pluginAPI.pressKey(data.response, data.rt);\n }\n }\n\n private create_simulation_data(trial: TrialType<Info>, simulation_options) {\n const default_data = {\n rt: this.jsPsych.randomization.sampleExGaussian(500, 50, 1 / 150, true),\n response: this.jsPsych.pluginAPI.getValidKey(trial.choices),\n };\n\n const data = this.jsPsych.pluginAPI.mergeSimulationData(default_data, simulation_options);\n\n this.jsPsych.pluginAPI.ensureSimulationDataConsistency(trial, data);\n\n return data;\n }\n}\n\nexport default CanvasKeyboardResponsePlugin;\n"],"names":["ParameterType"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var jsPsychCanvasKeyboardResponse=function(
|
|
1
|
+
var jsPsychCanvasKeyboardResponse=function(s){"use strict";const e={name:"canvas-keyboard-response",parameters:{stimulus:{type:s.ParameterType.FUNCTION,pretty_name:"Stimulus",default:void 0},choices:{type:s.ParameterType.KEYS,pretty_name:"Choices",default:"ALL_KEYS"},prompt:{type:s.ParameterType.HTML_STRING,pretty_name:"Prompt",default:null},stimulus_duration:{type:s.ParameterType.INT,pretty_name:"Stimulus duration",default:null},trial_duration:{type:s.ParameterType.INT,pretty_name:"Trial duration",default:null},response_ends_trial:{type:s.ParameterType.BOOL,pretty_name:"Response ends trial",default:!0},canvas_size:{type:s.ParameterType.INT,array:!0,pretty_name:"Canvas size",default:[500,500]}}};class t{constructor(s){this.jsPsych=s}trial(s,e){var t='<div id="jspsych-canvas-keyboard-response-stimulus"><canvas id="jspsych-canvas-stimulus" height="'+e.canvas_size[0]+'" width="'+e.canvas_size[1]+'"></canvas></div>';null!==e.prompt&&(t+=e.prompt),s.innerHTML=t;let a=document.getElementById("jspsych-canvas-stimulus");e.stimulus(a);var i={rt:null,key:null};const n=()=>{this.jsPsych.pluginAPI.clearAllTimeouts(),void 0!==r&&this.jsPsych.pluginAPI.cancelKeyboardResponse(r);var e={rt:i.rt,response:i.key};s.innerHTML="",this.jsPsych.finishTrial(e)};if("NO_KEYS"!=e.choices)var r=this.jsPsych.pluginAPI.getKeyboardResponse({callback_function:t=>{s.querySelector("#jspsych-canvas-keyboard-response-stimulus").className+=" responded",null==i.key&&(i=t),e.response_ends_trial&&n()},valid_responses:e.choices,rt_method:"performance",persist:!1,allow_held_key:!1});null!==e.stimulus_duration&&this.jsPsych.pluginAPI.setTimeout((()=>{s.querySelector("#jspsych-canvas-keyboard-response-stimulus").style.visibility="hidden"}),e.stimulus_duration),null!==e.trial_duration&&this.jsPsych.pluginAPI.setTimeout((()=>{n()}),e.trial_duration)}simulate(s,e,t,a){"data-only"==e&&(a(),this.simulate_data_only(s,t)),"visual"==e&&this.simulate_visual(s,t,a)}simulate_data_only(s,e){const t=this.create_simulation_data(s,e);this.jsPsych.finishTrial(t)}simulate_visual(s,e,t){const a=this.create_simulation_data(s,e),i=this.jsPsych.getDisplayElement();this.trial(i,s),t(),null!==a.rt&&this.jsPsych.pluginAPI.pressKey(a.response,a.rt)}create_simulation_data(s,e){const t={rt:this.jsPsych.randomization.sampleExGaussian(500,50,1/150,!0),response:this.jsPsych.pluginAPI.getValidKey(s.choices)},a=this.jsPsych.pluginAPI.mergeSimulationData(t,e);return this.jsPsych.pluginAPI.ensureSimulationDataConsistency(s,a),a}}return t.info=e,t}(jsPsychModule);
|
|
2
2
|
//# sourceMappingURL=index.browser.min.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.browser.min.js","sources":["../src/index.ts"],"sourcesContent":["import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from \"jspsych\";\n\nconst info = <const>{\n name: \"canvas-keyboard-response\",\n parameters: {\n /** The drawing function to apply to the canvas. Should take the canvas object as argument. */\n stimulus: {\n type: ParameterType.FUNCTION,\n pretty_name: \"Stimulus\",\n default: undefined,\n },\n /** Array containing the key(s) the subject is allowed to press to respond to the stimulus. */\n choices: {\n type: ParameterType.KEYS,\n pretty_name: \"Choices\",\n default: \"ALL_KEYS\",\n },\n /** Any content here will be displayed below the stimulus. */\n prompt: {\n type: ParameterType.HTML_STRING,\n pretty_name: \"Prompt\",\n default: null,\n },\n /** How long to show the stimulus. */\n stimulus_duration: {\n type: ParameterType.INT,\n pretty_name: \"Stimulus duration\",\n default: null,\n },\n /** How long to show trial before it ends. */\n trial_duration: {\n type: ParameterType.INT,\n pretty_name: \"Trial duration\",\n default: null,\n },\n /** If true, trial will end when subject makes a response. */\n response_ends_trial: {\n type: ParameterType.BOOL,\n pretty_name: \"Response ends trial\",\n default: true,\n },\n /** Array containing the height (first value) and width (second value) of the canvas element. */\n canvas_size: {\n type: ParameterType.INT,\n array: true,\n pretty_name: \"Canvas size\",\n default: [500, 500],\n },\n },\n};\n\ntype Info = typeof info;\n\n/**\n * **canvas-keyboard-response**\n *\n * jsPsych plugin for displaying a canvas stimulus and getting a keyboard response\n *\n * @author Chris Jungerius (modified from Josh de Leeuw)\n * @see {@link https://www.jspsych.org/plugins/jspsych-canvas-keyboard-response/ canvas-keyboard-response plugin documentation on jspsych.org}\n */\nclass CanvasKeyboardResponsePlugin implements JsPsychPlugin<Info> {\n static info = info;\n\n constructor(private jsPsych: JsPsych) {}\n\n trial(display_element: HTMLElement, trial: TrialType<Info>) {\n var new_html =\n '<div id=\"jspsych-canvas-keyboard-response-stimulus\">' +\n '<canvas id=\"jspsych-canvas-stimulus\" height=\"' +\n trial.canvas_size[0] +\n '\" width=\"' +\n trial.canvas_size[1] +\n '\"></canvas>' +\n \"</div>\";\n // add prompt\n if (trial.prompt !== null) {\n new_html += trial.prompt;\n }\n\n // draw\n display_element.innerHTML = new_html;\n let c = document.getElementById(\"jspsych-canvas-stimulus\");\n trial.stimulus(c);\n // store response\n var response = {\n rt: null,\n key: null,\n };\n\n // function to end trial when it is time\n const end_trial = () => {\n // kill any remaining setTimeout handlers\n this.jsPsych.pluginAPI.clearAllTimeouts();\n\n // kill keyboard listeners\n if (typeof keyboardListener !== \"undefined\") {\n this.jsPsych.pluginAPI.cancelKeyboardResponse(keyboardListener);\n }\n\n // gather the data to store for the trial\n var trial_data = {\n rt: response.rt,\n response: response.key,\n };\n\n // clear the display\n display_element.innerHTML = \"\";\n\n // move on to the next trial\n this.jsPsych.finishTrial(trial_data);\n };\n\n // function to handle responses by the subject\n var after_response =
|
|
1
|
+
{"version":3,"file":"index.browser.min.js","sources":["../src/index.ts"],"sourcesContent":["import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from \"jspsych\";\n\nconst info = <const>{\n name: \"canvas-keyboard-response\",\n parameters: {\n /** The drawing function to apply to the canvas. Should take the canvas object as argument. */\n stimulus: {\n type: ParameterType.FUNCTION,\n pretty_name: \"Stimulus\",\n default: undefined,\n },\n /** Array containing the key(s) the subject is allowed to press to respond to the stimulus. */\n choices: {\n type: ParameterType.KEYS,\n pretty_name: \"Choices\",\n default: \"ALL_KEYS\",\n },\n /** Any content here will be displayed below the stimulus. */\n prompt: {\n type: ParameterType.HTML_STRING,\n pretty_name: \"Prompt\",\n default: null,\n },\n /** How long to show the stimulus. */\n stimulus_duration: {\n type: ParameterType.INT,\n pretty_name: \"Stimulus duration\",\n default: null,\n },\n /** How long to show trial before it ends. */\n trial_duration: {\n type: ParameterType.INT,\n pretty_name: \"Trial duration\",\n default: null,\n },\n /** If true, trial will end when subject makes a response. */\n response_ends_trial: {\n type: ParameterType.BOOL,\n pretty_name: \"Response ends trial\",\n default: true,\n },\n /** Array containing the height (first value) and width (second value) of the canvas element. */\n canvas_size: {\n type: ParameterType.INT,\n array: true,\n pretty_name: \"Canvas size\",\n default: [500, 500],\n },\n },\n};\n\ntype Info = typeof info;\n\n/**\n * **canvas-keyboard-response**\n *\n * jsPsych plugin for displaying a canvas stimulus and getting a keyboard response\n *\n * @author Chris Jungerius (modified from Josh de Leeuw)\n * @see {@link https://www.jspsych.org/plugins/jspsych-canvas-keyboard-response/ canvas-keyboard-response plugin documentation on jspsych.org}\n */\nclass CanvasKeyboardResponsePlugin implements JsPsychPlugin<Info> {\n static info = info;\n\n constructor(private jsPsych: JsPsych) {}\n\n trial(display_element: HTMLElement, trial: TrialType<Info>) {\n var new_html =\n '<div id=\"jspsych-canvas-keyboard-response-stimulus\">' +\n '<canvas id=\"jspsych-canvas-stimulus\" height=\"' +\n trial.canvas_size[0] +\n '\" width=\"' +\n trial.canvas_size[1] +\n '\"></canvas>' +\n \"</div>\";\n // add prompt\n if (trial.prompt !== null) {\n new_html += trial.prompt;\n }\n\n // draw\n display_element.innerHTML = new_html;\n let c = document.getElementById(\"jspsych-canvas-stimulus\");\n trial.stimulus(c);\n // store response\n var response = {\n rt: null,\n key: null,\n };\n\n // function to end trial when it is time\n const end_trial = () => {\n // kill any remaining setTimeout handlers\n this.jsPsych.pluginAPI.clearAllTimeouts();\n\n // kill keyboard listeners\n if (typeof keyboardListener !== \"undefined\") {\n this.jsPsych.pluginAPI.cancelKeyboardResponse(keyboardListener);\n }\n\n // gather the data to store for the trial\n var trial_data = {\n rt: response.rt,\n response: response.key,\n };\n\n // clear the display\n display_element.innerHTML = \"\";\n\n // move on to the next trial\n this.jsPsych.finishTrial(trial_data);\n };\n\n // function to handle responses by the subject\n var after_response = (info) => {\n // after a valid response, the stimulus will have the CSS class 'responded'\n // which can be used to provide visual feedback that a response was recorded\n display_element.querySelector(\"#jspsych-canvas-keyboard-response-stimulus\").className +=\n \" responded\";\n\n // only record the first response\n if (response.key == null) {\n response = info;\n }\n\n if (trial.response_ends_trial) {\n end_trial();\n }\n };\n\n // start the response listener\n if (trial.choices != \"NO_KEYS\") {\n var keyboardListener = this.jsPsych.pluginAPI.getKeyboardResponse({\n callback_function: after_response,\n valid_responses: trial.choices,\n rt_method: \"performance\",\n persist: false,\n allow_held_key: false,\n });\n }\n\n // hide stimulus if stimulus_duration is set\n if (trial.stimulus_duration !== null) {\n this.jsPsych.pluginAPI.setTimeout(() => {\n display_element.querySelector<HTMLElement>(\n \"#jspsych-canvas-keyboard-response-stimulus\"\n ).style.visibility = \"hidden\";\n }, trial.stimulus_duration);\n }\n\n // end trial if trial_duration is set\n if (trial.trial_duration !== null) {\n this.jsPsych.pluginAPI.setTimeout(() => {\n end_trial();\n }, trial.trial_duration);\n }\n }\n\n simulate(\n trial: TrialType<Info>,\n simulation_mode,\n simulation_options: any,\n load_callback: () => void\n ) {\n if (simulation_mode == \"data-only\") {\n load_callback();\n this.simulate_data_only(trial, simulation_options);\n }\n if (simulation_mode == \"visual\") {\n this.simulate_visual(trial, simulation_options, load_callback);\n }\n }\n\n private simulate_data_only(trial: TrialType<Info>, simulation_options) {\n const data = this.create_simulation_data(trial, simulation_options);\n\n this.jsPsych.finishTrial(data);\n }\n\n private simulate_visual(trial: TrialType<Info>, simulation_options, load_callback: () => void) {\n const data = this.create_simulation_data(trial, simulation_options);\n\n const display_element = this.jsPsych.getDisplayElement();\n\n this.trial(display_element, trial);\n load_callback();\n\n if (data.rt !== null) {\n this.jsPsych.pluginAPI.pressKey(data.response, data.rt);\n }\n }\n\n private create_simulation_data(trial: TrialType<Info>, simulation_options) {\n const default_data = {\n rt: this.jsPsych.randomization.sampleExGaussian(500, 50, 1 / 150, true),\n response: this.jsPsych.pluginAPI.getValidKey(trial.choices),\n };\n\n const data = this.jsPsych.pluginAPI.mergeSimulationData(default_data, simulation_options);\n\n this.jsPsych.pluginAPI.ensureSimulationDataConsistency(trial, data);\n\n return data;\n }\n}\n\nexport default CanvasKeyboardResponsePlugin;\n"],"names":["info","name","parameters","stimulus","type","ParameterType","FUNCTION","pretty_name","default","undefined","choices","KEYS","prompt","HTML_STRING","stimulus_duration","INT","trial_duration","response_ends_trial","BOOL","canvas_size","array","CanvasKeyboardResponsePlugin","constructor","jsPsych","this","trial","display_element","new_html","innerHTML","c","document","getElementById","response","rt","key","end_trial","pluginAPI","clearAllTimeouts","keyboardListener","cancelKeyboardResponse","trial_data","finishTrial","getKeyboardResponse","callback_function","querySelector","className","valid_responses","rt_method","persist","allow_held_key","setTimeout","style","visibility","simulate","simulation_mode","simulation_options","load_callback","simulate_data_only","simulate_visual","data","create_simulation_data","getDisplayElement","pressKey","default_data","randomization","sampleExGaussian","getValidKey","mergeSimulationData","ensureSimulationDataConsistency"],"mappings":"2DAEA,MAAMA,EAAc,CAClBC,KAAM,2BACNC,WAAY,CAEVC,SAAU,CACRC,KAAMC,gBAAcC,SACpBC,YAAa,WACbC,aAASC,GAGXC,QAAS,CACPN,KAAMC,gBAAcM,KACpBJ,YAAa,UACbC,QAAS,YAGXI,OAAQ,CACNR,KAAMC,gBAAcQ,YACpBN,YAAa,SACbC,QAAS,MAGXM,kBAAmB,CACjBV,KAAMC,gBAAcU,IACpBR,YAAa,oBACbC,QAAS,MAGXQ,eAAgB,CACdZ,KAAMC,gBAAcU,IACpBR,YAAa,iBACbC,QAAS,MAGXS,oBAAqB,CACnBb,KAAMC,gBAAca,KACpBX,YAAa,sBACbC,SAAS,GAGXW,YAAa,CACXf,KAAMC,gBAAcU,IACpBK,OAAO,EACPb,YAAa,cACbC,QAAS,CAAC,IAAK,QAerB,MAAMa,EAGJC,YAAoBC,GAAAC,aAAAD,EAEpBE,MAAMC,EAA8BD,GAClC,IAAIE,EACF,oGAEAF,EAAMN,YAAY,GAClB,YACAM,EAAMN,YAAY,GAJlB,oBAQmB,OAAjBM,EAAMb,SACRe,GAAYF,EAAMb,QAIpBc,EAAgBE,UAAYD,EAC5B,IAAIE,EAAIC,SAASC,eAAe,2BAChCN,EAAMtB,SAAS0B,GAEf,IAAIG,EAAW,CACbC,GAAI,KACJC,IAAK,MAIP,MAAMC,EAAY,KAEhBX,KAAKD,QAAQa,UAAUC,wBAGS,IAArBC,GACTd,KAAKD,QAAQa,UAAUG,uBAAuBD,GAIhD,IAAIE,EAAa,CACfP,GAAID,EAASC,GACbD,SAAUA,EAASE,KAIrBR,EAAgBE,UAAY,GAG5BJ,KAAKD,QAAQkB,YAAYD,IAqB3B,GAAqB,WAAjBf,EAAMf,QACR,IAAI4B,EAAmBd,KAAKD,QAAQa,UAAUM,oBAAoB,CAChEC,kBAnBkB3C,IAGpB0B,EAAgBkB,cAAc,8CAA8CC,WAC1E,aAGkB,MAAhBb,EAASE,MACXF,EAAWhC,GAGTyB,EAAMR,qBACRkB,KAQAW,gBAAiBrB,EAAMf,QACvBqC,UAAW,cACXC,SAAS,EACTC,gBAAgB,IAKY,OAA5BxB,EAAMX,mBACRU,KAAKD,QAAQa,UAAUc,YAAW,KAChCxB,EAAgBkB,cACd,8CACAO,MAAMC,WAAa,WACpB3B,EAAMX,mBAIkB,OAAzBW,EAAMT,gBACRQ,KAAKD,QAAQa,UAAUc,YAAW,KAChCf,MACCV,EAAMT,gBAIbqC,SACE5B,EACA6B,EACAC,EACAC,GAEuB,aAAnBF,IACFE,IACAhC,KAAKiC,mBAAmBhC,EAAO8B,IAEV,UAAnBD,GACF9B,KAAKkC,gBAAgBjC,EAAO8B,EAAoBC,GAI5CC,mBAAmBhC,EAAwB8B,GACjD,MAAMI,EAAOnC,KAAKoC,uBAAuBnC,EAAO8B,GAEhD/B,KAAKD,QAAQkB,YAAYkB,GAGnBD,gBAAgBjC,EAAwB8B,EAAoBC,GAClE,MAAMG,EAAOnC,KAAKoC,uBAAuBnC,EAAO8B,GAE1C7B,EAAkBF,KAAKD,QAAQsC,oBAErCrC,KAAKC,MAAMC,EAAiBD,GAC5B+B,IAEgB,OAAZG,EAAK1B,IACPT,KAAKD,QAAQa,UAAU0B,SAASH,EAAK3B,SAAU2B,EAAK1B,IAIhD2B,uBAAuBnC,EAAwB8B,GACrD,MAAMQ,EAAe,CACnB9B,GAAIT,KAAKD,QAAQyC,cAAcC,iBAAiB,IAAK,GAAI,EAAI,KAAK,GAClEjC,SAAUR,KAAKD,QAAQa,UAAU8B,YAAYzC,EAAMf,UAG/CiD,EAAOnC,KAAKD,QAAQa,UAAU+B,oBAAoBJ,EAAcR,GAItE,OAFA/B,KAAKD,QAAQa,UAAUgC,gCAAgC3C,EAAOkC,GAEvDA,UA5IFtC,OAAOrB"}
|
package/dist/index.cjs
CHANGED
|
@@ -102,7 +102,7 @@ class CanvasKeyboardResponsePlugin {
|
|
|
102
102
|
this.jsPsych.finishTrial(trial_data);
|
|
103
103
|
};
|
|
104
104
|
// function to handle responses by the subject
|
|
105
|
-
var after_response =
|
|
105
|
+
var after_response = (info) => {
|
|
106
106
|
// after a valid response, the stimulus will have the CSS class 'responded'
|
|
107
107
|
// which can be used to provide visual feedback that a response was recorded
|
|
108
108
|
display_element.querySelector("#jspsych-canvas-keyboard-response-stimulus").className +=
|
|
@@ -127,17 +127,48 @@ class CanvasKeyboardResponsePlugin {
|
|
|
127
127
|
}
|
|
128
128
|
// hide stimulus if stimulus_duration is set
|
|
129
129
|
if (trial.stimulus_duration !== null) {
|
|
130
|
-
this.jsPsych.pluginAPI.setTimeout(
|
|
130
|
+
this.jsPsych.pluginAPI.setTimeout(() => {
|
|
131
131
|
display_element.querySelector("#jspsych-canvas-keyboard-response-stimulus").style.visibility = "hidden";
|
|
132
132
|
}, trial.stimulus_duration);
|
|
133
133
|
}
|
|
134
134
|
// end trial if trial_duration is set
|
|
135
135
|
if (trial.trial_duration !== null) {
|
|
136
|
-
this.jsPsych.pluginAPI.setTimeout(
|
|
136
|
+
this.jsPsych.pluginAPI.setTimeout(() => {
|
|
137
137
|
end_trial();
|
|
138
138
|
}, trial.trial_duration);
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
|
+
simulate(trial, simulation_mode, simulation_options, load_callback) {
|
|
142
|
+
if (simulation_mode == "data-only") {
|
|
143
|
+
load_callback();
|
|
144
|
+
this.simulate_data_only(trial, simulation_options);
|
|
145
|
+
}
|
|
146
|
+
if (simulation_mode == "visual") {
|
|
147
|
+
this.simulate_visual(trial, simulation_options, load_callback);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
simulate_data_only(trial, simulation_options) {
|
|
151
|
+
const data = this.create_simulation_data(trial, simulation_options);
|
|
152
|
+
this.jsPsych.finishTrial(data);
|
|
153
|
+
}
|
|
154
|
+
simulate_visual(trial, simulation_options, load_callback) {
|
|
155
|
+
const data = this.create_simulation_data(trial, simulation_options);
|
|
156
|
+
const display_element = this.jsPsych.getDisplayElement();
|
|
157
|
+
this.trial(display_element, trial);
|
|
158
|
+
load_callback();
|
|
159
|
+
if (data.rt !== null) {
|
|
160
|
+
this.jsPsych.pluginAPI.pressKey(data.response, data.rt);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
create_simulation_data(trial, simulation_options) {
|
|
164
|
+
const default_data = {
|
|
165
|
+
rt: this.jsPsych.randomization.sampleExGaussian(500, 50, 1 / 150, true),
|
|
166
|
+
response: this.jsPsych.pluginAPI.getValidKey(trial.choices),
|
|
167
|
+
};
|
|
168
|
+
const data = this.jsPsych.pluginAPI.mergeSimulationData(default_data, simulation_options);
|
|
169
|
+
this.jsPsych.pluginAPI.ensureSimulationDataConsistency(trial, data);
|
|
170
|
+
return data;
|
|
171
|
+
}
|
|
141
172
|
}
|
|
142
173
|
CanvasKeyboardResponsePlugin.info = info;
|
|
143
174
|
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/index.ts"],"sourcesContent":["import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from \"jspsych\";\n\nconst info = <const>{\n name: \"canvas-keyboard-response\",\n parameters: {\n /** The drawing function to apply to the canvas. Should take the canvas object as argument. */\n stimulus: {\n type: ParameterType.FUNCTION,\n pretty_name: \"Stimulus\",\n default: undefined,\n },\n /** Array containing the key(s) the subject is allowed to press to respond to the stimulus. */\n choices: {\n type: ParameterType.KEYS,\n pretty_name: \"Choices\",\n default: \"ALL_KEYS\",\n },\n /** Any content here will be displayed below the stimulus. */\n prompt: {\n type: ParameterType.HTML_STRING,\n pretty_name: \"Prompt\",\n default: null,\n },\n /** How long to show the stimulus. */\n stimulus_duration: {\n type: ParameterType.INT,\n pretty_name: \"Stimulus duration\",\n default: null,\n },\n /** How long to show trial before it ends. */\n trial_duration: {\n type: ParameterType.INT,\n pretty_name: \"Trial duration\",\n default: null,\n },\n /** If true, trial will end when subject makes a response. */\n response_ends_trial: {\n type: ParameterType.BOOL,\n pretty_name: \"Response ends trial\",\n default: true,\n },\n /** Array containing the height (first value) and width (second value) of the canvas element. */\n canvas_size: {\n type: ParameterType.INT,\n array: true,\n pretty_name: \"Canvas size\",\n default: [500, 500],\n },\n },\n};\n\ntype Info = typeof info;\n\n/**\n * **canvas-keyboard-response**\n *\n * jsPsych plugin for displaying a canvas stimulus and getting a keyboard response\n *\n * @author Chris Jungerius (modified from Josh de Leeuw)\n * @see {@link https://www.jspsych.org/plugins/jspsych-canvas-keyboard-response/ canvas-keyboard-response plugin documentation on jspsych.org}\n */\nclass CanvasKeyboardResponsePlugin implements JsPsychPlugin<Info> {\n static info = info;\n\n constructor(private jsPsych: JsPsych) {}\n\n trial(display_element: HTMLElement, trial: TrialType<Info>) {\n var new_html =\n '<div id=\"jspsych-canvas-keyboard-response-stimulus\">' +\n '<canvas id=\"jspsych-canvas-stimulus\" height=\"' +\n trial.canvas_size[0] +\n '\" width=\"' +\n trial.canvas_size[1] +\n '\"></canvas>' +\n \"</div>\";\n // add prompt\n if (trial.prompt !== null) {\n new_html += trial.prompt;\n }\n\n // draw\n display_element.innerHTML = new_html;\n let c = document.getElementById(\"jspsych-canvas-stimulus\");\n trial.stimulus(c);\n // store response\n var response = {\n rt: null,\n key: null,\n };\n\n // function to end trial when it is time\n const end_trial = () => {\n // kill any remaining setTimeout handlers\n this.jsPsych.pluginAPI.clearAllTimeouts();\n\n // kill keyboard listeners\n if (typeof keyboardListener !== \"undefined\") {\n this.jsPsych.pluginAPI.cancelKeyboardResponse(keyboardListener);\n }\n\n // gather the data to store for the trial\n var trial_data = {\n rt: response.rt,\n response: response.key,\n };\n\n // clear the display\n display_element.innerHTML = \"\";\n\n // move on to the next trial\n this.jsPsych.finishTrial(trial_data);\n };\n\n // function to handle responses by the subject\n var after_response = function (info) {\n // after a valid response, the stimulus will have the CSS class 'responded'\n // which can be used to provide visual feedback that a response was recorded\n display_element.querySelector(\"#jspsych-canvas-keyboard-response-stimulus\").className +=\n \" responded\";\n\n // only record the first response\n if (response.key == null) {\n response = info;\n }\n\n if (trial.response_ends_trial) {\n end_trial();\n }\n };\n\n // start the response listener\n if (trial.choices != \"NO_KEYS\") {\n var keyboardListener = this.jsPsych.pluginAPI.getKeyboardResponse({\n callback_function: after_response,\n valid_responses: trial.choices,\n rt_method: \"performance\",\n persist: false,\n allow_held_key: false,\n });\n }\n\n // hide stimulus if stimulus_duration is set\n if (trial.stimulus_duration !== null) {\n this.jsPsych.pluginAPI.setTimeout(function () {\n display_element.querySelector<HTMLElement>(\n \"#jspsych-canvas-keyboard-response-stimulus\"\n ).style.visibility = \"hidden\";\n }, trial.stimulus_duration);\n }\n\n // end trial if trial_duration is set\n if (trial.trial_duration !== null) {\n this.jsPsych.pluginAPI.setTimeout(function () {\n end_trial();\n }, trial.trial_duration);\n }\n }\n}\n\nexport default CanvasKeyboardResponsePlugin;\n"],"names":["ParameterType"],"mappings":";;;;AAEA,MAAM,IAAI,GAAU;IAClB,IAAI,EAAE,0BAA0B;IAChC,UAAU,EAAE;;QAEV,QAAQ,EAAE;YACR,IAAI,EAAEA,qBAAa,CAAC,QAAQ;YAC5B,WAAW,EAAE,UAAU;YACvB,OAAO,EAAE,SAAS;SACnB;;QAED,OAAO,EAAE;YACP,IAAI,EAAEA,qBAAa,CAAC,IAAI;YACxB,WAAW,EAAE,SAAS;YACtB,OAAO,EAAE,UAAU;SACpB;;QAED,MAAM,EAAE;YACN,IAAI,EAAEA,qBAAa,CAAC,WAAW;YAC/B,WAAW,EAAE,QAAQ;YACrB,OAAO,EAAE,IAAI;SACd;;QAED,iBAAiB,EAAE;YACjB,IAAI,EAAEA,qBAAa,CAAC,GAAG;YACvB,WAAW,EAAE,mBAAmB;YAChC,OAAO,EAAE,IAAI;SACd;;QAED,cAAc,EAAE;YACd,IAAI,EAAEA,qBAAa,CAAC,GAAG;YACvB,WAAW,EAAE,gBAAgB;YAC7B,OAAO,EAAE,IAAI;SACd;;QAED,mBAAmB,EAAE;YACnB,IAAI,EAAEA,qBAAa,CAAC,IAAI;YACxB,WAAW,EAAE,qBAAqB;YAClC,OAAO,EAAE,IAAI;SACd;;QAED,WAAW,EAAE;YACX,IAAI,EAAEA,qBAAa,CAAC,GAAG;YACvB,KAAK,EAAE,IAAI;YACX,WAAW,EAAE,aAAa;YAC1B,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC;SACpB;KACF;CACF,CAAC;AAIF;;;;;;;;AAQA,MAAM,4BAA4B;IAGhC,YAAoB,OAAgB;QAAhB,YAAO,GAAP,OAAO,CAAS;KAAI;IAExC,KAAK,CAAC,eAA4B,EAAE,KAAsB;QACxD,IAAI,QAAQ,GACV,sDAAsD;YACtD,+CAA+C;YAC/C,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;YACpB,WAAW;YACX,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;YACpB,aAAa;YACb,QAAQ,CAAC;;QAEX,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,EAAE;YACzB,QAAQ,IAAI,KAAK,CAAC,MAAM,CAAC;SAC1B;;QAGD,eAAe,CAAC,SAAS,GAAG,QAAQ,CAAC;QACrC,IAAI,CAAC,GAAG,QAAQ,CAAC,cAAc,CAAC,yBAAyB,CAAC,CAAC;QAC3D,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;;QAElB,IAAI,QAAQ,GAAG;YACb,EAAE,EAAE,IAAI;YACR,GAAG,EAAE,IAAI;SACV,CAAC;;QAGF,MAAM,SAAS,GAAG;;YAEhB,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,gBAAgB,EAAE,CAAC;;YAG1C,IAAI,OAAO,gBAAgB,KAAK,WAAW,EAAE;gBAC3C,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;aACjE;;YAGD,IAAI,UAAU,GAAG;gBACf,EAAE,EAAE,QAAQ,CAAC,EAAE;gBACf,QAAQ,EAAE,QAAQ,CAAC,GAAG;aACvB,CAAC;;YAGF,eAAe,CAAC,SAAS,GAAG,EAAE,CAAC;;YAG/B,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;SACtC,CAAC;;QAGF,IAAI,cAAc,GAAG,UAAU,IAAI;;;YAGjC,eAAe,CAAC,aAAa,CAAC,4CAA4C,CAAC,CAAC,SAAS;gBACnF,YAAY,CAAC;;YAGf,IAAI,QAAQ,CAAC,GAAG,IAAI,IAAI,EAAE;gBACxB,QAAQ,GAAG,IAAI,CAAC;aACjB;YAED,IAAI,KAAK,CAAC,mBAAmB,EAAE;gBAC7B,SAAS,EAAE,CAAC;aACb;SACF,CAAC;;QAGF,IAAI,KAAK,CAAC,OAAO,IAAI,SAAS,EAAE;YAC9B,IAAI,gBAAgB,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,mBAAmB,CAAC;gBAChE,iBAAiB,EAAE,cAAc;gBACjC,eAAe,EAAE,KAAK,CAAC,OAAO;gBAC9B,SAAS,EAAE,aAAa;gBACxB,OAAO,EAAE,KAAK;gBACd,cAAc,EAAE,KAAK;aACtB,CAAC,CAAC;SACJ;;QAGD,IAAI,KAAK,CAAC,iBAAiB,KAAK,IAAI,EAAE;YACpC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC;gBAChC,eAAe,CAAC,aAAa,CAC3B,4CAA4C,CAC7C,CAAC,KAAK,CAAC,UAAU,GAAG,QAAQ,CAAC;aAC/B,EAAE,KAAK,CAAC,iBAAiB,CAAC,CAAC;SAC7B;;QAGD,IAAI,KAAK,CAAC,cAAc,KAAK,IAAI,EAAE;YACjC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC;gBAChC,SAAS,EAAE,CAAC;aACb,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;SAC1B;KACF;;AA9FM,iCAAI,GAAG,IAAI;;;;"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/index.ts"],"sourcesContent":["import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from \"jspsych\";\n\nconst info = <const>{\n name: \"canvas-keyboard-response\",\n parameters: {\n /** The drawing function to apply to the canvas. Should take the canvas object as argument. */\n stimulus: {\n type: ParameterType.FUNCTION,\n pretty_name: \"Stimulus\",\n default: undefined,\n },\n /** Array containing the key(s) the subject is allowed to press to respond to the stimulus. */\n choices: {\n type: ParameterType.KEYS,\n pretty_name: \"Choices\",\n default: \"ALL_KEYS\",\n },\n /** Any content here will be displayed below the stimulus. */\n prompt: {\n type: ParameterType.HTML_STRING,\n pretty_name: \"Prompt\",\n default: null,\n },\n /** How long to show the stimulus. */\n stimulus_duration: {\n type: ParameterType.INT,\n pretty_name: \"Stimulus duration\",\n default: null,\n },\n /** How long to show trial before it ends. */\n trial_duration: {\n type: ParameterType.INT,\n pretty_name: \"Trial duration\",\n default: null,\n },\n /** If true, trial will end when subject makes a response. */\n response_ends_trial: {\n type: ParameterType.BOOL,\n pretty_name: \"Response ends trial\",\n default: true,\n },\n /** Array containing the height (first value) and width (second value) of the canvas element. */\n canvas_size: {\n type: ParameterType.INT,\n array: true,\n pretty_name: \"Canvas size\",\n default: [500, 500],\n },\n },\n};\n\ntype Info = typeof info;\n\n/**\n * **canvas-keyboard-response**\n *\n * jsPsych plugin for displaying a canvas stimulus and getting a keyboard response\n *\n * @author Chris Jungerius (modified from Josh de Leeuw)\n * @see {@link https://www.jspsych.org/plugins/jspsych-canvas-keyboard-response/ canvas-keyboard-response plugin documentation on jspsych.org}\n */\nclass CanvasKeyboardResponsePlugin implements JsPsychPlugin<Info> {\n static info = info;\n\n constructor(private jsPsych: JsPsych) {}\n\n trial(display_element: HTMLElement, trial: TrialType<Info>) {\n var new_html =\n '<div id=\"jspsych-canvas-keyboard-response-stimulus\">' +\n '<canvas id=\"jspsych-canvas-stimulus\" height=\"' +\n trial.canvas_size[0] +\n '\" width=\"' +\n trial.canvas_size[1] +\n '\"></canvas>' +\n \"</div>\";\n // add prompt\n if (trial.prompt !== null) {\n new_html += trial.prompt;\n }\n\n // draw\n display_element.innerHTML = new_html;\n let c = document.getElementById(\"jspsych-canvas-stimulus\");\n trial.stimulus(c);\n // store response\n var response = {\n rt: null,\n key: null,\n };\n\n // function to end trial when it is time\n const end_trial = () => {\n // kill any remaining setTimeout handlers\n this.jsPsych.pluginAPI.clearAllTimeouts();\n\n // kill keyboard listeners\n if (typeof keyboardListener !== \"undefined\") {\n this.jsPsych.pluginAPI.cancelKeyboardResponse(keyboardListener);\n }\n\n // gather the data to store for the trial\n var trial_data = {\n rt: response.rt,\n response: response.key,\n };\n\n // clear the display\n display_element.innerHTML = \"\";\n\n // move on to the next trial\n this.jsPsych.finishTrial(trial_data);\n };\n\n // function to handle responses by the subject\n var after_response = (info) => {\n // after a valid response, the stimulus will have the CSS class 'responded'\n // which can be used to provide visual feedback that a response was recorded\n display_element.querySelector(\"#jspsych-canvas-keyboard-response-stimulus\").className +=\n \" responded\";\n\n // only record the first response\n if (response.key == null) {\n response = info;\n }\n\n if (trial.response_ends_trial) {\n end_trial();\n }\n };\n\n // start the response listener\n if (trial.choices != \"NO_KEYS\") {\n var keyboardListener = this.jsPsych.pluginAPI.getKeyboardResponse({\n callback_function: after_response,\n valid_responses: trial.choices,\n rt_method: \"performance\",\n persist: false,\n allow_held_key: false,\n });\n }\n\n // hide stimulus if stimulus_duration is set\n if (trial.stimulus_duration !== null) {\n this.jsPsych.pluginAPI.setTimeout(() => {\n display_element.querySelector<HTMLElement>(\n \"#jspsych-canvas-keyboard-response-stimulus\"\n ).style.visibility = \"hidden\";\n }, trial.stimulus_duration);\n }\n\n // end trial if trial_duration is set\n if (trial.trial_duration !== null) {\n this.jsPsych.pluginAPI.setTimeout(() => {\n end_trial();\n }, trial.trial_duration);\n }\n }\n\n simulate(\n trial: TrialType<Info>,\n simulation_mode,\n simulation_options: any,\n load_callback: () => void\n ) {\n if (simulation_mode == \"data-only\") {\n load_callback();\n this.simulate_data_only(trial, simulation_options);\n }\n if (simulation_mode == \"visual\") {\n this.simulate_visual(trial, simulation_options, load_callback);\n }\n }\n\n private simulate_data_only(trial: TrialType<Info>, simulation_options) {\n const data = this.create_simulation_data(trial, simulation_options);\n\n this.jsPsych.finishTrial(data);\n }\n\n private simulate_visual(trial: TrialType<Info>, simulation_options, load_callback: () => void) {\n const data = this.create_simulation_data(trial, simulation_options);\n\n const display_element = this.jsPsych.getDisplayElement();\n\n this.trial(display_element, trial);\n load_callback();\n\n if (data.rt !== null) {\n this.jsPsych.pluginAPI.pressKey(data.response, data.rt);\n }\n }\n\n private create_simulation_data(trial: TrialType<Info>, simulation_options) {\n const default_data = {\n rt: this.jsPsych.randomization.sampleExGaussian(500, 50, 1 / 150, true),\n response: this.jsPsych.pluginAPI.getValidKey(trial.choices),\n };\n\n const data = this.jsPsych.pluginAPI.mergeSimulationData(default_data, simulation_options);\n\n this.jsPsych.pluginAPI.ensureSimulationDataConsistency(trial, data);\n\n return data;\n }\n}\n\nexport default CanvasKeyboardResponsePlugin;\n"],"names":["ParameterType"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -108,5 +108,9 @@ declare class CanvasKeyboardResponsePlugin implements JsPsychPlugin<Info> {
|
|
|
108
108
|
};
|
|
109
109
|
constructor(jsPsych: JsPsych);
|
|
110
110
|
trial(display_element: HTMLElement, trial: TrialType<Info>): void;
|
|
111
|
+
simulate(trial: TrialType<Info>, simulation_mode: any, simulation_options: any, load_callback: () => void): void;
|
|
112
|
+
private simulate_data_only;
|
|
113
|
+
private simulate_visual;
|
|
114
|
+
private create_simulation_data;
|
|
111
115
|
}
|
|
112
116
|
export default CanvasKeyboardResponsePlugin;
|
package/dist/index.js
CHANGED
|
@@ -100,7 +100,7 @@ class CanvasKeyboardResponsePlugin {
|
|
|
100
100
|
this.jsPsych.finishTrial(trial_data);
|
|
101
101
|
};
|
|
102
102
|
// function to handle responses by the subject
|
|
103
|
-
var after_response =
|
|
103
|
+
var after_response = (info) => {
|
|
104
104
|
// after a valid response, the stimulus will have the CSS class 'responded'
|
|
105
105
|
// which can be used to provide visual feedback that a response was recorded
|
|
106
106
|
display_element.querySelector("#jspsych-canvas-keyboard-response-stimulus").className +=
|
|
@@ -125,17 +125,48 @@ class CanvasKeyboardResponsePlugin {
|
|
|
125
125
|
}
|
|
126
126
|
// hide stimulus if stimulus_duration is set
|
|
127
127
|
if (trial.stimulus_duration !== null) {
|
|
128
|
-
this.jsPsych.pluginAPI.setTimeout(
|
|
128
|
+
this.jsPsych.pluginAPI.setTimeout(() => {
|
|
129
129
|
display_element.querySelector("#jspsych-canvas-keyboard-response-stimulus").style.visibility = "hidden";
|
|
130
130
|
}, trial.stimulus_duration);
|
|
131
131
|
}
|
|
132
132
|
// end trial if trial_duration is set
|
|
133
133
|
if (trial.trial_duration !== null) {
|
|
134
|
-
this.jsPsych.pluginAPI.setTimeout(
|
|
134
|
+
this.jsPsych.pluginAPI.setTimeout(() => {
|
|
135
135
|
end_trial();
|
|
136
136
|
}, trial.trial_duration);
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
|
+
simulate(trial, simulation_mode, simulation_options, load_callback) {
|
|
140
|
+
if (simulation_mode == "data-only") {
|
|
141
|
+
load_callback();
|
|
142
|
+
this.simulate_data_only(trial, simulation_options);
|
|
143
|
+
}
|
|
144
|
+
if (simulation_mode == "visual") {
|
|
145
|
+
this.simulate_visual(trial, simulation_options, load_callback);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
simulate_data_only(trial, simulation_options) {
|
|
149
|
+
const data = this.create_simulation_data(trial, simulation_options);
|
|
150
|
+
this.jsPsych.finishTrial(data);
|
|
151
|
+
}
|
|
152
|
+
simulate_visual(trial, simulation_options, load_callback) {
|
|
153
|
+
const data = this.create_simulation_data(trial, simulation_options);
|
|
154
|
+
const display_element = this.jsPsych.getDisplayElement();
|
|
155
|
+
this.trial(display_element, trial);
|
|
156
|
+
load_callback();
|
|
157
|
+
if (data.rt !== null) {
|
|
158
|
+
this.jsPsych.pluginAPI.pressKey(data.response, data.rt);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
create_simulation_data(trial, simulation_options) {
|
|
162
|
+
const default_data = {
|
|
163
|
+
rt: this.jsPsych.randomization.sampleExGaussian(500, 50, 1 / 150, true),
|
|
164
|
+
response: this.jsPsych.pluginAPI.getValidKey(trial.choices),
|
|
165
|
+
};
|
|
166
|
+
const data = this.jsPsych.pluginAPI.mergeSimulationData(default_data, simulation_options);
|
|
167
|
+
this.jsPsych.pluginAPI.ensureSimulationDataConsistency(trial, data);
|
|
168
|
+
return data;
|
|
169
|
+
}
|
|
139
170
|
}
|
|
140
171
|
CanvasKeyboardResponsePlugin.info = info;
|
|
141
172
|
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from \"jspsych\";\n\nconst info = <const>{\n name: \"canvas-keyboard-response\",\n parameters: {\n /** The drawing function to apply to the canvas. Should take the canvas object as argument. */\n stimulus: {\n type: ParameterType.FUNCTION,\n pretty_name: \"Stimulus\",\n default: undefined,\n },\n /** Array containing the key(s) the subject is allowed to press to respond to the stimulus. */\n choices: {\n type: ParameterType.KEYS,\n pretty_name: \"Choices\",\n default: \"ALL_KEYS\",\n },\n /** Any content here will be displayed below the stimulus. */\n prompt: {\n type: ParameterType.HTML_STRING,\n pretty_name: \"Prompt\",\n default: null,\n },\n /** How long to show the stimulus. */\n stimulus_duration: {\n type: ParameterType.INT,\n pretty_name: \"Stimulus duration\",\n default: null,\n },\n /** How long to show trial before it ends. */\n trial_duration: {\n type: ParameterType.INT,\n pretty_name: \"Trial duration\",\n default: null,\n },\n /** If true, trial will end when subject makes a response. */\n response_ends_trial: {\n type: ParameterType.BOOL,\n pretty_name: \"Response ends trial\",\n default: true,\n },\n /** Array containing the height (first value) and width (second value) of the canvas element. */\n canvas_size: {\n type: ParameterType.INT,\n array: true,\n pretty_name: \"Canvas size\",\n default: [500, 500],\n },\n },\n};\n\ntype Info = typeof info;\n\n/**\n * **canvas-keyboard-response**\n *\n * jsPsych plugin for displaying a canvas stimulus and getting a keyboard response\n *\n * @author Chris Jungerius (modified from Josh de Leeuw)\n * @see {@link https://www.jspsych.org/plugins/jspsych-canvas-keyboard-response/ canvas-keyboard-response plugin documentation on jspsych.org}\n */\nclass CanvasKeyboardResponsePlugin implements JsPsychPlugin<Info> {\n static info = info;\n\n constructor(private jsPsych: JsPsych) {}\n\n trial(display_element: HTMLElement, trial: TrialType<Info>) {\n var new_html =\n '<div id=\"jspsych-canvas-keyboard-response-stimulus\">' +\n '<canvas id=\"jspsych-canvas-stimulus\" height=\"' +\n trial.canvas_size[0] +\n '\" width=\"' +\n trial.canvas_size[1] +\n '\"></canvas>' +\n \"</div>\";\n // add prompt\n if (trial.prompt !== null) {\n new_html += trial.prompt;\n }\n\n // draw\n display_element.innerHTML = new_html;\n let c = document.getElementById(\"jspsych-canvas-stimulus\");\n trial.stimulus(c);\n // store response\n var response = {\n rt: null,\n key: null,\n };\n\n // function to end trial when it is time\n const end_trial = () => {\n // kill any remaining setTimeout handlers\n this.jsPsych.pluginAPI.clearAllTimeouts();\n\n // kill keyboard listeners\n if (typeof keyboardListener !== \"undefined\") {\n this.jsPsych.pluginAPI.cancelKeyboardResponse(keyboardListener);\n }\n\n // gather the data to store for the trial\n var trial_data = {\n rt: response.rt,\n response: response.key,\n };\n\n // clear the display\n display_element.innerHTML = \"\";\n\n // move on to the next trial\n this.jsPsych.finishTrial(trial_data);\n };\n\n // function to handle responses by the subject\n var after_response = function (info) {\n // after a valid response, the stimulus will have the CSS class 'responded'\n // which can be used to provide visual feedback that a response was recorded\n display_element.querySelector(\"#jspsych-canvas-keyboard-response-stimulus\").className +=\n \" responded\";\n\n // only record the first response\n if (response.key == null) {\n response = info;\n }\n\n if (trial.response_ends_trial) {\n end_trial();\n }\n };\n\n // start the response listener\n if (trial.choices != \"NO_KEYS\") {\n var keyboardListener = this.jsPsych.pluginAPI.getKeyboardResponse({\n callback_function: after_response,\n valid_responses: trial.choices,\n rt_method: \"performance\",\n persist: false,\n allow_held_key: false,\n });\n }\n\n // hide stimulus if stimulus_duration is set\n if (trial.stimulus_duration !== null) {\n this.jsPsych.pluginAPI.setTimeout(function () {\n display_element.querySelector<HTMLElement>(\n \"#jspsych-canvas-keyboard-response-stimulus\"\n ).style.visibility = \"hidden\";\n }, trial.stimulus_duration);\n }\n\n // end trial if trial_duration is set\n if (trial.trial_duration !== null) {\n this.jsPsych.pluginAPI.setTimeout(function () {\n end_trial();\n }, trial.trial_duration);\n }\n }\n}\n\nexport default CanvasKeyboardResponsePlugin;\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from \"jspsych\";\n\nconst info = <const>{\n name: \"canvas-keyboard-response\",\n parameters: {\n /** The drawing function to apply to the canvas. Should take the canvas object as argument. */\n stimulus: {\n type: ParameterType.FUNCTION,\n pretty_name: \"Stimulus\",\n default: undefined,\n },\n /** Array containing the key(s) the subject is allowed to press to respond to the stimulus. */\n choices: {\n type: ParameterType.KEYS,\n pretty_name: \"Choices\",\n default: \"ALL_KEYS\",\n },\n /** Any content here will be displayed below the stimulus. */\n prompt: {\n type: ParameterType.HTML_STRING,\n pretty_name: \"Prompt\",\n default: null,\n },\n /** How long to show the stimulus. */\n stimulus_duration: {\n type: ParameterType.INT,\n pretty_name: \"Stimulus duration\",\n default: null,\n },\n /** How long to show trial before it ends. */\n trial_duration: {\n type: ParameterType.INT,\n pretty_name: \"Trial duration\",\n default: null,\n },\n /** If true, trial will end when subject makes a response. */\n response_ends_trial: {\n type: ParameterType.BOOL,\n pretty_name: \"Response ends trial\",\n default: true,\n },\n /** Array containing the height (first value) and width (second value) of the canvas element. */\n canvas_size: {\n type: ParameterType.INT,\n array: true,\n pretty_name: \"Canvas size\",\n default: [500, 500],\n },\n },\n};\n\ntype Info = typeof info;\n\n/**\n * **canvas-keyboard-response**\n *\n * jsPsych plugin for displaying a canvas stimulus and getting a keyboard response\n *\n * @author Chris Jungerius (modified from Josh de Leeuw)\n * @see {@link https://www.jspsych.org/plugins/jspsych-canvas-keyboard-response/ canvas-keyboard-response plugin documentation on jspsych.org}\n */\nclass CanvasKeyboardResponsePlugin implements JsPsychPlugin<Info> {\n static info = info;\n\n constructor(private jsPsych: JsPsych) {}\n\n trial(display_element: HTMLElement, trial: TrialType<Info>) {\n var new_html =\n '<div id=\"jspsych-canvas-keyboard-response-stimulus\">' +\n '<canvas id=\"jspsych-canvas-stimulus\" height=\"' +\n trial.canvas_size[0] +\n '\" width=\"' +\n trial.canvas_size[1] +\n '\"></canvas>' +\n \"</div>\";\n // add prompt\n if (trial.prompt !== null) {\n new_html += trial.prompt;\n }\n\n // draw\n display_element.innerHTML = new_html;\n let c = document.getElementById(\"jspsych-canvas-stimulus\");\n trial.stimulus(c);\n // store response\n var response = {\n rt: null,\n key: null,\n };\n\n // function to end trial when it is time\n const end_trial = () => {\n // kill any remaining setTimeout handlers\n this.jsPsych.pluginAPI.clearAllTimeouts();\n\n // kill keyboard listeners\n if (typeof keyboardListener !== \"undefined\") {\n this.jsPsych.pluginAPI.cancelKeyboardResponse(keyboardListener);\n }\n\n // gather the data to store for the trial\n var trial_data = {\n rt: response.rt,\n response: response.key,\n };\n\n // clear the display\n display_element.innerHTML = \"\";\n\n // move on to the next trial\n this.jsPsych.finishTrial(trial_data);\n };\n\n // function to handle responses by the subject\n var after_response = (info) => {\n // after a valid response, the stimulus will have the CSS class 'responded'\n // which can be used to provide visual feedback that a response was recorded\n display_element.querySelector(\"#jspsych-canvas-keyboard-response-stimulus\").className +=\n \" responded\";\n\n // only record the first response\n if (response.key == null) {\n response = info;\n }\n\n if (trial.response_ends_trial) {\n end_trial();\n }\n };\n\n // start the response listener\n if (trial.choices != \"NO_KEYS\") {\n var keyboardListener = this.jsPsych.pluginAPI.getKeyboardResponse({\n callback_function: after_response,\n valid_responses: trial.choices,\n rt_method: \"performance\",\n persist: false,\n allow_held_key: false,\n });\n }\n\n // hide stimulus if stimulus_duration is set\n if (trial.stimulus_duration !== null) {\n this.jsPsych.pluginAPI.setTimeout(() => {\n display_element.querySelector<HTMLElement>(\n \"#jspsych-canvas-keyboard-response-stimulus\"\n ).style.visibility = \"hidden\";\n }, trial.stimulus_duration);\n }\n\n // end trial if trial_duration is set\n if (trial.trial_duration !== null) {\n this.jsPsych.pluginAPI.setTimeout(() => {\n end_trial();\n }, trial.trial_duration);\n }\n }\n\n simulate(\n trial: TrialType<Info>,\n simulation_mode,\n simulation_options: any,\n load_callback: () => void\n ) {\n if (simulation_mode == \"data-only\") {\n load_callback();\n this.simulate_data_only(trial, simulation_options);\n }\n if (simulation_mode == \"visual\") {\n this.simulate_visual(trial, simulation_options, load_callback);\n }\n }\n\n private simulate_data_only(trial: TrialType<Info>, simulation_options) {\n const data = this.create_simulation_data(trial, simulation_options);\n\n this.jsPsych.finishTrial(data);\n }\n\n private simulate_visual(trial: TrialType<Info>, simulation_options, load_callback: () => void) {\n const data = this.create_simulation_data(trial, simulation_options);\n\n const display_element = this.jsPsych.getDisplayElement();\n\n this.trial(display_element, trial);\n load_callback();\n\n if (data.rt !== null) {\n this.jsPsych.pluginAPI.pressKey(data.response, data.rt);\n }\n }\n\n private create_simulation_data(trial: TrialType<Info>, simulation_options) {\n const default_data = {\n rt: this.jsPsych.randomization.sampleExGaussian(500, 50, 1 / 150, true),\n response: this.jsPsych.pluginAPI.getValidKey(trial.choices),\n };\n\n const data = this.jsPsych.pluginAPI.mergeSimulationData(default_data, simulation_options);\n\n this.jsPsych.pluginAPI.ensureSimulationDataConsistency(trial, data);\n\n return data;\n }\n}\n\nexport default CanvasKeyboardResponsePlugin;\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jspsych/plugin-canvas-keyboard-response",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "jsPsych plugin for displaying a canvas stimulus and getting a keyboard response",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -34,10 +34,10 @@
|
|
|
34
34
|
},
|
|
35
35
|
"homepage": "https://www.jspsych.org/latest/plugins/canvas-keyboard-response",
|
|
36
36
|
"peerDependencies": {
|
|
37
|
-
"jspsych": ">=7.
|
|
37
|
+
"jspsych": ">=7.1.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@jspsych/config": "^1.
|
|
41
|
-
"@jspsych/test-utils": "^1.
|
|
40
|
+
"@jspsych/config": "^1.1.0",
|
|
41
|
+
"@jspsych/test-utils": "^1.1.0"
|
|
42
42
|
}
|
|
43
43
|
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { pressKey, simulateTimeline, startTimeline } from "@jspsych/test-utils";
|
|
2
|
+
import { initJsPsych } from "jspsych";
|
|
3
|
+
|
|
4
|
+
import canvasKeyboardResponse from ".";
|
|
5
|
+
|
|
6
|
+
function drawRect(c) {
|
|
7
|
+
var ctx = c.getContext("2d");
|
|
8
|
+
ctx.beginPath();
|
|
9
|
+
ctx.rect(150, 225, 200, 50);
|
|
10
|
+
ctx.stroke();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
jest.useFakeTimers();
|
|
14
|
+
|
|
15
|
+
describe("canvas-keyboard-response simulation", () => {
|
|
16
|
+
test("data mode works", async () => {
|
|
17
|
+
const timeline = [
|
|
18
|
+
{
|
|
19
|
+
type: canvasKeyboardResponse,
|
|
20
|
+
stimulus: drawRect,
|
|
21
|
+
},
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
const { expectFinished, getData } = await simulateTimeline(timeline);
|
|
25
|
+
|
|
26
|
+
await expectFinished();
|
|
27
|
+
|
|
28
|
+
expect(getData().values()[0].rt).toBeGreaterThan(0);
|
|
29
|
+
expect(typeof getData().values()[0].response).toBe("string");
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// can't run this until we mock canvas elements.
|
|
33
|
+
test("visual mode works", async () => {
|
|
34
|
+
const jsPsych = initJsPsych();
|
|
35
|
+
|
|
36
|
+
const timeline = [
|
|
37
|
+
{
|
|
38
|
+
type: canvasKeyboardResponse,
|
|
39
|
+
stimulus: drawRect,
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
const { expectFinished, expectRunning, getHTML, getData } = await simulateTimeline(
|
|
44
|
+
timeline,
|
|
45
|
+
"visual",
|
|
46
|
+
{},
|
|
47
|
+
jsPsych
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
await expectRunning();
|
|
51
|
+
|
|
52
|
+
expect(getHTML()).toContain("canvas");
|
|
53
|
+
|
|
54
|
+
jest.runAllTimers();
|
|
55
|
+
|
|
56
|
+
await expectFinished();
|
|
57
|
+
|
|
58
|
+
expect(getData().values()[0].rt).toBeGreaterThan(0);
|
|
59
|
+
expect(typeof getData().values()[0].response).toBe("string");
|
|
60
|
+
});
|
|
61
|
+
});
|
package/src/index.ts
CHANGED
|
@@ -112,7 +112,7 @@ class CanvasKeyboardResponsePlugin implements JsPsychPlugin<Info> {
|
|
|
112
112
|
};
|
|
113
113
|
|
|
114
114
|
// function to handle responses by the subject
|
|
115
|
-
var after_response =
|
|
115
|
+
var after_response = (info) => {
|
|
116
116
|
// after a valid response, the stimulus will have the CSS class 'responded'
|
|
117
117
|
// which can be used to provide visual feedback that a response was recorded
|
|
118
118
|
display_element.querySelector("#jspsych-canvas-keyboard-response-stimulus").className +=
|
|
@@ -141,7 +141,7 @@ class CanvasKeyboardResponsePlugin implements JsPsychPlugin<Info> {
|
|
|
141
141
|
|
|
142
142
|
// hide stimulus if stimulus_duration is set
|
|
143
143
|
if (trial.stimulus_duration !== null) {
|
|
144
|
-
this.jsPsych.pluginAPI.setTimeout(
|
|
144
|
+
this.jsPsych.pluginAPI.setTimeout(() => {
|
|
145
145
|
display_element.querySelector<HTMLElement>(
|
|
146
146
|
"#jspsych-canvas-keyboard-response-stimulus"
|
|
147
147
|
).style.visibility = "hidden";
|
|
@@ -150,11 +150,58 @@ class CanvasKeyboardResponsePlugin implements JsPsychPlugin<Info> {
|
|
|
150
150
|
|
|
151
151
|
// end trial if trial_duration is set
|
|
152
152
|
if (trial.trial_duration !== null) {
|
|
153
|
-
this.jsPsych.pluginAPI.setTimeout(
|
|
153
|
+
this.jsPsych.pluginAPI.setTimeout(() => {
|
|
154
154
|
end_trial();
|
|
155
155
|
}, trial.trial_duration);
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
|
+
|
|
159
|
+
simulate(
|
|
160
|
+
trial: TrialType<Info>,
|
|
161
|
+
simulation_mode,
|
|
162
|
+
simulation_options: any,
|
|
163
|
+
load_callback: () => void
|
|
164
|
+
) {
|
|
165
|
+
if (simulation_mode == "data-only") {
|
|
166
|
+
load_callback();
|
|
167
|
+
this.simulate_data_only(trial, simulation_options);
|
|
168
|
+
}
|
|
169
|
+
if (simulation_mode == "visual") {
|
|
170
|
+
this.simulate_visual(trial, simulation_options, load_callback);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
private simulate_data_only(trial: TrialType<Info>, simulation_options) {
|
|
175
|
+
const data = this.create_simulation_data(trial, simulation_options);
|
|
176
|
+
|
|
177
|
+
this.jsPsych.finishTrial(data);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
private simulate_visual(trial: TrialType<Info>, simulation_options, load_callback: () => void) {
|
|
181
|
+
const data = this.create_simulation_data(trial, simulation_options);
|
|
182
|
+
|
|
183
|
+
const display_element = this.jsPsych.getDisplayElement();
|
|
184
|
+
|
|
185
|
+
this.trial(display_element, trial);
|
|
186
|
+
load_callback();
|
|
187
|
+
|
|
188
|
+
if (data.rt !== null) {
|
|
189
|
+
this.jsPsych.pluginAPI.pressKey(data.response, data.rt);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
private create_simulation_data(trial: TrialType<Info>, simulation_options) {
|
|
194
|
+
const default_data = {
|
|
195
|
+
rt: this.jsPsych.randomization.sampleExGaussian(500, 50, 1 / 150, true),
|
|
196
|
+
response: this.jsPsych.pluginAPI.getValidKey(trial.choices),
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
const data = this.jsPsych.pluginAPI.mergeSimulationData(default_data, simulation_options);
|
|
200
|
+
|
|
201
|
+
this.jsPsych.pluginAPI.ensureSimulationDataConsistency(trial, data);
|
|
202
|
+
|
|
203
|
+
return data;
|
|
204
|
+
}
|
|
158
205
|
}
|
|
159
206
|
|
|
160
207
|
export default CanvasKeyboardResponsePlugin;
|