mirror of
https://github.com/jspsych/jsPsych.git
synced 2025-05-12 08:38:11 +00:00
removing dev folder from master branch. see branch plugin-dev-old for recovery.
This commit is contained in:
parent
ab6c105dd1
commit
3f25eac294
@ -1,174 +0,0 @@
|
||||
(function( $ ) {
|
||||
jsPsych.active_match = (function(){
|
||||
|
||||
var plugin = {};
|
||||
|
||||
plugin.create = function(params) {
|
||||
stims = params["stimuli"];
|
||||
trials = new Array(stims.length);
|
||||
for(var i = 0; i < trials.length; i++)
|
||||
{
|
||||
trials[i] = {};
|
||||
trials[i]["type"] = "active_match";
|
||||
trials[i]["target_idx"] = params["target_idx"][i];
|
||||
trials[i]["start_idx"] = params["start_idx"][i];
|
||||
trials[i]["stimuli"] = params["stimuli"][i];
|
||||
trials[i]["timing"] = params["timing"];
|
||||
trials[i]["key_dec"] = params["key_dec"];
|
||||
trials[i]["key_inc"] = params["key_inc"];
|
||||
if(params["prompt"] != undefined){
|
||||
trials[i]["prompt"] = params["prompt"];
|
||||
}
|
||||
if(params["data"]!=undefined){
|
||||
trials[i]["data"] = params["data"][i];
|
||||
}
|
||||
}
|
||||
return trials;
|
||||
}
|
||||
|
||||
// data to keep track of
|
||||
var responses = [];
|
||||
var last_response_time = 0;
|
||||
var start_time = 0;
|
||||
var direction_changes = 0;
|
||||
var last_response = -1;
|
||||
|
||||
plugin.trial = function(display_element, block, trial, part)
|
||||
{
|
||||
switch(part){
|
||||
case 1:
|
||||
// reset response variables
|
||||
responses = [];
|
||||
last_response_time = 0;
|
||||
start_time = 0;
|
||||
direction_changes = 0;
|
||||
last_response = -1;
|
||||
|
||||
// starting new trial
|
||||
start_time = (new Date()).getTime();
|
||||
last_response_time = start_time;
|
||||
|
||||
current_idx = trial.start_idx;
|
||||
|
||||
// show target image
|
||||
display_element.append($('<img>', {
|
||||
"src": trial.stimuli[trial.target_idx],
|
||||
"class": '',
|
||||
"id": 'am_target'
|
||||
}));
|
||||
|
||||
// show manipulate image
|
||||
display_element.append($('<img>', {
|
||||
"src": trial.stimuli[trial.start_idx],
|
||||
"class": '',
|
||||
"id": 'am_manipulate'
|
||||
}));
|
||||
|
||||
// append a div for showing messages
|
||||
display_element.append($('<div>', {
|
||||
"id": 'am_message_box'
|
||||
}));
|
||||
|
||||
if(trial.prompt)
|
||||
{
|
||||
display_element.append(trial.prompt);
|
||||
}
|
||||
|
||||
// add function on keypress to control manipulate image
|
||||
// pressing key_dec will move the index down
|
||||
// pressing key_inc will move the index up
|
||||
|
||||
var resp_func = function(e) {
|
||||
var change = 0;
|
||||
var valid_response = false;
|
||||
if(e.which == trial.key_dec)
|
||||
{
|
||||
change = -1;
|
||||
valid_response = true;
|
||||
} else if (e.which == trial.key_inc)
|
||||
{
|
||||
change = 1;
|
||||
valid_response = true;
|
||||
}
|
||||
|
||||
if(valid_response){
|
||||
var resp_time = (new Date()).getTime();
|
||||
var response = {"key": e.which, "rt": (resp_time-last_response_time)};
|
||||
responses.push(response);
|
||||
|
||||
if(e.which != last_response && last_response != -1)
|
||||
{
|
||||
direction_changes++;
|
||||
}
|
||||
|
||||
last_response = e.which;
|
||||
last_response_time = resp_time;
|
||||
|
||||
var next_idx = current_idx + change;
|
||||
if(next_idx < 0) {
|
||||
// can't do this
|
||||
if($('#am_message_box').children().length == 0)
|
||||
{
|
||||
$('#am_message_box').append("<p id='prompt'>Minimum value reached. Go the other direction.</p>");
|
||||
}
|
||||
next_idx = 0;
|
||||
} else if(next_idx == trial.stimuli.length) {
|
||||
// can't do this
|
||||
if($('#am_message_box').children().length == 0)
|
||||
{
|
||||
$('#am_message_box').append("<p id='prompt'>Maximum value reached. Go the other direction.</p>");
|
||||
}
|
||||
next_idx = current_idx;
|
||||
} else {
|
||||
// update current_idx
|
||||
current_idx = next_idx;
|
||||
|
||||
$("#am_message_box").html('');
|
||||
|
||||
// change the image
|
||||
$("#am_manipulate").attr("src",trial.stimuli[current_idx]);
|
||||
}
|
||||
|
||||
if(current_idx == trial.target_idx)
|
||||
{
|
||||
// unbind response function to prevent further change
|
||||
$(document).unbind('keyup',resp_func);
|
||||
// match!
|
||||
plugin.trial(display_element, block, trial, part + 1);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(document).keyup(resp_func);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
$("#am_target").addClass('matched');
|
||||
$("#am_manipulate").addClass('matched');
|
||||
|
||||
var key_responses_string = "";
|
||||
var rt_responses_string = "";
|
||||
for(var i=0;i<responses.length; i++)
|
||||
{
|
||||
key_responses_string = key_responses_string + responses[i].key +",";
|
||||
rt_responses_string = rt_responses_string + responses[i].rt +",";
|
||||
}
|
||||
|
||||
|
||||
var trial_data = {"key_responses": key_responses_string, "rt_responses": rt_responses_string, "num_responses": responses.length, "direction_changes": direction_changes, "start_idx":trial.start_idx, "target_idx": trial.target_idx};
|
||||
block.data[block.trial_idx] = $.extend({},trial_data,trial.data);
|
||||
|
||||
setTimeout(function(){plugin.trial(display_element, block, trial, part + 1);}, trial.timing[1]);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
display_element.html('');
|
||||
setTimeout(function(){block.next();}, trial.timing[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return plugin;
|
||||
})();
|
||||
})(jQuery);
|
@ -1,355 +0,0 @@
|
||||
/* jspsych-adaptive-category-train.js
|
||||
* Josh de Leeuw, Nov. 2012
|
||||
*
|
||||
* Train subjects on a category task adaptively.
|
||||
* Stimuli are presented in blocks, and after a particular stimulus has been identified correctly in X
|
||||
* consecutive blocks, it is removed from the training list. Training ends after all stimuli have been
|
||||
* correctly identified in X consecutive blocks.
|
||||
*
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
jsPsych.adaptive_category_train = (function() {
|
||||
|
||||
var plugin = {};
|
||||
|
||||
plugin.create = function(params) {
|
||||
trials = []; // everything is a single trial, since it is unknown how many presentations it will take.
|
||||
|
||||
trials[0] = {};
|
||||
trials[0].type = "adaptive_category_train";
|
||||
trials[0].items = params["items"]; // array of all the stimuli to learn
|
||||
trials[0].correct_key = params["correct_key"]; // array of all the correct key responses
|
||||
trials[0].text_answer = params["text_answer"]; // the labels of the category members
|
||||
trials[0].choices = params["choices"]; // valid key responses
|
||||
trials[0].correct_text = params["correct_text"]; // feedback text for correct answers.
|
||||
trials[0].incorrect_text = params["incorrect_text"]; // feedback text for incorrect answers
|
||||
trials[0].consecutive_correct_min = params["consecutive_correct_min"]; // how many times they have to get the correct answer in a row for a stim.
|
||||
trials[0].min_percent_correct = params["min_percent_correct"] || 60; // percent correct needed to have adaptive training kick in
|
||||
trials[0].min_items_per_block = params["min_items_per_block"] || 5; // when remaining items is less than this #, completed items are added back in.
|
||||
trials[0].stop_training_criteria = params["stop_training_criteria"] || -1; // after this number of rounds below min_percent_correct, stop training. -1 = continue indefinitely.
|
||||
// timing
|
||||
trials[0].timing_display_feedback = params["timing_display_feedback"] || 1500; // default 1000ms
|
||||
trials[0].timing_post_trial = params["timing_post_trial"] || 1000; // default 1000ms between trials.
|
||||
// display progress ?
|
||||
trials[0].show_progress = params["show_progress"] || true;
|
||||
|
||||
// optional parameters
|
||||
if(params["data"]!=undefined){
|
||||
trials[0].data = params["data"];
|
||||
}
|
||||
if(params["prompt"]!=undefined){
|
||||
trials[0].prompt = params["prompt"];
|
||||
}
|
||||
|
||||
return trials;
|
||||
}
|
||||
|
||||
plugin.trial = function(display_element, block, trial, part)
|
||||
{
|
||||
// create a tally for each item
|
||||
var all_items = [];
|
||||
for(var i=0; i<trial.items.length; i++)
|
||||
{
|
||||
all_items.push({
|
||||
"a_path": trial.items[i],
|
||||
"consecutive_correct_responses": 0,
|
||||
"correct_key": trial.correct_key[i],
|
||||
"text_answer": trial.text_answer[i],
|
||||
"choices":trial.choices,
|
||||
"correct_text": trial.correct_text,
|
||||
"incorrect_text": trial.incorrect_text,
|
||||
"min_percent_correct": trial.min_percent_correct,
|
||||
"timing_post_trial": trial.timing_post_trial,
|
||||
"timing_display_feedback": trial.timing_display_feedback,
|
||||
"prompt": trial.prompt,
|
||||
"complete": false
|
||||
});
|
||||
};
|
||||
|
||||
// create the training controller
|
||||
var controller = new TrainingControl(all_items, trial.consecutive_correct_min, trial.min_items_per_block,
|
||||
trial.min_percent_correct, display_element, block, trial.show_progress, trial.timing_post_trial,
|
||||
trial.stop_training_criteria);
|
||||
controller.next_round(); // when this finishes, block.next() is called.
|
||||
}
|
||||
|
||||
function TrainingControl(items, min_correct, min_per_block, min_percent_correct, display_element, block, show_progress, timing_post_trial, stop_criteria){
|
||||
|
||||
this.total_items = items.length;
|
||||
this.remaining_items = items;
|
||||
this.timing_post_trial = timing_post_trial;
|
||||
this.complete_items = [];
|
||||
this.curr_block = 0;
|
||||
this.blocks_under_thresh = 0;
|
||||
|
||||
this.next_round = function() {
|
||||
|
||||
if(stop_criteria > -1 && this.blocks_under_thresh >=stop_criteria)
|
||||
{
|
||||
// end training due to failure to learn
|
||||
|
||||
block.next();
|
||||
} else {
|
||||
if(this.remaining_items.length > 0)
|
||||
{
|
||||
if(this.remaining_items.length < min_per_block)
|
||||
{
|
||||
shuffle(this.complete_items);
|
||||
for( var i = 0; this.remaining_items.length < min_per_block; i++)
|
||||
{
|
||||
this.remaining_items.push(this.complete_items[i]);
|
||||
}
|
||||
}
|
||||
// present remaining items in random order
|
||||
shuffle(this.remaining_items);
|
||||
var iterator = new TrialIterator(display_element, this.remaining_items, this, block, this.curr_block);
|
||||
this.curr_block++;
|
||||
var updated_trials = iterator.next(); // when this finishes, all trials are complete.
|
||||
// updated_trials will have the updated consecutive correct responses
|
||||
|
||||
} else {
|
||||
// end training
|
||||
block.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.round_complete = function(trials)
|
||||
{
|
||||
// check items for threshold and remove items where consecutive responses has been reached
|
||||
var cont_trials = [];
|
||||
|
||||
this.remaining_items = trials;
|
||||
var score_denominator = this.remaining_items.length;
|
||||
var score_numerator = 0;
|
||||
|
||||
|
||||
for(var i=0; i<this.remaining_items.length; i++)
|
||||
{
|
||||
if(this.remaining_items[i].consecutive_correct_responses > 0)
|
||||
{
|
||||
score_numerator++;
|
||||
}
|
||||
}
|
||||
|
||||
var percent_correct = Math.round((score_numerator / score_denominator)*100);
|
||||
|
||||
if(percent_correct < min_percent_correct){
|
||||
this.blocks_under_thresh++;
|
||||
} else {
|
||||
this.blocks_under_thresh = 0;
|
||||
}
|
||||
|
||||
for(var i=0; i<this.remaining_items.length; i++)
|
||||
{
|
||||
if(this.remaining_items[i].complete == false)
|
||||
{
|
||||
if(this.remaining_items[i].consecutive_correct_responses < min_correct)
|
||||
{
|
||||
cont_trials.push(this.remaining_items[i]);
|
||||
} else {
|
||||
if(percent_correct>=min_percent_correct){
|
||||
// newly completed item
|
||||
this.remaining_items[i].complete = true;
|
||||
this.complete_items.push(this.remaining_items[i]);
|
||||
} else {
|
||||
cont_trials.push(this.remaining_items[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.remaining_items = cont_trials;
|
||||
|
||||
var remaining_objects = this.remaining_items.length;
|
||||
var completed_objects = this.total_items - remaining_objects;
|
||||
|
||||
|
||||
if(show_progress)
|
||||
{
|
||||
this.display_progress(completed_objects, remaining_objects, score_numerator, score_denominator);
|
||||
} else {
|
||||
// call next round
|
||||
this.next_round();
|
||||
}
|
||||
}
|
||||
|
||||
this.display_progress = function(completed_objects, remaining_objects, score_numerator, score_denominator, blocks_under_criteria)
|
||||
{
|
||||
var completed = '';
|
||||
|
||||
var percent_correct = Math.round((score_numerator / score_denominator)*100);
|
||||
|
||||
if(percent_correct < min_percent_correct)
|
||||
{
|
||||
completed = '<p>You need to categorize at least '+min_percent_correct+'% of the items correctly in each round in order to make progress in training.</p>'
|
||||
if(stop_criteria > -1) {
|
||||
var remaining_blocks = stop_criteria - this.blocks_under_thresh;
|
||||
if(remaining_blocks >= 1){
|
||||
completed += '<p>If you continue to have an accuracy below '+min_percent_correct+'% for '+remaining_blocks+' more round(s) of training, then training will stop and you will not be eligible for the bonus payment.</p>'
|
||||
} else {
|
||||
completed += '<p>Training will now stop because your accuracy was below '+min_percent_correct+'% for '+stop_criteria+' consecutive rounds.</p>'
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if(remaining_objects == 0)
|
||||
{
|
||||
completed = '<p>Congratulations! You have completed training.</p>';
|
||||
}
|
||||
else if(completed_objects > 0)
|
||||
{
|
||||
completed = '<p>You have correctly categorized '+completed_objects+' item(s) in '+min_correct+' consecutive rounds. You need to correctly categorize '+remaining_objects+
|
||||
' more item(s) in '+min_correct+' consecutive rounds to complete training. Items that you have correctly identified in '+min_correct+' consecutive rounds will not be shown as frequently.</p>';
|
||||
}
|
||||
else
|
||||
{
|
||||
completed = '<p>Good job! You need to categorize an item correctly in '+min_correct+' consecutive rounds to finish training for that item. Once you have finished training for all items the next part of the experiment will begin.</p>';
|
||||
}
|
||||
}
|
||||
|
||||
display_element.html(
|
||||
'<div id="adaptive_category_progress"><p>You correctly categorized '+percent_correct+'% of the items in that round.</p>'+completed+'<p>Press ENTER to continue.</p></div>'
|
||||
);
|
||||
|
||||
var controller = this;
|
||||
|
||||
var key_listener = function(e) {
|
||||
if(e.which=='13')
|
||||
{
|
||||
$(document).unbind('keyup',key_listener); // remove the response function, so that it doesn't get triggered again.
|
||||
display_element.html(''); // clear the display
|
||||
setTimeout(function(){controller.next_round();}, this.timing_post_trial); // call block.next() to advance the experiment after a delay.
|
||||
}
|
||||
}
|
||||
$(document).keyup(key_listener);
|
||||
}
|
||||
}
|
||||
|
||||
function TrialIterator(display_element, trials, controller, block, block_idx){
|
||||
this.trials = trials;
|
||||
this.curr_trial = 0;
|
||||
this.curr_block = block_idx;
|
||||
|
||||
this.next = function() {
|
||||
if(this.curr_trial >= this.trials.length)
|
||||
{
|
||||
// call function in the controller
|
||||
controller.round_complete(trials);
|
||||
} else {
|
||||
this.do_trial(this.trials[this.curr_trial], this.curr_trial, this.curr_block);
|
||||
}
|
||||
}
|
||||
|
||||
this.do_trial = function(trial, t_idx, b_idx)
|
||||
{
|
||||
// do the trial!
|
||||
|
||||
// show the image
|
||||
display_element.append($('<img>', {
|
||||
"src": trial.a_path,
|
||||
"class": 'cf'
|
||||
}));
|
||||
|
||||
display_element.append(trial.prompt);
|
||||
|
||||
startTime = (new Date()).getTime();
|
||||
|
||||
// get response
|
||||
var resp_func = function(e) {
|
||||
var flag = false;
|
||||
var correct = false;
|
||||
if(e.which==trial.correct_key) // correct category
|
||||
{
|
||||
flag = true;
|
||||
correct = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// check if the key is any of the options, or if it is an accidental keystroke
|
||||
for(var i=0;i<trial.choices.length;i++)
|
||||
{
|
||||
if(e.which==trial.choices[i])
|
||||
{
|
||||
flag = true;
|
||||
correct = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(flag)
|
||||
{
|
||||
// get response time
|
||||
endTime = (new Date()).getTime();
|
||||
rt = (endTime-startTime);
|
||||
|
||||
// update the consecutive correct responses
|
||||
if(correct){
|
||||
trial.consecutive_correct_responses++;
|
||||
} else {
|
||||
trial.consecutive_correct_responses = 0;
|
||||
}
|
||||
|
||||
|
||||
// store data
|
||||
var trial_data = {"block": b_idx, "trial_idx": t_idx, "rt": rt, "correct": correct, "a_path": trial.a_path, "key_press": e.which, "trial_type":"adaptive_train"}
|
||||
if(trial.data!="undefined"){
|
||||
block.data.push($.extend({},trial_data,trial.data));
|
||||
} else {
|
||||
block.data.push(trial_data);
|
||||
}
|
||||
$(document).unbind('keyup',resp_func);
|
||||
display_element.html('');
|
||||
show_feedback(correct, e.data.iterator_object);
|
||||
}
|
||||
}
|
||||
|
||||
$(document).keyup({"iterator_object":this},resp_func);
|
||||
|
||||
// provide feedback
|
||||
function show_feedback(is_correct, iterator_object){
|
||||
|
||||
display_element.append($('<img>', {
|
||||
"src": trial.a_path,
|
||||
"class": 'cf'
|
||||
}));
|
||||
|
||||
// give feedback
|
||||
var atext = "";
|
||||
if(is_correct)
|
||||
{
|
||||
atext = trial.correct_text.replace("&ANS&", trial.text_answer);
|
||||
} else {
|
||||
atext = trial.incorrect_text.replace("&ANS&", trial.text_answer);
|
||||
}
|
||||
display_element.append(atext);
|
||||
setTimeout(function(){finish_trial(iterator_object);}, trial.timing_display_feedback);
|
||||
}
|
||||
|
||||
function finish_trial(iterator_object){
|
||||
display_element.html('');
|
||||
|
||||
setTimeout(function(){
|
||||
iterator_object.curr_trial++;
|
||||
iterator_object.next();
|
||||
}, trial.timing_post_trial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function shuffle(array) {
|
||||
var tmp, current, top = array.length;
|
||||
|
||||
if(top) while(--top) {
|
||||
current = Math.floor(Math.random() * (top + 1));
|
||||
tmp = array[current];
|
||||
array[current] = array[top];
|
||||
array[top] = tmp;
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
return plugin;
|
||||
})();
|
||||
})(jQuery);
|
@ -1,223 +0,0 @@
|
||||
(function( $ ) {
|
||||
jsPsych.ballistic_match = (function(){
|
||||
|
||||
var plugin = {};
|
||||
|
||||
plugin.create = function(params) {
|
||||
stims = params["stimuli"];
|
||||
trials = new Array(stims.length);
|
||||
for(var i = 0; i < trials.length; i++)
|
||||
{
|
||||
trials[i] = {};
|
||||
trials[i]["type"] = "ballistic_match";
|
||||
trials[i]["target_idx"] = params["target_idx"][i];
|
||||
trials[i]["start_idx"] = params["start_idx"][i];
|
||||
trials[i]["stimuli"] = params["stimuli"][i];
|
||||
trials[i]["timing"] = params["timing"];
|
||||
trials[i]["key_dec"] = params["key_dec"];
|
||||
trials[i]["key_inc"] = params["key_inc"];
|
||||
trials[i]["animate_frame_time"] = params["animate_frame_time"] || 100;
|
||||
if(params["prompt"] != undefined){
|
||||
trials[i]["prompt"] = params["prompt"];
|
||||
}
|
||||
if(params["data"]!=undefined){
|
||||
trials[i]["data"] = params["data"][i];
|
||||
}
|
||||
}
|
||||
return trials;
|
||||
}
|
||||
|
||||
|
||||
var change = 0; // which direction they indicated the stim should move.
|
||||
var start_time;
|
||||
var end_time;
|
||||
|
||||
plugin.trial = function(display_element, block, trial, part)
|
||||
{
|
||||
switch(part){
|
||||
case 1:
|
||||
// starting new trial
|
||||
start_time = (new Date()).getTime();
|
||||
change = 0;
|
||||
|
||||
// show manipulate image
|
||||
display_element.append($('<img>', {
|
||||
"src": trial.stimuli[trial.start_idx],
|
||||
"class": 'bm_img',
|
||||
"id": 'bm_manipulate'
|
||||
}));
|
||||
|
||||
// show target image
|
||||
display_element.append($('<img>', {
|
||||
"src": trial.stimuli[trial.target_idx],
|
||||
"class": 'bm_img',
|
||||
"id": 'bm_target'
|
||||
}));
|
||||
|
||||
if(trial.prompt)
|
||||
{
|
||||
display_element.append(trial.prompt);
|
||||
}
|
||||
|
||||
// categorize the image.
|
||||
|
||||
var resp_func = function(e) {
|
||||
var valid_response = false;
|
||||
if(e.which == trial.key_dec)
|
||||
{
|
||||
change = -1;
|
||||
valid_response = true;
|
||||
} else if (e.which == trial.key_inc)
|
||||
{
|
||||
change = 1;
|
||||
valid_response = true;
|
||||
}
|
||||
|
||||
if(valid_response){
|
||||
end_time = (new Date()).getTime();
|
||||
plugin.trial(display_element,block,trial,part+1);
|
||||
$(document).unbind('keyup', resp_func);
|
||||
}
|
||||
}
|
||||
|
||||
$(document).keyup(resp_func);
|
||||
break;
|
||||
case 2:
|
||||
// clear everything
|
||||
display_element.html('');
|
||||
setTimeout(function(){plugin.trial(display_element, block, trial, part + 1);}, trial.timing[1]);
|
||||
break;
|
||||
case 3:
|
||||
// draw trajectory
|
||||
draw_trajectory(display_element,
|
||||
trial.stimuli[trial.target_idx],
|
||||
trial.stimuli[trial.start_idx],
|
||||
trial.target_idx/(trial.stimuli.length-1),
|
||||
trial.start_idx/(trial.stimuli.length-1));
|
||||
|
||||
display_element.append($('<div>',{
|
||||
"id":"bm_feedback",
|
||||
}));
|
||||
|
||||
if(change>0) {
|
||||
$("#bm_feedback").html('<p>You said increase.</p>');
|
||||
} else {
|
||||
$("#bm_feedback").html('<p>You said decrease.</p>');
|
||||
}
|
||||
|
||||
setTimeout(function(){plugin.trial(display_element, block, trial, part + 1);}, trial.timing[1]*3);
|
||||
break;
|
||||
case 4:
|
||||
var curr_loc = trial.start_idx
|
||||
animate_interval = setInterval(function(){
|
||||
|
||||
// clear everything
|
||||
display_element.html('');
|
||||
// draw trajectory
|
||||
draw_trajectory(display_element,
|
||||
trial.stimuli[trial.target_idx],
|
||||
trial.stimuli[curr_loc],
|
||||
trial.target_idx/(trial.stimuli.length-1),
|
||||
curr_loc/(trial.stimuli.length-1));
|
||||
|
||||
curr_loc += change;
|
||||
|
||||
|
||||
if(curr_loc - change == trial.target_idx || curr_loc < 0 || curr_loc == trial.stimuli.length)
|
||||
{
|
||||
clearInterval(animate_interval);
|
||||
var correct = false;
|
||||
if(change > 0 && trial.start_idx < trial.target_idx) { correct = true; }
|
||||
if(change < 0 && trial.start_idx > trial.target_idx) { correct = true; }
|
||||
|
||||
display_element.append($('<div>',{
|
||||
"id":"bm_feedback",
|
||||
}));
|
||||
if(correct){
|
||||
$("#bm_feedback").html('<p>Correct!</p>');
|
||||
} else {
|
||||
$("#bm_feedback").html('<p>Wrong.</p>');
|
||||
}
|
||||
setTimeout(function(){plugin.trial(display_element, block, trial, part + 1);}, trial.timing[1]*3);
|
||||
}
|
||||
}, trial.animate_frame_time);
|
||||
break;
|
||||
case 5:
|
||||
display_element.html('');
|
||||
var correct = false;
|
||||
if(change > 0 && trial.start_idx < trial.target_idx) { correct = true; }
|
||||
if(change < 0 && trial.start_idx > trial.target_idx) { correct = true; }
|
||||
|
||||
var trial_data = {"start_idx":trial.start_idx, "target_idx": trial.target_idx, "correct": correct, "rt": (end_time-start_time)};
|
||||
block.data[block.trial_idx] = $.extend({},trial_data,trial.data);
|
||||
|
||||
setTimeout(function(){block.next();}, trial.timing[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function draw_trajectory(display_element,target_img, moving_img, target_loc_percent, marker_loc_percent)
|
||||
{
|
||||
// display the image as it morphs
|
||||
display_element.append($('<img>',{
|
||||
"src": moving_img,
|
||||
"id": "moving_image"
|
||||
}));
|
||||
|
||||
// show the linear trajectory below
|
||||
|
||||
display_element.append($('<div>', {
|
||||
"id": "trajectory"}));
|
||||
|
||||
$("#trajectory").append($('<div>', {
|
||||
"id": "line"}));
|
||||
|
||||
// display the images on the trajectory
|
||||
$("#trajectory").append($('<div>', {
|
||||
"id": "target_flag"}));
|
||||
|
||||
$("#target_flag").append($('<div>', {
|
||||
"id": "target_dot"}));
|
||||
|
||||
$("#target_flag").append($('<div>', {
|
||||
"id": "target_words"}));
|
||||
|
||||
$("#target_words").html("<p>Target Cell</p>");
|
||||
|
||||
$("#trajectory").append($('<div>', {
|
||||
"id": "marker_flag"}));
|
||||
|
||||
$("#marker_flag").append($('<div>', {
|
||||
"id": "marker_dot"}));
|
||||
|
||||
$("#marker_flag").append($('<div>', {
|
||||
"id": "marker_words"}));
|
||||
|
||||
$("#marker_words").html("<p>Above Cell</p>");
|
||||
|
||||
// label the trajectory line
|
||||
$("#trajectory").append($('<span>', {
|
||||
"id": "left_label"}));
|
||||
|
||||
$("#trajectory").append($('<span>', {
|
||||
"id": "right_label"}));
|
||||
|
||||
$("#left_label").html("Less Chemical X");
|
||||
$("#right_label").html("More Chemical X");
|
||||
|
||||
// set the location of the flags on the line
|
||||
var dot_width = parseInt($("#marker_dot").css('width'));
|
||||
var line_width = parseInt($("#line").css('width'));
|
||||
|
||||
var target_flag_left = (line_width- dot_width) * target_loc_percent;
|
||||
var marker_flag_left = (line_width- dot_width) * marker_loc_percent;
|
||||
|
||||
$("#marker_flag").css('left', marker_flag_left);
|
||||
$("#target_flag").css('left', target_flag_left);
|
||||
|
||||
|
||||
}
|
||||
|
||||
return plugin;
|
||||
})();
|
||||
})(jQuery);
|
@ -1,227 +0,0 @@
|
||||
(function( $ ) {
|
||||
jsPsych.ballistic_match = (function(){
|
||||
|
||||
var plugin = {};
|
||||
|
||||
plugin.create = function(params) {
|
||||
stims = params["stimuli"];
|
||||
trials = new Array(stims.length);
|
||||
for(var i = 0; i < trials.length; i++)
|
||||
{
|
||||
trials[i] = {};
|
||||
trials[i]["type"] = "ballistic_match";
|
||||
trials[i]["target_idx"] = params["target_idx"][i];
|
||||
trials[i]["start_idx"] = params["start_idx"][i];
|
||||
trials[i]["stimuli"] = params["stimuli"][i];
|
||||
trials[i]["timing"] = params["timing"];
|
||||
trials[i]["key_dec"] = params["key_dec"];
|
||||
trials[i]["key_inc"] = params["key_inc"];
|
||||
trials[i]["animate_frame_time"] = params["animate_frame_time"] || 100;
|
||||
if(params["prompt"] != undefined){
|
||||
trials[i]["prompt"] = params["prompt"];
|
||||
}
|
||||
if(params["data"]!=undefined){
|
||||
trials[i]["data"] = params["data"][i];
|
||||
}
|
||||
}
|
||||
return trials;
|
||||
}
|
||||
|
||||
|
||||
var change = 0; // which direction they indicated the stim should move.
|
||||
var start_time;
|
||||
var end_time;
|
||||
|
||||
plugin.trial = function(display_element, block, trial, part)
|
||||
{
|
||||
switch(part){
|
||||
case 1:
|
||||
// starting new trial
|
||||
start_time = (new Date()).getTime();
|
||||
change = 0;
|
||||
|
||||
// show manipulate image
|
||||
display_element.append($('<img>', {
|
||||
"src": trial.stimuli[trial.start_idx],
|
||||
"class": 'bm_img',
|
||||
"id": 'bm_manipulate'
|
||||
}));
|
||||
|
||||
// show target image
|
||||
display_element.append($('<img>', {
|
||||
"src": trial.stimuli[trial.target_idx],
|
||||
"class": 'bm_img',
|
||||
"id": 'bm_target'
|
||||
}));
|
||||
|
||||
if(trial.prompt)
|
||||
{
|
||||
display_element.append(trial.prompt);
|
||||
}
|
||||
|
||||
// categorize the image.
|
||||
|
||||
var resp_func = function(e) {
|
||||
var valid_response = false;
|
||||
if(e.which == trial.key_dec)
|
||||
{
|
||||
change = -1;
|
||||
valid_response = true;
|
||||
} else if (e.which == trial.key_inc)
|
||||
{
|
||||
change = 1;
|
||||
valid_response = true;
|
||||
}
|
||||
|
||||
if(valid_response){
|
||||
end_time = (new Date()).getTime();
|
||||
plugin.trial(display_element,block,trial,part+1);
|
||||
$(document).unbind('keyup', resp_func);
|
||||
}
|
||||
}
|
||||
|
||||
$(document).keyup(resp_func);
|
||||
break;
|
||||
case 2:
|
||||
// clear everything
|
||||
display_element.html('');
|
||||
setTimeout(function(){plugin.trial(display_element, block, trial, part + 1);}, trial.timing[1]);
|
||||
break;
|
||||
case 3:
|
||||
// draw trajectory
|
||||
draw_trajectory(display_element,
|
||||
trial.stimuli[trial.target_idx],
|
||||
trial.stimuli[trial.start_idx],
|
||||
trial.target_idx/(trial.stimuli.length-1),
|
||||
trial.start_idx/(trial.stimuli.length-1));
|
||||
|
||||
display_element.append($('<div>',{
|
||||
"id":"bm_feedback",
|
||||
}));
|
||||
|
||||
if(change>0) {
|
||||
$("#bm_feedback").html('<p>You said increase.</p>');
|
||||
} else {
|
||||
$("#bm_feedback").html('<p>You said decrease.</p>');
|
||||
}
|
||||
|
||||
setTimeout(function(){plugin.trial(display_element, block, trial, part + 1);}, trial.timing[1]*3);
|
||||
break;
|
||||
case 4:
|
||||
var curr_loc = trial.start_idx
|
||||
animate_interval = setInterval(function(){
|
||||
|
||||
// clear everything
|
||||
display_element.html('');
|
||||
// draw trajectory
|
||||
draw_trajectory(display_element,
|
||||
trial.stimuli[trial.target_idx],
|
||||
trial.stimuli[curr_loc],
|
||||
trial.target_idx/(trial.stimuli.length-1),
|
||||
curr_loc/(trial.stimuli.length-1));
|
||||
|
||||
curr_loc += change;
|
||||
|
||||
|
||||
if(curr_loc - change == trial.target_idx || curr_loc < 0 || curr_loc == trial.stimuli.length)
|
||||
{
|
||||
clearInterval(animate_interval);
|
||||
var correct = false;
|
||||
if(change > 0 && trial.start_idx < trial.target_idx) { correct = true; }
|
||||
if(change < 0 && trial.start_idx > trial.target_idx) { correct = true; }
|
||||
|
||||
display_element.append($('<div>',{
|
||||
"id":"bm_feedback",
|
||||
}));
|
||||
if(correct){
|
||||
$("#bm_feedback").html('<p>Correct!</p>');
|
||||
} else {
|
||||
$("#bm_feedback").html('<p>Wrong.</p>');
|
||||
}
|
||||
setTimeout(function(){plugin.trial(display_element, block, trial, part + 1);}, trial.timing[1]*3);
|
||||
}
|
||||
}, trial.animate_frame_time);
|
||||
break;
|
||||
case 5:
|
||||
display_element.html('');
|
||||
var correct = false;
|
||||
if(change > 0 && trial.start_idx < trial.target_idx) { correct = true; }
|
||||
if(change < 0 && trial.start_idx > trial.target_idx) { correct = true; }
|
||||
|
||||
var trial_data = {"start_idx":trial.start_idx, "target_idx": trial.target_idx, "correct": correct, "rt": (end_time-start_time)};
|
||||
block.data[block.trial_idx] = $.extend({},trial_data,trial.data);
|
||||
|
||||
setTimeout(function(){block.next();}, trial.timing[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function draw_trajectory(display_element,target_img, moving_img, target_loc_percent, moving_loc_percent)
|
||||
{
|
||||
display_element.append($('<div>', {
|
||||
"id": "message_holder"}));
|
||||
$("#message_holder").append($('<p id="left">Less Chemical X</p>'));
|
||||
$("#message_holder").append($('<p id="right">More Chemical X</p>'));
|
||||
|
||||
$("#message_holder").append($('<img>',{
|
||||
"src":"img/400arrow.gif",
|
||||
"id":"arrow"
|
||||
}));
|
||||
// display the images on the trajectory
|
||||
display_element.append($('<div>',{
|
||||
"id": "bm_trajectory",
|
||||
"css": {
|
||||
"position":"relative"
|
||||
}
|
||||
}));
|
||||
|
||||
$("#bm_trajectory").append($('<img>',{
|
||||
"src":target_img,
|
||||
"id": "bm_target",
|
||||
"css": {
|
||||
"position":"absolute",
|
||||
}
|
||||
}));
|
||||
|
||||
var image_width = parseInt($("#bm_target").css('width'));
|
||||
var image_height = parseInt($("#bm_target").css('height'));
|
||||
var container_width = parseInt($("#bm_trajectory").css('width'));
|
||||
var target_left = (container_width - image_width) * target_loc_percent;
|
||||
var moving_left = (container_width - image_width) * moving_loc_percent;
|
||||
|
||||
$("#bm_target").css('left', target_left);
|
||||
$("#bm_target").css('top', image_height);
|
||||
|
||||
$("#bm_trajectory").append($('<img>',{
|
||||
"src":moving_img,
|
||||
"id": "bm_moving",
|
||||
"css": {
|
||||
"position":"absolute",
|
||||
"left": moving_left,
|
||||
"top": 0
|
||||
}
|
||||
}));
|
||||
|
||||
$("#bm_trajectory").append($(
|
||||
'<div>',
|
||||
{
|
||||
"id": "target_flag",
|
||||
"css": {
|
||||
"position":"absolute",
|
||||
"left": target_left+(image_width/2)-40,
|
||||
"bottom": "-10px",
|
||||
"background-color": "#cccccc",
|
||||
"border": "1px solid #999999",
|
||||
"width": 80,
|
||||
"height": 20
|
||||
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
$("#target_flag").html('<p>TARGET</p>');
|
||||
}
|
||||
|
||||
return plugin;
|
||||
})();
|
||||
})(jQuery);
|
@ -1,182 +0,0 @@
|
||||
// timing parameters: [length to show feedback, intertrial gap, optional length to display target]
|
||||
// if optional length to display target is missing, then target is displayed until subject responds.
|
||||
|
||||
//TODO
|
||||
// option to keep stim on screen during feedback
|
||||
// way to provide corrective feedback
|
||||
|
||||
(function( $ ) {
|
||||
jsPsych.categorize_multi = (function(){
|
||||
|
||||
var plugin = {};
|
||||
|
||||
plugin.create = function(params) {
|
||||
cf_stims = params["stimuli"];
|
||||
trials = new Array(cf_stims.length);
|
||||
for(var i = 0; i < trials.length; i++)
|
||||
{
|
||||
trials[i] = {};
|
||||
trials[i]["type"] = "categorize_multi";
|
||||
trials[i]["a_path"] = cf_stims[i];
|
||||
trials[i]["choices"] = params["choices"];
|
||||
trials[i]["answer_idx"] = params["answer_idx"][i];
|
||||
trials[i]["text_answer"] = params["text_answer"][i];
|
||||
trials[i]["correct_text"] = params["correct_text"];
|
||||
trials[i]["incorrect_text"] = params["incorrect_text"];
|
||||
trials[i]["show_stim_feedback"] = params["show_stim_feedback"] || true;
|
||||
// timing params
|
||||
trials[i]["timing_length_of_feedback"] = params["timing_length_of_feedback"] || 2000;
|
||||
// opt params
|
||||
if(params["prompt"] != undefined){
|
||||
trials[i]["prompt"] = params["prompt"];
|
||||
}
|
||||
if(params["data"]!=undefined){
|
||||
trials[i]["data"] = params["data"][i];
|
||||
}
|
||||
}
|
||||
return trials;
|
||||
}
|
||||
|
||||
// to save correct_answers between iterations of trial method...
|
||||
var correct_answers = [];
|
||||
|
||||
plugin.trial = function(display_element, block, trial, part)
|
||||
{
|
||||
switch(part){
|
||||
case 1:
|
||||
// show image
|
||||
display_element.append($('<img>', {
|
||||
"src": trial.a_path,
|
||||
"class": 'cm'
|
||||
}));
|
||||
|
||||
// hide image if the timing param is set.
|
||||
if(trial.timing_show_image > 0)
|
||||
{
|
||||
setTimeout(function(){
|
||||
$('.cm').css('visibility', 'hidden');
|
||||
}, trial.timing_show_image);
|
||||
}
|
||||
|
||||
// show prompt
|
||||
display_element.append(trial.prompt);
|
||||
|
||||
|
||||
// start recording for RT
|
||||
startTime = (new Date()).getTime();
|
||||
|
||||
// display button choices
|
||||
// for each SET of choices
|
||||
for(var i = 0; i<trial.choices.length; i++)
|
||||
{
|
||||
// add a DIV
|
||||
display_element.append($('<div>', {
|
||||
"id": "cm_"+i
|
||||
}));
|
||||
// for each INDIVIDUAL choice
|
||||
for(var j = 0; j < trial.choices[i].length; j++)
|
||||
{
|
||||
// add a RADIO button
|
||||
$('#cm_'+i).append($('<input>', {
|
||||
"type": "radio",
|
||||
"name": "category_"+i,
|
||||
"value": trial.choices[i][j],
|
||||
"id": "cat_"+i+"_"+j
|
||||
}));
|
||||
|
||||
$('#cm_'+i).append('<label>'+trial.choices[i][j]+'</label>');
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// add a button to hit when done.
|
||||
display_element.append($('<button>', {
|
||||
"type": "button",
|
||||
"value": "done",
|
||||
"name": "Next",
|
||||
"id": "nextBtn",
|
||||
"html": "Submit Answer"
|
||||
}));
|
||||
|
||||
// add response function to the button.
|
||||
$('#nextBtn').click(function(){
|
||||
|
||||
var correct_overall = true;
|
||||
var string_answers = "";
|
||||
correct_answers = [];
|
||||
|
||||
for(var i=0; i<trial.answer_idx.length; i++)
|
||||
{
|
||||
var corr_choice = trial.answer_idx[i];
|
||||
if($('#cat_'+i+'_'+corr_choice).is(':checked'))
|
||||
{
|
||||
correct_answers.push(true);
|
||||
string_answers = string_answers + "1";
|
||||
} else {
|
||||
correct_answers.push(false);
|
||||
correct_overall = false;
|
||||
string_answers = string_answers + "0";
|
||||
}
|
||||
}
|
||||
|
||||
// measure RT
|
||||
endTime = (new Date()).getTime();
|
||||
rt = (endTime-startTime);
|
||||
|
||||
// save data
|
||||
var trial_data = {"rt": rt, "correct": correct_overall, "a_path": trial.a_path, "cat_answers": string_answers}
|
||||
block.data[block.trial_idx] = $.extend({},trial_data,trial.data);
|
||||
|
||||
// clear everything
|
||||
display_element.html('');
|
||||
|
||||
plugin.trial(display_element, block, trial, part + 1);
|
||||
|
||||
});
|
||||
break;
|
||||
case 2:
|
||||
// show image
|
||||
display_element.append($('<img>', {
|
||||
"src": trial.a_path,
|
||||
"class": 'cm'
|
||||
}));
|
||||
|
||||
// show prompt
|
||||
display_element.append(trial.prompt);
|
||||
|
||||
// give feedback
|
||||
var atext = "";
|
||||
for(var i=0; i<correct_answers.length; i++)
|
||||
{
|
||||
// add a DIV
|
||||
display_element.append($('<div>', {
|
||||
"id": "cm_"+i
|
||||
}));
|
||||
|
||||
var text_to_add = "";
|
||||
if(correct_answers[i])
|
||||
{
|
||||
text_to_add = trial.correct_text.replace("&ANS&", trial.text_answer[i]);
|
||||
$('#cm_'+i).addClass('correct');
|
||||
} else {
|
||||
text_to_add = trial.incorrect_text.replace("&ANS&", trial.text_answer[i]);
|
||||
$('#cm_'+i).addClass('incorrect');
|
||||
}
|
||||
|
||||
|
||||
|
||||
$('#cm_'+i).append(text_to_add);
|
||||
}
|
||||
setTimeout(function(){plugin.trial(display_element, block, trial, part + 1);}, trial.timing_length_of_feedback); // fix timing?
|
||||
break;
|
||||
case 3:
|
||||
display_element.html('');
|
||||
setTimeout(function(){block.next()},1000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return plugin;
|
||||
})();
|
||||
})(jQuery);
|
||||
|
@ -1,186 +0,0 @@
|
||||
(function( $ ) {
|
||||
jsPsych.paint = (function(){
|
||||
|
||||
var plugin = {};
|
||||
|
||||
// private functions
|
||||
function colorPixel(ctx, x, y, fresh)
|
||||
{
|
||||
ctx.globalCompositeOperation = "destination-out";
|
||||
ctx.fillStyle = "rgba(0,0,0, 1.0)";
|
||||
//ctx.fillRect(x,y,10,10);
|
||||
//ctx.arc(x,y,10,0,Math.Pi*2,true);
|
||||
//ctx.fill();
|
||||
|
||||
ctx.lineWidth = 30;
|
||||
ctx.lineCap = ctx.lineJoin = 'round';
|
||||
ctx.strokeStyle = "rgba(0,0,0,1.0)";
|
||||
|
||||
if(fresh){
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x+0.01,y);
|
||||
}
|
||||
ctx.lineTo(x,y);
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
|
||||
plugin.create = function(params) {
|
||||
stims = params["stimuli"];
|
||||
trials = new Array(stims.length);
|
||||
for(var i = 0; i < trials.length; i++)
|
||||
{
|
||||
trials[i] = {};
|
||||
trials[i]["type"] = "paint";
|
||||
trials[i]["a_path"] = stims[i];
|
||||
trials[i]["height"] = params["height"];
|
||||
trials[i]["width"] = params["width"];
|
||||
trials[i]["timing"] = params["timing"];
|
||||
if(params["data"]!=undefined){
|
||||
trials[i]["data"] = params["data"][i];
|
||||
}
|
||||
if(params["prompt"]!=undefined){
|
||||
trials[i]["prompt"] = params["prompt"];
|
||||
}
|
||||
}
|
||||
return trials;
|
||||
}
|
||||
|
||||
plugin.trial = function(display_element, block, trial, part)
|
||||
{
|
||||
switch(part){
|
||||
case 1:
|
||||
p1_time = (new Date()).getTime();
|
||||
|
||||
display_element.append($('<div>', {
|
||||
"id": 'paintbox',
|
||||
"class": 'paint'}));
|
||||
|
||||
$('#paintbox').css({
|
||||
'position': 'relative',
|
||||
'width': trial.width,
|
||||
'height': trial.height});
|
||||
|
||||
$('#paintbox').append($('<img>', {
|
||||
"src": trial.a_path,
|
||||
"class": 'paint',
|
||||
"css": {
|
||||
'width':trial.width,
|
||||
'height':trial.height,
|
||||
'position': 'absolute',
|
||||
'top': '0',
|
||||
'left': '0',
|
||||
'z-index': '0'
|
||||
}
|
||||
}));
|
||||
|
||||
$('#paintbox').append($('<canvas>', {
|
||||
"id": "paintcanvas",
|
||||
"class": "paint",
|
||||
"css": {
|
||||
'position': 'absolute',
|
||||
'top': '0',
|
||||
'left': '0',
|
||||
'z-index': '1',
|
||||
'cursor': 'crosshair'
|
||||
}
|
||||
}));
|
||||
|
||||
$('#paintcanvas').attr('width',trial.width);
|
||||
$('#paintcanvas').attr('height',trial.height);
|
||||
|
||||
|
||||
var canvas = document.getElementById('paintcanvas');
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
ctx.fillStyle = "rgba(0,0,0,0.8)";
|
||||
ctx.fillRect(0,0,trial.width,trial.height);
|
||||
|
||||
var paint = false;
|
||||
|
||||
document.onselectstart = function(){
|
||||
return false;
|
||||
}
|
||||
|
||||
$('#paintcanvas').mousedown(function(e){
|
||||
var mouseX = e.pageX - $('#paintbox').offset().left;
|
||||
var mouseY = e.pageY - $('#paintbox').offset().top;
|
||||
|
||||
paint = true;
|
||||
|
||||
colorPixel(ctx, mouseX, mouseY, true);
|
||||
});
|
||||
|
||||
$('#paintcanvas').mousemove(function(e){
|
||||
var mouseX = e.pageX - $('#paintbox').offset().left;
|
||||
var mouseY = e.pageY - $('#paintbox').offset().top;
|
||||
|
||||
if(paint){
|
||||
colorPixel(ctx, mouseX, mouseY, false);
|
||||
}
|
||||
});
|
||||
|
||||
$(document).mouseup(function(e){
|
||||
paint = false;
|
||||
});
|
||||
|
||||
display_element.append($('<button>',{
|
||||
'id':'done',
|
||||
'class':'paint'}));
|
||||
|
||||
$('#done').html('Done');
|
||||
$('#done').click(function(){
|
||||
plugin.trial(display_element,block,trial,part+1);
|
||||
});
|
||||
|
||||
display_element.append($('<button>',{
|
||||
'id':'reset',
|
||||
'class':'paint'}));
|
||||
|
||||
$('#reset').html('Reset');
|
||||
$('#reset').click(function(){
|
||||
ctx.clearRect(0,0,trial.width,trial.height);
|
||||
ctx.globalCompositeOperation = "source-over";
|
||||
ctx.fillStyle = "rgba(0,0,0,0.8)";
|
||||
ctx.fillRect(0,0,trial.width,trial.height);
|
||||
});
|
||||
|
||||
if(trial.prompt){
|
||||
display_element.append(trial.prompt);
|
||||
}
|
||||
|
||||
break;
|
||||
case 2:
|
||||
var canvas = document.getElementById('paintcanvas');
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
var img = ctx.getImageData(0,0,trial.width,trial.height);
|
||||
var pix = img.data;
|
||||
|
||||
var tdata = new Array(trial.width*trial.height);
|
||||
var data_string = "";
|
||||
//tdata[0] = new Array();
|
||||
|
||||
for(var i=0, j=0, n=pix.length; i<n; i+=4, j++)
|
||||
{
|
||||
tdata[j] = (pix[i+3] == 0)
|
||||
if(pix[i+3] == 0)
|
||||
{
|
||||
data_string = data_string+"1";
|
||||
} else {
|
||||
data_string = data_string+"0";
|
||||
}
|
||||
}
|
||||
|
||||
block.data[block.trial_idx] = $.extend({},{"a_path": trial.a_path,"pixels": data_string},trial.data);
|
||||
|
||||
display_element.html('');
|
||||
|
||||
setTimeout(function(){block.next();}, trial.timing[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return plugin;
|
||||
})();
|
||||
})(jQuery);
|
@ -1,144 +0,0 @@
|
||||
// Josh de Leeuw
|
||||
// Nov. 2012
|
||||
|
||||
|
||||
(function( $ ) {
|
||||
jsPsych.samedifferentloc = (function(){
|
||||
|
||||
var plugin = {};
|
||||
|
||||
plugin.create = function(params) {
|
||||
var stims = params["stimuli"];
|
||||
trials = new Array(stims.length);
|
||||
for(var i = 0; i < trials.length; i++)
|
||||
{
|
||||
trials[i] = {};
|
||||
trials[i]["type"] = "samedifferentloc";
|
||||
trials[i]["a_path"] = sd_stims[i][0];
|
||||
trials[i]["b_path"] = sd_stims[i][1];
|
||||
trials[i]["mask_path"] = params["mask_path"];
|
||||
trials[i]["a_x_offset"] = params["a_x_offset"][i];
|
||||
trials[i]["a_y_offset"] = params["a_y_offset"][i];
|
||||
trials[i]["b_x_offset"] = params["b_x_offset"][i];
|
||||
trials[i]["b_y_offset"] = params["b_y_offset"][i];
|
||||
trials[i]["answer"] = params["answer"][i];
|
||||
trials[i]["same_key"] = params["same_key"] || 80;
|
||||
trials[i]["different_key"] = params["different_key"] || 81;
|
||||
// timing parameters
|
||||
trials[i]["timing_first_img"] = params["timing_first_img"] || 1500;
|
||||
trials[i]["timing_mask"] = params["timing_mask"] || 500;
|
||||
trials[i]["timing_second_img"] = params["timing_second_img"] || 1000;
|
||||
trials[i]["timing_fixation"] = params["timing_fixation"] || 3000;
|
||||
// optional parameters
|
||||
if(params["prompt"] != undefined){
|
||||
trials[i]["prompt"] = params["prompt"];
|
||||
}
|
||||
if(params["data"]!=undefined){
|
||||
trials[i]["data"] = params["data"][i];
|
||||
}
|
||||
}
|
||||
return trials;
|
||||
}
|
||||
|
||||
plugin.trial = function(display_element, block, trial, part)
|
||||
{
|
||||
switch(part){
|
||||
case 1:
|
||||
display_element.append($('<div>', {
|
||||
"id": 'sdl_img_container',
|
||||
"css": {
|
||||
"position": 'relative'
|
||||
}
|
||||
}));
|
||||
|
||||
$("#sdl_img_container").append($('<img>', {
|
||||
"src": trial.a_path,
|
||||
"class": 'sdl',
|
||||
"css": {
|
||||
"position": 'absolute',
|
||||
"top": trial.a_y_offset,
|
||||
"left": trial.a_x_offset
|
||||
}
|
||||
}));
|
||||
setTimeout(function(){plugin.trial(display_element, block, trial, part + 1);}, trial.timing_first_img);
|
||||
break;
|
||||
case 2:
|
||||
$('.sd1').remove();
|
||||
$("#sdl_img_container").append($('<img>', {
|
||||
"src": trial.mask_path,
|
||||
"class": 'sdl'
|
||||
}));
|
||||
setTimeout(function(){plugin.trial(display_element, block, trial, part + 1);}, trial.timing_mask);
|
||||
break;
|
||||
case 3:
|
||||
$('.sd1').remove();
|
||||
|
||||
$("#sdl_img_container").append($('<img>', {
|
||||
"src": trial.b_path,
|
||||
"class": 'sdl',
|
||||
"css": {
|
||||
"position": 'absolute',
|
||||
"top": trial.b_y_offset,
|
||||
"left": trial.b_x_offset
|
||||
}
|
||||
}));
|
||||
|
||||
setTimeout(function(){plugin.trial(display_element, block, trial, part + 1);}, trial.timing_second_img);
|
||||
break;
|
||||
case 4:
|
||||
$('.sd1').remove();
|
||||
|
||||
$("#sdl_img_container").append($('<img>', {
|
||||
"src": trial.fixation_path,
|
||||
"class": 'sdl'
|
||||
}));
|
||||
|
||||
startTime = (new Date()).getTime();
|
||||
|
||||
var correct = false;
|
||||
var response = false;
|
||||
|
||||
var resp_func = function(e) {
|
||||
var flag = false;
|
||||
if(e.which==trial.same_key)
|
||||
{
|
||||
flag = true;
|
||||
if(trial.answer == "same") { correct = true; }
|
||||
} else if(e.which==trial.different_key)
|
||||
{
|
||||
flag = true;
|
||||
if(trial.answer == "different"){ correct = true; }
|
||||
}
|
||||
if(flag)
|
||||
{
|
||||
endTime = (new Date()).getTime();
|
||||
rt = (endTime-startTime);
|
||||
$(document).unbind('keyup',resp_func);
|
||||
|
||||
response = true;
|
||||
}
|
||||
}
|
||||
|
||||
$(document).keyup(resp_func);
|
||||
|
||||
var finish_func = function() {
|
||||
if(!response)
|
||||
{
|
||||
rt = -1;
|
||||
}
|
||||
var trial_data = {"rt": rt, "correct": correct, "a_path": trial.a_path, "b_path": trial.b_path, "key_press": e.which,
|
||||
"a_x_loc": trial.a_x_offset,"a_y_loc": trial.a_y_offset,"b_x_loc": trial.b_x_offset, "b_y_loc": trial.b_y_offset };
|
||||
block.data[block.trial_idx] = $.extend({},trial_data,trial.data);
|
||||
display_element.html('');
|
||||
block.next();
|
||||
}
|
||||
|
||||
setTimeout(finish_func, trial.timing_fixation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return plugin;
|
||||
})();
|
||||
}) (jQuery);
|
||||
|
@ -1,248 +0,0 @@
|
||||
/* jspsych-staircase-categorize.js
|
||||
* Josh de Leeuw, Sep. 2013
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
jsPsych.staircase_categorize = (function() {
|
||||
|
||||
var plugin = {};
|
||||
|
||||
plugin.create = function(params) {
|
||||
var trials = []; // everything is a single trial, since it is unknown how many presentations it will take.
|
||||
|
||||
trials[0] = {};
|
||||
trials[0].type = "staircase_categorize";
|
||||
// items structure is four nested arrays. top level array is separate staircases that should be interleaved.
|
||||
// second level array is difficulty. third arrays are sets of options. inner most array are stimuli of equivalent
|
||||
// difficulty and category.
|
||||
trials[0].items = params.items;
|
||||
// two level nested array. top level is separate staircases.
|
||||
// second (inner) level is list of key responses in order that stimuli are ordered for third level of items array.
|
||||
trials[0].choices = params.choices;
|
||||
trials[0].n_up = params.n_up || 1;
|
||||
trials[0].n_down = params.n_down || 1;
|
||||
trials[0].n_turns = params.n_turns || 10;
|
||||
trials[0].n_turns_average = params.n_turns_average || 6;
|
||||
// timing
|
||||
trials[0].timing_post_trial = params.timing_post_trial || 1000; // default 1000ms between trials.
|
||||
trials[0].timing_item = params.timing_item || 1000;
|
||||
|
||||
// optional parameters
|
||||
if (params.data !== undefined) {
|
||||
trials[0].data = params.data;
|
||||
}
|
||||
if (params.prompt !== undefined) {
|
||||
trials[0].prompt = params.prompt;
|
||||
}
|
||||
|
||||
return trials;
|
||||
};
|
||||
|
||||
plugin.trial = function(display_element, block, trial, part) {
|
||||
|
||||
var interleaver = new StaircaseInterleaver(display_element, trial, block);
|
||||
interleaver.start();
|
||||
};
|
||||
|
||||
function StaircaseInterleaver(display_element, trial, block) {
|
||||
this.staircases = [];
|
||||
|
||||
for(var i=0; i<trial.items.length; i++)
|
||||
{
|
||||
var s_trial = $.extend(true, {}, trial);
|
||||
s_trial.items = s_trial.items[i];
|
||||
s_trial.choices = s_trial.choices[i];
|
||||
var staircase = new StaircaseController(display_element, s_trial, this, block);
|
||||
this.staircases.push(staircase);
|
||||
}
|
||||
|
||||
this.start = function() {
|
||||
this.next_trial();
|
||||
};
|
||||
|
||||
this.next_trial = function() {
|
||||
var eligible_staircases = [];
|
||||
for (var i = 0; i < this.staircases.length; i++) {
|
||||
if (this.staircases[i].is_complete === false) {
|
||||
eligible_staircases.push(this.staircases[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (eligible_staircases.length === 0) {
|
||||
this.finish();
|
||||
}
|
||||
else {
|
||||
var which_staircase = Math.floor(Math.random() * eligible_staircases.length);
|
||||
|
||||
eligible_staircases[which_staircase].next_trial();
|
||||
}
|
||||
};
|
||||
|
||||
this.finish = function()
|
||||
{
|
||||
// end the whole staircase process
|
||||
block.next();
|
||||
}
|
||||
}
|
||||
|
||||
function StaircaseController(display_element, trial, interleaver, block) {
|
||||
this.current_item = 0;
|
||||
this.total_turns = 0;
|
||||
this.current_direction = 1;
|
||||
this.turns = [];
|
||||
this.consecutive_correct = 0;
|
||||
this.consecutive_incorrect = 0;
|
||||
this.items = trial.items;
|
||||
this.is_complete = false;
|
||||
this.interleaver = interleaver;
|
||||
|
||||
this.next_trial = function() {
|
||||
|
||||
var item_set = this.items[this.current_item];
|
||||
|
||||
// pick which category to show randomly
|
||||
var which_category = Math.floor(Math.random()*item_set.length);
|
||||
|
||||
// pick which exemplar to show randomly
|
||||
var which_exemplar = Math.floor(Math.random()*item_set[which_category].length);
|
||||
|
||||
var this_trial = {
|
||||
a_path: item_set[which_category][which_exemplar],
|
||||
choices: trial.choices,
|
||||
correct_response: trial.choices[which_category]
|
||||
};
|
||||
|
||||
this.do_trial(this_trial);
|
||||
|
||||
};
|
||||
|
||||
this.finish_trial = function(correct) {
|
||||
// change the counters
|
||||
if (correct) {
|
||||
this.consecutive_incorrect = 0;
|
||||
this.consecutive_correct++;
|
||||
}
|
||||
else {
|
||||
this.consecutive_incorrect++;
|
||||
this.consecutive_correct = 0;
|
||||
}
|
||||
|
||||
var new_direction;
|
||||
|
||||
if (correct) {
|
||||
if (this.consecutive_correct >= trial.n_up) {
|
||||
new_direction = 1; // make it harder
|
||||
this.consecutive_correct = 0; // reset this because we changed difficulty.
|
||||
}
|
||||
else {
|
||||
// do the same
|
||||
new_direction = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this.consecutive_incorrect >= trial.n_down) {
|
||||
// make it easier
|
||||
new_direction = -1;
|
||||
this.consecutive_incorrect = 0; // reset because we changed difficulty
|
||||
}
|
||||
else {
|
||||
// do the same
|
||||
new_direction = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// if there is a turn, add it.
|
||||
if (new_direction !== 0) {
|
||||
if (this.current_direction != new_direction) {
|
||||
this.turns.push(this.current_item);
|
||||
}
|
||||
this.current_direction = new_direction;
|
||||
}
|
||||
|
||||
// check if we are done
|
||||
if (this.turns.length >= trial.n_turns ){
|
||||
this.is_complete = true;
|
||||
}
|
||||
|
||||
// now figure out what the next item is
|
||||
this.current_item = this.current_item + new_direction;
|
||||
if (this.current_item < 0) {
|
||||
this.current_item = 0;
|
||||
}
|
||||
if (this.current_item >= trial.items.length) {
|
||||
this.current_item = trial.items.length - 1;
|
||||
}
|
||||
|
||||
// tell the interleaver that we are done
|
||||
this.interleaver.next_trial();
|
||||
};
|
||||
|
||||
this.do_trial = function(this_trial) {
|
||||
|
||||
var trial_complete = false;
|
||||
|
||||
// show image
|
||||
display_element.append($('<img>', {
|
||||
"src": this_trial.a_path,
|
||||
"class": 'staircase-categorize'
|
||||
}));
|
||||
|
||||
if (trial.prompt) {
|
||||
display_element.append(trial.prompt);
|
||||
}
|
||||
|
||||
var startTime = (new Date()).getTime();
|
||||
|
||||
// set timer to remove image
|
||||
if (trial.timing_item > 0) {
|
||||
setTimeout(function() {
|
||||
if (!trial_complete) {
|
||||
$('.staircase-categorize').css('visibility', 'hidden');
|
||||
}
|
||||
}, trial.timing_item);
|
||||
}
|
||||
|
||||
var resp_func = function(e) {
|
||||
|
||||
var flag = false;
|
||||
var correct = false;
|
||||
|
||||
if ($.inArray(e.which, this_trial.choices) > -1) {
|
||||
flag = true;
|
||||
correct = (e.which == this_trial.correct_response);
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
var endTime = (new Date()).getTime();
|
||||
var rt = (endTime - startTime);
|
||||
var t_idx = block.data.length;
|
||||
|
||||
var trial_data = {
|
||||
"trial_type": "staircase-categorize",
|
||||
"trial_index": t_idx,
|
||||
"rt": rt,
|
||||
"correct": correct,
|
||||
"a_path": this_trial.a_path,
|
||||
"staircase_index": e.data.iterator_object.current_item,
|
||||
"staircase_direction": e.data.iterator_object.current_direction,
|
||||
"key_press": e.which
|
||||
};
|
||||
block.data.push($.extend({},trial_data,trial.data));
|
||||
$(document).unbind('keyup', resp_func);
|
||||
display_element.html(''); // remove all
|
||||
trial_complete = true;
|
||||
setTimeout(function() {
|
||||
e.data.iterator_object.finish_trial(correct);
|
||||
}, trial.timing_post_trial);
|
||||
}
|
||||
}
|
||||
$(document).keyup({iterator_object: this}, resp_func);
|
||||
}
|
||||
}
|
||||
|
||||
return plugin;
|
||||
})();
|
||||
})(jQuery);
|
@ -1,223 +0,0 @@
|
||||
/* jspsych-staircase.js
|
||||
* Josh de Leeuw, Sep. 2013
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
jsPsych.staircase_xab = (function() {
|
||||
|
||||
var plugin = {};
|
||||
|
||||
plugin.create = function(params) {
|
||||
var trials = []; // everything is a single trial, since it is unknown how many presentations it will take.
|
||||
|
||||
trials[0] = {};
|
||||
trials[0].type = "staircase_xab";
|
||||
trials[0].items = params.items;
|
||||
trials[0].foils = params.foils;
|
||||
trials[0].left_key = params.left_key || 81; // array of all the correct key responses
|
||||
trials[0].right_key = params.right_key || 80; // valid key responses
|
||||
trials[0].n_up = params.n_up || 1;
|
||||
trials[0].n_down = params.n_down || 1;
|
||||
trials[0].n_turns = params.n_turns || 10;
|
||||
trials[0].n_turns_average = params.n_turns_average || 6;
|
||||
// timing
|
||||
trials[0].timing_post_trial = params.timing_post_trial || 1000; // default 1000ms between trials.
|
||||
trials[0].timing_x = params.timing_x || 1000;
|
||||
trials[0].timing_xab_gap = params.timing_xab_gap || 1000;
|
||||
trials[0].timing_ab = params.timing_ab || -1; // default is indefinitely.
|
||||
|
||||
// optional parameters
|
||||
if (params.data !== undefined) {
|
||||
trials[0].data = params.data;
|
||||
}
|
||||
if (params.prompt !== undefined) {
|
||||
trials[0].prompt = params.prompt;
|
||||
}
|
||||
|
||||
return trials;
|
||||
};
|
||||
|
||||
plugin.trial = function(display_element, block, trial, part) {
|
||||
var current_item = 0; // start with the easiest item
|
||||
var total_turns = 0; // counter for keeping track of how many turns
|
||||
var current_direction = 1; // which way are we currently moving in item set; +1 = harder; -1 = easier
|
||||
var turns = []; // store the items where we turned
|
||||
var consecutive_correct = 0;
|
||||
var consecutive_incorrect = 0;
|
||||
|
||||
// do a trial, check if we've hit total_turns, if yes then end, if not do another trial.
|
||||
|
||||
var staircase_xab_trial_complete = false;
|
||||
|
||||
function next_trial() {
|
||||
if (total_turns < trial.n_turns) {
|
||||
// do trial
|
||||
var this_trial = { };
|
||||
do_trial(display_element, block, this )
|
||||
}
|
||||
else {
|
||||
// end run
|
||||
}
|
||||
}
|
||||
|
||||
function finish_trial(correct) {
|
||||
// change the counters
|
||||
if (correct) {
|
||||
consecutive_incorrect = 0;
|
||||
consecutive_correct++;
|
||||
}
|
||||
else {
|
||||
consecutive_incorrect++;
|
||||
consecutive_correct = 0;
|
||||
}
|
||||
|
||||
var new_direction;
|
||||
|
||||
if (correct) {
|
||||
if (consecutive_correct >= trial.n_up) {
|
||||
new_direction = 1; // make it harder
|
||||
consecutive_correct = 0; // reset this because we changed difficulty.
|
||||
}
|
||||
else {
|
||||
// do the same
|
||||
new_direction = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (consecutive_incorrect >= trial.n_down) {
|
||||
// make it easier
|
||||
new_direction = -1;
|
||||
consecutive_incorrect = 0; // reset because we changed difficulty
|
||||
}
|
||||
else {
|
||||
// do the same
|
||||
new_direction = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// if there is a turn, add it.
|
||||
if (new_direction !== 0) {
|
||||
if (current_direction != new_direction) {
|
||||
turns.push(current_item);
|
||||
}
|
||||
current_direction = new_direction;
|
||||
}
|
||||
|
||||
// now figure out what the next item is
|
||||
current_item = current_item + new_direction;
|
||||
if (current_item < 0) {
|
||||
current_item = 0;
|
||||
}
|
||||
if (current_item >= trial.items.length) {
|
||||
current_item = trial.items.length - 1;
|
||||
}
|
||||
}
|
||||
|
||||
function do_trial(display_element, block, trial, part) {
|
||||
switch (part) {
|
||||
case 1:
|
||||
|
||||
staircase_xab_trial_complete = false;
|
||||
|
||||
display_element.append($('<img>', {
|
||||
"src": trial.a_path,
|
||||
"class": 'staircase-xab'
|
||||
}));
|
||||
|
||||
setTimeout(function() {
|
||||
do_trial(display_element, block, trial, part + 1)
|
||||
}, trial.timing_x);
|
||||
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
||||
$('.staircase-xab').remove();
|
||||
|
||||
setTimeout(function() {
|
||||
do_trial(display_element, block, trial, part + 1)
|
||||
}, trial.timing_xab_gap);
|
||||
|
||||
break;
|
||||
|
||||
case 3:
|
||||
|
||||
var startTime = (new Date()).getTime();
|
||||
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 images
|
||||
display_element.append($('<img>', {
|
||||
"src": images[0],
|
||||
"class": 'staircase-xab'
|
||||
}));
|
||||
display_element.append($('<img>', {
|
||||
"src": images[1],
|
||||
"class": 'staircase-xab'
|
||||
}));
|
||||
|
||||
if (trial.prompt) {
|
||||
display_element.append(trial.prompt);
|
||||
}
|
||||
|
||||
if (trial.timing_ab > 0) {
|
||||
setTimeout(function() {
|
||||
if (!staircase_xab_trial_complete) {
|
||||
$('.staircase-xab').css('visibility', 'hidden');
|
||||
}
|
||||
}, trial.timing_ab);
|
||||
}
|
||||
|
||||
var resp_func = function(e) {
|
||||
var flag = false;
|
||||
var correct = false;
|
||||
if (e.which == trial.left_key) {
|
||||
flag = true;
|
||||
if (target_left) {
|
||||
correct = true;
|
||||
}
|
||||
}
|
||||
else if (e.which == trial.right_key) {
|
||||
flag = true;
|
||||
if (!target_left) {
|
||||
correct = true;
|
||||
}
|
||||
}
|
||||
if (flag) {
|
||||
var endTime = (new Date()).getTime();
|
||||
var rt = (endTime - startTime);
|
||||
|
||||
var trial_data = {
|
||||
"trial_type": "staircase-xab",
|
||||
"trial_index": block.trial_idx,
|
||||
"rt": rt,
|
||||
"correct": correct,
|
||||
"x_path": trial.x_path,
|
||||
"a_path": trial.a_path,
|
||||
"b_path": trial.b_path,
|
||||
"key_press": e.which
|
||||
}
|
||||
//block.data[block.trial_idx] = $.extend({},trial_data,trial.data);
|
||||
$(document).unbind('keyup', resp_func);
|
||||
display_element.html(''); // remove all
|
||||
staircase_xab_trial_complete = true;
|
||||
setTimeout(function() {
|
||||
block.next();
|
||||
}, trial.timing_post_trial);
|
||||
}
|
||||
}
|
||||
$(document).keyup(resp_func);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return plugin;
|
||||
})();
|
||||
})(jQuery);
|
@ -1,82 +0,0 @@
|
||||
(function( $ ) {
|
||||
jsPsych.storybook = (function(){
|
||||
|
||||
var plugin = {};
|
||||
|
||||
plugin.create = function(params) {
|
||||
stims = params["stimuli"];
|
||||
trials = new Array(stims.length);
|
||||
for(var i = 0; i < trials.length; i++)
|
||||
{
|
||||
trials[i] = {};
|
||||
trials[i]["type"] = "storybook";
|
||||
trials[i]["a_path"] = stims[i];
|
||||
trials[i]["click_num"] = params["click_num"];
|
||||
trials[i]["timing"] = params["timing"];
|
||||
if(params["data"]!=undefined){
|
||||
trials[i]["data"] = params["data"][i];
|
||||
}
|
||||
}
|
||||
return trials;
|
||||
}
|
||||
|
||||
plugin.trial = function(display_element, block, trial, part)
|
||||
{
|
||||
switch(part){
|
||||
case 1:
|
||||
p1_time = (new Date()).getTime();
|
||||
display_element.append($('<img>', {
|
||||
"src": trial.a_path,
|
||||
"class": 'storybook'
|
||||
}));
|
||||
|
||||
var click_count = 0;
|
||||
var click_locations = [];
|
||||
var click_times = [];
|
||||
|
||||
var touchfunction = function(e) {
|
||||
|
||||
e.originalEvent.preventDefault();
|
||||
|
||||
var rt = (new Date()).getTime() - p1_time;
|
||||
var x = e.originalEvent.touches[0].pageX;
|
||||
var y = e.originalEvent.touches[0].pageY;
|
||||
|
||||
click_count = click_count + 1;
|
||||
|
||||
console.log("click event "+x+" "+y+". click count "+click_count+". click num "+trial.click_num);
|
||||
|
||||
//save location
|
||||
click_locations.push([x,y]);
|
||||
click_times.push(rt);
|
||||
|
||||
//save response time
|
||||
if(click_count == trial.click_num)
|
||||
{
|
||||
var click_loc_data = {"click_locations": click_locations};
|
||||
var click_time_data = {"click_times": click_times};
|
||||
var img = {"img": trial.a_path };
|
||||
// save data
|
||||
block.data[block.trial_idx] = $.extend({}, img, click_loc_data, click_time_data, trial.data);
|
||||
|
||||
plugin.trial(display_element, block, trial, part + 1);
|
||||
}
|
||||
};
|
||||
|
||||
$('.storybook').click(function(){ void(0); })
|
||||
|
||||
//$('.storybook').mousedown(function(e){ touchfunction(e);});
|
||||
$('.storybook').bind("touchstart", function(e){touchfunction(e);});
|
||||
|
||||
break;
|
||||
case 2:
|
||||
$('.storybook').remove();
|
||||
|
||||
setTimeout(function(){block.next();}, trial.timing[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return plugin;
|
||||
})();
|
||||
})(jQuery);
|
@ -1,89 +0,0 @@
|
||||
(function( $ ) {
|
||||
jsPsych.touch_freepick = (function(){
|
||||
|
||||
var plugin = {};
|
||||
|
||||
plugin.create = function(params) {
|
||||
stims = params["stims"];
|
||||
trials = new Array(stims.length);
|
||||
for(var i = 0; i < trials.length; i++)
|
||||
{
|
||||
trials[i] = {};
|
||||
trials[i]["type"] = "touch_freepick";
|
||||
trials[i]["stims"] = stims[i];
|
||||
trials[i]["answer_text"] = params["answer_text"][i] || "";
|
||||
trials[i]["timing"] = params["timing"];
|
||||
trials[i]["force_correct_pick"] = params["force_correct_pick"] || false;
|
||||
if(params["data"]!=undefined){
|
||||
trials[i]["data"] = params["data"][i];
|
||||
}
|
||||
}
|
||||
return trials;
|
||||
}
|
||||
|
||||
plugin.trial = function(display_element, block, trial, part)
|
||||
{
|
||||
switch(part){
|
||||
case 1:
|
||||
p1_time = (new Date()).getTime();
|
||||
|
||||
var order = [];
|
||||
for(var i=0;i<trial.stims.length;i++)
|
||||
{
|
||||
order.push(i);
|
||||
}
|
||||
|
||||
order = shuffle(order);
|
||||
|
||||
// add images
|
||||
for(var i=0;i<trial.stims.length;i++){
|
||||
display_element.append($('<img>', {
|
||||
"src": trial.stims[order[i]],
|
||||
"class": 'freepick',
|
||||
"id":'fp'+order[i]
|
||||
}));
|
||||
}
|
||||
|
||||
// need to pick the right one!
|
||||
if(trial.force_correct_pick) {
|
||||
$("#fp0").click(
|
||||
function(){
|
||||
// clear everything
|
||||
display_element.html('');
|
||||
// add only target
|
||||
display_element.append($('<img>', {
|
||||
"src": trial.stims[0],
|
||||
"class": 'freepick',
|
||||
"id":'fp_answer'
|
||||
}));
|
||||
display_element.append($('<p class="answer">'+trial.answer_text+'</p>'));
|
||||
setTimeout(function(){plugin.trial(display_element,block,trial,part+1)}, trial.timing[0]);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
break;
|
||||
case 2:
|
||||
display_element.html('');
|
||||
|
||||
setTimeout(function(){block.next();}, trial.timing[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function shuffle(array) {
|
||||
var tmp, current, top = array.length;
|
||||
|
||||
if(top) while(--top) {
|
||||
current = Math.floor(Math.random() * (top + 1));
|
||||
tmp = array[current];
|
||||
array[current] = array[top];
|
||||
array[top] = tmp;
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
return plugin;
|
||||
})();
|
||||
})(jQuery);
|
@ -1,110 +0,0 @@
|
||||
// Josh de Leeuw
|
||||
// Nov. 2012
|
||||
|
||||
// This plugin is for presenting two images in sequence and collecting a key response.
|
||||
|
||||
(function( $ ) {
|
||||
jsPsych.twoimage_keyresponse = (function(){
|
||||
|
||||
var plugin = {};
|
||||
|
||||
plugin.create = function(params) {
|
||||
var stims = params["stimuli"];
|
||||
trials = new Array(stims.length);
|
||||
for(var i = 0; i < trials.length; i++)
|
||||
{
|
||||
trials[i] = {};
|
||||
trials[i]["type"] = "twoimage_keyresponse";
|
||||
trials[i]["a_path"] = stims[i][0];
|
||||
trials[i]["b_path"] = stims[i][1];
|
||||
trials[i]["choices"] = params["choices"];
|
||||
// timing parameters
|
||||
trials[i]["timing_first_stim"] = params["timing_first_stim"] || 1000;
|
||||
trials[i]["timing_gap"] = params["timing_gap"] || 500;
|
||||
trials[i]["timing_second_stim"] = params["timing_second_stim"]; // if undefined, then show indefinitely
|
||||
trials[i]["timing_post_trial"] = params["timing_post_trial"] || 1000;
|
||||
// optional parameters
|
||||
if(params["prompt"] != undefined){
|
||||
trials[i]["prompt"] = params["prompt"];
|
||||
}
|
||||
if(params["data"]!=undefined){
|
||||
trials[i]["data"] = params["data"][i];
|
||||
}
|
||||
}
|
||||
return trials;
|
||||
}
|
||||
|
||||
var tikr_trial_complete = false;
|
||||
plugin.trial = function(display_element, block, trial, part)
|
||||
{
|
||||
switch(part){
|
||||
case 1:
|
||||
tikr_trial_complete = false;
|
||||
|
||||
display_element.append($('<img>', {
|
||||
"src": trial.a_path,
|
||||
"id": 'tikr_a_img'
|
||||
}));
|
||||
|
||||
setTimeout(function(){plugin.trial(display_element, block, trial, part + 1)}, trial.timing_first_stim);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
$('#tikr_a_img').remove();
|
||||
setTimeout(function(){plugin.trial(display_element, block, trial, part + 1)}, trial.timing_gap);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
startTime = (new Date()).getTime();
|
||||
|
||||
display_element.append($('<img>', {
|
||||
"src": trial.b_path,
|
||||
"id": 'tikr_b_img'
|
||||
}));
|
||||
|
||||
//show prompt here
|
||||
if(trial.prompt != undefined){
|
||||
display_element.append(trial.prompt);
|
||||
}
|
||||
|
||||
// hide image if timing is set
|
||||
if(trial.timing_second_stim != undefined){
|
||||
setTimeout(function(){
|
||||
if(!tikr_trial_complete){
|
||||
$('#tikr_b_img').css('visibility','hidden');
|
||||
}
|
||||
}, trial.timing_second_stim);
|
||||
}
|
||||
|
||||
var resp_func = function(e) {
|
||||
var flag = false;
|
||||
// check if the key is any of the options, or if it is an accidental keystroke
|
||||
for(var i=0;i<trial.choices.length;i++)
|
||||
{
|
||||
if(e.which==trial.choices[i])
|
||||
{
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
if(flag)
|
||||
{
|
||||
endTime = (new Date()).getTime();
|
||||
rt = (endTime-startTime);
|
||||
|
||||
var trial_data = {"trial_type":"twoimage_keyresponse", "rt": rt, "a_path": trial.a_path, "b_path": trial.b_path, "key_press": e.which}
|
||||
block.data[block.trial_idx] = $.extend({},trial_data,trial.data);
|
||||
$(document).unbind('keyup',resp_func);
|
||||
display_element.html('');
|
||||
tikr_trial_complete = true;
|
||||
setTimeout(function(){block.next();}, trial.timing_post_trial);
|
||||
}
|
||||
}
|
||||
$(document).keyup(resp_func);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return plugin;
|
||||
})();
|
||||
})(jQuery);
|
||||
|
@ -1,96 +0,0 @@
|
||||
(function( $ ) {
|
||||
jsPsych.xab_touch = (function(){
|
||||
|
||||
var plugin = {};
|
||||
|
||||
plugin.create = function(params) {
|
||||
//xab_stims = shuffle(xab_stims);
|
||||
xab_stims = params["stimuli"];
|
||||
trials = new Array(xab_stims.length);
|
||||
for(var i = 0; i < trials.length; i++)
|
||||
{
|
||||
trials[i] = {};
|
||||
trials[i]["type"] = "xab_touch";
|
||||
trials[i]["a_path"] = xab_stims[i][0];
|
||||
trials[i]["b_path"] = xab_stims[i][1];
|
||||
trials[i]["timing"] = params["timing"];
|
||||
if(params["data"]!=undefined){
|
||||
trials[i]["data"] = params["data"][i];
|
||||
}
|
||||
}
|
||||
return trials;
|
||||
}
|
||||
|
||||
plugin.trial = function(display_element, block, trial, part)
|
||||
{
|
||||
switch(part){
|
||||
case 1:
|
||||
p1_time = (new Date()).getTime();
|
||||
display_element.append($('<img>', {
|
||||
"src": trial.a_path,
|
||||
"class": 'xab_touch'
|
||||
}));
|
||||
setTimeout(function(){plugin.trial(display_element, block, trial, part + 1);}, trial.timing[0]);
|
||||
break;
|
||||
case 2:
|
||||
p2_time = (new Date()).getTime();
|
||||
$('.xab_touch').remove();
|
||||
setTimeout(function(){plugin.trial(display_element, block, trial, part + 1);}, trial.timing[1]);
|
||||
break;
|
||||
case 3:
|
||||
p3_time = (new Date()).getTime();
|
||||
startTime = (new Date()).getTime();
|
||||
var images = [trial.a_path, trial.b_path];
|
||||
var target_left = (Math.floor(Math.random()*2)==0); // binary true/false choice
|
||||
if(!target_left){
|
||||
images = [trial.b_path, trial.a_path];
|
||||
}
|
||||
//$.fn.jsPsych.showImages(display_element, images, 'xab');
|
||||
|
||||
var correct=false;
|
||||
|
||||
display_element.append($('<img>', {
|
||||
"src": images[0],
|
||||
"class": 'xab_touch',
|
||||
"id": "left_img"
|
||||
}));
|
||||
$("#left_img").click(function() {
|
||||
if(target_left) { correct = true; }
|
||||
|
||||
endTime = (new Date()).getTime();
|
||||
rt = (endTime-startTime);
|
||||
stim1_time = (p2_time-p1_time);
|
||||
isi_time = (p3_time-p2_time);
|
||||
var trial_data = {"rt": rt, "correct": correct, "a_path": trial.a_path, "b_path": trial.b_path, "stim1_time": stim1_time, "isi_time":isi_time}
|
||||
block.data[block.trial_idx] = $.extend({},trial_data,trial.data);
|
||||
$('.xab_touch').remove();
|
||||
setTimeout(function(){block.next();}, trial.timing[2]);
|
||||
});
|
||||
|
||||
display_element.append($('<img>', {
|
||||
"src": images[1],
|
||||
"class": 'xab_touch',
|
||||
"id": "right_img"
|
||||
}));
|
||||
$("#right_img").click(function() {
|
||||
if(!target_left) { correct = true; }
|
||||
|
||||
endTime = (new Date()).getTime();
|
||||
rt = (endTime-startTime);
|
||||
stim1_time = (p2_time-p1_time);
|
||||
isi_time = (p3_time-p2_time);
|
||||
var trial_data = {"rt": rt, "correct": correct, "a_path": trial.a_path, "b_path": trial.b_path, "stim1_time": stim1_time, "isi_time":isi_time}
|
||||
block.data[block.trial_idx] = $.extend({},trial_data,trial.data);
|
||||
$('.xab_touch').remove();
|
||||
setTimeout(function(){block.next();}, trial.timing[2]);
|
||||
});
|
||||
|
||||
//TODO: CHECK IF IMAGE SHOULD DISAPPEAR
|
||||
//based on timings
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return plugin;
|
||||
})();
|
||||
})(jQuery);
|
Loading…
Reference in New Issue
Block a user