updating plugins to match new format

This commit is contained in:
Josh de Leeuw 2015-12-13 23:06:31 -05:00
parent 0742ebc246
commit dadede318d
5 changed files with 341 additions and 423 deletions

View File

@ -5,130 +5,118 @@
* documentation: docs.jspsych.org
*/
(function($) {
jsPsych.animation = (function() {
var plugin = {};
jsPsych.animation = (function() {
plugin.create = function(params) {
var plugin = {};
params = jsPsych.pluginAPI.enforceArray(params, ['choices']);
plugin.trial = function(display_element, trial) {
var trials = new Array(params.stimuli.length);
for (var i = 0; i < trials.length; i++) {
trials[i] = {};
trials[i].stims = params.stimuli[i];
trials[i].frame_time = params.frame_time || 250;
trials[i].frame_isi = params.frame_isi || 0;
trials[i].sequence_reps = params.sequence_reps || 1;
trials[i].choices = params.choices || [];
trials[i].prompt = (typeof params.prompt === 'undefined') ? "" : params.prompt;
}
return trials;
};
trials.frame_time = trial.frame_time || 250;
trials.frame_isi = trial.frame_isi || 0;
trials.sequence_reps = trial.sequence_reps || 1;
trials.choices = trial.choices || [];
trials.prompt = (typeof trial.prompt === 'undefined') ? "" : trial.prompt;
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 interval_time = trial.frame_time + trial.frame_isi;
var animate_frame = -1;
var reps = 0;
var startTime = (new Date()).getTime();
var animation_sequence = [];
var responses = [];
var current_stim = "";
var interval_time = trial.frame_time + trial.frame_isi;
var animate_frame = -1;
var reps = 0;
var startTime = (new Date()).getTime();
var animation_sequence = [];
var responses = [];
var current_stim = "";
var animate_interval = setInterval(function() {
var showImage = true;
display_element.html(""); // clear everything
animate_frame++;
if (animate_frame == trial.stims.length) {
animate_frame = 0;
reps++;
if (reps >= trial.sequence_reps) {
endTrial();
clearInterval(animate_interval);
showImage = false;
}
}
if (showImage) {
show_next_frame();
}
}, interval_time);
function show_next_frame() {
// show image
display_element.append($('<img>', {
"src": trial.stims[animate_frame],
"id": 'jspsych-animation-image'
}));
current_stim = trial.stims[animate_frame];
// record when image was shown
animation_sequence.push({
"stimulus": current_stim,
"time": (new Date()).getTime() - startTime
});
if (trial.prompt !== "") {
display_element.append(trial.prompt);
}
if (trial.frame_isi > 0) {
setTimeout(function() {
$('#jspsych-animation-image').css('visibility', 'hidden');
current_stim = 'blank';
// record when blank image was shown
animation_sequence.push({
"stimulus": 'blank',
"time": (new Date()).getTime() - startTime
});
}, trial.frame_time);
var animate_interval = setInterval(function() {
var showImage = true;
display_element.html(""); // clear everything
animate_frame++;
if (animate_frame == trial.stimuli.length) {
animate_frame = 0;
reps++;
if (reps >= trial.sequence_reps) {
endTrial();
clearInterval(animate_interval);
showImage = false;
}
}
var after_response = function(info) {
responses.push({
key_press: info.key,
rt: info.rt,
stimulus: current_stim
});
// after a valid response, the stimulus will have the CSS class 'responded'
// which can be used to provide visual feedback that a response was recorded
$("#jspsych-animation-image").addClass('responded');
if (showImage) {
show_next_frame();
}
}, interval_time);
// 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({
callback_function: after_response,
valid_responses: trial.choices,
rt_method: 'date',
persist: true,
allow_held_key: false
function show_next_frame() {
// show image
display_element.append($('<img>', {
"src": trial.stimuli[animate_frame],
"id": 'jspsych-animation-image'
}));
current_stim = trial.stimuli[animate_frame];
// record when image was shown
animation_sequence.push({
"stimulus": current_stim,
"time": (new Date()).getTime() - startTime
});
function endTrial() {
jsPsych.pluginAPI.cancelKeyboardResponse(response_listener);
jsPsych.data.write({
"animation_sequence": JSON.stringify(animation_sequence),
"responses": JSON.stringify(responses)
});
jsPsych.finishTrial();
if (trial.prompt !== "") {
display_element.append(trial.prompt);
}
};
return plugin;
})();
})(jQuery);
if (trial.frame_isi > 0) {
setTimeout(function() {
$('#jspsych-animation-image').css('visibility', 'hidden');
current_stim = 'blank';
// record when blank image was shown
animation_sequence.push({
"stimulus": 'blank',
"time": (new Date()).getTime() - startTime
});
}, trial.frame_time);
}
}
var after_response = function(info) {
responses.push({
key_press: info.key,
rt: info.rt,
stimulus: current_stim
});
// after a valid response, the stimulus will have the CSS class 'responded'
// which can be used to provide visual feedback that a response was recorded
$("#jspsych-animation-image").addClass('responded');
}
// 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({
callback_function: after_response,
valid_responses: trial.choices,
rt_method: 'date',
persist: true,
allow_held_key: false
});
function endTrial() {
jsPsych.pluginAPI.cancelKeyboardResponse(response_listener);
var trial_data = {
"animation_sequence": JSON.stringify(animation_sequence),
"responses": JSON.stringify(responses)
};
jsPsych.finishTrial(trial_data);
}
};
return plugin;
})();

View File

@ -9,165 +9,152 @@
*
*/
(function($) {
jsPsych.instructions = (function() {
jsPsych.instructions = (function() {
var plugin = {};
var plugin = {};
plugin.create = function(params) {
plugin.trial = function(display_element, trial) {
params = jsPsych.pluginAPI.enforceArray(params, ['pages']);
trial.key_forward = trial.key_forward || 'rightarrow';
trial.key_backward = trial.key_backward || 'leftarrow';
trial.allow_backward = (typeof trial.allow_backward === 'undefined') ? true : trial.allow_backward;
trial.allow_keys = (typeof trial.allow_keys === 'undefined') ? true : trial.allow_keys;
trial.show_clickable_nav = (typeof trial.show_clickable_nav === 'undefined') ? false : trial.show_clickable_nav;
var trials = new Array(1);
// if any trial variables are functions
// this evaluates the function and replaces
// it with the output of the function
trial = jsPsych.pluginAPI.evaluateFunctionParameters(trial);
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;
var current_page = 0;
return trials;
};
var view_history = [];
plugin.trial = function(display_element, trial) {
var start_time = (new Date()).getTime();
// 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 last_page_update_time = start_time;
var current_page = 0;
function show_current_page() {
display_element.html(trial.pages[current_page]);
var view_history = [];
if (trial.show_clickable_nav) {
var start_time = (new Date()).getTime();
var nav_html = "<div class='jspsych-instructions-nav'>";
if (current_page != 0 && trial.allow_backward) {
nav_html += "<button id='jspsych-instructions-back' class='jspsych-btn'>&lt; Previous</button>";
}
nav_html += "<button id='jspsych-instructions-next' class='jspsych-btn'>Next &gt;</button></div>"
var last_page_update_time = start_time;
display_element.append(nav_html);
function show_current_page() {
display_element.html(trial.pages[current_page]);
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' class='jspsych-btn'>&lt; Previous</button>";
}
nav_html += "<button id='jspsych-instructions-next' class='jspsych-btn'>Next &gt;</button></div>"
display_element.append(nav_html);
if (current_page != 0 && trial.allow_backward) {
$('#jspsych-instructions-back').on('click', function() {
clear_button_handlers();
back();
});
}
$('#jspsych-instructions-next').on('click', function() {
if (current_page != 0 && trial.allow_backward) {
$('#jspsych-instructions-back').on('click', function() {
clear_button_handlers();
next();
back();
});
}
}
function clear_button_handlers() {
$('#jspsych-instructions-next').off('click');
$('#jspsych-instructions-back').off('click');
}
function next() {
add_current_page_to_view_history()
current_page++;
// if done, finish up...
if (current_page >= trial.pages.length) {
endTrial();
} else {
show_current_page();
}
$('#jspsych-instructions-next').on('click', function() {
clear_button_handlers();
next();
});
}
}
function back() {
function clear_button_handlers() {
$('#jspsych-instructions-next').off('click');
$('#jspsych-instructions-back').off('click');
}
add_current_page_to_view_history()
function next() {
current_page--;
add_current_page_to_view_history()
current_page++;
// if done, finish up...
if (current_page >= trial.pages.length) {
endTrial();
} else {
show_current_page();
}
function add_current_page_to_view_history() {
}
var current_time = (new Date()).getTime();
function back() {
var page_view_time = current_time - last_page_update_time;
add_current_page_to_view_history()
view_history.push({
page_index: current_page,
viewing_time: page_view_time
});
last_page_update_time = current_time;
}
function endTrial() {
if (trial.allow_keys) {
jsPsych.pluginAPI.cancelKeyboardResponse(keyboard_listener);
}
display_element.html('');
jsPsych.data.write({
"view_history": JSON.stringify(view_history),
"rt": (new Date()).getTime() - start_time
});
jsPsych.finishTrial();
}
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({
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();
}
}
if (info.key === trial.key_forward || info.key === jsPsych.pluginAPI.convertKeyCharacterToKeyCode(trial.key_forward)) {
next();
}
};
current_page--;
show_current_page();
}
function add_current_page_to_view_history() {
var current_time = (new Date()).getTime();
var page_view_time = current_time - last_page_update_time;
view_history.push({
page_index: current_page,
viewing_time: page_view_time
});
last_page_update_time = current_time;
}
function endTrial() {
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
});
jsPsych.pluginAPI.cancelKeyboardResponse(keyboard_listener);
}
display_element.html('');
var trial_data = {
"view_history": JSON.stringify(view_history),
"rt": (new Date()).getTime() - start_time
};
jsPsych.finishTrial(trial_data);
}
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({
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();
}
}
if (info.key === trial.key_forward || info.key === jsPsych.pluginAPI.convertKeyCharacterToKeyCode(trial.key_forward)) {
next();
}
};
return plugin;
})();
})(jQuery);
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
});
}
};
return plugin;
})();

