+
+
+
+
+
+
+
+
diff --git a/examples/jspsych-image-keyboard-response.html b/examples/jspsych-image-keyboard-response.html
new file mode 100644
index 00000000..97132169
--- /dev/null
+++ b/examples/jspsych-image-keyboard-response.html
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/jspsych-single-stim.html b/examples/jspsych-single-stim.html
deleted file mode 100644
index bf0cf2d3..00000000
--- a/examples/jspsych-single-stim.html
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/plugins/jspsych-audio-keyboard-response.js b/plugins/jspsych-audio-keyboard-response.js
new file mode 100644
index 00000000..3645d3b5
--- /dev/null
+++ b/plugins/jspsych-audio-keyboard-response.js
@@ -0,0 +1,194 @@
+/**
+ * jspsych-audio-keyboard-response
+ * Josh de Leeuw
+ *
+ * plugin for playing an audio file and getting a keyboard response
+ *
+ * documentation: docs.jspsych.org
+ *
+ **/
+
+jsPsych.plugins["audio-keyboard-response"] = (function() {
+
+ var plugin = {};
+
+ jsPsych.pluginAPI.registerPreload('audio-keyboard-response', 'stimulus', 'audio');
+
+ plugin.info = {
+ name: 'audio-keyboard-response',
+ description: '',
+ parameters: {
+ stimulus: {
+ type: [jsPsych.plugins.parameterType.STRING],
+ default: undefined,
+ no_function: false,
+ description: ''
+ },
+ choices: {
+ type: [jsPsych.plugins.parameterType.KEYCODE],
+ array: true,
+ default: jsPsych.ALL_KEYS,
+ no_function: false,
+ description: ''
+ },
+ prompt: {
+ type: [jsPsych.plugins.parameterType.STRING],
+ default: '',
+ no_function: false,
+ description: ''
+ },
+ timing_response: {
+ type: [jsPsych.plugins.parameterType.INT],
+ default: -1,
+ no_function: false,
+ description: ''
+ },
+ response_ends_trial: {
+ type: [jsPsych.plugins.parameterType.BOOL],
+ default: true,
+ no_function: false,
+ description: ''
+ },
+ trial_ends_after_audio: {
+ type: [jsPsych.plugins.parameterType.BOOL],
+ default: false,
+ no_function: false,
+ description: ''
+ },
+ }
+ }
+
+ plugin.trial = function(display_element, trial) {
+
+ // default parameters
+ trial.choices = trial.choices || jsPsych.ALL_KEYS;
+ trial.response_ends_trial = (typeof trial.response_ends_trial === 'undefined') ? true : trial.response_ends_trial;
+ trial.trial_ends_after_audio = (typeof trial.trial_ends_after_audio === 'undefined') ? false : trial.trial_ends_after_audio;
+ trial.timing_response = trial.timing_response || -1; // if -1, then wait for response forever
+ trial.prompt = (typeof trial.prompt === 'undefined') ? "" : trial.prompt;
+
+ // if any trial variables are functions
+ // this evaluates the function and replaces
+ // it with the output of the function
+ trial = jsPsych.pluginAPI.evaluateFunctionParameters(trial);
+
+ // setup stimulus
+ var context = jsPsych.pluginAPI.audioContext();
+ if(context !== null){
+ var source = context.createBufferSource();
+ source.buffer = jsPsych.pluginAPI.getAudioBuffer(trial.stimulus);
+ source.connect(context.destination);
+ } else {
+ var audio = jsPsych.pluginAPI.getAudioBuffer(trial.stimulus);
+ audio.currentTime = 0;
+ }
+
+ // set up end event if trial needs it
+
+ if(trial.trial_ends_after_audio){
+ if(context !== null){
+ source.onended = function() {
+ end_trial();
+ }
+ } else {
+ audio.addEventListener('ended', end_trial);
+ }
+ }
+
+ // show prompt if there is one
+ if (trial.prompt !== "") {
+ display_element.innerHTML = trial.prompt;
+ }
+
+ // store response
+ var response = {
+ rt: -1,
+ key: -1
+ };
+
+ // function to end trial when it is time
+ function end_trial() {
+
+ // kill any remaining setTimeout handlers
+ jsPsych.pluginAPI.clearAllTimeouts();
+
+ // stop the audio file if it is playing
+ // remove end event listeners if they exist
+ if(context !== null){
+ source.stop();
+ source.onended = function() { }
+ } else {
+ audio.pause();
+ audio.removeEventListener('ended', end_trial);
+ }
+
+ // kill keyboard listeners
+ jsPsych.pluginAPI.cancelAllKeyboardResponses();
+
+ // gather the data to store for the trial
+ var trial_data = {
+ "rt": context !== null ? response.rt * 1000 : response.rt,
+ "stimulus": trial.stimulus,
+ "key_press": response.key
+ };
+
+ // clear the display
+ display_element.innerHTML = '';
+
+ // move on to the next trial
+ jsPsych.finishTrial(trial_data);
+ };
+
+ // function to handle responses by the subject
+ var after_response = function(info) {
+
+ // only record the first response
+ if (response.key == -1) {
+ response = info;
+ }
+
+ if (trial.response_ends_trial) {
+ end_trial();
+ }
+ };
+
+ // start audio
+ if(context !== null){
+ startTime = context.currentTime + 0.1;
+ source.start(startTime);
+ } else {
+ audio.play();
+ }
+
+ // start the response listener
+ if(context !== null) {
+ var keyboardListener = jsPsych.pluginAPI.getKeyboardResponse({
+ callback_function: after_response,
+ valid_responses: trial.choices,
+ rt_method: 'audio',
+ persist: false,
+ allow_held_key: false,
+ audio_context: context,
+ audio_context_start_time: startTime
+ });
+ } else {
+ var keyboardListener = jsPsych.pluginAPI.getKeyboardResponse({
+ callback_function: after_response,
+ valid_responses: trial.choices,
+ rt_method: 'date',
+ persist: false,
+ allow_held_key: false
+ });
+ }
+
+ // end trial if time limit is set
+ if (trial.timing_response > 0) {
+ jsPsych.pluginAPI.setTimeout(function() {
+ end_trial();
+ }, trial.timing_response);
+ }
+
+ };
+
+ return plugin;
+})();
diff --git a/plugins/jspsych-html-keyboard-response.js b/plugins/jspsych-html-keyboard-response.js
new file mode 100644
index 00000000..4512f2b0
--- /dev/null
+++ b/plugins/jspsych-html-keyboard-response.js
@@ -0,0 +1,154 @@
+/**
+ * jspsych-html-keyboard-response
+ * Josh de Leeuw
+ *
+ * plugin for displaying a stimulus and getting a keyboard response
+ *
+ * documentation: docs.jspsych.org
+ *
+ **/
+
+
+jsPsych.plugins["html-keyboard-response"] = (function() {
+
+ var plugin = {};
+
+ plugin.info = {
+ name: 'html-keyboard-response',
+ description: '',
+ parameters: {
+ stimulus: {
+ type: [jsPsych.plugins.parameterType.HTML_STRING],
+ default: undefined,
+ no_function: false,
+ description: ''
+ },
+ choices: {
+ type: [jsPsych.plugins.parameterType.KEYCODE],
+ array: true,
+ default: jsPsych.ALL_KEYS,
+ no_function: false,
+ description: ''
+ },
+ prompt: {
+ type: [jsPsych.plugins.parameterType.STRING],
+ default: '',
+ no_function: false,
+ description: ''
+ },
+ stimulus_duration: {
+ type: [jsPsych.plugins.parameterType.INT],
+ default: -1,
+ no_function: false,
+ description: ''
+ },
+ trial_duration: {
+ type: [jsPsych.plugins.parameterType.INT],
+ default: -1,
+ no_function: false,
+ description: ''
+ },
+ response_ends_trial: {
+ type: [jsPsych.plugins.parameterType.BOOL],
+ default: true,
+ no_function: false,
+ description: ''
+ },
+
+ }
+ }
+
+ plugin.trial = function(display_element, trial) {
+
+ // set default values for the parameters
+ trial.choices = trial.choices || jsPsych.ALL_KEYS;
+ trial.response_ends_trial = (typeof trial.response_ends_trial == 'undefined') ? true : trial.response_ends_trial;
+ trial.stimulus_duration = trial.stimulus_duration || -1;
+ trial.trial_duration = trial.trial_duration || -1;
+ trial.prompt = trial.prompt || "";
+
+ var new_html = '
'+trial.stimulus+'
';
+
+ // add prompt
+ new_html += trial.prompt;
+
+ // draw
+ display_element.innerHTML = new_html;
+
+ // store response
+ var response = {
+ rt: -1,
+ key: -1
+ };
+
+ // function to end trial when it is time
+ var end_trial = function() {
+
+ // kill any remaining setTimeout handlers
+ jsPsych.pluginAPI.clearAllTimeouts();
+
+ // kill keyboard listeners
+ if (typeof keyboardListener !== 'undefined') {
+ jsPsych.pluginAPI.cancelKeyboardResponse(keyboardListener);
+ }
+
+ // gather the data to store for the trial
+ var trial_data = {
+ "rt": response.rt,
+ "stimulus": trial.stimulus,
+ "key_press": response.key
+ };
+
+ // clear the display
+ display_element.innerHTML = '';
+
+ // move on to the next trial
+ jsPsych.finishTrial(trial_data);
+ };
+
+ // function to handle responses by the subject
+ var after_response = function(info) {
+
+ // after a valid response, the stimulus will have the CSS class 'responded'
+ // which can be used to provide visual feedback that a response was recorded
+ display_element.querySelector('#jspsych-html-keyboard-response-stimulus').className += ' responded';
+
+ // only record the first response
+ if (response.key == -1) {
+ response = info;
+ }
+
+ if (trial.response_ends_trial) {
+ end_trial();
+ }
+ };
+
+ // start the response listener
+ if (trial.choices != jsPsych.NO_KEYS) {
+ var keyboardListener = jsPsych.pluginAPI.getKeyboardResponse({
+ callback_function: after_response,
+ valid_responses: trial.choices,
+ rt_method: 'date',
+ persist: false,
+ allow_held_key: false
+ });
+ }
+
+ // hide stimulus if stimulus_duration is set
+ if (trial.stimulus_duration > 0) {
+ jsPsych.pluginAPI.setTimeout(function() {
+ display_element.querySelector('#jspsych-html-keyboard-response-stimulus').style.visibility = 'hidden';
+ }, trial.stimulus_duration);
+ }
+
+ // end trial if trial_duration is set
+ if (trial.trial_duration > 0) {
+ jsPsych.pluginAPI.setTimeout(function() {
+ end_trial();
+ }, trial.trial_duration);
+ }
+
+ };
+
+ return plugin;
+})();
diff --git a/plugins/jspsych-button-response.js b/plugins/jspsych-image-button-response.js
similarity index 67%
rename from plugins/jspsych-button-response.js
rename to plugins/jspsych-image-button-response.js
index c29b6e4c..04178145 100644
--- a/plugins/jspsych-button-response.js
+++ b/plugins/jspsych-image-button-response.js
@@ -1,5 +1,5 @@
/**
- * jspsych-button-response
+ * jspsych-image-button-response
* Josh de Leeuw
*
* plugin for displaying a stimulus and getting a keyboard response
@@ -8,28 +8,22 @@
*
**/
-jsPsych.plugins["button-response"] = (function() {
+jsPsych.plugins["image-button-response"] = (function() {
var plugin = {};
- jsPsych.pluginAPI.registerPreload('button-response', 'stimulus', 'image', function(t){ return !t.is_html || t.is_html == 'undefined'});
+ jsPsych.pluginAPI.registerPreload('image-button-response', 'stimulus', 'image');
plugin.info = {
- name: 'button-response',
+ name: 'image-button-response',
description: '',
parameters: {
stimulus: {
- type: [jsPsych.plugins.parameterType.STRING],
+ type: [jsPsych.plugins.parameterType.IMAGE],
default: undefined,
no_function: false,
description: ''
},
- is_html: {
- type: [jsPsych.plugins.parameterType.BOOL],
- default: false,
- no_function: false,
- description: ''
- },
choices: {
type: [jsPsych.plugins.parameterType.KEYCODE],
default: [],
@@ -50,13 +44,13 @@ jsPsych.plugins["button-response"] = (function() {
no_function: false,
description: ''
},
- timing_stim: {
+ stimulus_duration: {
type: [jsPsych.plugins.parameterType.INT],
default: -1,
no_function: false,
description: ''
},
- timing_response: {
+ trial_duration: {
type: [jsPsych.plugins.parameterType.INT],
default: -1,
no_function: false,
@@ -76,9 +70,8 @@ jsPsych.plugins["button-response"] = (function() {
// default trial parameters
trial.button_html = trial.button_html || '';
trial.response_ends_trial = (typeof trial.response_ends_trial === 'undefined') ? true : trial.response_ends_trial;
- trial.timing_stim = trial.timing_stim || -1; // if -1, then show indefinitely
- trial.timing_response = trial.timing_response || -1; // if -1, then wait for response forever
- trial.is_html = (typeof trial.is_html === 'undefined') ? false : trial.is_html;
+ trial.stimulus_duration = trial.stimulus_duration || -1; // if -1, then show indefinitely
+ trial.trial_duration = trial.trial_duration || -1; // if -1, then wait for response forever
trial.prompt = (typeof trial.prompt === 'undefined') ? "" : trial.prompt;
trial.margin_vertical = trial.margin_vertical || "0px";
trial.margin_horizontal = trial.margin_horizontal || "8px";
@@ -89,11 +82,7 @@ jsPsych.plugins["button-response"] = (function() {
trial = jsPsych.pluginAPI.evaluateFunctionParameters(trial);
// display stimulus
- if (!trial.is_html) {
- display_element.innerHTML = '';
- } else {
- display_element.innerHTML = '
'+trial.stimulus+'
';
- }
+ display_element.innerHTML = '';
//display buttons
var buttons = [];
@@ -101,19 +90,19 @@ jsPsych.plugins["button-response"] = (function() {
if (trial.button_html.length == trial.choices.length) {
buttons = trial.button_html;
} else {
- console.error('Error in button-response plugin. The length of the button_html array does not equal the length of the choices array');
+ console.error('Error in image-button-response plugin. The length of the button_html array does not equal the length of the choices array');
}
} else {
for (var i = 0; i < trial.choices.length; i++) {
buttons.push(trial.button_html);
}
}
- display_element.innerHTML += '';
+ display_element.innerHTML += '';
for (var i = 0; i < trial.choices.length; i++) {
var str = buttons[i].replace(/%choice%/g, trial.choices[i]);
- display_element.querySelector('#jspsych-button-response-btngroup').insertAdjacentHTML('beforeend',
- '