mirror of
https://github.com/jspsych/jsPsych.git
synced 2025-05-13 09:08:13 +00:00
commit
3f727bdd0d
@ -2,6 +2,46 @@
|
||||
|
||||
The jsPsych.data module contains functions for interacting with the data generated by jsPsych plugins.
|
||||
|
||||
---
|
||||
## jsPsych.data.addDataToLastTrial
|
||||
|
||||
```
|
||||
jsPsych.data.addDataToLastTrial(data)
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
Parameter | Type | Description
|
||||
----------|------|------------
|
||||
data | object | Object of key: value pairs to add to the data from the last trial.
|
||||
|
||||
### Return value
|
||||
|
||||
Returns nothing.
|
||||
|
||||
### Description
|
||||
|
||||
This method appends data to the data recorded by the last trial. It's particularly useful when combined with the `on_finish` event handler for a trial, as shown in the example below.
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
#### Evaluate a response and add to data
|
||||
```javascript
|
||||
var block = {
|
||||
type: 'single-stim',
|
||||
stimuli: ['img/happy_face_1.jpg', 'img/sad_face_1.jpg'],
|
||||
choices: [89,78], // Y or N
|
||||
prompt: '<p class="center-content">Have you seen this face before? Y or N.</p>',
|
||||
on_finish: function(trial_data){
|
||||
// let's imagine that the correct answer is NO for both trials
|
||||
var correct = (trial_data.key_press == 78);
|
||||
jsPsych.data.addDataToLastTrial({correct: correct});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
---
|
||||
## jsPsych.data.addProperties
|
||||
|
||||
|
@ -100,16 +100,21 @@ plugin.create = function(params) {
|
||||
## jsPsych.pluginAPI.getKeyboardResponse
|
||||
|
||||
```
|
||||
jsPsych.pluginAPI.getKeyboardResponse(callback_function, valid_responses, rt_method, persist)
|
||||
jsPsych.pluginAPI.getKeyboardResponse(parameters)
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
The method accepts an object of parameter values (see example below). The valid keys for this object are listed in the table below.
|
||||
|
||||
Parameter | Type | Description
|
||||
----------|------|------------
|
||||
callback_function | function | The function to execute whenever a valid keyboard response is generated.
|
||||
valid_responses | array | An array of key codes or character strings representing valid responses. Responses not on the list will be ignored. An empty array indicates that all responses are acceptable.
|
||||
rt_method | string | Indicates which method of recording time to use. The `'date'` method uses calls to `(new Date()).getTime()` to record timing information. The `'performance'` method uses calls to `performance.now()`, which is a more modern JavaScript feature. The `'performance'` approach is [not supported by all the major browsers yet](http://caniuse.com/#search=performance), but adoption rates are increasing.
|
||||
rt_method | string | Indicates which method of recording time to use. The `'date'` method uses calls to `(new Date()).getTime()` to record timing information. The `'performance'` method uses calls to `performance.now()`, which is a more modern JavaScript feature. The `'performance'` approach is [not supported by all the major browsers yet](http://caniuse.com/#search=performance), but adoption rates are increasing. The `audio` method is used in conjuction with an `audio_context` (set as an additional parameter). This uses the clock time of the `audio_context` when audio stimuli are being played.
|
||||
audio_context | AudioContext object | The AudioContext of the audio file that is being played.
|
||||
audio_context_start_time | numeric | The scheduled time of the sound file in the AudioContext. This will be used as the start time.
|
||||
allow_held_key | boolean | If `true`, then responses will be registered from keys that are being held down. If `false`, then a held key can only register a response the first time that `getKeyboardResponse` is called for that key. For example, if a participant holds down the `A` key before the experiment starts, then the first time `getKeyboardResponse` is called, the `A` will register as a key press. However, any future calls to `getKeyboardResponse` will not register the `A` until the participant releases the key and presses it again.
|
||||
persist | boolean | If false, then the keyboard listener will only trigger the first time a valid key is pressed. If true, then it will trigger every time a valid key is pressed until it is explicitly cancelled by `jsPsych.pluginAPI.cancelKeyboardResponse` or `jsPsych.pluginAPI.cancelAllKeyboardResponses`.
|
||||
|
||||
### Return value
|
||||
@ -131,7 +136,12 @@ var after_response = function(info){
|
||||
alert('You pressed key '+info.key+' after '+info.rt+'ms');
|
||||
}
|
||||
|
||||
jsPsych.pluginAPI.getKeyboardResponse(after_response, [], 'date', false);
|
||||
jsPsych.pluginAPI.getKeyboardResponse({
|
||||
callback_function:after_response,
|
||||
valid_responses: [],
|
||||
rt_method: 'date',
|
||||
persist: false
|
||||
});
|
||||
```
|
||||
|
||||
#### Get a responses from a key until the letter Q is pressed
|
||||
@ -145,7 +155,12 @@ var after_response = function(info){
|
||||
}
|
||||
}
|
||||
|
||||
var listener = jsPsych.pluginAPI.getKeyboardResponse(after_response, [], 'date', true);
|
||||
var listener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||
callback_function:after_response,
|
||||
valid_responses: [],
|
||||
rt_method: 'date',
|
||||
persist: true
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
@ -275,3 +275,56 @@ var shuffledArray = jsPsych.randomization.shuffle(myArray);
|
||||
|
||||
// output: shuffledArray = [3,2,4,1,5]
|
||||
```
|
||||
|
||||
---
|
||||
## jsPsych.randomization.shuffleNoRepeats
|
||||
|
||||
```
|
||||
jsPsych.randomization.shuffleNoRepeats(array, equalityTest)
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
Parameter | Type | Description
|
||||
----------|------|------------
|
||||
array | array | The array of values to shuffle
|
||||
equalityTest | function | A function to use to evaluate the equality of neighbors in the array. The function should accept two parameters, which are the two elements to be tested. It should return `true` if they are equal and `false` if not. The default function, if none is specified, is to use the `===` operator. This will work for primitive values, but fail for Objects and Arrays. An example function is given below in the examples.
|
||||
|
||||
### Return value
|
||||
|
||||
Returns an array with the same elements as the input array in a random order, with no repeating neighbors.
|
||||
|
||||
### Description
|
||||
|
||||
Shuffle an array, ensuring that neighboring elements in the array are different.
|
||||
|
||||
*Warning: if you provide an array that has very few valid permutations with no neighboring elements, then this method will fail and cause the browser to hang.*
|
||||
|
||||
### Examples
|
||||
|
||||
#### Basic example
|
||||
|
||||
```javascript
|
||||
|
||||
var myArray = [1,2,3,4,5,1,2,3,4,5,1,2,3,4,5];
|
||||
var shuffledArray = jsPsych.randomization.shuffleNoRepeats(myArray);
|
||||
|
||||
// output: shuffledArray = [2, 3, 5, 1, 2, 4, 1, 5, 4, 1, 3, 5, 4, 3, 2]
|
||||
```
|
||||
|
||||
#### Custom equalityTest
|
||||
|
||||
```javascript
|
||||
var myObjects = [
|
||||
{color:"blue"},
|
||||
{color:"red"},
|
||||
{color:"yellow"},
|
||||
{color:"orange"}
|
||||
];
|
||||
|
||||
var repeatedSet = jsPsych.randomization.repeat(myObjects,3);
|
||||
var shuffled = jsPsych.randomization.shuffleNoRepeats(repeatedSet, function(a,b) { return a.color === b.color });
|
||||
|
||||
// console.log(JSON.stringify(shuffled))
|
||||
// "[{"color":"red"},{"color":"yellow"},{"color":"blue"},{"color":"yellow"},{"color":"orange"},{"color":"red"},{"color":"yellow"},{"color":"orange"},{"color":"blue"},{"color":"orange"},{"color":"red"},{"color":"blue"}]"
|
||||
```
|
||||
|
@ -21,6 +21,7 @@ Every jsPsych experiment utilizes the core library (contained in the `jspsych.js
|
||||
|
||||
### [Data module](jspsych-data.md)
|
||||
|
||||
* [jsPsych.data.addDataToLastTrial](jspsych-data.md#jspsychdataadddatatolasttrial)
|
||||
* [jsPsych.data.addProperties](jspsych-data.md#jspsychdataaddproperties)
|
||||
* [jsPsych.data.dataAsCSV](jspsych-data.md#jspsychdatadataascsv)
|
||||
* [jsPsych.data.displayData](jspsych-data.md#jspsychdatadisplaydata)
|
||||
@ -43,6 +44,7 @@ Every jsPsych experiment utilizes the core library (contained in the `jspsych.js
|
||||
* [jsPsych.randomization.repeat](jspsych-randomization.md#jspsychrandomizationrepeat)
|
||||
* [jsPsych.randomization.sample](jspsych-randomization.md#jspsychrandomizationsample)
|
||||
* [jsPsych.randomization.shuffle](jspsych-randomization.md#jspsychrandomizationshuffle)
|
||||
* [jsPsych.randomization.shuffleNoRepeats](jspsych-randomization.md#jspsychrandomizationshufflenorepeats)
|
||||
|
||||
### [PluginAPI module](jspsych-pluginAPI.md)
|
||||
|
||||
|
@ -18,8 +18,12 @@ incorrect_text | string | "Wrong." | String to show when the wrong answer is giv
|
||||
prompt | string | "" | This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the subject is supposed to take (e.g. which key to press).
|
||||
force_correct_button_press | boolean | false | If set to true, then the subject must press the correct response key after feedback is given in order to advance to the next trial.
|
||||
show_stim_with_feedback | boolean | true | If set to true, then the stimulus will be shown during feedback. If false, then only the text feedback will display during feedback.
|
||||
show_feedback_on_timeout | boolean | false | If true, then category feedback will be displayed for an incorrect response after a timeout (timing_response is exceeded). If false, then a timeout message will be shown.
|
||||
timeout_message | string | "Please respond faster." | The message to show on a timeout non-response.
|
||||
timing_stim | numeric | -1 | How long to show the stimulus for (milliseconds). If -1, then the stimulus is shown until a response is given.
|
||||
timing_feedback_duration | numeric | 2000 | How long to show the feedback for (milliseconds).
|
||||
timing_response | numeric | -1 | The maximum time allowed for a response. If -1, then the experiment will wait indefinitely for a response.
|
||||
|
||||
|
||||
## Data Generated
|
||||
|
||||
|
@ -10,6 +10,8 @@ Parameter | Type | Default Value | Description
|
||||
----------|------|---------------|------------
|
||||
questions | array | *undefined* | Each array is an array of strings. The strings are the prompts for the subject to respond to. Each string gets its own response field. Each set of strings (inner arrays) will be presented on the same page (trial). The length of the outer array sets the number of trials in the block.
|
||||
preamble | string | empty string | HTML formatted string to display at the top of the page above all the questions.
|
||||
rows | array | 1 | The number of rows for the response text box. Array dimensions must match `questions` array, with a numeric value for each entry indicating the number of rows for that question's box.
|
||||
columns | array | 40 | The number of columns for the response text box. Array dimensions must match `questions` array, with a numeric value for each entry indicating the number of columns for that question's box.
|
||||
|
||||
## Data Generated
|
||||
|
||||
@ -34,3 +36,18 @@ var survey_block = {
|
||||
questions: [page_1_questions, page_2_questions],
|
||||
};
|
||||
```
|
||||
|
||||
### Custom number of rows and columns
|
||||
|
||||
```javascript
|
||||
// defining groups of questions that will go together.
|
||||
var page_1_questions = ["How old are you?", "Where were you born?"];
|
||||
var page_2_questions = ["What is your favorite food?"];
|
||||
|
||||
var survey_block = {
|
||||
type: 'survey-text',
|
||||
questions: [page_1_questions, page_2_questions],
|
||||
rows: [[5,3],[2]],
|
||||
columns: [[40,50],[60]]
|
||||
};
|
||||
```
|
||||
|
130
jspsych.js
130
jspsych.js
@ -645,7 +645,13 @@
|
||||
|
||||
// now add to list so that it gets appended to all future data
|
||||
dataProperties = $.extend({}, dataProperties, properties);
|
||||
};
|
||||
|
||||
module.addDataToLastTrial = function(data){
|
||||
if(allData.length == 0){
|
||||
throw new Error("Cannot add data to last trial - no data recorded so far");
|
||||
}
|
||||
allData[allData.length-1] = $.extend({},allData[allData.length-1],data);
|
||||
}
|
||||
|
||||
module.dataAsCSV = function() {
|
||||
@ -906,7 +912,7 @@
|
||||
repetitions = [repetitions];
|
||||
} else {
|
||||
repetitions = [repetitions[0]];
|
||||
console.log('Unclear parameters given to randomizeSimpleSample. Multiple set sizes specified, but only one item exists to sample. Proceeding using the first set size.');
|
||||
console.log('Unclear parameters given to randomization.repeat. Multiple set sizes specified, but only one item exists to sample. Proceeding using the first set size.');
|
||||
}
|
||||
} else {
|
||||
if (!rep_isArray) {
|
||||
@ -917,8 +923,18 @@
|
||||
repetitions = reps;
|
||||
} else {
|
||||
if (array.length != repetitions.length) {
|
||||
// throw warning if repetitions is too short,
|
||||
// throw warning if too long, and then use the first N
|
||||
console.warning('Unclear parameters given to randomization.repeat. Items and repetitions are unequal lengths. Behavior may not be as expected.');
|
||||
// throw warning if repetitions is too short, use first rep ONLY.
|
||||
if(repetitions.length < array.length){
|
||||
var reps = [];
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
reps.push(repetitions);
|
||||
}
|
||||
repetitions = reps;
|
||||
} else {
|
||||
// throw warning if too long, and then use the first N
|
||||
repetitions = repetions.slice(0, array.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -944,6 +960,36 @@
|
||||
return shuffle(arr);
|
||||
}
|
||||
|
||||
module.shuffleNoRepeats = function(arr, equalityTest){
|
||||
// define a default equalityTest
|
||||
if(typeof equalityTest == 'undefined'){
|
||||
equalityTest = function(a,b){
|
||||
if(a === b) { return true; }
|
||||
else { return false; }
|
||||
}
|
||||
}
|
||||
|
||||
var random_shuffle = shuffle(arr);
|
||||
for(var i=0; i<random_shuffle.length-2; i++){
|
||||
if(equalityTest(random_shuffle[i], random_shuffle[i+1])){
|
||||
// neighbors are equal, pick a new random neighbor to swap (not the first or last element, to avoid edge cases)
|
||||
var random_pick = Math.floor(Math.random()*(random_shuffle.length-2))+1;
|
||||
// test to make sure the new neighbor isn't equal to the old one
|
||||
while(
|
||||
equalityTest(random_shuffle[i+1], random_shuffle[random_pick]) ||
|
||||
(equalityTest(random_shuffle[i+1], random_shuffle[random_pick+1]) || equalityTest(random_shuffle[i+1], random_shuffle[random_pick-1]))
|
||||
){
|
||||
random_pick = Math.floor(Math.random()*(random_shuffle.length-2))+1;
|
||||
}
|
||||
var new_neighbor = random_shuffle[random_pick];
|
||||
random_shuffle[random_pick] = random_shuffle[i+1];
|
||||
random_shuffle[i+1] = new_neighbor;
|
||||
}
|
||||
}
|
||||
|
||||
return random_shuffle;
|
||||
}
|
||||
|
||||
module.sample = function(arr, size, withReplacement) {
|
||||
if(withReplacement == false) {
|
||||
if(size > arr.length){
|
||||
@ -1051,23 +1097,26 @@
|
||||
// keyboard listeners
|
||||
var keyboard_listeners = [];
|
||||
|
||||
var held_keys = [];
|
||||
|
||||
var module = {};
|
||||
|
||||
module.getKeyboardResponse = function(callback_function, valid_responses, rt_method, persist, audio_context, audio_context_start_time) {
|
||||
module.getKeyboardResponse = function(parameters){
|
||||
//parameters are: callback_function, valid_responses, rt_method, persist, audio_context, audio_context_start_time, allow_held_key?
|
||||
|
||||
rt_method = (typeof rt_method === 'undefined') ? 'date' : rt_method;
|
||||
if (rt_method != 'date' && rt_method != 'performance' && rt_method != 'audio') {
|
||||
parameters.rt_method = (typeof parameters.rt_method === 'undefined') ? 'date' : parameters.rt_method;
|
||||
if (parameters.rt_method != 'date' && parameters.rt_method != 'performance' && parameters.rt_method != 'audio') {
|
||||
console.log('Invalid RT method specified in getKeyboardResponse. Defaulting to "date" method.');
|
||||
rt_method = 'date';
|
||||
parameters.rt_method = 'date';
|
||||
}
|
||||
|
||||
var start_time;
|
||||
if (rt_method == 'date') {
|
||||
if (parameters.rt_method == 'date') {
|
||||
start_time = (new Date()).getTime();
|
||||
} else if (rt_method == 'performance') {
|
||||
} else if (parameters.rt_method == 'performance') {
|
||||
start_time = performance.now();
|
||||
} else if (rt_method == 'audio') {
|
||||
start_time = audio_context_start_time;
|
||||
} else if (parameters.rt_method == 'audio') {
|
||||
start_time = parameters.audio_context_start_time;
|
||||
}
|
||||
|
||||
var listener_id;
|
||||
@ -1075,51 +1124,66 @@
|
||||
var listener_function = function(e) {
|
||||
|
||||
var key_time;
|
||||
if (rt_method == 'date') {
|
||||
if (parameters.rt_method == 'date') {
|
||||
key_time = (new Date()).getTime();
|
||||
} else if (rt_method == 'performance') {
|
||||
} else if (parameters.rt_method == 'performance') {
|
||||
key_time = performance.now();
|
||||
} else if (rt_method == 'audio') {
|
||||
key_time = audio_context.currentTime
|
||||
} else if (parameters.rt_method == 'audio') {
|
||||
key_time = parameters.audio_context.currentTime
|
||||
}
|
||||
|
||||
var valid_response = false;
|
||||
if (typeof valid_responses === 'undefined' || valid_responses.length === 0) {
|
||||
if (typeof parameters.valid_responses === 'undefined' || parameters.valid_responses.length === 0) {
|
||||
valid_response = true;
|
||||
}
|
||||
for (var i = 0; i < valid_responses.length; i++) {
|
||||
if (typeof valid_responses[i] == 'string') {
|
||||
if (typeof keylookup[valid_responses[i]] !== 'undefined') {
|
||||
if (e.which == keylookup[valid_responses[i]]) {
|
||||
for (var i = 0; i < parameters.valid_responses.length; i++) {
|
||||
if (typeof parameters.valid_responses[i] == 'string') {
|
||||
if (typeof keylookup[parameters.valid_responses[i]] !== 'undefined') {
|
||||
if (e.which == keylookup[parameters.valid_responses[i]]) {
|
||||
valid_response = true;
|
||||
}
|
||||
} else {
|
||||
throw new Error('Invalid key string specified for getKeyboardResponse');
|
||||
}
|
||||
} else if (e.which == valid_responses[i]) {
|
||||
} else if (e.which == parameters.valid_responses[i]) {
|
||||
valid_response = true;
|
||||
}
|
||||
}
|
||||
// check if key was already held down
|
||||
|
||||
if ( ((typeof parameters.allow_held_key == 'undefined') || !parameters.allow_held_key) && valid_response ) {
|
||||
for(i in held_keys){
|
||||
if(held_keys[i]==e.which){
|
||||
valid_response = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (valid_response) {
|
||||
|
||||
held_keys.push(e.which);
|
||||
|
||||
parameters.callback_function({
|
||||
key: e.which,
|
||||
rt: key_time - start_time
|
||||
});
|
||||
|
||||
if ($.inArray(listener_id, keyboard_listeners) > -1) {
|
||||
|
||||
if (!parameters.persist) {
|
||||
// remove keyboard listener
|
||||
module.cancelKeyboardResponse(listener_id);
|
||||
}
|
||||
}
|
||||
|
||||
var after_up = function(up) {
|
||||
|
||||
if (up.which == e.which) {
|
||||
$(document).off('keyup', after_up);
|
||||
|
||||
if ($.inArray(listener_id, keyboard_listeners) > -1) {
|
||||
|
||||
if (!persist) {
|
||||
// remove keyboard listener
|
||||
module.cancelKeyboardResponse(listener_id);
|
||||
}
|
||||
|
||||
callback_function({
|
||||
key: e.which,
|
||||
rt: key_time - start_time
|
||||
});
|
||||
}
|
||||
// mark key as released
|
||||
held_keys.splice($.inArray(e.which, held_keys), 1);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -108,7 +108,13 @@
|
||||
// hold the jspsych response listener object in memory
|
||||
// so that we can turn off the response collection when
|
||||
// the trial ends
|
||||
var response_listener = jsPsych.pluginAPI.getKeyboardResponse(after_response, trial.choices, 'date', true);
|
||||
var response_listener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||
callback_function: after_response,
|
||||
valid_responses: trial.choices,
|
||||
rt_method: 'date',
|
||||
persist: true,
|
||||
allow_held_key: false
|
||||
});
|
||||
|
||||
function endTrial() {
|
||||
|
||||
|
@ -139,7 +139,13 @@
|
||||
|
||||
}
|
||||
|
||||
keyboard_listener = jsPsych.pluginAPI.getKeyboardResponse(after_response, trial.choices, 'date', true);
|
||||
keyboard_listener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||
callback_function: after_response,
|
||||
valid_responses: trial.choices,
|
||||
rt_method: 'date',
|
||||
persist: true,
|
||||
allow_held_key: false
|
||||
});
|
||||
|
||||
function endTrial() {
|
||||
clearInterval(animate_interval); // stop animation!
|
||||
|
@ -23,14 +23,16 @@
|
||||
trials[i].choices = params.choices;
|
||||
trials[i].correct_text = (typeof params.correct_text === 'undefined') ? "<p class='feedback'>Correct</p>" : params.correct_text;
|
||||
trials[i].incorrect_text = (typeof params.incorrect_text === 'undefined') ? "<p class='feedback'>Incorrect</p>" : params.incorrect_text;
|
||||
// timing params
|
||||
trials[i].timing_stim = params.timing_stim || -1; // default is to show image until response
|
||||
trials[i].timing_feedback_duration = params.timing_feedback_duration || 2000;
|
||||
// optional params
|
||||
trials[i].show_stim_with_feedback = (typeof params.show_stim_with_feedback === 'undefined') ? true : params.show_stim_with_feedback;
|
||||
trials[i].is_html = (typeof params.is_html === 'undefined') ? false : params.is_html;
|
||||
trials[i].force_correct_button_press = (typeof params.force_correct_button_press === 'undefined') ? false : params.force_correct_button_press;
|
||||
trials[i].prompt = (typeof params.prompt === 'undefined') ? '' : params.prompt;
|
||||
trials[i].show_feedback_on_timeout = (typeof params.show_feedback_on_timeout === 'undefined') ? false : params.show_feedback_on_timeout;
|
||||
trials[i].timeout_message = params.timeout_message || "<p>Please respond faster.</p>";
|
||||
// timing params
|
||||
trials[i].timing_stim = params.timing_stim || -1; // default is to show image until response
|
||||
trials[i].timing_response = params.timing_response || -1; // default is no max response time
|
||||
trials[i].timing_feedback_duration = params.timing_feedback_duration || 2000;
|
||||
}
|
||||
return trials;
|
||||
};
|
||||
@ -81,6 +83,9 @@
|
||||
clearTimeout(setTimeoutHandlers[i]);
|
||||
}
|
||||
|
||||
// clear keyboard listener
|
||||
jsPsych.pluginAPI.cancelAllKeyboardResponses();
|
||||
|
||||
var correct = false;
|
||||
if (trial.key_answer == info.key) {
|
||||
correct = true;
|
||||
@ -98,51 +103,72 @@
|
||||
|
||||
display_element.html('');
|
||||
|
||||
doFeedback(correct);
|
||||
var timeout = info.rt == -1;
|
||||
doFeedback(correct, timeout);
|
||||
}
|
||||
|
||||
jsPsych.pluginAPI.getKeyboardResponse(after_response, trial.choices, 'date', false);
|
||||
jsPsych.pluginAPI.getKeyboardResponse({
|
||||
callback_function: after_response,
|
||||
valid_responses: trial.choices,
|
||||
rt_method: 'date',
|
||||
persist: false,
|
||||
allow_held_key: false
|
||||
});
|
||||
|
||||
if(trial.timing_response > 0) {
|
||||
setTimeoutHandlers.push(setTimeout(function(){
|
||||
after_response({key: -1, rt: -1});
|
||||
}, trial.timing_response));
|
||||
}
|
||||
|
||||
function doFeedback(correct, timeout) {
|
||||
|
||||
function doFeedback(correct) {
|
||||
// show image during feedback if flag is set
|
||||
if (trial.show_stim_with_feedback) {
|
||||
if (!trial.is_html) {
|
||||
// add image to display
|
||||
display_element.append($('<img>', {
|
||||
"src": trial.a_path,
|
||||
"class": 'jspsych-categorize-stimulus',
|
||||
"id": 'jspsych-categorize-stimulus'
|
||||
}));
|
||||
} else {
|
||||
display_element.append($('<div>', {
|
||||
"id": 'jspsych-categorize-stimulus',
|
||||
"class": 'jspsych-categorize-stimulus',
|
||||
"html": trial.a_path
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// substitute answer in feedback string.
|
||||
var atext = "";
|
||||
if (correct) {
|
||||
atext = trial.correct_text.replace("%ANS%", trial.text_answer);
|
||||
if(timeout && !trial.show_feedback_on_timeout){
|
||||
display_element.append(trial.timeout_message);
|
||||
} else {
|
||||
atext = trial.incorrect_text.replace("%ANS%", trial.text_answer);
|
||||
// show image during feedback if flag is set
|
||||
if (trial.show_stim_with_feedback) {
|
||||
if (!trial.is_html) {
|
||||
// add image to display
|
||||
display_element.append($('<img>', {
|
||||
"src": trial.a_path,
|
||||
"class": 'jspsych-categorize-stimulus',
|
||||
"id": 'jspsych-categorize-stimulus'
|
||||
}));
|
||||
} else {
|
||||
display_element.append($('<div>', {
|
||||
"id": 'jspsych-categorize-stimulus',
|
||||
"class": 'jspsych-categorize-stimulus',
|
||||
"html": trial.a_path
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// substitute answer in feedback string.
|
||||
var atext = "";
|
||||
if (correct) {
|
||||
atext = trial.correct_text.replace("%ANS%", trial.text_answer);
|
||||
} else {
|
||||
atext = trial.incorrect_text.replace("%ANS%", trial.text_answer);
|
||||
}
|
||||
|
||||
// show the feedback
|
||||
display_element.append(atext);
|
||||
}
|
||||
|
||||
// show the feedback
|
||||
display_element.append(atext);
|
||||
|
||||
// check if force correct button press is set
|
||||
if (trial.force_correct_button_press && correct === false) {
|
||||
if (trial.force_correct_button_press && correct === false && ((timeout && trial.show_feedback_on_timeout) || !timeout)) {
|
||||
|
||||
var after_forced_response = function(info) {
|
||||
endTrial();
|
||||
}
|
||||
|
||||
jsPsych.pluginAPI.getKeyboardResponse(after_forced_response, trial.key_answer, 'date', false);
|
||||
jsPsych.pluginAPI.getKeyboardResponse({
|
||||
callback_function: after_forced_response,
|
||||
valid_responses: [trial.key_answer],
|
||||
rt_method: 'date',
|
||||
persist: false,
|
||||
allow_held_key: false
|
||||
});
|
||||
|
||||
} else {
|
||||
setTimeout(function() {
|
||||
|
@ -10,154 +10,164 @@
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
jsPsych.instructions = (function() {
|
||||
jsPsych.instructions = (function() {
|
||||
|
||||
var plugin = {};
|
||||
var plugin = {};
|
||||
|
||||
plugin.create = function(params) {
|
||||
plugin.create = function(params) {
|
||||
|
||||
params = jsPsych.pluginAPI.enforceArray(params, ['pages']);
|
||||
params = jsPsych.pluginAPI.enforceArray(params, ['pages']);
|
||||
|
||||
var trials = new Array(1);
|
||||
var trials = new Array(1);
|
||||
|
||||
trials[0] = {};
|
||||
trials[0].pages = params.pages;
|
||||
trials[0].key_forward = params.key_forward || 'rightarrow';
|
||||
trials[0].key_backward = params.key_backward || 'leftarrow';
|
||||
trials[0].allow_backward = (typeof params.allow_backward === 'undefined') ? true : params.allow_backward;
|
||||
trials[0].allow_keys = (typeof params.allow_keys === 'undefined') ? true : params.allow_keys;
|
||||
trials[0].show_clickable_nav = (typeof params.show_clickable_nav === 'undefined') ? false : params.show_clickable_nav;
|
||||
trials[0] = {};
|
||||
trials[0].pages = params.pages;
|
||||
trials[0].key_forward = params.key_forward || 'rightarrow';
|
||||
trials[0].key_backward = params.key_backward || 'leftarrow';
|
||||
trials[0].allow_backward = (typeof params.allow_backward === 'undefined') ? true : params.allow_backward;
|
||||
trials[0].allow_keys = (typeof params.allow_keys === 'undefined') ? true : params.allow_keys;
|
||||
trials[0].show_clickable_nav = (typeof params.show_clickable_nav === 'undefined') ? false : params.show_clickable_nav;
|
||||
|
||||
return trials;
|
||||
};
|
||||
return trials;
|
||||
};
|
||||
|
||||
plugin.trial = function(display_element, trial) {
|
||||
plugin.trial = function(display_element, trial) {
|
||||
|
||||
// if any trial variables are functions
|
||||
// this evaluates the function and replaces
|
||||
// it with the output of the function
|
||||
trial = jsPsych.pluginAPI.evaluateFunctionParameters(trial);
|
||||
// if any trial variables are functions
|
||||
// this evaluates the function and replaces
|
||||
// it with the output of the function
|
||||
trial = jsPsych.pluginAPI.evaluateFunctionParameters(trial);
|
||||
|
||||
var current_page = 0;
|
||||
var current_page = 0;
|
||||
|
||||
var view_history = [];
|
||||
var view_history = [];
|
||||
|
||||
var start_time = (new Date()).getTime();
|
||||
var start_time = (new Date()).getTime();
|
||||
|
||||
var last_page_update_time = start_time;
|
||||
var last_page_update_time = start_time;
|
||||
|
||||
function show_current_page(){
|
||||
display_element.html(trial.pages[current_page]);
|
||||
function show_current_page() {
|
||||
display_element.html(trial.pages[current_page]);
|
||||
|
||||
if(trial.show_clickable_nav){
|
||||
if (trial.show_clickable_nav) {
|
||||
|
||||
var nav_html = "<div class='jspsych-instructions-nav'>";
|
||||
if(current_page != 0 && trial.allow_backward){
|
||||
nav_html += "<button id='jspsych-instructions-back'>< Previous</button>";
|
||||
}
|
||||
nav_html += "<button id='jspsych-instructions-next'>Next ></button></div>"
|
||||
var nav_html = "<div class='jspsych-instructions-nav'>";
|
||||
if (current_page != 0 && trial.allow_backward) {
|
||||
nav_html += "<button id='jspsych-instructions-back'>< Previous</button>";
|
||||
}
|
||||
nav_html += "<button id='jspsych-instructions-next'>Next ></button></div>"
|
||||
|
||||
display_element.append(nav_html);
|
||||
display_element.append(nav_html);
|
||||
|
||||
if(current_page != 0 && trial.allow_backward){
|
||||
$('#jspsych-instructions-back').on('click',function(){
|
||||
clear_button_handlers();
|
||||
back();
|
||||
});
|
||||
}
|
||||
if (current_page != 0 && trial.allow_backward) {
|
||||
$('#jspsych-instructions-back').on('click', function() {
|
||||
clear_button_handlers();
|
||||
back();
|
||||
});
|
||||
}
|
||||
|
||||
$('#jspsych-instructions-next').on('click',function(){
|
||||
clear_button_handlers();
|
||||
next();
|
||||
});
|
||||
$('#jspsych-instructions-next').on('click', function() {
|
||||
clear_button_handlers();
|
||||
next();
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function clear_button_handlers() {
|
||||
$('#jspsych-instructions-next').off('click');
|
||||
$('#jspsych-instructions-back').off('click');
|
||||
}
|
||||
function clear_button_handlers() {
|
||||
$('#jspsych-instructions-next').off('click');
|
||||
$('#jspsych-instructions-back').off('click');
|
||||
}
|
||||
|
||||
function next() {
|
||||
function next() {
|
||||
|
||||
add_current_page_to_view_history()
|
||||
add_current_page_to_view_history()
|
||||
|
||||
current_page++;
|
||||
current_page++;
|
||||
|
||||
// if done, finish up...
|
||||
if(current_page >= trial.pages.length) {
|
||||
endTrial();
|
||||
} else {
|
||||
show_current_page();
|
||||
}
|
||||
// if done, finish up...
|
||||
if (current_page >= trial.pages.length) {
|
||||
endTrial();
|
||||
} else {
|
||||
show_current_page();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function back() {
|
||||
function back() {
|
||||
|
||||
add_current_page_to_view_history()
|
||||
add_current_page_to_view_history()
|
||||
|
||||
current_page--;
|
||||
current_page--;
|
||||
|
||||
show_current_page();
|
||||
}
|
||||
show_current_page();
|
||||
}
|
||||
|
||||
function add_current_page_to_view_history(){
|
||||
function add_current_page_to_view_history() {
|
||||
|
||||
var current_time = (new Date()).getTime();
|
||||
var current_time = (new Date()).getTime();
|
||||
|
||||
var page_view_time = current_time - last_page_update_time;
|
||||
var page_view_time = current_time - last_page_update_time;
|
||||
|
||||
view_history.push({
|
||||
page_index: current_page,
|
||||
viewing_time: page_view_time
|
||||
});
|
||||
view_history.push({
|
||||
page_index: current_page,
|
||||
viewing_time: page_view_time
|
||||
});
|
||||
|
||||
last_page_update_time = current_time;
|
||||
}
|
||||
last_page_update_time = current_time;
|
||||
}
|
||||
|
||||
function endTrial() {
|
||||
function endTrial() {
|
||||
|
||||
if(trial.allow_keys){
|
||||
jsPsych.pluginAPI.cancelKeyboardResponse(keyboard_listener);
|
||||
}
|
||||
if (trial.allow_keys) {
|
||||
jsPsych.pluginAPI.cancelKeyboardResponse(keyboard_listener);
|
||||
}
|
||||
|
||||
display_element.html('');
|
||||
display_element.html('');
|
||||
|
||||
jsPsych.data.write({
|
||||
"view_history": JSON.stringify(view_history),
|
||||
"rt": (new Date()).getTime() - start_time
|
||||
});
|
||||
jsPsych.data.write({
|
||||
"view_history": JSON.stringify(view_history),
|
||||
"rt": (new Date()).getTime() - start_time
|
||||
});
|
||||
|
||||
jsPsych.finishTrial();
|
||||
}
|
||||
jsPsych.finishTrial();
|
||||
}
|
||||
|
||||
var after_response = function(info) {
|
||||
var after_response = function(info) {
|
||||
|
||||
// have to reinitialize this instead of letting it persist to prevent accidental skips of pages by holding down keys too long
|
||||
keyboard_listener = jsPsych.pluginAPI.getKeyboardResponse(after_response, [trial.key_forward, trial.key_backward]);
|
||||
// have to reinitialize this instead of letting it persist to prevent accidental skips of pages by holding down keys too long
|
||||
keyboard_listener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||
callback_function: after_response,
|
||||
valid_responses: [trial.key_forward, trial.key_backward],
|
||||
rt_method: 'date',
|
||||
persist: false,
|
||||
allow_held_key: false
|
||||
});
|
||||
// check if key is forwards or backwards and update page
|
||||
if (info.key === trial.key_backward || info.key === jsPsych.pluginAPI.convertKeyCharacterToKeyCode(trial.key_backward)) {
|
||||
if (current_page !== 0 && trial.allow_backward) {
|
||||
back();
|
||||
}
|
||||
}
|
||||
|
||||
// check if key is forwards or backwards and update page
|
||||
if(info.key === trial.key_backward || info.key === jsPsych.pluginAPI.convertKeyCharacterToKeyCode(trial.key_backward)){
|
||||
if(current_page !== 0 && trial.allow_backward) {
|
||||
back();
|
||||
}
|
||||
}
|
||||
if (info.key === trial.key_forward || info.key === jsPsych.pluginAPI.convertKeyCharacterToKeyCode(trial.key_forward)) {
|
||||
next();
|
||||
}
|
||||
|
||||
if(info.key === trial.key_forward || info.key === jsPsych.pluginAPI.convertKeyCharacterToKeyCode(trial.key_forward)){
|
||||
next();
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
show_current_page();
|
||||
|
||||
show_current_page();
|
||||
if (trial.allow_keys) {
|
||||
var keyboard_listener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||
callback_function: after_response,
|
||||
valid_responses: [trial.key_forward, trial.key_backward],
|
||||
rt_method: 'date',
|
||||
persist: false
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if(trial.allow_keys){
|
||||
var keyboard_listener = jsPsych.pluginAPI.getKeyboardResponse(after_response, [trial.key_forward, trial.key_backward]);
|
||||
}
|
||||
};
|
||||
|
||||
return plugin;
|
||||
})();
|
||||
return plugin;
|
||||
})();
|
||||
})(jQuery);
|
||||
|
@ -1,212 +1,218 @@
|
||||
/**
|
||||
* jspsych-muli-stim-multi-response
|
||||
* Josh de Leeuw
|
||||
*
|
||||
* plugin for displaying a set of stimuli and collecting a set of responses
|
||||
* via the keyboard
|
||||
*
|
||||
* documentation: docs.jspsych.org
|
||||
*
|
||||
**/
|
||||
* jspsych-muli-stim-multi-response
|
||||
* Josh de Leeuw
|
||||
*
|
||||
* plugin for displaying a set of stimuli and collecting a set of responses
|
||||
* via the keyboard
|
||||
*
|
||||
* documentation: docs.jspsych.org
|
||||
*
|
||||
**/
|
||||
|
||||
(function($) {
|
||||
jsPsych["multi-stim-multi-response"] = (function() {
|
||||
jsPsych["multi-stim-multi-response"] = (function() {
|
||||
|
||||
var plugin = {};
|
||||
var plugin = {};
|
||||
|
||||
plugin.create = function(params) {
|
||||
plugin.create = function(params) {
|
||||
|
||||
var trials = new Array(params.stimuli.length);
|
||||
var trials = new Array(params.stimuli.length);
|
||||
|
||||
for (var i = 0; i < trials.length; i++) {
|
||||
trials[i] = {};
|
||||
trials[i].stimuli = params.stimuli[i];
|
||||
trials[i].choices = params.choices;
|
||||
// option to show image for fixed time interval, ignoring key responses
|
||||
// true = image will keep displaying after response
|
||||
// false = trial will immediately advance when response is recorded
|
||||
trials[i].response_ends_trial = (typeof params.response_ends_trial === 'undefined') ? true : params.response_ends_trial;
|
||||
// timing parameters
|
||||
var default_timing_array = [];
|
||||
for(var j = 0; j < params.stimuli[i].length; j++){
|
||||
default_timing_array.push(1000);
|
||||
}
|
||||
trials[i].timing_stim = params.timing_stim || default_timing_array;
|
||||
trials[i].timing_response = params.timing_response || -1; // if -1, then wait for response forever
|
||||
// optional parameters
|
||||
trials[i].is_html = (typeof params.is_html === 'undefined') ? false : params.is_html;
|
||||
trials[i].prompt = (typeof params.prompt === 'undefined') ? "" : params.prompt;
|
||||
}
|
||||
return trials;
|
||||
};
|
||||
for (var i = 0; i < trials.length; i++) {
|
||||
trials[i] = {};
|
||||
trials[i].stimuli = params.stimuli[i];
|
||||
trials[i].choices = params.choices;
|
||||
// option to show image for fixed time interval, ignoring key responses
|
||||
// true = image will keep displaying after response
|
||||
// false = trial will immediately advance when response is recorded
|
||||
trials[i].response_ends_trial = (typeof params.response_ends_trial === 'undefined') ? true : params.response_ends_trial;
|
||||
// timing parameters
|
||||
var default_timing_array = [];
|
||||
for (var j = 0; j < params.stimuli[i].length; j++) {
|
||||
default_timing_array.push(1000);
|
||||
}
|
||||
trials[i].timing_stim = params.timing_stim || default_timing_array;
|
||||
trials[i].timing_response = params.timing_response || -1; // if -1, then wait for response forever
|
||||
// optional parameters
|
||||
trials[i].is_html = (typeof params.is_html === 'undefined') ? false : params.is_html;
|
||||
trials[i].prompt = (typeof params.prompt === 'undefined') ? "" : params.prompt;
|
||||
}
|
||||
return trials;
|
||||
};
|
||||
|
||||
|
||||
|
||||
plugin.trial = function(display_element, trial) {
|
||||
plugin.trial = function(display_element, trial) {
|
||||
|
||||
// if any trial variables are functions
|
||||
// this evaluates the function and replaces
|
||||
// it with the output of the function
|
||||
trial = jsPsych.pluginAPI.evaluateFunctionParameters(trial);
|
||||
// if any trial variables are functions
|
||||
// this evaluates the function and replaces
|
||||
// it with the output of the function
|
||||
trial = jsPsych.pluginAPI.evaluateFunctionParameters(trial);
|
||||
|
||||
// this array holds handlers from setTimeout calls
|
||||
// that need to be cleared if the trial ends early
|
||||
var setTimeoutHandlers = [];
|
||||
// this array holds handlers from setTimeout calls
|
||||
// that need to be cleared if the trial ends early
|
||||
var setTimeoutHandlers = [];
|
||||
|
||||
// array to store if we have gotten a valid response for
|
||||
// all the different response types
|
||||
var validResponses = [];
|
||||
for(var i = 0; i < trial.choices.length; i++){
|
||||
validResponses[i] = false;
|
||||
}
|
||||
// array to store if we have gotten a valid response for
|
||||
// all the different response types
|
||||
var validResponses = [];
|
||||
for (var i = 0; i < trial.choices.length; i++) {
|
||||
validResponses[i] = false;
|
||||
}
|
||||
|
||||
// array for response times for each of the different response types
|
||||
var responseTimes = [];
|
||||
for(var i = 0; i < trial.choices.length; i++){
|
||||
responseTimes[i] = -1;
|
||||
}
|
||||
// array for response times for each of the different response types
|
||||
var responseTimes = [];
|
||||
for (var i = 0; i < trial.choices.length; i++) {
|
||||
responseTimes[i] = -1;
|
||||
}
|
||||
|
||||
// array for response keys for each of the different response types
|
||||
var responseKeys = [];
|
||||
for(var i = 0; i < trial.choices.length; i++){
|
||||
responseKeys[i] = -1;
|
||||
}
|
||||
// array for response keys for each of the different response types
|
||||
var responseKeys = [];
|
||||
for (var i = 0; i < trial.choices.length; i++) {
|
||||
responseKeys[i] = -1;
|
||||
}
|
||||
|
||||
// function to check if all of the valid responses are received
|
||||
function checkAllResponsesAreValid(){
|
||||
for(var i = 0; i<validResponses.length; i++){
|
||||
if(validResponses[i] == false){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// function to check if all of the valid responses are received
|
||||
function checkAllResponsesAreValid() {
|
||||
for (var i = 0; i < validResponses.length; i++) {
|
||||
if (validResponses[i] == false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// function to end trial when it is time
|
||||
var end_trial = function() {
|
||||
// function to end trial when it is time
|
||||
var end_trial = function() {
|
||||
|
||||
// kill any remaining setTimeout handlers
|
||||
for (var i = 0; i < setTimeoutHandlers.length; i++) {
|
||||
clearTimeout(setTimeoutHandlers[i]);
|
||||
}
|
||||
// kill any remaining setTimeout handlers
|
||||
for (var i = 0; i < setTimeoutHandlers.length; i++) {
|
||||
clearTimeout(setTimeoutHandlers[i]);
|
||||
}
|
||||
|
||||
// kill keyboard listeners
|
||||
jsPsych.pluginAPI.cancelKeyboardResponse(keyboardListener);
|
||||
// kill keyboard listeners
|
||||
jsPsych.pluginAPI.cancelKeyboardResponse(keyboardListener);
|
||||
|
||||
// gather the data to store for the trial
|
||||
var trial_data = {
|
||||
"rt": JSON.stringify(responseTimes),
|
||||
"stimulus": JSON.stringify(trial.stimuli),
|
||||
"key_press": JSON.stringify(responseKeys)
|
||||
};
|
||||
// gather the data to store for the trial
|
||||
var trial_data = {
|
||||
"rt": JSON.stringify(responseTimes),
|
||||
"stimulus": JSON.stringify(trial.stimuli),
|
||||
"key_press": JSON.stringify(responseKeys)
|
||||
};
|
||||
|
||||
jsPsych.data.write(trial_data);
|
||||
jsPsych.data.write(trial_data);
|
||||
|
||||
// clear the display
|
||||
display_element.html('');
|
||||
// clear the display
|
||||
display_element.html('');
|
||||
|
||||
// move on to the next trial
|
||||
jsPsych.finishTrial();
|
||||
};
|
||||
// move on to the next trial
|
||||
jsPsych.finishTrial();
|
||||
};
|
||||
|
||||
// function to handle responses by the subject
|
||||
var after_response = function(info) {
|
||||
// function to handle responses by the subject
|
||||
var after_response = function(info) {
|
||||
|
||||
var whichResponse;
|
||||
for(var i = 0; i<trial.choices.length; i++){
|
||||
var whichResponse;
|
||||
for (var i = 0; i < trial.choices.length; i++) {
|
||||
|
||||
for(var j = 0; j < trial.choices[i].length; j++){
|
||||
keycode = (typeof trial.choices[i][j] == 'string') ? jsPsych.pluginAPI.convertKeyCharacterToKeyCode(trial.choices[i][j]) : trial.choices[i][j];
|
||||
if(info.key == keycode){
|
||||
whichResponse = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (var j = 0; j < trial.choices[i].length; j++) {
|
||||
keycode = (typeof trial.choices[i][j] == 'string') ? jsPsych.pluginAPI.convertKeyCharacterToKeyCode(trial.choices[i][j]) : trial.choices[i][j];
|
||||
if (info.key == keycode) {
|
||||
whichResponse = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(typeof whichResponse !== 'undefined') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (typeof whichResponse !== 'undefined') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(validResponses[whichResponse] != true){
|
||||
validResponses[whichResponse] = true;
|
||||
responseTimes[whichResponse] = info.rt;
|
||||
responseKeys[whichResponse] = info.key;
|
||||
}
|
||||
if (validResponses[whichResponse] != true) {
|
||||
validResponses[whichResponse] = true;
|
||||
responseTimes[whichResponse] = info.rt;
|
||||
responseKeys[whichResponse] = info.key;
|
||||
}
|
||||
|
||||
if (trial.response_ends_trial) {
|
||||
if (trial.response_ends_trial) {
|
||||
|
||||
if(checkAllResponsesAreValid()){
|
||||
end_trial();
|
||||
}
|
||||
if (checkAllResponsesAreValid()) {
|
||||
end_trial();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
// flattened version of the choices array
|
||||
var allchoices = [];
|
||||
for(var i=0;i<trial.choices.length; i++){
|
||||
allchoices = allchoices.concat(trial.choices[i]);
|
||||
}
|
||||
// flattened version of the choices array
|
||||
var allchoices = [];
|
||||
for (var i = 0; i < trial.choices.length; i++) {
|
||||
allchoices = allchoices.concat(trial.choices[i]);
|
||||
}
|
||||
|
||||
var whichStimulus = 0;
|
||||
var whichStimulus = 0;
|
||||
|
||||
function showNextStimulus(){
|
||||
function showNextStimulus() {
|
||||
|
||||
// display stimulus
|
||||
if (!trial.is_html) {
|
||||
display_element.append($('<img>', {
|
||||
src: trial.stimuli[whichStimulus],
|
||||
id: 'jspsych-multi-stim-multi-response-stimulus'
|
||||
}));
|
||||
} else {
|
||||
display_element.append($('<div>', {
|
||||
html: trial.stimuli[whichStimulus],
|
||||
id: 'jspsych-multi-stim-multi-response-stimulus'
|
||||
}));
|
||||
}
|
||||
// display stimulus
|
||||
if (!trial.is_html) {
|
||||
display_element.append($('<img>', {
|
||||
src: trial.stimuli[whichStimulus],
|
||||
id: 'jspsych-multi-stim-multi-response-stimulus'
|
||||
}));
|
||||
} else {
|
||||
display_element.append($('<div>', {
|
||||
html: trial.stimuli[whichStimulus],
|
||||
id: 'jspsych-multi-stim-multi-response-stimulus'
|
||||
}));
|
||||
}
|
||||
|
||||
//show prompt if there is one
|
||||
if (trial.prompt !== "") {
|
||||
display_element.append(trial.prompt);
|
||||
}
|
||||
//show prompt if there is one
|
||||
if (trial.prompt !== "") {
|
||||
display_element.append(trial.prompt);
|
||||
}
|
||||
|
||||
if (typeof trial.timing_stim[whichStimulus] !== 'undefined' && trial.timing_stim[whichStimulus] > 0) {
|
||||
var t1 = setTimeout(function() {
|
||||
// clear the display, or hide the display
|
||||
if(typeof trial.stimuli[whichStimulus + 1] !== 'undefined'){
|
||||
display_element.html('');
|
||||
// show the next stimulus
|
||||
whichStimulus++;
|
||||
showNextStimulus();
|
||||
} else {
|
||||
$('#jspsych-multi-stim-multi-response-stimulus').css('visibility','hidden');
|
||||
}
|
||||
if (typeof trial.timing_stim[whichStimulus] !== 'undefined' && trial.timing_stim[whichStimulus] > 0) {
|
||||
var t1 = setTimeout(function() {
|
||||
// clear the display, or hide the display
|
||||
if (typeof trial.stimuli[whichStimulus + 1] !== 'undefined') {
|
||||
display_element.html('');
|
||||
// show the next stimulus
|
||||
whichStimulus++;
|
||||
showNextStimulus();
|
||||
} else {
|
||||
$('#jspsych-multi-stim-multi-response-stimulus').css('visibility', 'hidden');
|
||||
}
|
||||
|
||||
}, trial.timing_stim[whichStimulus]);
|
||||
}, trial.timing_stim[whichStimulus]);
|
||||
|
||||
setTimeoutHandlers.push(t1);
|
||||
}
|
||||
setTimeoutHandlers.push(t1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// show first stimulus
|
||||
showNextStimulus();
|
||||
// show first stimulus
|
||||
showNextStimulus();
|
||||
|
||||
// start the response listener
|
||||
var keyboardListener = jsPsych.pluginAPI.getKeyboardResponse(after_response, allchoices, "date", true);
|
||||
// start the response listener
|
||||
var keyboardListener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||
callback_function: after_response,
|
||||
valid_responses: allchoices,
|
||||
rt_method: 'date',
|
||||
persist: true,
|
||||
allow_held_key: false
|
||||
});
|
||||
|
||||
// end trial if time limit is set
|
||||
if (trial.timing_response > 0) {
|
||||
var t2 = setTimeout(function() {
|
||||
end_trial();
|
||||
}, trial.timing_response);
|
||||
setTimeoutHandlers.push(t2);
|
||||
}
|
||||
// end trial if time limit is set
|
||||
if (trial.timing_response > 0) {
|
||||
var t2 = setTimeout(function() {
|
||||
end_trial();
|
||||
}, trial.timing_response);
|
||||
setTimeoutHandlers.push(t2);
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
return plugin;
|
||||
})();
|
||||
return plugin;
|
||||
})();
|
||||
})(jQuery);
|
||||
|
@ -64,8 +64,13 @@
|
||||
}
|
||||
|
||||
// listen for responses
|
||||
var key_listener = jsPsych.pluginAPI.getKeyboardResponse(after_response, [trial.key_increase, trial.key_decrease], 'date', true);
|
||||
|
||||
var key_listener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||
callback_function: after_response,
|
||||
valid_responses: [trial.key_increase, trial.key_decrease],
|
||||
rt_method: 'date',
|
||||
persist: true,
|
||||
allow_held_key: true
|
||||
});
|
||||
// draw first iteration
|
||||
draw(param);
|
||||
|
||||
|
@ -132,7 +132,13 @@
|
||||
jsPsych.finishTrial();
|
||||
}
|
||||
|
||||
jsPsych.pluginAPI.getKeyboardResponse(after_response, [trial.same_key, trial.different_key], 'date', false);
|
||||
jsPsych.pluginAPI.getKeyboardResponse({
|
||||
callback_function: after_response,
|
||||
valid_responses: [trial.same_key, trial.different_key],
|
||||
rt_method: 'date',
|
||||
persist: false,
|
||||
allow_held_key: false
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
@ -111,8 +111,15 @@
|
||||
};
|
||||
|
||||
// start the response listener
|
||||
var keyboardListener = jsPsych.pluginAPI.getKeyboardResponse(after_response, trial.choices, 'audio', false, context, startTime);
|
||||
|
||||
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
|
||||
});
|
||||
// end trial if time limit is set
|
||||
if (trial.timing_response > 0) {
|
||||
var t2 = setTimeout(function() {
|
||||
|
@ -115,7 +115,13 @@
|
||||
|
||||
// start the response listener
|
||||
if(JSON.stringify(trial.choices) != JSON.stringify(["none"])) {
|
||||
var keyboardListener = jsPsych.pluginAPI.getKeyboardResponse(after_response, trial.choices);
|
||||
var keyboardListener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||
callback_function: after_response,
|
||||
valid_responses: trial.choices,
|
||||
rt_method: 'date',
|
||||
persist: false,
|
||||
allow_held_key: false
|
||||
});
|
||||
}
|
||||
|
||||
// hide image if timing is set
|
||||
|
@ -19,9 +19,19 @@
|
||||
|
||||
var trials = [];
|
||||
for (var i = 0; i < params.questions.length; i++) {
|
||||
var rows = [], cols = [];
|
||||
if(typeof params.rows == 'undefined' || typeof params.columns == 'undefined'){
|
||||
for(var j = 0; j < params.questions[i].length; j++){
|
||||
cols.push(40);
|
||||
rows.push(1);
|
||||
}
|
||||
}
|
||||
|
||||
trials.push({
|
||||
preamble: typeof params.preamble == 'undefined' ? "" : params.preamble[i],
|
||||
questions: params.questions[i]
|
||||
questions: params.questions[i],
|
||||
rows: typeof params.rows == 'undefined' ? rows : params.rows[i],
|
||||
columns: typeof params.columns == 'undefined' ? cols : params.columns[i]
|
||||
});
|
||||
}
|
||||
return trials;
|
||||
@ -54,7 +64,7 @@
|
||||
$("#jspsych-survey-text-" + i).append('<p class="jspsych-survey-text">' + trial.questions[i] + '</p>');
|
||||
|
||||
// add text box
|
||||
$("#jspsych-survey-text-" + i).append('<input type="text" name="#jspsych-survey-text-response-' + i + '"></input>');
|
||||
$("#jspsych-survey-text-" + i).append('<textarea name="#jspsych-survey-text-response-' + i + '" cols="'+trial.columns[i]+'" rows="'+trial.rows[i]+'"></textarea>');
|
||||
}
|
||||
|
||||
// add submit button
|
||||
@ -72,7 +82,7 @@
|
||||
var question_data = {};
|
||||
$("div.jspsych-survey-text-question").each(function(index) {
|
||||
var id = "Q" + index;
|
||||
var val = $(this).children('input').val();
|
||||
var val = $(this).children('textarea').val();
|
||||
var obje = {};
|
||||
obje[id] = val;
|
||||
$.extend(question_data, obje);
|
||||
|
@ -62,7 +62,13 @@
|
||||
display_element.click(mouse_listener);
|
||||
var start_time = (new Date()).getTime();
|
||||
} else {
|
||||
jsPsych.pluginAPI.getKeyboardResponse(after_response, trial.cont_key);
|
||||
jsPsych.pluginAPI.getKeyboardResponse({
|
||||
callback_function: after_response,
|
||||
valid_responses: trial.cont_key,
|
||||
rt_method: 'date',
|
||||
persist: false,
|
||||
allow_held_key: false
|
||||
});
|
||||
}
|
||||
|
||||
function save_data(key, rt) {
|
||||
|
@ -129,7 +129,13 @@
|
||||
|
||||
var valid_keys = [trial.target_present_key, trial.target_absent_key];
|
||||
|
||||
key_listener = jsPsych.pluginAPI.getKeyboardResponse(after_response, valid_keys, 'date', false);
|
||||
key_listener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||
callback_function: after_response,
|
||||
valid_responses: valid_keys,
|
||||
rt_method: 'date',
|
||||
persist: false,
|
||||
allow_held_key: false
|
||||
});
|
||||
|
||||
if (trial.timing_max_search > -1) {
|
||||
|
||||
@ -171,7 +177,7 @@
|
||||
}
|
||||
|
||||
function clear_display() {
|
||||
paper.clear();
|
||||
display_element.html('');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,7 +125,13 @@
|
||||
});
|
||||
}
|
||||
|
||||
key_listener = jsPsych.pluginAPI.getKeyboardResponse(after_response, trial.choices, 'date', true);
|
||||
key_listener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||
callback_function: after_response,
|
||||
valid_responses: trial.choices,
|
||||
rt_method: 'date',
|
||||
persist: true,
|
||||
allow_held_key: false
|
||||
});
|
||||
|
||||
if (trial.timing_pre_movement > 0) {
|
||||
setTimeout(function() {
|
||||
|
@ -9,172 +9,177 @@
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
jsPsych.xab = (function() {
|
||||
jsPsych.xab = (function() {
|
||||
|
||||
var plugin = {};
|
||||
var plugin = {};
|
||||
|
||||
plugin.create = function(params) {
|
||||
plugin.create = function(params) {
|
||||
|
||||
params = jsPsych.pluginAPI.enforceArray(params, ['data']);
|
||||
params = jsPsych.pluginAPI.enforceArray(params, ['data']);
|
||||
|
||||
// the number of trials is determined by how many entries the params.stimuli array has
|
||||
var trials = new Array(params.stimuli.length);
|
||||
// the number of trials is determined by how many entries the params.stimuli array has
|
||||
var trials = new Array(params.stimuli.length);
|
||||
|
||||
for (var i = 0; i < trials.length; i++) {
|
||||
trials[i] = {};
|
||||
trials[i].x_path = params.stimuli[i][0];
|
||||
// if there is only a pair of stimuli, then the first is the target and is shown twice.
|
||||
// if there is a triplet, then the first is X, the second is the target, and the third is foil (useful for non-exact-match XAB).
|
||||
if (params.stimuli[i].length == 2) {
|
||||
trials[i].a_path = params.stimuli[i][0];
|
||||
trials[i].b_path = params.stimuli[i][1];
|
||||
} else {
|
||||
trials[i].a_path = params.stimuli[i][1];
|
||||
trials[i].b_path = params.stimuli[i][2];
|
||||
}
|
||||
trials[i].left_key = params.left_key || 81; // defaults to 'q'
|
||||
trials[i].right_key = params.right_key || 80; // defaults to 'p'
|
||||
// timing parameters
|
||||
trials[i].timing_x = params.timing_x || 1000; // defaults to 1000msec.
|
||||
trials[i].timing_xab_gap = params.timing_xab_gap || 1000; // defaults to 1000msec.
|
||||
trials[i].timing_ab = params.timing_ab || -1; // defaults to -1, meaning infinite time on AB. If a positive number is used, then AB will only be displayed for that length.
|
||||
// optional parameters
|
||||
trials[i].is_html = (typeof params.is_html === 'undefined') ? false : params.is_html;
|
||||
trials[i].prompt = (typeof params.prompt === 'undefined') ? "" : params.prompt;
|
||||
for (var i = 0; i < trials.length; i++) {
|
||||
trials[i] = {};
|
||||
trials[i].x_path = params.stimuli[i][0];
|
||||
// if there is only a pair of stimuli, then the first is the target and is shown twice.
|
||||
// if there is a triplet, then the first is X, the second is the target, and the third is foil (useful for non-exact-match XAB).
|
||||
if (params.stimuli[i].length == 2) {
|
||||
trials[i].a_path = params.stimuli[i][0];
|
||||
trials[i].b_path = params.stimuli[i][1];
|
||||
} else {
|
||||
trials[i].a_path = params.stimuli[i][1];
|
||||
trials[i].b_path = params.stimuli[i][2];
|
||||
}
|
||||
trials[i].left_key = params.left_key || 81; // defaults to 'q'
|
||||
trials[i].right_key = params.right_key || 80; // defaults to 'p'
|
||||
// timing parameters
|
||||
trials[i].timing_x = params.timing_x || 1000; // defaults to 1000msec.
|
||||
trials[i].timing_xab_gap = params.timing_xab_gap || 1000; // defaults to 1000msec.
|
||||
trials[i].timing_ab = params.timing_ab || -1; // defaults to -1, meaning infinite time on AB. If a positive number is used, then AB will only be displayed for that length.
|
||||
// optional parameters
|
||||
trials[i].is_html = (typeof params.is_html === 'undefined') ? false : params.is_html;
|
||||
trials[i].prompt = (typeof params.prompt === 'undefined') ? "" : params.prompt;
|
||||
|
||||
}
|
||||
return trials;
|
||||
};
|
||||
}
|
||||
return trials;
|
||||
};
|
||||
|
||||
plugin.trial = function(display_element, trial) {
|
||||
plugin.trial = function(display_element, trial) {
|
||||
|
||||
// if any trial variables are functions
|
||||
// this evaluates the function and replaces
|
||||
// it with the output of the function
|
||||
trial = jsPsych.pluginAPI.evaluateFunctionParameters(trial);
|
||||
// if any trial variables are functions
|
||||
// this evaluates the function and replaces
|
||||
// it with the output of the function
|
||||
trial = jsPsych.pluginAPI.evaluateFunctionParameters(trial);
|
||||
|
||||
// this array holds handlers from setTimeout calls
|
||||
// that need to be cleared if the trial ends early
|
||||
var setTimeoutHandlers = [];
|
||||
// this array holds handlers from setTimeout calls
|
||||
// that need to be cleared if the trial ends early
|
||||
var setTimeoutHandlers = [];
|
||||
|
||||
// how we display the content depends on whether the content is
|
||||
// HTML code or an image path.
|
||||
if (!trial.is_html) {
|
||||
display_element.append($('<img>', {
|
||||
src: trial.x_path,
|
||||
"class": 'jspsych-xab-stimulus'
|
||||
}));
|
||||
} else {
|
||||
display_element.append($('<div>', {
|
||||
"class": 'jspsych-xab-stimulus',
|
||||
html: trial.x_path
|
||||
}));
|
||||
}
|
||||
// how we display the content depends on whether the content is
|
||||
// HTML code or an image path.
|
||||
if (!trial.is_html) {
|
||||
display_element.append($('<img>', {
|
||||
src: trial.x_path,
|
||||
"class": 'jspsych-xab-stimulus'
|
||||
}));
|
||||
} else {
|
||||
display_element.append($('<div>', {
|
||||
"class": 'jspsych-xab-stimulus',
|
||||
html: trial.x_path
|
||||
}));
|
||||
}
|
||||
|
||||
// start a timer of length trial.timing_x to move to the next part of the trial
|
||||
setTimeout(function() {
|
||||
showBlankScreen();
|
||||
}, trial.timing_x);
|
||||
// start a timer of length trial.timing_x to move to the next part of the trial
|
||||
setTimeout(function() {
|
||||
showBlankScreen();
|
||||
}, trial.timing_x);
|
||||
|
||||
|
||||
function showBlankScreen() {
|
||||
// remove the x stimulus
|
||||
$('.jspsych-xab-stimulus').remove();
|
||||
function showBlankScreen() {
|
||||
// remove the x stimulus
|
||||
$('.jspsych-xab-stimulus').remove();
|
||||
|
||||
// start timer
|
||||
setTimeout(function() {
|
||||
showSecondStimulus();
|
||||
}, trial.timing_xab_gap);
|
||||
}
|
||||
// start timer
|
||||
setTimeout(function() {
|
||||
showSecondStimulus();
|
||||
}, trial.timing_xab_gap);
|
||||
}
|
||||
|
||||
|
||||
function showSecondStimulus() {
|
||||
function showSecondStimulus() {
|
||||
|
||||
// randomize whether the target is on the left or the right
|
||||
var images = [trial.a_path, trial.b_path];
|
||||
var target_left = (Math.floor(Math.random() * 2) === 0); // 50% chance target is on left.
|
||||
if (!target_left) {
|
||||
images = [trial.b_path, trial.a_path];
|
||||
}
|
||||
// randomize whether the target is on the left or the right
|
||||
var images = [trial.a_path, trial.b_path];
|
||||
var target_left = (Math.floor(Math.random() * 2) === 0); // 50% chance target is on left.
|
||||
if (!target_left) {
|
||||
images = [trial.b_path, trial.a_path];
|
||||
}
|
||||
|
||||
// show the options
|
||||
if (!trial.is_html) {
|
||||
display_element.append($('<img>', {
|
||||
"src": images[0],
|
||||
"class": 'jspsych-xab-stimulus left'
|
||||
}));
|
||||
display_element.append($('<img>', {
|
||||
"src": images[1],
|
||||
"class": 'jspsych-xab-stimulus right'
|
||||
}));
|
||||
} else {
|
||||
display_element.append($('<div>', {
|
||||
"class": 'jspsych-xab-stimulus left',
|
||||
html: images[0]
|
||||
}));
|
||||
display_element.append($('<div>', {
|
||||
"class": 'jspsych-xab-stimulus right',
|
||||
html: images[1]
|
||||
}));
|
||||
}
|
||||
// show the options
|
||||
if (!trial.is_html) {
|
||||
display_element.append($('<img>', {
|
||||
"src": images[0],
|
||||
"class": 'jspsych-xab-stimulus left'
|
||||
}));
|
||||
display_element.append($('<img>', {
|
||||
"src": images[1],
|
||||
"class": 'jspsych-xab-stimulus right'
|
||||
}));
|
||||
} else {
|
||||
display_element.append($('<div>', {
|
||||
"class": 'jspsych-xab-stimulus left',
|
||||
html: images[0]
|
||||
}));
|
||||
display_element.append($('<div>', {
|
||||
"class": 'jspsych-xab-stimulus right',
|
||||
html: images[1]
|
||||
}));
|
||||
}
|
||||
|
||||
if (trial.prompt !== "") {
|
||||
display_element.append(trial.prompt);
|
||||
}
|
||||
if (trial.prompt !== "") {
|
||||
display_element.append(trial.prompt);
|
||||
}
|
||||
|
||||
// if timing_ab is > 0, then we hide the stimuli after timing_ab milliseconds
|
||||
if (trial.timing_ab > 0) {
|
||||
setTimeoutHandlers.push(setTimeout(function() {
|
||||
$('.jspsych-xab-stimulus').css('visibility', 'hidden');
|
||||
}, trial.timing_ab));
|
||||
}
|
||||
// if timing_ab is > 0, then we hide the stimuli after timing_ab milliseconds
|
||||
if (trial.timing_ab > 0) {
|
||||
setTimeoutHandlers.push(setTimeout(function() {
|
||||
$('.jspsych-xab-stimulus').css('visibility', 'hidden');
|
||||
}, trial.timing_ab));
|
||||
}
|
||||
|
||||
// create the function that triggers when a key is pressed.
|
||||
var after_response = function(info) {
|
||||
// create the function that triggers when a key is pressed.
|
||||
var after_response = function(info) {
|
||||
|
||||
// kill any remaining setTimeout handlers
|
||||
for (var i = 0; i < setTimeoutHandlers.length; i++) {
|
||||
clearTimeout(setTimeoutHandlers[i]);
|
||||
}
|
||||
// kill any remaining setTimeout handlers
|
||||
for (var i = 0; i < setTimeoutHandlers.length; i++) {
|
||||
clearTimeout(setTimeoutHandlers[i]);
|
||||
}
|
||||
|
||||
var correct = false; // true when the correct response is chosen
|
||||
var correct = false; // true when the correct response is chosen
|
||||
|
||||
if (info.key == trial.left_key) // 'q' key by default
|
||||
{
|
||||
if (target_left) {
|
||||
correct = true;
|
||||
}
|
||||
} else if (info.key == trial.right_key) // 'p' key by default
|
||||
{
|
||||
if (!target_left) {
|
||||
correct = true;
|
||||
}
|
||||
}
|
||||
if (info.key == trial.left_key) // 'q' key by default
|
||||
{
|
||||
if (target_left) {
|
||||
correct = true;
|
||||
}
|
||||
} else if (info.key == trial.right_key) // 'p' key by default
|
||||
{
|
||||
if (!target_left) {
|
||||
correct = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// create object to store data from trial
|
||||
var trial_data = {
|
||||
"rt": info.rt,
|
||||
"correct": correct,
|
||||
"stimulus": JSON.stringify([trial.x_path,trial.a_path,trial.b_path]),
|
||||
"key_press": info.key
|
||||
};
|
||||
jsPsych.data.write(trial_data);
|
||||
// create object to store data from trial
|
||||
var trial_data = {
|
||||
"rt": info.rt,
|
||||
"correct": correct,
|
||||
"stimulus": JSON.stringify([trial.x_path, trial.a_path, trial.b_path]),
|
||||
"key_press": info.key
|
||||
};
|
||||
jsPsych.data.write(trial_data);
|
||||
|
||||
display_element.html(''); // remove all
|
||||
display_element.html(''); // remove all
|
||||
|
||||
xab_trial_complete = true;
|
||||
xab_trial_complete = true;
|
||||
|
||||
// move on to the next trial after timing_post_trial milliseconds
|
||||
jsPsych.finishTrial();
|
||||
// move on to the next trial after timing_post_trial milliseconds
|
||||
jsPsych.finishTrial();
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
jsPsych.pluginAPI.getKeyboardResponse(after_response, [trial.left_key, trial.right_key], 'date', false);
|
||||
jsPsych.pluginAPI.getKeyboardResponse({
|
||||
callback_function: after_response,
|
||||
valid_responses: [trial.left_key, trial.right_key],
|
||||
rt_method: 'date',
|
||||
persist: false,
|
||||
allow_held_key: false
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
return plugin;
|
||||
})();
|
||||
return plugin;
|
||||
})();
|
||||
})(jQuery);
|
||||
|
40
tests&examples/data-add-to-last-trial.html
Normal file
40
tests&examples/data-add-to-last-trial.html
Normal file
@ -0,0 +1,40 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="js/jquery.min.js"></script>
|
||||
<script src="../jspsych.js"></script>
|
||||
<script src="../plugins/jspsych-single-stim.js"></script>
|
||||
<link rel="stylesheet" href="../css/jspsych.css"></link>
|
||||
<style>
|
||||
img { width: 300px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="jspsych-target"></div>
|
||||
</body>
|
||||
<script>
|
||||
|
||||
var block_1 = {
|
||||
type: 'single-stim',
|
||||
stimuli: ['img/happy_face_1.jpg', 'img/sad_face_1.jpg'],
|
||||
choices: [89,78], // Y or N
|
||||
prompt: '<p class="center-content">Have you seen this face before? Y or N.</p>',
|
||||
on_finish: function(){
|
||||
jsPsych.data.addDataToLastTrial({correct: true});
|
||||
}
|
||||
}
|
||||
|
||||
function start(){
|
||||
jsPsych.init({
|
||||
display_element: $('#jspsych-target'),
|
||||
experiment_structure: [block_1],
|
||||
on_finish: function(){
|
||||
jsPsych.data.displayData();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
jsPsych.preloadImages(['img/happy_face_1.jpg','img/sad_face_1.jpg'], start);
|
||||
|
||||
</script>
|
||||
</html>
|
@ -23,6 +23,9 @@
|
||||
correct_text: "<p class='center-content'>Correct. This face is %ANS%.</p>",
|
||||
incorrect_text: "<p class='center-content'>Incorrect. This face is %ANS%.</p>",
|
||||
prompt: "<p class='center-content'>Press H if the face is happy. Press S if the face is sad.</p>",
|
||||
timing_response: 1500,
|
||||
show_feedback_on_timeout: false,
|
||||
force_correct_button_press: true
|
||||
};
|
||||
|
||||
function start(){
|
||||
|
23
tests&examples/randomization-module.html
Normal file
23
tests&examples/randomization-module.html
Normal file
@ -0,0 +1,23 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="js/jquery.min.js"></script>
|
||||
<script src="../jspsych.js"></script>
|
||||
<link rel="stylesheet" href="../css/jspsych.css"></link>
|
||||
<style>
|
||||
img { width: 300px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="jspsych-target"></div>
|
||||
</body>
|
||||
<script>
|
||||
|
||||
var repeated_list = jsPsych.randomization.repeat([1,2,3,4,5],3);
|
||||
console.log(JSON.stringify(repeated_list));
|
||||
|
||||
var no_neighbor_repeats = jsPsych.randomization.shuffleNoRepeats(repeated_list);
|
||||
console.log(JSON.stringify(no_neighbor_repeats));
|
||||
|
||||
</script>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user