View File

@ -8,101 +8,90 @@
*
*/
(function($) {
jsPsych['survey-text'] = (function() {
var plugin = {};
jsPsych['survey-text'] = (function() {
plugin.create = function(params) {
var plugin = {};
//params = jsPsych.pluginAPI.enforceArray(params, ['data']);
plugin.trial = function(display_element, trial) {
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],
rows: typeof params.rows == 'undefined' ? rows : params.rows[i],
columns: typeof params.columns == 'undefined' ? cols : params.columns[i]
});
}
return trials;
};
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);
// show preamble text
display_element.append($('<div>', {
"id": 'jspsych-survey-text-preamble',
"class": 'jspsych-survey-text-preamble'
}));
$('#jspsych-survey-text-preamble').html(trial.preamble);
// add questions
trial.preamble = typeof trial.preamble == 'undefined' ? "" : trial.preamble;
if (typeof trial.rows == 'undefined') {
trial.rows = [];
for (var i = 0; i < trial.questions.length; i++) {
// create div
display_element.append($('<div>', {
"id": 'jspsych-survey-text-' + i,
"class": 'jspsych-survey-text-question'
}));
// add question text
$("#jspsych-survey-text-" + i).append('<p class="jspsych-survey-text">' + trial.questions[i] + '</p>');
// add text box
$("#jspsych-survey-text-" + i).append('<textarea name="#jspsych-survey-text-response-' + i + '" cols="'+trial.columns[i]+'" rows="'+trial.rows[i]+'"></textarea>');
trial.rows.push(1);
}
}
if (typeof trial.columns == 'undefined') {
trial.columns = [];
for (var i = 0; i < trial.questions.length; i++) {
trial.columns.push(40);
}
}
// add submit button
display_element.append($('<button>', {
'id': 'jspsych-survey-text-next',
'class': 'jspsych-survey-text'
// if any trial variables are functions
// this evaluates the function and replaces
// it with the output of the function
trial = jsPsych.pluginAPI.evaluateFunctionParameters(trial);
// show preamble text
display_element.append($('<div>', {
"id": 'jspsych-survey-text-preamble',
"class": 'jspsych-survey-text-preamble'
}));
$('#jspsych-survey-text-preamble').html(trial.preamble);
// add questions
for (var i = 0; i < trial.questions.length; i++) {
// create div
display_element.append($('<div>', {
"id": 'jspsych-survey-text-' + i,
"class": 'jspsych-survey-text-question'
}));
$("#jspsych-survey-text-next").html('Submit Answers');
$("#jspsych-survey-text-next").click(function() {
// measure response time
var endTime = (new Date()).getTime();
var response_time = endTime - startTime;
// create object to hold responses
var question_data = {};
$("div.jspsych-survey-text-question").each(function(index) {
var id = "Q" + index;
var val = $(this).children('textarea').val();
var obje = {};
obje[id] = val;
$.extend(question_data, obje);
});
// add question text
$("#jspsych-survey-text-" + i).append('<p class="jspsych-survey-text">' + trial.questions[i] + '</p>');
// save data
jsPsych.data.write({
"rt": response_time,
"responses": JSON.stringify(question_data)
});
// add text box
$("#jspsych-survey-text-" + i).append('<textarea name="#jspsych-survey-text-response-' + i + '" cols="' + trial.columns[i] + '" rows="' + trial.rows[i] + '"></textarea>');
}
display_element.html('');
// add submit button
display_element.append($('<button>', {
'id': 'jspsych-survey-text-next',
'class': 'jspsych-survey-text'
}));
$("#jspsych-survey-text-next").html('Submit Answers');
$("#jspsych-survey-text-next").click(function() {
// measure response time
var endTime = (new Date()).getTime();
var response_time = endTime - startTime;
// next trial
jsPsych.finishTrial();
// create object to hold responses
var question_data = {};
$("div.jspsych-survey-text-question").each(function(index) {
var id = "Q" + index;
var val = $(this).children('textarea').val();
var obje = {};
obje[id] = val;
$.extend(question_data, obje);
});
var startTime = (new Date()).getTime();
};
// save data
var trialdata = {
"rt": response_time,
"responses": JSON.stringify(question_data)
};
return plugin;
})();
})(jQuery);
display_element.html('');
// next trial
jsPsych.finishTrial(trialdata);
});
var startTime = (new Date()).getTime();
};
return plugin;
})();

