Compare commits
5 Commits
jspsych@6.
...
a0eda84fd8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a0eda84fd8 | ||
|
|
f13361932a | ||
|
|
23ec2b02b9 | ||
|
|
2a130f79b8 | ||
|
|
1cd4dd8a95 |
@@ -11,8 +11,12 @@ We've implemented some generic methods for audio testing with jsPsych:
|
|||||||
|
|
||||||
* A plugin to do alternative forced choice with sounds: [jspsych-audio-sequence-button-response](docs/jspsych-audio-sequence-button-response.md).
|
* A plugin to do alternative forced choice with sounds: [jspsych-audio-sequence-button-response](docs/jspsych-audio-sequence-button-response.md).
|
||||||
* A plugin to do extend `audio-keyboard-response`: [jspsych-audio-keyboard-response-wait](docs/jspsych-audio-keyboard-response-wait.md).
|
* A plugin to do extend `audio-keyboard-response`: [jspsych-audio-keyboard-response-wait](docs/jspsych-audio-keyboard-response-wait.md).
|
||||||
|
* A plugin to do extend `audio-keyboard-response`: [jspsych-audio-keyboard-response-clickable](plugins/jspsych-audio-keyboard-response-clickable.js).
|
||||||
* A plugin to display a Coordinate Response Measure interface: [jspsych-crm](docs/jspsych-crm.md).
|
* A plugin to display a Coordinate Response Measure interface: [jspsych-crm](docs/jspsych-crm.md).
|
||||||
* A plugin to do display a loading spinner while waiting for a (possible async) function to complete: [jspsych-waitfor-function](docs/jspsych-waitfor-function.md).
|
* A plugin to do display a loading spinner while waiting for a (possible async) function to complete: [jspsych-waitfor-function](docs/jspsych-waitfor-function.md).
|
||||||
|
* A plugin where html can be clickable: [jspsych-html-keyboard-response-clickable](plugins/jspsych-html-keyboard-response-clickable.js).
|
||||||
|
* A plugin where images can be clickable: [jspsych-image-keyboard-response-clickable](plugins/jspsych-image-keyboard-response-clickable.js).
|
||||||
|
* A plugin to deal with Safari's quirky behaviour: [jspsych-audio-safari-init](plugins/jspsych-audio-safari-init.js).
|
||||||
|
|
||||||
## Tools
|
## Tools
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ The trial can end when the subject responds, when the audio file has finished pl
|
|||||||
|
|
||||||
Note that the buttons are disabled during playing so the subject cannot press any button during that time.
|
Note that the buttons are disabled during playing so the subject cannot press any button during that time.
|
||||||
|
|
||||||
|
Make sure to define a CSS style for `.jspsych-audio-sequence-button-response button.highlighted` to see the button light up, and you may have to use `!important` for it to show up.
|
||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
|
|
||||||
Parameters with a default value of *undefined* must be specified. Other parameters can be left unspecified if the default value is acceptable.
|
Parameters with a default value of *undefined* must be specified. Other parameters can be left unspecified if the default value is acceptable.
|
||||||
@@ -72,6 +74,18 @@ The animation of the visual feedback can make use of [Semantic UI's transitions]
|
|||||||
|
|
||||||
#### Three alternative forced choice (3AFC)
|
#### Three alternative forced choice (3AFC)
|
||||||
|
|
||||||
|
CSS:
|
||||||
|
```css
|
||||||
|
.jspsych-audio-sequence-button-response button {
|
||||||
|
min-width: 5em;
|
||||||
|
min-height: 4em;
|
||||||
|
}
|
||||||
|
.jspsych-audio-sequence-button-response button.highlighted {
|
||||||
|
background-color: #ffff00 !important;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Javascript:
|
||||||
```javascript
|
```javascript
|
||||||
var trial = {
|
var trial = {
|
||||||
type: 'audio-button-response',
|
type: 'audio-button-response',
|
||||||
|
|||||||
18
js/tools.js
18
js/tools.js
@@ -5,6 +5,8 @@
|
|||||||
* (only to check if the sound level adjustment has been done already).
|
* (only to check if the sound level adjustment has been done already).
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// Latest version at https://git.web.rug.nl/dBSPL/jspsych-plugins/src/branch/main/js/tools.js
|
||||||
|
|
||||||
function is_browser_compatible(){
|
function is_browser_compatible(){
|
||||||
// Add here everything that needs to be tested for browser compatibility
|
// Add here everything that needs to be tested for browser compatibility
|
||||||
if( (new Audio()).canPlayType('audio/mp3') != 'probably' )
|
if( (new Audio()).canPlayType('audio/mp3') != 'probably' )
|
||||||
@@ -61,22 +63,28 @@ SLADi18n['title'] = {};
|
|||||||
SLADi18n['title']['fr'] = "Réglage du volume";
|
SLADi18n['title']['fr'] = "Réglage du volume";
|
||||||
SLADi18n['title']['en'] = "Sound level adjustment";
|
SLADi18n['title']['en'] = "Sound level adjustment";
|
||||||
SLADi18n['title']['nl'] = "Geluidsvolume";
|
SLADi18n['title']['nl'] = "Geluidsvolume";
|
||||||
|
SLADi18n['title']['de'] = "Lautstärkeanpassung";
|
||||||
SLADi18n['intro'] = {};
|
SLADi18n['intro'] = {};
|
||||||
SLADi18n['intro']['fr'] = "Il est conseillé de completer cette expérience dans un <b>environnement calme</b>, et de préférence en utilisant un <b>casque de bonne qualité</b>. Ajustez le volume de votre ordinateur de façon à ce que le son soit présenté à un niveau confortable, et gardez le volume identique pendant toute la durée de l'expérience.";
|
SLADi18n['intro']['fr'] = "Il est conseillé de completer cette expérience dans un <b>environnement calme</b>, et de préférence en utilisant un <b>casque de bonne qualité</b>. Ajustez le volume de votre ordinateur de façon à ce que le son soit présenté à un niveau confortable, et gardez le volume identique pendant toute la durée de l'expérience.";
|
||||||
SLADi18n['intro']['en'] = "You are kindly asked to perform this experiment in a <b>calm environment</b>, and preferably using <b>good quality headphones</b>. Adjust the sound level on your computer so that the sound plays at a comfortable level, and keep the volume the same during the whole experiment.";
|
SLADi18n['intro']['en'] = "You are kindly asked to perform this experiment in a <b>calm environment</b>, and preferably using <b>good quality headphones</b>. Adjust the sound level on your computer so that the sound plays at a comfortable level, and keep the volume the same during the whole experiment.";
|
||||||
SLADi18n['intro']['nl'] = "U wordt vriendelijk verzocht om dit experiment in een <b>stille omgeving</b> uit te voeren en bij voorkeur een <b>koptelefoon van goede kwaliteit</b> te gebruiken. Pas het geluidsvolume op uw computer aan zodat het geluid op een comfortabel niveau wordt afgespeeld, en verander het geluidsniveau verder niet meer gedurende het experiment.";
|
SLADi18n['intro']['nl'] = "U wordt vriendelijk verzocht om dit experiment in een <b>stille omgeving</b> uit te voeren en bij voorkeur een <b>koptelefoon van goede kwaliteit</b> te gebruiken. Pas het geluidsvolume op uw computer aan zodat het geluid op een comfortabel niveau wordt afgespeeld, en verander het geluidsniveau verder niet meer gedurende het experiment.";
|
||||||
|
SLADi18n['intro']['de'] = "Wir bitten Sie freundlich, dieses Experiment in einer ruhigen Umgebung und möglichst mit hochwertigen Kopfhörern durchzuführen. Stellen Sie die Lautstärke Ihres Computers so ein, dass der Klang in einer angenehmen Lautstärke wiedergegeben wird, und behalten Sie diese Einstellung während des gesamten Experiments bei.";
|
||||||
SLADi18n['loading'] = {};
|
SLADi18n['loading'] = {};
|
||||||
SLADi18n['loading']['fr'] = "Chargement...";
|
SLADi18n['loading']['fr'] = "Chargement...";
|
||||||
SLADi18n['loading']['en'] = "Loading...";
|
SLADi18n['loading']['en'] = "Loading...";
|
||||||
SLADi18n['loading']['nl'] = "Bezig met laden...";
|
SLADi18n['loading']['nl'] = "Bezig met laden...";
|
||||||
SLADi18n['when-ready'] = {};
|
SLADi18n['loading']['de'] = "Wird geladen...";
|
||||||
SLADi18n['when-ready']['fr'] = "Quand vous êtes prêt.e, cliquez sur \"Continuer\".";
|
|
||||||
SLADi18n['when-ready']['en'] = "When you are ready, click on \"Continue\".";
|
|
||||||
SLADi18n['when-ready']['nl'] = "Als u klaar bent, klik je op \"Doorgaan\".";
|
|
||||||
SLADi18n['continue'] = {};
|
SLADi18n['continue'] = {};
|
||||||
SLADi18n['continue']['fr'] = "Continuer";
|
SLADi18n['continue']['fr'] = "Continuer";
|
||||||
SLADi18n['continue']['en'] = "Continue";
|
SLADi18n['continue']['en'] = "Continue";
|
||||||
SLADi18n['continue']['nl'] = "Doorgaan";
|
SLADi18n['continue']['nl'] = "Doorgaan";
|
||||||
|
SLADi18n['continue']['de'] = "Weiter";
|
||||||
|
SLADi18n['when-ready'] = {};
|
||||||
|
SLADi18n['when-ready']['fr'] = `Quand vous êtes prêt.e, cliquez sur "${SLADi18n['continue']['fr']}".`;
|
||||||
|
SLADi18n['when-ready']['en'] = `When you are ready, click on "${SLADi18n['continue']['en']}".`;
|
||||||
|
SLADi18n['when-ready']['nl'] = `Als u klaar bent, klik je op "${SLADi18n['continue']['nl']}".`;
|
||||||
|
SLADi18n['when-ready']['de'] = `Um fortzufahren, klicken Sie bitte auf "${SLADi18n['continue']['de']}".`;
|
||||||
|
|
||||||
|
|
||||||
function _make_sound_level_adjustment(sound_file, after_cb)
|
function _make_sound_level_adjustment(sound_file, after_cb)
|
||||||
{
|
{
|
||||||
@@ -354,7 +362,7 @@ if(!Array.range) {
|
|||||||
if(!Array.linspace) {
|
if(!Array.linspace) {
|
||||||
Array.linspace = function(start, end, n){
|
Array.linspace = function(start, end, n){
|
||||||
var a = [];
|
var a = [];
|
||||||
var step = (end-start)/n;
|
var step = (end-start)/(n-1);
|
||||||
for(var i=0; i<n; i++){
|
for(var i=0; i<n; i++){
|
||||||
a.push(start+step*i);
|
a.push(start+step*i);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
/**
|
/**
|
||||||
* jspsych-audio-sequence-button-response
|
* jspsych-audio-sequence-button-response for jsPsych v6.3
|
||||||
* Etienne Gaudrain <etienne.gaudrain@cnrs.fr>
|
* Etienne Gaudrain <etienne.gaudrain@cnrs.fr> 2021-10-15
|
||||||
*
|
*
|
||||||
* Plugin for playing a sequence of audio files and getting an HTML button response
|
* Plugin for playing a sequence of audio files and getting an HTML button response
|
||||||
*
|
*
|
||||||
* Based on jspsych-audio-button-response.
|
* Based on jspsych-audio-button-response.
|
||||||
|
*
|
||||||
|
* 2022-03-19: Fixed bug that ISI was applied also to last item.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
jsPsych.plugins["audio-sequence-button-response"] = (function() {
|
jsPsych.plugins["audio-sequence-button-response"] = (function() {
|
||||||
@@ -103,11 +105,7 @@ jsPsych.plugins["audio-sequence-button-response"] = (function() {
|
|||||||
plugin.trial = function(display_element, trial) {
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
var context = jsPsych.pluginAPI.audioContext();
|
var context = jsPsych.pluginAPI.audioContext();
|
||||||
if(context !== null) {
|
|
||||||
var source;
|
|
||||||
} else {
|
|
||||||
var audio;
|
var audio;
|
||||||
}
|
|
||||||
|
|
||||||
if(trial.visual_feedback===true && trial.i_correct===null)
|
if(trial.visual_feedback===true && trial.i_correct===null)
|
||||||
throw "'i_correct' has to be defined if visual feedback is requested.";
|
throw "'i_correct' has to be defined if visual feedback is requested.";
|
||||||
@@ -125,12 +123,6 @@ jsPsych.plugins["audio-sequence-button-response"] = (function() {
|
|||||||
play_next_audio.i = 0;
|
play_next_audio.i = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// We un-highlight the previous button
|
|
||||||
if(play_next_audio.i>0)
|
|
||||||
$(display_element).find('#jspsych-audio-sequence-button-response-' + (play_next_audio.i-1) +' button').toggleClass('highlighted');
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Is it the last stimulus, do we need to end trial?
|
// Is it the last stimulus, do we need to end trial?
|
||||||
if(play_next_audio.i >= trial.stimuli.length) {
|
if(play_next_audio.i >= trial.stimuli.length) {
|
||||||
$(display_element).find(".jspsych-audio-sequence-button-response button").removeClass("disabled").prop('disabled', false);
|
$(display_element).find(".jspsych-audio-sequence-button-response button").removeClass("disabled").prop('disabled', false);
|
||||||
@@ -141,34 +133,37 @@ jsPsych.plugins["audio-sequence-button-response"] = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Prepare the next sound to play
|
// Prepare the next sound to play
|
||||||
|
jsPsych.pluginAPI.getAudioBuffer(trial.stimuli[play_next_audio.i]).then(function(buffer){
|
||||||
if(context !== null) {
|
if(context !== null) {
|
||||||
source = context.createBufferSource();
|
audio = context.createBufferSource();
|
||||||
source.buffer = jsPsych.pluginAPI.getAudioBuffer(trial.stimuli[play_next_audio.i]);
|
audio.buffer = buffer;
|
||||||
source.connect(context.destination);
|
audio.connect(context.destination);
|
||||||
source.onended = function(){
|
|
||||||
$(display_element).find('.jspsych-audio-sequence-button-response button.highlighted').removeClass('highlighted');
|
|
||||||
setTimeout(play_next_audio, trial.isi);
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
audio = jsPsych.pluginAPI.getAudioBuffer(trial.stimuli[play_next_audio.i]);
|
audio = buffer;
|
||||||
audio.currentTime = 0;
|
audio.currentTime = 0;
|
||||||
audio.addEventListener('ended', function(){
|
|
||||||
$(display_element).find('.jspsych-audio-sequence-button-response button.highlighted').removeClass('highlighted');
|
|
||||||
setTimeout(play_next_audio, trial.isi);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
audio.addEventListener('ended', function _audio_ended(){
|
||||||
|
$(display_element).find('.jspsych-audio-sequence-button-response button.highlighted').removeClass('highlighted');
|
||||||
|
if(play_next_audio.i<trial.stimuli.length){
|
||||||
|
setTimeout(play_next_audio, trial.isi);
|
||||||
|
} else {
|
||||||
|
setTimeout(play_next_audio, 0);
|
||||||
|
}
|
||||||
|
audio.removeEventListener('ended', _audio_ended);
|
||||||
|
});
|
||||||
|
|
||||||
// Highlight the current button
|
// Highlight the current button
|
||||||
$(display_element).find('#jspsych-audio-sequence-button-response-' + play_next_audio.i +' button').addClass('highlighted');
|
$(display_element).find('#jspsych-audio-sequence-button-response-' + play_next_audio.i +' button').addClass('highlighted');
|
||||||
|
|
||||||
if(context !== null) {
|
if(context !== null) {
|
||||||
startTime = context.currentTime;
|
startTime = context.currentTime;
|
||||||
source.start(startTime);
|
audio.start(startTime);
|
||||||
} else {
|
} else {
|
||||||
audio.play();
|
audio.play();
|
||||||
}
|
}
|
||||||
|
|
||||||
play_next_audio.i++;
|
play_next_audio.i++;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//display buttons
|
//display buttons
|
||||||
@@ -288,12 +283,11 @@ jsPsych.plugins["audio-sequence-button-response"] = (function() {
|
|||||||
// stop the audio file if it is playing
|
// stop the audio file if it is playing
|
||||||
// remove end event listeners if they exist
|
// remove end event listeners if they exist
|
||||||
if(context !== null) {
|
if(context !== null) {
|
||||||
source.stop();
|
audio.stop();
|
||||||
source.onended = function() {}
|
|
||||||
} else {
|
} else {
|
||||||
audio.pause();
|
audio.pause();
|
||||||
audio.removeEventListener('ended', end_trial);
|
|
||||||
}
|
}
|
||||||
|
audio.removeEventListener('ended', end_trial);
|
||||||
|
|
||||||
// kill any remaining setTimeout handlers
|
// kill any remaining setTimeout handlers
|
||||||
jsPsych.pluginAPI.clearAllTimeouts();
|
jsPsych.pluginAPI.clearAllTimeouts();
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* Etienne Gaudrain
|
* Etienne Gaudrain
|
||||||
*
|
*
|
||||||
* Based on:
|
* Based on:
|
||||||
* jspsych-image-keyboard-response @6.1.0
|
* jspsych-image-keyboard-response @6.2.0
|
||||||
* Josh de Leeuw
|
* Josh de Leeuw
|
||||||
*
|
*
|
||||||
* plugin for displaying a stimulus and getting a keyboard response or click on
|
* plugin for displaying a stimulus and getting a keyboard response or click on
|
||||||
@@ -21,7 +21,7 @@ jsPsych.plugins["image-keyboard-response-clickable"] = (function() {
|
|||||||
jsPsych.pluginAPI.registerPreload('image-keyboard-response-clickable', 'stimulus', 'image');
|
jsPsych.pluginAPI.registerPreload('image-keyboard-response-clickable', 'stimulus', 'image');
|
||||||
|
|
||||||
plugin.info = {
|
plugin.info = {
|
||||||
name: 'image-keyboard-response',
|
name: 'image-keyboard-response-clickable',
|
||||||
description: '',
|
description: '',
|
||||||
parameters: {
|
parameters: {
|
||||||
stimulus: {
|
stimulus: {
|
||||||
@@ -85,37 +85,102 @@ jsPsych.plugins["image-keyboard-response-clickable"] = (function() {
|
|||||||
default: true,
|
default: true,
|
||||||
description: 'If true, trial will end when subject makes a response.'
|
description: 'If true, trial will end when subject makes a response.'
|
||||||
},
|
},
|
||||||
|
render_on_canvas: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Render on canvas',
|
||||||
|
default: true,
|
||||||
|
description: 'If true, the image will be drawn onto a canvas element (prevents blank screen between consecutive images in some browsers).' +
|
||||||
|
'If false, the image will be shown via an img element.'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin.trial = function(display_element, trial) {
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
var start_time;
|
var height, width, start_time;
|
||||||
|
if(trial.render_on_canvas) {
|
||||||
// display stimulus
|
// first clear the display element (because the render_on_canvas method appends to display_element instead of overwriting it with .innerHTML)
|
||||||
var html = '<img src="' + trial.stimulus + '" id="jspsych-image-keyboard-response-stimulus" style="';
|
if(display_element.hasChildNodes()) {
|
||||||
if(trial.stimulus_height !== null) {
|
// can't loop through child list because the list will be modified by .removeChild()
|
||||||
html += 'height:' + trial.stimulus_height + 'px; '
|
while(display_element.firstChild) {
|
||||||
if(trial.stimulus_width == null && trial.maintain_aspect_ratio) {
|
display_element.removeChild(display_element.firstChild);
|
||||||
html += 'width: auto; ';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// create canvas element and image
|
||||||
|
var canvas = document.createElement("canvas");
|
||||||
|
canvas.id = "jspsych-image-keyboard-response-stimulus";
|
||||||
|
canvas.style.margin = 0;
|
||||||
|
canvas.style.padding = 0;
|
||||||
|
var img = new Image();
|
||||||
|
img.src = trial.stimulus;
|
||||||
|
// determine image height and width
|
||||||
|
if(trial.stimulus_height !== null) {
|
||||||
|
height = trial.stimulus_height;
|
||||||
|
if(trial.stimulus_width == null && trial.maintain_aspect_ratio) {
|
||||||
|
width = img.naturalWidth * (trial.stimulus_height / img.naturalHeight);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
height = img.naturalHeight;
|
||||||
|
}
|
||||||
if(trial.stimulus_width !== null) {
|
if(trial.stimulus_width !== null) {
|
||||||
html += 'width:' + trial.stimulus_width + 'px; '
|
width = trial.stimulus_width;
|
||||||
if(trial.stimulus_height == null && trial.maintain_aspect_ratio) {
|
if(trial.stimulus_height == null && trial.maintain_aspect_ratio) {
|
||||||
html += 'height: auto; ';
|
height = img.naturalHeight * (trial.stimulus_width / img.naturalWidth);
|
||||||
}
|
}
|
||||||
|
} else if(!(trial.stimulus_height !== null & trial.maintain_aspect_ratio)) {
|
||||||
|
// if stimulus width is null, only use the image's natural width if the width value wasn't set
|
||||||
|
// in the if statement above, based on a specified height and maintain_aspect_ratio = true
|
||||||
|
width = img.naturalWidth;
|
||||||
|
}
|
||||||
|
canvas.height = height;
|
||||||
|
canvas.width = width;
|
||||||
|
// add canvas and draw image
|
||||||
|
display_element.insertBefore(canvas, null);
|
||||||
|
var ctx = canvas.getContext("2d");
|
||||||
|
ctx.drawImage(img, 0, 0, width, height);
|
||||||
|
// add prompt if there is one
|
||||||
|
if(trial.prompt !== null) {
|
||||||
|
display_element.insertAdjacentHTML('beforeend', trial.prompt);
|
||||||
}
|
}
|
||||||
html += '"></img>';
|
|
||||||
|
|
||||||
|
start_time = performance.now();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// display stimulus as an image element
|
||||||
|
var html = '<img src="' + trial.stimulus + '" id="jspsych-image-keyboard-response-stimulus">';
|
||||||
// add prompt
|
// add prompt
|
||||||
if(trial.prompt !== null) {
|
if(trial.prompt !== null) {
|
||||||
html += trial.prompt;
|
html += trial.prompt;
|
||||||
}
|
}
|
||||||
|
// update the page content
|
||||||
// render
|
|
||||||
display_element.innerHTML = html;
|
display_element.innerHTML = html;
|
||||||
|
|
||||||
|
// set image dimensions after image has loaded (so that we have access to naturalHeight/naturalWidth)
|
||||||
|
var img = display_element.querySelector('#jspsych-image-keyboard-response-stimulus');
|
||||||
|
if(trial.stimulus_height !== null) {
|
||||||
|
height = trial.stimulus_height;
|
||||||
|
if(trial.stimulus_width == null && trial.maintain_aspect_ratio) {
|
||||||
|
width = img.naturalWidth * (trial.stimulus_height / img.naturalHeight);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
height = img.naturalHeight;
|
||||||
|
}
|
||||||
|
if(trial.stimulus_width !== null) {
|
||||||
|
width = trial.stimulus_width;
|
||||||
|
if(trial.stimulus_height == null && trial.maintain_aspect_ratio) {
|
||||||
|
height = img.naturalHeight * (trial.stimulus_width / img.naturalWidth);
|
||||||
|
}
|
||||||
|
} else if(!(trial.stimulus_height !== null & trial.maintain_aspect_ratio)) {
|
||||||
|
// if stimulus width is null, only use the image's natural width if the width value wasn't set
|
||||||
|
// in the if statement above, based on a specified height and maintain_aspect_ratio = true
|
||||||
|
width = img.naturalWidth;
|
||||||
|
}
|
||||||
|
img.style.height = height.toString() + "px";
|
||||||
|
img.style.width = width.toString() + "px";
|
||||||
|
|
||||||
start_time = performance.now();
|
start_time = performance.now();
|
||||||
|
}
|
||||||
|
|
||||||
// store response
|
// store response
|
||||||
var response = {
|
var response = {
|
||||||
@@ -165,17 +230,6 @@ jsPsych.plugins["image-keyboard-response-clickable"] = (function() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 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: 'performance',
|
|
||||||
persist: false,
|
|
||||||
allow_held_key: false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if(trial.clickable){
|
if(trial.clickable){
|
||||||
display_element.querySelectorAll(".clickable").forEach(function(e){
|
display_element.querySelectorAll(".clickable").forEach(function(e){
|
||||||
var clickHandler = function(event){
|
var clickHandler = function(event){
|
||||||
@@ -188,6 +242,17 @@ jsPsych.plugins["image-keyboard-response-clickable"] = (function() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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: 'performance',
|
||||||
|
persist: false,
|
||||||
|
allow_held_key: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// hide stimulus if stimulus_duration is set
|
// hide stimulus if stimulus_duration is set
|
||||||
if(trial.stimulus_duration !== null) {
|
if(trial.stimulus_duration !== null) {
|
||||||
jsPsych.pluginAPI.setTimeout(function() {
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
@@ -200,8 +265,9 @@ jsPsych.plugins["image-keyboard-response-clickable"] = (function() {
|
|||||||
jsPsych.pluginAPI.setTimeout(function() {
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
end_trial();
|
end_trial();
|
||||||
}, trial.trial_duration);
|
}, trial.trial_duration);
|
||||||
|
} else if(trial.response_ends_trial === false) {
|
||||||
|
console.warn("The experiment may be deadlocked. Try setting a trial duration or set response_ends_trial to true.");
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return plugin;
|
return plugin;
|
||||||
|
|||||||
BIN
tests/res/eg-syllables-bi01.wav
Normal file
BIN
tests/res/eg-syllables-bi01.wav
Normal file
Binary file not shown.
BIN
tests/res/eg-syllables-bu01.wav
Normal file
BIN
tests/res/eg-syllables-bu01.wav
Normal file
Binary file not shown.
BIN
tests/res/eg-syllables-di01.wav
Normal file
BIN
tests/res/eg-syllables-di01.wav
Normal file
Binary file not shown.
BIN
tests/res/eg-syllables-du01.wav
Normal file
BIN
tests/res/eg-syllables-du01.wav
Normal file
Binary file not shown.
64
tests/test_jspsych-audio-sequence-button-response.html
Normal file
64
tests/test_jspsych-audio-sequence-button-response.html
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>Test for jspsych-html-keyboard-response-clickable</title>
|
||||||
|
<script src="https://cdn.jsdelivr.net/gh/jquery/jquery/dist/jquery.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/gh/jspsych/jsPsych@6.3.1/jspsych.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/gh/jspsych/jsPsych@6.3.1/plugins/jspsych-html-button-response.js"></script>
|
||||||
|
<link href="https://cdn.jsdelivr.net/gh/jspsych/jsPsych@6.3.1/css/jspsych.css" rel="stylesheet" type="text/css">
|
||||||
|
<script src="../plugins/jspsych-audio-sequence-button-response.js"></script>
|
||||||
|
<style>
|
||||||
|
.jspsych-audio-sequence-button-response button {
|
||||||
|
min-width: 5em;
|
||||||
|
min-height: 4em;
|
||||||
|
}
|
||||||
|
.jspsych-audio-sequence-button-response button.highlighted {
|
||||||
|
background-color: #ffff00 !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function(event) {
|
||||||
|
|
||||||
|
var timeline = [];
|
||||||
|
|
||||||
|
timeline.push({
|
||||||
|
type: 'html-button-response',
|
||||||
|
choices: ['start'],
|
||||||
|
stimulus: ""
|
||||||
|
});
|
||||||
|
|
||||||
|
timeline.push({
|
||||||
|
type: 'audio-sequence-button-response',
|
||||||
|
choices: [' ', ' ', ' '],
|
||||||
|
prompt: '<p>Prompt</p>',
|
||||||
|
stimuli: ['res/eg-syllables-bi01.wav', 'res/eg-syllables-bu01.wav', 'res/eg-syllables-di01.wav'],
|
||||||
|
trial_ends_after_audio: true,
|
||||||
|
on_finish: function(){
|
||||||
|
console.log("Trial is finished.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
timeline.push({
|
||||||
|
type: 'audio-sequence-button-response',
|
||||||
|
choices: [' ', ' ', ' '],
|
||||||
|
prompt: '<p>Prompt</p>',
|
||||||
|
stimuli: ['res/eg-syllables-bi01.wav', 'res/eg-syllables-bu01.wav', 'res/eg-syllables-di01.wav'],
|
||||||
|
trial_ends_after_audio: true,
|
||||||
|
on_finish: function(){
|
||||||
|
console.log("Trial is finished.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
jsPsych.init({
|
||||||
|
timeline: timeline
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user