View File

@ -9,76 +9,63 @@
*
*/
(function($) {
jsPsych.text = (function() {
jsPsych.text = (function() {
var plugin = {};
var plugin = {};
plugin.create = function(params) {
plugin.trial = function(display_element, trial) {
params = jsPsych.pluginAPI.enforceArray(params, ['text','cont_key']);
trial.cont_key = trial.cont_key || [];
var trials = new Array(params.text.length);
for (var i = 0; i < trials.length; i++) {
trials[i] = {};
trials[i].text = params.text[i]; // text of all trials
trials[i].cont_key = params.cont_key || []; // keycode to press to advance screen, default is all keys.
}
return trials;
};
// if any trial variables are functions
// this evaluates the function and replaces
// it with the output of the function
trial = jsPsych.pluginAPI.evaluateFunctionParameters(trial);
plugin.trial = function(display_element, trial) {
// set the HTML of the display target to replaced_text.
display_element.html(trial.text);
// 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 after_response = function(info) {
// set the HTML of the display target to replaced_text.
display_element.html(trial.text);
display_element.html(''); // clear the display
var after_response = function(info) {
var trialdata = {
"rt": info.rt,
"key_press": info.key
}
display_element.html(''); // clear the display
jsPsych.finishTrial(trialdata);
save_data(info.key, info.rt);
};
jsPsych.finishTrial();
var mouse_listener = function(e) {
};
var rt = (new Date()).getTime() - start_time;
var mouse_listener = function(e) {
display_element.unbind('click', mouse_listener);
var rt = (new Date()).getTime() - start_time;
after_response({
key: 'mouse',
rt: rt
});
display_element.unbind('click', mouse_listener);
};
after_response({key: 'mouse', rt: rt});
// check if key is 'mouse'
if (trial.cont_key == 'mouse') {
display_element.click(mouse_listener);
var start_time = (new Date()).getTime();
} else {
jsPsych.pluginAPI.getKeyboardResponse({
callback_function: after_response,
valid_responses: trial.cont_key,
rt_method: 'date',
persist: false,
allow_held_key: false
});
}
};
};
// check if key is 'mouse'
if (trial.cont_key == 'mouse') {
display_element.click(mouse_listener);
var start_time = (new Date()).getTime();
} else {
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) {
jsPsych.data.write({
"rt": rt,
"key_press": key
});
}
};
return plugin;
})();
})(jQuery);
return plugin;
})();

View File

@ -1,65 +1,32 @@
/**
* Josh de Leeuw
* November 2013
*
* This is a basic template for a jsPsych plugin. Use it to start creating your
* own plugin. There is more information about how to create a plugin on the
* jsPsych wiki (https://github.com/jodeleeuw/jsPsych/wiki/Create-a-Plugin).
*
*
/*
* Example plugin template
*/
(function( $ ) {
jsPsych["PLUGIN-NAME"] = (function(){
var plugin = {};
plugin.create = function(params) {
var trials = new Array(NUMBER_OF_TRIALS);
for(var i = 0; i < NUMBER_OF_TRIALS; i++)
{
trials[i] = {};
trials[i].type = "PLUGIN-NAME";
// other information needed for the trial method can be added here
// supporting the generic data object with the following line
// is always a good idea. it allows people to pass in the data
// parameter, but if they don't it gracefully adds an empty object
// in it's place.
trials[i].data = (typeof params.data === 'undefined') ? {} : params.data[i];
}
return trials;
};
plugin.trial = function(display_element, trial) {
// set default values for parameters
trial.parameter = trial.parameter || 'default value';
plugin.trial = function(display_element, block, trial, part) {
// code for running the trial goes here
// allow variables as functions
// this allows any trial variable to be specified as a function
// that will be evaluated when the trial runs. this allows users
// to dynamically adjust the contents of a trial as a result
// of other trials, among other uses. you can leave this out,
// but in general it should be included
trial = jsPsych.evaluateFunctionParameters(trial);
trial = jsPsych.evaluateFunctionParameters(trial);
// data saving
// this is technically optional, but virtually every plugin will
// need to do it. it is good practice to include the type and
// trial_index fields for all plugins.
var trial_data = {
type: trial.type,
trial_index: block.trial_idx,
// other values to save go here
parameter_name: 'parameter value'
};
// this line merges together the trial_data object and the generic
// data object (trial.data), and then stores them.
block.writeData($.extend({}, trial_data, trial.data));
// this method must be called at the end of the trial
block.next();
// end trial
jsPsych.finishTrial(trial_data);
};
return plugin;
})();
}) (jQuery);